diff --git a/.travis.yml b/.travis.yml index 61ef216c..6e6a0328 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,7 +52,10 @@ before_script: # Reference and enable rules in build site. - ln -s $TESTDIR modules/rules + - drush --yes dl webprofiler - drush --yes pm-enable simpletest rules + - drush cr + - drush --yes pm-enable webprofiler # Start a web server on port 8080, run in the background; wait for # initialization. This is temporarly disabled since there are no web tests diff --git a/config/install/rules.settings.yml b/config/install/rules.settings.yml index 64f5e97a..f3193f8b 100644 --- a/config/install/rules.settings.yml +++ b/config/install/rules.settings.yml @@ -1,4 +1,3 @@ log_errors: warning debug_log: false -debug: false log_level: info diff --git a/config/schema/rules.schema.yml b/config/schema/rules.schema.yml index 6a7b1482..5b26c4b1 100644 --- a/config/schema/rules.schema.yml +++ b/config/schema/rules.schema.yml @@ -125,14 +125,11 @@ rules.settings: label: 'Rules settings' mapping: log_errors: - type: integer + type: string label: 'Logging of Rules evaluation errors' debug_log: type: boolean label: 'Log debug information to the available loggers' - debug: - type: boolean - label: 'Show debug information' log_level: - type: integer + type: string label: 'Log level' diff --git a/rules.info.yml b/rules.info.yml index 563cb89a..467770c3 100644 --- a/rules.info.yml +++ b/rules.info.yml @@ -3,3 +3,5 @@ type: module description: 'React on events and conditionally evaluate actions.' package: Rules core: 8.x +test_dependencies: + - webprofiler \ No newline at end of file diff --git a/src/Logger/RulesLoggerChannel.php b/src/Logger/RulesLoggerChannel.php index 967a2fdb..55ac97ee 100644 --- a/src/Logger/RulesLoggerChannel.php +++ b/src/Logger/RulesLoggerChannel.php @@ -25,13 +25,6 @@ class RulesLoggerChannel extends LoggerChannel { */ protected $config; - /** - * Static storage of log entries. - * - * @var array - */ - protected $logs = []; - /** * Creates RulesLoggerChannel object. * @@ -47,12 +40,6 @@ public function __construct(ConfigFactoryInterface $config_factory) { * {@inheritdoc} */ public function log($level, $message, array $context = []) { - $this->logs[] = [ - 'level' => $level, - 'message' => $message, - 'context' => $context, - ]; - // Log message only if rules logging setting is enabled. if ($this->config->get('debug_log')) { if ($this->levelTranslation[$this->config->get('log_errors')] >= $this->levelTranslation[$level]) { @@ -61,21 +48,4 @@ public function log($level, $message, array $context = []) { } } - /** - * Returns the structured array of entries. - * - * @return array - * Array of stored log entries. - */ - public function getLogs() { - return $this->logs; - } - - /** - * Clears the static logs entries cache. - */ - public function clearLogs() { - $this->logs = []; - } - } diff --git a/src/Logger/RulesStubLogger.php b/src/Logger/RulesStubLogger.php new file mode 100644 index 00000000..943c5d3e --- /dev/null +++ b/src/Logger/RulesStubLogger.php @@ -0,0 +1,54 @@ +logs[] = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + } + + /** + * Clears static logs storage. + */ + public function cleanLogs() { + $this->logs = array(); + } + + /** + * Returns statically saved logs. + * + * @return array + * Array of logs. + */ + public function getLogs() { + return $this->logs; + } + +} diff --git a/src/RulesServiceProvider.php b/src/RulesServiceProvider.php new file mode 100644 index 00000000..038b2847 --- /dev/null +++ b/src/RulesServiceProvider.php @@ -0,0 +1,39 @@ +hasDefinition('logger.channel.rules') && $container->hasDefinition('webprofiler.drupal')) { + $container->register('webprofiler.rules', 'Drupal\rules\WebProfiler\DataCollector\RulesDataCollector') + ->addArgument(new Reference('logger.channel.rules')) + ->addTag('data_collector', array( + 'template' => '@rules/Collector/rules.html.twig', + 'id' => 'rules', + 'title' => 'Rules', + 'priority' => 200, + )); + // Replace the regular logger.channel.rules service with a traceable one. + $definition = $container->findDefinition('logger.channel.rules'); + $definition->setClass('Drupal\rules\WebProfiler\RulesChannelLoggerWrapper'); + } + } + +} diff --git a/src/Tests/ConfigEntityTest.php b/src/Tests/ConfigEntityTest.php index 64d05d21..15213df9 100644 --- a/src/Tests/ConfigEntityTest.php +++ b/src/Tests/ConfigEntityTest.php @@ -89,7 +89,6 @@ public function testConfigRule() { // Create the Rules expression object from the configuration. $expression = $loaded_entity->getExpression(); $expression->execute(); - // Test that the action logged something. $this->assertRulesLogEntryExists('action called'); } diff --git a/src/Tests/RulesDrupalTestBase.php b/src/Tests/RulesDrupalTestBase.php index 9ebb97b6..576b9135 100644 --- a/src/Tests/RulesDrupalTestBase.php +++ b/src/Tests/RulesDrupalTestBase.php @@ -7,6 +7,7 @@ namespace Drupal\rules\Tests; +use Drupal\rules\Logger\RulesStubLogger; use Drupal\simpletest\KernelTestBase; /** @@ -35,14 +36,6 @@ abstract class RulesDrupalTestBase extends KernelTestBase { */ protected $typedDataManager; - - /** - * Rules logger. - * - * @var \Drupal\rules\Logger\RulesLoggerChannel - */ - protected $logger; - /** * Modules to enable. * @@ -56,10 +49,15 @@ abstract class RulesDrupalTestBase extends KernelTestBase { public function setUp() { parent::setUp(); - $this->logger = $this->container->get('logger.channel.rules'); - // Clear the log from any stale entries that are bleeding over from previous - // tests. - $this->logger->clearLogs(); + // Prepare Rules logging for testing. + $this->installConfig(array('rules')); + $logger = new RulesStubLogger(); + $this->container->get('config.factory') + ->getEditable('rules.settings') + ->set('debug_log', 1) + ->save(); + $this->container->set('logger', $logger); + $this->container->get('logger')->cleanLogs(); $this->expressionManager = $this->container->get('plugin.manager.rules_expression'); $this->conditionManager = $this->container->get('plugin.manager.condition'); @@ -92,7 +90,7 @@ protected function createCondition($id) { */ protected function assertRulesLogEntryExists($message, $log_item_index = 0) { // Test that the action has logged something. - $logs = $this->logger->getLogs(); + $logs = $this->container->get('logger')->getLogs(); $this->assertEqual($logs[$log_item_index]['message'], $message); } diff --git a/src/Tests/RulesDrupalWebTestBase.php b/src/Tests/RulesDrupalWebTestBase.php new file mode 100644 index 00000000..5d16c084 --- /dev/null +++ b/src/Tests/RulesDrupalWebTestBase.php @@ -0,0 +1,52 @@ +user = $this->drupalCreateUser(); + // @todo uncomment it when patch with permission comes. + // $this->adminUser = $this->drupalCreateUser($permissions); + } + +} diff --git a/src/Tests/RulesEngineTest.php b/src/Tests/RulesEngineTest.php index f9b9baa9..239c7694 100644 --- a/src/Tests/RulesEngineTest.php +++ b/src/Tests/RulesEngineTest.php @@ -79,7 +79,6 @@ public function testContextPassing() { $rule->addAction('rules_test_log'); $rule->setContextValue('test', 'test value'); $rule->execute(); - // Test that the action logged something. $this->assertRulesLogEntryExists('action called'); } @@ -99,7 +98,6 @@ public function testProvidedVariables() { $rule->addAction('rules_test_log'); $rule->execute(); - // Test that the action logged something. $this->assertRulesLogEntryExists('action called'); } diff --git a/src/Tests/RulesWebProfilerTest.php b/src/Tests/RulesWebProfilerTest.php new file mode 100644 index 00000000..0c16a078 --- /dev/null +++ b/src/Tests/RulesWebProfilerTest.php @@ -0,0 +1,76 @@ +container->get('config.factory') + ->getEditable('rules.settings') + ->set('debug_log', 1) + ->set('log_errors', 'debug') + ->save(); + + $this->webProfilerUser = $this->drupalCreateUser(array( + 'access webprofiler', + 'view webprofiler toolbar', + )); + + // Enables rules web debugging with WebProfiler. + $this->container->get('config.factory') + ->getEditable('webprofiler.config') + ->set('active_toolbar_items.rules', 'rules') + ->save(); + + $this->drupalLogin($this->webProfilerUser); + } + + /** + * Goes to WebProfiler page using link from toolbar and check entries there. + */ + public function testWebProfilerPage() { + $this->drupalGet('404', [ + 'query' => [ + 'log' => '1', + 'log-level' => 'critical', + 'log-message' => 'critical message', + 'log-amount' => 5, + ], + ]); + + $this->drupalGet('admin/reports/profiler/list'); + $links = $this->xpath('//main//table[1]//a'); + $url = $this->getAbsoluteUrl($links[0]['href']); + $this->drupalGet($url); + $this->assertText('Rules logs', 'Rules logs table exists'); + $this->assertText('critical message', 'Rules log entry exists'); + } + +} diff --git a/src/WebProfiler/DataCollector/RulesDataCollector.php b/src/WebProfiler/DataCollector/RulesDataCollector.php new file mode 100644 index 00000000..0afca5b5 --- /dev/null +++ b/src/WebProfiler/DataCollector/RulesDataCollector.php @@ -0,0 +1,161 @@ +rulesLogger = $rulesLogger; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Exception $exception = NULL) { + $this->data['logs'] = $this->rulesLogger->getLogs(); + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'rules'; + } + + /** + * {@inheritdoc} + */ + public function getTitle() { + return $this->t('Rules'); + } + + /** + * {@inheritdoc} + */ + public function getPanelSummary() { + return $this->t('Total rules log entries: @count', array('@count' => $this->getLogsCount())); + } + + /** + * Return amount of rules log entries. + * + * @return int + * Amount of rules log entries. + */ + public function getLogsCount() { + return count($this->data['logs']); + } + + /** + * Return amount of Rules log entries with level higher then warning. + * + * @return int + * Amount of error Rules log entries. + */ + public function getErrorLogsCount() { + $logs = array_filter($this->data['logs'], function ($log) { + return in_array($log['level'], array( + LogLevel::ERROR, + LogLevel::CRITICAL, + LogLevel::ALERT, + LogLevel::EMERGENCY + )); + }); + + return count($logs); + } + + /** + * Return amount of Rules log entries with level notice or warning. + * + * @return int + * Amount of error Rules log entries. + */ + public function getNoticeLogsCount() { + $logs = array_filter($this->data['logs'], function ($log) { + return in_array($log['level'], array(LogLevel::WARNING, LogLevel::NOTICE)); + }); + + return count($logs); + } + + /** + * Return amount of Rules info log entries. + * + * @return int + * Amount of error Rules log entries. + */ + public function getInfoLogsCount() { + $logs = array_filter($this->data['logs'], function ($log) { + return in_array($log['level'], array(LogLevel::DEBUG, LogLevel::INFO)); + }); + + return count($logs); + } + + /** + * {@inheritdoc} + */ + public function getPanel() { + $build = array(); + + $build['table_title'] = array( + '#type' => 'inline_template', + '#template' => '