Passed
Pull Request — master (#13)
by Vincent
07:15
created

KeyValueQuery::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
c 1
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Bdf\Prime\Query\Custom\KeyValue;
4
5
use Bdf\Prime\Connection\ConnectionInterface;
6
use Bdf\Prime\Exception\DBALException;
7
use Bdf\Prime\Exception\PrimeException;
8
use Bdf\Prime\Query\AbstractReadCommand;
9
use Bdf\Prime\Query\Compiler\Preprocessor\DefaultPreprocessor;
10
use Bdf\Prime\Query\Compiler\Preprocessor\PreprocessorInterface;
11
use Bdf\Prime\Query\Contract\Compilable;
12
use Bdf\Prime\Query\Contract\Limitable;
13
use Bdf\Prime\Query\Contract\Paginable;
14
use Bdf\Prime\Query\Contract\Query\KeyValueQueryInterface;
15
use Bdf\Prime\Query\Contract\ReadOperation;
16
use Bdf\Prime\Query\Contract\WriteOperation;
17
use Bdf\Prime\Query\Extension\CompilableTrait;
18
use Bdf\Prime\Query\Extension\LimitableTrait;
19
use Bdf\Prime\Query\Extension\PaginableTrait;
20
use Bdf\Prime\Query\Extension\ProjectionableTrait;
21
use Doctrine\DBAL\DBALException as BaseDBALException;
22
23
/**
24
 * Query for perform simple key / value search
25
 *
26
 * This query can only perform "equals" comparison, with "AND" combination only on the current table (no relation resolve)
27
 *
28
 * <code>
29
 * $query
30
 *     ->from('test_')
31
 *     ->where('foo', 'bar')
32
 *     ->first()
33
 * ;
34
 * </code>
35
 */
36
class KeyValueQuery extends AbstractReadCommand implements KeyValueQueryInterface, Compilable, Paginable, Limitable
37
{
38
    use CompilableTrait;
39
    use LimitableTrait;
40
    use PaginableTrait;
41
    use ProjectionableTrait;
42
43
44
    /**
45
     * KeyValueQuery constructor.
46
     *
47
     * @param ConnectionInterface $connection
48
     * @param PreprocessorInterface|null $preprocessor
49
     */
50 171
    public function __construct(ConnectionInterface $connection, PreprocessorInterface $preprocessor = null)
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before function; 2 found
Loading history...
51
    {
52 171
        parent::__construct($connection, $preprocessor ?: new DefaultPreprocessor());
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
53
54 171
        $this->statements = [
55
            'where'     => [],
56
            'table'     => null,
57
            'columns'   => [],
58
            'aggregate' => null,
59
            'limit'     => null,
60
            'offset'    => null,
61
            'values'    => [
62
                'data'  => [],
63
                'types' => []
0 ignored issues
show
introduced by
A comma should follow the last multiline array item. Found: ]
Loading history...
64
            ]
0 ignored issues
show
introduced by
A comma should follow the last multiline array item. Found: ]
Loading history...
65
        ];
66 171
    }
67
68
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $alias should have a doc-comment as per coding-style.
Loading history...
69
     * {@inheritdoc}
70
     */
71 167
    public function from($table, $alias = null)
0 ignored issues
show
Coding Style introduced by
The method parameter $alias is never used
Loading history...
72
    {
73 167
        if ($this->statements['table'] !== $table) {
74 167
            $this->compilerState->invalidate('columns');
75 167
            $this->statements['table'] = $table;
76
        }
77
78 167
        return $this;
79
    }
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $field should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $value should have a doc-comment as per coding-style.
Loading history...
82
     * {@inheritdoc}
83
     */
84 217
    public function where($field, $value = null)
85
    {
86 217
        if (is_array($field)) {
87 137
            if (array_keys($field) !== array_keys($this->statements['where'])) {
88 117
                $this->compilerState->invalidate('where');
89
            }
90
91 137
            $this->statements['where'] = $field + $this->statements['where'];
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
92
        } else {
93 109
            if (!isset($this->statements['where'][$field])) {
94 46
                $this->compilerState->invalidate('where');
95
            }
96
97 109
            $this->statements['where'][$field] = $value;
98
        }
99
100 217
        return $this;
101
    }
102
103
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $values should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
104
     * {@inheritdoc}
105
     */
106 58
    public function values(array $values = [], array $types = [])
107
    {
108 58
        if (array_keys($values) !== array_keys($this->statements['values']) || $types !== $this->statements['values']['types']) {
109 58
            $this->compilerState->invalidate('values');
110
        }
111
112 58
        $this->statements['values'] = [
113 58
            'data'  => $values,
114 58
            'types' => $types,
115
        ];
116
117 58
        return $this;
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
124 41
    public function count($column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
125
    {
126 41
        return (int) $this->aggregate(__FUNCTION__, $column);
0 ignored issues
show
Coding Style introduced by
A cast statement should not be followed as per the coding-style.
Loading history...
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
133 1
    public function avg($column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
134
    {
135 1
        return (float) $this->aggregate(__FUNCTION__, $column);
0 ignored issues
show
Coding Style introduced by
A cast statement should not be followed as per the coding-style.
Loading history...
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
142 1
    public function min($column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
143
    {
144 1
        return $this->aggregate(__FUNCTION__, $column);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->aggregate(__FUNCTION__, $column) returns the type string which is incompatible with the return type mandated by Bdf\Prime\Query\Contract\Aggregatable::min() of double.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
151 1
    public function max($column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
152
    {
153 1
        return $this->aggregate(__FUNCTION__, $column);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->aggregate(__FUNCTION__, $column) returns the type string which is incompatible with the return type mandated by Bdf\Prime\Query\Contract\Aggregatable::max() of double.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
160 1
    public function sum($column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
161
    {
162 1
        return (float) $this->aggregate(__FUNCTION__, $column);
0 ignored issues
show
Coding Style introduced by
A cast statement should not be followed as per the coding-style.
Loading history...
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
169 48
    public function aggregate($function, $column = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
170
    {
171 48
        $statements = $this->statements;
172
173 48
        $this->compilerState->invalidate();
174
175 48
        $this->statements['aggregate'] = [$function, $column ?: '*'];
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
176
177 48
        $aggregate = $this->execute()[0]['aggregate'];
178
179 48
        $this->compilerState->invalidate();
180 48
        $this->statements = $statements;
181
182 48
        return $aggregate;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
189 2
    public function paginationCount($columns = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
190
    {
191 2
        $statements = $this->statements;
192
193 2
        $this->compilerState->invalidate();
194
195 2
        $this->statements['limit'] = null;
196 2
        $this->statements['offset'] = null;
197 2
        $this->statements['aggregate'] = ['count', $columns ?: '*'];
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
198
199 2
        $count = (int)$this->execute()[0]['aggregate'];
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
200
201 2
        $this->compilerState->invalidate();
202 2
        $this->statements = $statements;
203
204 2
        return $count;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    #[ReadOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
211 182
    public function execute($columns = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
212
    {
213 182
        $this->setType(self::TYPE_SELECT);
214
215 182
        if (!empty($columns)) {
216 17
            $this->select($columns);
217
        }
218
219 182
        return $this->executeCached();
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    #[WriteOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
226 36
    public function delete()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
227
    {
228 36
        $this->setType(self::TYPE_DELETE);
229
230 36
        $count = $this->connection->execute($this)->count();
231
232 35
        if ($count > 0) {
233 30
            $this->clearCacheOnWrite();
234
        }
235
236 35
        return $count;
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242
    #[WriteOperation]
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Perl-style comments are not allowed; use "// Comment" instead
Loading history...
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
243 53
    public function update($values = null)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
244
    {
245 53
        if ($values !== null) {
246 5
            $this->values($values);
247
        }
248
249 53
        $this->setType(self::TYPE_UPDATE);
250
251 53
        $count = $this->connection->execute($this)->count();
252
253 52
        if ($count > 0) {
254 44
            $this->clearCacheOnWrite();
255
        }
256
257 52
        return $count;
258
    }
259
260
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $limit should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $offset should have a doc-comment as per coding-style.
Loading history...
261
     * {@inheritdoc}
262
     */
263 46
    public function limit($limit, $offset = null)
264
    {
265 46
        if ($this->statements['limit'] === $limit && $this->statements['offset'] === $offset) {
266 22
            return $this;
267
        }
268
269
        // Do not reset query when changing pagination
270 32
        if ($offset !== null && $this->hasPagination()) {
271 2
            $this->statements['limit'] = $limit;
272 2
            $this->statements['offset'] = $offset;
273
274 2
            return $this;
275
        }
276
277 32
        $this->compilerState->invalidate();
278
279 32
        $this->statements['limit'] = $limit;
280
281 32
        if ($offset !== null) {
282 3
            $this->statements['offset'] = $offset;
283
        }
284
285 32
        return $this;
286
    }
287
288
    /**
289
     * Get the SQL query
290
     *
291
     * @return string
292
     * @throws PrimeException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
293
     */
294 7
    public function toSql()
295
    {
296 7
        $this->compile();
297
298 7
        return $this->compilerState->compiledParts['sql'] ?? false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->compilerSt...edParts['sql'] ?? false could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 221
    public function getBindings()
305
    {
306 221
        return $this->compiler->getBindings($this);
307
    }
308
309
    /**
310
     * Get cache namespace
311
     *
312
     * @return string
313
     */
314 4
    protected function cacheNamespace()
315
    {
316 4
        return $this->connection->getName().':'.$this->statements['table'];
317
    }
318
319
    /**
320
     * Get the cache key
321
     *
322
     * @return string
323
     */
324 2
    protected function cacheKey()
325
    {
326 2
        $sql = $this->toSql();
327
328 2
        if (!$sql) {
329
            return null;
330
        }
331
332 2
        return sha1($sql.'-'.serialize($this->getBindings()));
333
    }
334
}
335