Skip to content
Snippets Groups Projects
Commit e855e0fb authored by Vladimir Roudakov's avatar Vladimir Roudakov Committed by Joseph Olstad
Browse files

Issue #3455312 by joseph.olstad, smulvih2, vladimiraus, jurgenhaas, project...

Issue #3455312 by joseph.olstad, smulvih2, vladimiraus, jurgenhaas, project update bot: Automated Drupal 11 compatibility fixes for toc_api
parent 89c0b377
Branches
Tags 2.0.0-beta1
1 merge request!16Drupal 11 fixes
Pipeline #464686 passed
Showing
with 283 additions and 111 deletions
contenu
rockowitz
selectmenu
spécial
strto
tocs
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Add border to tree when displayed within a node * Add border to tree when displayed within a node
*/ */
.node .toc-tree { .node .toc-tree {
border: 1px solid #ccc;
padding: 0 1em;
margin: 1em 0; margin: 1em 0;
padding: 0 1em;
border: 1px solid #ccc;
} }
...@@ -4,19 +4,15 @@ ...@@ -4,19 +4,15 @@
*/ */
(function ($, Drupal) { (function ($, Drupal) {
"use strict";
Drupal.behaviors.tocMenu = { Drupal.behaviors.tocMenu = {
attach: function (context) { attach(context) {
$('form.toc-menu > select', context).change(function () { $('form.toc-menu > select', context).change(function () {
var value = $(this).val(); const value = this.value;
if (value) { if (value) {
location.hash = value; window.location.hash = value;
} }
this.selectedIndex = 0; this.selectedIndex = 0;
}); });
} },
}; };
})(jQuery, Drupal); })(jQuery, Drupal);
...@@ -4,25 +4,37 @@ ...@@ -4,25 +4,37 @@
*/ */
(function ($, Drupal, once) { (function ($, Drupal, once) {
"use strict";
Drupal.behaviors.tocTypeOptions = {
attach: function (context) {
$(once('.js-toc-type-options-header-min, .js-toc-type-options-header-max', context)).change(toggleHeaders);
}
};
toggleHeaders();
function toggleHeaders() { function toggleHeaders() {
var min = $('.js-toc-type-options-header-min').val(); const min = parseInt(
var max = $('.js-toc-type-options-header-max').val(); document.querySelector('.js-toc-type-options-header-min')?.value || 1,
10,
);
const max = parseInt(
document.querySelector('.js-toc-type-options-header-max')?.value || 6,
10,
);
for (var i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
// Having to use the id instead of $('.js-toc-type-options-header-h' + i). const $header = $(`details[id$="-headers-h${i}"]`);
var $header = $('details[id$="-headers-h' + i + '"]'); if (i >= min && i <= max) {
(i >= min && i <= max) ? $header.show() : $header.hide(); $header.show();
} else {
$header.hide();
}
} }
} }
Drupal.behaviors.tocTypeOptions = {
attach(context) {
once(
'toc-type-header-change',
'.js-toc-type-options-header-min, .js-toc-type-options-header-max',
context,
).forEach((el) => {
el.addEventListener('change', toggleHeaders);
});
toggleHeaders();
},
};
})(jQuery, Drupal, once); })(jQuery, Drupal, once);
...@@ -2,6 +2,6 @@ name: 'TOC API example' ...@@ -2,6 +2,6 @@ name: 'TOC API example'
type: module type: module
description: 'Example of a custom implementation of the TOC API that adds a table of contents to specified content types.' description: 'Example of a custom implementation of the TOC API that adds a table of contents to specified content types.'
package: 'Example modules' package: 'Example modules'
core_version_requirement: ^9.4 || ^10.0 core_version_requirement: ^9.5 || ^10.2 || ^11.0
dependencies: dependencies:
- toc_api:toc_api - toc_api:toc_api
...@@ -2,24 +2,25 @@ ...@@ -2,24 +2,25 @@
/** /**
* @file * @file
* Example of a custom implementation of the TOC API that adds a table of contents to specified content types. * Example of a custom implementation of the TOC API.
*/ */
use Drupal\node\NodeInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\node\NodeInterface;
use Drupal\toc_api\Entity\TocType; use Drupal\toc_api\Entity\TocType;
/** /**
* Implements hook_node_view(). * Implements hook_node_view().
*/ */
function toc_api_example_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) { function toc_api_example_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, string $view_mode): void {
// Add TOC to 'page' and 'article' content types that are being viewed as a full (page) with a body field. // Add TOC to 'page' and 'article' content types that are being viewed as a
// full (page) with a body field.
if (in_array($node->getType(), ['page', 'article']) && $view_mode == 'full' && isset($build['body'][0])) { if (in_array($node->getType(), ['page', 'article']) && $view_mode == 'full' && isset($build['body'][0])) {
// Get the completely render (and filtered) body value. // Get the completely render (and filtered) body value.
$body = (string) \Drupal::service('renderer')->render($build['body'][0]); $body = (string) \Drupal::service('renderer')->render($build['body'][0]);
// Get 'default' TOC type options. // Get 'default' TOC type options.
/** @var \Drupal\toc_api\TocTypeInterface $toc_type */ /** @var \Drupal\toc_api\TocTypeInterface|null $toc_type */
$toc_type = TocType::load('default'); $toc_type = TocType::load('default');
$options = ($toc_type) ? $toc_type->getOptions() : []; $options = ($toc_type) ? $toc_type->getOptions() : [];
......
parameters:
level: 6
ignoreErrors:
- identifier: missingType.iterableValue
...@@ -64,9 +64,9 @@ class TocType extends ConfigEntityBase implements TocTypeInterface { ...@@ -64,9 +64,9 @@ class TocType extends ConfigEntityBase implements TocTypeInterface {
/** /**
* The TOC type options. * The TOC type options.
* *
* @var array * @var array|null
*/ */
protected $options; protected $options = NULL;
/** /**
* {@inheritdoc} * {@inheritdoc}
......
...@@ -3,15 +3,19 @@ ...@@ -3,15 +3,19 @@
namespace Drupal\toc_api\Plugin\Block; namespace Drupal\toc_api\Plugin\Block;
use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\toc_api\TocInterface;
use Drupal\toc_api\TocManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* Provides a base TOC block which displays the current TOC module's TOC in a * Provides a base block which displays the current TOC module's TOC in a block.
* block.
*/ */
abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginInterface { abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginInterface {
...@@ -20,7 +24,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -20,7 +24,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* *
* @var \Drupal\Core\Routing\RouteMatchInterface * @var \Drupal\Core\Routing\RouteMatchInterface
*/ */
protected $routeMatch; protected RouteMatchInterface $routeMatch;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The TOC manager.
*
* @var \Drupal\toc_api\TocManagerInterface
*/
protected TocManagerInterface $tocManager;
/** /**
* Creates a LocalActionsBlock instance. * Creates a LocalActionsBlock instance.
...@@ -33,34 +51,38 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -33,34 +51,38 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* The plugin implementation definition. * The plugin implementation definition.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match. * The route match.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\toc_api\TocManagerInterface $toc_manager
* The TOC manager.
*/ */
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { final public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager, TocManagerInterface $toc_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition); parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->routeMatch = $route_match; $this->routeMatch = $route_match;
$this->entityTypeManager = $entity_type_manager;
$this->tocManager = $toc_manager;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static( return new static(
$configuration, $configuration,
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$container->get('current_route_match') $container->get('current_route_match'),
$container->get('entity_type.manager'),
$container->get('toc_api.manager')
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function build() { public function build(): array {
$toc = $this->getCurrentToc(); $toc = $this->getCurrentToc();
if (empty($toc)) {
return [];
}
// Build the TOC. // Build the TOC.
$options = $toc->getOptions(); $options = $toc->getOptions();
$build = [ $build = [
...@@ -82,12 +104,9 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -82,12 +104,9 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* @return \Drupal\toc_api\TocInterface * @return \Drupal\toc_api\TocInterface
* A TOC object. * A TOC object.
*/ */
protected function getCurrentToc() { protected function getCurrentToc(): TocInterface {
/** @var \Drupal\toc_api\TocManagerInterface $toc_manager */
$toc_manager = \Drupal::service('toc_api.manager');
// Get the new TOC instance using the module name. // Get the new TOC instance using the module name.
return $toc_manager->getToc($this->getCurrentTocId()); return $this->tocManager->getToc($this->getCurrentTocId());
} }
/** /**
...@@ -99,21 +118,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -99,21 +118,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* @return string * @return string
* The current TOC block's plugin ID. * The current TOC block's plugin ID.
*/ */
protected function getCurrentTocId() { protected function getCurrentTocId(): string {
return $this->pluginId; return $this->pluginId;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getCacheContexts() { public function getCacheContexts(): array {
return ['route']; return ['route'];
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getCacheTags() { public function getCacheTags(): array {
$node = $this->getCurrentNode(); $node = $this->getCurrentNode();
return ($node) ? ['node:' . $node->id()] : []; return ($node) ? ['node:' . $node->id()] : [];
} }
...@@ -122,14 +141,15 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -122,14 +141,15 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* Load the node associated with the current request. * Load the node associated with the current request.
* *
* @return \Drupal\node\NodeInterface|null * @return \Drupal\node\NodeInterface|null
* A node entity, or NULL if no node is not found. * A node entity, or NULL if no node is found.
*/ */
protected function getCurrentNode() { protected function getCurrentNode(): ?NodeInterface {
switch ($this->routeMatch->getRouteName()) { switch ($this->routeMatch->getRouteName()) {
// Look at the request's node revision. // Look at the request's node revision.
case 'node.revision_show': case 'node.revision_show':
return node_revision_load($this->routeMatch $node_storage = $this->entityTypeManager->getStorage('node');
->getParameter('node_revision')); $node = $node_storage->loadRevision($this->routeMatch->getParameter('node_revision'));
return ($node instanceof NodeInterface) ? $node : NULL;
// Look at the request's node preview. // Look at the request's node preview.
case 'entity.node.preview': case 'entity.node.preview':
...@@ -146,14 +166,10 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI ...@@ -146,14 +166,10 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function blockAccess(AccountInterface $account) { protected function blockAccess(AccountInterface $account): AccessResultInterface {
$this->getCurrentTocId();
/** @var \Drupal\toc_api\TocManagerInterface $toc_manager */
$toc_manager = \Drupal::service('toc_api.manager');
// Get the new TOC instance and see if it is visible and should be // Get the new TOC instance and see if it is visible and should be
// displayed in a block. // displayed in a block.
$toc = $toc_manager->getToc($this->getCurrentTocId()); $toc = $this->tocManager->getToc($this->getCurrentTocId());
if (!$toc || !$toc->isVisible() || !$toc->isBlock()) { if (!$toc || !$toc->isVisible() || !$toc->isBlock()) {
return AccessResult::forbidden(); return AccessResult::forbidden();
......
...@@ -72,9 +72,9 @@ class Toc implements TocInterface { ...@@ -72,9 +72,9 @@ class Toc implements TocInterface {
/** /**
* The number of root headers found in the content. * The number of root headers found in the content.
* *
* @var int * @var int|null
*/ */
protected $headerCount; protected $headerCount = NULL;
/** /**
* The source content with unique header ids. * The source content with unique header ids.
...@@ -100,9 +100,9 @@ class Toc implements TocInterface { ...@@ -100,9 +100,9 @@ class Toc implements TocInterface {
/** /**
* The toc represent as a tree. * The toc represent as a tree.
* *
* @var array * @var array|null
*/ */
protected $tree; protected $tree = NULL;
/** /**
* Existing in the source content IDs. * Existing in the source content IDs.
...@@ -192,16 +192,12 @@ class Toc implements TocInterface { ...@@ -192,16 +192,12 @@ class Toc implements TocInterface {
$this->allowedTags = $this->formatter()->convertAllowedTagsToArray($this->options['header_allowed_tags']); $this->allowedTags = $this->formatter()->convertAllowedTagsToArray($this->options['header_allowed_tags']);
$this->initialize(); $this->initialize();
// DEBUG:
// dsm($this->getIndex());
// dsm($this->getTree());
} }
/** /**
* Initializes the table of content index and ensure unique header ids. * Initializes the table of content index and ensure unique header ids.
*/ */
protected function initialize() { protected function initialize(): void {
$this->index = []; $this->index = [];
// Setup an empty array of keys to track the index's keys. // Setup an empty array of keys to track the index's keys.
...@@ -340,7 +336,7 @@ class Toc implements TocInterface { ...@@ -340,7 +336,7 @@ class Toc implements TocInterface {
'#markup' => $header_html, '#markup' => $header_html,
'#allowed_tags' => $this->getAllowedTags(), '#allowed_tags' => $this->getAllowedTags(),
], ],
'url' => Url::fromRoute('<none>', NULL, [ 'url' => Url::fromRoute('<none>', [], [
'fragment' => $header_id, 'fragment' => $header_id,
]), ]),
]; ];
...@@ -356,6 +352,7 @@ class Toc implements TocInterface { ...@@ -356,6 +352,7 @@ class Toc implements TocInterface {
* The TOC formatter * The TOC formatter
*/ */
protected function formatter() { protected function formatter() {
// @phpstan-ignore-next-line
return \Drupal::service('toc_api.formatter'); return \Drupal::service('toc_api.formatter');
} }
...@@ -398,7 +395,8 @@ class Toc implements TocInterface { ...@@ -398,7 +395,8 @@ class Toc implements TocInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getHeaderCount() { public function getHeaderCount() {
if (!isset($this->headerCount)) { if ($this->headerCount === NULL) {
$this->headerCount = 0;
foreach ($this->index as $item) { foreach ($this->index as $item) {
if (empty($item['parent'])) { if (empty($item['parent'])) {
$this->headerCount++; $this->headerCount++;
...@@ -419,7 +417,7 @@ class Toc implements TocInterface { ...@@ -419,7 +417,7 @@ class Toc implements TocInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getTree() { public function getTree() {
if (!isset($this->tree)) { if ($this->tree === NULL) {
$this->tree = [ $this->tree = [
'title' => $this->options['title'], 'title' => $this->options['title'],
]; ];
...@@ -445,7 +443,7 @@ class Toc implements TocInterface { ...@@ -445,7 +443,7 @@ class Toc implements TocInterface {
* @param array $children * @param array $children
* An array of keys to be associative to the parent header item. * An array of keys to be associative to the parent header item.
*/ */
protected function buildTree(array &$item, array $children) { protected function buildTree(array &$item, array $children): void {
$item['below_type'] = ''; $item['below_type'] = '';
$item['below'] = []; $item['below'] = [];
foreach ($children as $key) { foreach ($children as $key) {
...@@ -498,8 +496,6 @@ class Toc implements TocInterface { ...@@ -498,8 +496,6 @@ class Toc implements TocInterface {
* *
* @param \DOMDocument $dom * @param \DOMDocument $dom
* DOM object. * DOM object.
*
* @return void
*/ */
protected function collectExistingIds(\DOMDocument $dom): void { protected function collectExistingIds(\DOMDocument $dom): void {
$xpath = new \DOMXPath($dom); $xpath = new \DOMXPath($dom);
...@@ -518,8 +514,6 @@ class Toc implements TocInterface { ...@@ -518,8 +514,6 @@ class Toc implements TocInterface {
* *
* @param \DOMDocument $dom * @param \DOMDocument $dom
* DOM object. * DOM object.
*
* @return void
*/ */
protected function useIdsOnly(\DOMDocument $dom): void { protected function useIdsOnly(\DOMDocument $dom): void {
$xpath = new \DOMXPath($dom); $xpath = new \DOMXPath($dom);
......
...@@ -4,11 +4,14 @@ namespace Drupal\toc_api; ...@@ -4,11 +4,14 @@ namespace Drupal\toc_api;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss; use Drupal\Component\Utility\Xss;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RendererInterface; use Drupal\Core\Render\RendererInterface;
/** /**
* Defines a service that builds and renders a table of contents and update an * Defines a service to build TOC.
* HTML document's headers. *
* This service builds and renders a table of contents and update an HTML
* document's headers.
*/ */
class TocBuilder implements TocBuilderInterface { class TocBuilder implements TocBuilderInterface {
...@@ -150,10 +153,13 @@ class TocBuilder implements TocBuilderInterface { ...@@ -150,10 +153,13 @@ class TocBuilder implements TocBuilderInterface {
*/ */
public function renderToc(TocInterface $toc) { public function renderToc(TocInterface $toc) {
if (!$toc->isVisible()) { if (!$toc->isVisible()) {
return ''; return Markup::create('');
} }
$build = $this->buildToc($toc); $build = $this->buildToc($toc);
if (empty($build)) {
return Markup::create('');
}
return $this->renderer->render($build); return $this->renderer->render($build);
} }
......
...@@ -26,8 +26,8 @@ interface TocBuilderInterface { ...@@ -26,8 +26,8 @@ interface TocBuilderInterface {
* A TOC object. * A TOC object.
* *
* @return array * @return array
* A render array containing the table of content's body content with bookmarked, typed, and custom * A render array containing the table of content's body content with
* headers with back to top links. * bookmarked, typed, and custom headers with back to top links.
*/ */
public function buildContent(TocInterface $toc); public function buildContent(TocInterface $toc);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Drupal\toc_api; namespace Drupal\toc_api;
/** /**
* Defines a service for formatting a table of content's headers, numbering, and ids.. * Defines a service for formatting a TOC headers, numbering, and ids.
*/ */
class TocFormatter implements TocFormatterInterface { class TocFormatter implements TocFormatterInterface {
...@@ -12,7 +12,90 @@ class TocFormatter implements TocFormatterInterface { ...@@ -12,7 +12,90 @@ class TocFormatter implements TocFormatterInterface {
*/ */
public function convertStringToId($text) { public function convertStringToId($text) {
// Replace accents with their counterparts. // Replace accents with their counterparts.
$text = strtr($text, ['Š' => 'S', 'š' => 's', 'Đ' => 'Dj', 'đ' => 'dj', 'Ž' => 'Z', 'ž' => 'z', 'Č' => 'C', 'č' => 'c', 'Ć' => 'C', 'ć' => 'c', 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'A', 'Ç' => 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ý' => 'Y', 'Þ' => 'B', 'ß' => 'Ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'o', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'þ' => 'b', 'ÿ' => 'y', 'Ŕ' => 'R', 'ŕ' => 'r', 'Ā' => 'A', 'Ē' => 'E', 'Ī' => 'I', 'Ō' => 'O', 'Ū' => 'U', 'ā' => 'a', 'ē' => 'e', 'ī' => 'i', 'ō' => 'o', 'ū' => 'u']); $text = strtr($text, [
'Š' => 'S',
'š' => 's',
'Đ' => 'Dj',
'đ' => 'dj',
'Ž' => 'Z',
'ž' => 'z',
'Č' => 'C',
'č' => 'c',
'Ć' => 'C',
'ć' => 'c',
'À' => 'A',
'Á' => 'A',
'Â' => 'A',
'Ã' => 'A',
'Ä' => 'A',
'Å' => 'A',
'Æ' => 'A',
'Ç' => 'C',
'È' => 'E',
'É' => 'E',
'Ê' => 'E',
'Ë' => 'E',
'Ì' => 'I',
'Í' => 'I',
'Î' => 'I',
'Ï' => 'I',
'Ñ' => 'N',
'Ò' => 'O',
'Ó' => 'O',
'Ô' => 'O',
'Õ' => 'O',
'Ö' => 'O',
'Ø' => 'O',
'Ù' => 'U',
'Ú' => 'U',
'Û' => 'U',
'Ü' => 'U',
'Ý' => 'Y',
'Þ' => 'B',
'ß' => 'Ss',
'à' => 'a',
'á' => 'a',
'â' => 'a',
'ã' => 'a',
'ä' => 'a',
'å' => 'a',
'æ' => 'a',
'ç' => 'c',
'è' => 'e',
'é' => 'e',
'ê' => 'e',
'ë' => 'e',
'ì' => 'i',
'í' => 'i',
'î' => 'i',
'ï' => 'i',
'ð' => 'o',
'ñ' => 'n',
'ò' => 'o',
'ó' => 'o',
'ô' => 'o',
'õ' => 'o',
'ö' => 'o',
'ø' => 'o',
'ù' => 'u',
'ú' => 'u',
'û' => 'u',
'ý' => 'y',
'þ' => 'b',
'ÿ' => 'y',
'Ŕ' => 'R',
'ŕ' => 'r',
'Ā' => 'A',
'Ē' => 'E',
'Ī' => 'I',
'Ō' => 'O',
'Ū' => 'U',
'ā' => 'a',
'ē' => 'e',
'ī' => 'i',
'ō' => 'o',
'ū' => 'u',
]);
// Lowercase. // Lowercase.
$text = strtolower($text); $text = strtolower($text);
...@@ -40,6 +123,10 @@ class TocFormatter implements TocFormatterInterface { ...@@ -40,6 +123,10 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function convertNumberToListTypeValue($number, $type) { public function convertNumberToListTypeValue($number, $type) {
if ($type === NULL) {
$type = '';
}
$case_func = NULL; $case_func = NULL;
// Check if type should upper or lower cased. // Check if type should upper or lower cased.
if (preg_match('/^(upper|lower)-(.+)$/', (string) $type, $match)) { if (preg_match('/^(upper|lower)-(.+)$/', (string) $type, $match)) {
...@@ -72,7 +159,21 @@ class TocFormatter implements TocFormatterInterface { ...@@ -72,7 +159,21 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function convertNumberToRomanNumeral($number) { public function convertNumberToRomanNumeral($number) {
$roman_numerals = ['M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1]; $roman_numerals = [
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1,
];
$result = ''; $result = '';
foreach ($roman_numerals as $roman_numeral => $roman_number) { foreach ($roman_numerals as $roman_numeral => $roman_number) {
$matches = intval($number / $roman_number); $matches = intval($number / $roman_number);
...@@ -86,7 +187,34 @@ class TocFormatter implements TocFormatterInterface { ...@@ -86,7 +187,34 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function convertNumberToLetter($number) { public function convertNumberToLetter($number) {
static $letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; static $letters = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
];
return $letters[(($number - 1) % 26)]; return $letters[(($number - 1) % 26)];
} }
......
...@@ -38,7 +38,7 @@ interface TocFormatterInterface { ...@@ -38,7 +38,7 @@ interface TocFormatterInterface {
* *
* @param int $number * @param int $number
* A number. * A number.
* @param string $type * @param string|null $type
* The HTML5 list-style-type. * The HTML5 list-style-type.
* *
* @return string * @return string
......
...@@ -50,7 +50,9 @@ interface TocInterface { ...@@ -50,7 +50,9 @@ interface TocInterface {
/** /**
* Returns a hierarchical array of headers. * Returns a hierarchical array of headers.
* *
* @return array * @todo update the description text.
*
* @return int
* An hierarchical array of headers. * An hierarchical array of headers.
*/ */
public function getHeaderCount(); public function getHeaderCount();
......
...@@ -38,10 +38,11 @@ class TocManager implements TocManagerInterface { ...@@ -38,10 +38,11 @@ class TocManager implements TocManagerInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function create($id, $source, array $options = []) { public function create(string $id, string $source, array $options = []): TocInterface {
// Merge default TOC type options with passed options. // Merge default TOC type options with passed options.
/** @var \Drupal\toc_api\TocTypeInterface $default_toc */ /** @var \Drupal\toc_api\TocTypeInterface|null $default_toc */
if ($default_toc = TocType::load('default')) { $default_toc = TocType::load('default');
if ($default_toc !== NULL) {
$options = NestedArray::mergeDeep($default_toc->getOptions(), $options); $options = NestedArray::mergeDeep($default_toc->getOptions(), $options);
} }
...@@ -53,14 +54,14 @@ class TocManager implements TocManagerInterface { ...@@ -53,14 +54,14 @@ class TocManager implements TocManagerInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getToc($id) { public function getToc(string $id): ?TocInterface {
return (isset($this->tocs[$id])) ? $this->tocs[$id] : NULL; return (isset($this->tocs[$id])) ? $this->tocs[$id] : NULL;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function reset($id = NULL) { public function reset(?string $id = NULL): void {
if ($id === NULL) { if ($id === NULL) {
$this->tocs = []; $this->tocs = [];
} }
......
...@@ -23,7 +23,7 @@ interface TocManagerInterface { ...@@ -23,7 +23,7 @@ interface TocManagerInterface {
* @return \Drupal\toc_api\TocInterface * @return \Drupal\toc_api\TocInterface
* A new TOC object. * A new TOC object.
*/ */
public function create($id, $source, array $options = []); public function create(string $id, string $source, array $options = []): TocInterface;
/** /**
* Get the current TOC instance. * Get the current TOC instance.
...@@ -32,10 +32,10 @@ interface TocManagerInterface { ...@@ -32,10 +32,10 @@ interface TocManagerInterface {
* ID used to track the TOC object's instance. Typically, the ID can be * ID used to track the TOC object's instance. Typically, the ID can be
* the TOC implementation's module name. * the TOC implementation's module name.
* *
* @return \Drupal\toc_api\TocInterface * @return \Drupal\toc_api\TocInterface|null
* The current TOC instance. * The current TOC instance.
*/ */
public function getToc($id); public function getToc(string $id): ?TocInterface;
/** /**
* Reset the current TOC instance. * Reset the current TOC instance.
...@@ -44,6 +44,6 @@ interface TocManagerInterface { ...@@ -44,6 +44,6 @@ interface TocManagerInterface {
* ID used to track the TOC object's instance. Typically, the ID can be * ID used to track the TOC object's instance. Typically, the ID can be
* the TOC implementation's module name. * the TOC implementation's module name.
*/ */
public function reset($id = NULL); public function reset(?string $id = NULL): void;
} }
...@@ -48,13 +48,14 @@ class TocTypeForm extends EntityForm { ...@@ -48,13 +48,14 @@ class TocTypeForm extends EntityForm {
* *
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity query factory. * The entity query factory.
*
* @param \Drupal\Core\Theme\Registry $theme_registry * @param \Drupal\Core\Theme\Registry $theme_registry
* The theme registry. * The theme registry.
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
* The theme manager. * The theme manager.
* @param \Drupal\Core\Theme\ThemeInitializationInterface $theme_initialization
* The theme initialization logic.
*/ */
public function __construct(EntityTypeManagerInterface $entity_type_manager, Registry $theme_registry, ThemeManagerInterface $theme_manager, ThemeInitializationInterface $theme_initialization) { final public function __construct(EntityTypeManagerInterface $entity_type_manager, Registry $theme_registry, ThemeManagerInterface $theme_manager, ThemeInitializationInterface $theme_initialization) {
$this->entityTypeManager = $entity_type_manager; $this->entityTypeManager = $entity_type_manager;
$this->themeRegistry = $theme_registry; $this->themeRegistry = $theme_registry;
$this->themeManager = $theme_manager; $this->themeManager = $theme_manager;
...@@ -64,7 +65,7 @@ class TocTypeForm extends EntityForm { ...@@ -64,7 +65,7 @@ class TocTypeForm extends EntityForm {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container): static {
return new static( return new static(
$container->get('entity_type.manager'), $container->get('entity_type.manager'),
$container->get('theme.registry'), $container->get('theme.registry'),
...@@ -78,6 +79,9 @@ class TocTypeForm extends EntityForm { ...@@ -78,6 +79,9 @@ class TocTypeForm extends EntityForm {
*/ */
public function buildForm(array $form, FormStateInterface $form_state) { public function buildForm(array $form, FormStateInterface $form_state) {
$toc_type = $this->entity; $toc_type = $this->entity;
if (!($toc_type instanceof TocTypeInterface)) {
return $form;
}
$options = $toc_type->getOptions(); $options = $toc_type->getOptions();
// An associative array of HTML header tags keyed by level. // An associative array of HTML header tags keyed by level.
...@@ -309,8 +313,7 @@ class TocTypeForm extends EntityForm { ...@@ -309,8 +313,7 @@ class TocTypeForm extends EntityForm {
$form['options']['numbering']['headers'][$header_tag]['custom'] = [ $form['options']['numbering']['headers'][$header_tag]['custom'] = [
'#title' => $this->t('Customize @tag numbering', [ '#title' => $this->t('Customize @tag numbering', [
'@tag' => $header_tag, '@tag' => $header_tag,
] ]),
),
'#type' => 'checkbox', '#type' => 'checkbox',
'#default_value' => $header_options['custom'], '#default_value' => $header_options['custom'],
'#attributes' => ['class' => ["js-toc-type-options-headers-$header_tag-custom"]], '#attributes' => ['class' => ["js-toc-type-options-headers-$header_tag-custom"]],
...@@ -367,7 +370,7 @@ class TocTypeForm extends EntityForm { ...@@ -367,7 +370,7 @@ class TocTypeForm extends EntityForm {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function submitForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state): void {
$values = $form_state->getValues(); $values = $form_state->getValues();
$options = $values['general'] + $values['header'] + $values['top'] + $values['numbering']; $options = $values['general'] + $values['header'] + $values['top'] + $values['numbering'];
...@@ -405,6 +408,7 @@ class TocTypeForm extends EntityForm { ...@@ -405,6 +408,7 @@ class TocTypeForm extends EntityForm {
$this->messenger()->addMessage($this->t('Table of contents type %label saved.', ['%label' => $toc_type->label()])); $this->messenger()->addMessage($this->t('Table of contents type %label saved.', ['%label' => $toc_type->label()]));
$form_state->setRedirect('entity.toc_type.collection'); $form_state->setRedirect('entity.toc_type.collection');
return parent::save($form, $form_state);
} }
/** /**
...@@ -418,13 +422,12 @@ class TocTypeForm extends EntityForm { ...@@ -418,13 +422,12 @@ class TocTypeForm extends EntityForm {
*/ */
public function exists($id) { public function exists($id) {
return (bool) $this->entityTypeManager return (bool) $this->entityTypeManager
->get('toc_type') ->getStorage('toc_type')
->condition('id', $id) ->load($id);
->execute();
} }
/** /**
* Get TOC templates from the theme registry for the default theme as an associative array of options. * Get TOC templates from the theme registry for the default theme.
* *
* @return array * @return array
* TOC templates as an associative array of options. * TOC templates as an associative array of options.
......
...@@ -26,6 +26,9 @@ class TocTypeListBuilder extends ConfigEntityListBuilder { ...@@ -26,6 +26,9 @@ class TocTypeListBuilder extends ConfigEntityListBuilder {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function buildRow(EntityInterface $entity) { public function buildRow(EntityInterface $entity) {
if (!($entity instanceof TocTypeInterface)) {
return parent::buildRow($entity);
}
$options = $entity->getOptions(); $options = $entity->getOptions();
$row['label'] = $entity->label(); $row['label'] = $entity->label();
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* - index: List of header items. Each header item contains: * - index: List of header items. Each header item contains:
* - prefix: The header option prefix. Either indentation or the complete path. * - prefix: The header option prefix. Either indentation or the complete path.
* - title: The header title. * - title: The header title.
* - url: The header fragrment (ie hash) URL, instance of \Drupal\Core\Url. * - url: The header fragment (ie hash) URL, instance of \Drupal\Core\Url.
* *
* @ingroup themeable * @ingroup themeable
*/ */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment