devel_wizard-2.x-dev/src/Plugin/DevelWizard/Spell/EventSubscriberSpell.php
src/Plugin/DevelWizard/Spell/EventSubscriberSpell.php
<?php
declare(strict_types=1);
namespace Drupal\devel_wizard\Plugin\DevelWizard\Spell;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleExtensionList;
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;
#[DevelWizardSpell(
id: 'devel_wizard_event_subscriber',
category: new TranslatableMarkup('Code'),
label: new TranslatableMarkup('Event subscriber'),
description: new TranslatableMarkup('Generates an event subscriber.'),
tags: [
'code' => new TranslatableMarkup('Code'),
'event_subscriber' => new TranslatableMarkup('Event subscriber'),
],
)]
class EventSubscriberSpell extends SpellBase implements
PluginFormInterface,
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('twig'),
new Filesystem(),
);
}
/**
* {@inheritdoc}
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
MessengerInterface $messenger,
LoggerInterface $logger,
TranslationInterface $stringTranslation,
Utils $utils,
ConfigFactoryInterface $configFactory,
protected ModuleExtensionList $moduleList,
protected TwigEnvironment $twig,
protected Filesystem $fs,
) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$messenger,
$logger,
$stringTranslation,
$utils,
$configFactory,
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration(): array {
return [
'module' => [
'machineName' => '',
],
'eventSubscriber' => [
'id' => '',
],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$conf = $this->getConfiguration();
$form['module'] = [
'#type' => 'details',
'#tree' => TRUE,
'#title' => $this->t('Module'),
'#open' => TRUE,
'machineName' => [
'#type' => 'textfield',
'#required' => TRUE,
'#title' => $this->t('Machine-name'),
'#default_value' => $conf['module']['machineName'],
'#autocomplete_route_name' => 'devel_wizard.autocomplete.module',
],
];
$form['eventSubscriber'] = [
'#type' => 'details',
'#tree' => TRUE,
'#title' => $this->t('Event subscriber'),
'#open' => TRUE,
'id' => [
'#type' => 'textfield',
'#required' => TRUE,
'#title' => $this->t('ID'),
'#default_value' => $conf['eventSubscriber']['id'],
],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
// @todo Module exists.
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$configuration = $form_state->getValue($form['#parents'], []);
$this->setConfiguration($configuration);
}
protected function populateCalculatedConfigurationValues(): static {
parent::populateCalculatedConfigurationValues();
if (empty($this->configuration['module']['machineName'])) {
throw new \InvalidArgumentException('module.machineName is required');
}
if (empty($this->configuration['eventSubscriber']['id'])) {
throw new \InvalidArgumentException('event_subscriber.id is required');
}
$this->configuration['module'] += $this->utils->stringVariants(
$this->configuration['module']['machineName'],
'machineName',
);
$this->configuration['module']['dir'] = $this
->moduleList
->getPath($this->configuration['module']['machineName']);
$this->configuration['eventSubscriber'] += $this->utils->stringVariants(
$this->configuration['eventSubscriber']['id'],
'id',
);
$this->configuration['eventSubscriber'] += [
'classNamespace' => sprintf(
'Drupal\\%s\\EventSubscriber',
$this->configuration['module']['machineName'],
),
'className' => $this->configuration['eventSubscriber']['idUpperCamel'] . 'EventSubscriber',
];
$this->configuration['eventSubscriber'] += [
'classFqn' => sprintf(
'%s\\%s',
$this->configuration['eventSubscriber']['classNamespace'],
$this->configuration['eventSubscriber']['className'],
),
];
$this->configuration['eventSubscriber'] += [
'filePath' => Path::join(
$this->configuration['module']['dir'],
$this->utils->classFqnToFilePath($this->configuration['eventSubscriber']['classFqn']),
),
];
return $this;
}
/**
* @throws \Twig\Error\SyntaxError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\LoaderError
*/
protected function doIt(): static {
$this
->doItClass()
->doItService();
$this->batchContext['sandbox']['finished'] = 1.0;
return $this;
}
/**
* @throws \Twig\Error\SyntaxError
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
*/
protected function doItClass(): static {
$conf = $this->getConfiguration();
$fileContent = $this->twig->render(
'@devel_wizard/spell/event_subscriber/class.php.twig',
$conf,
);
$this->fs->dumpFile($conf['eventSubscriber']['filePath'], $fileContent);
$this->messageFilesystemEntryCreate($conf['eventSubscriber']['filePath']);
return $this;
}
protected function doItService(): static {
$filePath = Path::join(
$this->configuration['module']['dir'],
"{$this->configuration['module']['machineName']}.services.yml",
);
$serviceName = "{$this->configuration['module']['machineName']}.{$this->configuration['eventSubscriber']['id']}";
$entries = [
$serviceName => [
'class' => $this->configuration['eventSubscriber']['classFqn'],
'arguments' => [
'@entity_type.manager',
],
'tags' => [
[
'name' => 'event_subscriber',
],
],
],
];
$this->utils->ymlFileReplace($filePath, $entries, ['services']);
$this->messageFilesystemEntryUpdate($filePath);
return $this;
}
}
