Completed
Push — master ( 69e2c3...3de1cd )
by JHONATAN
02:37
created

ObjectStorage::isEquals()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 16
cts 16
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 15
nc 5
nop 1
crap 6
1
<?php
2
3
namespace Vox\Webservice;
4
5
use InvalidArgumentException;
6
use Metadata\MetadataFactoryInterface;
7
use BadMethodCallException;
8
use Vox\Metadata\PropertyMetadata;
9
use Vox\Webservice\Mapping\BelongsTo;
10
use Vox\Webservice\Metadata\TransferMetadata;
11
12
/**
13
 * A object storage using an id hashmap pattern
14
 * 
15
 * @author Jhonatan Teixeira <[email protected]>
16
 */
17
class ObjectStorage implements ObjectStorageInterface
18
{
19
    use MetadataTrait;
20
    
21
    private $storage = [];
22
    
23 24
    public function __construct(MetadataFactoryInterface $metadataFactory)
24
    {
25 24
        $this->metadataFactory = $metadataFactory;
26 24
    }
27
    
28 13
    public function contains($object): bool
29
    {
30 13
        return isset($this->storage[get_class($object)][$this->getIdValue($object)]);
31
    }
32
    
33 12
    public function attach($object)
34
    {
35 12
        $className = get_class($object);
36 12
        $id        = $this->getIdValue($object);
37
        
38 12
        if (!$id) {
39
            throw new InvalidArgumentException('object has no id value');
40
        }
41
        
42 12
        $this->storage[$className][$id] = $object;
43 12
    }
44
    
45 8
    public function detach($object)
46
    {
47 8
        unset($this->storage[get_class($object)][$this->getIdValue($object)]);
48 8
    }
49
50 10
    public function getIterator()
51
    {
52 10
        $items = [];
53
        
54 10
        foreach ($this->storage as $transferData) {
55 8
            foreach ($transferData as $item) {
56 8
                $items[] = $item;
57
            }
58
        }
59
        
60 10
        return new \ArrayIterator($items);
61
    }
62
63 7
    public function isEquals($object): bool
64
    {
65 7
        $className    = get_class($object);
66 7
        $metadata     = $this->getClassMetadata($object);
67 7
        $idValue      = $this->getIdValue($object);
68 7
        $storedObject = $this->storage[$className][$idValue];
69
70
        /* @var $propertyMetadata PropertyMetadata */
71 7
        foreach ($metadata->propertyMetadata as $name => $propertyMetadata) {
72 7
            $storedValue = $propertyMetadata->getValue($storedObject);
73 7
            $value       = $propertyMetadata->getValue($object);
74
75 7
            if ($propertyMetadata->hasAnnotation(BelongsTo::class)) {
76 1
                if (!empty($value)
77 1
                    && $this->hasRelationshipChanged($object, $value, $propertyMetadata, $metadata)) {
78 1
                    return false;
79
                }
80
81 1
                continue;
82
            }
83
84 7
            if ($storedValue != $value) {
85 7
                return false;
86
            }
87
        }
88
89 1
        return true;
90
    }
91
92 1
    private function hasRelationshipChanged(
93
        $object,
94
        $value,
95
        PropertyMetadata $propertyMetadata,
96
        TransferMetadata $metadata
97
    ): bool {
98
        /* @var $belongsTo BelongsTo */
99 1
        $belongsTo  = $propertyMetadata->getAnnotation(BelongsTo::class);
100 1
        $externalId = $this->getIdValue($value);
101 1
        $internalId = $metadata->propertyMetadata[$belongsTo->foreignField]->getValue($object);
102
103 1
        if ($externalId !== $internalId) {
104 1
            return true;
105
        }
106
107 1
        return false;
108
    }
109
110
    /**
111
     * @param string $className
112
     * @param scalar $id
113
     *
114
     * @return object
115
     */
116 6
    public function fetchByParams(...$params)
117
    {
118 6
        if (count($params) != 2) {
119
            throw new BadMethodCallException('this method needs two params, $className: string, $id: scalar');
120
        }
121
122 6
        $className = (string) $params[0];
123 6
        $id        = $params[1];
124
125 6
        if (!is_scalar($id)) {
126
            throw new BadMethodCallException('$id must be scalar value');
127
        }
128
129 6
        return $this->storage[$className][$id] ?? null;
130
    }
131
}
132