reviewer-1.2.x-dev/modules/reviewer_test_kit/src/Plugin/reviewer/Task/Entity/Display/DisplayFieldsTaskBase.php

modules/reviewer_test_kit/src/Plugin/reviewer/Task/Entity/Display/DisplayFieldsTaskBase.php
<?php

declare(strict_types=1);

namespace Drupal\reviewer_test_kit\Plugin\reviewer\Task\Entity\Display;

use Drupal\Core\Entity\Display\EntityDisplayInterface;

/**
 * Base task for checking entity display field configuration.
 *
 * While it may be occasionally useful to extend this class, there is likely a
 * different reviewer test kit task that could be used to implement checks with
 * much less effort instead.
 *
 * Tasks extending this class must define either the $fieldTypes or $fieldNames
 * properties. If both properties are empty, a \LogicException will be thrown.
 */
abstract class DisplayFieldsTaskBase extends DisplayTaskBase {

  /**
   * The types of fields to check.
   *
   * Field types are the field widget or formatter plugin names. To check all
   * fields, set the value to ['*'].
   *
   * Entity reference fields often do not convey enough information for tasks to
   * accurately check the field based on type alone, because the correct
   * behavior is often dependent on the type of handler and bundle of the entity
   * referenced. In this case, you may specify the handler as the array key. You
   * may also specify handler bundles using a pipe followed by a comma-separated
   * list.
   *
   * For example, to check all entity reference media fields use
   * ['default:media' => 'entity_reference'], and to check only image and icon
   * media fields use ['default:media|icon,image' => 'entity_reference'].
   *
   * Do not access this directly in tasks, but use the fieldsToCheck() method to
   * return a list of fields from the $fieldNames and $fieldTypes properties
   * evaluated for a specific entity display.
   *
   * A \LogicException will be thrown if this property and $fieldNames are both
   * empty.
   *
   * @var array<int|string, string>
   *
   * @see \Drupal\Core\Field\FieldDefinitionInterface
   * @see \Drupal\reviewer_test_kit\Plugin\reviewer\Task\Entity\Display\DisplayTaskBase
   */
  protected array $fieldTypes = [];

  /**
   * The names of fields to check.
   *
   * To check all fields, set the value to ['*'].
   *
   * Do not access this directly in tasks, but use the fieldsToCheck() method to
   * return a list of fields from the $fieldNames and $fieldTypes properties
   * evaluated for a specific entity display.
   *
   * A \LogicException will be thrown if this property and $fieldTypes are both
   * empty.
   *
   * @var string[]
   */
  protected array $fieldNames = [];

  /**
   * {@inheritdoc}
   */
  protected function checkValidProperties(): void {
    parent::checkValidProperties();

    if (\count($this->fieldTypes) === 0 && \count($this->fieldNames) === 0) {
      throw new \LogicException(sprintf('Both %1$s::fieldTypes and %1$s::fieldNames properties cannot be empty.', static::class));
    }
  }

  /**
   * Get a list of all field names to check for a specific display.
   *
   * @return string[]
   */
  protected function fieldsToCheck(EntityDisplayInterface $display): array {
    // If all field names are specified, then skip the more expensive type
    // checks and just return all the field names from the components.
    return $this->fieldNames === ['*']
      ? array_keys($this->fieldsCallback($display))
      : array_unique(array_merge($this->fieldNames, $this->fieldNamesFromTypes($display)));
  }

  /**
   * Get all field names matching the field type and optional handler.
   *
   * @return string[]
   */
  protected function fieldNamesFromTypes(EntityDisplayInterface $display): array {
    // We can short-circuit here if types are empty or all types are matched.
    if (!$this->fieldTypes) {
      return [];
    }

    if ($this->fieldTypes === ['*']) {
      return array_keys($this->fieldsCallback($display));
    }

    // Only check fields which match the type.
    $field_names = array_filter(
      $this->fieldsCallback($display),
      fn(array $configuration): bool => \in_array($configuration['type'] ?? '', $this->fieldTypes, TRUE),
    );

    // No string keys means no handlers to parse.
    if (array_is_list($this->fieldTypes)) {
      return array_keys($field_names);
    }

    // Order the types so those without handlers come first. This helps later
    // to not load field definitions to check handlers unless it's necessary.
    $field_types = $this->fieldTypes;
    ksort($field_types);

    foreach ($field_names as $field_name => $configuration) {
      $field_definition = NULL;

      foreach ($field_types as $handler => $field_type) {
        // Get the field definition it doesn't exist yet.
        $field_definition ??= $this->fieldDefinition($field_name);

        // Fields without a field definition are not valid matches.
        if (!$field_definition) {
          break;
        }

        if (\is_int($handler)) {
          // Types without handlers were sorted to the end, so if the type
          // matches move on to the next field, as types with handlers have
          // already been checked.
          if (($configuration['type'] ?? '') === $field_type) {
            continue 2;
          }

          // The type does not match, so keep looking through the types.
          continue;
        }

        // Retrieve the handler and bundles for the field.
        [$handler, $bundles] = array_pad(explode('|', $handler), 2, NULL);

        // The handler does not match, so keep looking through the types.
        if ($field_definition->getSetting('handler') !== $handler) {
          continue;
        }

        // If there are bundles specified, make sure these match as well.
        if ($bundles) {
          $bundles = explode(',', $bundles);
          /** @var array{target_bundles?: string[]} $handler_settings */
          $handler_settings = $field_definition->getSetting('handler_settings');
          $field_bundles = $handler_settings['target_bundles'] ?? [];

          // No bundles are matched on the field, so keep looking through the
          // types.
          if (\count(array_intersect($bundles, $field_bundles)) === 0) {
            continue;
          }
        }

        // The handler and bundles match, so move on to the next field.
        continue 2;
      }

      // There was no handler or bundle match that moved over this field, so it
      // should be removed.
      unset($field_names[$field_name]);
    }

    return array_keys($field_names);
  }

}

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

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