You are here

Tag.php in Extensible BBCode 8.3

Same filename and directory in other branches
  1. 4.0.x src/Entity/Tag.php

File

src/Entity/Tag.php
View source
<?php

namespace Drupal\xbbcode\Entity;

use Drupal;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;

/**
 * Represents a custom XBBCode tag that can be altered by administrators.
 *
 * @ConfigEntityType(
 *   id = "xbbcode_tag",
 *   label = @Translation("custom tag"),
 *   label_plural = @Translation("custom tags"),
 *   handlers = {
 *     "form" = {
 *       "add" = "Drupal\xbbcode\Form\TagForm",
 *       "edit" = "Drupal\xbbcode\Form\TagForm",
 *       "delete" = "Drupal\Core\Entity\EntityDeleteForm",
 *       "view" = "Drupal\xbbcode\Form\TagFormView",
 *       "copy" = "Drupal\xbbcode\Form\TagFormCopy"
 *     },
 *     "list_builder" = "Drupal\xbbcode\TagListBuilder",
 *     "access" = "Drupal\xbbcode\TagAccessHandler"
 *   },
 *   config_prefix = "tag",
 *   admin_permission = "administer custom BBCode tags",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "status" = "status"
 *   },
 *   links = {
 *     "edit-form" = "/admin/config/content/xbbcode/tags/manage/{xbbcode_tag}/edit",
 *     "delete-form" = "/admin/config/content/xbbcode/tags/manage/{xbbcode_tag}/delete",
 *     "view-form" = "/admin/config/content/xbbcode/tags/manage/{xbbcode_tag}/view",
 *     "copy-form" = "/admin/config/content/xbbcode/tags/manage/{xbbcode_tag}/copy",
 *     "collection" = "/admin/config/content/xbbcode/tags"
 *   },
 *   config_export = {
 *     "id",
 *     "label",
 *     "description",
 *     "sample",
 *     "name",
 *     "attached",
 *     "editable",
 *     "template_code",
 *     "template_file"
 *   }
 * )
 */
class Tag extends ConfigEntityBase implements TagInterface {

  /**
   * Description of the tag.
   *
   * @var string
   */
  protected $description;

  /**
   * Default tag name.
   *
   * @var string
   */
  protected $name;

  /**
   * Any attachments required to render this tag.
   *
   * @var array
   */
  protected $attached = [];

  /**
   * Sample code.
   *
   * @var string
   */
  protected $sample;

  /**
   * An inline Twig template.
   *
   * @var string
   */
  protected $template_code;

  /**
   * A Twig template file.
   *
   * @var string
   */
  protected $template_file;

  /**
   * Settings for this tag.
   *
   * @var array
   */
  protected $settings = [];

  /**
   * Whether the tag is editable by admins.
   *
   * This should be left off for tags defined by modules.
   *
   * @var bool
   */
  protected $editable = FALSE;

  /**
   * {@inheritdoc}
   */
  public function getDescription() : string {
    return $this->description ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getName() : string {
    return $this->name ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getSample() : string {
    return $this->sample ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getTemplateCode() : string {
    return $this->template_code ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getTemplateFile() : string {
    return $this->template_file ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getAttachments() : array {
    return $this->attached;
  }

  /**
   * {@inheritdoc}
   */
  public function isEditable() : bool {
    return $this->editable;
  }

  /**
   * {@inheritdoc}
   */
  public function getSettings() : array {
    return $this->settings;
  }

  /**
   * {@inheritdoc}
   */
  protected function invalidateTagsOnSave($update) : void {
    parent::invalidateTagsOnSave($update);

    // Rebuild the tag plugins.
    Drupal::service('plugin.manager.xbbcode')
      ->clearCachedDefinitions();

    // Filters can't tag their formats' cache, so invalidate it explicitly.
    if ($tags = $this
      ->filterFormatCacheTags()) {
      filter_formats_reset();
    }
    if (!$update) {

      // New tags affect all filters without a tag set.
      $tags['xbbcode_tag_new'] = 'xbbcode_tag_new';
    }
    if ($tags) {
      Cache::invalidateTags($tags);
    }
  }

  /**
   * {@inheritdoc}
   */
  protected static function invalidateTagsOnDelete(EntityTypeInterface $entity_type, array $entities) : void {

    /** @var \Drupal\xbbcode\Entity\Tag[] $entities */
    parent::invalidateTagsOnDelete($entity_type, $entities);
    $tags = [];
    foreach ($entities as $entity) {
      $tags += $entity
        ->filterFormatCacheTags();
    }
    if ($tags) {
      filter_formats_reset();
      Cache::invalidateTags($tags);
    }
  }

  /**
   * Get all formats that use this tag.
   *
   * @return \Drupal\filter\FilterFormatInterface[]
   *   An array of filter formats using a tag set where this tag is active.
   */
  protected function getFormats() : array {
    $formats = [];
    try {

      // Load all formats that use the BBCode filter.
      $storage = Drupal::entityTypeManager()
        ->getStorage('filter_format');
      $ids = $storage
        ->getQuery()
        ->condition('filters.xbbcode.status', TRUE)
        ->execute();

      /** @var \Drupal\filter\FilterFormatInterface $format */
      foreach ($storage
        ->loadMultiple($ids) as $id => $format) {
        $config = $format
          ->filters('xbbcode')
          ->getConfiguration();
        $tag_set_id = $config['settings']['tags'];

        // If it references an existing tag set without this tag, skip.
        if ($tag_set_id) {

          /** @var \Drupal\xbbcode\Entity\TagSetInterface $tag_set */
          $tag_set = TagSet::load($tag_set_id);
          if ($tag_set !== NULL && !$tag_set
            ->hasTag($this
            ->id())) {
            continue;
          }
        }

        // Otherwise, include it.
        $formats[$id] = $format;
      }
    } catch (InvalidPluginDefinitionException|PluginNotFoundException $exception) {

      // A broken filter_format entity type is beyond this module to handle.
      watchdog_exception('filter', $exception);
    }
    return $formats;
  }

  /**
   * Get the cache tags of all text formats that use this BBCode tag.
   *
   * @return string[]
   *   Array of cache tags.
   *
   * @internal
   */
  protected function filterFormatCacheTags() : array {
    if ($formats = $this
      ->getFormats()) {
      $tags = [
        'config:filter_format_list',
      ];
      foreach ($formats as $id => $format) {
        $tags[] = "config:filter_format:{$id}";
      }
      return array_combine($tags, $tags);
    }
    return [];
  }

}

Classes

Namesort descending Description
Tag Represents a custom XBBCode tag that can be altered by administrators.