devel_wizard-2.x-dev/src/Plugin/DevelWizard/Spell/ConfigEntityUserRoleSpellBase.php

src/Plugin/DevelWizard/Spell/ConfigEntityUserRoleSpellBase.php
<?php

declare(strict_types=1);

namespace Drupal\devel_wizard\Plugin\DevelWizard\Spell;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ModuleInstallerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\devel_wizard\ShellProcessFactoryInterface;
use Drupal\devel_wizard\Spell\SpellTraitPackageManager;
use Drupal\devel_wizard\Spell\SpellTraitUserRoleManager;
use Drupal\devel_wizard\Utils;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

abstract class ConfigEntityUserRoleSpellBase extends ConfigEntitySpellBase {

  use SpellTraitPackageManager;
  use SpellTraitUserRoleManager;

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('messenger'),
      $container->get('logger.channel.devel_wizard_spell'),
      $container->get('string_translation'),
      $container->get('devel_wizard.utils'),
      $container->get('config.factory'),
      $container->get('entity_type.manager'),
      $container->get('devel_wizard.shell_process_factory'),
      $container->get('module_installer'),
      $container->get('extension.list.module'),
    );
  }

  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    MessengerInterface $messenger,
    LoggerInterface $logger,
    TranslationInterface $stringTranslation,
    Utils $utils,
    ConfigFactoryInterface $configFactory,
    EntityTypeManagerInterface $entityTypeManager,
    ShellProcessFactoryInterface $shellProcessFactory,
    ModuleInstallerInterface $moduleInstaller,
    ModuleExtensionList $moduleList,
  ) {
    $this->entityTypeManager = $entityTypeManager;
    $this->shellProcessFactory = $shellProcessFactory;
    $this->moduleInstaller = $moduleInstaller;
    $this->moduleList = $moduleList;

    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $messenger,
      $logger,
      $stringTranslation,
      $utils,
      $configFactory,
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'machine_name' => '',
      'user_role' => [
        'values' => [
          'status' => TRUE,
          'id' => '',
          'label' => '',
          'weight' => 10,
          'is_admin' => FALSE,
          'permissions' => [],
        ],
      ],
      'role_delegation_enabled' => TRUE,
      'role_delegation' => [
        'roles' => [],
      ],
    ];
  }

  public function populateCalculatedConfigurationValues(): static {
    parent::populateCalculatedConfigurationValues();
    if (empty($this->configuration['machine_name'])) {
      throw new \InvalidArgumentException('machine_name is required');
    }

    $machineName = $this->configuration['machine_name'];

    if (empty($this->configuration['user_role']['values']['id'])) {
      $this->configuration['user_role']['values']['id'] = "{$this->configEntityTypeId}_{$machineName}_admin";
    }

    if (empty($this->configuration['user_role']['values']['label'])) {
      $this->configuration['user_role']['values']['label'] = "{$this->configEntityTypeId} {$machineName} administrator";
    }

    if (empty($this->configuration['user_role']['values']['permissions'])) {
      $this->configuration['user_role']['values']['permissions'] = $this->getDefaultPermissions();
    }

    $this->configuration['user_role']['values']['permissions'] = array_keys(
      $this->configuration['user_role']['values']['permissions'],
      TRUE,
      TRUE,
    );

    return $this;
  }

  /**
   * @phpstan-return array<string, bool>
   */
  abstract protected function getDefaultPermissions(): array;

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $configuration = $this->getConfiguration();
    $configEntityType = $this->getConfigEntityType();

    $form['machine_name'] = [
      '#type' => 'textfield',
      '#required' => TRUE,
      '#title' => $configEntityType?->getLabel() ?: $this->t('Bundle'),
      '#description' => $this->t(
        'The machine name of the @entity_type.label to create the new role for.',
        [
          '@entity_type.label' => $configEntityType?->getLabel() ?: $this->configEntityTypeId,
        ],
      ),
      '#default_value' => $configuration['machine_name'],
      '#autocomplete_route_name' => 'devel_wizard.autocomplete.config_entity_instance',
      '#autocomplete_route_parameters' => [
        'entityTypeId' => $this->configEntityTypeId,
      ],
    ];

    $form['user_role'] = [
      '#type' => 'details',
      '#tree' => TRUE,
      '#title' => $this->t('User role'),
      '#open' => TRUE,

      'values' => [
        '#type' => 'container',
        '#tree' => TRUE,

        'id' => [
          '#type' => 'textfield',
          '#title' => $this->t('Machine-name'),
          '#description' => $this->t(
            'Default value: <code>@configEntity.id_BUNDLE_admin</code>',
            [
              '@configEntity.id' => $this->configEntityTypeId,
            ],
          ),
          '#default_value' => $configuration['user_role']['values']['id'],
          '#autocomplete_route_name' => 'devel_wizard.autocomplete.config_entity_instance',
          '#autocomplete_route_parameters' => ['entityTypeId' => $this->configEntityTypeId],
        ],
      ],
    ];

    $inputNameRoleDelegationEnabled = $this->utils->inputName($form['#parents'], 'role_delegation_enabled');
    $form['role_delegation_enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable role delegation'),
      '#return_value' => 1,
      '#default_value' => $configuration['role_delegation_enabled'],
    ];
    $form['role_delegation'] = [
      '#type' => 'details',
      '#title' => $this->t('Role delegation'),
      '#tree' => TRUE,
      '#open' => TRUE,
      '#states' => [
        'visible' => [
          ":input[name='{$inputNameRoleDelegationEnabled}']" => ['checked' => TRUE],
        ],
      ],

      'message' => [
        '#markup' => '<p>' . $this->t('No configuration options yet') . '</p>',
      ],
    ];

    return $form;
  }

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

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValue($form['#parents'], []);
    $this->setConfiguration($values);
  }

  /**
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\Entity\EntityMalformedException
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function doIt(): static {
    if (!isset($this->batchContext['sandbox']['current_step'])) {
      $this->batchContext['message'] = $this->t('Run `composer require` in order to download the required packages');
      $this->batchContext['sandbox']['current_step'] = 'composer_require';
      $this->batchContext['sandbox']['finished'] = 0.1;

      return $this;
    }

    $configuration = $this->getConfiguration();

    switch ($this->batchContext['sandbox']['current_step']) {
      case 'composer_require':
        $this->doItComposerRequire();
        drupal_flush_all_caches();

        $this->batchContext['message'] = $this->t('Install the required modules');
        $this->batchContext['sandbox']['current_step'] = 'module_install';
        $this->batchContext['sandbox']['finished'] = 0.2;
        break;

      case 'module_install':
        $this->doItModuleInstall();
        drupal_flush_all_caches();

        $this->batchContext['message'] = $this->t('Create user role');
        $this->batchContext['sandbox']['current_step'] = 'user_role_create';
        $this->batchContext['sandbox']['finished'] = 0.4;
        break;

      case 'user_role_create':
        $this->doItUserRoleCreate();
        drupal_flush_all_caches();

        if ($configuration['role_delegation_enabled']) {
          $this->batchContext['message'] = $this->t('Configure Role Delegation');
          $this->batchContext['sandbox']['current_step'] = 'role_delegation_configure';
          $this->batchContext['sandbox']['finished'] = 0.6;

          break;
        }

        $this->batchContext['sandbox']['current_step'] = '_finished';
        $this->batchContext['sandbox']['finished'] = 1.0;
        break;

      case 'role_delegation_configure':
        $this->doItRoleDelegationConfigure();
        drupal_flush_all_caches();

        $this->batchContext['sandbox']['current_step'] = '_finished';
        $this->batchContext['sandbox']['finished'] = 1.0;
        break;

      case '_finished':
        // This case never gonna happen.
        $this->batchContext['sandbox']['finished'] = 1.0;
        break;

    }

    return $this;
  }

  /**
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\Entity\EntityStorageException
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  protected function doItUserRoleCreate(): static {
    $configuration = $this->getConfiguration();
    $userRoleStorage = $this->entityTypeManager->getStorage('user_role');
    /** @var \Drupal\user\RoleInterface $userRole */
    $userRole = $userRoleStorage->load($this->configuration['user_role']['values']['id']);
    if ($userRole) {
      $this->messageConfigEntityExists($userRole);
      foreach ($configuration['user_role']['values']['permissions'] as $permission) {
        $userRole->grantPermission($permission);
      }

      $userRole->save();

      return $this;
    }

    $userRole = $userRoleStorage->create($this->configuration['user_role']['values']);
    $userRole->save();
    $this->messageConfigEntityCreate($userRole);

    return $this;
  }

  /**
   * Update permissions for the role if needed.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   * @throws \Drupal\Core\Entity\EntityStorageException
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function doItRoleDelegationConfigure(): static {
    /* @noinspection PhpUnhandledExceptionInspection */
    $userRoleStorage = $this->entityTypeManager->getStorage('user_role');
    $bundleAdminRoleId = $this->configuration['user_role']['values']['id'];
    $bundleAdminRole = $userRoleStorage->load($bundleAdminRoleId);
    $args['@user_role_id'] = $bundleAdminRoleId;
    if (!$bundleAdminRole) {
      // @todo Add messages to $this->batchContext.
      $this->messenger->addWarning($this->t(
        '@spell - role_delegation can not be configured because role @user_role_id is missing',
        $args,
      ));

      return $this;
    }

    $roleDelegatorRole = $this->ensureUserRole([
      'status' => TRUE,
      'weight' => 10,
      // @todo Make this configurable.
      'id' => 'role_delegator',
      // @todo Translatable.
      'label' => 'Role delegator',
      'is_admin' => FALSE,
      'permissions' => [],
    ]);

    $roleDelegatorRole
      ->grantPermission("assign {$bundleAdminRoleId} role")
      ->save();

    $this->messageConfigEntityUpdated($roleDelegatorRole);

    return $this;
  }

  public function getRequiredPackagesProd(): array {
    $packages = parent::getRequiredPackagesProd();

    if ($this->configuration['role_delegation_enabled']) {
      $packages['drupal/role_delegation'] = '';
    }

    return $packages;
  }

  public function getRequiredModules(): array {
    $modules = parent::getRequiredModules();
    if ($this->configuration['role_delegation_enabled']) {
      $modules['role_delegation'] = TRUE;
    }

    return $modules;
  }

}

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

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