Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

lexer.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 10.25 KiB


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\template\twig;
015   
016  class lexer extends \Twig_Lexer
017  {
018      public function set_environment(\Twig_Environment $env)
019      {
020          $this->env = $env;
021      }
022   
023      public function tokenize($code, $filename = null)
024      {
025          // Our phpBB tags
026          // Commented out tokens are handled separately from the main replace
027          $phpbb_tags = array(
028              /*'BEGIN',
029              'BEGINELSE',
030              'END',
031              'IF',
032              'ELSE',
033              'ELSEIF',
034              'ENDIF',
035              'DEFINE',
036              'UNDEFINE',*/
037              'ENDDEFINE',
038              'INCLUDE',
039              'INCLUDEPHP',
040              'INCLUDEJS',
041              'INCLUDECSS',
042              'PHP',
043              'ENDPHP',
044              'EVENT',
045          );
046   
047          // Twig tag masks
048          $twig_tags = array(
049              'autoescape',
050              'endautoescape',
051              'if',
052              'elseif',
053              'else',
054              'endif',
055              'block',
056              'endblock',
057              'use',
058              'extends',
059              'embed',
060              'filter',
061              'endfilter',
062              'flush',
063              'for',
064              'endfor',
065              'macro',
066              'endmacro',
067              'import',
068              'from',
069              'sandbox',
070              'endsandbox',
071              'set',
072              'endset',
073              'spaceless',
074              'endspaceless',
075              'verbatim',
076              'endverbatim',
077          );
078   
079          // Fix tokens that may have inline variables (e.g. <!-- DEFINE $TEST = '{FOO}')
080          $code = $this->strip_surrounding_quotes(array(
081              'INCLUDE',
082              'INCLUDEPHP',
083              'INCLUDEJS',
084              'INCLUDECSS',
085          ), $code);
086          $code = $this->fix_inline_variable_tokens(array(
087              'DEFINE \$[a-zA-Z0-9_]+ =',
088              'INCLUDE',
089              'INCLUDEPHP',
090              'INCLUDEJS',
091              'INCLUDECSS',
092          ), $code);
093          $code = $this->add_surrounding_quotes(array(
094              'INCLUDE',
095              'INCLUDEPHP',
096              'INCLUDEJS',
097              'INCLUDECSS',
098          ), $code);
099   
100          // Fix our BEGIN statements
101          $code = $this->fix_begin_tokens($code);
102   
103          // Fix our IF tokens
104          $code = $this->fix_if_tokens($code);
105   
106          // Fix our DEFINE tokens
107          $code = $this->fix_define_tokens($code);
108   
109          // Replace all of our starting tokens, <!-- TOKEN --> with Twig style, {% TOKEN %}
110          // This also strips outer parenthesis, <!-- IF (blah) --> becomes <!-- IF blah -->
111          $code = preg_replace('#<!-- (' . implode('|', $phpbb_tags) . ')(?: (.*?) ?)?-->#', '{% $1 $2 %}', $code);
112   
113          // Replace all of our twig masks with Twig code (e.g. <!-- BLOCK .+ --> with {% block $1 %})
114          $code = $this->replace_twig_tag_masks($code, $twig_tags);
115   
116          // Replace all of our language variables, {L_VARNAME}, with Twig style, {{ lang('NAME') }}
117          // Appends any filters after lang()
118          $code = preg_replace('#{L_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2 }}', $code);
119   
120          // Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|escape('js') }}
121          // Appends any filters after lang(), but before escape('js')
122          $code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|escape(\'js\') }}', $code);
123   
124          // Replace all of our variables, {VARNAME}, with Twig style, {{ VARNAME }}
125          // Appends any filters
126          $code = preg_replace('#{([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ $1$2 }}', $code);
127   
128          return parent::tokenize($code, $filename);
129      }
130   
131      /**
132      * Strip surrounding quotes
133      *
134      * First step to fix tokens that may have inline variables
135      * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE {TEST}.html
136      *
137      * @param array $tokens array of tokens to search for (imploded to a regular expression)
138      * @param string $code
139      * @return string
140      */
141      protected function strip_surrounding_quotes($tokens, $code)
142      {
143          // Remove matching quotes at the beginning/end if a statement;
144          // E.g. 'asdf'"' -> asdf'"
145          // E.g. "asdf'"" -> asdf'"
146          // E.g. 'asdf'" -> 'asdf'"
147          return preg_replace('#<!-- (' . implode('|', $tokens) . ') (([\'"])?(.*?)\1) -->#', '<!-- $1 $2 -->', $code);
148      }
149   
150      /**
151      * Fix tokens that may have inline variables
152      *
153      * Second step to fix tokens that may have inline variables
154      * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE ' ~ {TEST} ~ '.html
155      *
156      * @param array $tokens array of tokens to search for (imploded to a regular expression)
157      * @param string $code
158      * @return string
159      */
160      protected function fix_inline_variable_tokens($tokens, $code)
161      {
162          $callback = function($matches)
163          {
164              // Replace template variables with start/end to parse variables (' ~ TEST ~ '.html)
165              $matches[2] = preg_replace('#{([a-zA-Z0-9_\.$]+)}#', "'~ \$1 ~'", $matches[2]);
166   
167              return "<!-- {$matches[1]} {$matches[2]} -->";
168          };
169   
170          return preg_replace_callback('#<!-- (' . implode('|', $tokens) . ') (.+?) -->#', $callback, $code);
171      }
172   
173      /**
174      * Add surrounding quotes
175      *
176      * Last step to fix tokens that may have inline variables
177      * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE '' ~ {TEST} ~ '.html'
178      *
179      * @param array $tokens array of tokens to search for (imploded to a regular expression)
180      * @param string $code
181      * @return string
182      */
183      protected function add_surrounding_quotes($tokens, $code)
184      {
185          return preg_replace('#<!-- (' . implode('|', $tokens) . ') (.+?) -->#', '<!-- $1 \'$2\' -->', $code);
186      }
187   
188      /**
189      * Fix begin tokens (convert our BEGIN to Twig for)
190      *
191      * Not meant to be used outside of this context, public because the anonymous function calls this
192      *
193      * @param string $code
194      * @param array $parent_nodes (used in recursion)
195      * @return string
196      */
197      public function fix_begin_tokens($code, $parent_nodes = array())
198      {
199          // PHP 5.3 cannot use $this in an anonymous function, so use this as a work-around
200          $parent_class = $this;
201          $callback = function ($matches) use ($parent_class, $parent_nodes)
202          {
203              $hard_parents = explode('.', $matches[1]);
204              array_pop($hard_parents); // ends with .
205              if ($hard_parents)
206              {
207                  $parent_nodes = array_merge($hard_parents, $parent_nodes);
208              }
209   
210              $name = $matches[2];
211              $subset = trim(substr($matches[3], 1, -1)); // Remove parenthesis
212              $body = $matches[4];
213   
214              // Replace <!-- BEGINELSE -->
215              $body = str_replace('<!-- BEGINELSE -->', '{% else %}', $body);
216   
217              // Is the designer wanting to call another loop in a loop?
218              // <!-- BEGIN loop -->
219              // <!-- BEGIN !loop2 -->
220              // <!-- END !loop2 -->
221              // <!-- END loop -->
222              // 'loop2' is actually on the same nesting level as 'loop' you assign
223              // variables to it with template->assign_block_vars('loop2', array(...))
224              if (strpos($name, '!') === 0)
225              {
226                  // Count the number if ! occurrences
227                  $count = substr_count($name, '!');
228                  for ($i = 0; $i < $count; $i++)
229                  {
230                      array_pop($parent_nodes);
231                      $name = substr($name, 1);
232                  }
233              }
234   
235              // Remove all parent nodes, e.g. foo, bar from foo.bar.foobar.VAR
236              foreach ($parent_nodes as $node)
237              {
238                  $body = preg_replace('#([^a-zA-Z0-9_])' . $node . '\.([a-zA-Z0-9_]+)\.#', '$1$2.', $body);
239              }
240   
241              // Add current node to list of parent nodes for child nodes
242              $parent_nodes[] = $name;
243   
244              // Recursive...fix any child nodes
245              $body = $parent_class->fix_begin_tokens($body, $parent_nodes);
246   
247              // Need the parent variable name
248              array_pop($parent_nodes);
249              $parent = (!empty($parent_nodes)) ? end($parent_nodes) . '.' : '';
250   
251              if ($subset !== '')
252              {
253                  $subset = '|subset(' . $subset . ')';
254              }
255   
256              $parent = ($parent) ?: 'loops.';
257              // Turn into a Twig for loop
258              return "{% for {$name} in {$parent}{$name}{$subset} %}{$body}{% endfor %}";
259          };
260   
261          return preg_replace_callback('#<!-- BEGIN ((?:[a-zA-Z0-9_]+\.)*)([!a-zA-Z0-9_]+)(\([0-9,\-]+\))? -->(.+?)<!-- END \1\2 -->#s', $callback, $code);
262      }
263   
264      /**
265      * Fix IF statements
266      *
267      * @param string $code
268      * @return string
269      */
270      protected function fix_if_tokens($code)
271      {
272          // Replace ELSE IF with ELSEIF
273          $code = preg_replace('#<!-- ELSE IF (.+?) -->#', '<!-- ELSEIF $1 -->', $code);
274   
275          // Replace our "div by" with Twig's divisibleby (Twig does not like test names with spaces)
276          $code = preg_replace('# div by ([0-9]+)#', ' divisibleby($1)', $code);
277   
278          $callback = function($matches)
279          {
280              $inner = $matches[2];
281              // Replace $TEST with definition.TEST
282              $inner = preg_replace('#(\s\(*!?)\$([a-zA-Z_0-9]+)#', '$1definition.$2', $inner);
283   
284              // Replace .foo with loops.foo|length
285              $inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9]+)([^a-zA-Z_0-9\.])#', '$1loops.$2|length$3', $inner);
286   
287              // Replace .foo.bar with foo.bar|length
288              $inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9\.]+)([^a-zA-Z_0-9\.])#', '$1$2|length$3', $inner);
289   
290              return "<!-- {$matches[1]}IF{$inner}-->";
291          };
292   
293          return preg_replace_callback('#<!-- (ELSE)?IF((.*?) (?:\(*!?[\$|\.]([^\s]+)(.*?))?)-->#', $callback, $code);
294      }
295   
296      /**
297      * Fix DEFINE statements and {$VARNAME} variables
298      *
299      * @param string $code
300      * @return string
301      */
302      protected function fix_define_tokens($code)
303      {
304          /**
305          * Changing $VARNAME to definition.varname because set is only local
306          * context (e.g. DEFINE $TEST will only make $TEST available in current
307          * template and any child templates, but not any parent templates).
308          *
309          * DEFINE handles setting it properly to definition in its node, but the
310          * variables reading FROM it need to be altered to definition.VARNAME
311          *
312          * Setting up definition as a class in the array passed to Twig
313          * ($context) makes set definition.TEST available in the global context
314          */
315   
316          // Replace <!-- DEFINE $NAME with {% DEFINE definition.NAME
317          $code = preg_replace('#<!-- DEFINE \$(.*?) -->#', '{% DEFINE $1 %}', $code);
318   
319          // Changing UNDEFINE NAME to DEFINE NAME = null to save from creating an extra token parser/node
320          $code = preg_replace('#<!-- UNDEFINE \$(.*?)-->#', '{% DEFINE $1= null %}', $code);
321   
322          // Replace all of our variables, {$VARNAME}, with Twig style, {{ definition.VARNAME }}
323          $code = preg_replace('#{\$([a-zA-Z0-9_\.]+)}#', '{{ definition.$1 }}', $code);
324   
325          // Replace all of our variables, ~ $VARNAME ~, with Twig style, ~ definition.VARNAME ~
326          $code = preg_replace('#~ \$([a-zA-Z0-9_\.]+) ~#', '~ definition.$1 ~', $code);
327   
328          return $code;
329      }
330   
331      /**
332      * Replace Twig tag masks with Twig tag calls
333      *
334      * E.g. <!-- BLOCK foo --> with {% block foo %}
335      *
336      * @param string $code
337      * @param array $twig_tags All tags we want to create a mask for
338      * @return string
339      */
340      protected function replace_twig_tag_masks($code, $twig_tags)
341      {
342          $callback = function ($matches)
343          {
344              $matches[1] = strtolower($matches[1]);
345   
346              return "{% {$matches[1]}{$matches[2]}%}";
347          };
348   
349          foreach ($twig_tags as &$tag)
350          {
351              $tag = strtoupper($tag);
352          }
353   
354          // twig_tags is an array of the twig tags, which are all lowercase, but we use all uppercase tags
355          $code = preg_replace_callback('#<!-- (' . implode('|', $twig_tags) . ')(.*?)-->#',$callback, $code);
356   
357          return $code;
358      }
359  }
360