[ Index ]

PHP Cross Reference of phpBB-3.3.7-deutsch

title

Body

[close]

/phpbb/template/ -> context.php (source)

   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  }


Generated: Thu Mar 24 21:31:15 2022 Cross-referenced by PHPXref 0.7.1