contacts-8.x-1.x-dev/src/Form/AddContactBase.php

src/Form/AddContactBase.php
<?php

namespace Drupal\contacts\Form;

use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\WidgetPluginManager;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Base class for the add contact forms.
 *
 * @deprecated in contacts:2.0.0 and is removed from contacts:3.0.0.
 *   This has been replaced by the AddContactForm.
 *
 * @see https://www.drupal.org/project/contacts/issues/3306887
 */
abstract class AddContactBase extends FormBase {

  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManager
   */
  protected $entityFieldManager;

  /**
   * The widget plugin manager.
   *
   * @var \Drupal\Core\Field\WidgetPluginManager
   */
  protected $widgetManager;

  /**
   * The user entity.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $user;

  /**
   * Validation violations for the user entity.
   *
   * @var \Drupal\Core\Entity\EntityConstraintViolationListInterface
   */
  protected $userViolations;

  /**
   * The profile entity.
   *
   * @var \Drupal\profile\Entity\ProfileInterface
   */
  protected $profile;

  /**
   * Validation violations for the profile entity.
   *
   * @var \Drupal\Core\Entity\EntityConstraintViolationListInterface
   */
  protected $profileViolations;

  /**
   * Construct the add contact form object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager
   *   The entity field manager.
   * @param \Drupal\Core\Field\WidgetPluginManager $widget_manager
   *   The widget manager.
   */
  public function __construct(EntityTypeManager $entity_type_manager, EntityFieldManager $entity_field_manager, WidgetPluginManager $widget_manager) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->widgetManager = $widget_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('entity_field.manager'),
      $container->get('plugin.manager.field.widget'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // During the initial form build, add this form object to the form state and
    // allow for initial preparation before form building and processing.
    if (!$form_state->has('entity_form_initialized')) {
      $this->init($form_state);
    }

    $form['#parents'] = [];
    $form['#after_build'][] = '::afterBuild';
    $weight = 0;

    $user_fields = $this->entityFieldManager->getFieldDefinitions('user', 'user');
    foreach ($this->getUserFields($user_fields) as $field_name => $configuration) {
      $form[$field_name] = $this->getWidgetForm($this->user, $user_fields, $field_name, $form, $form_state, $configuration);
      $form[$field_name]['#entity_namespace'] = 'user';
      $form[$field_name]['#weight'] = $configuration['weight'] ?? $weight++;
    }

    $profile_fields = $this->entityFieldManager->getFieldDefinitions('profile', $this->profile->bundle());
    foreach ($this->getProfileFields($profile_fields) as $field_name => $configuration) {
      $form[$field_name] = $this->getWidgetForm($this->profile, $profile_fields, $field_name, $form, $form_state, $configuration);
      $form[$field_name]['#entity_namespace'] = 'profile';
      $form[$field_name]['#weight'] = $weight++;
    }

    $form['actions'] = ['#type' => 'actions'];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add'),
    ];

    return $form;
  }

  /**
   * Initialize the form state and entities before the first form build.
   */
  protected function init(FormStateInterface $form_state): void {
    // Flag that this form has been initialized.
    $form_state->set('entity_form_initialized', TRUE);
    $this->user = $this->entityTypeManager->getStorage('user')->create();
  }

  /**
   * Get the user fields to be added to the form.
   *
   * @param \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions
   *   The field definitions for the user. Modifications can be made here, such
   *   as setting fields to required.
   *
   * @return array
   *   Keys are the field name, values are the configuration for the widget.
   */
  protected function getUserFields(array $field_definitions): array {
    $field_definitions['mail']->setRequired(TRUE);
    return [
      'mail' => ['weight' => 0.5],
    ];
  }

  /**
   * Get the profile fields to be added to the form.
   *
   * @param \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions
   *   The field definitions for the profile bundle. Modifications can be made
   *   here, such as setting fields to required.
   *
   * @return array
   *   Keys are the field name, values are the configuration for the widget.
   */
  abstract protected function getProfileFields(array $field_definitions): array;

  /**
   * Form element #after_build callback: Updates the entity with submitted data.
   *
   * Updates the internal entity objects with submitted values when the form is
   * being rebuilt (e.g. submitted via AJAX), so that subsequent processing
   * (e.g. AJAX callbacks) can rely on it.
   */
  public function afterBuild(array $element, FormStateInterface $form_state) {
    // Rebuild the entity if #after_build is being called as part of a form
    // rebuild, i.e. if we are processing input. As element validation may not
    // have happened at this stage, we simply copy the values from form state.
    if ($form_state->isProcessingInput()) {
      // Rebuild the entity if #after_build is being called as part of a form
      // rebuild, i.e. if we are processing input. As element validation may not
      // have happened at this stage, we simply copy the values from form state.
      if ($form_state->isProcessingInput()) {
        foreach (Element::children($element) as $field_name) {
          if (!isset($element[$field_name]['#entity_namepsace'])) {
            continue;
          }

          $namespace = $element[$field_name]['#entity_namespace'];
          if (!isset($this->{$namespace})) {
            continue;
          }

          $parents = $element[$field_name]['widget']['#parents'];
          /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
          $entity = $this->{$namespace};
          if ($entity->hasField($field_name)) {
            $entity->set($field_name, $form_state->getValue($parents));
          }
        }
      }
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface[]
   *   The built and validated entities.
   */
  public function validateForm(array &$form, FormStateInterface $form_state): array {
    $entities = $this->buildEntities($form, $form_state);

    foreach ($entities as $namespace => $entity) {
      $violations = $entity->validate();

      // Filter the violations by the fields we expose.
      $filter_fields = array_diff($violations->getFieldNames(), $this->getViolationFields($form, $namespace));
      $violations = $violations->filterByFields($filter_fields);

      // Flag entity level violations.
      foreach ($violations->getEntityViolations() as $violation) {
        /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
        $form_state->setErrorByName('', $violation->getMessage());
      }

      // Flag field level violations.
      foreach ($violations->getFieldNames() as $field_name) {
        foreach ($violations->getByField($field_name) as $violation) {
          $form_state->setErrorByName($field_name, $violation->getMessage());
        }
      }

      // Mark entity validation required properties.
      $entity->setValidationRequired(FALSE);
    }

    // Mark the form as validated.
    $form_state->setTemporaryValue('entity_validated', TRUE);

    return $entities;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    foreach ($this->buildEntities($form, $form_state) as $property => $entity) {
      $this->{$property} = $entity;
    }

    $this->user->save();
    $this->profile->setOwner($this->user);
    $this->profile->save();
    $form_state->setRedirect('contacts.contact', [
      'user' => $this->user->id(),
    ]);
  }

  /**
   * Retrieve the widget form element.
   *
   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
   *   The entity we are working with.
   * @param \Drupal\field\Entity\FieldConfig[] $field_definitions
   *   The field definitions for the given entity.
   * @param string $field_name
   *   The field name to get the widget for.
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param array $configuration
   *   (Optional) The widget plugin configuration.
   *
   * @return array
   *   The widget form array.
   */
  protected function getWidgetForm(FieldableEntityInterface $entity, array $field_definitions, $field_name, array $form, FormStateInterface $form_state, array $configuration = []) {
    $widget = $this->getWidget($field_definitions, $field_name, $configuration);
    $items = $entity->get($field_name);
    $items->filterEmptyItems();
    $element = $widget->form($items, $form, $form_state);
    $element['#widget_configuration'] = $configuration;
    return $element;
  }

  /**
   * Get the widget plugin for an entity field.
   *
   * @param \Drupal\field\Entity\FieldConfig[] $field_definitions
   *   The field definitions for the given entity.
   * @param string $field_name
   *   The field name to get the widget for.
   * @param array $configuration
   *   (Optional) The widget plugin configuration.
   *
   * @return \Drupal\Core\Field\WidgetInterface|null
   *   The field widget plugin.
   */
  protected function getWidget(array $field_definitions, $field_name, array $configuration = []) {
    $widget = $this->widgetManager->getInstance([
      'field_definition' => $field_definitions[$field_name],
      'configuration' => $configuration,
    ]);
    return $widget;
  }

  /**
   * Get fields in the form that require entity field validation.
   *
   * @param array $form
   *   The form array.
   * @param string $entity
   *   The entity to validate the field against.
   *
   * @return array
   *   Array of field names to validate.
   */
  protected function getViolationFields(array $form, string $entity) {
    $field_names = [];
    foreach (Element::children($form) as $field_name) {
      if ($entity === ($form[$field_name]['#entity_namespace'] ?? NULL)) {
        $field_names[] = $field_name;
      }
    }
    return $field_names;
  }

  /**
   * Copy form values onto our entities.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface[]
   *   The built entities.
   */
  protected function buildEntities(array $form, FormStateInterface $form_state): array {
    $entities = [];

    foreach (['user', 'profile'] as $namespace) {
      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
      $entity = clone $this->{$namespace};
      $entity->setValidationRequired(!$form_state->getTemporaryValue('entity_validated'));

      $fields = $this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());

      foreach (Element::children($form) as $field_name) {
        if ($namespace !== ($form[$field_name]['#entity_namespace'] ?? NULL)) {
          continue;
        }

        $widget = $this->getWidget($fields, $field_name, $form[$field_name]['#widget_configuration']);
        $widget->extractFormValues($entity->get($field_name), $form, $form_state);
      }

      $entities[$namespace] = $entity;
    }

    return $entities;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc