diff --git a/core/modules/help_topics/help_topics/core.security.html.twig b/core/modules/help_topics/help_topics/core.security.html.twig index 63b12c4937..6c04f7dc96 100644 --- a/core/modules/help_topics/help_topics/core.security.html.twig +++ b/core/modules/help_topics/help_topics/core.security.html.twig @@ -1,4 +1,4 @@ - +
{% trans %}The topics listed here will help you make and keep your site secure.{% endtrans %}
diff --git a/core/modules/help_topics/tests/src/Kernel/HelpTopicCoreTopicsTest.php b/core/modules/help_topics/tests/src/Kernel/HelpTopicCoreTopicsTest.php index 4ba764b44e..6ca6eb4929 100644 --- a/core/modules/help_topics/tests/src/Kernel/HelpTopicCoreTopicsTest.php +++ b/core/modules/help_topics/tests/src/Kernel/HelpTopicCoreTopicsTest.php @@ -14,30 +14,70 @@ class HelpTopicCoreTopicsTest extends KernelTestBase { /** - * Ensure all core help topics do not throw exceptions. + * The topic plugin definitions, keyed by ID. + * + * @var array + */ + protected $definitions; + + /** + * The list of IDs of the top-level topics. + * + * @var string[] + */ + protected $topLevelIds = []; + + /** + * Ensure all core help topics do not throw exceptions and follow standards. */ public function testCoreTopics() { - // Get a list of all core modules including inactive ones. $directories = []; - // Add module directories. - $module_list = \Drupal::service('extension.list.module')->getList(); - foreach ($module_list as $module) { - /** @var \Drupal\Core\Extension\Extension $module */ - $directories[$module->getName()] = $module->getPath() . '/help_topics'; + // Add directories for all modules and themes, even if they are not + // installed, but excluding test modules/themes. + foreach (['module', 'theme'] as $type) { + $lister = \Drupal::service('extension.list.' . $type); + foreach ($lister->getAllAvailableInfo() as $name => $info) { + $path = $lister->getPath($name); + // You can tell test modules because they are in package 'Testing', but + // test themes are only known by being found in test directories. So... + // exclude things in test directories. + if (strpos($path, '/tests/' . $type . 's/') === FALSE) { + $directories[$name] = $path . '/help_topics'; + } + } } - // Add theme directories. - $theme_list = \Drupal::service('theme_handler')->rebuildThemeData(); - foreach ($theme_list as $provider => $theme) { - $directories[$provider] = $theme->subpath . '/help_topics'; - } + // Just to make sure, verify that a few key modules and themes are listed. + // If these lines fail, it is probably because a theme or module is being + // removed. Substitute another theme that still exists so that this test + // can continue. + $this->assertTrue(isset($directories['system']), 'System module is being scanned'); + $this->assertTrue(isset($directories['help']), 'Help module is being scanned'); + $this->assertTrue(isset($directories['seven']), 'Seven theme is being scanned'); // Add core. $directories['core'] = 'core/help_topics'; - // Create a single topic that is expected to fail. + // Discover the help topics within these directories. + $discovery = new HelpTopicDiscovery($directories); + $this->definitions = $discovery->getDefinitions(); + $this->assertTrue(count($this->definitions) > 1, 'At least 1 topic was found'); + + // Figure out which topics are top-level. + foreach ($this->definitions as $id => $definition) { + if (isset($definition['top_level']) && $definition['top_level']) { + $this->topLevelIds[$id] = $id; + } + } + + // Test each topic for compliance with standards. + foreach (array_keys($this->definitions) as $id) { + $this->verifyTopic($id); + } + + // Create a single topic that is expected to fail discovery. vfsStream::setup('root'); vfsStream::create([ 'modules' => [ @@ -49,17 +89,77 @@ public function testCoreTopics() { ], ], ]); - $directories['expected_failure'] = vfsStream::url('root/modules/test/help_topics'); + $fail_directories['expected_failure'] = vfsStream::url('root/modules/test/help_topics'); - // Check that just this expected failure topic does throw an exception to - // ensure this test is actually running. + // Check that just this expected failure topic does throw an exception. $this->expectException(DiscoveryException::class); $this->expectExceptionMessage("vfs://root/modules/test/help_topics/test.topic.html.twig should begin with 'expected_failure.'"); + $fail_discovery = new HelpTopicDiscovery($fail_directories); + $fail_discovery->getDefinitions(); + } - // Load all found help topics within all core modules. This will trigger - // an exception if any have any issues. - $discovery = new HelpTopicDiscovery($directories); - $discovery->findAll(); + /** + * Tests an individual help topic. + * + * @param string $id + * The topic ID to verify. + */ + protected function verifyTopic($id) { + $definition = $this->definitions[$id]; + // Verify that the topic is either top-level or 'related' to a top-level + // topic. + if (!in_array($id, $this->topLevelIds)) { + if (!isset($definition['related']) || empty($definition['related'])) { + $this->fail('Topic ' . $id . ' is either top-level or related to at least one other topic'); + } + else { + $ok = FALSE; + foreach ($definition['related'] as $related_id) { + $ok = $ok || in_array($related_id, $this->topLevelIds); + } + $this->assertTrue($ok, 'Topic ' . $id . ' is either top-level or related to a top-level topic'); + } + } + + // Verify that all the related topics exist. + if (isset($definition['related'])) { + foreach ($definition['related'] as $related_id) { + $this->assertTrue(isset($this->definitions[$related_id]), 'Topic ' . $id . ' is only related to topics that exist (' . $related_id . ')'); + } + } + + // Verify that the label is not empty. + $this->assertTrue(isset($definition['label']) && !empty($definition['label']), 'Topic ' . $id . ' has a non-empty label'); + + // Read in the file so we can run some tests on that. + $body = file_get_contents($definition[HelpTopicDiscovery::FILE_KEY]); + $this->assertFalse(empty($body), 'Topic ' . $id . ' has a non-empty Twig file'); + + // Remove the meta tags (already tested above), and Twig set and variable + // printouts from the file. + $body = preg_replace('|\