NetteDatabaseTableDataSource::limit()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 2
cts 2
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
/**
4
 * @copyright   Copyright (c) 2015 ublaboo <[email protected]>
5
 * @author      Pavel Janda <[email protected]>
6
 * @package     Ublaboo
7
 */
8
9
namespace Ublaboo\DataGrid\DataSource;
10
11
use Nette\Database\Table\Selection;
12
use Nette\Utils\Strings;
13
use Ublaboo\DataGrid\Filter;
14
use Ublaboo\DataGrid\Utils\DateTimeHelper;
15
use Ublaboo\DataGrid\Utils\Sorting;
16
17 1
class NetteDatabaseTableDataSource extends FilterableDataSource implements IDataSource
18
{
19
20
	/**
21
	 * @var Selection
22
	 */
23
	protected $data_source;
24
25
	/**
26
	 * @var array
27
	 */
28
	protected $data = [];
29
30
	/**
31
	 * @var string
32
	 */
33
	protected $primary_key;
34
35
36
	/**
37
	 * @param Selection $data_source
38
	 * @param string $primary_key
39
	 */
40
	public function __construct(Selection $data_source, $primary_key)
41
	{
42 1
		$this->data_source = $data_source;
43 1
		$this->primary_key = $primary_key;
44 1
	}
45
46
47
	/********************************************************************************
48
	 *                          IDataSource implementation                          *
49
	 ********************************************************************************/
50
51
52
	/**
53
	 * Get count of data
54
	 * @return int
55
	 */
56
	public function getCount()
57
	{
58 1
		$data_source_sql_builder = $this->data_source->getSqlBuilder();
59
60
		try {
61 1
			$primary = $this->data_source->getPrimary();
62
63
		} catch (\LogicException $e) {
64
			if ($data_source_sql_builder->getGroup() !== '') {
65
				return $this->data_source->count(
66
					'DISTINCT ' . Strings::replace($data_source_sql_builder->getGroup(), '~ (DESC|ASC)~')
67
				);
68
			}
69
70
			return $this->data_source->count('*');
71
		}
72
73 1
		if ($data_source_sql_builder->getGroup() !== '') {
74
			return $this->data_source->count(
75
				'DISTINCT ' . Strings::replace($data_source_sql_builder->getGroup(), '~ (DESC|ASC)~')
76
			);
77
		} else {
78 1
			return $this->data_source->count(
79 1
				$this->data_source->getName() . '.' . (is_array($primary) ? reset($primary) : $primary)
80
			);
81
		}
82
	}
83
84
85
	/**
86
	 * Get the data
87
	 * @return array
88
	 */
89
	public function getData()
90
	{
91 1
		return $this->data ?: $this->data_source->fetchAll();
92
	}
93
94
95
	/**
96
	 * Filter data - get one row
97
	 * @param array $condition
98
	 * @return static
99
	 */
100
	public function filterOne(array $condition)
101
	{
102 1
		$this->data_source->where($condition)->limit(1);
103
104 1
		return $this;
105
	}
106
107
108
	/**
109
	 * Filter by date
110
	 * @param  Filter\FilterDate $filter
111
	 * @return void
112
	 */
113 View Code Duplication
	public function applyFilterDate(Filter\FilterDate $filter)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
	{
115
		$conditions = $filter->getCondition();
116
117
		$date = DateTimeHelper::tryConvertToDateTime($conditions[$filter->getColumn()], [$filter->getPhpFormat()]);
118
119
		$this->data_source->where("DATE({$filter->getColumn()}) = ?", $date->format('Y-m-d'));
120
	}
121
122
123
	/**
124
	 * Filter by date range
125
	 * @param  Filter\FilterDateRange $filter
126
	 * @return void
127
	 */
128 View Code Duplication
	public function applyFilterDateRange(Filter\FilterDateRange $filter)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
	{
130
		$conditions = $filter->getCondition();
131
132
		$value_from = $conditions[$filter->getColumn()]['from'];
133
		$value_to = $conditions[$filter->getColumn()]['to'];
134
135
		if ($value_from) {
136
			$date_from = DateTimeHelper::tryConvertToDateTime($value_from, [$filter->getPhpFormat()]);
137
			$date_from->setTime(0, 0, 0);
138
139
			$this->data_source->where("DATE({$filter->getColumn()}) >= ?", $date_from->format('Y-m-d'));
140
		}
141
142
		if ($value_to) {
143
			$date_to = DateTimeHelper::tryConvertToDateTime($value_to, [$filter->getPhpFormat()]);
144
			$date_to->setTime(23, 59, 59);
145
146
			$this->data_source->where("DATE({$filter->getColumn()}) <= ?", $date_to->format('Y-m-d'));
147
		}
148
	}
149
150
151
	/**
152
	 * Filter by range
153
	 * @param  Filter\FilterRange $filter
154
	 * @return void
155
	 */
156 View Code Duplication
	public function applyFilterRange(Filter\FilterRange $filter)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
	{
158 1
		$conditions = $filter->getCondition();
159
160 1
		$value_from = $conditions[$filter->getColumn()]['from'];
161 1
		$value_to = $conditions[$filter->getColumn()]['to'];
162
163 1
		if ($value_from) {
164 1
			$this->data_source->where("{$filter->getColumn()} >= ?", $value_from);
165
		}
166
167 1
		if ($value_to) {
168 1
			$this->data_source->where("{$filter->getColumn()} <= ?", $value_to);
169
		}
170 1
	}
171
172
173
	/**
174
	 * Filter by keyword
175
	 * @param  Filter\FilterText $filter
176
	 * @return void
177
	 */
178
	public function applyFilterText(Filter\FilterText $filter)
179
	{
180 1
		$or = [];
181 1
		$args = [];
182 1
		$big_or = '(';
183 1
		$big_or_args = [];
184 1
		$condition = $filter->getCondition();
185
186 1
		foreach ($condition as $column => $value) {
187 1
			$like = '(';
188 1
			$args = [];
189
190 1
			if ($filter->isExactSearch()) {
191 1
				$like .= "$column = ? OR ";
192 1
				$args[] = "$value";
193
			} else {
194 1 View Code Duplication
				if ($filter->hasSplitWordsSearch() === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195 1
					$words = [$value];
196
				} else {
197 1
					$words = explode(' ', $value);
198
				}
199 1
				foreach ($words as $word) {
200 1
					$like .= "$column LIKE ? OR ";
201 1
					$args[] = "%$word%";
202
				}
203
			}
204 1
			$like = substr($like, 0, strlen($like) - 4) . ')';
205
206 1
			$or[] = $like;
207 1
			$big_or .= "$like OR ";
208 1
			$big_or_args = array_merge($big_or_args, $args);
209
		}
210
211 1
		if (sizeof($or) > 1) {
212 1
			$big_or = substr($big_or, 0, strlen($big_or) - 4) . ')';
213
214 1
			$query = array_merge([$big_or], $big_or_args);
215
216 1
			call_user_func_array([$this->data_source, 'where'], $query);
217
		} else {
218 1
			$query = array_merge($or, $args);
219
220 1
			call_user_func_array([$this->data_source, 'where'], $query);
221
		}
222 1
	}
223
224
225
	/**
226
	 * Filter by multi select value
227
	 * @param  Filter\FilterMultiSelect $filter
228
	 * @return void
229
	 */
230
	public function applyFilterMultiSelect(Filter\FilterMultiSelect $filter)
231
	{
232
		$condition = $filter->getCondition();
233
		$values = $condition[$filter->getColumn()];
234
		$or = '(';
235
236
		if (sizeof($values) > 1) {
237
			$length = sizeof($values);
238
			$i = 1;
239
240
			foreach ($values as $value) {
241
				if ($i == $length) {
242
					$or .= $filter->getColumn() . ' = ?)';
243
				} else {
244
					$or .= $filter->getColumn() . ' = ? OR ';
245
				}
246
247
				$i++;
248
			}
249
250
			array_unshift($values, $or);
251
252
			call_user_func_array([$this->data_source, 'where'], $values);
253
		} else {
254
			$this->data_source->where($filter->getColumn() . ' = ?', reset($values));
255
		}
256
	}
257
258
259
	/**
260
	 * Filter by select value
261
	 * @param  Filter\FilterSelect $filter
262
	 * @return void
263
	 */
264
	public function applyFilterSelect(Filter\FilterSelect $filter)
265
	{
266
		$this->data_source->where($filter->getCondition());
267
	}
268
269
270
	/**
271
	 * Apply limit and offset on data
272
	 * @param int $offset
273
	 * @param int $limit
274
	 * @return static
275
	 */
276
	public function limit($offset, $limit)
277
	{
278 1
		$this->data = $this->data_source->limit($limit, $offset)->fetchAll();
279
280 1
		return $this;
281
	}
282
283
284
	/**
285
	 * Sort data
286
	 * @param  Sorting $sorting
287
	 * @return static
288
	 */
289 View Code Duplication
	public function sort(Sorting $sorting)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
290
	{
291 1
		if (is_callable($sorting->getSortCallback())) {
292
			call_user_func(
293
				$sorting->getSortCallback(),
294
				$this->data_source,
295
				$sorting->getSort()
296
			);
297
298
			return $this;
299
		}
300
301 1
		$sort = $sorting->getSort();
302
303 1
		if (!empty($sort)) {
304 1
			$this->data_source->getSqlBuilder()->setOrder([], []);
305
306 1
			foreach ($sort as $column => $order) {
307 1
				$this->data_source->order("$column $order");
308
			}
309
		} else {
310
			/**
311
			 * Has the statement already a order by clause?
312
			 */
313
			if (!$this->data_source->getSqlBuilder()->getOrder()) {
314
				$this->data_source->order($this->primary_key);
315
			}
316
		}
317
318 1
		return $this;
319
	}
320
321
322
	/**
323
	 * @param  callable $aggregationCallback
324
	 * @return void
325
	 */
326
	public function processAggregation(callable $aggregationCallback)
327
	{
328
		call_user_func($aggregationCallback, $this->data_source);
329
	}
330
}
331