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

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

declare(strict_types=1);

namespace Drupal\devel_wizard\Plugin\DevelWizard\Spell;

use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ProfileExtensionList;
use Drupal\Core\Extension\ThemeExtensionList;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Template\TwigEnvironment;
use Drupal\devel_wizard\Attribute\DevelWizardSpell;
use Drupal\devel_wizard\Utils;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\String\UnicodeString;

#[DevelWizardSpell(
  id: 'devel_wizard_theme_claro',
  category: new TranslatableMarkup('Code'),
  label: new TranslatableMarkup('Theme based on Claro'),
  description: new TranslatableMarkup('Generates a new Theme based on Claro.'),
  tags: [
    'code' => new TranslatableMarkup('Code'),
    'theme' => new TranslatableMarkup('Theme'),
  ],
)]
class ThemeClaroSpell extends SpellBase implements
  PluginFormInterface,
  ConfigurableInterface,
  ContainerFactoryPluginInterface {

  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('extension.list.module'),
      $container->get('extension.list.theme'),
      $container->get('extension.list.profile'),
      $container->get('twig'),
      new Filesystem(),
    );
  }

  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    MessengerInterface $messenger,
    LoggerInterface $logger,
    TranslationInterface $stringTranslation,
    Utils $utils,
    ConfigFactoryInterface $configFactory,
    protected ModuleExtensionList $moduleList,
    protected ThemeExtensionList $themeList,
    protected ProfileExtensionList $profileList,
    protected TwigEnvironment $twig,
    protected Filesystem $fs,
  ) {
    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $messenger,
      $logger,
      $stringTranslation,
      $utils,
      $configFactory,
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    // @todo Is standalone?
    return [
      'machineNameLowerUnderscore' => '',
    ];
  }

  protected function populateCalculatedConfigurationValues(): static {
    parent::populateCalculatedConfigurationValues();
    if (empty($this->configuration['machineNameLowerUnderscore'])) {
      throw new \InvalidArgumentException(sprintf(
        '%s can not be empty',
        'machineNameLowerUnderscore',
      ));
    }
    $machineName = $this->configuration['machineNameLowerUnderscore'];
    $this->configuration['baseDir'] = "themes/custom/$machineName";
    $this->configuration['machineNameLowerDash'] = str_replace('_', '-', $machineName);
    $this->configuration['machineNameLowerCamel'] = (new UnicodeString($machineName))
      ->camel()
      ->toString();
    $this->configuration['machineNameUpperCamel'] = (new UnicodeString("a_{$machineName}"))
      ->camel()
      ->trimPrefix('a')
      ->toString();

    return $this;
  }

  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $conf = $this->getConfiguration();

    $form['machineNameLowerUnderscore'] = [
      '#type' => 'machine_name',
      '#default_value' => $conf['machineNameLowerUnderscore'],
      '#maxlength' => 64,
      '#description' => $this->t('A unique name for the new theme. It must only contain lowercase letters, numbers, and underscores.'),
      '#machine_name' => [
        'exists' => [$this, 'exists'],
        'source' => [],
        'standalone' => TRUE,
      ],
      '#autocomplete_route_name' => 'devel_wizard.autocomplete.extension_all',
    ];

    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);
  }

  public function exists(string $machine_name): bool {
    return array_key_exists($machine_name, $this->moduleList->getList())
      || array_key_exists($machine_name, $this->themeList->getList())
      || array_key_exists($machine_name, $this->profileList->getList());
  }

  /**
   * @throws \Twig\Error\Error
   */
  protected function doIt(): static {
    $this->doItCode();

    drupal_flush_all_caches();

    $this->batchContext['finished'] = 1.0;

    return $this;
  }

  /**
   * @throws \Twig\Error\Error
   */
  protected function doItCode(): static {
    foreach ($this->getYamlFiles() as $filePath => $fileContent) {
      $this->fs->mkdir(Path::getDirectory($filePath));
      $this->fs->dumpFile($filePath, Yaml::encode($fileContent));
      $this->messageFilesystemEntryCreate($filePath);
    }

    foreach ($this->getTwigFiles() as $dstFilePath => $template) {
      $dstFileContent = $this->twig->render(
        $template,
        $this->configuration,
      );
      $this->fs->mkdir(Path::getDirectory($dstFilePath));
      $this->fs->dumpFile($dstFilePath, $dstFileContent);
      $this->messageFilesystemEntryCreate($dstFilePath);
    }

    foreach ($this->getFilesToCopy() as $src => $dst) {
      $this->fs->copy($src, $dst);
    }

    return $this;
  }

  protected function getYamlFiles(): array {
    return $this->getYamlFilesInfo()
      + $this->getYamlFilesConfig()
      + $this->getYamlFilesOther();
  }

  protected function getYamlFilesInfo(): array {
    $machineName = $this->configuration['machineNameLowerUnderscore'];
    $versionParts = explode('.', \Drupal::VERSION);
    $baseDir = $this->configuration['baseDir'];

    return [
      "$baseDir/$machineName.info.yml" => [
        'type' => 'theme',
        'core_version_requirement' => sprintf(
          '^%d.%d',
          $versionParts[0],
          $versionParts[1],
        ),
        'name' => $this->configuration['machineNameLowerUnderscore'],
        'description' => 'Useless description.',
        'base theme' => 'claro',
        'screenshot' => 'screenshot.png',
        'regions' => [
          'header' => 'Header',
          'pre_content' => 'Pre-content',
          'breadcrumb' => 'Breadcrumb',
          'highlighted' => 'Highlighted',
          'help' => 'Help',
          'content' => 'Content',
          'sidebar_first' => 'First sidebar',
          'footer_top' => 'Footer Top',
          'footer_bottom' => 'Footer Bottom',
          'page_top' => 'Page top',
          'page_bottom' => 'Page bottom',
        ],
        'regions_hidden' => [
          'sidebar_first',
        ],
        'libraries' => [
          "$machineName/global-styling",
        ],
        'libraries-extend' => [
          'module_filter/modules.tabs' => [
            "$machineName/module_filter.tabs",
          ],
          'toolbar/toolbar' => [
            "$machineName/toolbar.toolbar",
          ],
          'views_ui/admin.styling' => [
            "$machineName/views_ui.admin.styling",
          ],
          'type_tray/type_tray' => [
            "$machineName/type_tray.type_tray",
          ],
        ],
      ],
    ];
  }

  protected function getYamlFilesConfig(): array {
    $machineName = $this->configuration['machineNameLowerUnderscore'];
    $baseDir = $this->configuration['baseDir'];

    return [
      "$baseDir/config/schema/$machineName.settings.yml" => [
        "$machineName.settings" => [
          'type' => 'theme_settings',
          'label' => "{$this->configuration['machineNameLowerUnderscore']} - Backend theme settings",
        ],
      ],
      "$baseDir/config/install/$machineName.settings.yml" => [
        'features' => [
          'comment_user_picture' => TRUE,
          'comment_user_verification' => TRUE,
          'favicon' => TRUE,
          'node_user_picture' => TRUE,
        ],
        'favicon' => [
          'mimetype' => 'image/svg+xml',
          'path' => "themes/custom/$machineName/favicon.svg",
          'url' => "/themes/custom/$machineName/favicon.svg",
          'use_default' => FALSE,
        ],
        'logo' => [
          'path' => '',
          'url' => '',
          'use_default' => TRUE,
        ],
      ],
    ];
  }

  protected function getYamlFilesOther(): array {
    $machineName = $this->configuration['machineNameLowerUnderscore'];
    $baseDir = $this->configuration['baseDir'];

    return [
      "$baseDir/$machineName.libraries.yml" => [
        'global-styling' => [
          'css' => [
            'component' => [
              "library/$machineName.global-styling/fieldset.css" => [],
            ],
          ],
        ],
        'table-sort' => [
          'js' => [
            "library/$machineName.table-sort/lib.js" => [],
            "library/$machineName.table-sort/db.js" => [],
          ],
          'css' => [
            'base' => [
              "library/$machineName.table-sort/base.css" => [],
            ],
          ],
          'dependencies' => [
            'core/jquery.once',
          ],
        ],
        'module_filter.tabs' => [
          'js' => [
            'library/module_filter.tabs/index.js' => [],
          ],
          'css' => [
            'theme' => [
              'library/module_filter.tabs/theme.css' => [],
            ],
          ],
        ],
        'toolbar.toolbar' => [
          'css' => [
            'theme' => [
              '/modules/contrib/devel_wizard/css/toolbar.icon.theme.css' => [],
            ],
          ],
        ],
        'type_tray.type_tray' => [
          'css' => [
            'theme' => [
              'library/type_tray.type_tray/theme.css' => [],
            ],
          ],
        ],
        'views_ui.admin.styling' => [
          'css' => [
            'theme' => [
              'library/views_ui.admin.styling/theme.css' => [],
            ],
          ],
        ],
      ],
      "$baseDir/$machineName.breakpoints.yml" => [
        "$machineName.sm" => [
          'label' => 'Small',
          'mediaQuery' => 'all and (min-width: 500px)',
          'weight' => 0,
          'multipliers' => ['1x'],
        ],
        "$machineName.md" => [
          'label' => 'Medium',
          'mediaQuery' => 'all and (min-width: 700px)',
          'weight' => 1,
          'multipliers' => ['1x'],
        ],
        "$machineName.lg" => [
          'label' => 'Large',
          'mediaQuery' => 'all and (min-width: 1000px)',
          'weight' => 2,
          'multipliers' => ['1x'],
        ],
        "$machineName.xl" => [
          'label' => 'X-Large',
          'mediaQuery' => 'all and (min-width: 1300px)',
          'weight' => 3,
          'multipliers' => ['1x'],
        ],
        "$machineName.nav-md" => [
          'label' => 'Nav Medium',
          'mediaQuery' => 'all and (min-width: 500px)',
          'weight' => 4,
          'multipliers' => ['1x'],
        ],
        "$machineName.nav" => [
          'label' => 'Nav',
          'mediaQuery' => 'all and (min-width: 1200px)',
          'weight' => 5,
          'multipliers' => ['1x'],
        ],
        "$machineName.grid-md" => [
          'label' => 'Grid Medium',
          'mediaQuery' => 'all and (min-width: 700px)',
          'weight' => 6,
          'multipliers' => ['1x'],
        ],
        "$machineName.grid-max" => [
          'label' => 'Grid Max',
          'mediaQuery' => 'all and (min-width: 1440px)',
          'weight' => 7,
          'multipliers' => ['1x'],
        ],
      ],
    ];
  }

  protected function getTwigFiles(): array {
    $machineName = $this->configuration['machineNameLowerUnderscore'];
    $baseDir = $this->configuration['baseDir'];

    return [
      "$baseDir/library/$machineName.global-styling/fieldset.scss" => '@devel_wizard/spell/theme_claro/library/global-styling/fieldset.css.twig',
      "$baseDir/library/module_filter.tabs/index.js" => '@devel_wizard/spell/theme_claro/library/module_filter.tabs/index.js.twig',
      "$baseDir/library/module_filter.tabs/theme.scss" => '@devel_wizard/spell/theme_claro/library/module_filter.tabs/theme.css.twig',
      "$baseDir/library/table-sort/base.scss" => '@devel_wizard/spell/theme_claro/library/table-sort/base.css.twig',
      "$baseDir/library/table-sort/db.js" => '@devel_wizard/spell/theme_claro/library/table-sort/db.js.twig',
      "$baseDir/library/table-sort/lib.js" => '@devel_wizard/spell/theme_claro/library/table-sort/lib.js.twig',
      "$baseDir/library/type_tray.type_tray/theme.scss" => '@devel_wizard/spell/theme_claro/library/type_tray.type_tray/theme.css.twig',
      "$baseDir/library/views_ui.admin.styling/theme.scss" => '@devel_wizard/spell/theme_claro/library/views_ui.admin.styling/theme.css.twig',
    ];
  }

  protected function getFilesToCopy(): array {
    $baseDir = $this->configuration['baseDir'];

    return [
      'core/themes/claro/screenshot.png' => "$baseDir/screenshot.png",
      'core/themes/claro/logo.svg' => "$baseDir/logo.svg",
      "$baseDir/logo.svg" => "$baseDir/favicon.svg",
    ];
  }

}

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

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