devel_wizard-2.x-dev/src/Plugin/DevelWizard/Spell/SpellBase.php
src/Plugin/DevelWizard/Spell/SpellBase.php
<?php
declare(strict_types=1);
namespace Drupal\devel_wizard\Plugin\DevelWizard\Spell;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\devel_wizard\Spell\SpellInterface;
use Drupal\devel_wizard\Utils;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
/**
* @method \Drupal\devel_wizard\Spell\SpellDefinition getPluginDefinition()
*/
abstract class SpellBase extends PluginBase implements
SpellInterface,
LoggerAwareInterface {
use LoggerAwareTrait;
/**
* Maybe it is not a good idea to define a limit.
*
* @todo Different identifiers can have different limits.
* For example module name and config entity ID.
*/
protected int $identifierMaxLength = 64;
/**
* Maybe it is not a good idea to define a limit.
*/
protected int $identifierInputSize = 32;
/**
* @var \Drupal\devel_wizard\Spell\SpellDefinition
*/
protected $pluginDefinition;
protected array|\ArrayObject $batchContext = [];
protected Utils $utils;
protected ConfigFactoryInterface $configFactory;
/**
* {@inheritdoc}
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
MessengerInterface $messenger,
LoggerInterface $logger,
TranslationInterface $stringTranslation,
Utils $utils,
ConfigFactoryInterface $configFactory,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->setConfiguration($configuration);
$this->setMessenger($messenger);
$this->setLogger($logger);
$this->setStringTranslation($stringTranslation);
$this->utils = $utils;
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$this->configuration = array_replace_recursive(
$this->defaultConfiguration(),
$configuration,
);
}
protected function populateCalculatedConfigurationValues(): static {
return $this;
}
/**
* {@inheritdoc}
*/
public function validate(array $configuration): ConstraintViolationListInterface {
throw new \LogicException('Not implemented');
}
/**
* @throws \Throwable
*/
public function prepare(): static {
$this->populateCalculatedConfigurationValues();
return $this;
}
public function getRequiredPackagesProd(): array {
return [];
}
public function getRequiredPackagesDev(): array {
return [];
}
public function getRequiredModules(): array {
return [];
}
/**
* {@inheritdoc}
*/
public function abracadabra(array|\ArrayObject &$context): static {
$this->batchContext =& $context;
try {
$this->doIt();
$this->batchContext['finished'] = $this->calculateFinished();
}
catch (\Throwable $exception) {
$this->batchContext['sandbox']['messages'][] = [
// @todo Translatable.
'message' => $exception->getMessage(),
'type' => MessengerInterface::TYPE_ERROR,
];
$this->batchContext['finished'] = 1.0;
}
if ($this->batchContext['finished'] === 1.0) {
$this->postProcessBatchContext();
}
return $this;
}
abstract protected function doIt(): static;
protected function calculateFinished(): float {
if (!isset($this->batchContext['sandbox'])) {
$this->batchContext['sandbox'] = [];
}
$this->batchContext['sandbox'] += [
'sub_spells' => [],
'finished' => 1,
];
$progress = $this->batchContext['sandbox']['finished'];
$count = count($this->batchContext['sandbox']['sub_spells']) + 1;
foreach ($this->batchContext['sandbox']['sub_spells'] as $subSpellBatchContext) {
$progress += $subSpellBatchContext['finished'] ?? 1;
}
return (float) ($progress / $count);
}
protected function messageMissingModules(array $modules): static {
$missingModules = array_keys($modules, TRUE, TRUE);
if (!$missingModules) {
return $this;
}
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_ERROR,
'message' => $this->formatPlural(
count($missingModules),
'The following module has to be enabled: @modules',
'The following modules have to be enabled: @modules',
[
'@modules' => implode(', ', $missingModules),
],
),
];
return $this;
}
protected function messageFilesystemEntryCreate(string $fileName): static {
/* @noinspection HtmlUnknownTarget */
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_STATUS,
'message' => $this->t(
'@spell - file has been created: <a href="@file.href">@file.name</a>',
[
'@spell' => $this->getPluginDefinition()->id(),
'@file.href' => $this->utils->openFileUrl($fileName),
'@file.name' => $fileName,
],
),
];
return $this;
}
protected function messageFilesystemEntryUpdate(string $filePath): static {
/* @noinspection HtmlUnknownTarget */
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_STATUS,
'message' => $this->t(
'@spell - file has been updated: <a href="@file.href">@file.name</a>',
[
'@spell' => $this->getPluginDefinition()->id(),
'@file.href' => $this->utils->openFileUrl($filePath),
'@file.name' => $filePath,
],
),
];
return $this;
}
/**
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
protected function messageConfigEntityCreate(ConfigEntityInterface $entity): static {
$editable = $entity->getEntityType()->hasLinkTemplate('edit-form');
/* @noinspection HtmlUnknownTarget */
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_STATUS,
'message' => $this->t(
'@spell - @entity_type.label has been created: <a href="@entity_type.url.canonical">@bundle.label</a>',
[
'@spell' => $this->getPluginDefinition()->id(),
'@entity_type.label' => $entity->getEntityType()->getLabel(),
'@entity_type.url.canonical' => $editable ? $entity->toUrl()->toString() : '#',
'@bundle.label' => $entity->label(),
],
),
];
return $this;
}
/**
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
protected function messageConfigEntityExists(ConfigEntityInterface $entity): static {
$editable = $entity->getEntityType()->hasLinkTemplate('edit-form');
/* @noinspection HtmlUnknownTarget */
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_STATUS,
'message' => $this->t(
'@spell - @entity_type already exists: <a href="@href-canonical">@label</a>',
[
// @todo Uniformize the placeholder names.
'@spell' => $this->getPluginDefinition()->id(),
'@entity_type' => $entity->getEntityType()->getLabel(),
'@href-canonical' => $editable ? $entity->toUrl()->toString() : '#',
'@label' => $entity->label(),
],
),
];
return $this;
}
/**
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
protected function messageConfigEntityUpdated(ConfigEntityInterface $entity): static {
$editable = $entity->getEntityType()->hasLinkTemplate('edit-form');
/* @noinspection HtmlUnknownTarget */
$this->batchContext['sandbox']['messages'][] = [
'type' => MessengerInterface::TYPE_STATUS,
'message' => $this->t(
'@spell - @entity_type updated: <a href="@href-canonical">@label</a>',
[
// @todo Uniformize the placeholder names.
'@spell' => $this->getPluginDefinition()->id(),
'@entity_type' => $entity->getEntityType()->getLabel(),
'@href-canonical' => $editable ? $entity->toUrl()->toString() : '#',
'@label' => $entity->label(),
],
),
];
return $this;
}
protected function postProcessBatchContext(): static {
$this->batchContext['results']['messages'] = $this->batchContext['sandbox']['messages'] ?? [];
if (isset($this->batchContext['sandbox']['sub_spells'])) {
foreach ($this->batchContext['sandbox']['sub_spells'] as $subSpellContext) {
$this->batchContext['results']['messages'] = array_merge(
$this->batchContext['results']['messages'],
$subSpellContext['sandbox']['messages'] ?? [],
);
}
}
return $this;
}
}
