[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/joomla/data/src/ -> DataSet.php (source)

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


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