JOOMLA中国
  • Joomla中国首页
  • 社区
  • 教程
  • 应用市场
  • B计划
Joomla! Framework TM
  • Namespace
  • Class
  • Tree
  • Deprecated

Namespaces

  • Composer
    • Autoload
  • Joomla
    • Application
      • Cli
        • Output
          • Processor
      • Web
    • Data
    • DI
      • Exception
    • Event
    • Filter
    • Input
    • Ldap
    • Registry
      • Format
    • Session
      • Storage
    • String
    • Uri
    • Utilities
  • None
  • PasswordCompat
    • binary
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Yaml
        • Exception
    • Polyfill
      • Util

Classes

  • AbstractRegistryFormat
  • Factory
  • Registry

Interfaces

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