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
18
class Visitor implements VisitorInterface
19
{
20
    const SUPPORTED_ACCESS_TYPE = [
21
        Ast\Bag\Context::ARRAY_ACCESS,
22
        Ast\Bag\Context::ATTRIBUTE_ACCESS,
23
    ];
24
25
    /** @var Disassembly */
26
    protected $disassembly;
27
28 7
    public function __construct()
29
    {
30 7
        $this->disassembly = new Disassembly();
31 7
    }
32
33 7
    public function visit(ElementInterface $element, &$handle = null, $eldnah = null)
34
    {
35 7
        if ($element instanceof Ast\Model) {
36 7
            return $this->visitModel($element, $handle, $eldnah);
37
        }
38
39 7
        if ($element instanceof Ast\Operator) {
40 7
            return $this->visitOperator($element, $handle, $eldnah);
41
        }
42
43 7
        if ($element instanceof Ast\Bag\Scalar) {
44 5
            return $this->visitScalar($element, $handle, $eldnah);
45
        }
46
47 7
        if ($element instanceof Ast\Bag\RulerArray) {
48 2
            return $this->visitArray($element, $handle, $eldnah);
49
        }
50
51 7
        if ($element instanceof Ast\Bag\Context) {
52 7
            return $this->visitAccess($element, $handle, $eldnah);
53
        }
54
55
        // @codeCoverageIgnoreStart
56
        throw new \LogicException(sprintf('Element of type "%s" not handled', get_class($element)));
57
        // @codeCoverageIgnoreEnd
58
    }
59
60 7
    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

60
    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

60
    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...
61
    {
62 7
        if ($element->getId() === '?') {
63 1
            return literal($element->getId());
64
        }
65
66 7
        $identifier = [$element->getId()];
67 7
        foreach ($element->getDimensions() as $dimension) {
68 5
            $this->assertValidAccess($element, $dimension[Ast\Bag\Context::ACCESS_TYPE]);
69 4
            $identifier[] = $dimension[Ast\Bag\Context::ACCESS_VALUE];
70
        }
71
72 6
        return identify(implode('.', $identifier));
73
    }
74
75 5
    protected function assertValidAccess(Ast\Bag\Context $element, int $type): void
76
    {
77 5
        if (in_array($type, self::SUPPORTED_ACCESS_TYPE) === false) {
78 1
            throw new \LogicException(sprintf(
79 1
                'Invalid access type in expression: %s',
80 1
                $this->disassembly->visit($element)
81
            ));
82
        }
83 4
    }
84
85 5
    protected function visitScalar(Ast\Bag\Scalar $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

85
    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...
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

85
    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...
86
    {
87 5
        return param($element->getValue());
88
    }
89
90 2
    protected function visitArray(Ast\Bag\RulerArray $element, &$handle = null, $eldnah = null)
91
    {
92 2
        return express('(%s)', listing(array_map($this->remapper($handle, $eldnah), $element->getArray())));
93
    }
94
95 7
    protected function visitModel(Ast\Model $element, &$handle = null, $eldnah = null)
96
    {
97 7
        return $element->getExpression()->accept($this, $handle, $eldnah);
98
    }
99
100 7
    protected function visitOperator(Ast\Operator $element, &$handle = null, $eldnah = null)
101
    {
102 7
        $values = array_map($this->remapper($handle, $eldnah), $element->getArguments());
103
104 6
        if ($element->isFunction()) {
105 1
            return criteria(sprintf('%s(%%s)', strtoupper($element->getName())), listing($values));
106
        }
107
108 6
        if (count($values) === 2) {
109 6
            $operator = $element->getName();
110
            // `NULL` requires operator replacements: `=` becomes `IS` and `!=` becomes `IS NOT`
111 6
            $parameter = $element->getArguments()[1];
112 6
            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...
113 1
                $operator = $element->getName() === '!=' ? 'IS NOT' : 'IS';
114
            }
115
116 6
            return criteria(sprintf('%%s %s %%s', strtoupper($operator)), $values[0], $values[1]);
117
        }
118
119 1
        return criteria(sprintf('%s (%%s)', $element->getName()), listing($values, ' '));
120
    }
121
122
    protected function remapper(&$handle, $eldnah): callable
123
    {
124 7
        return function ($element) use (&$handle, $eldnah) {
125 7
            return $element->accept($this, $handle, $eldnah);
126 7
        };
127
    }
128
}
129