Completed
Pull Request — master (#375)
by Dalibor
05:23
created

addAggregationColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
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 Ublaboo\DataGrid\Filter;
13
use Ublaboo\DataGrid\Utils\Sorting;
14
15
class NetteDatabaseTableDataSource extends FilterableDataSource implements IDataSource
16
{
17
18
	/**
19
	 * @var Selection
20
	 */
21
	protected $data_source;
22
23
	/**
24
	 * @var array
25
	 */
26
	protected  $aggregations =[];
27
28
	/**
29
	 * @var array
30
	 */
31
	protected $data = [];
32
33
	/**
34
	 * @var string
35
	 */
36
	protected $primary_key;
37
38
39
	/**
40
	 * @param Selection $data_source
41
	 * @param string $primary_key
42
	 */
43
	public function __construct(Selection $data_source, $primary_key)
44
	{
45
		$this->data_source = $data_source;
46
47
		$this->primary_key = $primary_key;
48
	}
49
50
51
	/********************************************************************************
52
	 *                          IDataSource implementation                          *
53
	 ********************************************************************************/
54
55
56
	/**
57
	 * Get count of data
58
	 * @return int
59
	 */
60
	public function getCount()
61
	{
62
		try {
63
			$primary = $this->data_source->getPrimary();
64
		} catch (\LogicException $e) {
65
			return $this->data_source->count('*');
66
		}
67
68
		return $this->data_source->count(
69
			$this->data_source->getName() . '.' . (is_array($primary) ? reset($primary) : $primary)
70
		);
71
	}
72
73
74
	/**
75
	 * Get the data
76
	 * @return array
77
	 */
78
	public function getData()
79
	{
80
		return $this->data ?: $this->data_source->fetchAll();
81
	}
82
83
84
	/**
85
	 * Filter data - get one row
86
	 * @param array $condition
87
	 * @return static
88
	 */
89
	public function filterOne(array $condition)
90
	{
91
		$this->data_source->where($condition)->limit(1);
92
93
		return $this;
94
	}
95
96
97
	/**
98
	 * Filter by date
99
	 * @param  Filter\FilterDate $filter
100
	 * @return void
101
	 */
102 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...
103
	{
104
		$conditions = $filter->getCondition();
105
106
		$date = \DateTime::createFromFormat($filter->getPhpFormat(), $conditions[$filter->getColumn()]);
107
108
		$this->data_source->where("DATE({$filter->getColumn()}) = ?", $date->format('Y-m-d'));
109
	}
110
111
112
	/**
113
	 * Filter by date range
114
	 * @param  Filter\FilterDateRange $filter
115
	 * @return void
116
	 */
117 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...
118
	{
119
		$conditions = $filter->getCondition();
120
121
		$value_from = $conditions[$filter->getColumn()]['from'];
122
		$value_to   = $conditions[$filter->getColumn()]['to'];
123
124
		if ($value_from) {
125
			$date_from = \DateTime::createFromFormat($filter->getPhpFormat(), $value_from);
126
			$date_from->setTime(0, 0, 0);
127
128
			$this->data_source->where("DATE({$filter->getColumn()}) >= ?", $date_from->format('Y-m-d'));
129
		}
130
131
		if ($value_to) {
132
			$date_to = \DateTime::createFromFormat($filter->getPhpFormat(), $value_to);
133
			$date_to->setTime(23, 59, 59);
134
135
			$this->data_source->where("DATE({$filter->getColumn()}) <= ?", $date_to->format('Y-m-d'));
136
		}
137
	}
138
139
140
	/**
141
	 * Filter by range
142
	 * @param  Filter\FilterRange $filter
143
	 * @return void
144
	 */
145 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...
146
	{
147
		$conditions = $filter->getCondition();
148
149
		$value_from = $conditions[$filter->getColumn()]['from'];
150
		$value_to   = $conditions[$filter->getColumn()]['to'];
151
152
		if ($value_from) {
153
			$this->data_source->where("{$filter->getColumn()} >= ?", $value_from);
154
		}
155
156
		if ($value_to) {
157
			$this->data_source->where("{$filter->getColumn()} <= ?", $value_to);
158
		}
159
	}
160
161
162
	/**
163
	 * Filter by keyword
164
	 * @param  Filter\FilterText $filter
165
	 * @return void
166
	 */
167
	public function applyFilterText(Filter\FilterText $filter)
168
	{
169
		$or = [];
170
		$args = [];
171
		$big_or = '(';
172
		$big_or_args = [];
173
		$condition = $filter->getCondition();
174
175
		foreach ($condition as $column => $value) {
176
177
			$like = '(';
178
			$args = [];
179
180
			if($filter->isExactSearch()){
181
				$like .=  "$column = ? OR ";
182
				$args[] = "$value";
183
			} else {
184 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...
185
					$words = [$value];
186
				} else {
187
					$words = explode(' ', $value);
188
				}
189
				foreach ($words as $word) {
190
					$like .= "$column LIKE ? OR ";
191
					$args[] = "%$word%";
192
				}
193
			}
194
			$like = substr($like, 0, strlen($like) - 4) . ')';
195
196
			$or[] = $like;
197
			$big_or .= "$like OR ";
198
			$big_or_args = array_merge($big_or_args, $args);
199
		}
200
201
		if (sizeof($or) > 1) {
202
			$big_or = substr($big_or, 0, strlen($big_or) - 4).')';
203
204
			$query = array_merge([$big_or], $big_or_args);
205
206
			call_user_func_array([$this->data_source, 'where'], $query);
207
		} else {
208
			$query = array_merge($or, $args);
209
210
			call_user_func_array([$this->data_source, 'where'], $query);
211
		}
212
	}
213
214
215
	/**
216
	 * Filter by multi select value
217
	 * @param  Filter\FilterMultiSelect $filter
218
	 * @return void
219
	 */
220
	public function applyFilterMultiSelect(Filter\FilterMultiSelect $filter)
221
	{
222
		$condition = $filter->getCondition();
223
		$values = $condition[$filter->getColumn()];
224
		$or = '(';
225
226
		if (sizeof($values) > 1) {
227
			$length = sizeof($values);
228
			$i = 1;
229
		
230
			foreach ($values as $value) {
231
				if ($i == $length) {
232
					$or .= $filter->getColumn() . ' = ?)';
233
				} else {
234
					$or .= $filter->getColumn() . ' = ? OR ';
235
				}
236
237
				$i++;
238
			}
239
240
			array_unshift($values, $or);
241
242
			call_user_func_array([$this->data_source, 'where'], $values);
243
		} else {
244
			$this->data_source->where($filter->getColumn() . ' = ?', reset($values));
245
		}
246
	}
247
248
249
	/**
250
	 * Filter by select value
251
	 * @param  Filter\FilterSelect $filter
252
	 * @return void
253
	 */
254
	public function applyFilterSelect(Filter\FilterSelect $filter)
255
	{
256
		$this->data_source->where($filter->getCondition());
257
	}
258
259
260
	/**
261
	 * Apply limit and offset on data
262
	 * @param int $offset
263
	 * @param int $limit
264
	 * @return static
265
	 */
266
	public function limit($offset, $limit)
267
	{
268
		$this->data = $this->data_source->limit($limit, $offset)->fetchAll();
269
270
		return $this;
271
	}
272
273
274
	/**
275
	 * Sort data
276
	 * @param  Sorting $sorting
277
	 * @return static
278
	 */
279 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...
280
	{
281
		if (is_callable($sorting->getSortCallback())) {
282
			call_user_func(
283
				$sorting->getSortCallback(),
284
				$this->data_source,
285
				$sorting->getSort()
286
			);
287
288
			return $this;
289
		}
290
291
		$sort = $sorting->getSort();
292
293
		if (!empty($sort)) {
294
			$this->data_source->getSqlBuilder()->setOrder([], []);
295
296
			foreach ($sort as $column => $order) {
297
				$this->data_source->order("$column $order");
298
			}
299
		} else {
300
			/**
301
			 * Has the statement already a order by clause?
302
			 */
303
			if (!$this->data_source->getSqlBuilder()->getOrder()) {
304
				$this->data_source->order($this->primary_key);
305
			}
306
		}
307
308
		return $this;
309
	}
310
311
	/**
312
	 * @param string $aggregation_type
313
	 * @param string $column
314
	 * @return mixed|void
315
	 */
316
	public function addAggregationColumn($aggregation_type, $column)
317
	{
318
		$this->aggregations[$column] = $aggregation_type;
319
	}
320
321
	/**
322
	 * get aggregation row
323
	 * @return array
324
	 */
325
	public function getAggregationData()
326
	{
327
		$result = [];
328
		//there should really be some better way to do this and get all results in one query, this could be big performance issue on bigger tables
329
		foreach ($this->aggregations as $column => $aggregation_type) {
330
			$result[$column] = $this->data_source->aggregation($aggregation_type . '(' . $column . ')');
331
		}
332
		return $result;
333
	}
334
}
335