Enumerator.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. /*
  3. * This file is part of Object Enumerator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\ObjectEnumerator;
  11. use SebastianBergmann\RecursionContext\Context;
  12. /**
  13. * Traverses array structures and object graphs
  14. * to enumerate all referenced objects.
  15. */
  16. class Enumerator
  17. {
  18. /**
  19. * Returns an array of all objects referenced either
  20. * directly or indirectly by a variable.
  21. *
  22. * @param array|object $variable
  23. *
  24. * @return object[]
  25. */
  26. public function enumerate($variable)
  27. {
  28. if (!is_array($variable) && !is_object($variable)) {
  29. throw new InvalidArgumentException;
  30. }
  31. if (isset(func_get_args()[1])) {
  32. if (!func_get_args()[1] instanceof Context) {
  33. throw new InvalidArgumentException;
  34. }
  35. $processed = func_get_args()[1];
  36. } else {
  37. $processed = new Context;
  38. }
  39. $objects = [];
  40. if ($processed->contains($variable)) {
  41. return $objects;
  42. }
  43. $array = $variable;
  44. $processed->add($variable);
  45. if (is_array($variable)) {
  46. foreach ($array as $element) {
  47. if (!is_array($element) && !is_object($element)) {
  48. continue;
  49. }
  50. $objects = array_merge(
  51. $objects,
  52. $this->enumerate($element, $processed)
  53. );
  54. }
  55. } else {
  56. $objects[] = $variable;
  57. $reflector = new \ReflectionObject($variable);
  58. foreach ($reflector->getProperties() as $attribute) {
  59. $attribute->setAccessible(true);
  60. try {
  61. $value = $attribute->getValue($variable);
  62. } catch (\Throwable $e) {
  63. continue;
  64. } catch (\Exception $e) {
  65. continue;
  66. }
  67. if (!is_array($value) && !is_object($value)) {
  68. continue;
  69. }
  70. $objects = array_merge(
  71. $objects,
  72. $this->enumerate($value, $processed)
  73. );
  74. }
  75. }
  76. return $objects;
  77. }
  78. }