You are here

class ListTagPlugin in Extensible BBCode 4.0.x

Same name and namespace in other branches
  1. 8.3 standard/src/Plugin/XBBCode/ListTagPlugin.php \Drupal\xbbcode_standard\Plugin\XBBCode\ListTagPlugin

Renders a list.

Plugin annotation


@XBBCodeTag(
  id = "list",
  label = @Translation("List"),
  description = @Translation("List with optional style."),
  name = "list",
)

Hierarchy

Expanded class hierarchy of ListTagPlugin

File

standard/src/Plugin/XBBCode/ListTagPlugin.php, line 22

Namespace

Drupal\xbbcode_standard\Plugin\XBBCode
View source
class ListTagPlugin extends RenderTagPlugin {
  use TreeEncodeTrait;

  /**
   * {@inheritdoc}
   */
  public function buildElement(TagElementInterface $tag) : array {
    $element['#theme'] = 'item_list';
    $style = $tag
      ->getOption() ?: $tag
      ->getAttribute('style');
    [
      $numbered,
      $style,
    ] = static::validateStyle($style);
    if ($numbered) {
      $element['#list_type'] = 'ol';
    }
    if ($style) {
      $element['#attributes']['style'] = 'list-style-type: ' . $style;
    }
    foreach (self::splitContent($tag
      ->getChildren()) as $i => $item) {
      $element['#items'][$i] = Markup::create($item
        ->getContent());
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultSample() : string {
    return $this
      ->t('[{{ name }}=lower-roman]
[*] One
[*] Two
[*] Three
[/{{ name }}]');
  }

  /**
   * Validate a style directive.
   *
   * @param string $style
   *   The user-entered style directive.
   *
   * @return array
   *   An array with two elements:
   *   - A boolean that is TRUE if the style is numbered, otherwise FALSE.
   *   - The style, if it is valid.
   */
  protected static function validateStyle(string $style) : array {

    // The predefined un-ordered styles.
    if (in_array($style, [
      'disc',
      'circle',
      'square',
      'none',
    ], TRUE)) {
      return [
        FALSE,
        $style,
      ];
    }

    // If the style contains no HTML characters, decode any character entities.
    if (!preg_match('/\'"<>/', $style)) {
      $style = Html::decodeEntities($style);
    }
    $style = trim($style);

    // Match any quoted string.
    if (preg_match('/
    (?\'quote\'[\'"])
      \\\\
      (?:
        [0-9a-fA-F]{1,6}  # 1-6 hex digits preceded by a backslash.
        |
        [^0-9a-fA-F]      # any other character preceded by a backslash.
      )
      |
      (?!\\k\'quote\')[^\\\\] # any permissible non-backslash character.
    \\k\'quote\'
    /x', $style)) {
      return [
        FALSE,
        $style,
      ];
    }

    // Match any expression.
    if (preg_match('/
    (?:
      [^"\';]             # anything other than quotes or semicolon.
      |
      \\\\
      (?:
        [0-9a-fA-F]{1,6}  # 1-6 hex digits preceded by a backslash.
        |
        [^0-9a-fA-F]      # any other character preceded by a backslash.
      )
      |
      (?\'quote\'[\'"])
        \\\\
        (?:
          [0-9a-fA-F]{1,6}  # 1-6 hex digits preceded by a backslash.
          |
          [^0-9a-fA-F]      # any other character preceded by a backslash.
        )
        |
        (?!\\k\'quote\')[^\\\\] # any permissible non-backslash character.
      \\k\'quote\'
    )*
    /x', $style)) {
      return [
        TRUE,
        $style,
      ];
    }
    return [
      FALSE,
      '',
    ];
  }

  /**
   * Split the tag's children into list items.
   *
   * Any instance of [*] in the top-level text will be used as a delimiter.
   *
   * @param \Drupal\xbbcode\Parser\Tree\ElementInterface[] $children
   *   The tag's child elements in the parse tree.
   *
   * @return \Drupal\xbbcode\Parser\Tree\NodeElementInterface[]
   *   A sequence of nodes, each containing a part of the parse tree.
   */
  protected static function splitContent(array $children) : array {
    [
      $token,
      $text,
    ] = static::encodeTree($children);

    // Trim, and strip linebreaks before newlines.
    $trimmed = preg_replace('/<br\\s*\\/?>\\n/', "\n", $text);
    $breaks = $trimmed !== $text;
    $text = trim($trimmed);

    // Split on [*] at the start of lines.
    $items = preg_split('/^\\s*\\[\\*]\\s*/m', $text);
    array_shift($items);
    foreach ($items as $i => $item) {
      $item = trim($item);
      if ($breaks) {
        $item = nl2br($item);
      }
      $items[$i] = static::decodeTree($item, $children, $token);
    }
    return $items;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 2
DependencySerializationTrait::__wakeup public function 2
ListTagPlugin::buildElement public function Build a render array from the tag. Overrides RenderTagPlugin::buildElement
ListTagPlugin::getDefaultSample public function Return the unprocessed sample code. Overrides TagPluginBase::getDefaultSample
ListTagPlugin::splitContent protected static function Split the tag's children into list items.
ListTagPlugin::validateStyle protected static function Validate a style directive.
MessengerTrait::$messenger protected property The messenger. 27
MessengerTrait::messenger public function Gets the messenger. 27
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 2
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
RenderTagPlugin::$renderer protected property The Drupal renderer.
RenderTagPlugin::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
RenderTagPlugin::doProcess public function Create the actual output. Overrides TagPluginBase::doProcess
RenderTagPlugin::__construct public function RenderTagPlugin constructor. Overrides TagPluginBase::__construct
StringTranslationTrait::$stringTranslation protected property The string translation service. 4
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TagPluginBase::$name protected property The configurable tag name.
TagPluginBase::$sample protected property The sample code of this tag.
TagPluginBase::$settings protected property The settings for this tag plugin.
TagPluginBase::$status protected property A Boolean indicating whether this tag is enabled.
TagPluginBase::defaultConfiguration public function Get default plugin configuration from definition.
TagPluginBase::getConfiguration public function Get the plugin configuration.
TagPluginBase::getDefaultName public function Returns the default tag name. Overrides TagPluginInterface::getDefaultName
TagPluginBase::getDescription public function Returns the administrative description for this tag plugin. Overrides TagPluginInterface::getDescription
TagPluginBase::getName public function Returns the configured name. Overrides TagPluginInterface::getName
TagPluginBase::getSample public function Return a sample tag for the filter tips. Overrides TagPluginInterface::getSample
TagPluginBase::label public function Returns the administrative label for this tag plugin. Overrides TagPluginInterface::label
TagPluginBase::prepare public function Transform an elements' content, to armor against other filters. Overrides TagPluginInterface::prepare 2
TagPluginBase::process public function Generate output from a tag element. Overrides TagPluginInterface::process
TagPluginBase::setConfiguration public function Set the plugin configuration after instancing.
TagPluginBase::status public function Returns the status of this tag plugin. Overrides TagPluginInterface::status
TreeEncodeTrait::decodeTree protected static function Decode a part of the encoded tree.
TreeEncodeTrait::encodeTree protected static function Concatenate the top-level text of the tree.