Skip to content

Commit 30f8fa0

Browse files
committed
Add method Selection::havingOr
1 parent 8c81bf3 commit 30f8fa0

File tree

2 files changed

+147
-17
lines changed

2 files changed

+147
-17
lines changed

src/Database/Table/Selection.php

+41-17
Original file line numberDiff line numberDiff line change
@@ -355,23 +355,7 @@ public function whereOr(array $parameters)
355355
if (count($parameters) < 2) {
356356
return $this->where($parameters);
357357
}
358-
$columns = [];
359-
$values = [];
360-
foreach ($parameters as $key => $val) {
361-
if (is_int($key)) { // whereOr(['full condition'])
362-
$columns[] = $val;
363-
} elseif (strpos($key, '?') === false) { // whereOr(['column1' => 1])
364-
$columns[] = $key . ' ?';
365-
$values[] = $val;
366-
} else { // whereOr(['column1 > ?' => 1])
367-
$qNumber = substr_count($key, '?');
368-
if ($qNumber > 1 && (!is_array($val) || $qNumber !== count($val))) {
369-
throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
370-
}
371-
$columns[] = $key;
372-
$values = array_merge($values, $qNumber > 1 ? $val : [$val]);
373-
}
374-
}
358+
[$columns, $values] = $this->paramsOr($parameters);
375359
$columnsString = '(' . implode(') OR (', $columns) . ')';
376360
return $this->where($columnsString, $values);
377361
}
@@ -442,6 +426,19 @@ public function having(string $having, ...$params)
442426
}
443427

444428

429+
/**
430+
* Sets having clause, more calls rewrite old value.
431+
* @param array $parameters ['column1' => 1, 'column2 > ?' => 2, 'full condition']
432+
* @return static
433+
*/
434+
public function havingOr(array $parameters)
435+
{
436+
[$columns, $values] = $this->paramsOr($parameters);
437+
$columnsString = count($columns) > 1 ? '(' . implode(') OR (', $columns) . ')' : implode('', $columns);
438+
return $this->having($columnsString, $values);
439+
}
440+
441+
445442
/**
446443
* Aliases table. Example ':book:book_tag.tag', 'tg'
447444
* @return static
@@ -756,6 +753,33 @@ public function getDataRefreshed(): bool
756753
}
757754

758755

756+
/**
757+
* @param array $parameters ['column1' => 1, 'column2 > ?' => 2, 'full condition']
758+
* @return array [$columns, $values] to be used with `where` or `having`
759+
*/
760+
protected function paramsOr(array $parameters): array
761+
{
762+
$columns = [];
763+
$values = [];
764+
foreach ($parameters as $key => $val) {
765+
if (is_int($key)) { // whereOr(['full condition'])
766+
$columns[] = $val;
767+
} elseif (strpos($key, '?') === FALSE) { // whereOr(['column1' => 1])
768+
$columns[] = $key . ' ?';
769+
$values[] = $val;
770+
} else { // whereOr(['column1 > ?' => 1])
771+
$qNumber = substr_count($key, '?');
772+
if ($qNumber > 1 && (!is_array($val) || $qNumber !== count($val))) {
773+
throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
774+
}
775+
$columns[] = $key;
776+
$values = array_merge($values, $qNumber > 1 ? $val : [$val]);
777+
}
778+
}
779+
return [$columns, $values];
780+
}
781+
782+
759783
/********************* manipulation ****************d*g**/
760784

761785

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\Database\Table: WhereOr operations
5+
* @dataProvider? ../databases.ini
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
use Tester\Assert;
11+
12+
require __DIR__ . '/../connect.inc.php'; // create $connection
13+
14+
Nette\Database\Helpers::loadFromFile($connection, __DIR__ . "/../files/{$driverName}-nette_test1.sql");
15+
16+
// without question mark
17+
test(function () use ($context) {
18+
$count = $context->table('book')->havingOr([
19+
'author_id' => 12,
20+
'title' => 'JUSH',
21+
])->count();
22+
Assert::same(3, $count);
23+
});
24+
25+
26+
// full condition
27+
test(function () use ($context) {
28+
$count = $context->table('book')->havingOr([
29+
'translator_id IS NULL',
30+
'title' => 'Dibi',
31+
])->count();
32+
Assert::same(2, $count);
33+
});
34+
35+
36+
// with question mark
37+
test(function () use ($context) {
38+
$count = $context->table('book')->havingOr([
39+
'id > ?' => 3,
40+
'translator_id' => 11,
41+
])->count();
42+
Assert::same(2, $count);
43+
});
44+
45+
46+
// just one condition
47+
test(function () use ($context) {
48+
$count = $context->table('book')->havingOr([
49+
'id > ?' => 3,
50+
])->count();
51+
Assert::same(1, $count);
52+
});
53+
54+
55+
// with question mark
56+
test(function () use ($context) {
57+
$count = $context->table('book')->havingOr([
58+
'id ?' => [3, 4],
59+
'translator_id' => 11,
60+
])->count();
61+
Assert::same(3, $count);
62+
});
63+
64+
65+
// multiple values for one key
66+
test(function () use ($context) {
67+
$count = $context->table('author')->havingOr([
68+
'id > ?' => 12,
69+
'ROUND(id, ?) = ?' => [5, 3],
70+
])->count();
71+
Assert::same(1, $count);
72+
});
73+
74+
75+
// nested condition
76+
test(function () use ($context) {
77+
$books = $context->table('book')->havingOr([
78+
'id = ?' => 4,
79+
'author_id = ? AND translator_id ?' => [11, null],
80+
]);
81+
Assert::same(2, $books->count());
82+
});
83+
84+
85+
// invalid param count
86+
test(function () use ($context) {
87+
$f = function () use ($context) {
88+
$context->table('author')->havingOr([
89+
'id > ?' => 3,
90+
'ROUND(id, ?) = ?' => [5],
91+
])->count();
92+
};
93+
Assert::throws($f, Nette\InvalidArgumentException::class, 'Argument count does not match placeholder count.');
94+
});
95+
96+
97+
// invalid param count
98+
test(function () use ($context) {
99+
$f = function () use ($context) {
100+
$context->table('author')->havingOr([
101+
'id > ?' => 3,
102+
'ROUND(id, ?) = ?' => 5,
103+
])->count();
104+
};
105+
Assert::throws($f, Nette\InvalidArgumentException::class, 'Argument count does not match placeholder count.');
106+
});

0 commit comments

Comments
 (0)