Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
registry.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Registry
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 jimport('joomla.utilities.arrayhelper');
13 
14 /**
15  * JRegistry class
16  *
17  * @package Joomla.Platform
18  * @subpackage Registry
19  * @since 11.1
20  */
21 class JRegistry implements JsonSerializable
22 {
23  /**
24  * Registry Object
25  *
26  * @var object
27  * @since 11.1
28  */
29  protected $data;
30 
31  /**
32  * @var array JRegistry instances container.
33  * @since 11.3
34  */
35  protected static $instances = array();
36 
37  /**
38  * Constructor
39  *
40  * @param mixed $data The data to bind to the new JRegistry object.
41  *
42  * @since 11.1
43  */
44  public function __construct($data = null)
45  {
46  // Instantiate the internal data object.
47  $this->data = new stdClass;
48 
49  // Optionally load supplied data.
50  if (is_array($data) || is_object($data))
51  {
52  $this->bindData($this->data, $data);
53  }
54  elseif (!empty($data) && is_string($data))
55  {
56  $this->loadString($data);
57  }
58  }
59 
60  /**
61  * Magic function to clone the registry object.
62  *
63  * @return JRegistry
64  *
65  * @since 11.1
66  */
67  public function __clone()
68  {
69  $this->data = unserialize(serialize($this->data));
70  }
71 
72  /**
73  * Magic function to render this object as a string using default args of toString method.
74  *
75  * @return string
76  *
77  * @since 11.1
78  */
79  public function __toString()
80  {
81  return $this->toString();
82  }
83 
84  /**
85  * Implementation for the JsonSerializable interface.
86  * Allows us to pass JRegistry objects to json_encode.
87  *
88  * @return object
89  *
90  * @since 12.2
91  * @note The interface is only present in PHP 5.4 and up.
92  */
93  public function jsonSerialize()
94  {
95  return $this->data;
96  }
97 
98  /**
99  * Sets a default value if not already assigned.
100  *
101  * @param string $key The name of the parameter.
102  * @param mixed $default An optional value for the parameter.
103  *
104  * @return mixed The value set, or the default if the value was not previously set (or null).
105  *
106  * @since 11.1
107  */
108  public function def($key, $default = '')
109  {
110  $value = $this->get($key, $default);
111  $this->set($key, $value);
112 
113  return $value;
114  }
115 
116  /**
117  * Check if a registry path exists.
118  *
119  * @param string $path Registry path (e.g. joomla.content.showauthor)
120  *
121  * @return boolean
122  *
123  * @since 11.1
124  */
125  public function exists($path)
126  {
127  // Explode the registry path into an array
128  if ($nodes = explode('.', $path))
129  {
130  // Initialize the current node to be the registry root.
131  $node = $this->data;
132 
133  // Traverse the registry to find the correct node for the result.
134  for ($i = 0, $n = count($nodes); $i < $n; $i++)
135  {
136  if (isset($node->$nodes[$i]))
137  {
138  $node = $node->$nodes[$i];
139  }
140  else
141  {
142  break;
143  }
144 
145  if ($i + 1 == $n)
146  {
147  return true;
148  }
149  }
150  }
151 
152  return false;
153  }
154 
155  /**
156  * Get a registry value.
157  *
158  * @param string $path Registry path (e.g. joomla.content.showauthor)
159  * @param mixed $default Optional default value, returned if the internal value is null.
160  *
161  * @return mixed Value of entry or null
162  *
163  * @since 11.1
164  */
165  public function get($path, $default = null)
166  {
167  $result = $default;
168 
169  if (!strpos($path, '.'))
170  {
171  return (isset($this->data->$path) && $this->data->$path !== null && $this->data->$path !== '') ? $this->data->$path : $default;
172  }
173 
174  // Explode the registry path into an array
175  $nodes = explode('.', $path);
176 
177  // Initialize the current node to be the registry root.
178  $node = $this->data;
179  $found = false;
180 
181  // Traverse the registry to find the correct node for the result.
182  foreach ($nodes as $n)
183  {
184  if (isset($node->$n))
185  {
186  $node = $node->$n;
187  $found = true;
188  }
189  else
190  {
191  $found = false;
192  break;
193  }
194  }
195 
196  if ($found && $node !== null && $node !== '')
197  {
198  $result = $node;
199  }
200 
201  return $result;
202  }
203 
204  /**
205  * Returns a reference to a global JRegistry object, only creating it
206  * if it doesn't already exist.
207  *
208  * This method must be invoked as:
209  * <pre>$registry = JRegistry::getInstance($id);</pre>
210  *
211  * @param string $id An ID for the registry instance
212  *
213  * @return JRegistry The JRegistry object.
214  *
215  * @since 11.1
216  */
217  public static function getInstance($id)
218  {
219  if (empty(self::$instances[$id]))
220  {
221  self::$instances[$id] = new JRegistry;
222  }
223 
224  return self::$instances[$id];
225  }
226 
227  /**
228  * Load a associative array of values into the default namespace
229  *
230  * @param array $array Associative array of value to load
231  *
232  * @return boolean True on success
233  *
234  * @since 11.1
235  */
236  public function loadArray($array)
237  {
238  $this->bindData($this->data, $array);
239 
240  return true;
241  }
242 
243  /**
244  * Load the public variables of the object into the default namespace.
245  *
246  * @param object $object The object holding the publics to load
247  *
248  * @return boolean True on success
249  *
250  * @since 11.1
251  */
252  public function loadObject($object)
253  {
254  $this->bindData($this->data, $object);
255 
256  return true;
257  }
258 
259  /**
260  * Load the contents of a file into the registry
261  *
262  * @param string $file Path to file to load
263  * @param string $format Format of the file [optional: defaults to JSON]
264  * @param array $options Options used by the formatter
265  *
266  * @return boolean True on success
267  *
268  * @since 11.1
269  */
270  public function loadFile($file, $format = 'JSON', $options = array())
271  {
272  $data = file_get_contents($file);
273 
274  return $this->loadString($data, $format, $options);
275  }
276 
277  /**
278  * Load a string into the registry
279  *
280  * @param string $data String to load into the registry
281  * @param string $format Format of the string
282  * @param array $options Options used by the formatter
283  *
284  * @return boolean True on success
285  *
286  * @since 11.1
287  */
288  public function loadString($data, $format = 'JSON', $options = array())
289  {
290  // Load a string into the given namespace [or default namespace if not given]
291  $handler = JRegistryFormat::getInstance($format);
292 
293  $obj = $handler->stringToObject($data, $options);
294  $this->loadObject($obj);
295 
296  return true;
297  }
298 
299  /**
300  * Merge a JRegistry object into this one
301  *
302  * @param JRegistry $source Source JRegistry object to merge.
303  *
304  * @return boolean True on success
305  *
306  * @since 11.1
307  */
308  public function merge($source)
309  {
310  if (!$source instanceof JRegistry)
311  {
312  return false;
313  }
314 
315  // Load the variables into the registry's default namespace.
316  foreach ($source->toArray() as $k => $v)
317  {
318  if (($v !== null) && ($v !== ''))
319  {
320  $this->data->$k = $v;
321  }
322  }
323 
324  return true;
325  }
326 
327  /**
328  * Set a registry value.
329  *
330  * @param string $path Registry Path (e.g. joomla.content.showauthor)
331  * @param mixed $value Value of entry
332  *
333  * @return mixed The value of the that has been set.
334  *
335  * @since 11.1
336  */
337  public function set($path, $value)
338  {
339  $result = null;
340 
341  /**
342  * Explode the registry path into an array and remove empty
343  * nodes caused by passing in double dotted strings. ex: joomla..test.
344  * Finally, re-key the array so it is sequential.
345  */
346  $nodes = array_values(array_filter(explode('.', $path), 'strlen'));
347 
348  if ($nodes)
349  {
350  // Initialize the current node to be the registry root.
351  $node = $this->data;
352 
353  // Traverse the registry to find the correct node for the result.
354  for ($i = 0, $n = count($nodes) - 1; $i < $n; $i++)
355  {
356  if (!isset($node->$nodes[$i]) && ($i != $n))
357  {
358  $node->$nodes[$i] = new stdClass;
359  }
360 
361  $node = (object) $node->$nodes[$i];
362  }
363 
364  // Get the old value if exists so we can return it
365  $result = $node->$nodes[$i] = $value;
366  }
367 
368  return $result;
369  }
370 
371  /**
372  * Transforms a namespace to an array
373  *
374  * @return array An associative array holding the namespace data
375  *
376  * @since 11.1
377  */
378  public function toArray()
379  {
380  return (array) $this->asArray($this->data);
381  }
382 
383  /**
384  * Transforms a namespace to an object
385  *
386  * @return object An an object holding the namespace data
387  *
388  * @since 11.1
389  */
390  public function toObject()
391  {
392  return $this->data;
393  }
394 
395  /**
396  * Get a namespace in a given string format
397  *
398  * @param string $format Format to return the string in
399  * @param mixed $options Parameters used by the formatter, see formatters for more info
400  *
401  * @return string Namespace in string format
402  *
403  * @since 11.1
404  */
405  public function toString($format = 'JSON', $options = array())
406  {
407  // Return a namespace in a given format
408  $handler = JRegistryFormat::getInstance($format);
409 
410  return $handler->objectToString($this->data, $options);
411  }
412 
413  /**
414  * Method to recursively bind data to a parent object.
415  *
416  * @param object $parent The parent object on which to attach the data values.
417  * @param mixed $data An array or object of data to bind to the parent object.
418  *
419  * @return void
420  *
421  * @since 11.1
422  */
423  protected function bindData($parent, $data)
424  {
425  // Ensure the input data is an array.
426  if (is_object($data))
427  {
428  $data = get_object_vars($data);
429  }
430  else
431  {
432  $data = (array) $data;
433  }
434 
435  foreach ($data as $k => $v)
436  {
437  if ((is_array($v) && JArrayHelper::isAssociative($v)) || is_object($v))
438  {
439  $parent->$k = new stdClass;
440  $this->bindData($parent->$k, $v);
441  }
442  else
443  {
444  $parent->$k = $v;
445  }
446  }
447  }
448 
449  /**
450  * Method to recursively convert an object of data to an array.
451  *
452  * @param object $data An object of data to return as an array.
453  *
454  * @return array Array representation of the input object.
455  *
456  * @since 11.1
457  */
458  protected function asArray($data)
459  {
460  $array = array();
461 
462  foreach (get_object_vars((object) $data) as $k => $v)
463  {
464  if (is_object($v))
465  {
466  $array[$k] = $this->asArray($v);
467  }
468  else
469  {
470  $array[$k] = $v;
471  }
472  }
473 
474  return $array;
475  }
476 }