Source for file set.php

Documentation is available at set.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Data
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2011 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. /**
  13.  * JDataSet is a collection class that allows the developer to operate on a set of JData objects as if they were in a
  14.  * typical PHP array.
  15.  *
  16.  * @package     Joomla.Platform
  17.  * @subpackage  Data
  18.  * @since       12.3
  19.  */
  20. class JDataSet implements JDataDumpableArrayAccessCountableIterator
  21. {
  22.     /**
  23.      * The current position of the iterator.
  24.      *
  25.      * @var    integer 
  26.      * @since  12.3
  27.      */
  28.     private $_current false;
  29.  
  30.     /**
  31.      * The iterator objects.
  32.      *
  33.      * @var    array 
  34.      * @since  12.3
  35.      */
  36.     private $_objects array();
  37.  
  38.     /**
  39.      * The class constructor.
  40.      *
  41.      * @param   array  $objects  An array of JData objects to bind to the data set.
  42.      *
  43.      * @since   12.3
  44.      * @throws  InvalidArgumentException if an object is not an instance of JData.
  45.      */
  46.     public function __construct(array $objects array())
  47.     {
  48.         // Set the objects.
  49.         $this->_initialise($objects);
  50.     }
  51.  
  52.     /**
  53.      * The magic call method is used to call object methods using the iterator.
  54.      *
  55.      * Example: $array = $objectList->foo('bar');
  56.      *
  57.      * The object list will iterate over its objects and see if each object has a callable 'foo' method.
  58.      * If so, it will pass the argument list and assemble any return values. If an object does not have
  59.      * a callable method no return value is recorded.
  60.      * The keys of the objects and the result array are maintained.
  61.      *
  62.      * @param   string  $method     The name of the method called.
  63.      * @param   array   $arguments  The arguments of the method called.
  64.      *
  65.      * @return  array   An array of values returned by the methods called on the objects in the data set.
  66.      *
  67.      * @since   12.3
  68.      */
  69.     public function __call($method$arguments array())
  70.     {
  71.         $return array();
  72.  
  73.         // Iterate through the objects.
  74.         foreach ($this->_objects as $key => $object)
  75.         {
  76.             // Create the object callback.
  77.             $callback array($object$method);
  78.  
  79.             // Check if the callback is callable.
  80.             if (is_callable($callback))
  81.             {
  82.                 // Call the method for the object.
  83.                 $return[$keycall_user_func_array($callback$arguments);
  84.             }
  85.         }
  86.  
  87.         return $return;
  88.     }
  89.  
  90.     /**
  91.      * The magic get method is used to get a list of properties from the objects in the data set.
  92.      *
  93.      * Example: $array = $dataSet->foo;
  94.      *
  95.      * This will return a column of the values of the 'foo' property in all the objects
  96.      * (or values determined by custom property setters in the individual JData's).
  97.      * The result array will contain an entry for each object in the list (compared to __call which may not).
  98.      * The keys of the objects and the result array are maintained.
  99.      *
  100.      * @param   string  $property  The name of the data property.
  101.      *
  102.      * @return  array  An associative array of the values.
  103.      *
  104.      * @since   12.3
  105.      */
  106.     public function __get($property)
  107.     {
  108.         $return array();
  109.  
  110.         // Iterate through the objects.
  111.         foreach ($this->_objects as $key => $object)
  112.         {
  113.             // Get the property.
  114.             $return[$key$object->$property;
  115.         }
  116.  
  117.         return $return;
  118.     }
  119.  
  120.     /**
  121.      * The magic isset method is used to check the state of an object property using the iterator.
  122.      *
  123.      * Example: $array = isset($objectList->foo);
  124.      *
  125.      * @param   string  $property  The name of the property.
  126.      *
  127.      * @return  boolean  True if the property is set in any of the objects in the data set.
  128.      *
  129.      * @since   12.3
  130.      */
  131.     public function __isset($property)
  132.     {
  133.         $return array();
  134.  
  135.         // Iterate through the objects.
  136.         foreach ($this->_objects as $object)
  137.         {
  138.             // Check the property.
  139.             $return[= isset($object->$property);
  140.         }
  141.  
  142.         return in_array(true$returntruetrue false;
  143.     }
  144.  
  145.     /**
  146.      * The magic set method is used to set an object property using the iterator.
  147.      *
  148.      * Example: $objectList->foo = 'bar';
  149.      *
  150.      * This will set the 'foo' property to 'bar' in all of the objects
  151.      * (or a value determined by custom property setters in the JData).
  152.      *
  153.      * @param   string  $property  The name of the property.
  154.      * @param   mixed   $value     The value to give the data property.
  155.      *
  156.      * @return  void 
  157.      *
  158.      * @since   12.3
  159.      */
  160.     public function __set($property$value)
  161.     {
  162.         // Iterate through the objects.
  163.         foreach ($this->_objects as $object)
  164.         {
  165.             // Set the property.
  166.             $object->$property $value;
  167.         }
  168.     }
  169.  
  170.     /**
  171.      * The magic unset method is used to unset an object property using the iterator.
  172.      *
  173.      * Example: unset($objectList->foo);
  174.      *
  175.      * This will unset all of the 'foo' properties in the list of JData's.
  176.      *
  177.      * @param   string  $property  The name of the property.
  178.      *
  179.      * @return  void 
  180.      *
  181.      * @since   12.3
  182.      */
  183.     public function __unset($property)
  184.     {
  185.         // Iterate through the objects.
  186.         foreach ($this->_objects as $object)
  187.         {
  188.             unset($object->$property);
  189.         }
  190.     }
  191.  
  192.     /**
  193.      * Gets the number of data objects in the set.
  194.      *
  195.      * @return  integer  The number of objects.
  196.      *
  197.      * @since   12.3
  198.      */
  199.     public function count()
  200.     {
  201.         return count($this->_objects);
  202.     }
  203.  
  204.     /**
  205.      * Clears the objects in the data set.
  206.      *
  207.      * @return  JDataSet  Returns itself to allow chaining.
  208.      *
  209.      * @since   12.3
  210.      */
  211.     public function clear()
  212.     {
  213.         $this->_objects array();
  214.         $this->rewind();
  215.  
  216.         return $this;
  217.     }
  218.  
  219.     /**
  220.      * Get the current data object in the set.
  221.      *
  222.      * @return  JData  The current object, or false if the array is empty or the pointer is beyond the end of the elements.
  223.      *
  224.      * @since   12.3
  225.      */
  226.     public function current()
  227.     {
  228.         return is_scalar($this->_current$this->_objects[$this->_currentfalse;
  229.     }
  230.  
  231.     /**
  232.      * Dumps the data object in the set, recursively if appropriate.
  233.      *
  234.      * @param   integer           $depth   The maximum depth of recursion (default = 3).
  235.      *                                      For example, a depth of 0 will return a stdClass with all the properties in native
  236.      *                                      form. A depth of 1 will recurse into the first level of properties only.
  237.      * @param   SplObjectStorage  $dumped  An array of already serialized objects that is used to avoid infinite loops.
  238.      *
  239.      * @return  array  An associative array of the date objects in the set, dumped as a simple PHP stdClass object.
  240.      *
  241.      * @see     JData::dump()
  242.      * @since   12.3
  243.      */
  244.     public function dump($depth 3SplObjectStorage $dumped null)
  245.     {
  246.         // Check if we should initialise the recursion tracker.
  247.         if ($dumped === null)
  248.         {
  249.             $dumped new SplObjectStorage;
  250.         }
  251.  
  252.         // Add this object to the dumped stack.
  253.         $dumped->attach($this);
  254.  
  255.         $objects array();
  256.  
  257.         // Make sure that we have not reached our maximum depth.
  258.         if ($depth 0)
  259.         {
  260.             // Handle JSON serialization recursively.
  261.             foreach ($this->_objects as $key => $object)
  262.             {
  263.                 $objects[$key$object->dump($depth$dumped);
  264.             }
  265.         }
  266.  
  267.         return $objects;
  268.     }
  269.  
  270.     /**
  271.      * Gets the data set in a form that can be serialised to JSON format.
  272.      *
  273.      * Note that this method will not return an associative array, otherwise it would be encoded into an object.
  274.      * JSON decoders do not consistently maintain the order of associative keys, whereas they do maintain the order of arrays.
  275.      *
  276.      * @param   mixed  $serialized  An array of objects that have already been serialized that is used to infinite loops
  277.      *                               (null on first call).
  278.      *
  279.      * @return  array  An array that can be serialised by json_encode().
  280.      *
  281.      * @since   12.3
  282.      */
  283.     public function jsonSerialize($serialized null)
  284.     {
  285.         // Check if we should initialise the recursion tracker.
  286.         if ($serialized === null)
  287.         {
  288.             $serialized array();
  289.         }
  290.  
  291.         // Add this object to the serialized stack.
  292.         $serialized[spl_object_hash($this);
  293.         $return array();
  294.  
  295.         // Iterate through the objects.
  296.         foreach ($this->_objects as $object)
  297.         {
  298.             // Call the method for the object.
  299.             $return[$object->jsonSerialize($serialized);
  300.         }
  301.  
  302.         return $return;
  303.     }
  304.  
  305.     /**
  306.      * Gets the key of the current object in the iterator.
  307.      *
  308.      * @return  scalar  The object key on success; null on failure.
  309.      *
  310.      * @since   12.3
  311.      */
  312.     public function key()
  313.     {
  314.         return $this->_current;
  315.     }
  316.  
  317.     /**
  318.      * Gets the array of keys for all the objects in the iterator (emulates array_keys).
  319.      *
  320.      * @return  array  The array of keys
  321.      *
  322.      * @since   12.3
  323.      */
  324.     public function keys()
  325.     {
  326.         return array_keys($this->_objects);
  327.     }
  328.  
  329.     /**
  330.      * Advances the iterator to the next object in the iterator.
  331.      *
  332.      * @return  void 
  333.      *
  334.      * @since   12.3
  335.      */
  336.     public function next()
  337.     {
  338.         // Get the object offsets.
  339.         $keys $this->keys();
  340.  
  341.         // Check if _current has been set to false but offsetUnset.
  342.         if ($this->_current === false && isset($keys[0]))
  343.         {
  344.             // This is a special case where offsetUnset was used in a foreach loop and the first element was unset.
  345.             $this->_current $keys[0];
  346.         }
  347.         else
  348.         {
  349.             // Get the current key.
  350.             $position array_search($this->_current$keys);
  351.  
  352.             // Check if there is an object after the current object.
  353.             if ($position !== false && isset($keys[$position 1]))
  354.             {
  355.                 // Get the next id.
  356.                 $this->_current $keys[$position 1];
  357.             }
  358.             else
  359.             {
  360.                 // That was the last object or the internal properties have become corrupted.
  361.                 $this->_current null;
  362.             }
  363.         }
  364.     }
  365.  
  366.     /**
  367.      * Checks whether an offset exists in the iterator.
  368.      *
  369.      * @param   mixed  $offset  The object offset.
  370.      *
  371.      * @return  boolean  True if the object exists, false otherwise.
  372.      *
  373.      * @since   12.3
  374.      */
  375.     public function offsetExists($offset)
  376.     {
  377.         return isset($this->_objects[$offset]);
  378.     }
  379.  
  380.     /**
  381.      * Gets an offset in the iterator.
  382.      *
  383.      * @param   mixed  $offset  The object offset.
  384.      *
  385.      * @return  JData  The object if it exists, null otherwise.
  386.      *
  387.      * @since   12.3
  388.      */
  389.     public function offsetGet($offset)
  390.     {
  391.         return isset($this->_objects[$offset]$this->_objects[$offsetnull;
  392.     }
  393.  
  394.     /**
  395.      * Sets an offset in the iterator.
  396.      *
  397.      * @param   mixed  $offset  The object offset.
  398.      * @param   JData  $object  The object object.
  399.      *
  400.      * @return  void 
  401.      *
  402.      * @since   12.3
  403.      * @throws  InvalidArgumentException if an object is not an instance of JData.
  404.      */
  405.     public function offsetSet($offset$object)
  406.     {
  407.         // Check if the object is a JData object.
  408.         if (!($object instanceof JData))
  409.         {
  410.             throw new InvalidArgumentException(sprintf('%s("%s", *%s*)'__METHOD__$offsetgettype($object)));
  411.         }
  412.  
  413.         // Set the offset.
  414.         $this->_objects[$offset$object;
  415.     }
  416.  
  417.     /**
  418.      * Unsets an offset in the iterator.
  419.      *
  420.      * @param   mixed  $offset  The object offset.
  421.      *
  422.      * @return  void 
  423.      *
  424.      * @since   12.3
  425.      */
  426.     public function offsetUnset($offset)
  427.     {
  428.         if (!$this->offsetExists($offset))
  429.         {
  430.             // Do nothing if the offset does not exist.
  431.             return;
  432.         }
  433.  
  434.         // Check for special handling of unsetting the current position.
  435.         if ($offset == $this->_current)
  436.         {
  437.             // Get the current position.
  438.             $keys $this->keys();
  439.             $position array_search($this->_current$keys);
  440.  
  441.             // Check if there is an object before the current object.
  442.             if ($position 0)
  443.             {
  444.                 // Move the current position back one.
  445.                 $this->_current $keys[$position 1];
  446.             }
  447.             else
  448.             {
  449.                 // We are at the start of the keys AND let's assume we are in a foreach loop and `next` is going to be called.
  450.                 $this->_current false;
  451.             }
  452.         }
  453.  
  454.         unset($this->_objects[$offset]);
  455.     }
  456.  
  457.     /**
  458.      * Rewinds the iterator to the first object.
  459.      *
  460.      * @return  void 
  461.      *
  462.      * @since   12.3
  463.      */
  464.     public function rewind()
  465.     {
  466.         // Set the current position to the first object.
  467.         if (empty($this->_objects))
  468.         {
  469.             $this->_current false;
  470.         }
  471.         else
  472.         {
  473.             $keys $this->keys();
  474.             $this->_current array_shift($keys);
  475.         }
  476.     }
  477.  
  478.     /**
  479.      * Validates the iterator.
  480.      *
  481.      * @return  boolean  True if valid, false otherwise.
  482.      *
  483.      * @since   12.3
  484.      */
  485.     public function valid()
  486.     {
  487.         // Check the current position.
  488.         if (!is_scalar($this->_current|| !isset($this->_objects[$this->_current]))
  489.         {
  490.             return false;
  491.         }
  492.  
  493.         return true;
  494.     }
  495.  
  496.     /**
  497.      * Initialises the list with an array of objects.
  498.      *
  499.      * @param   array  $input  An array of objects.
  500.      *
  501.      * @return  void 
  502.      *
  503.      * @since   12.3
  504.      * @throws  InvalidArgumentException if an object is not an instance of JData.
  505.      */
  506.     private function _initialise(array $input array())
  507.     {
  508.         foreach ($input as $key => $object)
  509.         {
  510.             if (!is_null($object))
  511.             {
  512.                 $this->offsetSet($key$object);
  513.             }
  514.         }
  515.  
  516.         $this->rewind();
  517.     }
  518. }

Documentation generated on Tue, 19 Nov 2013 15:12:56 +0100 by phpDocumentor 1.4.3