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 11namespace SebastianBergmann\ObjectEnumerator; 12 13use SebastianBergmann\RecursionContext\Context; 14 15/** 16 * Traverses array structures and object graphs 17 * to enumerate all referenced objects. 18 */ 19class Enumerator 20{ 21 /** 22 * Returns an array of all objects referenced either 23 * directly or indirectly by a variable. 24 * 25 * @param array|object $variable 26 * 27 * @return object[] 28 */ 29 public function enumerate($variable) 30 { 31 if (!is_array($variable) && !is_object($variable)) { 32 throw new InvalidArgumentException; 33 } 34 35 if (isset(func_get_args()[1])) { 36 if (!func_get_args()[1] instanceof Context) { 37 throw new InvalidArgumentException; 38 } 39 40 $processed = func_get_args()[1]; 41 } else { 42 $processed = new Context; 43 } 44 45 $objects = []; 46 47 if ($processed->contains($variable)) { 48 return $objects; 49 } 50 51 $array = $variable; 52 $processed->add($variable); 53 54 if (is_array($variable)) { 55 foreach ($array as $element) { 56 if (!is_array($element) && !is_object($element)) { 57 continue; 58 } 59 60 $objects = array_merge( 61 $objects, 62 $this->enumerate($element, $processed) 63 ); 64 } 65 } else { 66 $objects[] = $variable; 67 $reflector = new \ReflectionObject($variable); 68 69 foreach ($reflector->getProperties() as $attribute) { 70 $attribute->setAccessible(true); 71 72 try { 73 $value = $attribute->getValue($variable); 74 } catch (\Throwable $e) { 75 continue; 76 } catch (\Exception $e) { 77 continue; 78 } 79 80 if (!is_array($value) && !is_object($value)) { 81 continue; 82 } 83 84 $objects = array_merge( 85 $objects, 86 $this->enumerate($value, $processed) 87 ); 88 } 89 } 90 91 return $objects; 92 } 93} 94