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

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

context.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 15.72 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;
015   
016  /**
017  * Stores variables assigned to template.
018  */
019  class context
020  {
021      /**
022      * variable that holds all the data we'll be substituting into
023      * the compiled templates. Takes form:
024      * --> $this->tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value
025      * if it's a root-level variable, it'll be like this:
026      * --> $this->tpldata[.][0][varname] == value
027      *
028      * @var array
029      */
030      private $tpldata = array('.' => array(0 => array()));
031   
032      /**
033      * @var array Reference to template->tpldata['.'][0]
034      */
035      private $rootref;
036   
037      /**
038      * @var bool
039      */
040      private $num_rows_is_set;
041   
042      public function __construct()
043      {
044          $this->clear();
045      }
046   
047      /**
048      * Clears template data set.
049      */
050      public function clear()
051      {
052          $this->tpldata = array('.' => array(0 => array()));
053          $this->rootref = &$this->tpldata['.'][0];
054          $this->num_rows_is_set = false;
055      }
056   
057      /**
058      * Assign a single scalar value to a single key.
059      *
060      * Value can be a string, an integer or a boolean.
061      *
062      * @param string $varname Variable name
063      * @param string $varval Value to assign to variable
064      * @return true
065      */
066      public function assign_var($varname, $varval)
067      {
068          $this->rootref[$varname] = $varval;
069   
070          return true;
071      }
072   
073      /**
074      * Append text to the string value stored in a key.
075      *
076      * Text is appended using the string concatenation operator (.).
077      *
078      * @param string $varname Variable name
079      * @param string $varval Value to append to variable
080      * @return true
081      */
082      public function append_var($varname, $varval)
083      {
084          $this->rootref[$varname] = (isset($this->rootref[$varname]) ? $this->rootref[$varname] : '') . $varval;
085   
086          return true;
087      }
088   
089      /**
090      * Retrieve a single scalar value from a single key.
091      *
092      * @param string $varname Variable name
093      * @return mixed Variable value, or null if not set
094      */
095      public function retrieve_var($varname)
096      {
097          return isset($this->rootref[$varname]) ? $this->rootref[$varname] : null;
098      }
099   
100      /**
101      * Returns a reference to template data array.
102      *
103      * This function is public so that template renderer may invoke it.
104      * Users should alter template variables via functions in \phpbb\template\template.
105      *
106      * Note: modifying returned array will affect data stored in the context.
107      *
108      * @return array template data
109      */
110      public function &get_data_ref()
111      {
112          // returning a reference directly is not
113          // something php is capable of doing
114          $ref = &$this->tpldata;
115   
116          if (!$this->num_rows_is_set)
117          {
118              /*
119              * We do not set S_NUM_ROWS while adding a row, to reduce the complexity
120              * If we would set it on adding, each subsequent adding would cause
121              * n modifications, resulting in a O(n!) complexity, rather then O(n)
122              */
123              foreach ($ref as $loop_name => &$loop_data)
124              {
125                  if ($loop_name === '.')
126                  {
127                      continue;
128                  }
129   
130                  $this->set_num_rows($loop_data);
131              }
132              $this->num_rows_is_set = true;
133          }
134   
135          return $ref;
136      }
137   
138      /**
139      * Set S_NUM_ROWS for each row in this template block
140      *
141      * @param array $loop_data
142      */
143      protected function set_num_rows(&$loop_data)
144      {
145          $s_num_rows = count($loop_data);
146          foreach ($loop_data as &$mod_block)
147          {
148              foreach ($mod_block as $sub_block_name => &$sub_block)
149              {
150                  // If the key name is lowercase and the data is an array,
151                  // it could be a template loop. So we set the S_NUM_ROWS there
152                  // as well.
153                  if ($sub_block_name === strtolower($sub_block_name) && is_array($sub_block))
154                  {
155                      $this->set_num_rows($sub_block);
156                  }
157              }
158   
159              // Check whether we are inside a block before setting the variable
160              if (isset($mod_block['S_BLOCK_NAME']))
161              {
162                  $mod_block['S_NUM_ROWS'] = $s_num_rows;
163              }
164          }
165      }
166   
167      /**
168      * Returns a reference to template root scope.
169      *
170      * This function is public so that template renderer may invoke it.
171      * Users should not need to invoke this function.
172      *
173      * Note: modifying returned array will affect data stored in the context.
174      *
175      * @return array template data
176      */
177      public function &get_root_ref()
178      {
179          // rootref is already a reference
180          return $this->rootref;
181      }
182   
183      /**
184      * Assign key variable pairs from an array to a specified block
185      *
186      * @param string $blockname Name of block to assign $vararray to
187      * @param array $vararray A hash of variable name => value pairs
188      * @return true
189      */
190      public function assign_block_vars($blockname, array $vararray)
191      {
192          $this->num_rows_is_set = false;
193   
194          // For nested block, $blockcount > 0, for top-level block, $blockcount == 0
195          $blocks = explode('.', $blockname);
196          $blockcount = count($blocks) - 1;
197   
198          $block = &$this->tpldata;
199          for ($i = 0; $i < $blockcount; $i++)
200          {
201              $pos = strpos($blocks[$i], '[');
202              $name = ($pos !== false) ? substr($blocks[$i], 0, $pos) : $blocks[$i];
203              $block = &$block[$name];
204              $block_count = empty($block) ? 0 : count($block) - 1;
205              $index = (!$pos || strpos($blocks[$i], '[]') === $pos) ? $block_count : (min((int) substr($blocks[$i], $pos + 1, -1), $block_count));
206              $block = &$block[$index];
207          }
208   
209          // $block = &$block[$blocks[$i]]; // Do not traverse the last block as it might be empty
210          $name = $blocks[$i];
211   
212          // Assign S_ROW_COUNT and S_ROW_NUM
213          $s_row_count = isset($block[$name]) ? count($block[$name]) : 0;
214          $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count;
215   
216          // Assign S_FIRST_ROW
217          if (!$s_row_count)
218          {
219              $vararray['S_FIRST_ROW'] = true;
220          }
221   
222          // Assign S_BLOCK_NAME
223          $vararray['S_BLOCK_NAME'] = $name;
224   
225          // Now the tricky part, we always assign S_LAST_ROW and remove the entry before
226          // This is much more clever than going through the complete template data on display (phew)
227          $vararray['S_LAST_ROW'] = true;
228          if ($s_row_count > 0)
229          {
230              unset($block[$name][($s_row_count - 1)]['S_LAST_ROW']);
231          }
232   
233          // Now we add the block that we're actually assigning to.
234          // We're adding a new iteration to this block with the given
235          // variable assignments.
236          $block[$name][] = $vararray;
237   
238          return true;
239      }
240   
241      /**
242      * Assign key variable pairs from an array to a whole specified block loop
243      *
244      * @param string $blockname Name of block to assign $block_vars_array to
245      * @param array $block_vars_array An array of hashes of variable name => value pairs
246      * @return true
247      */
248      public function assign_block_vars_array($blockname, array $block_vars_array)
249      {
250          foreach ($block_vars_array as $vararray)
251          {
252              $this->assign_block_vars($blockname, $vararray);
253          }
254   
255          return true;
256      }
257   
258      /**
259      * Retrieve key variable pairs from the specified block
260      *
261      * @param string $blockname Name of block to retrieve $vararray from
262      * @param array $vararray An array of variable names, empty array retrieves all vars
263      * @return array of hashes with variable name as key and retrieved value or null as value
264      */
265      public function retrieve_block_vars($blockname, array $vararray)
266      {
267          // For nested block, $blockcount > 0, for top-level block, $blockcount == 0
268          $blocks = explode('.', $blockname);
269          $blockcount = count($blocks) - 1;
270   
271          $block = $this->tpldata;
272          for ($i = 0; $i <= $blockcount; $i++)
273          {
274              if (($pos = strpos($blocks[$i], '[')) !== false)
275              {
276                  $name = substr($blocks[$i], 0, $pos);
277   
278                  if (empty($block[$name]))
279                  {
280                      return array();
281                  }
282   
283                  if (strpos($blocks[$i], '[]') === $pos)
284                  {
285                      $index = count($block[$name]) - 1;
286                  }
287                  else
288                  {
289                      $index = min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1);
290                  }
291              }
292              else
293              {
294                  $name = $blocks[$i];
295                  if (empty($block[$name]))
296                  {
297                      return array();
298                  }
299   
300                  $index = count($block[$name]) - 1;
301              }
302              $block = $block[$name];
303              $block = $block[$index];
304          }
305   
306          $result = array();
307          if ($vararray === array())
308          {
309              // The calculated vars that depend on the block position are excluded from the complete block returned results
310              $excluded_vars = array('S_FIRST_ROW', 'S_LAST_ROW', 'S_BLOCK_NAME', 'S_NUM_ROWS', 'S_ROW_COUNT', 'S_ROW_NUM');
311   
312              foreach ($block as $varname => $varvalue)
313              {
314                  if ($varname === strtoupper($varname) && !is_array($varvalue) && !in_array($varname, $excluded_vars))
315                  {
316                      $result[$varname] = $varvalue;
317                  }
318              }
319          }
320          else
321          {
322              foreach ($vararray as $varname)
323              {
324                  $result[$varname] = isset($block[$varname]) ? $block[$varname] : null;
325              }
326          }
327          return $result;
328      }
329   
330      /**
331      * Find the index for a specified key in the innermost specified block
332      *
333      * @param    string    $blockname    the blockname, for example 'loop'
334      * @param    mixed    $key        Key to search for
335      *
336      * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position]
337      *
338      * int: Position [the position to search for]
339      *
340      * If key is false the position is set to 0
341      * If key is true the position is set to the last entry
342      *
343      * @return mixed false if not found, index position otherwise; be sure to test with ===
344      */
345      public function find_key_index($blockname, $key)
346      {
347          // For nested block, $blockcount > 0, for top-level block, $blockcount == 0
348          $blocks = explode('.', $blockname);
349          $blockcount = count($blocks) - 1;
350   
351          $block = $this->tpldata;
352          for ($i = 0; $i < $blockcount; $i++)
353          {
354              $pos = strpos($blocks[$i], '[');
355              $name = ($pos !== false) ? substr($blocks[$i], 0, $pos) : $blocks[$i];
356   
357              if (!isset($block[$name]))
358              {
359                  return false;
360              }
361   
362              $index = (!$pos || strpos($blocks[$i], '[]') === $pos) ? (count($block[$name]) - 1) : (min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1));
363   
364              if (!isset($block[$name][$index]))
365              {
366                  return false;
367              }
368              $block = $block[$name][$index];
369          }
370   
371          if (!isset($block[$blocks[$i]]))
372          {
373              return false;
374          }
375          $block = $block[$blocks[$i]]; // Traverse the last block
376   
377          // Change key to zero (change first position) if false and to last position if true
378          if (is_bool($key))
379          {
380              return (!$key) ? 0 : count($block) - 1;
381          }
382   
383          // Get correct position if array given
384          if (is_array($key))
385          {
386              // Search array to get correct position
387              $search_key = key($key);
388              $search_value = current($key);
389   
390              foreach ($block as $i => $val_ary)
391              {
392                  if ($val_ary[$search_key] === $search_value)
393                  {
394                      return $i;
395                  }
396              }
397          }
398   
399          return (is_int($key) && ((0 <= $key) && ($key < count($block)))) ? $key : false;
400      }
401   
402      /**
403      * Change already assigned key variable pair (one-dimensional - single loop entry)
404      *
405      * An example of how to use this function:
406      * {@example alter_block_array.php}
407      *
408      * @param    string    $blockname    the blockname, for example 'loop'
409      * @param    array    $vararray    the var array to insert/add or merge
410      * @param    mixed    $key        Key to search for
411      *
412      * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position]
413      *
414      * int: Position [the position to change or insert at directly given]
415      *
416      * If key is false the position is set to 0
417      * If key is true the position is set to the last entry
418      *
419      * @param    string    $mode        Mode to execute (valid modes are 'insert', 'change' and 'delete')
420      *
421      *    If insert, the vararray is inserted at the given position (position counting from zero).
422      *    If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new \value).
423      *    If delete, the vararray is ignored, and the block at the given position (counting from zero) is removed.
424      *
425      * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)
426      * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars)
427      *
428      * @return bool false on error, true on success
429      */
430      public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert')
431      {
432          $this->num_rows_is_set = false;
433   
434          // For nested block, $blockcount > 0, for top-level block, $blockcount == 0
435          $blocks = explode('.', $blockname);
436          $blockcount = count($blocks) - 1;
437   
438          $block = &$this->tpldata;
439          for ($i = 0; $i < $blockcount; $i++)
440          {
441              if (($pos = strpos($blocks[$i], '[')) !== false)
442              {
443                  $name = substr($blocks[$i], 0, $pos);
444   
445                  if (strpos($blocks[$i], '[]') === $pos)
446                  {
447                      $index = count($block[$name]) - 1;
448                  }
449                  else
450                  {
451                      $index = min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1);
452                  }
453              }
454              else
455              {
456                  $name = $blocks[$i];
457                  $index = count($block[$name]) - 1;
458              }
459              $block = &$block[$name];
460              $block = &$block[$index];
461          }
462          $name = $blocks[$i];
463   
464          // If last block does not exist and we are inserting, and not searching for key, we create it empty; otherwise, nothing to do
465          if (!isset($block[$name]))
466          {
467              if ($mode != 'insert' || is_array($key))
468              {
469                  return false;
470              }
471              $block[$name] = array();
472          }
473   
474          $block = &$block[$name]; // Now we can traverse the last block
475   
476          // Change key to zero (change first position) if false and to last position if true
477          if ($key === false || $key === true)
478          {
479              $key = ($key === false) ? 0 : count($block);
480          }
481   
482          // Get correct position if array given
483          if (is_array($key))
484          {
485              // Search array to get correct position
486              $search_key = key($key);
487              $search_value = current($key);
488   
489              $key = null;
490              foreach ($block as $i => $val_ary)
491              {
492                  if ($val_ary[$search_key] === $search_value)
493                  {
494                      $key = $i;
495                      break;
496                  }
497              }
498   
499              // key/value pair not found
500              if ($key === null)
501              {
502                  return false;
503              }
504          }
505   
506          // Insert Block
507          if ($mode == 'insert')
508          {
509              // Make sure we are not exceeding the last iteration
510              if ($key >= count($block))
511              {
512                  $key = count($block);
513                  unset($block[($key - 1)]['S_LAST_ROW']);
514                  $vararray['S_LAST_ROW'] = true;
515              }
516              if ($key <= 0)
517              {
518                  $key = 0;
519                  unset($block[0]['S_FIRST_ROW']);
520                  $vararray['S_FIRST_ROW'] = true;
521              }
522   
523              // Assign S_BLOCK_NAME
524              $vararray['S_BLOCK_NAME'] = $name;
525   
526              // Re-position template blocks
527              for ($i = count($block); $i > $key; $i--)
528              {
529                  $block[$i] = $block[$i-1];
530   
531                  $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i;
532              }
533   
534              // Insert vararray at given position
535              $block[$key] = $vararray;
536              $block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key;
537   
538              return true;
539          }
540   
541          // Which block to change?
542          if ($mode == 'change')
543          {
544              // If key is out of bounds, do not change anything
545              if ($key > count($block) || $key < 0)
546              {
547                  return false;
548              }
549   
550              if ($key == count($block))
551              {
552                  $key--;
553              }
554   
555              $block[$key] = array_merge($block[$key], $vararray);
556   
557              return true;
558          }
559   
560          // Delete Block
561          if ($mode == 'delete')
562          {
563              // If we are exceeding last iteration, do not delete anything
564              if ($key > count($block) || $key < 0)
565              {
566                  return false;
567              }
568   
569              // If we are positioned at the end, we remove the last element
570              if ($key == count($block))
571              {
572                  $key--;
573              }
574   
575              // We are deleting the last element in the block, so remove the block
576              if (count($block) === 1)
577              {
578                  $block = null; // unset($block); does not work on references
579                  return true;
580              }
581   
582              // Re-position template blocks
583              for ($i = $key; $i < count($block)-1; $i++)
584              {
585                  $block[$i] = $block[$i+1];
586                  $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i;
587              }
588   
589              // Remove the last element
590              unset($block[$i]);
591   
592              // Set first and last elements again, in case they were removed
593              $block[0]['S_FIRST_ROW'] = true;
594              $block[count($block)-1]['S_LAST_ROW'] = true;
595   
596              return true;
597          }
598   
599          return false;
600      }
601   
602      /**
603      * Reset/empty complete block
604      *
605      * @param string $blockname Name of block to destroy
606      * @return true
607      */
608      public function destroy_block_vars($blockname)
609      {
610          $this->num_rows_is_set = false;
611          if (strpos($blockname, '.') !== false)
612          {
613              // Nested block.
614              $blocks = explode('.', $blockname);
615              $blockcount = count($blocks) - 1;
616   
617              $str = &$this->tpldata;
618              for ($i = 0; $i < $blockcount; $i++)
619              {
620                  $str = &$str[$blocks[$i]];
621                  $str = &$str[count($str) - 1];
622              }
623   
624              unset($str[$blocks[$blockcount]]);
625          }
626          else
627          {
628              // Top-level block.
629              unset($this->tpldata[$blockname]);
630          }
631   
632          return true;
633      }
634  }
635