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 |
XPathConvertor.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\Configurator\RendererGenerators\PHP;
009
010 use RuntimeException;
011 use s9e\TextFormatter\Configurator\RecursiveParser;
012 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\BooleanFunctions;
013 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\BooleanOperators;
014 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Comparisons;
015 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Core;
016 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Math;
017 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\MultiByteStringManipulation;
018 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\PHP80Functions;
019 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\SingleByteStringFunctions;
020 use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\SingleByteStringManipulation;
021
022 class XPathConvertor
023 {
024 /**
025 * @var array Array of togglable PHP features ("mbstring" and "php80")
026 */
027 public $features;
028
029 /**
030 * @var RecursiveParser
031 */
032 protected $parser;
033
034 /**
035 * Constructor
036 */
037 public function __construct(RecursiveParser $parser = null)
038 {
039 $this->features = [
040 'mbstring' => extension_loaded('mbstring'),
041 'php80' => version_compare(PHP_VERSION, '8.0', '>=')
042 ];
043 if (isset($parser))
044 {
045 $this->parser = $parser;
046 }
047 }
048
049 /**
050 * Convert an XPath expression (used in a condition) into PHP code
051 *
052 * This method is similar to convertXPath() but it selectively replaces some simple conditions
053 * with the corresponding DOM method for performance reasons
054 *
055 * @param string $expr XPath expression
056 * @return string PHP code
057 */
058 public function convertCondition($expr)
059 {
060 // Replace @attr with boolean(@attr) in boolean expressions
061 $expr = preg_replace(
062 '((^|(?<!\\bboolean)\\(\\s*|\\b(?:and|or)\\s*)([\\(\\s]*)([$@][-\\w]+|@\\*)([\\)\\s]*)(?=$|\\s+(?:and|or)))',
063 '$1$2boolean($3)$4',
064 trim($expr)
065 );
066
067 // Replace not(boolean(@attr)) with not(@attr)
068 $expr = preg_replace(
069 '(not\\(boolean\\(([$@][-\\w]+)\\)\\))',
070 'not($1)',
071 $expr
072 );
073
074 try
075 {
076 return $this->getParser()->parse($expr)['value'];
077 }
078 catch (RuntimeException $e)
079 {
080 // Do nothing
081 }
082
083 // If the condition does not seem to contain a relational expression, or start with a
084 // function call, we wrap it inside of a boolean() call
085 if (!preg_match('([=<>]|\\bor\\b|\\band\\b|^[-\\w]+\\s*\\()', $expr))
086 {
087 $expr = 'boolean(' . $expr . ')';
088 }
089
090 return '$this->xpath->evaluate(' . $this->exportXPath($expr) . ',$node)';
091 }
092
093 /**
094 * Convert an XPath expression (used as value) into PHP code
095 *
096 * @param string $expr XPath expression
097 * @return string PHP code
098 */
099 public function convertXPath($expr)
100 {
101 $expr = trim($expr);
102 try
103 {
104 return $this->getParser()->parse($expr)['value'];
105 }
106 catch (RuntimeException $e)
107 {
108 // Do nothing
109 }
110
111 // Make sure the expression evaluates as a string
112 if (!preg_match('(^[-\\w]*s(?:late|pace|tring)[-\\w]*\\()', $expr))
113 {
114 $expr = 'string(' . $expr . ')';
115 }
116
117 return '$this->xpath->evaluate(' . $this->exportXPath($expr) . ',$node)';
118 }
119
120 /**
121 * Export an XPath expression as PHP with special consideration for XPath variables
122 *
123 * Will return PHP source representing the XPath expression, with special consideration for XPath
124 * variables which are returned as a method call to XPath::export()
125 *
126 * @param string $expr XPath expression
127 * @return string PHP representation of the expression
128 */
129 protected function exportXPath($expr)
130 {
131 $phpTokens = [];
132 foreach ($this->tokenizeXPathForExport($expr) as [$type, $content])
133 {
134 $methodName = 'exportXPath' . $type;
135 $phpTokens[] = $this->$methodName($content);
136 }
137
138 return implode('.', $phpTokens);
139 }
140
141 /**
142 * Convert a "current()" XPath expression to its PHP source representation
143 *
144 * @return string
145 */
146 protected function exportXPathCurrent()
147 {
148 return '$node->getNodePath()';
149 }
150
151 /**
152 * Convert a fragment of an XPath expression to its PHP source representation
153 *
154 * @param string $fragment
155 * @return string
156 */
157 protected function exportXPathFragment($fragment)
158 {
159 return var_export($fragment, true);
160 }
161
162 /**
163 * Convert an XSLT parameter to its PHP source representation
164 *
165 * @param string $param Parameter, including the leading $
166 * @return string
167 */
168 protected function exportXPathParam($param)
169 {
170 $paramName = ltrim($param, '$');
171
172 return '$this->getParamAsXPath(' . var_export($paramName, true) . ')';
173 }
174
175 /**
176 * Generate and return the a parser with the default set of matchers
177 *
178 * @return RecursiveParser
179 */
180 protected function getDefaultParser()
181 {
182 $parser = new RecursiveParser;
183 $matchers = [];
184 $matchers[] = new SingleByteStringFunctions($parser);
185 $matchers[] = new BooleanFunctions($parser);
186 $matchers[] = new BooleanOperators($parser);
187 $matchers[] = new Comparisons($parser);
188 $matchers[] = new Core($parser);
189 $matchers[] = new Math($parser);
190 if (!empty($this->features['mbstring']))
191 {
192 $matchers[] = new MultiByteStringManipulation($parser);
193 }
194 $matchers[] = new SingleByteStringManipulation($parser);
195 if (!empty($this->features['php80']))
196 {
197 $matchers[] = new PHP80Functions($parser);
198 }
199
200 $parser->setMatchers($matchers);
201
202 return $parser;
203 }
204
205 /**
206 * Return (and if necessary, create) the cached instance of the XPath parser
207 *
208 * @return RecursiveParser
209 */
210 protected function getParser(): RecursiveParser
211 {
212 if (!isset($this->parser))
213 {
214 $this->parser = $this->getDefaultParser();
215 }
216
217 return $this->parser;
218 }
219
220 /**
221 * Tokenize an XPath expression for use in PHP
222 *
223 * @param string $expr XPath expression
224 * @return array
225 */
226 protected function tokenizeXPathForExport($expr)
227 {
228 $tokenExprs = [
229 '(*:Current)\\bcurrent\\(\\)',
230 '(*:Param)\\$\\w+',
231 '(*:Fragment)(?:"[^"]*"|\'[^\']*\'|(?!current\\(\\)|\\$\\w).)++'
232 ];
233 preg_match_all('(' . implode('|', $tokenExprs) . ')s', $expr, $matches, PREG_SET_ORDER);
234
235 $tokens = [];
236 foreach ($matches as $m)
237 {
238 $tokens[] = [$m['MARK'], $m[0]];
239 }
240
241 return $tokens;
242 }
243 }