diff --git a/inmail.install b/inmail.install index 0d15490..fd62246 100644 --- a/inmail.install +++ b/inmail.install @@ -3,6 +3,46 @@ * @file * Implementations of install hooks for the Inmail module. */ +use Drupal\inmail\PluginRequirementsInterface; + +/** + * Implements hook_requirements(). + */ +function inmail_requirements($phase) { + $requirements = []; + if ($phase == 'runtime') { + $requirements += inmail_get_plugin_requirements(); + } + + return $requirements; +} + +/** + * Returns plugin requirements for enabled instances. + * + * @return array + * An array of plugin requirements. + */ +function inmail_get_plugin_requirements() { + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = \Drupal::entityTypeManager(); + $plugin_types = ['analyzer', 'deliverer', 'handler']; + $plugins = []; + + foreach ($plugin_types as $plugin_type) { + $enabled_instances = $entity_type_manager->getStorage("inmail_$plugin_type")->loadByProperties(['status' => TRUE]); + /** @var \Drupal\inmail\Entity\PluginConfigEntity $enabled_instance */ + foreach ($enabled_instances as $enabled_instance) { + $key = $plugin_type . '_' . $enabled_instance->id(); + $plugins[$key] = $enabled_instance->checkRequirements(); + } + } + + // Filter plugins with no requirements. + $plugins = array_filter($plugins); + + return $plugins; +} /** * Implements hook_install(). diff --git a/src/Entity/PluginConfigEntity.php b/src/Entity/PluginConfigEntity.php index 366ae77..4f4ba18 100644 --- a/src/Entity/PluginConfigEntity.php +++ b/src/Entity/PluginConfigEntity.php @@ -3,11 +3,12 @@ namespace Drupal\inmail\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\inmail\PluginRequirementsInterface; /** * Defines a config entity skeleton for plugin configuration. */ -abstract class PluginConfigEntity extends ConfigEntityBase { +abstract class PluginConfigEntity extends ConfigEntityBase implements PluginRequirementsInterface { /** * The machine name of the plugin configuration. @@ -71,4 +72,25 @@ abstract class PluginConfigEntity extends ConfigEntityBase { $this->configuration = $configuration; return $this; } + + /** + * {@inheritdoc} + */ + public function checkRequirements() { + $requirements = []; + // @todo: Move to the entity level. + $entity_type_parameters = explode('_', $this->getEntityTypeId()); + $plugin_type = end($entity_type_parameters); + + /** @var \Drupal\Core\Plugin\DefaultPluginManager $plugin_manager */ + $plugin_manager = \Drupal::service("plugin.manager.inmail.$plugin_type"); + // Create plugin instance. + // @todo: Implement getPlugin() method. + if ($plugin = $plugin_manager->createInstance($this->getPluginId(), $this->getConfiguration())) { + return $plugin->checkRequirements(); + } + + return $requirements; + } + } diff --git a/src/MessageProcessor.php b/src/MessageProcessor.php index d41d1de..2333b94 100644 --- a/src/MessageProcessor.php +++ b/src/MessageProcessor.php @@ -115,7 +115,7 @@ class MessageProcessor implements MessageProcessorInterface { uasort($analyzer_configs, array($this->analyzerStorage->getEntityType()->getClass(), 'sort')); foreach ($analyzer_configs as $analyzer_config) { /** @var \Drupal\inmail\Entity\AnalyzerConfig $analyzer_config */ - if ($analyzer_config->status()) { + if ($analyzer_config->status() && empty($analyzer_config->checkRequirements())) { /** @var \Drupal\inmail\Plugin\inmail\Analyzer\AnalyzerInterface $analyzer */ $analyzer = $this->analyzerManager->createInstance($analyzer_config->getPluginId(), $analyzer_config->getConfiguration()); $analyzer->analyze($message, $result); @@ -136,7 +136,7 @@ class MessageProcessor implements MessageProcessorInterface { // Handle message. foreach ($this->handlerStorage->loadMultiple() as $handler_config) { /** @var \Drupal\inmail\Entity\HandlerConfig $handler_config */ - if ($handler_config->status()) { + if ($handler_config->status() && empty($handler_config->checkRequirements())) { /** @var \Drupal\inmail\Plugin\inmail\handler\HandlerInterface $handler */ $handler = $this->handlerManager->createInstance($handler_config->getPluginId(), $handler_config->getConfiguration()); $handler->invoke($message, $result); diff --git a/src/Plugin/inmail/Analyzer/AnalyzerBase.php b/src/Plugin/inmail/Analyzer/AnalyzerBase.php index 5b71343..d18a68d 100644 --- a/src/Plugin/inmail/Analyzer/AnalyzerBase.php +++ b/src/Plugin/inmail/Analyzer/AnalyzerBase.php @@ -69,4 +69,12 @@ abstract class AnalyzerBase extends PluginBase implements AnalyzerInterface { public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { } + /** + * {@inheritdoc} + */ + public function checkRequirements() { + // By default, plugins have no requirements. + return []; + } + } diff --git a/src/Plugin/inmail/Analyzer/AnalyzerInterface.php b/src/Plugin/inmail/Analyzer/AnalyzerInterface.php index 2d2af2f..7891bd8 100644 --- a/src/Plugin/inmail/Analyzer/AnalyzerInterface.php +++ b/src/Plugin/inmail/Analyzer/AnalyzerInterface.php @@ -6,6 +6,7 @@ use Drupal\Component\Plugin\ConfigurablePluginInterface; use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Plugin\PluginFormInterface; use Drupal\inmail\MIME\MessageInterface; +use Drupal\inmail\PluginRequirementsInterface; use Drupal\inmail\ProcessorResultInterface; /** @@ -13,7 +14,7 @@ use Drupal\inmail\ProcessorResultInterface; * * @ingroup analyzer */ -interface AnalyzerInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface { +interface AnalyzerInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface, PluginRequirementsInterface { /** * Analyze the given message. diff --git a/src/Plugin/inmail/Deliverer/DelivererBase.php b/src/Plugin/inmail/Deliverer/DelivererBase.php index 599edec..8c9adea 100644 --- a/src/Plugin/inmail/Deliverer/DelivererBase.php +++ b/src/Plugin/inmail/Deliverer/DelivererBase.php @@ -22,4 +22,12 @@ abstract class DelivererBase extends PluginBase implements DelivererInterface { return $this->pluginDefinition['label']; } + /** + * {@inheritdoc} + */ + public function checkRequirements() { + // By default, plugins have no requirements. + return []; + } + } diff --git a/src/Plugin/inmail/Deliverer/DelivererInterface.php b/src/Plugin/inmail/Deliverer/DelivererInterface.php index 81a35ea..9df55d4 100644 --- a/src/Plugin/inmail/Deliverer/DelivererInterface.php +++ b/src/Plugin/inmail/Deliverer/DelivererInterface.php @@ -3,6 +3,7 @@ namespace Drupal\inmail\Plugin\inmail\Deliverer; use Drupal\Component\Plugin\PluginInspectionInterface; +use Drupal\inmail\PluginRequirementsInterface; /** * Defines methods for deliverers. @@ -11,7 +12,7 @@ use Drupal\Component\Plugin\PluginInspectionInterface; * * @ingroup deliverer */ -interface DelivererInterface extends PluginInspectionInterface { +interface DelivererInterface extends PluginInspectionInterface, PluginRequirementsInterface { /** * Returns the deliverer label. diff --git a/src/Plugin/inmail/Handler/HandlerBase.php b/src/Plugin/inmail/Handler/HandlerBase.php index 1c7cb56..e85ecc1 100644 --- a/src/Plugin/inmail/Handler/HandlerBase.php +++ b/src/Plugin/inmail/Handler/HandlerBase.php @@ -72,4 +72,12 @@ abstract class HandlerBase extends PluginBase implements HandlerInterface { public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { } + /** + * {@inheritdoc} + */ + public function checkRequirements() { + // By default, plugins have no requirements. + return []; + } + } diff --git a/src/Plugin/inmail/Handler/HandlerInterface.php b/src/Plugin/inmail/Handler/HandlerInterface.php index b89b065..240657a 100644 --- a/src/Plugin/inmail/Handler/HandlerInterface.php +++ b/src/Plugin/inmail/Handler/HandlerInterface.php @@ -6,6 +6,7 @@ use Drupal\Component\Plugin\ConfigurablePluginInterface; use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Plugin\PluginFormInterface; use Drupal\inmail\MIME\MessageInterface; +use Drupal\inmail\PluginRequirementsInterface; use Drupal\inmail\ProcessorResultInterface; /** @@ -13,7 +14,7 @@ use Drupal\inmail\ProcessorResultInterface; * * @ingroup handler */ -interface HandlerInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface { +interface HandlerInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface, PluginRequirementsInterface { /** * Returns helpful explanation for using and configuring the handler. diff --git a/src/PluginRequirementsInterface.php b/src/PluginRequirementsInterface.php new file mode 100644 index 0000000..a4b36d6 --- /dev/null +++ b/src/PluginRequirementsInterface.php @@ -0,0 +1,18 @@ +getAnalyzerResult(DefaultAnalyzerResult::TOPIC); + + // Do the fake body update. This should not be executed because of the + // plugin requirements check. + $default_result->setBody('The body has been updated by MissingRequirementAnalyzer.'); + } + + /** + * {@inheritdoc} + */ + public function checkRequirements() { + return [ + 'title' => $this->t('Missing test extension'), + 'description' => $this->t('Missing Requirement Analyzer cannot be used because of missing test extension'), + 'severity' => REQUIREMENT_ERROR, + ]; + } + +} diff --git a/tests/modules/inmail_test/src/Plugin/inmail/Analyzer/TestAnalyzer.php b/tests/modules/inmail_test/src/Plugin/inmail/Analyzer/TestAnalyzer.php index 08a0c2e..aeb12f3 100644 --- a/tests/modules/inmail_test/src/Plugin/inmail/Analyzer/TestAnalyzer.php +++ b/tests/modules/inmail_test/src/Plugin/inmail/Analyzer/TestAnalyzer.php @@ -40,6 +40,9 @@ class TestAnalyzer extends AnalyzerBase { $demo_user->save(); } $default_result->setAccount($demo_user); + + // Update the body of the default result. + $default_result->setBody($message->getBody()); } /** diff --git a/tests/src/Kernel/ProcessorTest.php b/tests/src/Kernel/ProcessorTest.php index e203425..d6a56e2 100644 --- a/tests/src/Kernel/ProcessorTest.php +++ b/tests/src/Kernel/ProcessorTest.php @@ -47,9 +47,9 @@ class ProcessorTest extends KernelTestBase { } /** - * Tests account switching mechanism. + * Tests the sample message processing. */ - public function testAccountSwitching() { + public function testMessageProcessing() { $raw = << @@ -62,6 +62,10 @@ EOF; $processor = \Drupal::service('inmail.processor'); AnalyzerConfig::create(['id' => 'test_analyzer', 'plugin' => 'test_analyzer'])->save(); + // Add an analyzer with missing requirements. + $missing_requirement_analyzer = AnalyzerConfig::create(['id' => 'missing_requirement_analyzer', 'plugin' => 'missing_requirement_analyzer']); + $missing_requirement_analyzer->save(); + HandlerConfig::create(['id' => 'result_keeper', 'plugin' => 'result_keeper'])->save(); $processor->process($raw, DelivererConfig::create(['id' => 'test'])); @@ -73,6 +77,16 @@ EOF; $this->assertEquals('Demo User', $default_result->getAccount()->getDisplayName()); // Assert the account was switched on handler's level. $this->assertEquals('Demo User', ResultKeeperHandler::getAccountName()); + + // Assert the requirements message. + $this->assertEquals([ + 'title' => t('Missing test extension'), + 'description' => t('Missing Requirement Analyzer cannot be used because of missing test extension'), + 'severity' => REQUIREMENT_ERROR, + ], $missing_requirement_analyzer->checkRequirements()); + // The body message has not changed. It implies MissingRequirementAnalyzer + // did not run. + $this->assertEquals('Hello world!', $default_result->getBody()); } }