sector_long_form-1.0.x-dev/src/Plugin/Field/FieldFormatter/TocChunkerFormatter.php
src/Plugin/Field/FieldFormatter/TocChunkerFormatter.php
<?php
namespace Drupal\sector_long_form\Plugin\Field\FieldFormatter;
use Drupal\chunker\Plugin\Field\FieldFormatter\ChunkerFormatter;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\toc_api\TocBuilderInterface;
use Drupal\toc_api\TocManagerInterface;
/**
* Plugin implementation of the 'ToC Chunker' formatter.
*
* Divide long HTML content into sections based on h2 headings.
* Runs ToC content before chunking, to get ids assigned to headings.
*
* @FieldFormatter(
* id = "toc_chunker",
* label = @Translation("ToC Chunker"),
* field_types = {
* "text_long",
* "text_with_summary"
* }
* )
*/
class TocChunkerFormatter extends ChunkerFormatter {
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The service that builds and renders a table of contents and update an HTML document's headers.
*
* @var \Drupal\toc_api\TocBuilderInterface
*/
protected $tocBuilder;
/**
* The service that creates and manages table of contents instances.
*
* @var \Drupal\toc_api\TocManagerInterface
*/
protected $tocManager;
/**
* The ToC type entity storage.
*
* @var \Drupal\toc_api\TocTypeInterface
*/
protected $tocStorage;
/**
* Constructs a TocChunkerFormatter object.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
* @param array $third_party_settings
* Any third party settings.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\toc_api\TocBuilderInterface $toc_builder
* The service that builds and renders a table of contents and update an HTML document's headers.
* @param \Drupal\toc_api\TocManagerInterface $toc_manager
* The service that creates and manages table of contents instances.
* @param \Drupal\Core\Entity\EntityStorageInterface $toc_storage
* The ToC type storage.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, RendererInterface $renderer, TocBuilderInterface $toc_builder, TocManagerInterface $toc_manager, EntityStorageInterface $toc_storage) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->renderer = $renderer;
$this->tocBuilder = $toc_builder;
$this->tocManager = $toc_manager;
$this->tocStorage = $toc_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('renderer'),
$container->get('toc_api.builder'),
$container->get('toc_api.manager'),
$container->get('entity_type.manager')->getStorage('toc_type')
);
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'toc_type' => 'default'
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state);
// Create options for the select field.
$options = [];
$all_toc_types = $this->tocStorage->loadMultiple();
foreach ($all_toc_types as $toc_machine_name => $toc_type) {
$options[$toc_machine_name] = $toc_type->label();
}
$form['toc_type'] = [
'#title' => $this->t('ToC type'),
'#description' => $this->t('Table of contents type machine name from ToC API'),
'#type' => 'select',
'#options' => $options,
'#required' => TRUE,
'#default_value' => $this->getSetting('toc_type'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
$summary[] = $this->t('ToC type: @toc_type', [
'@toc_type' => $this->getSetting('toc_type'),
]);
return $summary;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
$settings = $this->getSettings();
// Treat as for default formatter, but we chunk the HTML.
// The ProcessedText element already handles cache context & tag bubbling.
// @see \Drupal\filter\Element\ProcessedText::preRenderText()
foreach ($items as $delta => $item) {
$toc_type = $this->tocStorage->load($settings['toc_type']);
$options = ($toc_type) ? $toc_type->getOptions() : [];
// Create a TOC instance using the TOC manager.
$toc = $this->tocManager->create('sector_long_form', $item->value, $options);
// Build a TOC instance using the TOC builder.
$toc_content = $this->tocBuilder->buildContent($toc);
$toc_content_rendered = (string) $this->renderer->render($toc_content);
$elements[$delta] = [
'#type' => 'processed_text',
'#text' => $this->chunkText($toc_content_rendered, $settings),
'#format' => $item->format,
'#langcode' => $item->getLangcode(),
];
}
return $elements;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
$toc_type_id = $this->getSetting('toc_type');
if ($toc_type_id && $toc_type = $this->tocStorage->load($toc_type_id)) {
// If this formatter uses a valid toc type, add toc type configuration entity
// as dependency of this formatter.
$dependencies[$toc_type->getConfigDependencyKey()][] = $toc_type->getConfigDependencyName();
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
public function onDependencyRemoval(array $dependencies) {
$changed = parent::onDependencyRemoval($dependencies);
$toc_type_id = $this->getSetting('toc_type');
if ($toc_type_id && $toc_type = $this->tocStorage->load($toc_type_id)) {
if (!empty($dependencies[$toc_type->getConfigDependencyKey()][$toc_type->getConfigDependencyName()])) {
// Remove the currently used toc type from the formatter configuration.
$this->setSetting('toc_type', '');
$changed = TRUE;
}
}
return $changed;
}
}
