rdf_sync-1.x-dev/src/Form/Alter/BundleEntityFormAlter.php

src/Form/Alter/BundleEntityFormAlter.php
<?php

declare(strict_types=1);

namespace Drupal\rdf_sync\Form\Alter;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\text\Plugin\Field\FieldType\TextItemBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Bundle entity form alter.
 */
class BundleEntityFormAlter extends AbstractFormAlter implements ContainerInjectionInterface {

  use DependencySerializationTrait;

  /**
   * Constructs BundleEntityFormAlter instance.
   *
   * @param \Drupal\Component\Plugin\PluginManagerInterface $uriGeneratorPluginManager
   *   Plugin manager.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   Entity field manager.
   * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $fieldTypePluginManager
   *   Field type manager.
   */
  public function __construct(
    protected PluginManagerInterface $uriGeneratorPluginManager,
    protected EntityFieldManagerInterface $entityFieldManager,
    protected FieldTypePluginManagerInterface $fieldTypePluginManager,
  ) {

  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new static(
      $container->get('plugin.manager.rdf_sync.uri_generator'),
      $container->get('entity_field.manager'),
      $container->get('plugin.manager.field.field_type'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function alter(array &$form, FormStateInterface $formState): void {
    /** @var \Drupal\Core\Entity\BundleEntityFormBase $bundleEntity */
    $bundleEntity = $formState->getFormObject();
    /** @var \Drupal\Core\Config\Entity\ConfigEntityBundleBase $configEntity */
    $configEntity = $bundleEntity->getEntity();

    $settings = $configEntity->getThirdPartySettings('rdf_sync');

    $form['rdf_sync'] = [
      '#type' => 'details',
      '#group' => 'additional_settings',
      '#title' => $this->t('RDF sync'),
      '#open' => TRUE,
      '#weight' => 10,
      '#tree' => TRUE,
    ];

    $hideStates = [
      'visible' => [':input[name="rdf_sync[enabled]"]' => ['checked' => TRUE]],
    ];

    $form['rdf_sync']['enabled'] = [
      '#type' => 'checkbox',
      '#default_value' => !empty($settings['type']),
      '#title' => $this->t('Enable RDF sync'),
    ];

    $form['rdf_sync']['type'] = [
      '#type' => 'url',
      '#title' => $this->t('RDF type mapping'),
      '#default_value' => $settings['type'] ?? '',
      '#states' => $hideStates +
        ['required' => $hideStates['visible']],
    ];

    $form['rdf_sync']['uri_field_name'] = [
      '#type' => 'textfield',
      '#title' => $this->t('URI field name'),
      '#description' => $this->t('If omitted, <code>uri</code> will be used.'),
      '#default_value' => $settings['uri_field_name'] ?? '',
      '#states' => $hideStates,
    ];

    $form['rdf_sync']['uri_plugin'] = [
      '#type' => 'select',
      '#title' => $this->t('URI generator plugin'),
      '#default_value' => $settings['uri_plugin'] ?? '',
      '#empty_value' => '',
      '#options' => $this->getListOfPluginOptions(),
      '#states' => $hideStates,
    ];

    $form['rdf_sync']['base_fields_mapping'] = [
      '#type' => 'details',
      '#title' => $this->t('Field mapping'),
      '#description' => $this->t('Please map the bundle base fields to their corresponding RDF properties.'),
      '#states' => $hideStates,
    ];

    $baseFields = $this->entityFieldManager->getBaseFieldDefinitions($configEntity->getEntityType()
      ->getBundleOf());

    foreach ($baseFields as $baseField) {
      $fieldColumns = $this->getColumnFields($baseField);
      if (empty($fieldColumns)) {
        continue;
      }

      $form['rdf_sync']['base_fields_mapping'][$baseField->getName()] = [
        '#type' => 'details',
        '#title' => $baseField->getLabel(),
        '#description' => $baseField->getDescription(),
      ];

      foreach ($fieldColumns as $column) {
        $fieldSettings = $settings['fields'][$baseField->getName()][$column] ?? [];

        $form['rdf_sync']['base_fields_mapping'][$baseField->getName()][$column] = [
          '#type' => 'details',
          '#title' => $column,
          '#open' => TRUE,
        ];

        $form['rdf_sync']['base_fields_mapping'][$baseField->getName()][$column]['predicate'] = $this->getPredicateElement($fieldSettings);
        $form['rdf_sync']['base_fields_mapping'][$baseField->getName()][$column]['type'] = $this->getTypeElement($fieldSettings);
      }
    }

    $form['rdf_sync']['namespaces'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Namespaces'),
      '#description' => [
        [
          '#markup' => $this->t("Add one namespace per line with the prefix and its URI separated by a pipe (|). For instance:"),
        ],
        [
          '#markup' => "my-ns|http://example.com/my-namespace#\nother|http://example.com/other/",
          '#prefix' => '<pre><code>',
          '#suffix' => '</code></pre>',
        ],
      ],
      '#default_value' => $this->packNamespaces($settings['namespaces'] ?? []),
      '#states' => $hideStates,
    ];

    // Since this entityFormEntityBuild and also the helper methods it uses are
    // heavily building on services, it seems it isn't a very bad idea to add
    // it as an non-static callable. But we use DependencySerializationTrait
    // because the form *must* stay serializable.
    $form['#entity_builders'][] = [$this, 'entityFormEntityBuild'];
  }

  /**
   * Gets list of plugin options.
   *
   * @return array
   *   List of plugins.
   */
  protected function getListOfPluginOptions(): array {
    return array_reduce(
      $this->uriGeneratorPluginManager->getDefinitions(),
      function ($result, $item) {
        if ($item['id'] === 'default') {
          return $result;
        }

        $result[$item['id']] = $item['label'];
        return $result;
      },
      [],
    );
  }

  /**
   * Gets field columns.
   *
   * @param \Drupal\Core\Field\FieldDefinitionInterface $fieldDefinition
   *   Field definition.
   *
   * @return array
   *   Columns.
   */
  protected function getColumnFields(FieldDefinitionInterface $fieldDefinition): array {
    if (empty($fieldDefinition->getColumns())) {
      return [];
    }

    $columns = array_keys($fieldDefinition->getColumns());
    if (is_subclass_of($this->fieldTypePluginManager->getPluginClass($fieldDefinition->getType()), TextItemBase::class)) {
      $columns[] = 'processed';
    }

    return $columns;
  }

  /**
   * Entity builder method.
   *
   * @param string $entityType
   *   The type of the entity.
   * @param \Drupal\Core\Config\Entity\ConfigEntityBundleBase $fieldConfig
   *   The field config.
   * @param array $form
   *   A nested array form elements comprising the form.
   * @param \Drupal\Core\Form\FormStateInterface $formState
   *   The current state of the form.
   */
  public function entityFormEntityBuild(string $entityType, ConfigEntityBundleBase $fieldConfig, array $form, FormStateInterface $formState): void {
    $enabled = $formState->getValue(['rdf_sync', 'enabled']);

    // Remove.
    $fieldConfig->unsetThirdPartySetting('rdf_sync', 'type');
    $fieldConfig->unsetThirdPartySetting('rdf_sync', 'uri_field_name');
    $fieldConfig->unsetThirdPartySetting('rdf_sync', 'uri_plugin');
    $fieldConfig->unsetThirdPartySetting('rdf_sync', 'fields');
    $fieldConfig->unsetThirdPartySetting('rdf_sync', 'namespaces');
    // Disabled so nothing to set.
    if (!$enabled) {
      return;
    }

    $mappings = ['type', 'uri_field_name'];
    foreach ($mappings as $mapping) {
      $mappingValue = $formState->getValue(['rdf_sync', $mapping]);
      if ($mappingValue) {
        $fieldConfig->setThirdPartySetting('rdf_sync', $mapping, $mappingValue);
      }
    }

    $uri_plugin = $formState->getValue(['rdf_sync', 'uri_plugin']) ?: NULL;
    $fieldConfig->setThirdPartySetting('rdf_sync', 'uri_plugin', $uri_plugin);

    $fields = [];
    $baseFields = $this->entityFieldManager->getBaseFieldDefinitions($fieldConfig->getEntityType()
      ->getBundleOf());

    foreach ($baseFields as $baseField) {
      foreach ($this->getColumnFields($baseField) as $column) {
        $data = $formState->getValue([
          'rdf_sync',
          'base_fields_mapping',
          $baseField->getName(),
          $column,
        ]);

        if (!empty($data['predicate'])) {
          $data['type'] = $data['type'] ?: NULL;
          $fields[$baseField->getName()][$column] = $data;
        }
      }
    }

    $fieldConfig->setThirdPartySetting('rdf_sync', 'fields', $fields);

    $namespaces = $this->unpackNamespaces($formState->getValue(['rdf_sync', 'namespaces']));
    if ($namespaces) {
      $fieldConfig->setThirdPartySetting('rdf_sync', 'namespaces', $namespaces);
    }
  }

  /**
   * Packs the namespaces array as a blob.
   *
   * @param array<string, string> $namespaces
   *   Associative array of namespace URIs, keyed by namespace prefix.
   *
   * @return string
   *   Namespaces packed as blob.
   */
  protected function packNamespaces(array $namespaces): string {
    return implode("\n", array_map(
      function ($prefix) use ($namespaces): string {
        return "$prefix|$namespaces[$prefix]";
      },
      array_keys($namespaces)
    ));
  }

  /**
   * Unpacks the namespaces blob as array.
   *
   * @param string $namespaces
   *   Namespaces packed as blob.
   *
   * @return array<string, string>
   *   Associative array of namespace URIs, keyed by namespace prefix.
   */
  protected function unpackNamespaces(string $namespaces): array {
    // Replace Windows or legacy Apple line endings.
    $namespaces = str_replace("\r", "\n", $namespaces);
    // Explode and remove white spaces.
    $namespaces = array_map('trim', explode("\n", $namespaces));
    // Remove empty lines.
    $namespaces = array_filter($namespaces);

    $ns = [];
    foreach ($namespaces as $namespace) {
      if (!str_contains($namespace, '|')) {
        // Ignore malformed.
        continue;
      }
      [$prefix, $uri] = explode('|', $namespace, 2);
      $ns[$prefix] = $uri;
    }

    return $ns;
  }

}

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

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