content_lock-8.x-2.1/src/Form/ContentLockSettingsForm.php

src/Form/ContentLockSettingsForm.php
<?php

namespace Drupal\content_lock\Form;

use Drupal\content_lock\ContentLock\ContentLockInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\ConfigTarget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a form for configuring the Content Lock module.
 *
 * @package Drupal\content_lock\Form
 */
class ContentLockSettingsForm extends ConfigFormBase {

  public function __construct(
    ConfigFactoryInterface $config_factory,
    TypedConfigManagerInterface $typedConfigManager,
    protected EntityTypeManagerInterface $entityTypeManager,
    protected ModuleHandlerInterface $moduleHandler,
  ) {
    parent::__construct($config_factory, $typedConfigManager);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('config.factory'),
      $container->get('config.typed'),
      $container->get('entity_type.manager'),
      $container->get('module_handler')
    );
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array {
    return [
      'content_lock.settings',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'content_lock_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $config = $this->config('content_lock.settings');

    $form['general'] = [
      '#type' => 'details',
      '#title' => $this->t('Verbose'),
      '#open' => TRUE,
      '#tree' => TRUE,
      '#process' => [[get_class($this), 'formProcessMergeParent']],
      '#weight' => 0,
    ];
    $form['general']['verbose'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable this option to display a message to the user when they lock a content item by editing it.'),
      '#description' => $this->t('Users trying to edit a content locked still see the content lock message.'),
      '#default_value' => $config->get('verbose'),
      '#return_value' => 1,
      '#empty' => 0,
    ];

    $form['entities'] = [
      '#type' => 'details',
      '#title' => $this->t('Entity type protected'),
      '#open' => TRUE,
      '#tree' => TRUE,
      '#process' => [[get_class($this), 'formProcessMergeParent']],
      '#weight' => 1,
    ];

    $definitions = $this->entityTypeManager->getDefinitions();
    $entity_types = [];
    $selected_entity_types = [];
    foreach ($definitions as $definition) {
      if ($definition instanceof ContentEntityTypeInterface) {
        $entity_types[$definition->id()] = $definition->getLabel();
        if (!empty($config->get('types.' . $definition->id()))) {
          $selected_entity_types[] = $definition->id();
        }
      }
    }
    $form['entities']['entity_types'] = [
      '#type' => 'checkboxes',
      '#title' => 'Protected entity types',
      '#options' => $entity_types,
      '#default_value' => $selected_entity_types,
      '#attributes' => [
        'class' => ['content-lock-entity-types'],
      ],
    ];

    foreach ($definitions as $definition) {
      if ($definition instanceof ContentEntityTypeInterface) {
        $form['entities'][$definition->id()] = [
          '#type' => 'container',
          '#title' => $definition->getLabel(),
          '#theme' => 'content_lock_settings_entities',
          '#states' => [
            'visible' => [
              ':input[name="entity_types[' . $definition->id() . ']"]' => ['checked' => TRUE],
            ],
          ],
          '#attributes' => [
            'class' => [$definition->id()],
          ],
        ];

        $options = [
          '*' => $this->t('All'),
        ];

        if ($definition->getBundleEntityType()) {
          $bundles = $this->entityTypeManager
            ->getStorage($definition->getBundleEntityType())
            ->loadMultiple();

          foreach ($bundles as $bundle) {
            $options[$bundle->id()] = $bundle->label();
          }
        }
        else {
          $options[$definition->id()] = $definition->getLabel();
        }
        $form['entities'][$definition->id()]['bundles'] = [
          '#type' => 'checkboxes',
          '#title' => $definition->getBundleLabel() ?: $definition->getLabel(),
          '#description' => $this->t('Select the bundles on which enable content lock'),
          '#options' => $options,
          '#default_value' => $config->get('types.' . $definition->id()) ?: [],
          '#attributes' => ['class' => ['content-lock-entity-settings']],
        ];

        $form['entities'][$definition->id()]['settings']['translation_lock'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('Lock only on entity translation level.'),
          '#default_value' => in_array($definition->id(), $config->get('types_translation_lock') ?: []),
          '#description' => $this->t('Activating this options allows users to edit multiple translations concurrently'),
        ];
        if (!$this->moduleHandler->moduleExists('conflict')) {
          $form['entities'][$definition->id()]['settings']['translation_lock'] = [
            '#disabled' => TRUE,
            '#default_value' => FALSE,
            '#description' => $this->t('To allow editing multiple translations concurrently you need to install %module',
              [
                '%module' => Link::fromTextAndUrl('Conflict', Url::fromUri('https://www.drupal.org/project/conflict'))->toString(),
              ]
            ),
          ] + $form['entities'][$definition->id()]['settings']['translation_lock'];
        }

        if (!empty($definition->getHandlerClasses()['form'])) {
          $form['entities'][$definition->id()]['settings']['form_op_lock'] = [
            '#tree' => 1,
          ];
          $form['entities'][$definition->id()]['settings']['form_op_lock']['mode'] = [
            '#type' => 'radios',
            '#title' => $this->t('Lock only on entity form operation level.'),
            '#options' => [
              ContentLockInterface::FORM_OP_MODE_DISABLED => $this->t('Disabled'),
              ContentLockInterface::FORM_OP_MODE_ALLOWLIST => $this->t('Enable lock for selected form operations'),
              ContentLockInterface::FORM_OP_MODE_DENYLIST => $this->t('Disable lock for selected form operations'),
            ],
            '#default_value' => $config->get('form_op_lock.' . $definition->id() . '.mode') ?: ContentLockInterface::FORM_OP_MODE_DISABLED,
            '#description' => $this->t('Activating this options allows users to edit different entity forms concurrently'),
          ];

          $form_ops = array_keys($definition->getHandlerClasses()['form']);
          $form_ops = array_combine($form_ops, $form_ops);
          $form['entities'][$definition->id()]['settings']['form_op_lock']['values'] = [
            '#type' => 'checkboxes',
            '#title' => $this->t('Form operations'),
            '#options' => $form_ops,
            '#default_value' => (array) $config->get('form_op_lock.' . $definition->id() . '.values'),
            '#states' => [
              'invisible' => [
                ':input[name="' . $definition->id() . '[settings][form_op_lock][mode]"]' => ['value' => ContentLockInterface::FORM_OP_MODE_DISABLED],
              ],
            ],
          ];
        }
      }
    }

    $form['timeout'] = [
      '#type' => 'number',
      '#title' => $this->t('Lock timeout'),
      '#description' => $this->t('The maximum time in minutes that each lock may be kept. To disable breaking locks after a timeout, clear the value. It is recommended for user experience to set this value.'),
      '#min' => 1,
      '#config_target' => new ConfigTarget('content_lock.settings', 'timeout', fn($value) => empty($value) ? '' : $value / 60, fn($value) => empty($value) ? NULL : $value * 60),
    ];

    $form['#attached']['library'][] = 'content_lock/drupal.content_lock.settings';
    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    parent::submitForm($form, $form_state);

    $content_lock = $this->config('content_lock.settings');
    $definitions = $this->entityTypeManager->getDefinitions();
    foreach ($definitions as $definition) {
      if ($definition instanceof ContentEntityTypeInterface) {
        if ($form_state->getValue($definition->id())) {
          $content_lock->set('types.' . $definition->id(), $this->removeEmptyValue($form_state->getValue([$definition->id(), 'bundles'])));

          $translation_lock = (bool) $form_state->getValue([$definition->id(), 'settings', 'translation_lock']);
          $types_translation_lock = $content_lock->get('types_translation_lock') ?: [];
          if ($translation_lock && !in_array($definition->id(), $types_translation_lock)) {
            $types_translation_lock[] = $definition->id();
          }
          elseif (!$translation_lock && in_array($definition->id(), $types_translation_lock)) {
            $types_translation_lock = array_diff($types_translation_lock, [$definition->id()]);
          }
          $content_lock->set('types_translation_lock', $types_translation_lock);

          $content_lock->set('form_op_lock.' . $definition->id() . '.mode', $form_state->getValue([$definition->id(), 'settings', 'form_op_lock', 'mode']));
          $content_lock->set('form_op_lock.' . $definition->id() . '.values', $this->removeEmptyValue((array) $form_state->getValue([$definition->id(), 'settings', 'form_op_lock', 'values'])));
        }
      }
    }

    $content_lock->set('verbose', $form_state->getValue('verbose'))
      ->save();
  }

  /**
   * Helper function to filter empty value in an array.
   *
   * @param array $array
   *   The array to check for empty values.
   *
   * @return array
   *   The array without empty values.
   */
  protected function removeEmptyValue(array $array): array {
    return array_filter($array, function ($value) {
      return !empty($value);
    });
  }

  /**
   * Merge elements to the level up.
   *
   * Render API callback: Moves entity_reference specific Form API elements
   * (i.e. 'handler_settings') up a level for easier processing values.
   *
   * @param array $element
   *   The array to filter.
   *
   * @return array
   *   The array filtered.
   *
   * @see _entity_reference_field_settings_process()
   */
  public static function formProcessMergeParent(array $element): array {
    $parents = $element['#parents'];
    array_pop($parents);
    $element['#parents'] = $parents;
    return $element;
  }

}

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

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