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

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

declare(strict_types=1);

namespace Drupal\devel_wizard\Plugin\DevelWizard\Spell;

use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
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;

/**
 * @todo Enable and configure Symfony plugin.
 * @todo Enable and configure PHPCS.
 * @todo Configure directory <---> PHP namespace mapping.
 * @todo Configure Task server.
 * @todo Configure Git repository.
 * @todo Configure GitLink plugin.
 *
 * @see \Drupal\devel_wizard\Plugin\DevelWizard\Spell\ProjectDrupalDrushSpell::doItPhpstorm
 */
#[DevelWizardSpell(
  id: 'devel_wizard_phpstorm_idea',
  category: new TranslatableMarkup('Code'),
  label: new TranslatableMarkup('PHPStorm .idea'),
  description: new TranslatableMarkup('Generates a basic PHPStorm project.'),
  tags: [
    'code' => new TranslatableMarkup('Code'),
    'ide' => new TranslatableMarkup('IDE'),
    'phpstorm' => new TranslatableMarkup('PHPStorm'),
  ],
)]
class PhpstormIdeaSpell extends SpellBase implements
  PluginFormInterface,
  ContainerFactoryPluginInterface,
  ConfigurableInterface {

  protected Filesystem $fs;

  protected TwigEnvironment $twig;

  /**
   * {@inheritdoc}
   */
  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('twig'),
      new Filesystem(),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    MessengerInterface $messenger,
    LoggerInterface $logger,
    TranslationInterface $stringTranslation,
    Utils $utils,
    ConfigFactoryInterface $configFactory,
    TwigEnvironment $twig,
    Filesystem $fs,
  ) {
    $this->fs = $fs;
    $this->twig = $twig;
    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $messenger,
      $logger,
      $stringTranslation,
      $utils,
      $configFactory,
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'project_root' => '',
      'project_name' => [],
      'version_major' => 0,
    ];
  }

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

    $composerFilePath = "{$this->configuration['project_root']}/composer.json";
    if (!$this->fs->exists($composerFilePath)) {
      throw new \InvalidArgumentException("$composerFilePath not exists");
    }

    $composer = json_decode(file_get_contents($composerFilePath) ?: '{}', TRUE);
    $parts = explode('/', $composer['name'] ?? '/');
    if (empty($parts[0]) || empty($parts[1])) {
      throw new \InvalidArgumentException("$composerFilePath is invalid");
    }

    $this->configuration['project_name'] = [
      'vendor' => $parts[0],
      'project' => $parts[1],
    ];

    $dir = pathinfo($this->configuration['project_root'], \PATHINFO_BASENAME);
    $parts = explode('-', $dir);
    $branch = end($parts);
    if (!$branch) {
      $branch = '1.x';
    }

    $matches = [];
    preg_match('/^(?P<major>\d+)\./', $branch, $matches);
    $this->configuration['version_major'] = $matches['major'] ?? '1';

    $this->configuration['project_name_full'] = sprintf(
      '%s.%s-%d',
      $this->configuration['project_name']['vendor'],
      $this->configuration['project_name']['project'],
      $this->configuration['version_major'],
    );

    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form['project_root'] = [
      '#type' => 'textfield',
      '#required' => TRUE,
      '#title' => $this->t('Project root'),
      '#description' => $this->t('The directory where the <code>composer.json</code> is.'),
      '#default_value' => $this->configuration['project_root'] ?? '',
    ];

    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 \Twig\Error\SyntaxError
   * @throws \Twig\Error\RuntimeError
   * @throws \Twig\Error\LoaderError
   */
  protected function doIt(): static {
    $this
      ->doItName()
      ->doItIml()
      ->doItModules();

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

    return $this;
  }

  protected function doItName(): static {
    $fileName = Path::join($this->configuration['project_root'], '.idea', '.name');
    $this->fs->mkdir(Path::getDirectory($fileName));
    $this->fs->dumpFile($fileName, $this->configuration['project_name_full']);
    $this->messageFilesystemEntryCreate($fileName);

    return $this;
  }

  /**
   * @throws \Twig\Error\RuntimeError
   * @throws \Twig\Error\SyntaxError
   * @throws \Twig\Error\LoaderError
   */
  protected function doItIml(): static {
    // - Find *.iml
    $fileNames = glob("{$this->configuration['project_root']}/.idea/*.iml");
    $fileName = $fileNames ? reset($fileNames) : NULL;
    if (!$fileName) {
      $fileName = Path::join(
        $this->configuration['project_root'],
        '.idea',
        "{$this->configuration['project_name_full']}.iml",
      );

      $this->fs->mkdir(Path::getDirectory($fileName));
      $this->fs->dumpFile(
        $fileName,
        $this->twig->render('@devel_wizard/phpstorm_idea/iml.xml.twig', $this->configuration),
      );
      $this->messageFilesystemEntryCreate($fileName);

      return $this;
    }

    $dir = Path::getDirectory($fileName);
    $fileName = pathinfo($fileName, \PATHINFO_BASENAME);
    $fileNameExpected = "{$this->configuration['project_name_full']}.iml";
    if ($fileName !== $fileNameExpected) {
      $this->fs->rename(
        "$dir/$fileName",
        "$dir/$fileNameExpected",
      );
      // @todo Message.
    }

    return $this;
  }

  /**
   * @throws \Twig\Error\RuntimeError
   * @throws \Twig\Error\SyntaxError
   * @throws \Twig\Error\LoaderError
   */
  protected function doItModules(): static {
    $filePath = Path::join($this->configuration['project_root'], '.idea', 'modules.xml');
    if ($this->fs->exists($filePath)) {
      // @todo Update.
      return $this;
    }

    $this->configuration['idea_modules'] = [
      'root' => [
        'fileurl' => "file://\$PROJECT_DIR\$/.idea/{$this->configuration['project_name_full']}.iml",
        'filepath' => "\$PROJECT_DIR\$/.idea/{$this->configuration['project_name_full']}.iml",
      ],
    ];

    $filePath = Path::join(
      $this->configuration['project_root'],
      '.idea',
      'modules.xml',
    );
    $this->fs->mkdir(Path::getDirectory($filePath));
    $this->fs->dumpFile(
      $filePath,
      $this->twig->render('@devel_wizard/phpstorm_idea/modules.xml.twig', $this->configuration),
    );
    $this->messageFilesystemEntryCreate($filePath);

    return $this;
  }

}

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

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