entityconnect-8.x-2.0-rc1/src/EntityconnectWidgetProcessor.php

src/EntityconnectWidgetProcessor.php
<?php

namespace Drupal\entityconnect;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\FieldConfigInterface;
use Drupal\views\Views;

/**
 * A reference field widget processing class for entityconnect module.
 */
class EntityconnectWidgetProcessor {
  use StringTranslationTrait;

  /**
   * The entity reference field definition.
   *
   * @var \Drupal\field\Entity\FieldConfig
   */
  protected $fieldDefinition;

  /**
   * The entity reference field widget element.
   *
   * @var array
   */
  protected $widget;

  /**
   * The entityconnect settings array.
   *
   * @var array
   */
  protected $entityconnectSettings;

  /**
   * The target entity type.
   *
   * @var string
   */
  protected $entityType;

  /**
   * The target entity bundles.
   *
   * @var array
   */
  protected $acceptableTypes;

  /**
   * Constructs a EntityconnectWidgetProcessor object.
   *
   * @param \Drupal\field\Entity\FieldConfig $field_definition
   *   The entity reference field definition.
   * @param array $widget
   *   The entity reference field widget form element.
   */
  public function __construct(FieldConfig $field_definition, array $widget) {
    $this->fieldDefinition = $field_definition;
    $this->widget = $widget;

    // Initialize entityconnect settings on the field.
    $this->entityconnectSettings = $this->fieldDefinition->getThirdPartySettings('entityconnect');
    // Use global defaults if no settings on the field.
    if (!$this->entityconnectSettings) {
      $this->entityconnectSettings = \Drupal::config('entityconnect.administration_config')->get();
    }

    // Initialize the target entity type and bundles.
    $this->initTargetInfo();
  }

  /**
   * Form API callback: Processes an entity_reference field element.
   *
   * Adds entityconnect buttons to the field.
   *
   * This method is assigned as a #process callback in
   * entityconnect_form_alter() function.
   *
   * @param array $element
   *   The widget container element to attach the buttons.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The parent entity form state.
   * @param array $form
   *   The parent entity form.
   *
   * @return array
   *   The altered element.
   */
  public static function process(array $element, FormStateInterface $form_state, array $form) {
    if (!method_exists($form_state->getFormObject(), 'getEntity')) {
      return $element;
    }

    $entity = $form_state->getFormObject()->getEntity();
    $fieldDefinition = $entity->getFieldDefinition($element['widget']['#field_name']);

    // Instantiate this class so we don't have to pass variables around.
    if ($fieldDefinition instanceof FieldConfigInterface) {
      $widgetProcessor = new EntityconnectWidgetProcessor($fieldDefinition, $element['widget']);

      // Give other contrib modules the chance to change the target.
      $entityType = $widgetProcessor->getEntityType();
      $acceptableTypes = $widgetProcessor->getAcceptableTypes();
      $data = [
        'entity_type' => &$entityType,
        'acceptable_types' => &$acceptableTypes,
        'field' => $fieldDefinition,
      ];
      \Drupal::moduleHandler()->alter('entityconnect_field_attach_form', $data);
      $widgetProcessor->setEntityType($data['entity_type']);
      $widgetProcessor->setAcceptableTypes($data['acceptable_types']);

      // We currently should separate Autocomplete widget from others
      // because "Edit" button will not react well on multiple selected items.
      // Autocomplete widget has no #type value, so we are testing it
      // via $element['widget']['#type']. This does not apply to
      // Autocomplete Tags widget so we have to check for target_id too.
      if (isset($element['widget']['#type']) || isset($element['widget']['target_id'])) {
        $widgetProcessor->attachButtons($element);
      }
      else {
        foreach (Element::getVisibleChildren($element['widget']) as $key) {
          if (is_numeric($key)) {
            $widgetProcessor->attachButtons($element, $key);
          }
        }
      }
    }

    return $element;
  }

  /**
   * Attach the entity connect buttons to a single widget element.
   *
   * @param array $element
   *   The widget element to attach the button to.
   * @param string $key
   *   The key of an autocomplete widget element.
   */
  protected function attachButtons(array &$element, $key = 'all') {

    // Get the parents.
    $parents = '';
    if (isset($this->widget['#field_parents'])) {
      foreach ($this->widget['#field_parents'] as $parent) {
        $parents .= ($parents ? '-' : '') . $parent;
      }
    }

    $fieldStorage = $this->fieldDefinition->getFieldStorageDefinition();
    $extraClass = $this->widget['#type'] ?? 'autocomplete';
    $extraClass .= $fieldStorage->getCardinality() > 1 ? ' multiple-values' : ' single-value';
    $extraClass .= (isset($this->widget['#multiple']) && $this->widget['#multiple'] == TRUE) ? ' multiple-selection' : ' single-selection';
    if (isset($this->widget['#type'])) {
      if ((isset($this->widget['#multiple']) && $this->widget['#multiple'] == TRUE) || $this->widget['#type'] == 'radios' || $this->widget['#type'] == 'checkboxes') {
        $element['#attributes']['class'][] = 'inline-label';
      }
    }

    // Set the class strings for the button.
    $buttonClasses = [
      'extra_class' => $extraClass,
      'parents_class' => $parents,
    ];

    // Set the correct element to attach to.
    if ($key === 'all') {
      // Options widget.
      if (isset($this->widget['#type'])) {
        $widgetElement = &$element;
      }
      // Autocomplete Tags widget.
      else {
        $widgetElement = &$element['widget'];
      }
    }
    // Autocomplete widget.
    else {
      $widgetElement = &$element['widget'][$key];
    }

    $this->attachAddButton($widgetElement, $buttonClasses, $key);
    $this->attachEditButton($widgetElement, $buttonClasses, $key);

  }

  /**
   * Attach the Add button.
   *
   * @param array $element
   *   The widget container element.
   * @param string[] $entityconnect_classes
   *   Button CSS definition array:
   *   - 'extra_class': extra css class string
   *   - 'parents_class': parents class string.
   * @param string $key
   *   Default is 'all' (optional).
   */
  protected function attachAddButton(array &$element, array $entityconnect_classes, $key = 'all') {

    // Button values are opposite; 0=On, 1=Off.
    $addbuttonallowed = empty($this->entityconnectSettings['buttons']['button_add']);
    $addIcon = $this->entityconnectSettings['icons']['icon_add'];

    // Get the subset of target bundles the user has permission to create.
    $acceptableTypes = [];

    if (!$this->acceptableTypes) {
      // @FIXME: The acceptable types is ALL so check the access for all.
      if (\Drupal::entityTypeManager()
        ->getAccessControlHandler($this->entityType)
        ->createAccess($this->entityType)
      ) {
        $acceptableTypes[] = $this->entityType;
      }
    }
    else {
      foreach ($this->acceptableTypes as $bundle) {
        if (\Drupal::entityTypeManager()
          ->getAccessControlHandler($this->entityType)
          ->createAccess($bundle)
        ) {
          $acceptableTypes[] = $bundle;
        }
      }
    }
    // Now we need to make sure the user should see this button.
    if (\Drupal::currentUser()->hasPermission('entityconnect add button') && $addbuttonallowed && $acceptableTypes) {
      $classes = [];
      // Determine how the button should be displayed.
      if (isset($addIcon)) {
        if ($addIcon == '0') {
          $classes = $entityconnect_classes['extra_class'] . ' add-icon';
        }
        elseif ($addIcon == '1') {
          $classes = $entityconnect_classes['extra_class'] . ' add-icon add-text';
        }
        else {
          $classes = $entityconnect_classes['extra_class'];
        }
      }

      // Build the button name.
      $button_name = "add_entityconnect__{$this->fieldDefinition->getName()}_{$key}_{$entityconnect_classes['parents_class']}";

      // Build the button element.
      $element[$button_name] = [
        '#type' => 'entityconnect_submit',
        '#value' => $this->t('New content'),
        '#name' => $button_name,
        '#prefix' => "<div class = 'entityconnect-add $classes'>",
        '#suffix' => '</div>',
        '#key' => $key,
        '#field' => $this->fieldDefinition->getName(),
        '#entity_type_target' => $this->entityType,
        '#acceptable_types' => $acceptableTypes,
        '#add_child' => TRUE,
        '#weight' => 100,
      ];

      // Button should be at same form level as widget,
      // or text box if multivalue autocomplete field.
      $parents = $this->widget['#parents'];
      if (is_numeric($key)) {
        $parents[] = $key;
      }
      $element[$button_name]['#parents'] = array_merge($parents, [$button_name]);

    }
  }

  /**
   * Attach the edit button.
   *
   * @param array $element
   *   The widget container element.
   * @param string[] $entityconnect_classes
   *   Button CSS definition array:
   *   - 'extra_class': extra css class string
   *   - 'parents_class': parents class string.
   * @param int|string $key
   *   Target entity id (optional).
   */
  protected function attachEditButton(array &$element, array $entityconnect_classes, $key = 'all') {

    // Button values are opposite; 0=On, 1=Off.
    $editbuttonallowed = empty($this->entityconnectSettings['buttons']['button_edit']);
    $editIcon = $this->entityconnectSettings['icons']['icon_edit'];

    // Now we need to make sure the user should see this button.
    if (\Drupal::currentUser()->hasPermission('entityconnect edit button') && $editbuttonallowed) {
      $classes = [];
      // Determine how the button should be displayed.
      if (isset($editIcon)) {
        if ($editIcon == '0') {
          $classes = $entityconnect_classes['extra_class'] . ' edit-icon';
        }
        elseif ($editIcon == '1') {
          $classes = $entityconnect_classes['extra_class'] . ' edit-icon edit-text';
        }
        else {
          $classes = $entityconnect_classes['extra_class'];
        }
      }

      // Build the button name.
      $button_name = "edit_entityconnect__{$this->fieldDefinition->getName()}_{$key}_{$entityconnect_classes['parents_class']}";

      // Build the button element.
      $element[$button_name] = [
        '#type' => 'entityconnect_submit',
        '#value' => $this->t('Edit content'),
        '#name' => $button_name,
        '#prefix' => "<div class = 'entityconnect-edit $classes'>",
        '#suffix' => '</div>',
        '#key' => $key,
        '#field' => $this->fieldDefinition->getName(),
        '#entity_type_target' => $this->entityType,
        '#acceptable_types' => $this->acceptableTypes,
        '#add_child' => FALSE,
        '#weight' => 100,
      ];

      // Button should be at same form level as widget,
      // or text box if multivalue autocomplete field.
      $parents = $this->widget['#parents'];
      if (is_numeric($key)) {
        $parents[] = $key;
      }
      $element[$button_name]['#parents'] = array_merge($parents, [$button_name]);

    }
  }

  /**
   * Returns the array of acceptable target bundles.
   *
   * @return array
   *   Array of acceptable bundles.
   */
  public function getAcceptableTypes() {
    return $this->acceptableTypes;
  }

  /**
   * Returns the target entity type.
   *
   * @return string
   *   Target entity type.
   */
  public function getEntityType() {
    return $this->entityType;
  }

  /**
   * Sets the target entity type.
   *
   * @param string $entityType
   *   Target entity type.
   */
  public function setEntityType($entityType) {
    $this->entityType = $entityType;
  }

  /**
   * Sets the target bundles.
   *
   * @param array $acceptableTypes
   *   Array of acceptable bundles.
   */
  public function setAcceptableTypes(array $acceptableTypes) {
    $this->acceptableTypes = $acceptableTypes;
  }

  /**
   * Initialize entityType and targetBundles from the handler settings.
   */
  protected function initTargetInfo() {
    $targetSettings = $this->fieldDefinition->getSettings();
    $this->entityType = $targetSettings['target_type'];
    $this->acceptableTypes = [];

    // If this is the default setting then just get the target bundles.
    if (isset($targetSettings['handler_settings']['target_bundles'])) {
      if (!is_null($targetSettings['handler_settings']['target_bundles'])) {
        $this->acceptableTypes = $targetSettings['handler_settings']['target_bundles'];
      }
      else {
        // Use the entity type if the target entity has no bundles.
        $this->acceptableTypes[] = $this->entityType;
      }
    }
    // If this is an entity_reference view, then try getting the target bundles
    // from the filter.
    elseif ($targetSettings['handler'] == 'views') {
      $view = Views::getView($targetSettings['handler_settings']['view']['view_name']);
      // Get filters from the entity_reference display.
      $viewDisplay = $view->storage->getDisplay($targetSettings['handler_settings']['view']['display_name']);
      if (!isset($viewDisplay['display_options']['filters'])) {
        // Get filters from the Master display.
        $viewDisplay = $view->storage->getDisplay('default');
      }

      switch ($this->entityType) {
        // Type(bundle) value is under vid key for taxonomy terms.
        case 'taxonomy_term':
          if (isset($viewDisplay['display_options']['filters']['vid'])) {
            $this->acceptableTypes = $viewDisplay['display_options']['filters']['vid']['value'];
          }
          break;

        // Otherwise, type(bundle) value is under type key.
        default:
          if (isset($viewDisplay['display_options']['filters']['type'])) {
            $this->acceptableTypes = $viewDisplay['display_options']['filters']['type']['value'];
          }
          // $this->acceptableTypes was already set to empty array before.
          break;
      }
    }
  }

}

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

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