Collector   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Test Coverage

Coverage 71.15%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 63
c 2
b 1
f 0
dl 0
loc 106
ccs 37
cts 52
cp 0.7115
rs 10
wmc 29

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A hasKeyInCurrent() 0 11 4
A setInCurrent() 0 8 5
D processEvent() 0 54 19
1
<?php
2
declare(strict_types=1);
3
4
namespace JsonDecodeStream\Collector;
5
6
use JsonDecodeStream\Event;
7
use JsonDecodeStream\Exception\CollectorException;
8
use JsonDecodeStream\Exception\SelectorException;
9
use stdClass;
10
11
class Collector implements CollectorInterface
12
{
13
    /** @var string */
14
    protected $selector;
15
    /** @var bool */
16
    protected $objectsAsAssocArrays;
17
18
    /** @var null|array|stdClass */
19
    protected $current = null;
20
    /** @var array|array[]|stdClass[] */
21
    protected $stack = [];
22
    /** @var null|string */
23
    protected $key = null;
24
    /** @var string[]|null[] */
25
    protected $keyStack = [];
26
27 13
    public function __construct(string $selector = null, bool $objectsAsAssocArrays = false)
28
    {
29 13
        $this->selector = $selector;
30 13
        $this->objectsAsAssocArrays = $objectsAsAssocArrays;
31 13
    }
32
33
    /**
34
     * @param Event $event
35
     * @return array|null
36
     * @throws CollectorException
37
     * @throws SelectorException
38
     */
39 13
    public function processEvent(Event $event)
40
    {
41 13
        if ($this->selector !== null && !$event->matchPath($this->selector)) {
42 9
            return null;
43
        }
44
45 13
        switch ($event->getId()) {
46
            case Event::KEY:
47 6
                $this->key = $event->getValue();
48 6
                break;
49
50
            case Event::VALUE:
51 13
                if ($this->current === null) {
52 7
                    return [ $event->getPath(), $event->getValue() ];
53 7
                } elseif ($this->key !== null && $this->hasKeyInCurrent($this->key)) {
54
                    throw CollectorException::duplicatedKey($this->key, $event);
55
                } else {
56 7
                    $this->setInCurrent($event->getValue(), $this->key);
57
                }
58 7
                break;
59
60
            case Event::OBJECT_START:
61
            case Event::ARRAY_START:
62 7
                if ($this->current !== null) {
63
                    $this->stack[] = $this->current;
64
                    $this->keyStack[] = $this->key;
65
                }
66 7
                if ($event->getId() == Event::OBJECT_START) {
67 6
                    $this->current = $this->objectsAsAssocArrays ? [] : new stdClass();
68 2
                } elseif ($event->getId() == Event::ARRAY_START) {
69 2
                    $this->current = [];
70
                }
71 7
                $this->key = null;
72 7
                break;
73
74
            case Event::OBJECT_END:
75
            case Event::ARRAY_END:
76 7
                $finished = $this->current;
77 7
                if (!empty($this->stack)) {
78
                    $this->current = array_pop($this->stack);
79
                    $this->key = array_pop($this->keyStack);
80
                    if ($this->key !== null && $this->hasKeyInCurrent($this->key)) {
81
                        throw CollectorException::duplicatedKey($this->key, $event);
82
                    }
83
                    $this->setInCurrent($finished, $this->key);
84
                } else {
85 7
                    $this->current = null;
86 7
                    $this->key = null;
87 7
                    return [ $event->getPath(), $finished ];
88
                }
89
                break;
90
        }
91
92 7
        return null;
93
    }
94
95 6
    protected function hasKeyInCurrent($key)
96
    {
97 6
        if ($key === null) {
98
            return false;
99
        }
100 6
        if (is_object($this->current)) {
101 6
            return isset($this->current->{$key});
102
        } elseif (is_array($this->current)) {
103
            return isset($this->current[$key]);
104
        } else {
105
            return false;
106
        }
107
    }
108
109 7
    protected function setInCurrent($value, $key = null)
110
    {
111 7
        if (is_object($this->current)) {
112 6
            $this->current->{$key} = $value;
113 2
        } elseif (is_array($this->current) && $key === null) {
114 2
            $this->current[] = $value;
115
        } elseif (is_array($this->current)) {
116
            $this->current[$key] = $value;
117
        }
118 7
    }
119
}
120