Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
bbcode_merger.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb\textformatter\s9e;
015
016 use phpbb\textformatter\s9e\factory;
017 use s9e\TextFormatter\Configurator\Helpers\TemplateLoader;
018 use s9e\TextFormatter\Configurator\Items\UnsafeTemplate;
019
020 class bbcode_merger
021 {
022 /**
023 * @var \s9e\TextFormatter\Configurator $configurator Configurator instance used to inspect BBCodes
024 */
025 protected $configurator;
026
027 /**
028 * @param factory $factory
029 */
030 public function __construct(factory $factory)
031 {
032 $this->configurator = $factory->get_configurator();
033 }
034
035 /**
036 * Merge two BBCode definitions
037 *
038 * All of the arrays contain a "usage" element and a "template" element
039 *
040 * @throws InvalidArgumentException if a definition cannot be interpreted
041 * @throws RuntimeException if something unexpected occurs
042 *
043 * @param array $without BBCode definition without an attribute
044 * @param array $with BBCode definition with an attribute
045 * @return array Merged definition
046 */
047 public function merge_bbcodes(array $without, array $with)
048 {
049 $without = $this->create_bbcode($without);
050 $with = $this->create_bbcode($with);
051
052 // Select the appropriate strategy for merging this BBCode
053 if (!$this->is_optional_bbcode($without, $with) && $this->is_content_bbcode($without, $with))
054 {
055 $merged = $this->merge_content_bbcode($without, $with);
056 }
057 else
058 {
059 $merged = $this->merge_optional_bbcode($without, $with);
060 }
061
062 $merged['template'] = $this->normalize_template($merged['template']);
063
064 return $merged;
065 }
066
067 /**
068 * Create a custom BBCode for inspection
069 *
070 * @param array $definition Original BBCode definition
071 * @return array Updated definition containing a BBCode object and a Tag
072 */
073 protected function create_bbcode(array $definition)
074 {
075 $bbcode = $this->configurator->BBCodes->addCustom(
076 $definition['usage'],
077 new UnsafeTemplate($definition['template'])
078 );
079
080 $definition['bbcode'] = $bbcode;
081 $definition['tag'] = $this->configurator->tags[$bbcode->tagName];
082
083 return $definition;
084 }
085
086 /**
087 * Indent given template for readability
088 *
089 * @param string $template
090 * @return string
091 */
092 protected function indent_template($template)
093 {
094 $dom = TemplateLoader::load($template);
095 $dom->formatOutput = true;
096 $template = TemplateLoader::save($dom);
097
098 // Remove the first level of indentation if the template starts with whitespace
099 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 }
200