breezy_utility-1.0.x-dev/src/Plugin/BreezyUtility/Element/BreezyUtilityElementBase.php

src/Plugin/BreezyUtility/Element/BreezyUtilityElementBase.php
<?php

namespace Drupal\breezy_utility\Plugin\BreezyUtility\Element;

use Drupal\breezy_utility\BreezyUtilityClassServiceInterface;
use Drupal\breezy_utility\BreezyUtilityElementPluginManagerInterface;
use Drupal\breezy_utility\Utility\BreezyUtilityElementHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\OptGroup;
use Drupal\Core\Plugin\PluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a base for BreezyUtilityElement plugins.
 *
 * @package Drupal\breezy_utility\Plugin\BreezyUtility\Element.
 */
abstract class BreezyUtilityElementBase extends PluginBase implements BreezyUtilityElementInterface {

  /**
   * The element.
   *
   * @var array
   */
  protected array $element = [];

  /**
   * The CSS property.
   *
   * @var string
   */
  protected string $property = '';

  /**
   * BreezyUtilityElementPluginManagerInterface definition.
   *
   * @var \Drupal\breezy_utility\BreezyUtilityElementPluginManagerInterface
   */
  protected BreezyUtilityElementPluginManagerInterface $elementManager;

  /**
   * BreezyUtilityClassServiceInterface definition.
   *
   * @var \Drupal\breezy_utility\BreezyUtilityClassServiceInterface
   */
  protected BreezyUtilityClassServiceInterface $classService;

  /**
   * An associative array of an element's default properties names and values.
   *
   * @var array
   */
  protected $defaultProperties;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);

    /** @var \Drupal\breezy_utility\BreezyUtilityElementPluginManagerInterface $element_manager */
    $element_manager = $container->get('plugin.manager.breezy_utility.element');
    $instance->elementManager = $element_manager;

    /** @var \Drupal\breezy_utility\BreezyUtilityClassServiceInterface $class_service */
    $class_service = $container->get('breezy_utility.utility_classes');
    $instance->classService = $class_service;

    return $instance;
  }

  /**
   * Define an element's default properties.
   *
   * @return array
   *   An associative array contain an the element's default properties.
   */
  protected function defineDefaultProperties(): array {
    $properties = [
      'title' => '',
      'default_value' => '',
      'required' => FALSE,
      'attributes' => [],
      'property' => '',
    ];
    $properties += $this->defineDefaultBaseProperties();
    return $properties;
  }

  /**
   * Define default multiple properties used by most elements.
   *
   * @return array
   *   An associative array containing default multiple properties.
   */
  protected function defineDefaultMultipleProperties(): array {
    return [
      'multiple' => FALSE,
      'multiple__header_label' => '',
      'multiple__min_items' => NULL,
      'multiple__empty_items' => 1,
      'multiple__add_more' => TRUE,
      'multiple__add_more_items' => 1,
      'multiple__add_more_button_label' => (string) $this->t('Add'),
      'multiple__add_more_input' => TRUE,
      'multiple__add_more_input_label' => (string) $this->t('more items'),
      'multiple__item_label' => (string) $this->t('item'),
      'multiple__no_items_message' => '<p>' . $this->t('No items entered. Please add items below.') . '</p>',
      'multiple__sorting' => TRUE,
      'multiple__operations' => TRUE,
      'multiple__add' => TRUE,
      'multiple__remove' => TRUE,
    ];
  }

  /**
   * Define default base properties used by all elements.
   *
   * @return array
   *   An associative array containing base properties used by all elements.
   */
  protected function defineDefaultBaseProperties(): array {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultProperties(): array {
    if (!isset($this->defaultProperties)) {
      $properties = $this->defineDefaultProperties();
      // Apply default format settings to element edit form properties.
      // This approach prevents having to refactor how default formats
      // are handled.
      $this->defaultProperties = $properties;
    }
    return $this->defaultProperties;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration(): array {
    return [
      'property' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getConfiguration() {
    return $this->configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    $this->configuration = $configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function isInput(array $element): bool {
    return (!empty($element['#type'])) ? TRUE : FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function hasProperty($property_name): bool {
    $default_properties = $this->getDefaultProperties();
    return array_key_exists($property_name, $default_properties);
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultProperty($property_name) {
    $default_properties = $this->getDefaultProperties();
    return (array_key_exists($property_name, $default_properties)) ? $default_properties[$property_name] : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getElementProperty(array $element, $property_name) {
    return $element["#$property_name"] ?? $this->getDefaultProperty($property_name);
  }

  /**
   * {@inheritdoc}
   */
  public function label(): string {
    return $this->pluginDefinition['label'];
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription() {
    return $this->pluginDefinition['description'] ?? NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function isHidden(): bool {
    return $this->pluginDefinition['hidden'];
  }

  /**
   * {@inheritdoc}
   */
  public function hasUi(): bool {
    return $this->pluginDefinition['ui'];
  }

  /**
   * {@inheritdoc}
   */
  public function initialize(array &$element) {
    // Set element options.
    // @todo Allow for creating options.
    // Set #admin_title to #title without any HTML markup.
    if (!empty($element['#title']) && empty($element['#admin_title'])) {
      $element['#admin_title'] = strip_tags($element['#title']);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function prepare(array &$element) {
    $attributes_property = ($this->hasWrapper($element)) ? '#wrapper_attributes' : '#attributes';

    // Enable template preprocessing enhancements.
    // @see \Drupal\webform\Utility\WebformElementHelper::isWebformElement
    $element['#breezy_utility_element'] = TRUE;

    // Add .breezy-utility-has-field-prefix and .breezy-utility-has-field-suffix
    // class.
    if (!empty($element['#field_prefix'])) {
      $element[$attributes_property]['class'][] = 'breezy-utility-has-field-prefix';
    }
    if (!empty($element['#field_suffix'])) {
      $element[$attributes_property]['class'][] = 'breezy-utility-has-field-suffix';
    }

  }

  /**
   * {@inheritdoc}
   */
  public function setDefaultValue(array &$element) {

  }

  /**
   * {@inheritdoc}
   */
  public function getLabel(array $element): string {
    return (!empty($element['#title'])) ? $element['#title'] : $element['#breezy_utility_key'];
  }

  /**
   * {@inheritdoc}
   */
  public function getAdminLabel(array $element): string {
    $element += ['#admin_title' => '', '#title' => '', '#breezy_utility_key' => ''];
    return $element['#admin_title'] ?: $element['#title'] ?: $element['#breezy_utility_key'];
  }

  /**
   * {@inheritdoc}
   */
  public function getKey(array $element): string {
    return $element['#breezy_utility_key'];
  }

  /**
   * {@inheritdoc}
   */
  public function hasWrapper(array $element) {
    return $this->hasProperty('wrapper_attributes');
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $element = $form_state->get('element');
    if (is_null($element)) {
      throw new \Exception('Element must be defined in the $form_state.');
    }
    // The CSS property.
    $this->property = $form_state->get('property');

    // Element properties.
    $default_properties = $this->getDefaultProperties();

    $element_properties = $form_state->get('element') + $default_properties;

    // Set default and element properties.
    // Note: Storing this information in the variant's state allows modules to
    // view and alter this information using variant alteration hooks.
    $form_state->set('default_properties', $default_properties);
    $form_state->set('element_properties', $element_properties);

    $form = $this->form($form, $form_state);

    // Get default and element properties which can be altered by
    // WebformElementHandlers.
    // @see \Drupal\webform\Plugin\WebformElement\WebformEntityReferenceTrait::form
    $element_properties = $form_state->get('element_properties');

    // Copy element properties to custom properties which will be determined
    // as the default values are set.
    $custom_properties = $element_properties;

    // Populate the form.
    $this->setConfigurationFormDefaultValueRecursive($form, $custom_properties);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state): array {

    $element = $form_state->get('element');
    $type = $element['#type'];

    $form['element'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Settings for @element', [
        '@element' => $this->label(),
      ]),
      '#weight' => -50,
    ];

    $form['element']['type'] = [
      '#type' => 'hidden',
      '#value' => $type,
    ];

    $form['element']['title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Title'),
      '#required' => TRUE,
      '#default_value' => $form_state->getValue('title') ?? '',
    ];

    $form['element']['required'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Required'),
      '#default_value' => $form_state->getValue('required') ?? FALSE,
    ];

    // Get the property plugin, display the API url.
    if ($api_url = $this->classService->getPropertyApiUrl($this->property)) {
      $form['element']['property_api'] = [
        '#title' => $this->t('Documentation for: <em>@property</em>', ['@property' => $this->property]),
        '#type' => 'link',
        '#url' => $api_url,
        '#attributes' => [
          'target' => '_blank',
        ],
      ];
    }

    // Placeholder elements with #options.
    // @see \Drupal\breezy_utility\Plugin\BreezyUtility\Element\OptionsBase::form
    $form['options'] = [];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function getConfigurationFormProperties(array $form, FormStateInterface $form_state) {
    $element_properties = $form_state->getValues();

    return $element_properties;
  }

  /**
   * Set configuration default values recursively.
   *
   * @param array $form
   *   A variant render array.
   * @param array $element_properties
   *   The element's properties without hash prefix. Any property that is found
   *   in the variant will be populated and unset from
   *   $element_properties array.
   *
   * @return bool
   *   TRUE is the variant has any inputs.
   */
  protected function setConfigurationFormDefaultValueRecursive(array &$form, array &$element_properties) {

    $has_input = FALSE;
    foreach ($form as $property_name => &$property_element) {

      if (BreezyUtilityElementHelper::property($property_name)) {
        continue;
      }

      if ($property_name == 'property') {
        continue;
      }

      $is_input = $this->elementManager->getElementInstance($property_element)->isInput($property_element);

      if ($is_input) {
        if (array_key_exists($property_name, $element_properties)) {
          // If this property exists, then set its default value.
          $this->setConfigurationFormDefaultValue($form, $element_properties, $property_element, $property_name);
          $has_input = TRUE;
        }
      }
      else {
        // Recurse down this container and see if it's children have inputs.
        $container_has_input = $this->setConfigurationFormDefaultValueRecursive($property_element, $element_properties);
        if ($container_has_input) {
          $has_input = TRUE;
        }
      }
    }

    return $has_input;
  }

  /**
   * Set an element's configuration element default value.
   *
   * @param array $form
   *   An element's configuration form.
   * @param array $element_properties
   *   The element's properties without hash prefix.
   * @param array $property_element
   *   The form input used to set an element's property.
   * @param string $property_name
   *   THe property's name.
   */
  protected function setConfigurationFormDefaultValue(array &$form, array &$element_properties, array &$property_element, $property_name) {
    $default_value = '';
    if (isset($element_properties['element'][$property_name])) {
      $default_value = $element_properties['element'][$property_name];
    }
    $type = $property_element['#type'] ?? NULL;

    switch ($type) {
      case 'radios':
      case 'select':
        if (isset($default_value['options'])) {
          $default_value = $default_value['options'];
        }
        if (!is_array($default_value) && isset($property_element['#options'])) {
          $flattened_options = OptGroup::flattenOptions($property_element['#options']);
          if (!isset($flattened_options[$default_value])) {
            $default_value = NULL;
          }
        }

        $property_element['#default_value'] = $default_value;

        break;

      default:
        // Convert default_value array into a comma delimited list.
        // This is applicable to elements that support #multiple #options.
        // @todo Check if element is composite.
        if (is_array($default_value) && $property_name === 'default_value') {
          $property_element['#default_value'] = implode(', ', $default_value);
        }
        elseif (is_bool($default_value) && $property_name === 'default_value') {
          $property_element['#default_value'] = $default_value ? 1 : 0;
        }
        elseif (is_null($default_value) && $property_name === 'default_value') {
          $property_element['#default_value'] = (string) $default_value;
        }
        else {
          $property_element['#default_value'] = $default_value;
        }
        break;
    }
    $property_element['#parents'] = ['properties', 'element', $property_name];
    unset($element_properties[$property_name]);
  }

  /**
   * {@inheritdoc}
   */
  public function getTableColumn(array $element) {
    $key = $element['#breezy_utility_key'];
    return [
      'element__' . $key => [
        'title' => $this->getAdminLabel($element),
        'sort' => TRUE,
        'key' => $key,
        'property_name' => NULL,
        'element' => $element,
        'plugin' => $this,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function hasMultipleValues(array $element): bool {
    if ($this->hasProperty('multiple')) {
      if (isset($element['#multiple'])) {
        return $element['#multiple'];
      }
      else {
        $default_property = $this->getDefaultProperties();
        return $default_property['multiple'];
      }
    }
    else {
      return FALSE;
    }
  }

}

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

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