[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
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 |