[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package s9e\TextFormatter 5 * @copyright Copyright (c) 2010-2022 The s9e authors 6 * @license http://www.opensource.org/licenses/mit-license.php The MIT License 7 */ 8 namespace s9e\TextFormatter\Renderers; 9 10 use DOMNode; 11 use DOMXPath; 12 use RuntimeException; 13 use s9e\TextFormatter\Renderer; 14 use s9e\TextFormatter\Utils\XPath; 15 16 abstract class PHP extends Renderer 17 { 18 /** 19 * @var array[] Stack of dictionaries used by the Quick renderer [[attrName => attrValue]] 20 */ 21 protected $attributes; 22 23 /** 24 * @var array Dictionary of replacements used by the Quick renderer [id => [match, replace]] 25 */ 26 protected $dynamic; 27 28 /** 29 * @var bool Whether to enable the Quick renderer 30 */ 31 public $enableQuickRenderer = false; 32 33 /** 34 * @var string Renderer's output 35 */ 36 protected $out; 37 38 /** 39 * @var string Regexp that matches XML elements to be rendered by the quick renderer 40 */ 41 protected $quickRegexp = '((?!))'; 42 43 /** 44 * @var string Regexp that matches nodes that SHOULD NOT be rendered by the quick renderer 45 */ 46 protected $quickRenderingTest = '((?<=<)[!?])'; 47 48 /** 49 * @var array Dictionary of static replacements used by the Quick renderer [id => replacement] 50 */ 51 protected $static; 52 53 /** 54 * @var DOMXPath XPath object used to query the document being rendered 55 */ 56 protected $xpath; 57 58 /** 59 * Render given DOMNode 60 * 61 * @param DOMNode $node 62 * @return void 63 */ 64 abstract protected function renderNode(DOMNode $node); 65 66 public function __sleep() 67 { 68 return ['enableQuickRenderer', 'params']; 69 } 70 71 /** 72 * Render the content of given node 73 * 74 * Matches the behaviour of an xsl:apply-templates element 75 * 76 * @param DOMNode $root Context node 77 * @param string $query XPath query used to filter which child nodes to render 78 * @return void 79 */ 80 protected function at(DOMNode $root, $query = null) 81 { 82 if ($root->nodeType === XML_TEXT_NODE) 83 { 84 // Text nodes are outputted directly 85 $this->out .= htmlspecialchars($root->textContent, ENT_NOQUOTES); 86 } 87 else 88 { 89 $nodes = (isset($query)) ? $this->xpath->query($query, $root) : $root->childNodes; 90 foreach ($nodes as $node) 91 { 92 $this->renderNode($node); 93 } 94 } 95 } 96 97 /** 98 * Test whether given XML can be rendered with the Quick renderer 99 * 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |