Verzeichnisstruktur phpBB-2.0.0


Veröffentlicht
03.04.2002

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

template.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 13.99 KiB


001  <?php
002  /***************************************************************************
003   *                              template.php
004   *                            -------------------
005   *   begin                : Saturday, Feb 13, 2001
006   *   copyright            : (C) 2001 The phpBB Group
007   *   email                : support@phpbb.com
008   *
009   *   $Id$
010   *
011   *
012   ***************************************************************************/
013   
014  /***************************************************************************
015   *
016   *   This program is free software; you can redistribute it and/or modify
017   *   it under the terms of the GNU General Public License as published by
018   *   the Free Software Foundation; either version 2 of the License, or
019   *   (at your option) any later version.
020   *
021   ***************************************************************************/
022   
023  /**
024   * Template class. By Nathan Codding of the phpBB group.
025   * The interface was originally inspired by PHPLib templates,
026   * and the template file formats are quite similar.
027   *
028   */
029   
030  class Template {
031      var $classname = "Template";
032   
033      // variable that holds all the data we'll be substituting into
034      // the compiled templates.
035      // ...
036      // This will end up being a multi-dimensional array like this:
037      // $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value
038      // if it's a root-level variable, it'll be like this:
039      // $this->_tpldata[.][0][varname] == value
040      var $_tpldata = array();
041   
042      // Hash of filenames for each template handle.
043      var $files = array();
044   
045      // Root template directory.
046      var $root = "";
047   
048      // this will hash handle names to the compiled code for that handle.
049      var $compiled_code = array();
050   
051      // This will hold the uncompiled code for that handle.
052      var $uncompiled_code = array();
053   
054      /**
055       * Constructor. Simply sets the root dir.
056       *
057       */
058      function Template($root = ".")
059      {
060          $this->set_rootdir($root);
061      }
062   
063      /**
064       * Destroys this template object. Should be called when you're done with it, in order
065       * to clear out the template data so you can load/parse a new template set.
066       */
067      function destroy()
068      {
069          $this->_tpldata = array();
070      }
071   
072      /**
073       * Sets the template root directory for this Template object.
074       */
075      function set_rootdir($dir)
076      {
077          if (!is_dir($dir))
078          {
079              return false;
080          }
081   
082          $this->root = $dir;
083          return true;
084      }
085   
086      /**
087       * Sets the template filenames for handles. $filename_array
088       * should be a hash of handle => filename pairs.
089       */
090      function set_filenames($filename_array)
091      {
092          if (!is_array($filename_array))
093          {
094              return false;
095          }
096   
097          reset($filename_array);
098          while(list($handle, $filename) = each($filename_array))
099          {
100              $this->files[$handle] = $this->make_filename($filename);
101          }
102   
103          return true;
104      }
105   
106   
107      /**
108       * Load the file for the handle, compile the file,
109       * and run the compiled code. This will print out
110       * the results of executing the template.
111       */
112      function pparse($handle)
113      {
114          if (!$this->loadfile($handle))
115          {
116              die("Template->pparse(): Couldn't load template file for handle $handle");
117          }
118   
119          // actually compile the template now.
120          if (!isset($this->compiled_code[$handle]) || empty($this->compiled_code[$handle]))
121          {
122              // Actually compile the code now.
123              $this->compiled_code[$handle] = $this->compile($this->uncompiled_code[$handle]);
124          }
125   
126          // Run the compiled code.
127          eval($this->compiled_code[$handle]);
128          return true;
129      }
130   
131      /**
132       * Inserts the uncompiled code for $handle as the
133       * value of $varname in the root-level. This can be used
134       * to effectively include a template in the middle of another
135       * template.
136       * Note that all desired assignments to the variables in $handle should be done
137       * BEFORE calling this function.
138       */
139      function assign_var_from_handle($varname, $handle)
140      {
141          if (!$this->loadfile($handle))
142          {
143              die("Template->assign_var_from_handle(): Couldn't load template file for handle $handle");
144          }
145   
146          // Compile it, with the "no echo statements" option on.
147          $_str = "";
148          $code = $this->compile($this->uncompiled_code[$handle], true, '_str');
149   
150          // evaluate the variable assignment.
151          eval($code);
152          // assign the value of the generated variable to the given varname.
153          $this->assign_var($varname, $_str);
154   
155          return true;
156      }
157   
158      /**
159       * Block-level variable assignment. Adds a new block iteration with the given
160       * variable assignments. Note that this should only be called once per block
161       * iteration.
162       */
163      function assign_block_vars($blockname, $vararray)
164      {
165          if (strstr($blockname, '.'))
166          {
167              // Nested block.
168              $blocks = explode('.', $blockname);
169              $blockcount = sizeof($blocks) - 1;
170              $str = '$this->_tpldata';
171              for ($i = 0; $i < $blockcount; $i++)
172              {
173                  $str .= '[\'' . $blocks[$i] . '.\']';
174                  eval('$lastiteration = sizeof(' . $str . ') - 1;');
175                  $str .= '[' . $lastiteration . ']';
176              }
177              // Now we add the block that we're actually assigning to.
178              // We're adding a new iteration to this block with the given
179              // variable assignments.
180              $str .= '[\'' . $blocks[$blockcount] . '.\'][] = $vararray;';
181   
182              // Now we evaluate this assignment we've built up.
183              eval($str);
184          }
185          else
186          {
187              // Top-level block.
188              // Add a new iteration to this block with the variable assignments
189              // we were given.
190              $this->_tpldata[$blockname . '.'][] = $vararray;
191          }
192   
193          return true;
194      }
195   
196      /**
197       * Root-level variable assignment. Adds to current assignments, overriding
198       * any existing variable assignment with the same name.
199       */
200      function assign_vars($vararray)
201      {
202          reset ($vararray);
203          while (list($key, $val) = each($vararray))
204          {
205              $this->_tpldata['.'][0][$key] = $val;
206          }
207   
208          return true;
209      }
210   
211      /**
212       * Root-level variable assignment. Adds to current assignments, overriding
213       * any existing variable assignment with the same name.
214       */
215      function assign_var($varname, $varval)
216      {
217          $this->_tpldata['.'][0][$varname] = $varval;
218   
219          return true;
220      }
221   
222   
223      /**
224       * Generates a full path+filename for the given filename, which can either
225       * be an absolute name, or a name relative to the rootdir for this Template
226       * object.
227       */
228      function make_filename($filename)
229      {
230          // Check if it's an absolute or relative path.
231          if (substr($filename, 0, 1) != '/')
232          {
233                 $filename = ($rp_filename = phpbb_realpath($this->root . '/' . $filename)) ? $rp_filename : $filename;
234          }
235   
236          if (!file_exists($filename))
237          {
238              die("Template->make_filename(): Error - file $filename does not exist");
239          }
240   
241          return $filename;
242      }
243   
244   
245      /**
246       * If not already done, load the file for the given handle and populate
247       * the uncompiled_code[] hash with its code. Do not compile.
248       */
249      function loadfile($handle)
250      {
251          // If the file for this handle is already loaded and compiled, do nothing.
252          if (isset($this->uncompiled_code[$handle]) && !empty($this->uncompiled_code[$handle]))
253          {
254              return true;
255          }
256   
257          // If we don't have a file assigned to this handle, die.
258          if (!isset($this->files[$handle]))
259          {
260              die("Template->loadfile(): No file specified for handle $handle");
261          }
262   
263          $filename = $this->files[$handle];
264   
265          $str = implode("", @file($filename));
266          if (empty($str))
267          {
268              die("Template->loadfile(): File $filename for handle $handle is empty");
269          }
270   
271          $this->uncompiled_code[$handle] = $str;
272   
273          return true;
274      }
275   
276   
277   
278      /**
279       * Compiles the given string of code, and returns
280       * the result in a string.
281       * If "do_not_echo" is true, the returned code will not be directly
282       * executable, but can be used as part of a variable assignment
283       * for use in assign_code_from_handle().
284       */
285      function compile($code, $do_not_echo = false, $retvar = '')
286      {
287          // replace \ with \\ and then ' with \'.
288          $code = str_replace('\\', '\\\\', $code);
289          $code = str_replace('\'', '\\\'', $code);
290   
291          // change template varrefs into PHP varrefs
292   
293          // This one will handle varrefs WITH namespaces
294          $varrefs = array();
295          preg_match_all('#\{(([a-z0-9\-_]+?\.)+?)([a-z0-9\-_]+?)\}#is', $code, $varrefs);
296          $varcount = sizeof($varrefs[1]);
297          for ($i = 0; $i < $varcount; $i++)
298          {
299              $namespace = $varrefs[1][$i];
300              $varname = $varrefs[3][$i];
301              $new = $this->generate_block_varref($namespace, $varname);
302   
303              $code = str_replace($varrefs[0][$i], $new, $code);
304          }
305   
306          // This will handle the remaining root-level varrefs
307          $code = preg_replace('#\{([a-z0-9\-_]*?)\}#is', '\' . ( ( isset($this->_tpldata[\'.\'][0][\'\1\']) ) ? $this->_tpldata[\'.\'][0][\'\1\'] : \'\' ) . \'', $code);
308   
309          // Break it up into lines.
310          $code_lines = explode("\n", $code);
311   
312          $block_nesting_level = 0;
313          $block_names = array();
314          $block_names[0] = ".";
315   
316          // Second: prepend echo ', append ' . "\n"; to each line.
317          $line_count = sizeof($code_lines);
318          for ($i = 0; $i < $line_count; $i++)
319          {
320              $code_lines[$i] = chop($code_lines[$i]);
321              if (preg_match('#<!-- BEGIN (.*?) -->#', $code_lines[$i], $m))
322              {
323                  $n[0] = $m[0];
324                  $n[1] = $m[1];
325   
326                  // Added: dougk_ff7-Keeps templates from bombing if begin is on the same line as end.. I think. :)
327                  if ( preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $n) )
328                  {
329                      $block_nesting_level++;
330                      $block_names[$block_nesting_level] = $m[1];
331                      if ($block_nesting_level < 2)
332                      {
333                          // Block is not nested.
334                          $code_lines[$i] = '$_' . $n[1] . '_count = ( isset($this->_tpldata[\'' . $n[1] . '.\']) ) ?  sizeof($this->_tpldata[\'' . $n[1] . '.\']) : 0;';
335                          $code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
336                          $code_lines[$i] .= "\n" . '{';
337                      }
338                      else
339                      {
340                          // This block is nested.
341   
342                          // Generate a namespace string for this block.
343                          $namespace = implode('.', $block_names);
344                          // strip leading period from root level..
345                          $namespace = substr($namespace, 2);
346                          // Get a reference to the data array for this block that depends on the
347                          // current indices of all parent blocks.
348                          $varref = $this->generate_block_data_ref($namespace, false);
349                          // Create the for loop code to iterate over this block.
350                          $code_lines[$i] = '$_' . $n[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
351                          $code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
352                          $code_lines[$i] .= "\n" . '{';
353                      }
354   
355                      // We have the end of a block.
356                      unset($block_names[$block_nesting_level]);
357                      $block_nesting_level--;
358                      $code_lines[$i] .= '} // END ' . $n[1];
359                      $m[0] = $n[0];
360                      $m[1] = $n[1];
361                  }
362                  else
363                  {
364                      // We have the start of a block.
365                      $block_nesting_level++;
366                      $block_names[$block_nesting_level] = $m[1];
367                      if ($block_nesting_level < 2)
368                      {
369                          // Block is not nested.
370                          $code_lines[$i] = '$_' . $m[1] . '_count = ( isset($this->_tpldata[\'' . $m[1] . '.\']) ) ? sizeof($this->_tpldata[\'' . $m[1] . '.\']) : 0;';
371                          $code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
372                          $code_lines[$i] .= "\n" . '{';
373                      }
374                      else
375                      {
376                          // This block is nested.
377   
378                          // Generate a namespace string for this block.
379                          $namespace = implode('.', $block_names);
380                          // strip leading period from root level..
381                          $namespace = substr($namespace, 2);
382                          // Get a reference to the data array for this block that depends on the
383                          // current indices of all parent blocks.
384                          $varref = $this->generate_block_data_ref($namespace, false);
385                          // Create the for loop code to iterate over this block.
386                          $code_lines[$i] = '$_' . $m[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
387                          $code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
388                          $code_lines[$i] .= "\n" . '{';
389                      }
390                  }
391              }
392              else if (preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $m))
393              {
394                  // We have the end of a block.
395                  unset($block_names[$block_nesting_level]);
396                  $block_nesting_level--;
397                  $code_lines[$i] = '} // END ' . $m[1];
398              }
399              else
400              {
401                  // We have an ordinary line of code.
402                  if (!$do_not_echo)
403                  {
404                      $code_lines[$i] = 'echo \'' . $code_lines[$i] . '\' . "\\n";';
405                  }
406                  else
407                  {
408                      $code_lines[$i] = '$' . $retvar . '.= \'' . $code_lines[$i] . '\' . "\\n";'; 
409                  }
410              }
411          }
412   
413          // Bring it back into a single string of lines of code.
414          $code = implode("\n", $code_lines);
415          return $code    ;
416   
417      }
418   
419   
420      /**
421       * Generates a reference to the given variable inside the given (possibly nested)
422       * block namespace. This is a string of the form:
423       * ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
424       * It's ready to be inserted into an "echo" line in one of the templates.
425       * NOTE: expects a trailing "." on the namespace.
426       */
427      function generate_block_varref($namespace, $varname)
428      {
429          // Strip the trailing period.
430          $namespace = substr($namespace, 0, strlen($namespace) - 1);
431   
432          // Get a reference to the data block for this namespace.
433          $varref = $this->generate_block_data_ref($namespace, true);
434          // Prepend the necessary code to stick this in an echo line.
435   
436          // Append the variable reference.
437          $varref .= '[\'' . $varname . '\']';
438   
439          $varref = '\' . ( ( isset(' . $varref . ') ) ? ' . $varref . ' : \'\' ) . \'';
440   
441          return $varref;
442   
443      }
444   
445   
446      /**
447       * Generates a reference to the array of data values for the given
448       * (possibly nested) block namespace. This is a string of the form:
449       * $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN']
450       *
451       * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
452       * NOTE: does not expect a trailing "." on the blockname.
453       */
454      function generate_block_data_ref($blockname, $include_last_iterator)
455      {
456          // Get an array of the blocks involved.
457          $blocks = explode(".", $blockname);
458          $blockcount = sizeof($blocks) - 1;
459          $varref = '$this->_tpldata';
460          // Build up the string with everything but the last child.
461          for ($i = 0; $i < $blockcount; $i++)
462          {
463              $varref .= '[\'' . $blocks[$i] . '.\'][$_' . $blocks[$i] . '_i]';
464          }
465          // Add the block reference for the last child.
466          $varref .= '[\'' . $blocks[$blockcount] . '.\']';
467          // Add the iterator for the last child if requried.
468          if ($include_last_iterator)
469          {
470              $varref .= '[$_' . $blocks[$blockcount] . '_i]';
471          }
472   
473          return $varref;
474      }
475   
476  }
477   
478  ?>