Issues (12)

src/Ruler/Visitor.php (5 issues)

1
<?php
2
declare(strict_types=1);
3
4
namespace Latitude\QueryBuilder\Ruler;
5
6
use Hoa\Ruler\Model as Ast;
7
use Hoa\Ruler\Visitor\Disassembly;
8
use Hoa\Visitor\Element as ElementInterface;
9
use Hoa\Visitor\Visit as VisitorInterface;
10
11
use function Latitude\QueryBuilder\criteria;
12
use function Latitude\QueryBuilder\express;
13
use function Latitude\QueryBuilder\identify;
14
use function Latitude\QueryBuilder\listing;
15
use function Latitude\QueryBuilder\literal;
16
use function Latitude\QueryBuilder\param;
17
use function Latitude\QueryBuilder\group;
18
19
class Visitor implements VisitorInterface
20
{
21
    const SUPPORTED_ACCESS_TYPE = [
22
        Ast\Bag\Context::ARRAY_ACCESS,
23
        Ast\Bag\Context::ATTRIBUTE_ACCESS,
24
    ];
25
26
    /** @var Disassembly */
27
    protected $disassembly;
28
29 8
    public function __construct()
30
    {
31 8
        $this->disassembly = new Disassembly();
32 8
    }
33
34 8
    public function visit(ElementInterface $element, &$handle = null, $eldnah = null)
35
    {
36 8
        if ($element instanceof Ast\Model) {
37 8
            return $this->visitModel($element, $handle, $eldnah);
38
        }
39
40 8
        if ($element instanceof Ast\Operator) {
41 8
            return $this->visitOperator($element, $handle, $eldnah);
42
        }
43
44 8
        if ($element instanceof Ast\Bag\Scalar) {
45 6
            return $this->visitScalar($element, $handle, $eldnah);
46
        }
47
48 8
        if ($element instanceof Ast\Bag\RulerArray) {
49 2
            return $this->visitArray($element, $handle, $eldnah);
50
        }
51
52 8
        if ($element instanceof Ast\Bag\Context) {
53 8
            return $this->visitAccess($element, $handle, $eldnah);
54
        }
55
56
        // @codeCoverageIgnoreStart
57
        throw new \LogicException(sprintf('Element of type "%s" not handled', get_class($element)));
58
        // @codeCoverageIgnoreEnd
59
    }
60
61 8
    protected function visitAccess(Ast\Bag\Context $element, &$handle = null, $eldnah = null)
0 ignored issues
show
The parameter $handle is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

61
    protected function visitAccess(Ast\Bag\Context $element, /** @scrutinizer ignore-unused */ &$handle = null, $eldnah = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $eldnah is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

61
    protected function visitAccess(Ast\Bag\Context $element, &$handle = null, /** @scrutinizer ignore-unused */ $eldnah = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
62
    {
63 8
        if ($element->getId() === '?') {
64 1
            return literal($element->getId());
65
        }
66
67 8
        $identifier = [$element->getId()];
68 8
        foreach ($element->getDimensions() as $dimension) {
69 6
            $this->assertValidAccess($element, $dimension[Ast\Bag\Context::ACCESS_TYPE]);
70 5
            $identifier[] = $dimension[Ast\Bag\Context::ACCESS_VALUE];
71
        }
72
73 7
        return identify(implode('.', $identifier));
74
    }
75
76 6
    protected function assertValidAccess(Ast\Bag\Context $element, int $type): void
77
    {
78 6
        if (in_array($type, self::SUPPORTED_ACCESS_TYPE) === false) {
79 1
            throw new \LogicException(sprintf(
80 1
                'Invalid access type in expression: %s',
81 1
                $this->disassembly->visit($element)
82
            ));
83
        }
84 5
    }
85
86 6
    protected function visitScalar(Ast\Bag\Scalar $element, &$handle = null, $eldnah = null)
0 ignored issues
show
The parameter $eldnah is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

86
    protected function visitScalar(Ast\Bag\Scalar $element, &$handle = null, /** @scrutinizer ignore-unused */ $eldnah = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $handle is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

86
    protected function visitScalar(Ast\Bag\Scalar $element, /** @scrutinizer ignore-unused */ &$handle = null, $eldnah = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
87
    {
88 6
        return param($element->getValue());
89
    }
90
91 2
    protected function visitArray(Ast\Bag\RulerArray $element, &$handle = null, $eldnah = null)
92
    {
93 2
        return express('(%s)', listing(array_map($this->remapper($handle, $eldnah), $element->getArray())));
94
    }
95
96 8
    protected function visitModel(Ast\Model $element, &$handle = null, $eldnah = null)
97
    {
98 8
        return $element->getExpression()->accept($this, $handle, $eldnah);
99
    }
100
101 8
    protected function visitOperator(Ast\Operator $element, &$handle = null, $eldnah = null)
102
    {
103 8
        $values = array_map($this->remapper($handle, $eldnah), $element->getArguments());
104
105 7
        if ($element->getName() === 'or') {
106 1
            return group(criteria(
107 1
                sprintf('%%s %s %%s', strtoupper($element->getName())),
108 1
                $values[0],
109 1
                $values[1]
110
            ));
111
        }
112
113 7
        if ($element->isFunction()) {
114 1
            return criteria(sprintf('%s(%%s)', strtoupper($element->getName())), listing($values));
115
        }
116
117 7
        if (count($values) === 2) {
118 7
            $operator = $element->getName();
119
            // `NULL` requires operator replacements: `=` becomes `IS` and `!=` becomes `IS NOT`
120 7
            $parameter = $element->getArguments()[1];
121 7
            if ($parameter instanceof Ast\Bag\Scalar and is_null($parameter->getValue())) {
0 ignored issues
show
The condition is_null($parameter->getValue()) is always false.
Loading history...
122 1
                $operator = $element->getName() === '!=' ? 'IS NOT' : 'IS';
123
            }
124
125 7
            return criteria(sprintf('%%s %s %%s', strtoupper($operator)), $values[0], $values[1]);
126
        }
127
128 1
        return criteria(sprintf('%s (%%s)', $element->getName()), listing($values, ' '));
129
    }
130
131 8
    protected function remapper(&$handle, $eldnah): callable
132
    {
133
        return function ($element) use (&$handle, $eldnah) {
134 8
            return $element->accept($this, $handle, $eldnah);
135 8
        };
136
    }
137
}
138