[ Index ]

PHP Cross Reference of phpBB-3.2.8-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      * Retreive 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                  // aswell.
 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              list($search_key, $search_value) = @each($key);
 388              foreach ($block as $i => $val_ary)
 389              {
 390                  if ($val_ary[$search_key] === $search_value)
 391                  {
 392                      return $i;
 393                  }
 394              }
 395          }
 396  
 397          return (is_int($key) && ((0 <= $key) && ($key < count($block)))) ? $key : false;
 398      }
 399  
 400      /**
 401      * Change already assigned key variable pair (one-dimensional - single loop entry)
 402      *
 403      * An example of how to use this function:
 404      * {@example alter_block_array.php}
 405      *
 406      * @param    string    $blockname    the blockname, for example 'loop'
 407      * @param    array    $vararray    the var array to insert/add or merge
 408      * @param    mixed    $key        Key to search for
 409      *
 410      * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position]
 411      *
 412      * int: Position [the position to change or insert at directly given]
 413      *
 414      * If key is false the position is set to 0
 415      * If key is true the position is set to the last entry
 416      *
 417      * @param    string    $mode        Mode to execute (valid modes are 'insert', 'change' and 'delete')
 418      *
 419      *    If insert, the vararray is inserted at the given position (position counting from zero).
 420      *    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).
 421      *    If delete, the vararray is ignored, and the block at the given position (counting from zero) is removed.
 422      *
 423      * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)
 424      * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars)
 425      *
 426      * @return bool false on error, true on success
 427      */
 428  	public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert')
 429      {
 430          $this->num_rows_is_set = false;
 431  
 432          // For nested block, $blockcount > 0, for top-level block, $blockcount == 0
 433          $blocks = explode('.', $blockname);
 434          $blockcount = count($blocks) - 1;
 435  
 436          $block = &$this->tpldata;
 437          for ($i = 0; $i < $blockcount; $i++)
 438          {
 439              if (($pos = strpos($blocks[$i], '[')) !== false)
 440              {
 441                  $name = substr($blocks[$i], 0, $pos);
 442  
 443                  if (strpos($blocks[$i], '[]') === $pos)
 444                  {
 445                      $index = count($block[$name]) - 1;
 446                  }
 447                  else
 448                  {
 449                      $index = min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1);
 450                  }
 451              }
 452              else
 453              {
 454                  $name = $blocks[$i];
 455                  $index = count($block[$name]) - 1;
 456              }
 457              $block = &$block[$name];
 458              $block = &$block[$index];
 459          }
 460          $name = $blocks[$i];
 461  
 462          // If last block does not exist and we are inserting, and not searching for key, we create it empty; otherwise, nothing to do
 463          if (!isset($block[$name]))
 464          {
 465              if ($mode != 'insert' || is_array($key))
 466              {
 467                  return false;
 468              }
 469              $block[$name] = array();
 470          }
 471  
 472          $block = &$block[$name]; // Now we can traverse the last block
 473  
 474          // Change key to zero (change first position) if false and to last position if true
 475          if ($key === false || $key === true)
 476          {
 477              $key = ($key === false) ? 0 : count($block);
 478          }
 479  
 480          // Get correct position if array given
 481          if (is_array($key))
 482          {
 483              // Search array to get correct position
 484              list($search_key, $search_value) = @each($key);
 485  
 486              $key = null;
 487              foreach ($block as $i => $val_ary)
 488              {
 489                  if ($val_ary[$search_key] === $search_value)
 490                  {
 491                      $key = $i;
 492                      break;
 493                  }
 494              }
 495  
 496              // key/value pair not found
 497              if ($key === null)
 498              {
 499                  return false;
 500              }
 501          }
 502  
 503          // Insert Block
 504          if ($mode == 'insert')
 505          {
 506              // Make sure we are not exceeding the last iteration
 507              if ($key >= count($block))
 508              {
 509                  $key = count($block);
 510                  unset($block[($key - 1)]['S_LAST_ROW']);
 511                  $vararray['S_LAST_ROW'] = true;
 512              }
 513              if ($key <= 0)
 514              {
 515                  $key = 0;
 516                  unset($block[0]['S_FIRST_ROW']);
 517                  $vararray['S_FIRST_ROW'] = true;
 518              }
 519  
 520              // Assign S_BLOCK_NAME
 521              $vararray['S_BLOCK_NAME'] = $name;
 522  
 523              // Re-position template blocks
 524              for ($i = count($block); $i > $key; $i--)
 525              {
 526                  $block[$i] = $block[$i-1];
 527  
 528                  $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i;
 529              }
 530  
 531              // Insert vararray at given position
 532              $block[$key] = $vararray;
 533              $block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key;
 534  
 535              return true;
 536          }
 537  
 538          // Which block to change?
 539          if ($mode == 'change')
 540          {
 541              // If key is out of bounds, do not change anything
 542              if ($key > count($block) || $key < 0)
 543              {
 544                  return false;
 545              }
 546  
 547              if ($key == count($block))
 548              {
 549                  $key--;
 550              }
 551  
 552              $block[$key] = array_merge($block[$key], $vararray);
 553  
 554              return true;
 555          }
 556  
 557          // Delete Block
 558          if ($mode == 'delete')
 559          {
 560              // If we are exceeding last iteration, do not delete anything
 561              if ($key > count($block) || $key < 0)
 562              {
 563                  return false;
 564              }
 565  
 566              // If we are positioned at the end, we remove the last element
 567              if ($key == count($block))
 568              {
 569                  $key--;
 570              }
 571  
 572              // We are deleting the last element in the block, so remove the block
 573              if (count($block) === 1)
 574              {
 575                  $block = null; // unset($block); does not work on references
 576                  return true;
 577              }
 578  
 579              // Re-position template blocks
 580              for ($i = $key; $i < count($block)-1; $i++)
 581              {
 582                  $block[$i] = $block[$i+1];
 583                  $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i;
 584              }
 585  
 586              // Remove the last element
 587              unset($block[$i]);
 588  
 589              // Set first and last elements again, in case they were removed
 590              $block[0]['S_FIRST_ROW'] = true;
 591              $block[count($block)-1]['S_LAST_ROW'] = true;
 592  
 593              return true;
 594          }
 595  
 596          return false;
 597      }
 598  
 599      /**
 600      * Reset/empty complete block
 601      *
 602      * @param string $blockname Name of block to destroy
 603      * @return true
 604      */
 605  	public function destroy_block_vars($blockname)
 606      {
 607          $this->num_rows_is_set = false;
 608          if (strpos($blockname, '.') !== false)
 609          {
 610              // Nested block.
 611              $blocks = explode('.', $blockname);
 612              $blockcount = count($blocks) - 1;
 613  
 614              $str = &$this->tpldata;
 615              for ($i = 0; $i < $blockcount; $i++)
 616              {
 617                  $str = &$str[$blocks[$i]];
 618                  $str = &$str[count($str) - 1];
 619              }
 620  
 621              unset($str[$blocks[$blockcount]]);
 622          }
 623          else
 624          {
 625              // Top-level block.
 626              unset($this->tpldata[$blockname]);
 627          }
 628  
 629          return true;
 630      }
 631  }


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1