[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |