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 |
context.php
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