ObjectGraphVisitor   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Test Coverage

Coverage 97.22%

Importance

Changes 0
Metric Value
wmc 17
dl 0
loc 83
ccs 35
cts 36
cp 0.9722
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
C visit() 0 28 7
A __construct() 0 6 1
A doVisit() 0 8 4
A addVisitor() 0 5 1
A visitCollection() 0 8 4
1
<?php
2
3
namespace Vox\Data;
4
5
use InvalidArgumentException;
6
use Metadata\MetadataFactoryInterface;
7
use Traversable;
8
use Vox\Metadata\PropertyMetadata;
9
10
class ObjectGraphVisitor implements ObjectGraphVisitorInterface
11
{
12
    /**
13
     * @var MetadataFactoryInterface
14
     */
15
    private $metadataFactory;
16
    
17
    /**
18
     * @var PropertyAccessorInterface
19
     */
20
    private $propertyAccessor;
21
    
22
    /**
23
     * @var ObjectVisitorInterface[]
24
     */
25
    private $visitors = [];
26
    
27 2
    public function __construct(
28
        MetadataFactoryInterface $metadataFactory,
29
        PropertyAccessorInterface $propertyAccessor = null
30
    ) {
31 2
        $this->metadataFactory  = $metadataFactory;
32 2
        $this->propertyAccessor = $propertyAccessor;
33 2
    }
34
    
35 2
    public function visit($object, array &$context = [])
36
    {
37 2
        if (!is_object($object)) {
38
            throw new InvalidArgumentException('can only visit objects');
39
        }
40
        
41 2
        $this->doVisit($object, $context);
42 2
        $context['visited'][] = $object;
43
        
44 2
        $objectMetadata = $this->metadataFactory->getMetadataForClass(get_class($object));
45
        
46
        /* @var $propertyMetadata PropertyMetadata */
47 2
        foreach ($objectMetadata->propertyMetadata as $propertyMetadata) {
0 ignored issues
show
Bug introduced by
The property propertyMetadata does not seem to exist on Metadata\ClassHierarchyMetadata.
Loading history...
48 2
            $value = $this->propertyAccessor 
49 1
                ? $this->propertyAccessor->get($object, $propertyMetadata->name) 
50 2
                : $propertyMetadata->getValue($object);
51
            
52 2
            if (is_array($value) || $value instanceof Traversable) {
53 2
                $this->visitCollection($value, $context);
54
                
55 2
                continue;
56
            }
57
            
58 2
            if (!is_object($value)) {
59 2
                continue;
60
            }
61
            
62 2
            $this->visit($value, $context);
63
        }
64 2
    }
65
    
66 2
    private function visitCollection($collection, array &$context)
67
    {
68 2
        foreach ($collection as $item) {
69 2
            if (!is_object($item) || in_array($item, $context['visited'] ?? [], true)) {
70 2
                continue;
71
            }
72
73 2
            $this->visit($item, $context);
74
        }
75 2
    }
76
    
77 2
    private function doVisit($object, array &$context)
78
    {
79 2
        foreach ($this->visitors as $visitor) {
80 2
            if (in_array($object, $context['visited'] ?? [], true) || !$visitor->canVisit($object)) {
81 2
                continue;
82
            }
83
84 2
            $visitor->visit($object, $context);
85
        }
86 2
    }
87
    
88 2
    public function addVisitor(ObjectVisitorInterface $visitor): ObjectGraphVisitorInterface
89
    {
90 2
        $this->visitors[] = $visitor;
91
        
92 2
        return $this;
93
    }
94
}
95