[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 namespace phpbb\template; 15 16 /** 17 * Stores variables assigned to template. 18 */ 19 class context 20 { 21 /** 22 * variable that holds all the data we'll be substituting into 23 * the compiled templates. Takes form: 24 * --> $this->tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value 25 * if it's a root-level variable, it'll be like this: 26 * --> $this->tpldata[.][0][varname] == value 27 * 28 * @var array 29 */ 30 private $tpldata = array('.' => array(0 => array())); 31 32 /** 33 * @var array Reference to template->tpldata['.'][0] 34 */ 35 private $rootref; 36 37 /** 38 * @var bool 39 */ 40 private $num_rows_is_set; 41 42 public function __construct() 43 { 44 $this->clear(); 45 } 46 47 /** 48 * Clears template data set. 49 */ 50 public function clear() 51 { 52 $this->tpldata = array('.' => array(0 => array())); 53 $this->rootref = &$this->tpldata['.'][0]; 54 $this->num_rows_is_set = false; 55 } 56 57 /** 58 * Assign a single scalar value to a single key. 59 * 60 * Value can be a string, an integer or a boolean. 61 * 62 * @param string $varname Variable name 63 * @param string $varval Value to assign to variable 64 * @return true 65 */ 66 public function assign_var($varname, $varval) 67 { 68 $this->rootref[$varname] = $varval; 69 70 return true; 71 } 72 73 /** 74 * Append text to the string value stored in a key. 75 * 76 * Text is appended using the string concatenation operator (.). 77 * 78 * @param string $varname Variable name 79 * @param string $varval Value to append to variable 80 * @return true 81 */ 82 public function append_var($varname, $varval) 83 { 84 $this->rootref[$varname] = (isset($this->rootref[$varname]) ? $this->rootref[$varname] : '') . $varval; 85 86 return true; 87 } 88 89 /** 90 * Retrieve a single scalar value from a single key. 91 * 92 * @param string $varname Variable name 93 * @return mixed Variable value, or null if not set 94 */ 95 public function retrieve_var($varname) 96 { 97 return isset($this->rootref[$varname]) ? $this->rootref[$varname] : null; 98 } 99 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |