HelpTestTwigNodeVisitor.php

Same filename in other branches
  1. 10 core/modules/help/tests/modules/help_topics_twig_tester/src/HelpTestTwigNodeVisitor.php
  2. 11.x core/modules/help/tests/modules/help_topics_twig_tester/src/HelpTestTwigNodeVisitor.php

Namespace

Drupal\help_topics_twig_tester

File

core/modules/help_topics/tests/modules/help_topics_twig_tester/src/HelpTestTwigNodeVisitor.php

View source
<?php

namespace Drupal\help_topics_twig_tester;

use Drupal\Core\Template\TwigNodeTrans;
use Twig\Environment;
use Twig\Node\Node;
use Twig\Node\PrintNode;
use Twig\Node\SetNode;
use Twig\Node\TextNode;
use Twig\Node\Expression\AbstractExpression;
use Twig\NodeVisitor\AbstractNodeVisitor;

/**
 * Defines a Twig node visitor for testing help topics.
 *
 * See static::setStateValue() for information on the special processing
 * this class can do.
 */
class HelpTestTwigNodeVisitor extends AbstractNodeVisitor {
    
    /**
     * Delimiter placed around single translated chunks.
     */
    public const DELIMITER = 'Not Likely To Be Inside A Template';
    
    /**
     * Name used in \Drupal::state() for saving state information.
     */
    protected const STATE_NAME = 'help_test_twig_node_visitor';
    
    /**
     * {@inheritdoc}
     */
    protected function doEnterNode(Node $node, Environment $env) {
        return $node;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function doLeaveNode(Node $node, Environment $env) {
        $processing = static::getState();
        if (!$processing['manner']) {
            return $node;
        }
        // For all special processing, we want to remove variables, set statements,
        // and assorted Twig expression calls (if, do, etc.).
        if ($node instanceof SetNode || $node instanceof PrintNode || $node instanceof AbstractExpression) {
            return NULL;
        }
        if ($node instanceof TwigNodeTrans) {
            // Count the number of translated chunks.
            $this_chunk = $processing['chunk_count'] + 1;
            static::setStateValue('chunk_count', $this_chunk);
            if ($this_chunk > $processing['max_chunk']) {
                static::setStateValue('max_chunk', $this_chunk);
            }
            if ($processing['manner'] == 'remove_translated') {
                // Remove all translated text.
                return NULL;
            }
            elseif ($processing['manner'] == 'replace_translated') {
                // Replace with a dummy string.
                $node = new TextNode('dummy', 0);
            }
            elseif ($processing['manner'] == 'translated_chunk') {
                // Return the text only if it's the next chunk we're supposed to return.
                // Add a wrapper, because non-translated nodes will still be returned.
                if ($this_chunk == $processing['return_chunk']) {
                    return new TextNode(static::DELIMITER . $this->extractText($node) . static::DELIMITER, 0);
                }
                else {
                    return NULL;
                }
            }
        }
        if ($processing['manner'] == 'remove_translated' && $node instanceof TextNode) {
            // For this processing, we also want to remove all HTML tags and
            // whitespace from TextNodes.
            $text = $node->getAttribute('data');
            $text = strip_tags($text);
            $text = preg_replace('|\\s+|', '', $text);
            return new TextNode($text, 0);
        }
        return $node;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getPriority() {
        return -100;
    }
    
    /**
     * Extracts the text from a translated text object.
     *
     * @param \Drupal\Core\Template\TwigNodeTrans $node
     *   Translated text node.
     *
     * @return string
     *   Text in the node.
     */
    protected function extractText(TwigNodeTrans $node) {
        // Extract the singular/body and optional plural text from the
        // TwigNodeTrans object.
        $bodies = $node->getNode('body');
        if (!count($bodies)) {
            $bodies = [
                $bodies,
            ];
        }
        if ($node->hasNode('plural')) {
            $plural = $node->getNode('plural');
            if (!count($plural)) {
                $bodies[] = $plural;
            }
            else {
                foreach ($plural as $item) {
                    $bodies[] = $item;
                }
            }
        }
        // Extract the text from each component of the singular/plural strings.
        $text = '';
        foreach ($bodies as $body) {
            if ($body->hasAttribute('data')) {
                $text .= $body->getAttribute('data');
            }
        }
        return trim($text);
    }
    
    /**
     * Returns the state information.
     *
     * @return array
     *   The state information.
     */
    public static function getState() {
        return \Drupal::state()->get(static::STATE_NAME, [
            'manner' => 0,
        ]);
    }
    
    /**
     * Sets state information.
     *
     * @param string $key
     *   Key to set. Possible keys:
     *   - manner: Type of special processing to do when rendering. Values:
     *     - 0: No processing.
     *     - remove_translated: Remove all translated text, HTML tags, and
     *       whitespace.
     *     - replace_translated: Replace all translated text with dummy text.
     *     - translated_chunk: Remove all translated text except one designated
     *       chunk (see return_chunk below).
     *     - bare_body (or any other non-zero value): Remove variables, set
     *       statements, and Twig programming, but leave everything else intact.
     *   - chunk_count: Current index of translated chunks. Reset to -1 before
     *     each rendering run. (Used internally by this class.)
     *   - max_chunk: Maximum index of translated chunks. Reset to -1 before
     *     each rendering run.
     *   - return_chunk: Chunk index to keep intact for translated_chunk
     *     processing. All others are removed.
     * @param $value
     *   Value to set for $key.
     */
    public static function setStateValue(string $key, $value) {
        $state = \Drupal::state();
        $values = $state->get(static::STATE_NAME, [
            'manner' => 0,
        ]);
        $values[$key] = $value;
        $state->set(static::STATE_NAME, $values);
    }

}

Classes

Title Deprecated Summary
HelpTestTwigNodeVisitor Defines a Twig node visitor for testing help topics.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.