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 |
PHP.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Renderers;
009
010 use DOMNode;
011 use DOMXPath;
012 use RuntimeException;
013 use s9e\TextFormatter\Renderer;
014 use s9e\TextFormatter\Utils\XPath;
015
016 abstract class PHP extends Renderer
017 {
018 /**
019 * @var array[] Stack of dictionaries used by the Quick renderer [[attrName => attrValue]]
020 */
021 protected $attributes;
022
023 /**
024 * @var array Dictionary of replacements used by the Quick renderer [id => [match, replace]]
025 */
026 protected $dynamic;
027
028 /**
029 * @var bool Whether to enable the Quick renderer
030 */
031 public $enableQuickRenderer = false;
032
033 /**
034 * @var string Renderer's output
035 */
036 protected $out;
037
038 /**
039 * @var string Regexp that matches XML elements to be rendered by the quick renderer
040 */
041 protected $quickRegexp = '((?!))';
042
043 /**
044 * @var string Regexp that matches nodes that SHOULD NOT be rendered by the quick renderer
045 */
046 protected $quickRenderingTest = '((?<=<)[!?])';
047
048 /**
049 * @var array Dictionary of static replacements used by the Quick renderer [id => replacement]
050 */
051 protected $static;
052
053 /**
054 * @var DOMXPath XPath object used to query the document being rendered
055 */
056 protected $xpath;
057
058 /**
059 * Render given DOMNode
060 *
061 * @param DOMNode $node
062 * @return void
063 */
064 abstract protected function renderNode(DOMNode $node);
065
066 public function __sleep()
067 {
068 return ['enableQuickRenderer', 'params'];
069 }
070
071 /**
072 * Render the content of given node
073 *
074 * Matches the behaviour of an xsl:apply-templates element
075 *
076 * @param DOMNode $root Context node
077 * @param string $query XPath query used to filter which child nodes to render
078 * @return void
079 */
080 protected function at(DOMNode $root, $query = null)
081 {
082 if ($root->nodeType === XML_TEXT_NODE)
083 {
084 // Text nodes are outputted directly
085 $this->out .= htmlspecialchars($root->textContent, ENT_NOQUOTES);
086 }
087 else
088 {
089 $nodes = (isset($query)) ? $this->xpath->query($query, $root) : $root->childNodes;
090 foreach ($nodes as $node)
091 {
092 $this->renderNode($node);
093 }
094 }
095 }
096
097 /**
098 * Test whether given XML can be rendered with the Quick renderer
099 *
100 * @param string $xml
101 * @return bool
102 */
103 protected function canQuickRender($xml)
104 {
105 return ($this->enableQuickRenderer && !preg_match($this->quickRenderingTest, $xml) && substr($xml, -4) === '</r>');
106 }
107
108 /**
109 * Ensure that a tag pair does not contain a start tag of itself
110 *
111 * Detects malformed matches such as <X><X></X>
112 *
113 * @param string $id
114 * @param string $xml
115 * @return void
116 */
117 protected function checkTagPairContent($id, $xml)
118 {
119 if (strpos($xml, '<' . $id, 1) !== false)
120 {
121 throw new RuntimeException;
122 }
123 }
124
125 /**
126 * Return a parameter's value as an XPath expression
127 *
128 * @param string $paramName
129 * @return string
130 */
131 protected function getParamAsXPath($paramName)
132 {
133 return (isset($this->params[$paramName])) ? XPath::export($this->params[$paramName]) : "''";
134 }
135
136 /**
137 * Extract the text content from given XML
138 *
139 * NOTE: numeric character entities are decoded beforehand, we don't need to decode them here
140 *
141 * @param string $xml Original XML
142 * @return string Text content, with special characters decoded
143 */
144 protected function getQuickTextContent($xml)
145 {
146 return htmlspecialchars_decode(strip_tags($xml));
147 }
148
149 /**
150 * Test whether given array has any non-null values
151 *
152 * @param array $array
153 * @return bool
154 */
155 protected function hasNonNullValues(array $array)
156 {
157 foreach ($array as $v)
158 {
159 if (isset($v))
160 {
161 return true;
162 }
163 }
164
165 return false;
166 }
167
168 /**
169 * Capture and return the attributes of an XML element
170 *
171 * NOTE: XML character entities are left as-is
172 *
173 * @param string $xml Element in XML form
174 * @return array Dictionary of [attrName => attrValue]
175 */
176 protected function matchAttributes($xml)
177 {
178 if (strpos($xml, '="') === false)
179 {
180 return [];
181 }
182
183 // Match all name-value pairs until the first right bracket
184 preg_match_all('(([^ =]++)="([^"]*))S', substr($xml, 0, strpos($xml, '>')), $m);
185
186 return array_combine($m[1], $m[2]);
187 }
188
189 /**
190 * Render an intermediate representation using the Quick renderer
191 *
192 * @param string $xml Intermediate representation
193 * @return string
194 */
195 protected function renderQuick($xml)
196 {
197 $this->attributes = [];
198 $xml = $this->decodeSMP($xml);
199 $html = preg_replace_callback(
200 $this->quickRegexp,
201 [$this, 'renderQuickCallback'],
202 substr($xml, 1 + strpos($xml, '>'), -4)
203 );
204
205 return str_replace('<br/>', '<br>', $html);
206 }
207
208 /**
209 * Render a string matched by the Quick renderer
210 *
211 * This stub should be overwritten by generated renderers
212 *
213 * @param string[] $m
214 * @return string
215 */
216 protected function renderQuickCallback(array $m)
217 {
218 if (isset($m[3]))
219 {
220 return $this->renderQuickSelfClosingTag($m);
221 }
222
223 if (isset($m[2]))
224 {
225 // Single tag
226 $id = $m[2];
227 }
228 else
229 {
230 // Tag pair
231 $id = $m[1];
232 $this->checkTagPairContent($id, $m[0]);
233 }
234
235 if (isset($this->static[$id]))
236 {
237 return $this->static[$id];
238 }
239 if (isset($this->dynamic[$id]))
240 {
241 return preg_replace($this->dynamic[$id][0], $this->dynamic[$id][1], $m[0], 1);
242 }
243
244 return $this->renderQuickTemplate($id, $m[0]);
245 }
246
247 /**
248 * Render a self-closing tag using the Quick renderer
249 *
250 * @param string[] $m
251 * @return string
252 */
253 protected function renderQuickSelfClosingTag(array $m)
254 {
255 unset($m[3]);
256
257 $m[0] = substr($m[0], 0, -2) . '>';
258 $html = $this->renderQuickCallback($m);
259
260 $m[0] = '</' . $m[2] . '>';
261 $m[2] = '/' . $m[2];
262 $html .= $this->renderQuickCallback($m);
263
264 return $html;
265 }
266
267 /**
268 * Render a string matched by the Quick renderer using a generated PHP template
269 *
270 * This stub should be overwritten by generated renderers
271 *
272 * @param integer $id Tag's ID (tag name optionally preceded by a slash)
273 * @param string $xml Tag's XML or tag pair's XML including their content
274 * @return string Rendered template
275 */
276 protected function renderQuickTemplate($id, $xml)
277 {
278 throw new RuntimeException('Not implemented');
279 }
280
281 /**
282 * {@inheritdoc}
283 */
284 protected function renderRichText($xml)
285 {
286 $this->setLocale();
287
288 try
289 {
290 if ($this->canQuickRender($xml))
291 {
292 $html = $this->renderQuick($xml);
293 $this->restoreLocale();
294
295 return $html;
296 }
297 }
298 catch (RuntimeException $e)
299 {
300 // Do nothing
301 }
302
303 $dom = $this->loadXML($xml);
304 $this->out = '';
305 $this->xpath = new DOMXPath($dom);
306 $this->at($dom->documentElement);
307 $html = $this->out;
308 $this->reset();
309 $this->restoreLocale();
310
311 return $html;
312 }
313
314 /**
315 * Reset object properties that are populated during rendering
316 *
317 * @return void
318 */
319 protected function reset()
320 {
321 unset($this->attributes);
322 unset($this->out);
323 unset($this->xpath);
324 }
325 }