[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/textformatter/s9e/ -> bbcode_merger.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\textformatter\s9e;
  15  
  16  use phpbb\textformatter\s9e\factory;
  17  use s9e\TextFormatter\Configurator\Helpers\TemplateLoader;
  18  use s9e\TextFormatter\Configurator\Items\UnsafeTemplate;
  19  
  20  class bbcode_merger
  21  {
  22      /**
  23      * @var \s9e\TextFormatter\Configurator $configurator Configurator instance used to inspect BBCodes
  24      */
  25      protected $configurator;
  26  
  27      /**
  28      * @param factory $factory
  29      */
  30  	public function __construct(factory $factory)
  31      {
  32          $this->configurator = $factory->get_configurator();
  33      }
  34  
  35      /**
  36      * Merge two BBCode definitions
  37      *
  38      * All of the arrays contain a "usage" element and a "template" element
  39      *
  40      * @throws InvalidArgumentException if a definition cannot be interpreted
  41      * @throws RuntimeException if something unexpected occurs
  42      *
  43      * @param  array $without BBCode definition without an attribute
  44      * @param  array $with    BBCode definition with an attribute
  45      * @return array          Merged definition
  46      */
  47  	public function merge_bbcodes(array $without, array $with)
  48      {
  49          $without = $this->create_bbcode($without);
  50          $with    = $this->create_bbcode($with);
  51  
  52          // Select the appropriate strategy for merging this BBCode
  53          if (!$this->is_optional_bbcode($without, $with) && $this->is_content_bbcode($without, $with))
  54          {
  55              $merged = $this->merge_content_bbcode($without, $with);
  56          }
  57          else
  58          {
  59              $merged = $this->merge_optional_bbcode($without, $with);
  60          }
  61  
  62          $merged['template'] = $this->normalize_template($merged['template']);
  63  
  64          return $merged;
  65      }
  66  
  67      /**
  68      * Create a custom BBCode for inspection
  69      *
  70      * @param  array $definition Original BBCode definition
  71      * @return array             Updated definition containing a BBCode object and a Tag
  72      */
  73  	protected function create_bbcode(array $definition)
  74      {
  75          $bbcode = $this->configurator->BBCodes->addCustom(
  76              $definition['usage'],
  77              new UnsafeTemplate($definition['template'])
  78          );
  79  
  80          $definition['bbcode'] = $bbcode;
  81          $definition['tag']    = $this->configurator->tags[$bbcode->tagName];
  82  
  83          return $definition;
  84      }
  85  
  86      /**
  87      * Indent given template for readability
  88      *
  89      * @param  string $template
  90      * @return string
  91      */
  92  	protected function indent_template($template)
  93      {
  94          $dom = TemplateLoader::load($template);
  95          $dom->formatOutput = true;
  96          $template = TemplateLoader::save($dom);
  97  
  98          // Remove the first level of indentation if the template starts with whitespace
  99          if (preg_match('(^\\n +)', $template, $m))
 100          {
 101              $template = str_replace($m[0], "\n", $template);
 102          }
 103  
 104          return trim($template);
 105      }
 106  
 107      /**
 108      * Test whether the two definitions form a "content"-style BBCode
 109      *
 110      * Such BBCodes include the [url] BBCode, which uses its text content as
 111      * attribute if none is provided
 112      *
 113      * @param  array $without BBCode definition without an attribute
 114      * @param  array $with    BBCode definition with an attribute
 115      * @return bool
 116      */
 117  	protected function is_content_bbcode(array $without, array $with)
 118      {
 119          // Test whether we find the same non-TEXT token between "]" and "[" in the usage
 120          // as between ">" and "<" in the template
 121          return (preg_match('(\\]\\s*(\\{(?!TEXT)[^}]+\\})\\s*\\[)', $without['usage'], $m)
 122              && preg_match('(>[^<]*?' . preg_quote($m[1]) . '[^>]*?<)s', $without['template']));
 123      }
 124  
 125      /**
 126      * Test whether the two definitions form BBCode with an optional attribute
 127      *
 128      * @param  array $without BBCode definition without an attribute
 129      * @param  array $with    BBCode definition with an attribute
 130      * @return bool
 131      */
 132  	protected function is_optional_bbcode(array $without, array $with)
 133      {
 134          // Remove the default attribute from the definition
 135          $with['usage'] = preg_replace('(=[^\\]]++)', '', $with['usage']);
 136  
 137          // Test whether both definitions are the same, regardless of case
 138          return strcasecmp($without['usage'], $with['usage']) === 0;
 139      }
 140  
 141      /**
 142      * Merge the two BBCode definitions of a "content"-style BBCode
 143      *
 144      * @param  array $without BBCode definition without an attribute
 145      * @param  array $with    BBCode definition with an attribute
 146      * @return array          Merged definition
 147      */
 148  	protected function merge_content_bbcode(array $without, array $with)
 149      {
 150          // Convert [x={X}] into [x={X;useContent}]
 151          $usage = preg_replace('(\\})', ';useContent}', $with['usage'], 1);
 152  
 153          // Use the template from the definition that uses an attribute
 154          $template = $with['tag']->template;
 155  
 156          return ['usage' => $usage, 'template' => $template];
 157      }
 158  
 159      /**
 160      * Merge the two BBCode definitions of a BBCode with an optional argument
 161      *
 162      * Such BBCodes include the [quote] BBCode, which takes an optional argument
 163      * but otherwise does not behave differently
 164      *
 165      * @param  array $without BBCode definition without an attribute
 166      * @param  array $with    BBCode definition with an attribute
 167      * @return array          Merged definition
 168      */
 169  	protected function merge_optional_bbcode(array $without, array $with)
 170      {
 171          // Convert [X={X}] into [X={X?}]
 172          $usage = preg_replace('(\\})', '?}', $with['usage'], 1);
 173  
 174          // Build a template for both versions
 175          $template = '<xsl:choose><xsl:when test="@' . $with['bbcode']->defaultAttribute . '">' . $with['tag']->template . '</xsl:when><xsl:otherwise>' . $without['tag']->template . '</xsl:otherwise></xsl:choose>';
 176  
 177          return ['usage' => $usage, 'template' => $template];
 178      }
 179  
 180      /**
 181      * Normalize a template
 182      *
 183      * @param  string $template
 184      * @return string
 185      */
 186  	protected function normalize_template($template)
 187      {
 188          // Normalize the template to simplify it
 189          $template = $this->configurator->templateNormalizer->normalizeTemplate($template);
 190  
 191          // Convert xsl:value-of elements back to {L_} tokens where applicable
 192          $template = preg_replace('(<xsl:value-of select="\\$(L_\\w+)"/>)', '{$1}', $template);
 193  
 194          // Beautify the template
 195          $template = $this->indent_template($template);
 196  
 197          return $template;
 198      }
 199  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1