ScalarFilter   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 5
dl 0
loc 113
ccs 54
cts 54
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
B find() 0 24 5
A cast() 0 8 1
B findMultiple() 0 27 4
A findSingle() 0 10 2
A sort() 0 10 3
A getOptions() 0 20 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rs\XmlFilter\Filter;
6
7
use Rs\XmlFilter\Document\Element;
8
use Rs\XmlFilter\Exception\AmbigousValueException;
9
use Rs\XmlFilter\Exception\NoValueException;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
12
class ScalarFilter extends AbstractFilter implements Filter
13
{
14
    /**
15
     * {@inheritdoc}
16
     */
17 36
    public function find(Element $element, array $options)
18
    {
19 36
        $nodes = $element->find($this->preparePath($options['path'], $options));
20
21 36
        if (true === $options['multiple']) {
22 8
            return $this->findMultiple($element, $nodes, $options);
23
        }
24
25 32
        if (1 === count($nodes)) {
26 27
            return $this->findSingle($nodes, $options);
27
        }
28
29 5
        if (0 === count($nodes)) {
30 4
            if ($options['nullable']) {
31 3
                return;
32
            }
33
34 1
            throw new NoValueException(sprintf('no value detected! "%s"', $options['path']), $element, $options);
35
        }
36
37 1
        $error = sprintf('non unique filter result detected! "%s" has %d different values (%s).', $options['path'], count($nodes), implode(',', $nodes));
38
39 1
        throw new AmbigousValueException($error, $element, $options, $nodes);
40
    }
41
42 31
    private function cast(Element $node, string $cast)
43
    {
44 31
        $value = (string) $node;
45
46 31
        settype($value, $cast);
47
48 31
        return $value;
49
    }
50
51 8
    private function findMultiple(Element $element, array $nodes, array $options) : array
52
    {
53 8
        $values = [];
54 8
        foreach ($nodes as $index => $node) {
55
            /* @var Element $node */
56
57 8
            if (is_string($options['sort'])) {
58 1
                $index = $this->find($this->getSearchElement($element, $options), array_merge($options, [
59 1
                    'multiple' => false,
60 1
                    'context'  => $node,
61 1
                    'path'     => $this->preparePath($options['sort'], $options),
62
                ]));
63
            }
64
65 8
            $value = $this->cast($node, $options['cast']);
66
67 8
            if (false === $this->checkCondition($index, $value, $options, $node)) {
68 1
                continue;
69
            }
70
71 8
            $values[$index] = $value;
72
        }
73
74 8
        $values = $this->sort($values, $options);
75
76 8
        return array_values($values);
77
    }
78
79 27
    private function findSingle(array $nodes, array $options)
80
    {
81 27
        $node = reset($nodes);
82
83 27
        $value = $this->cast($node, $options['cast']);
84
85 27
        if ($this->checkCondition(null, $value, $options, $node)) {
86 26
            return $value;
87
        }
88 1
    }
89
90 8
    protected function sort(array $data, array $options): array
91
    {
92 8
        if (true === $options['sort']) {
93 6
            sort($data);
94 2
        } elseif (is_string($options['sort'])) {
95 1
            ksort($data);
96
        }
97
98 8
        return $data;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 37
    public function getOptions(OptionsResolver $resolver)
105
    {
106 37
        $resolver->setRequired([
107 37
            'path',
108
109
        ]);
110
111 37
        $resolver->setDefaults([
112 37
            'nullable'         => true,
113
            'multiple'         => false,
114
            'cast'             => 'string',
115
        ]);
116 37
        $resolver->remove('context');
117 37
        $resolver->setAllowedTypes('path', 'string');
118 37
        $resolver->setAllowedTypes('nullable', 'bool');
119 37
        $resolver->setAllowedTypes('multiple', 'boolean');
120 37
        $resolver->setAllowedValues('cast', ['string', 'int', 'float', 'bool']);
121
122 37
        parent::getOptions($resolver);
123 37
    }
124
}
125