[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/joomla/registry/src/ -> Registry.php (source)

   1  <?php
   2  /**
   3   * Part of the Joomla Framework Registry Package
   4   *
   5   * @copyright  Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
   6   * @license    GNU General Public License version 2 or later; see LICENSE
   7   */
   8  
   9  namespace Joomla\Registry;
  10  
  11  use Joomla\Utilities\ArrayHelper;
  12  
  13  /**
  14   * Registry class
  15   *
  16   * @since  1.0
  17   */
  18  class Registry implements \JsonSerializable, \ArrayAccess, \IteratorAggregate, \Countable
  19  {
  20      /**
  21       * Registry Object
  22       *
  23       * @var    \stdClass
  24       * @since  1.0
  25       */
  26      protected $data;
  27  
  28      /**
  29       * Flag if the Registry data object has been initialized
  30       *
  31       * @var    boolean
  32       * @since  1.5.2
  33       */
  34      protected $initialized = false;
  35  
  36      /**
  37       * Path separator
  38       *
  39       * @var    string
  40       * @since  1.4.0
  41       */
  42      public $separator = '.';
  43  
  44      /**
  45       * Constructor
  46       *
  47       * @param   mixed  $data  The data to bind to the new Registry object.
  48       *
  49       * @since   1.0
  50       */
  51  	public function __construct($data = null)
  52      {
  53          // Instantiate the internal data object.
  54          $this->data = new \stdClass;
  55  
  56          // Optionally load supplied data.
  57          if ($data instanceof self)
  58          {
  59              $this->merge($data);
  60          }
  61          elseif (\is_array($data) || \is_object($data))
  62          {
  63              $this->bindData($this->data, $data);
  64          }
  65          elseif (!empty($data) && \is_string($data))
  66          {
  67              $this->loadString($data);
  68          }
  69      }
  70  
  71      /**
  72       * Magic function to clone the registry object.
  73       *
  74       * @return  void
  75       *
  76       * @since   1.0
  77       */
  78  	public function __clone()
  79      {
  80          $this->data = unserialize(serialize($this->data));
  81      }
  82  
  83      /**
  84       * Magic function to render this object as a string using default args of toString method.
  85       *
  86       * @return  string
  87       *
  88       * @since   1.0
  89       */
  90  	public function __toString()
  91      {
  92          return $this->toString();
  93      }
  94  
  95      /**
  96       * Count elements of the data object
  97       *
  98       * @return  integer  The custom count as an integer.
  99       *
 100       * @link    https://www.php.net/manual/en/countable.count.php
 101       * @since   1.3.0
 102       */
 103      #[\ReturnTypeWillChange]
 104  	public function count()
 105      {
 106          return \count(get_object_vars($this->data));
 107      }
 108  
 109      /**
 110       * Implementation for the JsonSerializable interface.
 111       * Allows us to pass Registry objects to json_encode.
 112       *
 113       * @return  object
 114       *
 115       * @since   1.0
 116       * @note    The interface is only present in PHP 5.4 and up.
 117       */
 118      #[\ReturnTypeWillChange]
 119  	public function jsonSerialize()
 120      {
 121          return $this->data;
 122      }
 123  
 124      /**
 125       * Sets a default value if not already assigned.
 126       *
 127       * @param   string  $key      The name of the parameter.
 128       * @param   mixed   $default  An optional value for the parameter.
 129       *
 130       * @return  mixed  The value set, or the default if the value was not previously set (or null).
 131       *
 132       * @since   1.0
 133       */
 134  	public function def($key, $default = '')
 135      {
 136          $value = $this->get($key, $default);
 137          $this->set($key, $value);
 138  
 139          return $value;
 140      }
 141  
 142      /**
 143       * Check if a registry path exists.
 144       *
 145       * @param   string  $path  Registry path (e.g. joomla.content.showauthor)
 146       *
 147       * @return  boolean
 148       *
 149       * @since   1.0
 150       */
 151  	public function exists($path)
 152      {
 153          // Return default value if path is empty
 154          if (empty($path))
 155          {
 156              return false;
 157          }
 158  
 159          // Explode the registry path into an array
 160          $nodes = explode($this->separator, $path);
 161  
 162          // Initialize the current node to be the registry root.
 163          $node  = $this->data;
 164          $found = false;
 165  
 166          // Traverse the registry to find the correct node for the result.
 167          foreach ($nodes as $n)
 168          {
 169              if (\is_array($node) && isset($node[$n]))
 170              {
 171                  $node  = $node[$n];
 172                  $found = true;
 173  
 174                  continue;
 175              }
 176  
 177              if (!isset($node->$n))
 178              {
 179                  return false;
 180              }
 181  
 182              $node  = $node->$n;
 183              $found = true;
 184          }
 185  
 186          return $found;
 187      }
 188  
 189      /**
 190       * Get a registry value.
 191       *
 192       * @param   string  $path     Registry path (e.g. joomla.content.showauthor)
 193       * @param   mixed   $default  Optional default value, returned if the internal value is null.
 194       *
 195       * @return  mixed  Value of entry or null
 196       *
 197       * @since   1.0
 198       */
 199  	public function get($path, $default = null)
 200      {
 201          // Return default value if path is empty
 202          if (empty($path))
 203          {
 204              return $default;
 205          }
 206  
 207          if (!strpos($path, $this->separator))
 208          {
 209              return (isset($this->data->$path) && $this->data->$path !== null && $this->data->$path !== '') ? $this->data->$path : $default;
 210          }
 211  
 212          // Explode the registry path into an array
 213          $nodes = explode($this->separator, trim($path));
 214  
 215          // Initialize the current node to be the registry root.
 216          $node  = $this->data;
 217          $found = false;
 218  
 219          // Traverse the registry to find the correct node for the result.
 220          foreach ($nodes as $n)
 221          {
 222              if (\is_array($node) && isset($node[$n]))
 223              {
 224                  $node  = $node[$n];
 225                  $found = true;
 226  
 227                  continue;
 228              }
 229  
 230              if (!isset($node->$n))
 231              {
 232                  return $default;
 233              }
 234  
 235              $node  = $node->$n;
 236              $found = true;
 237          }
 238  
 239          if (!$found || $node === null || $node === '')
 240          {
 241              return $default;
 242          }
 243  
 244          return $node;
 245      }
 246  
 247      /**
 248       * Gets this object represented as an ArrayIterator.
 249       *
 250       * This allows the data properties to be accessed via a foreach statement.
 251       *
 252       * @return  \ArrayIterator  This object represented as an ArrayIterator.
 253       *
 254       * @see     IteratorAggregate::getIterator()
 255       * @since   1.3.0
 256       */
 257      #[\ReturnTypeWillChange]
 258  	public function getIterator()
 259      {
 260          return new \ArrayIterator($this->data);
 261      }
 262  
 263      /**
 264       * Load an associative array of values into the default namespace
 265       *
 266       * @param   array    $array      Associative array of value to load
 267       * @param   boolean  $flattened  Load from a one-dimensional array
 268       * @param   string   $separator  The key separator
 269       *
 270       * @return  $this
 271       *
 272       * @since   1.0
 273       */
 274  	public function loadArray(array $array, $flattened = false, $separator = null)
 275      {
 276          if (!$flattened)
 277          {
 278              $this->bindData($this->data, $array);
 279  
 280              return $this;
 281          }
 282  
 283          foreach ($array as $k => $v)
 284          {
 285              $this->set($k, $v, $separator);
 286          }
 287  
 288          return $this;
 289      }
 290  
 291      /**
 292       * Load the public variables of the object into the default namespace.
 293       *
 294       * @param   object  $object  The object holding the publics to load
 295       *
 296       * @return  $this
 297       *
 298       * @since   1.0
 299       */
 300  	public function loadObject($object)
 301      {
 302          $this->bindData($this->data, $object);
 303  
 304          return $this;
 305      }
 306  
 307      /**
 308       * Load the contents of a file into the registry
 309       *
 310       * @param   string  $file     Path to file to load
 311       * @param   string  $format   Format of the file [optional: defaults to JSON]
 312       * @param   array   $options  Options used by the formatter
 313       *
 314       * @return  $this
 315       *
 316       * @since   1.0
 317       */
 318  	public function loadFile($file, $format = 'JSON', array $options = [])
 319      {
 320          $data = file_get_contents($file);
 321  
 322          return $this->loadString($data, $format, $options);
 323      }
 324  
 325      /**
 326       * Load a string into the registry
 327       *
 328       * @param   string  $data     String to load into the registry
 329       * @param   string  $format   Format of the string
 330       * @param   array   $options  Options used by the formatter
 331       *
 332       * @return  $this
 333       *
 334       * @since   1.0
 335       */
 336  	public function loadString($data, $format = 'JSON', array $options = [])
 337      {
 338          // Load a string into the given namespace [or default namespace if not given]
 339          $obj = Factory::getFormat($format, $options)->stringToObject($data, $options);
 340  
 341          // If the data object has not yet been initialized, direct assign the object
 342          if (!$this->initialized)
 343          {
 344              $this->data        = $obj;
 345              $this->initialized = true;
 346  
 347              return $this;
 348          }
 349  
 350          $this->loadObject($obj);
 351  
 352          return $this;
 353      }
 354  
 355      /**
 356       * Merge a Registry object into this one
 357       *
 358       * @param   Registry  $source     Source Registry object to merge.
 359       * @param   boolean   $recursive  True to support recursive merge the children values.
 360       *
 361       * @return  $this
 362       *
 363       * @since   1.0
 364       */
 365  	public function merge(Registry $source, $recursive = false)
 366      {
 367          $this->bindData($this->data, $source->toArray(), $recursive, false);
 368  
 369          return $this;
 370      }
 371  
 372      /**
 373       * Method to extract a sub-registry from path
 374       *
 375       * @param   string  $path  Registry path (e.g. joomla.content.showauthor)
 376       *
 377       * @return  Registry  Registry object (empty if no data is present)
 378       *
 379       * @since   1.2.0
 380       */
 381  	public function extract($path)
 382      {
 383          $data = $this->get($path);
 384  
 385          return new Registry($data);
 386      }
 387  
 388      /**
 389       * Checks whether an offset exists in the iterator.
 390       *
 391       * @param   mixed  $offset  The array offset.
 392       *
 393       * @return  boolean  True if the offset exists, false otherwise.
 394       *
 395       * @since   1.0
 396       */
 397      #[\ReturnTypeWillChange]
 398  	public function offsetExists($offset)
 399      {
 400          return $this->exists($offset);
 401      }
 402  
 403      /**
 404       * Gets an offset in the iterator.
 405       *
 406       * @param   mixed  $offset  The array offset.
 407       *
 408       * @return  mixed  The array value if it exists, null otherwise.
 409       *
 410       * @since   1.0
 411       */
 412      #[\ReturnTypeWillChange]
 413  	public function offsetGet($offset)
 414      {
 415          return $this->get($offset);
 416      }
 417  
 418      /**
 419       * Sets an offset in the iterator.
 420       *
 421       * @param   mixed  $offset  The array offset.
 422       * @param   mixed  $value   The array value.
 423       *
 424       * @return  void
 425       *
 426       * @since   1.0
 427       */
 428      #[\ReturnTypeWillChange]
 429  	public function offsetSet($offset, $value)
 430      {
 431          $this->set($offset, $value);
 432      }
 433  
 434      /**
 435       * Unsets an offset in the iterator.
 436       *
 437       * @param   mixed  $offset  The array offset.
 438       *
 439       * @return  void
 440       *
 441       * @since   1.0
 442       */
 443      #[\ReturnTypeWillChange]
 444  	public function offsetUnset($offset)
 445      {
 446          $this->remove($offset);
 447      }
 448  
 449      /**
 450       * Set a registry value.
 451       *
 452       * @param   string  $path       Registry Path (e.g. joomla.content.showauthor)
 453       * @param   mixed   $value      Value of entry
 454       * @param   string  $separator  The key separator
 455       *
 456       * @return  mixed  The value of the that has been set.
 457       *
 458       * @since   1.0
 459       */
 460  	public function set($path, $value, $separator = null)
 461      {
 462          if (empty($separator))
 463          {
 464              $separator = $this->separator;
 465          }
 466  
 467          /*
 468           * Explode the registry path into an array and remove empty
 469           * nodes that occur as a result of a double separator. ex: joomla..test
 470           * Finally, re-key the array so they are sequential.
 471           */
 472          $nodes = array_values(array_filter(explode($separator, $path), 'strlen'));
 473  
 474          if (!$nodes)
 475          {
 476              return;
 477          }
 478  
 479          // Initialize the current node to be the registry root.
 480          $node = $this->data;
 481  
 482          // Traverse the registry to find the correct node for the result.
 483          for ($i = 0, $n = \count($nodes) - 1; $i < $n; $i++)
 484          {
 485              if (\is_object($node))
 486              {
 487                  if (!isset($node->{$nodes[$i]}) && ($i !== $n))
 488                  {
 489                      $node->{$nodes[$i]} = new \stdClass;
 490                  }
 491  
 492                  // Pass the child as pointer in case it is an object
 493                  $node = &$node->{$nodes[$i]};
 494  
 495                  continue;
 496              }
 497  
 498              if (\is_array($node))
 499              {
 500                  if (($i !== $n) && !isset($node[$nodes[$i]]))
 501                  {
 502                      $node[$nodes[$i]] = new \stdClass;
 503                  }
 504  
 505                  // Pass the child as pointer in case it is an array
 506                  $node = &$node[$nodes[$i]];
 507              }
 508          }
 509  
 510          // Get the old value if exists so we can return it
 511          switch (true)
 512          {
 513              case \is_object($node):
 514                  $result = $node->{$nodes[$i]} = $value;
 515  
 516                  break;
 517  
 518              case \is_array($node):
 519                  $result = $node[$nodes[$i]] = $value;
 520  
 521                  break;
 522  
 523              default:
 524                  $result = null;
 525  
 526                  break;
 527          }
 528  
 529          return $result;
 530      }
 531  
 532      /**
 533       * Append value to a path in registry
 534       *
 535       * @param   string  $path   Parent registry Path (e.g. joomla.content.showauthor)
 536       * @param   mixed   $value  Value of entry
 537       *
 538       * @return  mixed  The value of the that has been set.
 539       *
 540       * @since   1.4.0
 541       */
 542  	public function append($path, $value)
 543      {
 544          $result = null;
 545  
 546          /*
 547           * Explode the registry path into an array and remove empty
 548           * nodes that occur as a result of a double dot. ex: joomla..test
 549           * Finally, re-key the array so they are sequential.
 550           */
 551          $nodes = array_values(array_filter(explode('.', $path), 'strlen'));
 552  
 553          if ($nodes)
 554          {
 555              // Initialize the current node to be the registry root.
 556              $node = $this->data;
 557  
 558              // Traverse the registry to find the correct node for the result.
 559              // TODO Create a new private method from part of code below, as it is almost equal to 'set' method
 560              for ($i = 0, $n = \count($nodes) - 1; $i <= $n; $i++)
 561              {
 562                  if (\is_object($node))
 563                  {
 564                      if (!isset($node->{$nodes[$i]}) && ($i !== $n))
 565                      {
 566                          $node->{$nodes[$i]} = new \stdClass;
 567                      }
 568  
 569                      // Pass the child as pointer in case it is an array
 570                      $node = &$node->{$nodes[$i]};
 571                  }
 572                  elseif (\is_array($node))
 573                  {
 574                      if (($i !== $n) && !isset($node[$nodes[$i]]))
 575                      {
 576                          $node[$nodes[$i]] = new \stdClass;
 577                      }
 578  
 579                      // Pass the child as pointer in case it is an array
 580                      $node = &$node[$nodes[$i]];
 581                  }
 582              }
 583  
 584              if (!\is_array($node))
 585              {
 586                  // Convert the node to array to make append possible
 587                  $node = get_object_vars($node);
 588              }
 589  
 590              $node[] = $value;
 591              $result = $value;
 592          }
 593  
 594          return $result;
 595      }
 596  
 597      /**
 598       * Delete a registry value
 599       *
 600       * @param   string  $path  Registry Path (e.g. joomla.content.showauthor)
 601       *
 602       * @return  mixed  The value of the removed node or null if not set
 603       *
 604       * @since   1.6.0
 605       */
 606  	public function remove($path)
 607      {
 608          // Cheap optimisation to direct remove the node if there is no separator
 609          if (!strpos($path, $this->separator))
 610          {
 611              $result = (isset($this->data->$path) && $this->data->$path !== null && $this->data->$path !== '') ? $this->data->$path : null;
 612  
 613              unset($this->data->$path);
 614  
 615              return $result;
 616          }
 617  
 618          /*
 619           * Explode the registry path into an array and remove empty
 620           * nodes that occur as a result of a double separator. ex: joomla..test
 621           * Finally, re-key the array so they are sequential.
 622           */
 623          $nodes = array_values(array_filter(explode($this->separator, $path), 'strlen'));
 624  
 625          if (!$nodes)
 626          {
 627              return;
 628          }
 629  
 630          // Initialize the current node to be the registry root.
 631          $node   = $this->data;
 632          $parent = null;
 633  
 634          // Traverse the registry to find the correct node for the result.
 635          for ($i = 0, $n = \count($nodes) - 1; $i < $n; $i++)
 636          {
 637              if (\is_object($node))
 638              {
 639                  if (!isset($node->{$nodes[$i]}) && ($i !== $n))
 640                  {
 641                      continue;
 642                  }
 643  
 644                  $parent = &$node;
 645                  $node   = $node->{$nodes[$i]};
 646  
 647                  continue;
 648              }
 649  
 650              if (\is_array($node))
 651              {
 652                  if (($i !== $n) && !isset($node[$nodes[$i]]))
 653                  {
 654                      continue;
 655                  }
 656  
 657                  $parent = &$node;
 658                  $node   = $node[$nodes[$i]];
 659  
 660                  continue;
 661              }
 662          }
 663  
 664          // Get the old value if exists so we can return it
 665          switch (true)
 666          {
 667              case \is_object($node):
 668                  $result = $node->{$nodes[$i]} ?? null;
 669                  unset($parent->{$nodes[$i]});
 670  
 671                  break;
 672  
 673              case \is_array($node):
 674                  $result = $node[$nodes[$i]] ?? null;
 675                  unset($parent[$nodes[$i]]);
 676  
 677                  break;
 678  
 679              default:
 680                  $result = null;
 681  
 682                  break;
 683          }
 684  
 685          return $result;
 686      }
 687  
 688      /**
 689       * Transforms a namespace to an array
 690       *
 691       * @return  array  An associative array holding the namespace data
 692       *
 693       * @since   1.0
 694       */
 695  	public function toArray()
 696      {
 697          return (array) $this->asArray($this->data);
 698      }
 699  
 700      /**
 701       * Transforms a namespace to an object
 702       *
 703       * @return  object   An an object holding the namespace data
 704       *
 705       * @since   1.0
 706       */
 707  	public function toObject()
 708      {
 709          return $this->data;
 710      }
 711  
 712      /**
 713       * Get a namespace in a given string format
 714       *
 715       * @param   string  $format   Format to return the string in
 716       * @param   array   $options  Parameters used by the formatter, see formatters for more info
 717       *
 718       * @return  string   Namespace in string format
 719       *
 720       * @since   1.0
 721       */
 722  	public function toString($format = 'JSON', array $options = [])
 723      {
 724          return Factory::getFormat($format, $options)->objectToString($this->data, $options);
 725      }
 726  
 727      /**
 728       * Method to recursively bind data to a parent object.
 729       *
 730       * @param   object   $parent     The parent object on which to attach the data values.
 731       * @param   mixed    $data       An array or object of data to bind to the parent object.
 732       * @param   boolean  $recursive  True to support recursive bindData.
 733       * @param   boolean  $allowNull  True to allow null values.
 734       *
 735       * @return  void
 736       *
 737       * @since   1.0
 738       */
 739  	protected function bindData($parent, $data, $recursive = true, $allowNull = true)
 740      {
 741          // The data object is now initialized
 742          $this->initialized = true;
 743  
 744          // Ensure the input data is an array.
 745          $data = \is_object($data) ? get_object_vars($data) : (array) $data;
 746  
 747          foreach ($data as $k => $v)
 748          {
 749              if (!$allowNull && !(($v !== null) && ($v !== '')))
 750              {
 751                  continue;
 752              }
 753  
 754              if ($recursive && ((\is_array($v) && ArrayHelper::isAssociative($v)) || \is_object($v)))
 755              {
 756                  if (!isset($parent->$k))
 757                  {
 758                      $parent->$k = new \stdClass;
 759                  }
 760  
 761                  $this->bindData($parent->$k, $v);
 762  
 763                  continue;
 764              }
 765  
 766              $parent->$k = $v;
 767          }
 768      }
 769  
 770      /**
 771       * Method to recursively convert an object of data to an array.
 772       *
 773       * @param   object  $data  An object of data to return as an array.
 774       *
 775       * @return  array  Array representation of the input object.
 776       *
 777       * @since   1.0
 778       */
 779  	protected function asArray($data)
 780      {
 781          $array = [];
 782  
 783          if (\is_object($data))
 784          {
 785              $data = get_object_vars($data);
 786          }
 787  
 788          foreach ($data as $k => $v)
 789          {
 790              if (\is_object($v) || \is_array($v))
 791              {
 792                  $array[$k] = $this->asArray($v);
 793  
 794                  continue;
 795              }
 796  
 797              $array[$k] = $v;
 798          }
 799  
 800          return $array;
 801      }
 802  
 803      /**
 804       * Dump to one dimension array.
 805       *
 806       * @param   string  $separator  The key separator.
 807       *
 808       * @return  string[]  Dumped array.
 809       *
 810       * @since   1.3.0
 811       */
 812  	public function flatten($separator = null)
 813      {
 814          $array = [];
 815  
 816          if (empty($separator))
 817          {
 818              $separator = $this->separator;
 819          }
 820  
 821          $this->toFlatten($separator, $this->data, $array);
 822  
 823          return $array;
 824      }
 825  
 826      /**
 827       * Method to recursively convert data to one dimension array.
 828       *
 829       * @param   string        $separator  The key separator.
 830       * @param   array|object  $data       Data source of this scope.
 831       * @param   array         $array      The result array, it is passed by reference.
 832       * @param   string        $prefix     Last level key prefix.
 833       *
 834       * @return  void
 835       *
 836       * @since   1.3.0
 837       */
 838  	protected function toFlatten($separator = null, $data = null, array &$array = [], $prefix = '')
 839      {
 840          $data = (array) $data;
 841  
 842          if (empty($separator))
 843          {
 844              $separator = $this->separator;
 845          }
 846  
 847          foreach ($data as $k => $v)
 848          {
 849              $key = $prefix ? $prefix . $separator . $k : $k;
 850  
 851              if (\is_object($v) || \is_array($v))
 852              {
 853                  $this->toFlatten($separator, $v, $array, $key);
 854  
 855                  continue;
 856              }
 857  
 858              $array[$key] = $v;
 859          }
 860      }
 861  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer