Issues (52)

src/Concerns/HasHaving.php (1 issue)

Labels
Severity
1
<?php
2
declare(strict_types=1);
3
4
namespace Level23\Druid\Concerns;
5
6
use Closure;
7
use InvalidArgumentException;
8
use Level23\Druid\Filters\LikeFilter;
9
use Level23\Druid\Filters\FilterInterface;
10
use Level23\Druid\HavingFilters\HavingBuilder;
11
use Level23\Druid\HavingFilters\OrHavingFilter;
12
use Level23\Druid\HavingFilters\NotHavingFilter;
13
use Level23\Druid\HavingFilters\AndHavingFilter;
14
use Level23\Druid\HavingFilters\QueryHavingFilter;
15
use Level23\Druid\HavingFilters\EqualToHavingFilter;
16
use Level23\Druid\HavingFilters\LessThanHavingFilter;
17
use Level23\Druid\HavingFilters\HavingFilterInterface;
18
use Level23\Druid\HavingFilters\GreaterThanHavingFilter;
19
use Level23\Druid\HavingFilters\DimensionSelectorHavingFilter;
20
21
trait HasHaving
22
{
23
    protected ?HavingFilterInterface $having = null;
24
25
    /**
26
     * Build our "having" part of the query.
27
     *
28
     * The operator can be '=', '>', '>=', '<', '<=', '<>', '!=' or 'like'
29
     *
30
     * @param Closure|string|FilterInterface|HavingFilterInterface $havingOrMetricOrClosure
31
     * @param float|string|null                                    $operator
32
     * @param float|string|null|bool                               $value
33
     * @param string                                               $boolean
34
     *
35
     * @return $this
36
     */
37 23
    public function having(
38
        Closure|string|HavingFilterInterface|FilterInterface $havingOrMetricOrClosure,
39
        float|string|null $operator = null,
40
        float|string|bool|null $value = null,
41
        string $boolean = 'and'
42
    ): self {
43 23
        $having = null;
44
45 23
        if ($value === null && $operator !== null) {
46 2
            $value = $operator;
47 2
            $operator = '=';
48
        }
49
50 23
        if (is_string($havingOrMetricOrClosure) && is_string($operator) && $value !== null) {
51 19
            if ($operator == '=') {
52 6
                $having = new DimensionSelectorHavingFilter($havingOrMetricOrClosure, (string)$value);
53 13
            } elseif ($operator == '<>' || $operator == '!=') {
54 4
                $having = new NotHavingFilter(new DimensionSelectorHavingFilter($havingOrMetricOrClosure,
55 4
                    (string)$value));
56 9
            } elseif ($operator == '>') {
57 3
                $having = new GreaterThanHavingFilter($havingOrMetricOrClosure, floatval($value));
58 6
            } elseif ($operator == '<') {
59 1
                $having = new LessThanHavingFilter($havingOrMetricOrClosure, floatval($value));
60 5
            } elseif ($operator == '>=') {
61 2
                $having = new OrHavingFilter([
62 2
                    new GreaterThanHavingFilter($havingOrMetricOrClosure, floatval($value)),
63 2
                    new EqualToHavingFilter($havingOrMetricOrClosure, floatval($value)),
64 2
                ]);
65 3
            } elseif ($operator == '<=') {
66 1
                $having = new OrHavingFilter([
67 1
                    new LessThanHavingFilter($havingOrMetricOrClosure, floatval($value)),
68 1
                    new EqualToHavingFilter($havingOrMetricOrClosure, floatval($value)),
69 1
                ]);
70 2
            } elseif (strtolower($operator) == 'like') {
71 1
                $having = new QueryHavingFilter(new LikeFilter($havingOrMetricOrClosure, (string)$value));
72 1
            } elseif (strtolower($operator) == 'not like') {
73 19
                $having = new NotHavingFilter(
74 19
                    new QueryHavingFilter(new LikeFilter($havingOrMetricOrClosure, (string)$value))
75 19
                );
76
            }
77 4
        } elseif ($havingOrMetricOrClosure instanceof FilterInterface) {
78 1
            $having = new QueryHavingFilter($havingOrMetricOrClosure);
79 3
        } elseif ($havingOrMetricOrClosure instanceof HavingFilterInterface) {
80 2
            $having = $havingOrMetricOrClosure;
81 2
        } elseif ($havingOrMetricOrClosure instanceof Closure) {
82
83
            // let's create a bew builder object where the user can mess around with
84 2
            $obj = new HavingBuilder();
85
86
            // call the user function
87 2
            call_user_func($havingOrMetricOrClosure, $obj);
88
89
            // Now retrieve the having filter which was created and add it to our current filter set.
90 2
            $having = $obj->getHaving();
91
        }
92
93 23
        if ($having === null) {
94 1
            throw new InvalidArgumentException('The arguments which you have supplied cannot be parsed');
95
        }
96
97 22
        strtolower($boolean) == 'and' ? $this->addAndHaving($having) : $this->addOrHaving($having);
98
99 22
        return $this;
100
    }
101
102
    /**
103
     * Add a having filter
104
     *
105
     * @param Closure|string|HavingFilterInterface $havingOrMetricOrClosure
106
     * @param float|string|null                    $operator
107
     * @param float|string|null                    $value
108
     *
109
     * @return $this
110
     */
111 1
    public function orHaving(
112
        Closure|HavingFilterInterface|string $havingOrMetricOrClosure,
113
        float|string|null $operator = null,
114
        float|string|null $value = null
115
    ): self {
116 1
        return $this->having($havingOrMetricOrClosure, $operator, $value, 'or');
117
    }
118
119
    /**
120
     * @return \Level23\Druid\HavingFilters\HavingFilterInterface|null
121
     */
122 21
    public function getHaving(): ?HavingFilterInterface
123
    {
124 21
        return $this->having;
125
    }
126
127
    /**
128
     * Helper method to add an OR filter
129
     *
130
     * @param \Level23\Druid\HavingFilters\HavingFilterInterface $havingFilter
131
     */
132 1
    protected function addOrHaving(HavingFilterInterface $havingFilter): void
133
    {
134 1
        if (!$this->having instanceof HavingFilterInterface) {
135 1
            $this->having = $havingFilter;
136
137 1
            return;
138
        }
139
140 1
        if ($this->having instanceof OrHavingFilter) {
141 1
            $this->having->addHavingFilter($havingFilter);
0 ignored issues
show
The method addHavingFilter() does not exist on Level23\Druid\HavingFilters\HavingFilterInterface. It seems like you code against a sub-type of Level23\Druid\HavingFilters\HavingFilterInterface such as Level23\Druid\HavingFilters\OrHavingFilter or Level23\Druid\HavingFilters\AndHavingFilter. ( Ignorable by Annotation )

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

141
            $this->having->/** @scrutinizer ignore-call */ 
142
                           addHavingFilter($havingFilter);
Loading history...
142
143 1
            return;
144
        }
145
146 1
        $this->having = new OrHavingFilter([$this->having, $havingFilter]);
147
    }
148
149
    /**
150
     * Helper method to add an OR filter
151
     *
152
     * @param \Level23\Druid\HavingFilters\HavingFilterInterface $havingFilter
153
     */
154 21
    protected function addAndHaving(HavingFilterInterface $havingFilter): void
155
    {
156 21
        if (!$this->having instanceof HavingFilterInterface) {
157 21
            $this->having = $havingFilter;
158
159 21
            return;
160
        }
161
162 17
        if ($this->having instanceof AndHavingFilter) {
163 2
            $this->having->addHavingFilter($havingFilter);
164
165 2
            return;
166
        }
167
168 17
        $this->having = new AndHavingFilter([$this->having, $havingFilter]);
169
    }
170
}