diff --git a/config/install/config_help.topic.config_basic.yml b/config/install/config_help.topic.config_basic.yml index 11aac50..4b6b45e 100644 --- a/config/install/config_help.topic.config_basic.yml +++ b/config/install/config_help.topic.config_basic.yml @@ -12,37 +12,31 @@ related: { } list_on: { } body: - - id: paragraph - text: - value: 'The settings for your site are configured on various administrative pages, as follows:' - format: help_plain + text: 'The settings for your site are configured on various administrative pages, as follows:' + prefix_tags: '
' + suffix_tags: '
' - - id: description_name - text: - value: 'Site name, slogan, and email address' - format: help_plain + text: 'Site name, slogan, and email address' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Responding to software errors' - format: help_plain + text: 'Responding to software errors' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Viewing the site log' - format: help_plain + text: 'Viewing the site log' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.config_help.yml b/config/install/config_help.topic.config_help.yml index aff3e06..2488e41 100644 --- a/config/install/config_help.topic.config_help.yml +++ b/config/install/config_help.topic.config_help.yml @@ -14,32 +14,27 @@ related: list_on: { } body: - - id: paragraph - text: - value: 'Follow these steps to build a help system for different types/roles of users on your system to use:' - format: help_plain + text: 'Follow these steps to build a help system for different types/roles of users on your system to use:' + prefix_tags: '' + suffix_tags: '
' - - id: numbered - text: - value: 'Plan your help system: make a list of the topics each type/role of user would benefit from.' - format: help_plain + text: 'Plan your help system: make a list of the topics each type/role of user would benefit from.' + prefix_tags: '' + suffix_tags: '
' + - + text: 'Top-level topic' + prefix_tags: '' + suffix_tags: '
' - - id: bullet - text: - value: 'Choose short titles. If the topic describes a task, start with a verb in -ing form, like "Building a help system".' - format: help_plain + text: 'Choose short titles. If the topic describes a task, start with a verb in -ing form, like "Building a help system".' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.menu_overview.yml b/config/install/config_help.topic.menu_overview.yml index 7e75c1b..6d29ae1 100644 --- a/config/install/config_help.topic.menu_overview.yml +++ b/config/install/config_help.topic.menu_overview.yml @@ -12,7 +12,7 @@ related: { } list_on: { } body: - - id: paragraph - text: - value: 'The related topics listed here describe how to set up various aspects of site navigation and URLs.' - format: help_plain + text: 'The related topics listed here describe how to set up various aspects of site navigation and URLs.' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.security.yml b/config/install/config_help.topic.security.yml index 5cc4ba6..d44e373 100644 --- a/config/install/config_help.topic.security.yml +++ b/config/install/config_help.topic.security.yml @@ -12,7 +12,7 @@ related: { } list_on: { } body: - - id: paragraph - text: - value: 'The topics listed here will help you make and keep your site secure.' - format: help + text: 'The topics listed here will help you make and keep your site secure.' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.security_account_settings.yml b/config/install/config_help.topic.security_account_settings.yml index 081f8af..6261d2e 100644 --- a/config/install/config_help.topic.security_account_settings.yml +++ b/config/install/config_help.topic.security_account_settings.yml @@ -15,27 +15,23 @@ list_on: - security body: - - id: paragraph - text: - value: 'On the Account settings page, which you can reach from the Manage administrative menu, by navigating to Configuration > People > Account settings (requires the Administer account settings permission), you can configure several settings related to how user accounts are created:' - format: help + text: 'On the Account settings page, which you can reach from the Manage administrative menu, by navigating to Configuration > People > Account settings (requires the Administer account settings permission), you can configure several settings related to how user accounts are created:' + prefix_tags: '' + suffix_tags: '
' - - id: bullet - text: - value: 'You can make it possible for new users to register themselves, with or without administrator approval. Or, you can make it so only administrators with Administer users permission can register new users.' - format: help + text: 'You can make it possible for new users to register themselves, with or without administrator approval. Or, you can make it so only administrators with Administer users permission can register new users.' + prefix_tags: '' + suffix_tags: '
' - - id: description_name - text: - value: 'Disabling drag-and-drop functionality' - format: help_plain + text: 'Disabling drag-and-drop functionality' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.ui_contextual.yml b/config/install/config_help.topic.ui_contextual.yml index c0dde05..acbecc5 100644 --- a/config/install/config_help.topic.ui_contextual.yml +++ b/config/install/config_help.topic.ui_contextual.yml @@ -14,37 +14,31 @@ list_on: - ui_components body: - - id: heading - text: - value: 'What are contextual links?' - format: help_plain + text: 'What are contextual links?' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Displaying and using contextual links' - format: help_plain + text: 'Displaying and using contextual links' + prefix_tags: '' + suffix_tags: '
' - - id: bullet - text: - value: 'Hovering your mouse over an area on the page will temporarily make the contextual links button visible, if there is one for that area of the page. Also, in most themes, the page area that the contextual links pertain to will be outlined while you are hovering.' - format: help_plain + text: 'Hovering your mouse over an area on the page will temporarily make the contextual links button visible, if there is one for that area of the page. Also, in most themes, the page area that the contextual links pertain to will be outlined while you are hovering.' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.ui_shortcuts.yml b/config/install/config_help.topic.ui_shortcuts.yml index 9e923d9..001f69a 100644 --- a/config/install/config_help.topic.ui_shortcuts.yml +++ b/config/install/config_help.topic.ui_shortcuts.yml @@ -14,32 +14,27 @@ list_on: - ui_components body: - - id: heading - text: - value: 'What are shortcuts?' - format: help_plain + text: 'What are shortcuts?' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Creating and deleting shortcuts' - format: help_plain + text: 'Creating and deleting shortcuts' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Viewing and using shortcuts' - format: help_plain + text: 'Viewing and using shortcuts' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/config_help.topic.ui_tours.yml b/config/install/config_help.topic.ui_tours.yml index 84c8d4c..ec45443 100644 --- a/config/install/config_help.topic.ui_tours.yml +++ b/config/install/config_help.topic.ui_tours.yml @@ -14,22 +14,19 @@ list_on: - ui_components body: - - id: heading - text: - value: 'What are tours?' - format: help_plain + text: 'What are tours?' + prefix_tags: '' + suffix_tags: '
' - - id: heading - text: - value: 'Viewing tours' - format: help_plain + text: 'Viewing tours' + prefix_tags: '' + suffix_tags: '
' +body_format: help diff --git a/config/install/filter.format.help.yml b/config/install/filter.format.help.yml index 2031cdd..274682a 100644 --- a/config/install/filter.format.help.yml +++ b/config/install/filter.format.help.yml @@ -4,7 +4,7 @@ dependencies: enforced: module: - config_help -name: 'Help - HTML' +name: Help format: help weight: 0 filters: @@ -14,6 +14,6 @@ filters: status: true weight: -10 settings: - allowed_html: ' ' + allowed_html: '
'
filter_html_help: true
filter_html_nofollow: false
diff --git a/config/install/filter.format.help_plain.yml b/config/install/filter.format.help_plain.yml
deleted file mode 100644
index c0f6b5f..0000000
--- a/config/install/filter.format.help_plain.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-langcode: en
-status: true
-dependencies:
- enforced:
- module:
- - config_help
-name: 'Help - plain text'
-format: help_plain
-weight: 0
-filters:
- filter_html_escape:
- id: filter_html_escape
- provider: filter
- status: true
- weight: -10
- settings: { }
diff --git a/config/optional/editor.editor.help.yml b/config/optional/editor.editor.help.yml
new file mode 100644
index 0000000..66c2f58
--- /dev/null
+++ b/config/optional/editor.editor.help.yml
@@ -0,0 +1,52 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - filter.format.help
+ module:
+ - ckeditor
+format: help
+editor: ckeditor
+settings:
+ toolbar:
+ rows:
+ -
+ -
+ name: Formatting
+ items:
+ - Bold
+ - Italic
+ -
+ name: Links
+ items:
+ - DrupalLink
+ - DrupalUnlink
+ -
+ name: Lists
+ items:
+ - BulletedList
+ - NumberedList
+ - Indent
+ - Outdent
+ - Table
+ -
+ name: Media
+ items:
+ - DrupalImage
+ -
+ name: Tools
+ items:
+ - Source
+ plugins:
+ stylescombo:
+ styles: ''
+ language:
+ language_list: un
+image_upload:
+ status: false
+ scheme: public
+ directory: inline-images
+ max_size: ''
+ max_dimensions:
+ width: null
+ height: null
diff --git a/config/schema/config_help.schema.yml b/config/schema/config_help.schema.yml
index c8df7e7..576ca10 100644
--- a/config/schema/config_help.schema.yml
+++ b/config/schema/config_help.schema.yml
@@ -29,13 +29,19 @@ config_help.topic.*:
label: 'Body'
sequence:
type: config_help_text
+ body_format:
+ type: string
+ label: 'Body format'
config_help_text:
type: mapping
mapping:
- id:
- label: 'Type'
+ prefix_tags:
type: string
+ label: 'Prefix tags'
text:
+ type: text
label: 'Text'
- type: text_format
+ suffix_tags:
+ type: string
+ label: 'Suffix tags'
diff --git a/config_help.api.php b/config_help.api.php
deleted file mode 100644
index 80056bb..0000000
--- a/config_help.api.php
+++ /dev/null
@@ -1,35 +0,0 @@
-getEditable('filter.format.help');
+ $filters = $config->get('filters');
+ foreach ($filters as $index => $filter) {
+ if ($filter['id'] == 'filter_html') {
+ $filter['settings']['allowed_html'] .= '
-
-
-
';
+ $filters[$index] = $filter;
+ }
+ }
+ $config->set('filters', $filters);
+ $config->save(TRUE);
+
+ // Find the list of all existing help topics.
+ $sandbox['topics'] = $config_factory->listAll('config_help.topic.');
+ $sandbox['start_with'] = 0;
+ $sandbox['num'] = count($sandbox['topics']);
+ }
+
+ // Update up to 20 topics in a batch.
+ $topics = array_slice($sandbox['topics'], $sandbox['start_with'], 20);
+ if (!$topics) {
+ $sandbox['#finished'] = 1;
+ return;
+ }
+ $sandbox['#finished'] = ($sandbox['start_with'] + 20) / $sandbox['num'];
+ $sandbox['start_with'] += 20;
+
+ foreach ($topics as $topic) {
+ $config = $config_factory->getEditable($topic);
+ $config->set('body_format', 'help');
+
+ $old_body = $config->get('body');
+ $new_body = [];
+ $previous_list = '';
+ $previous_index = 0;
+ foreach ($old_body as $index => $old_chunk) {
+ $new_chunk = ['text' => $old_chunk['text']['value']];
+ switch ($old_chunk['id']) {
+ case 'paragraph':
+ $new_list = '';
+ $new_chunk['prefix_tags'] = '';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'heading':
+ $new_list = '';
+ $new_chunk['prefix_tags'] = '';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'subheading':
+ $new_list = '';
+ $new_chunk['prefix_tags'] = '';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'code':
+ $new_list = '';
+ $new_chunk['prefix_tags'] = '';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'bullet':
+ $new_list = 'ul';
+ $new_chunk['prefix_tags'] = '- ';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'numbered':
+ $new_list = 'ol';
+ $new_chunk['prefix_tags'] = '- ';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'description_name':
+ $new_list = 'dl';
+ $new_chunk['prefix_tags'] = '- ';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ case 'description_value':
+ $new_list = 'dl';
+ $new_chunk['prefix_tags'] = '- ';
+ $new_chunk['suffix_tags'] = '
';
+ break;
+
+ default:
+ $new_list = '';
+ $new_chunk['prefix_tags'] = '';
+ $new_chunk['suffix_tags'] = '';
+ break;
+ }
+
+ // Close previous list if this isn't part of it.
+ if ($previous_list && ($new_list != $previous_list)) {
+ $new_body[$previous_index]['suffix_tags'] .= '' . $previous_list . '>';
+ }
+ // Open new list if it wasn't already open.
+ if ($new_list && ($new_list != $previous_list)) {
+ $new_chunk['prefix_tags'] = '<' . $new_list . '>' . $new_chunk['prefix_tags'];
+ }
+ // Save this chunk and update previous variables.
+ $new_body[$index] = $new_chunk;
+ $previous_index = $index;
+ $previous_list = $new_list;
+ }
+
+ // Close out the last list if necessary.
+ if ($previous_list) {
+ $new_body[$previous_index]['suffix_tags'] .= '' . $previous_list . '>';
+ }
+
+ // Save the configuration.
+ $config->set('body', $new_body);
+ $config->save(TRUE);
+ }
+}
diff --git a/config_help.module b/config_help.module
index 1bb36df..b7e2319 100644
--- a/config_help.module
+++ b/config_help.module
@@ -14,51 +14,22 @@ use Drupal\Core\Url;
function config_help_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.config_help':
- $sections = [];
- $sections[] = [
- '#section_type' => 'heading',
- '#text' => t('About'),
- ];
- $sections[] = [
- '#section_type' => 'paragraph',
- '#text' => t('The Configurable Help module adds configurable help topics to the module-provided help from the core Help module. For more information, see the online documentation for the Configurable Help module.', [':online' => 'https://www.drupal.org/modules/config_help']),
- ];
- $sections[] = [
- '#section_type' => 'heading',
- '#text' => ['#markup' => t('Uses')],
- ];
- $sections[] = [
- '#section_type' => 'description_name',
- '#text' => t('Configuring help topics'),
- ];
- $sections[] = [
- '#section_type' => 'description_value',
- '#text' => t('You can add, edit, delete, and translate configure help topics on the Help topics administration page. The help topics that are listed in the Module help section of the main Help page cannot be edited or deleted. See the Building a help system topic for more information on configuring help topics.', [
- ':topic_admin' => Url::fromRoute('entity.help_topic.collection')->toString(),
- ':main_topic' => Url::fromRoute('entity.help_topic.canonical', ['help_topic' => 'config_help'])->toString(),
- ]),
- ];
- $sections[] = [
- '#section_type' => 'description_name',
- '#text' => t('Viewing configurable help topics'),
- ];
- $sections[] = [
- '#section_type' => 'description_value',
- '#text' => t('The top-level configured help topics are listed on the main Help page.', [':help_page' => Url::fromRoute('help.main')->toString()]),
- ];
- $sections[] = [
- '#section_type' => 'description_name',
- '#text' => t('Updating help topics'),
- ];
- $sections[] = [
- '#section_type' => 'description_value',
- '#text' => t('Help topics provided by modules and themes may be updated when a module or theme is updated, or new topics may be added. However, help topics are only imported into your site configuration when you first install the module or theme. The contributed Configuration Update Manager module can be used to check for updates, see differences, and import or update topics that have been added or have changed. It is advisable not to edit module- or theme-provided topics, to make updates easier.', [':config_update' => 'https://www.drupal.org/project/config_update']),
- ];
-
- return [
- '#type' => 'text_sections',
- '#sections' => $sections,
- ];
+ $output = '';
+ $output .= '' . t('About') . '
';
+ $output .= '' . t('The Configurable Help module adds configurable help topics to the module-provided help from the core Help module. For more information, see the online documentation for the Configurable Help module.', [':online' => 'https://www.drupal.org/modules/config_help']) . '
';
+ $output .= '' . t('Uses') . '
';
+ $output .= '';
+ $output .= '- ' . t('Configuring help topics') . '
';
+ $output .= '- ' . t('You can add, edit, delete, and translate configure help topics on the Help topics administration page. The help topics that are listed in the Module help section of the main Help page cannot be edited or deleted. See the Building a help system topic for more information on configuring help topics.', [
+ ':topic_admin' => Url::fromRoute('entity.help_topic.collection')->toString(),
+ ':main_topic' => Url::fromRoute('entity.help_topic.canonical', ['help_topic' => 'config_help'])->toString(),
+ ]) . '
';
+ $output .= '- ' . t('Viewing configurable help topics') . '
';
+ $output .= '- ' . t('The top-level configured help topics are listed on the main Help page.', [':help_page' => Url::fromRoute('help.main')->toString()]) . '
';
+ $output .= '- ' . t('Updating help topics') . '
';
+ $output .= '- ' . t('Help topics provided by modules and themes may be updated when a module or theme is updated, or new topics may be added. However, help topics are only imported into your site configuration when you first install the module or theme. The contributed Configuration Update Manager module can be used to check for updates, see differences, and import or update topics that have been added or have changed. It is advisable not to edit module- or theme-provided topics, to make updates easier.', [':config_update' => 'https://www.drupal.org/project/config_update']) . '
';
+ $output .= '
';
+ return ['#markup' => $output];
}
}
diff --git a/config_help.services.yml b/config_help.services.yml
index 30ecb77..07ec438 100644
--- a/config_help.services.yml
+++ b/config_help.services.yml
@@ -4,7 +4,3 @@ services:
arguments: ['@string_translation']
tags:
- { name: breadcrumb_builder, priority: 900 }
-
- plugin.manager.text_section:
- class: Drupal\config_help\TextSectionManager
- parent: default_plugin_manager
diff --git a/src/Annotation/TextSection.php b/src/Annotation/TextSection.php
deleted file mode 100644
index 95714a5..0000000
--- a/src/Annotation/TextSection.php
+++ /dev/null
@@ -1,57 +0,0 @@
- 'text_sections',
- * '#sections' => [
- * [
- * '#section_type' => 'heading',
- * '#text' => ['#markup' => t('Greetings')],
- * ],
- * [
- * '#section_type' => 'paragraph',
- * '#text' => ['#markup' => t('Hello, world.')],
- * ],
- * ],
- * ];
- * @endcode
- *
- * @see \Drupal\config_help\TextSectionPluginInterface
- *
- * @RenderElement("text_sections")
- */
-class TextSections extends RenderElement {
-
- /**
- * {@inheritdoc}
- */
- public function getInfo() {
- $class = get_class($this);
- return [
- '#pre_render' => [[$class, 'preRenderSections']],
- ];
- }
-
- /**
- * Expands a #text_sections element into an array of sections.
- *
- * @param array $element
- * The form element to process. See main class documentation for properties.
- *
- * @return array
- * The form element.
- */
- public static function preRenderSections(array $element) {
- /** @var \Drupal\config_help\TextSectionPluginCollection */
- $collection = new TextSectionPluginCollection(self::sectionManager(), []);
- $collection->addFromRenderArray($element);
-
- unset($element['#sections']);
- unset($element['#type']);
- return $collection->preRenderCollection(self::renderer(), $element);
- }
-
- /**
- * Wraps the text section manager service.
- *
- * @return \Drupal\config_help\TextSectionManager
- * The text section plugin manager.
- */
- protected static function sectionManager() {
- return \Drupal::service('plugin.manager.text_section');
- }
-
- /**
- * Wraps the renderer service.
- *
- * @return \Drupal\Core\Render\Renderer
- * The renderer.
- */
- protected static function renderer() {
- return \Drupal::service('renderer');
- }
-
-}
diff --git a/src/Entity/HelpTopic.php b/src/Entity/HelpTopic.php
index 2f7b3d6..daa019a 100644
--- a/src/Entity/HelpTopic.php
+++ b/src/Entity/HelpTopic.php
@@ -2,12 +2,12 @@
namespace Drupal\config_help\Entity;
+use Drupal\Component\Utility\Html;
use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Config\ConfigValueException;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
use Drupal\config_help\HelpTopicInterface;
-use Drupal\config_help\TextSectionPluginCollection;
/**
* Defines a configuration entity for help topics.
@@ -63,6 +63,7 @@ use Drupal\config_help\TextSectionPluginCollection;
* "related",
* "list_on",
* "body",
+ * "body_format",
* },
* admin_permission = "administer help topics",
* links = {
@@ -76,7 +77,7 @@ use Drupal\config_help\TextSectionPluginCollection;
* }
* )
*/
-class HelpTopic extends ConfigEntityBase implements HelpTopicInterface, EntityWithPluginCollectionInterface {
+class HelpTopic extends ConfigEntityBase implements HelpTopicInterface {
/**
* The topic machine name.
@@ -93,16 +94,20 @@ class HelpTopic extends ConfigEntityBase implements HelpTopicInterface, EntityWi
protected $label;
/**
- * The unprocessed topic body text.
- *
- * See \Drupal\config_help\HelpTopicInterface::getBody() for documentation
- * of the structure.
+ * The unprocessed topic body text (in the configuration schema format).
*
* @var array
*/
protected $body = [];
/**
+ * The machine name of the text format for the body in HTML form.
+ *
+ * @var string
+ */
+ protected $body_format = '';
+
+ /**
* Whether or not the topic should appear on the help topics list.
*
* @var bool
@@ -131,26 +136,46 @@ class HelpTopic extends ConfigEntityBase implements HelpTopicInterface, EntityWi
protected $list_on = [];
/**
- * The plugin collection for the text section plugins.
- *
- * @var \Drupal\config_help\TextSectionPluginCollection
+ * {@inheritdoc}
*/
- protected $pluginCollection;
+ public function getBody() {
+ // Concatenate all the tags and text into one HTML string and return it.
+ $body_text = '';
+ foreach ($this->get('body') as $chunk) {
+ $body_text .= $chunk['prefix_tags'] . $chunk['text'] . $chunk['suffix_tags'];
+ }
+ return $body_text;
+ }
/**
* {@inheritdoc}
*/
- public function getBody() {
- return $this->get('body');
+ public function setBody($body) {
+ // Chunk the passed-in string and save it as an array.
+ $dom = Html::load($body);
+ if (!$dom) {
+ throw new ConfigValueException($this->t('Body HTML is malformed'));
+ }
+ $chunks = [];
+ $body_node = $dom->getElementsByTagName('body')->item(0);
+ if ($body_node) {
+ $chunks = $this->chunkDomNode($dom, $body_node);
+ }
+ return $this->set('body', $chunks);
}
/**
* {@inheritdoc}
*/
- public function setBody(array $body) {
- // Setting this invalidates the plugin collection if already instantiated.
- $this->pluginCollection = NULL;
- return $this->set('body', $body);
+ public function getBodyFormat() {
+ return $this->get('body_format');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setBodyFormat($format) {
+ return $this->set('body_format', $format);
}
/**
@@ -304,13 +329,130 @@ class HelpTopic extends ConfigEntityBase implements HelpTopicInterface, EntityWi
}
/**
- * {@inheritdoc}
+ * Splits a DOM node recursively into chunks.
+ *
+ * @param \DOMDocument $dom
+ * The DOM document this came from.
+ * @param \DOMNode $node
+ * DOM node to split into chunks.
+ * @param string $prefix
+ * (optional) Prefix tags to put on first chunk.
+ * @param string $suffix
+ * (optional) Suffix tags to put on last chunk.
+ *
+ * @return array
+ * Array of chunks from $node. Each chunk is an array with elements:
+ * - text: Text content of the chunk, which may contain HTML.
+ * - prefix_tags: HTML tags that go before the text content.
+ * - suffix_tags: HTML tags that go after the text content.
+ * The intent is that if you concatenate all the chunks' prefix_tags,
+ * text, and suffix_tags, you will end up with the original HTML.
*/
- public function getPluginCollections() {
- if (!$this->pluginCollection) {
- $this->pluginCollection = new TextSectionPluginCollection(\Drupal::service('plugin.manager.text_section'), $this->body);
+ protected function chunkDomNode(\DOMDocument $dom, \DOMNode $node, $prefix = '', $suffix = '') {
+
+ // These HTML tags generate an automatic chunk.
+ $chunk_tags = [
+ 'p',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'li',
+ 'dt',
+ 'dd',
+ 'code',
+ 'pre',
+ 'blockquote',
+ 'td',
+ 'th',
+ 'caption',
+ ];
+
+ $chunks = [];
+ foreach ($node->childNodes as $node) {
+ switch($node->nodeType) {
+ case XML_ELEMENT_NODE:
+ if (!$node->hasChildNodes()) {
+ // It's an empty element, so just add it to the prefix for the
+ // next chunk.
+ $prefix .= $dom->saveXML($node);
+ }
+ else {
+ $open_tag = '<' . $node->tagName;
+ if ($node->hasAttributes()) {
+ foreach ($node->attributes as $attr) {
+ $open_tag .= $dom->saveXML($attr);
+ }
+ }
+ $open_tag .= '>';
+ $close_tag = '' . $node->tagName . '>';
+
+ if (in_array($node->tagName, $chunk_tags)) {
+ // Don't go deeper, just save everything this node contains
+ // as one chunk.
+ $text = '';
+ foreach ($node->childNodes as $inner) {
+ $text .= $dom->saveXML($inner);
+ }
+ $chunks[] = [
+ 'text' => $text,
+ 'prefix_tags' => $prefix . $open_tag,
+ 'suffix_tags' => $close_tag,
+ ];
+ $prefix = '';
+ }
+ else {
+ // Recursively generate chunks from this node's children.
+ $new_chunks = $this->chunkDomNode($dom, $node, $prefix . $open_tag, $close_tag);
+ $chunks = array_merge($chunks, $new_chunks);
+ $prefix = '';
+ }
+ }
+ break;
+
+ case XML_TEXT_NODE:
+ // Add text nodes as their own chunks.
+ $chunks[] = [
+ 'text' => $dom->saveXML($node),
+ 'prefix_tags' => $prefix,
+ 'suffix_tags' => '',
+ ];
+ $prefix = '';
+ break;
+
+ default:
+ // For nodes that are anything except elements or text, just add
+ // them to the prefix we are working on. These are things like HTML
+ // comments, for example.
+ $prefix .= $dom->saveXML($node);
+ break;
+ }
+ }
+
+ // If we have prefix left over, add it as a chunk.
+ if ($prefix) {
+ $chunks[] = [
+ 'text' => '',
+ 'prefix_tags' => $prefix,
+ 'suffix_tags' => '',
+ ];
}
- return ['body' => $this->pluginCollection];
+
+ // If we have a suffix left over, add it to the last chunk.
+ if ($suffix) {
+ if (!$chunks) {
+ $chunks[] = [
+ 'text' => '',
+ 'prefix_tags' => '',
+ 'suffix_tags' => '',
+ ];
+ }
+ $chunks[count($chunks) - 1]['suffix_tags'] .= $suffix;
+ }
+
+ return $chunks;
}
}
diff --git a/src/Form/HelpTopicForm.php b/src/Form/HelpTopicForm.php
index 17a1592..7c72e38 100644
--- a/src/Form/HelpTopicForm.php
+++ b/src/Form/HelpTopicForm.php
@@ -3,7 +3,6 @@
namespace Drupal\config_help\Form;
use Drupal\Component\Utility\Html;
-use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
@@ -13,7 +12,6 @@ use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
-use Drupal\config_help\TextSectionManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -43,13 +41,6 @@ class HelpTopicForm extends EntityForm {
protected $themeHandler;
/**
- * The plugin manager for text sections.
- *
- * @var \Drupal\config_help\TextSectionManager
- */
- protected $sectionManager;
-
- /**
* Constructs a new help topic form.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
@@ -58,14 +49,11 @@ class HelpTopicForm extends EntityForm {
* The module handler.
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
* The theme handler.
- * @param \Drupal\config_help\TextSectionManager $section_manager
- * The text section plugin manager.
*/
- public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, TextSectionManager $section_manager) {
+ public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
$this->helpStorage = $entity_type_manager->getStorage('help_topic');
$this->moduleHandler = $module_handler;
$this->themeHandler = $theme_handler;
- $this->sectionManager = $section_manager;
}
/**
@@ -75,8 +63,7 @@ class HelpTopicForm extends EntityForm {
return new static(
$container->get('entity_type.manager'),
$container->get('module_handler'),
- $container->get('theme_handler'),
- $container->get('plugin.manager.text_section')
+ $container->get('theme_handler')
);
}
@@ -124,96 +111,19 @@ class HelpTopicForm extends EntityForm {
'#languages' => LanguageInterface::STATE_ALL,
];
- // The body is a sequence of elements. Use a standard multiple-value form
- // element in the form, with an add new button.
- // See how many elements we should make.
- $body = $entity->getBody();
- $bodycount = count($body);
- $max = $bodycount ? $bodycount : 1;
- $stuff = $form_state->getStorage();
- if (isset($stuff['config_help_body_count'])) {
- // This is coming from an Ajax request. Add one to the count
- // so we build an additional form element.
- $max = $stuff['config_help_body_count'] + 1;
- }
-
- // Save the information in storage.
- $stuff['config_help_body_count'] = $max;
- $form_state->setStorage($stuff);
-
- // Build the wrapper element. This is borrowed from the Field API's
- // \Drupal\Core\Field\WidgetBase::formMultipleElements() method.
- $id_prefix = 'config-help-body-field';
- $wrapper_id = Html::getUniqueId($id_prefix . '-add-more-wrapper');
- $field_name = 'body';
- $form[$field_name] = [
- '#theme' => 'field_multiple_value_form',
- '#tree' => TRUE,
- '#field_name' => $field_name,
- '#cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
- '#cardinality_multiple' => TRUE,
- '#required' => FALSE,
- '#title' => $this->t('Body components'),
- '#description' => $this->t('Compose the body of a help topic using headers, paragraphs, code areas, and list items.'),
- '#max_delta' => $max,
- '#prefix' => '',
- '#suffix' => '',
+ $form['body'] = [
+ '#type' => 'text_format',
+ '#title' => $this->t('Body'),
+ '#default_value' => $entity->getBody(),
+ '#format' => $entity->getBodyFormat(),
+ '#description' => $this->t('You can use tokens like [route:url:ROUTE_NAME] and [help_topic:url:MACHINE_NAME] to insert URLs to administrative page routes and to other help topics into the text.'),
];
-
- // Add edit elements for each body component.
- for ($delta = 0; $delta < $max; $delta++) {
- if (!isset($body[$delta])) {
- $body[$delta] = [
- 'id' => '',
- 'text' => [
- 'value' => '',
- 'format' => 'help',
- ],
- ];
- }
-
- $element = [
- '#delta' => $delta,
- '#weight' => $delta,
- '#required' => FALSE,
- ];
- $element['id'] = [
- '#type' => 'select',
- '#options' => $this->sectionManager->getOptionsList(),
- '#default_value' => $body[$delta]['id'],
- ];
- $element['text'] = [
- '#type' => 'text_format',
- '#default_value' => $body[$delta]['text']['value'],
- '#format' => $body[$delta]['text']['format'],
- '#description' => $this->t('You can use tokens like [route:url:ROUTE_NAME] and [help_topic:url:MACHINE_NAME] to insert URLs to administrative page routes and to other help topics into the text.'),
- ];
- $element['_weight'] = [
- '#type' => 'weight',
- '#title' => $this->t('Weight for row @number', ['@number' => $delta + 1]),
- '#title_display' => 'invisible',
- '#delta' => $max,
- '#default_value' => $delta,
- '#weight' => 100,
- ];
-
- $form[$field_name][$delta] = $element;
+ // The filter module will deny access if the format is set to '', so unset
+ // to instead use the first format that the user can access as the default.
+ if (!$form['body']['#format']) {
+ unset($form['body']['#format']);
}
- // Include the add more button.
- $form[$field_name]['add_more'] = [
- '#type' => 'submit',
- '#name' => strtr($id_prefix, '-', '_') . '_add_more',
- '#value' => $this->t('Add another item'),
- '#attributes' => ['class' => ['field-add-more-submit']],
- '#submit' => ['::addMoreSubmit'],
- '#ajax' => [
- 'callback' => '::addMoreAjax',
- 'wrapper' => $wrapper_id,
- 'effect' => 'fade',
- ],
- ];
-
$form['relationships'] = [
'#type' => 'details',
'#open' => TRUE,
@@ -227,7 +137,6 @@ class HelpTopicForm extends EntityForm {
'#description' => $this->t('Check box if this topic should be displayed on the Help page topics list'),
];
-
$form['relationships']['related'] = [
'#title' => $this->t('Topics to list here'),
'#description' => $this->t("Topics to list in this topic's Related topics section. Comma-separated list of machine names."),
@@ -279,35 +188,6 @@ class HelpTopicForm extends EntityForm {
}
/**
- * Handles the Ajax submit for the add more button.
- *
- * Modified from \Drupal\Core\Field\WidgetBase::addMoreSubmit().
- */
- public static function addMoreSubmit(array $form, FormStateInterface $form_state) {
- $form_state->setRebuild();
- }
-
- /**
- * Handles the Ajax response for the add more button.
- *
- * Modified from \Drupal\Core\Field\WidgetBase::addMoreAjax().
- */
- public static function addMoreAjax(array $form, FormStateInterface $form_state) {
- // Go one level up from the Add More button, so we're looking at the list.
- $button = $form_state->getTriggeringElement();
- $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
-
- // Add a DIV around the delta receiving the Ajax effect.
- $latest = $element['#max_delta'];
- if (isset($element[$latest])) {
- $element[$latest]['#prefix'] = '' . (isset($element[$latest]['#prefix']) ? $element[$latest]['#prefix'] : '');
- $element[$latest]['#suffix'] = (isset($element[$latest]['#suffix']) ? $element[$latest]['#suffix'] : '') . '';
- }
-
- return $element;
- }
-
- /**
* Copies the topics and dependencies field values to the entity properties.
*
* This is added to $form['#entity_builders'] in the form builder method.
@@ -322,6 +202,7 @@ class HelpTopicForm extends EntityForm {
* Form state.
*/
protected function copyTopicFieldsToEntity($type, EntityInterface $entity, array &$form, FormStateInterface &$form_state) {
+ $body = $form_state->getValue('body');
$entity
->setRelated(Tags::explode($form_state->getValue('related')))
->setListOn(Tags::explode($form_state->getValue('list_on')))
@@ -329,7 +210,8 @@ class HelpTopicForm extends EntityForm {
'module' => Tags::explode($form_state->getValue('modules')),
'theme' => Tags::explode($form_state->getValue('themes')),
])
- ->setBody($this->cleanBody($form_state->getValue('body')));
+ ->setBody($body['value'])
+ ->setBodyFormat($body['format']);
}
/**
@@ -338,6 +220,11 @@ class HelpTopicForm extends EntityForm {
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
+ // Make sure that the HTML in the body can at least be loaded/parsed.
+ if (!Html::load($form_state->getValue('body')['value'])) {
+ $form_state->setErrorByName('body', $this->t('Body HTML is malformed'));
+ }
+
// Make sure that the two reference fields only contain machine names of
// actual help topics.
foreach (['related', 'list_on'] as $field) {
@@ -389,36 +276,4 @@ class HelpTopicForm extends EntityForm {
}
}
- /**
- * Cleans an unprocessed body field value.
- *
- * @param array $body
- * Array of body text pieces.
- *
- * @return array
- * List of non-empty body text pieces, in order by weight.
- */
- protected function cleanBody(array $body) {
- if (!$body || !is_array($body)) {
- return [];
- }
-
- $cleaned = [];
- foreach ($body as $piece) {
- if (is_array($piece) && isset($piece['id']) && isset($piece['text']['value']) && isset($piece['text']['format'])) {
- // Make sure there is actually something relevant in the text.
- $text = trim($piece['text']['value']);
- if ($text) {
- $piece['text']['value'] = $text;
- $weight = $piece['_weight'];
- unset($piece['_weight']);
- $cleaned[$weight] = $piece;
- }
- }
- }
-
- ksort($cleaned);
- return array_values($cleaned);
- }
-
}
diff --git a/src/HelpTopicInterface.php b/src/HelpTopicInterface.php
index e742357..80b669d 100644
--- a/src/HelpTopicInterface.php
+++ b/src/HelpTopicInterface.php
@@ -12,34 +12,38 @@ use Drupal\Core\Config\Entity\ConfigEntityInterface;
interface HelpTopicInterface extends ConfigEntityInterface {
/**
- * Returns the unprocessed body of the topic.
+ * Returns body of the topic.
*
- * @return array
- * A number-indexed array of pieces of body text. Each piece is an array
- * with two elements:
- * - id: The machine name of a text section type plugin.
- * - text: The text, which in turn is an array with two elements:
- * - value: Unformatted, unfiltered text.
- * - format: ID of the text format to use to filter/format the text.
- *
- * @see \Drupal\Core\Render\Annotation\TextSection
+ * @return string
+ * The HTML-formatted body of the topic.
*/
public function getBody();
/**
- * Sets the unprocessed body value for the topic.
+ * Sets the body value for the topic.
+ *
+ * @param string $body
+ * The HTML-formatted body to save in the topic.
*
- * @param array $body
- * A number-indexed array of pieces of body text. Each piece is an array
- * with two elements:
- * - id: The machine name of a text section type plugin.
- * - text: The text, which in turn is an array with two elements:
- * - value: Unformatted, unfiltered text.
- * - format: ID of the text format to use to filter/format the text.
+ * @throws \Drupal\Core\Config\ConfigValueException if the HTML is malformed.
+ */
+ public function setBody($body);
+
+ /**
+ * Returns text format for the body of the topic.
+ *
+ * @return string
+ * The machine name of the text format for the topic body.
+ */
+ public function getBodyFormat();
+
+ /**
+ * Sets the text format for the body of the topic.
*
- * @see \Drupal\Core\Render\Annotation\TextSection
+ * @param string $format
+ * The machine name of the text format to use for the topic body.
*/
- public function setBody(array $body);
+ public function setBodyFormat($format);
/**
* Returns whether this is a top-level topic or not.
diff --git a/src/HelpViewBuilder.php b/src/HelpViewBuilder.php
index 17ffb65..c7a928a 100644
--- a/src/HelpViewBuilder.php
+++ b/src/HelpViewBuilder.php
@@ -80,11 +80,14 @@ class HelpViewBuilder extends EntityViewBuilder {
$build['#langcode'] = $langcode;
$build['#title'] = $help_topic->label();
- // Add in the body.
- $collections = $help_topic->getPluginCollections();
- /** @var \Drupal\config_help\TextSectionPluginCollection $body_collection */
- $body_collection = $collections['body'];
- $build['#body'] = $body_collection->buildRenderArray([$this, 'processBodyItem']);
+ // Add in the body, with token replacement.
+ $bubbleable_metadata = new BubbleableMetadata();
+ $build['#body'] = [
+ '#type' => 'processed_text',
+ '#text' => $this->token->replace($help_topic->getBody(), [], [], $bubbleable_metadata),
+ '#format' => $help_topic->getBodyFormat(),
+ ];
+ $bubbleable_metadata->applyTo($build['#body']);
// Figure out which topics to list as related, including topics this
// entity lists as related, plus topics that have said "Add me to this
@@ -126,25 +129,4 @@ class HelpViewBuilder extends EntityViewBuilder {
return $output;
}
- /**
- * Processes a piece of text from the body.
- *
- * @param array $item
- * Array containing the 'value' and 'format' elements from a single
- * paragraph-sized piece of the body.
- *
- * @return array
- * Render array section for this piece of the body, with tokens replaced.
- */
- public function processBodyItem(array $item) {
- $bubbleable_metadata = new BubbleableMetadata();
- $section = [
- '#type' => 'processed_text',
- '#text' => $this->token->replace($item['value'], [], [], $bubbleable_metadata),
- '#format' => $item['format'],
- ];
- $bubbleable_metadata->applyTo($section);
- return $section;
- }
-
}
diff --git a/src/Plugin/TextSection/BulletItem.php b/src/Plugin/TextSection/BulletItem.php
deleted file mode 100644
index 035d310..0000000
--- a/src/Plugin/TextSection/BulletItem.php
+++ /dev/null
@@ -1,39 +0,0 @@
- 'item_list',
- '#list_type' => 'ul',
- '#items' => [],
- ];
-
- $group['#items'][] = $this->getInnerBuild();
-
- return $group;
- }
-
-}
diff --git a/src/Plugin/TextSection/Code.php b/src/Plugin/TextSection/Code.php
deleted file mode 100644
index d77d32d..0000000
--- a/src/Plugin/TextSection/Code.php
+++ /dev/null
@@ -1,26 +0,0 @@
- '',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
-}
diff --git a/src/Plugin/TextSection/DescriptionName.php b/src/Plugin/TextSection/DescriptionName.php
deleted file mode 100644
index 70e8362..0000000
--- a/src/Plugin/TextSection/DescriptionName.php
+++ /dev/null
@@ -1,53 +0,0 @@
- '- ',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
- /**
- * {@inheritdoc}
- */
- public function groupWith() {
- return ['description_name', 'description_value'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function addToGroup(array $group) {
- // Initialize the group, in case this is the first item.
- $group += [
- '#prefix' => '',
- '#suffix' => '
',
- 'list' => [],
- ];
-
- $group['list'][] = $this->getInnerBuild();
-
- return $group;
- }
-
-}
diff --git a/src/Plugin/TextSection/DescriptionValue.php b/src/Plugin/TextSection/DescriptionValue.php
deleted file mode 100644
index 0f6986c..0000000
--- a/src/Plugin/TextSection/DescriptionValue.php
+++ /dev/null
@@ -1,53 +0,0 @@
- '- ',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
- /**
- * {@inheritdoc}
- */
- public function groupWith() {
- return ['description_name', 'description_value'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function addToGroup(array $group) {
- // Initialize the group, in case this is the first item.
- $group += [
- '#prefix' => '',
- '#suffix' => '
',
- 'list' => [],
- ];
-
- $group['list'][] = $this->getInnerBuild();
-
- return $group;
- }
-
-}
diff --git a/src/Plugin/TextSection/Heading.php b/src/Plugin/TextSection/Heading.php
deleted file mode 100644
index 6583917..0000000
--- a/src/Plugin/TextSection/Heading.php
+++ /dev/null
@@ -1,26 +0,0 @@
- '',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
-}
diff --git a/src/Plugin/TextSection/NumberedItem.php b/src/Plugin/TextSection/NumberedItem.php
deleted file mode 100644
index 518a052..0000000
--- a/src/Plugin/TextSection/NumberedItem.php
+++ /dev/null
@@ -1,39 +0,0 @@
- 'item_list',
- '#list_type' => 'ol',
- '#items' => [],
- ];
-
- $group['#items'][] = $this->getInnerBuild();
-
- return $group;
- }
-
-}
diff --git a/src/Plugin/TextSection/Paragraph.php b/src/Plugin/TextSection/Paragraph.php
deleted file mode 100644
index 33752cc..0000000
--- a/src/Plugin/TextSection/Paragraph.php
+++ /dev/null
@@ -1,26 +0,0 @@
- '',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
-}
diff --git a/src/Plugin/TextSection/SubHeading.php b/src/Plugin/TextSection/SubHeading.php
deleted file mode 100644
index 95aa972..0000000
--- a/src/Plugin/TextSection/SubHeading.php
+++ /dev/null
@@ -1,26 +0,0 @@
- '',
- '#suffix' => '
',
- ] + parent::getInnerBuild();
- }
-
-}
diff --git a/src/Plugin/TextSection/TextSectionBase.php b/src/Plugin/TextSection/TextSectionBase.php
deleted file mode 100644
index 03270f5..0000000
--- a/src/Plugin/TextSection/TextSectionBase.php
+++ /dev/null
@@ -1,55 +0,0 @@
- $text];
- }
- $this->text = $text;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getInnerBuild() {
- return $this->text;
- }
-
- /**
- * {@inheritdoc}
- */
- public function groupWith() {
- return [];
- }
-
- /**
- * {@inheritdoc}
- */
- public function addToGroup(array $group) {
- return [];
- }
-
-}
diff --git a/src/TextSectionManager.php b/src/TextSectionManager.php
deleted file mode 100644
index bbda01a..0000000
--- a/src/TextSectionManager.php
+++ /dev/null
@@ -1,96 +0,0 @@
-alterInfo('text_section_info');
- $this->setCacheBackend($cache_backend, 'text_section_plugins');
- }
-
- /**
- * {@inheritdoc}
- */
- public function findDefinitions() {
- $definitions = parent::findDefinitions();
- uasort($definitions, [$this, 'sortPlugins']);
- return $definitions;
- }
-
- /**
- * Makes an options array for a select list of text section plugins.
- *
- * @return array
- * Array whose keys are machine names of text section plugins, and whose
- * values are the translated labels for the plugins, suitable for use as
- * options for radios or select lists.
- */
- public function getOptionsList() {
- $plugins = $this->getDefinitions();
- $options = [];
- foreach ($plugins as $plugin_id => $plugin_definition) {
- $options[$plugin_id] = $plugin_definition['label'];
- }
-
- return $options;
- }
-
- /**
- * Provides a uasort() callback for sorting plugin definitions.
- *
- * Sorts by weight first, and within the same weight, alphabetically by
- * label.
- *
- * @param array $definition1
- * First plugin definition to compare.
- * @param array $definition2
- * Second plugin definition to compare.
- *
- * @return int
- * A number <1 if the first plugin should come first, >1 if the second
- * should, and 0 if this cannot be determined.
- */
- protected function sortPlugins(array $definition1, array $definition2) {
- if ($definition1['weight'] < $definition2['weight']) {
- return -1;
- }
- if ($definition2['weight'] < $definition1['weight']) {
- return 1;
- }
- if ($definition1['label'] < $definition2['label']) {
- return -1;
- }
- if ($definition2['label'] < $definition1['label']) {
- return 1;
- }
- return 0;
- }
-
-}
diff --git a/src/TextSectionPluginCollection.php b/src/TextSectionPluginCollection.php
deleted file mode 100644
index 4ad83a0..0000000
--- a/src/TextSectionPluginCollection.php
+++ /dev/null
@@ -1,130 +0,0 @@
- 'text_sections',
- '#sections' => [],
- ];
-
- $configuration = $this->getConfiguration();
- if (!$configuration) {
- return $build;
- }
-
- foreach ($configuration as $key => $item) {
- $section = [
- '#section_type' => $item['id'],
- '#text' => $item['text'],
- ];
- if ($callback) {
- $section['#text'] = call_user_func($callback, $section['#text']);
- }
- $build['#sections'][] = $section;
- }
-
- return $build;
- }
-
- /**
- * Adds plugins to the collection from a text_sections render array.
- *
- * @param array $element
- * Render array element of #type 'text_sections' to add plugins from.
- *
- * @return $this
- *
- * @see \Drupal\config_help\TextSectionPluginCollection::buildRenderArray()
- */
- public function addFromRenderArray(array $element) {
- $sections = $element['#sections'];
- foreach ($sections as $index => $section) {
- $this->addInstanceId($index, [
- 'id' => $section['#section_type'],
- 'text' => $section['#text'],
- ]);
- }
-
- return $this;
- }
-
- /**
- * Pre-renders the current collection.
- *
- * @param \Drupal\Core\Render\Renderer $renderer
- * The renderer service to use.
- * @param array $element
- * The render array to add information to.
- *
- * @return array
- * Render array: starts with $element, and adds the formatted text from the
- * plugins.
- */
- public function preRenderCollection(Renderer $renderer, array $element) {
- $previous_type = '';
- $group_build = [];
- $element['text_sections'] = [];
-
- $all_configuration = $this->getConfiguration();
- foreach ($all_configuration as $id => $config) {
- /** @var \Drupal\config_help\TextSectionPluginInterface $plugin */
- $plugin = $this->get($id);
- $plugin->setText($config['text']);
- $renderer->addCacheableDependency($element, $plugin);
-
- // Check for grouping.
- $this_group_with = $plugin->groupWith();
-
- if (!in_array($previous_type, $this_group_with) && !empty($group_build)) {
- // This section should not be grouped with the previous one, so add the
- // previous grouping to the element and reset the in-progress group.
- $element['text_sections'][] = $group_build;
- $group_build = [];
- }
-
- if (!empty($this_group_with)) {
- // This is a grouped section, either for a new group or a compatible
- // group. Add this to the group, or initialize a new group.
- $group_build = $plugin->addToGroup($group_build);
- }
- else {
- // It is not grouped, so just add it to the element.
- $element['text_sections'][] = $plugin->getInnerBuild();
- }
-
- // Save this type for the next grouping decision.
- $previous_type = $plugin->getPluginId();
- }
-
- // Add the last in-progress group to the element if there is one.
- if (!empty($group_build)) {
- $element['text_sections'][] = $group_build;
- }
-
- return $element;
- }
-
-}
diff --git a/src/TextSectionPluginInterface.php b/src/TextSectionPluginInterface.php
deleted file mode 100644
index d69507b..0000000
--- a/src/TextSectionPluginInterface.php
+++ /dev/null
@@ -1,77 +0,0 @@
-link to the Help module topic, and it should link to the help admin page. Also there should be a related topic link below to the Help module topic page and the linked topic.'
- format: help
+ text: 'This is a test. It should link to the Help module topic, and it should link to the help admin page. Also there should be a related topic link below to the Help module topic page and the linked topic.'
+ prefix_tags: ''
+ suffix_tags: '
'
+body_format: help
diff --git a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_additional.yml b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_additional.yml
index 8ce3949..6bc550a 100644
--- a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_additional.yml
+++ b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_additional.yml
@@ -14,7 +14,7 @@ list_on:
- help_test
body:
-
- id: paragraph
- text:
- value: 'This topic should get listed automatically on the Help test topic.'
- format: help_plain
+ text: 'This topic should get listed automatically on the Help test topic.'
+ prefix_tags: ''
+ suffix_tags: '
'
+body_format: help
diff --git a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_linked.yml b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_linked.yml
index 1f7f422..43ba6ee 100644
--- a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_linked.yml
+++ b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_linked.yml
@@ -13,7 +13,7 @@ related: { }
list_on: { }
body:
-
- id: paragraph
- text:
- value: 'This topic is not supposed to be top-level.'
- format: help
+ text: 'This topic is not supposed to be top-level.'
+ prefix_tags: ''
+ suffix_tags: '
'
+body_format: help
diff --git a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_locked.yml b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_locked.yml
index 23a3101..2a608fb 100644
--- a/tests/modules/config_help_test/config/optional/config_help.topic.help_test_locked.yml
+++ b/tests/modules/config_help_test/config/optional/config_help.topic.help_test_locked.yml
@@ -13,7 +13,7 @@ related: { }
list_on: { }
body:
-
- id: paragraph
- text:
- value: 'This topic is supposed to be locked to editing.'
- format: help
+ text: 'This topic is supposed to be locked to editing.'
+ prefix_tags: ''
+ suffix_tags: '
'
+body_format: help
diff --git a/tests/src/Functional/HelpTopicAdminTest.php b/tests/src/Functional/HelpTopicAdminTest.php
index ad84a8f..1f5fa9e 100644
--- a/tests/src/Functional/HelpTopicAdminTest.php
+++ b/tests/src/Functional/HelpTopicAdminTest.php
@@ -239,7 +239,7 @@ class HelpTopicAdminTest extends BrowserTestBase {
'label' => $title,
'id' => $id,
'top_level' => TRUE,
- 'body[0][text][value]' => $body,
+ 'body[value]' => $body,
], 'Save');
$session = $this->assertSession();
$session->pageTextContains('Help topic added');
@@ -319,7 +319,7 @@ class HelpTopicAdminTest extends BrowserTestBase {
'label' => $title,
'id' => 'foobar',
'top_level' => TRUE,
- 'body[0][text][value]' => $body,
+ 'body[value]' => $body,
'related' => 'invalid.text',
], 'Save');
$session = $this->assertSession();
diff --git a/tests/src/Functional/HelpTopicTest.php b/tests/src/Functional/HelpTopicTest.php
index 1276884..b690837 100644
--- a/tests/src/Functional/HelpTopicTest.php
+++ b/tests/src/Functional/HelpTopicTest.php
@@ -116,7 +116,7 @@ class HelpTopicTest extends BrowserTestBase {
$session->linkNotExists('ABC Help Test');
}
- /**
+ /**
* Tests export and import of help topics, and topic create from array.
*/
public function testTopicExportImport() {
@@ -126,12 +126,14 @@ class HelpTopicTest extends BrowserTestBase {
'label' => 'Foo',
'body' => [
[
- 'type' => 'heading',
'text' => 'Greetings',
+ 'prefix_tags' => '',
+ 'suffix_tags' => '
',
],
[
- 'type' => 'paragraph',
'text' => 'Hello, world!',
+ 'prefix_tags' => '',
+ 'suffix_tags' => '
',
],
],
'top_level' => TRUE,
@@ -157,10 +159,10 @@ class HelpTopicTest extends BrowserTestBase {
// Verify that everything is OK.
$to_check = [
// This is an array of method name => component in $values, except
- // dependencies, which are checked separately.
+ // dependencies and body, which are checked separately.
'id' => 'id',
'label' => 'label',
- 'getBody' => 'body',
+ 'getBody' => FALSE,
'isTopLevel' => 'top_level',
'isLocked' => 'locked',
'getRelated' => 'related',
@@ -176,11 +178,46 @@ class HelpTopicTest extends BrowserTestBase {
}
$this->assertEqual(call_user_func([$foo, $method]), call_user_func([$bar, $method]), 'Method ' . $method . ' is the same before and after export/import');
}
+
+ // Check that the getEnforcedDepenencies() method works correctly. The
+ // getBody() and setBody() methods are checked in a different test method.
$this->assertEqual($foo->getEnforcedDependencies(), $dependencies, 'Data for dependencies is the same as method getEnforcedDependencies');
}
/**
+ * Tests the help topic body get and set functions.
+ */
+ public function testTopicBodyGetSet() {
+ $topic = HelpTopic::create();
+
+ $body = '' .
+ 'A paragraph with attributes
' .
+ 'A heading
' .
+ 'A sub-heading
' .
+ '- Bullet 1
- Bullet 2
' .
+ '- Number 1
- Number 2
' .
+ 'Col 1 Col 2 ' .
+ 'Data 1 Data 2
' .
+ '- Item 1
- Definition 1
- Item 2
- Definition 2
';
+
+ // Make sure after set/get, the body is unchanged.
+ $topic->setBody($body);
+ $body_out = $topic->getBody($body);
+ $this->assertEqual($body, $body_out);
+
+ // Make sure that if we strip out tags, all remaining text is in the 'text'
+ // parts of the chunked body array.
+ $body_plain = strip_tags($body);
+ $body_chunked = $topic->toArray()['body'];
+ $chunked_text = '';
+ foreach ($body_chunked as $item) {
+ $chunked_text .= $item['text'];
+ }
+ $this->assertEqual($body_plain, $chunked_text);
+ }
+
+ /**
* Verifies the logged in user has access to various help links and pages.
*
* @param int $response
diff --git a/tests/src/Functional/HelpTopicTranslateTest.php b/tests/src/Functional/HelpTopicTranslateTest.php
index a810120..7784372 100644
--- a/tests/src/Functional/HelpTopicTranslateTest.php
+++ b/tests/src/Functional/HelpTopicTranslateTest.php
@@ -75,7 +75,7 @@ class HelpTopicTranslateTest extends BrowserTestBase {
$this->clickLink('Add');
$this->drupalPostForm(NULL, [
'translation[config_names][config_help.topic.help_test][label]' => $es_title,
- 'translation[config_names][config_help.topic.help_test][body][0][text][value]' => $es_body,
+ 'translation[config_names][config_help.topic.help_test][body][0][text]' => $es_body,
], 'Save translation');
// Visit the page in English and verify.
@@ -105,7 +105,7 @@ class HelpTopicTranslateTest extends BrowserTestBase {
'label' => $second_es_title,
'id' => 'foo',
'top_level' => TRUE,
- 'body[0][text][value]' => $second_es_body,
+ 'body[value]' => $second_es_body,
], 'Save');
// Translate it into English.
@@ -113,7 +113,7 @@ class HelpTopicTranslateTest extends BrowserTestBase {
$this->clickLink('Add');
$this->drupalPostForm(NULL, [
'translation[config_names][config_help.topic.foo][label]' => $second_en_title,
- 'translation[config_names][config_help.topic.foo][body][0][text][value]' => $second_en_body,
+ 'translation[config_names][config_help.topic.foo][body][0][text]' => $second_en_body,
], 'Save translation');
// Visit the page in English and verify.
diff --git a/tests/src/Kernel/TextSectionRenderingTest.php b/tests/src/Kernel/TextSectionRenderingTest.php
deleted file mode 100644
index 239067c..0000000
--- a/tests/src/Kernel/TextSectionRenderingTest.php
+++ /dev/null
@@ -1,221 +0,0 @@
- 'text_sections',
- '#sections' => [
- [
- '#section_type' => 'heading',
- '#text' => ['#markup' => 'First H2 header'],
- ],
- [
- '#section_type' => 'heading',
- '#text' => 'Second H2 header',
- ],
- [
- '#section_type' => 'subheading',
- '#text' => ['#markup' => 'First H3 sub-header'],
- ],
- [
- '#section_type' => 'subheading',
- '#text' => 'Second H3 sub-header',
- ],
- [
- '#section_type' => 'paragraph',
- '#text' => 'First paragraph',
- ],
- [
- '#section_type' => 'paragraph',
- '#text' => ['#markup' => 'Second paragraph'],
- ],
- [
- '#section_type' => 'code',
- '#text' => 'Some code',
- ],
- [
- '#section_type' => 'code',
- '#text' => ['#markup' => 'More code'],
- ],
- [
- '#section_type' => 'bullet',
- '#text' => ['#markup' => 'First list, first bullet'],
- ],
- [
- '#section_type' => 'bullet',
- '#text' => 'First list, second bullet',
- ],
- [
- '#section_type' => 'numbered',
- '#text' => ['#markup' => 'Numbered list, first item'],
- ],
- [
- '#section_type' => 'numbered',
- '#text' => 'Numbered list, second item',
- ],
- [
- '#section_type' => 'description_name',
- '#text' => 'DL list, first name',
- ],
- [
- '#section_type' => 'description_value',
- '#text' => 'DL list, first value',
- ],
- [
- '#section_type' => 'description_name',
- '#text' => ['#markup' => 'DL list, second name'],
- ],
- [
- '#section_type' => 'description_value',
- '#text' => ['#markup' => 'DL list, second value'],
- ],
- ],
- ];
-
- // Pre-render the element into a more basic render array.
- $result = TextSections::preRenderSections($element);
-
- // Compare to the expected result, but only the text_sections part.
- $expected = [
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'First H2 header',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'Second H2 header',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'First H3 sub-header',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'Second H3 sub-header',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'First paragraph',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'Second paragraph',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'Some code',
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- '#markup' => 'More code',
- ],
- [
- '#theme' => 'item_list',
- '#list_type' => 'ul',
- '#items' => [
- ['#markup' => 'First list, first bullet'],
- ['#markup' => 'First list, second bullet'],
- ],
- ],
- [
- '#theme' => 'item_list',
- '#list_type' => 'ol',
- '#items' => [
- ['#markup' => 'Numbered list, first item'],
- ['#markup' => 'Numbered list, second item'],
- ],
- ],
- [
- '#prefix' => '',
- '#suffix' => '
',
- 'list' => [
- [
- '#prefix' => '- ',
- '#suffix' => '
',
- '#markup' => 'DL list, first name',
- ],
- [
- '#prefix' => '- ',
- '#suffix' => '
',
- '#markup' => 'DL list, first value',
- ],
- [
- '#prefix' => '- ',
- '#suffix' => '
',
- '#markup' => 'DL list, second name',
- ],
- [
- '#prefix' => '- ',
- '#suffix' => '
',
- '#markup' => 'DL list, second value',
- ],
- ],
- ],
- ];
-
- $this->assertTrue($result['text_sections'] == $expected, 'Pre-processing behaved as expected');
- }
-
- /**
- * Tests the options list for text sections.
- */
- public function testOptionsList() {
- /** @var \Drupal\config_help\TextSectionManager $manager */
- $manager = \Drupal::service('plugin.manager.text_section');
- $options = $manager->getOptionsList();
-
- // The sorting of the list should be by weight first, then alphabetically
- // by label.
- $expected = [
- // Weight is -100.
- 'paragraph' => 'Paragraph',
- // Weight is -20.
- 'heading' => 'Heading',
- // Weight is -19.
- 'subheading' => 'Sub-heading',
- // Weight is -10.
- 'bullet' => 'Bullet list item',
- 'numbered' => 'Numbered list item',
- // Weight is 10.
- 'description_name' => 'Description list name item',
- // Weight is 11.
- 'description_value' => 'Description list value item',
- // Weight is 100.
- 'code' => 'Code',
- ];
-
- $this->assertTrue($options == $expected, 'Options list was as expected');
- }
-
-}