computed_field-8.x-2.x-dev/src/Element/ComputedFieldPlugin.php

src/Element/ComputedFieldPlugin.php
<?php

namespace Drupal\computed_field\Element;

use Drupal\computed_field\Utility\NestedArrayRecursive;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\FormElement;
use Symfony\Component\HttpFoundation\Request;

/**
 * Form element for selecting and configuring a computed field plugin.
 *
 * @todo Replace this with Plugin module when
 * https://www.drupal.org/project/plugin/issues/3197304 is fixed. Any changes to
 * this class should be submitted to the merge request on that issue.
 *
 * @FormElement("computed_field")
 */
class ComputedFieldPlugin extends FormElement {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $class = static::class;

    return [
      '#input' => TRUE,
      '#element_validate' => [
        [$class, 'validatePluginConfiguration'],
      ],
      '#process' => [
        [$class, 'processPlugin'],
      ],
      '#options_element_type' => 'select',
    ];
  }

  /**
   * Process callback.
   */
  public static function processPlugin(&$element, FormStateInterface $form_state, &$complete_form) {
    $element['#tree'] = TRUE;

    $container_html_id = Html::getUniqueId('ajax-link');
    $element['container'] = [
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => $element['#title'] ?? '',
      '#attributes' => ['id' => $container_html_id],
    ];

    $plugin_id_parents = $element['#array_parents'];
    $plugin_id_parents[] = 'plugin_id';

    if (empty($form_state->getValue($plugin_id_parents))) {
      $selected_plugin_id = $element['#default_value']['plugin_id'] ?? '';
    }
    else {
      // Get the value if it already exists.
      $selected_plugin_id = $form_state->getValue($plugin_id_parents);
    }

    $element['container']['plugin_id'] = [
      '#type' => $element['#options_element_type'],
      '#title' => $element['#title'] ?? '',
      '#options' => [],
      '#empty_value' => '',
      '#required' => $element['#required'],
      '#default_value' => $selected_plugin_id,
      '#ajax' => [
        'callback' => [static::class, 'pluginDropdownCallback'],
        'wrapper' => $container_html_id,
        'options' => [
          // Pass the array parents to the AJAX callback in a query parameter,
          // so that it can determine where in the form our element is located.
          'query' => [
            'element_parents' => implode('/', $element['#array_parents']),
          ],
        ],
      ],
    ];

    // Build the plugin options.
    $options = [];

    $plugins_method = $element['#plugins_method'] ?? 'getDefinitions';
    foreach (static::getPluginManager()->{$plugins_method}() as $plugin_id => $plugin_definition) {
      $options[$plugin_id] = $plugin_definition['label'];

      // Add plugin descriptions to radios, if they exist.
      if (isset($plugin_definition['description']) && $element['#options_element_type'] == 'radios') {
        $element['container']['plugin_id'][$plugin_id]['#description'] = $plugin_definition['description'];
      }
    }
    natcasesort($options);
    $element['container']['plugin_id']['#options'] = $options;

    // Add the plugin's configuration form, if it provides one.
    if ($selected_plugin_id) {
      $plugin = static::getPluginManager()->createInstance($selected_plugin_id);
      if ($plugin instanceof PluginFormInterface) {
        $plugin_subform = [];
        $element['container']['plugin_configuration'] = $plugin->buildConfigurationForm($plugin_subform, SubformState::createForSubform($plugin_subform, $element, $form_state));

        // If this is the original load of the form, set the default values on
        // the plugin configuration.
        if (isset($element['#default_value']['plugin_id']) && $element['#default_value']['plugin_id'] == $selected_plugin_id) {
          $plugin_configuration_form = &$element['container']['plugin_configuration'];

          // Recurse into nested configuration values.
          NestedArrayRecursive::arrayWalkNested($element['#default_value']['plugin_configuration'], function ($value, $parents) use (&$plugin_configuration_form) {
            $default_value_parents = $parents;
            $default_value_parents[] = '#default_value';

            // Allow plugin forms to set default values themselves.
            $default_value_key_exists = NULL;
            NestedArray::getValue($plugin_configuration_form, $default_value_parents, $default_value_key_exists);

            if (!$default_value_key_exists) {
              NestedArray::setValue($plugin_configuration_form, $default_value_parents, $value);
            }
          });
        }
      }
      else {
        $element['container']['plugin_configuration'] = [
          '#markup' => t("The @label plugin has no configuration.", [
            '@label' => $plugin->getPluginDefinition()['label'],
          ]),
        ];
      }
    }

    return $element;
  }

  /**
   * AJAX callback for the plugin ID select element.
   */
  public static function pluginDropdownCallback(&$form, FormStateInterface &$form_state, Request $request) {
    $form_parents = explode('/', $request->query->get('element_parents'));

    // Sanitize form parents before using them.
    $form_parents = array_filter($form_parents, [Element::class, 'child']);

    // Retrieve the element to be rendered.
    $form = NestedArray::getValue($form, $form_parents);

    return $form;
  }

  /**
   * Element validate callback.
   */
  public static function validatePluginConfiguration($element, FormStateInterface &$form_state, $form) {
    $plugin_id_parents = $element['#array_parents'];
    $plugin_id_parents[] = 'plugin_id';
    $selected_plugin_id = $form_state->getValue($plugin_id_parents);
    if ($selected_plugin_id) {
      $plugin = static::getPluginManager()->createInstance($selected_plugin_id);
      if ($plugin instanceof PluginFormInterface) {
        $plugin->validateConfigurationForm($element, $form_state);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    if ($input === FALSE) {
      return $element['#default_value'] ?? [];
    }
    elseif ($input === NULL) {
      // Not sure how this happens.
      return '';
    }
    else {
      return $input['container'];
    }
  }

  /**
   * Gets the plugin manager.
   *
   * @return mixed
   *   The plugin manager service for the plugin type.
   */
  protected static function getPluginManager() {
    return \Drupal::service('plugin.manager.computed_field');
  }

}

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

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