association-1.0.0-alpha2/src/Entity/Form/AssociationTypeForm.php

src/Entity/Form/AssociationTypeForm.php
<?php

namespace Drupal\association\Entity\Form;

use Drupal\association\Plugin\AssociationPluginFormInterface;
use Drupal\association\Plugin\BehaviorPluginManagerInterface;
use Drupal\association\Plugin\LandingPagePluginManagerInterface;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Plugin\PluginFormFactoryInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\Utility\Error;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form for editing and creating new association types.
 */
class AssociationTypeForm extends EntityForm {

  /**
   * Service providing entity bundle information.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityBundleInfo;

  /**
   * The form factory for getting form objects for plugins operations.
   *
   * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
   */
  protected $pluginFormFactory;

  /**
   * Association type behavior plugin manager.
   *
   * @var \Drupal\association\Plugin\BehaviorPluginManagerInterface
   */
  protected BehaviorPluginManagerInterface $behaviorManager;

  /**
   * The landing page plugin manager.
   *
   * @var \Drupal\association\Plugin\LandingPagePluginManagerInterface
   */
  protected LandingPagePluginManagerInterface $landingPageManager;

  /**
   * Create a new instance of the AssociationTypeForm object.
   *
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_bundle_info
   *   Service providing entity bundle information.
   * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_factory
   *   The form factory for getting form objects for plugins operations.
   * @param \Drupal\association\Plugin\BehaviorPluginManagerInterface $behavior_manager
   *   Association type behavior plugin manager.
   * @param \Drupal\association\Plugin\LandingPagePluginManagerInterface $landing_page_manager
   *   The landing page plugin manager.
   */
  public function __construct(EntityTypeBundleInfoInterface $entity_bundle_info, PluginFormFactoryInterface $plugin_form_factory, BehaviorPluginManagerInterface $behavior_manager, LandingPagePluginManagerInterface $landing_page_manager) {
    $this->entityBundleInfo = $entity_bundle_info;
    $this->pluginFormFactory = $plugin_form_factory;
    $this->behaviorManager = $behavior_manager;
    $this->landingPageManager = $landing_page_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.bundle.info'),
      $container->get('plugin_form.factory'),
      $container->get('plugin.manager.association.behavior'),
      $container->get('plugin.manager.association.landing_page')
    );
  }

  /**
   * Check to see if an ID is already in use for association type bundle.
   *
   * @return bool
   *   The boolean to indicate if this ID is already in use. TRUE if it already
   *   exists, and FALSE otherwise.
   */
  public function exists($id) {
    if ($id === 'add') {
      return TRUE;
    }

    $entityType = $this->getEntity()->getEntityType();
    $entityIds = $this->entityTypeManager
      ->getStorage($entityType->id())
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition($entityType->getKey('id'), $id)
      ->execute();

    return (bool) $entityIds;
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    $form += ['#parents' => []];

    /** @var \Drupal\association\Entity\AssociationTypeInterface $entity */
    $entity = $this->entity;
    $hasData = $entity->hasData();

    if ($hasData) {
      $form['warning'] = [
        '#type' => 'fieldset',
        '#title' => $this->t('This association type has data!'),
        '#attributes' => [
          'class' => ['message', 'message--warning'],
        ],
        '#markup' => $this->t('This Entity Association type has data (association instances) and will therefore lock configuration options that should not be changed because they can break existing content. You must remove all @label associations to edit these settings.', [
          '@label' => $entity->label(),
        ]),
      ];
    }

    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Label'),
      '#maxlength' => 255,
      '#default_value' => $entity->label(),
      '#description' => $this->t("Label for the Entity Association type."),
      '#required' => TRUE,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $entity->id(),
      '#machine_name' => [
        'source' => ['label'],
        'exists' => [$this, 'exists'],
      ],
      '#disabled' => !$entity->isNew(),
    ];

    // Build the definted association type plugins.
    foreach ($this->getPluginDefinitions() as $pluginKey => $pluginInfo) {
      $wrapperId = 'association-type-' . strtr($pluginInfo['id'], '_', '-') . '-configuration';

      $form[$pluginKey] = [
        '#type' => 'fieldset',
        '#title' => $pluginInfo['label'],
        '#tree' => TRUE,

        'id' => [
          '#type' => 'select',
          '#title' => $this->t('Type'),
          '#required' => TRUE,
          '#disabled' => $hasData,
          '#options' => $pluginInfo['options'],
          '#default_value' => 'none',
          '#ajax' => [
            'wrapper' => $wrapperId,
            'callback' => static::class . '::pluginConfigurationAjax',
          ],
        ],
        'config' => [
          '#parents' => [$pluginKey, 'config'],
          '#array_parents' => [$pluginKey, 'config'],
        ],
      ];

      if ($plugin = $entity->getPlugin($pluginInfo['id'], TRUE)) {
        $valueKey = $hasData ? '#value' : '#default_value';
        $form[$pluginKey]['id'][$valueKey] = $plugin->getPluginId();

        if ($pluginFormInstance = $this->getConfigurePluginForm($plugin)) {
          $pluginForm = &$form[$pluginKey]['config'];
          $subformState = SubformState::createForSubform($pluginForm, $form, $form_state);
          $pluginForm = $pluginFormInstance->buildConfigurationForm($pluginForm, $subformState, $entity);

          // Apply the default form wrapping components if nothing was defined
          // internally by the plugin configuration form itself.
          $pluginForm += [
            '#type' => 'container',
            '#attributes' => [],
          ];
        }
        else {
          $form[$pluginKey]['config']['#value'] = [];
        }
      }

      // Add a consistent wrapper around the configuration form elements.
      $form[$pluginKey]['config']['#prefix'] = '<div id="' . $wrapperId . '">';
      $form[$pluginKey]['config']['#suffix'] = '</div>';
    }

    $form['additional_settings'] = [
      '#type' => 'vertical_tabs',
      '#weight' => 50,
    ];

    $form['landingPage']['#group'] = 'additional_settings';
    $form['landingPage']['#type'] = 'details';

    $form['search_settings'] = [
      '#type' => 'details',
      '#title' => $this->t('Search'),
      '#group' => 'additional_settings',

      'searchable' => [
        '#type' => 'checkbox',
        '#title' => $this->t('Is associated content searchable?'),
        '#default_value' => $entity->isContentSearchable(),
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    foreach ($this->getPluginDefinitions() as $pluginKey => $pluginDef) {
      $pluginId = $form_state->getValue([$pluginKey, 'id']);

      if (!empty($pluginId)) {
        try {
          $config = [];
          /** @var \Drupal\association\Entity\AssociationTypeInterface $entity */
          $entity = $this->getEntity();
          /** @var \Drupal\association\Entity\AssociationTypeInterface $current */
          $current = $this->entityTypeManager
            ->getStorage('association_type')
            ->load($entity->id());

          if ($current) {
            $currentPlugin = $current->get($pluginDef['id']);
            $config = $currentPlugin['id'] === $pluginId ? $currentPlugin['config'] : [];
          }

          $plugin = $pluginDef['manager']->createInstance($pluginId, $config);

          if ($pluginFormInstance = $this->getConfigurePluginForm($plugin)) {
            $subformState = SubformState::createForSubform($form[$pluginKey]['config'], $form, $form_state);
            $pluginFormInstance->validateConfigurationForm($form[$pluginKey]['config'], $subformState);
          }
        }
        catch (\Exception $e) {
          $form_state->setError($form[$pluginKey], $this->t('Unable to use selected @lablel plugin due to an internal error.', [
            '@label' => $pluginDef['label'],
          ]));
          Error::logException($this->getLogger('association'), $e);
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\association\Entity\AssociationTypeInterface $entity */
    $entity = $this->entity;

    try {
      foreach ($this->getPluginDefinitions() as $pluginKey => $pluginDef) {
        /** @var \Drupal\Component\Plugin\PluginInspectionInterface&\Drupal\Component\Plugin\ConfigurableInterface $plugin */
        $plugin = $entity->getPlugin($pluginDef['id']);

        // If this plugin uses a configuration form, allow the configuration
        // submit handler to properly handle building the configuration values.
        if ($pluginFormInstance = $this->getConfigurePluginForm($plugin)) {
          $subformState = SubformState::createForSubform($form[$pluginKey]['config'], $form, $form_state);
          $pluginFormInstance->submitConfigurationForm($form[$pluginKey]['config'], $subformState);

          $entity->set($pluginDef['id'], [
            'id' => $plugin->getPluginId(),
            'config' => $plugin->getConfiguration(),
          ]);
        }
      }

      // Save the bundle entity changes.
      $status = $entity->save();
      $form_state->setRedirectUrl($entity->toUrl('collection'));

      // Inform the admin that the association type has been saved.
      $msgParams = ['%label' => $entity->label()];
      $this->messenger()->addStatus(SAVED_NEW === $status
        ? $this->t('Created the %label Entity Association type.', $msgParams)
        : $this->t('Saved the %label Entity Association type changes.', $msgParams)
      );

      return $status;
    }
    catch (\Exception $e) {
      $this->messenger()->addError($this->t('Unable to have changes to the Entity Association type settings.'));
    }

    return 0;
  }

  /**
   * AJAX callback for when the association type behavior is changed.
   *
   * @param array $form
   *   Complete form structure and element definitions.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Current state, build information and user input for the form.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse|array
   *   A set of AJAX commands or a renderable array with the form changes to
   *   perform through AJAX.
   */
  public static function pluginConfigurationAjax(array $form, FormStateInterface $form_state) {
    $element = $form_state->getTriggeringElement();
    $parents = $element['#array_parents'];
    array_pop($parents);
    $parents[] = 'config';

    return NestedArray::getValue($form, $parents);
  }

  /**
   * Get list of association type plugin types.
   *
   * Enumerates the association plugin types and provides basic info about each
   * in order to create plugin configurations for each. These are plugins that
   * are managed at the association type, for all associations of that type.
   *
   * @return array
   *   The id, label and plugin options information about each of the
   *   association plugin types.
   */
  protected function getPluginDefinitions(): array {
    return [
      'behavior' => [
        'id' => 'behavior',
        'label' => $this->t('Behavior settings'),
        'manager' => $this->behaviorManager,
        'options' => $this->getPluginOptions($this->behaviorManager),
      ],
      'landingPage' => [
        'id' => 'landing_page',
        'label' => $this->t('Landing page settings'),
        'manager' => $this->landingPageManager,
        'options' => $this->getPluginOptions($this->landingPageManager),
      ],
    ];
  }

  /**
   * Get a list of plugins options for use with association types.
   *
   * Association types have different plugin types that are configured at the
   * assocation type level. The ::getPluginDefinitions() method defines info
   * about the plugin types that can be configured.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]|string[]
   *   An array of behavior plugin labels, keyed by the plugin ID.
   *
   * @see self::getPluginDefinitions()
   */
  protected function getPluginOptions(PluginManagerInterface $plugin_manager): array {
    $options = [];
    foreach ($plugin_manager->getDefinitions() as $id => $definition) {
      $options[$id] = $definition['label'];
    }
    return $options;
  }

  /**
   * Get an instance of the plugin configuration form if there is one.
   *
   * @param \Drupal\Component\Plugin\PluginInspectionInterface $plugin
   *   The association plugin to generate a configuration form for.
   *
   * @return \Drupal\association\Plugin\AssociationPluginFormInterface|null
   *   A plugin form object if the plugin has a configuration form.
   */
  protected function getConfigurePluginForm(PluginInspectionInterface $plugin): ?AssociationPluginFormInterface {
    if ($plugin instanceof PluginFormInterface) {
      return $plugin;
    }

    if ($plugin instanceof PluginWithFormsInterface) {
      try {
        return $this->pluginFormFactory->createInstance($plugin, 'configure');
      }
      catch (InvalidPluginDefinitionException $e) {
        // Plugin does not have this form operation defined.
      }
    }
    return NULL;
  }

}

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

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