clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
name: 'Help Page Test'
type: module
description: 'Module to test the help page.'
package: Testing
version: VERSION
hidden: true

View File

@@ -0,0 +1,31 @@
<?php
/**
* @file
* Help Page Test module to test the help page.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function help_page_test_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.help_page_test':
// Make the help text conform to core standards. See
// \Drupal\system\Tests\Functional\GenericModuleTestBase::assertHookHelp().
return t('Read the <a href=":url">online documentation for the Help Page Test module</a>.', [':url' => 'http://www.example.com']);
case 'help_page_test.has_help':
return t('I have help!');
case 'help_page_test.test_array':
return ['#markup' => 'Help text from help_page_test_help module.'];
}
// Ensure that hook_help() can return an empty string and not cause the block
// to display.
return '';
}

View File

@@ -0,0 +1,20 @@
help_page_test.has_help:
path: '/help_page_test/has_help'
defaults:
_controller: '\Drupal\help_page_test\HelpPageTestController::hasHelp'
requirements:
_access: 'TRUE'
help_page_test.no_help:
path: '/help_page_test/no_help'
defaults:
_controller: '\Drupal\help_page_test\HelpPageTestController::noHelp'
requirements:
_access: 'TRUE'
help_page_test.test_array:
path: '/help_page_test/test_array'
defaults:
_controller: '\Drupal\help_page_test\HelpPageTestController::testArray'
requirements:
_access: 'TRUE'

View File

@@ -0,0 +1,40 @@
<?php
namespace Drupal\help_page_test;
/**
* Provides controllers for testing the help block.
*/
class HelpPageTestController {
/**
* Provides a route with help.
*
* @return array
* A render array.
*/
public function hasHelp() {
return ['#markup' => 'A route with help.'];
}
/**
* Provides a route with no help.
*
* @return array
* A render array.
*/
public function noHelp() {
return ['#markup' => 'A route without help.'];
}
/**
* Provides a route which has multiple array returns from hook_help().
*
* @return array
* A render array.
*/
public function testArray() {
return ['#markup' => 'A route which has multiple array returns from hook_help().'];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Drupal\help_page_test\Plugin\HelpSection;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
use Drupal\help\Attribute\HelpSection;
/**
* Provides an empty section for the help page, for testing.
*/
#[HelpSection(
id: 'empty_section',
title: new TranslatableMarkup('Empty section'),
description: new TranslatableMarkup('This description should appear.')
)]
class EmptyHelpSection extends HelpSectionPluginBase {
/**
* {@inheritdoc}
*/
public function listTopics() {
return [];
}
}

View File

@@ -0,0 +1,5 @@
name: help_test
type: module
package: Testing
dependencies:
- drupal:help

View File

@@ -0,0 +1,16 @@
<?php
/**
* @file
* Test Help module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function help_test_help($route_name, RouteMatchInterface $route_match) {
// Do not implement a module overview page to test an empty implementation.
// @see \Drupal\help\Tests\HelpTest
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Drupal\help_test;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;
/**
* Implements a URL generator which always thrown an exception.
*/
class SupernovaGenerator implements UrlGeneratorInterface {
/**
* {@inheritdoc}
*/
public function setContext(RequestContext $context) {
throw new \Exception();
}
/**
* {@inheritdoc}
*/
public function getContext(): RequestContext {
throw new \Exception();
}
/**
* {@inheritdoc}
*/
public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH): string {
throw new \Exception();
}
/**
* {@inheritdoc}
*/
public function getPathFromRoute($name, $parameters = []) {
throw new \Exception();
}
/**
* {@inheritdoc}
*/
public function generateFromRoute($name, $parameters = [], $options = [], $collect_bubbleable_metadata = FALSE) {
throw new \Exception();
}
}

View File

@@ -0,0 +1,5 @@
---
label: 'Help topic with bad HTML syntax'
top_level: true
---
<p>{% trans %}Body goes here{% endtrans %}</h3>

View File

@@ -0,0 +1,6 @@
---
label: 'Bad HTML syntax within trans section'
top_level: true
---
<p>{% trans %}<a href="/foo">Text here{% endtrans %}</a></p>

View File

@@ -0,0 +1,5 @@
---
label: 'Unclosed HTML tag'
top_level: true
---
<p>{% trans %}<a href="/foo">Text here{% endtrans %}</p>

View File

@@ -0,0 +1,4 @@
---
label: 'Help topic containing no body'
top_level: true
---

View File

@@ -0,0 +1,5 @@
---
label: 'Help topic with H1 header'
top_level: true
---
<h1>{% trans %}Body goes here{% endtrans %}</h1>

View File

@@ -0,0 +1,5 @@
---
label: 'Help topic with h3 without an h2'
top_level: true
---
<h3>{% trans %}Body goes here{% endtrans %}</h3>

View File

@@ -0,0 +1,5 @@
---
label: 'Help topic with locale-unsafe tag'
top_level: true
---
<p>{% trans %}some translated text and a <script>alert('hello')</script>{% endtrans %}</p>

View File

@@ -0,0 +1,7 @@
---
label: 'Help topic related to nonexistent topic'
top_level: true
related:
- this.is.not.a.valid.help_topic.id
---
<p>{% trans %}Body goes here{% trans %}</p>

View File

@@ -0,0 +1,4 @@
---
label: 'Help topic not top level or related to top level'
---
<p>{% trans %}Body goes here{% endtrans %}</p>

View File

@@ -0,0 +1,6 @@
---
label: 'Help topic with untranslated text'
top_level: true
---
<p>Body goes here</p>
<p>{% trans %}some translated text too{% endtrans %}</p>

View File

@@ -0,0 +1,9 @@
---
label: 'URL test topic that uses outdated url function'
top_level: true
---
{% set link_uses_url_func = render_var(url('valid.route')) %}
<p>{% trans %}This topic should be top-level. It is used to test URLs{% endtrans %}</p>
<ul>
<li>{% trans %}Valid link, but generated with <code>url()</code> instead of <code>help_route_link()</code> or <code>help_topic_link()</code>: {{ link_uses_url_func }}{% endtrans %}</li>
</ul>

View File

@@ -0,0 +1,6 @@
---
label: 'Additional topic'
related:
- help_topics_test.test
---
<p>{% trans %}This topic should get listed automatically on the Help test topic.{% endtrans %}</p>

View File

@@ -0,0 +1,4 @@
---
label: 'Linked topic'
---
<p>{% trans %}This topic is not supposed to be top-level.{% endtrans %}</p>

View File

@@ -0,0 +1,11 @@
---
label: "ABC Help Test module"
top_level: true
related:
- help_topics_test.linked
- does_not_exist.and_no_error
---
{% set help_topic_link = render_var(help_topic_link('help_topics_test.test_urls')) %}
<p>{% trans %}This is a test. It should link to the URL test topic {{ help_topic_link }}. Also there should be a related topic link below to the Help module topic page and the linked topic.{% endtrans %}</p>
<p>{% trans %}Non-word-item to translate.{% endtrans %}</p>
<p>{% trans %}Test translation.{% endtrans %}</p>

View File

@@ -0,0 +1,19 @@
---
label: 'URL test topic'
top_level: true
---
{% set non_route_link = render_var(help_route_link('not a route', 'not_a_real_route')) %}
{% set missing_params_link = render_var(help_route_link('missing params', 'help_topics_test.test_route')) %}
{% set invalid_params_link = render_var(help_route_link('invalid params', 'help_topics_test.test_route', {'int_param': 'not_an_int'})) %}
{% set valid_link = render_var(help_route_link('valid link', 'help_topics_test.test_route', {'int_param': 2})) %}
{% set topic_link = render_var(help_topic_link('help_topics_test.additional')) %}
{% set not_a_topic = render_var(help_topic_link('not_a_topic')) %}
<p>{% trans %}This topic should be top-level. It is used to test URLs{% endtrans %}</p>
<ul>
<li>{% trans %}Should not be a link: {{ non_route_link }}{% endtrans %}</li>
<li>{% trans %}Should not be a link: {{ missing_params_link }}{% endtrans %}</li>
<li>{% trans %}Should not be a link: {{ invalid_params_link }}{% endtrans %}</li>
<li>{% trans %}Should be a link if user has access: {{ valid_link }}{% endtrans %}</li>
<li>{% trans %}Should be a link: {{ topic_link }}{% endtrans %}</li>
<li>{% trans %}Should not be a link: {{ not_a_topic }}{% endtrans %}</li>
</ul>

View File

@@ -0,0 +1,9 @@
help_topics_test_direct_yml:
class: 'Drupal\help_topics_test\Plugin\HelpTopic\TestHelpTopicPlugin'
top_level: true
related: {}
label: "Test direct yaml topic label"
body: "Test direct yaml body"
help_topics_derivatives:
deriver: 'Drupal\help_topics_test\Plugin\Deriver\TestHelpTopicDeriver'

View File

@@ -0,0 +1,8 @@
# The name of this module is deliberately different from its machine
# name to test the presented order of help topics.
name: 'ABC Help Test'
type: module
description: 'Support module for help testing.'
package: Testing
dependencies:
- drupal:help

View File

@@ -0,0 +1,31 @@
<?php
/**
* @file
* Test module for help.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function help_topics_test_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.help_topics_test':
return 'Some kind of non-empty output for testing';
}
}
/**
* Implements hook_help_topics_info_alter().
*/
function help_topics_test_help_topics_info_alter(array &$info) {
// To prevent false positive search results limit list to testing topis only.
$filter = fn(string $key) => str_starts_with($key, 'help_topics_test') || in_array($key, [
'help_topics_test_direct_yml',
'help_topics_derivatives:test_derived_topic',
], TRUE);
$info = array_filter($info, $filter, ARRAY_FILTER_USE_KEY);
$info['help_topics_test.test']['top_level'] = \Drupal::state()->get('help_topics_test.test:top_level', TRUE);
}

View File

@@ -0,0 +1,2 @@
access test help:
title: 'Access the test help section'

View File

@@ -0,0 +1,11 @@
help_topics_test.test_route:
path: '/help_topics_test/{int_param<\d+>}'
defaults:
_controller: '\Drupal\help_topics_test\Controller\HelpTopicsTestController::testPage'
_title: 'Page for testing URLs in topics'
requirements:
_permission: 'access test help'
options:
parameters:
required_param:
type: int

View File

@@ -0,0 +1,28 @@
<?php
namespace Drupal\help_topics_test\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* Returns the response for help_topics_test routes.
*/
class HelpTopicsTestController extends ControllerBase {
/**
* Displays a dummy page for testing.
*
* @param int $int_param
* Required parameter (ignored).
*
* @return array
* Render array for the dummy page.
*/
public function testPage(int $int_param) {
$build = [
'#markup' => 'You have reached the help topics test routing page.',
];
return $build;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Drupal\help_topics_test\Plugin\Deriver;
use Drupal\Component\Plugin\Derivative\DeriverInterface;
/**
* A test discovery deriver for fake help topics.
*/
class TestHelpTopicDeriver implements DeriverInterface {
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
$prefix = $base_plugin_definition['id'];
$id = 'test_derived_topic';
$plugin_id = $prefix . ':' . $id;
$definitions[$id] = [
'plugin_id' => $plugin_id,
'id' => $plugin_id,
'class' => 'Drupal\\help_topics_test\\Plugin\\HelpTopic\\TestHelpTopicPlugin',
'label' => 'Label for ' . $id,
'body' => 'Body for ' . $id,
'top_level' => TRUE,
'related' => [],
'provider' => 'help_topics_test',
];
return $definitions;
}
/**
* {@inheritdoc}
*/
public function getDerivativeDefinition($derivative_id, $base_plugin_definition) {
return $base_plugin_definition;
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Drupal\help_topics_test\Plugin\HelpSection;
use Drupal\help\SearchableHelpInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
use Drupal\help\Attribute\HelpSection;
use Drupal\Core\StringTranslation\TranslatableMarkup;
// cspell:ignore asdrsad barmm foomm sqruct wcsrefsdf sdeeeee
/**
* Provides a searchable help section for testing.
*/
#[HelpSection(
id: 'help_topics_test',
title: new TranslatableMarkup('Test section'),
description: new TranslatableMarkup('For testing search'),
permission: 'access test help',
weight: 100
)]
class TestHelpSection extends HelpSectionPluginBase implements SearchableHelpInterface {
/**
* {@inheritdoc}
*/
public function listTopics() {
return [
Link::fromTextAndUrl('Foo', Url::fromUri('https://foo.com')),
Link::fromTextAndUrl('Bar', Url::fromUri('https://bar.com')),
];
}
/**
* {@inheritdoc}
*/
public function listSearchableTopics() {
return ['foo', 'bar'];
}
/**
* {@inheritdoc}
*/
public function renderTopicForSearch($topic_id, LanguageInterface $language) {
switch ($topic_id) {
case 'foo':
if ($language->getId() == 'en') {
return [
'title' => 'Foo in English title wcsrefsdf',
'text' => 'Something about foo body not-a-word-english sqruct',
'url' => Url::fromUri('https://foo.com'),
];
}
return [
'title' => 'Foomm Foreign heading',
'text' => 'Fake foreign foo text not-a-word-german asdrsad',
'url' => Url::fromUri('https://mm.foo.com'),
];
case 'bar':
if ($language->getId() == 'en') {
return [
'title' => 'Bar in English',
'text' => 'Something about bar another-word-english asdrsad',
'url' => Url::fromUri('https://bar.com'),
];
}
return [
'title' => \Drupal::state()->get('help_topics_test:translated_title', 'Barmm Foreign sdeeeee'),
'text' => 'Fake foreign barmm another-word-german sqruct',
'url' => Url::fromUri('https://mm.bar.com'),
];
default:
throw new \InvalidArgumentException('Unexpected ID encountered');
}
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Drupal\help_topics_test\Plugin\HelpTopic;
use Drupal\Core\Cache\Cache;
use Drupal\help\HelpTopicPluginBase;
/**
* A fake help topic plugin for testing.
*/
class TestHelpTopicPlugin extends HelpTopicPluginBase {
/**
* {@inheritdoc}
*/
public function getBody() {
return [
'#type' => 'markup',
'#markup' => $this->pluginDefinition['body'],
];
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return [];
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
return ['foobar'];
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge() {
return Cache::PERMANENT;
}
}

View File

@@ -0,0 +1,6 @@
name: 'Help Topics Twig Tester'
type: module
description: 'Support module for help testing.'
package: Testing
dependencies:
- drupal:help

View File

@@ -0,0 +1,6 @@
services:
help_test_twig.extension:
class: Drupal\help_topics_twig_tester\HelpTestTwigExtension
arguments: []
tags:
- { name: twig.extension, priority: 500 }

View File

@@ -0,0 +1,21 @@
<?php
namespace Drupal\help_topics_twig_tester;
use Twig\Extension\AbstractExtension;
/**
* Defines and registers Drupal Twig extensions for testing help topics.
*/
class HelpTestTwigExtension extends AbstractExtension {
/**
* {@inheritdoc}
*/
public function getNodeVisitors() {
return [
new HelpTestTwigNodeVisitor(),
];
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace Drupal\help_topics_twig_tester;
use Drupal\Core\Template\TwigNodeTrans;
use Twig\Environment;
use Twig\Node\Node;
use Twig\Node\PrintNode;
use Twig\Node\SetNode;
use Twig\Node\TextNode;
use Twig\Node\Expression\AbstractExpression;
use Twig\NodeVisitor\NodeVisitorInterface;
/**
* Defines a Twig node visitor for testing help topics.
*
* See static::setStateValue() for information on the special processing
* this class can do.
*/
class HelpTestTwigNodeVisitor implements NodeVisitorInterface {
/**
* Delimiter placed around single translated chunks.
*/
public const DELIMITER = 'Not Likely To Be Inside A Template';
/**
* Name used in \Drupal::state() for saving state information.
*/
protected const STATE_NAME = 'help_test_twig_node_visitor';
/**
* {@inheritdoc}
*/
public function enterNode(Node $node, Environment $env): Node {
return $node;
}
/**
* {@inheritdoc}
*/
public function leaveNode(Node $node, Environment $env): ?Node {
$processing = static::getState();
if (!$processing['manner']) {
return $node;
}
// For all special processing, we want to remove variables, set statements,
// and assorted Twig expression calls (if, do, etc.).
if ($node instanceof SetNode || $node instanceof PrintNode ||
$node instanceof AbstractExpression) {
return NULL;
}
if ($node instanceof TwigNodeTrans) {
// Count the number of translated chunks.
$this_chunk = $processing['chunk_count'] + 1;
static::setStateValue('chunk_count', $this_chunk);
if ($this_chunk > $processing['max_chunk']) {
static::setStateValue('max_chunk', $this_chunk);
}
if ($processing['manner'] == 'remove_translated') {
// Remove all translated text.
return NULL;
}
elseif ($processing['manner'] == 'replace_translated') {
// Replace with a dummy string.
$node = new TextNode('dummy', 0);
}
elseif ($processing['manner'] == 'translated_chunk') {
// Return the text only if it's the next chunk we're supposed to return.
// Add a wrapper, because non-translated nodes will still be returned.
if ($this_chunk == $processing['return_chunk']) {
return new TextNode(static::DELIMITER . $this->extractText($node) . static::DELIMITER, 0);
}
else {
return NULL;
}
}
}
if ($processing['manner'] == 'remove_translated' && $node instanceof TextNode) {
// For this processing, we also want to remove all HTML tags and
// whitespace from TextNodes.
$text = $node->getAttribute('data');
$text = strip_tags($text);
$text = preg_replace('|\s+|', '', $text);
return new TextNode($text, 0);
}
return $node;
}
/**
* {@inheritdoc}
*/
public function getPriority() {
return -100;
}
/**
* Extracts the text from a translated text object.
*
* @param \Drupal\Core\Template\TwigNodeTrans $node
* Translated text node.
*
* @return string
* Text in the node.
*/
protected function extractText(TwigNodeTrans $node) {
// Extract the singular/body and optional plural text from the
// TwigNodeTrans object.
$bodies = $node->getNode('body');
if (!count($bodies)) {
$bodies = [$bodies];
}
if ($node->hasNode('plural')) {
$plural = $node->getNode('plural');
if (!count($plural)) {
$bodies[] = $plural;
}
else {
foreach ($plural as $item) {
$bodies[] = $item;
}
}
}
// Extract the text from each component of the singular/plural strings.
$text = '';
foreach ($bodies as $body) {
if ($body->hasAttribute('data')) {
$text .= $body->getAttribute('data');
}
}
return trim($text);
}
/**
* Returns the state information.
*
* @return array
* The state information.
*/
public static function getState() {
return \Drupal::state()->get(static::STATE_NAME, ['manner' => 0]);
}
/**
* Sets state information.
*
* @param string $key
* Key to set. Possible keys:
* - manner: Type of special processing to do when rendering. Values:
* - 0: No processing.
* - remove_translated: Remove all translated text, HTML tags, and
* whitespace.
* - replace_translated: Replace all translated text with dummy text.
* - translated_chunk: Remove all translated text except one designated
* chunk (see return_chunk below).
* - bare_body (or any other non-zero value): Remove variables, set
* statements, and Twig programming, but leave everything else intact.
* - chunk_count: Current index of translated chunks. Reset to -1 before
* each rendering run. (Used internally by this class.)
* - max_chunk: Maximum index of translated chunks. Reset to -1 before
* each rendering run.
* - return_chunk: Chunk index to keep intact for translated_chunk
* processing. All others are removed.
* @param $value
* Value to set for $key.
*/
public static function setStateValue(string $key, $value) {
$state = \Drupal::state();
$values = $state->get(static::STATE_NAME, ['manner' => 0]);
$values[$key] = $value;
$state->set(static::STATE_NAME, $values);
}
}

View File

@@ -0,0 +1,6 @@
name: 'More Help Page Test'
type: module
description: 'Module to test the help page.'
package: Testing
version: VERSION
hidden: true

View File

@@ -0,0 +1,27 @@
<?php
/**
* @file
* More Help Page Test module to test the help blocks.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function more_help_page_test_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Return help for the same route as the help_page_test module.
case 'help_page_test.test_array':
return ['#markup' => 'Help text from more_help_page_test_help module.'];
}
}
/**
* Implements hook_help_section_info_alter().
*/
function more_help_page_test_help_section_info_alter(array &$info) {
$info['hook_help']['weight'] = 500;
}