Completed
Push — master ( cfaeec...115a9a )
by Nazar
04:33
created

CRUD_helpers   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 1 Features 1
Metric Value
dl 0
loc 198
ccs 95
cts 95
cp 1
rs 10
c 1
b 1
f 1
wmc 30
lcom 1
cbo 3

5 Methods

Rating   Name   Duplication   Size   Complexity  
A search() 0 18 4
B search_do() 0 29 4
C search_conditions() 0 24 8
C search_order_by() 0 34 7
C search_conditions_join_table() 0 37 7
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2015-2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs;
9
/**
10
 * CRUD trait extended with useful additional methods, for example, for searching
11
 *
12
 * Might me used instead of regular CRUD trait
13
 */
14
trait CRUD_helpers {
15
	use
16
		CRUD;
17
	/**
18
	 * Generic search
19
	 *
20
	 * @param mixed[] $search_parameters Array in form [attribute => value];<br>
21
	 *                                   Or [attribute => [value1, value2, value3]];<br>
22
	 *                                   Or [attribute => [from => a, to => b]];<br>
23
	 *                                   Or [attribute => [...]] in case of joined tables, where ... is any of three constructions mentioned above;<br>
24
	 *                                   if `total_count => true` element is present - total number of found rows will be returned instead of rows themselves
25
	 * @param int     $page
26
	 * @param int     $count
27
	 * @param string  $order_by
28
	 * @param bool    $asc
29
	 *
30
	 * @return false|int|int[]|string[] Array of `id` or number of elements
31
	 */
32 12
	protected function search ($search_parameters = [], $page = 1, $count = 100, $order_by = 'id', $asc = false) {
33 12
		$joins        = '';
34 12
		$join_params  = [];
35 12
		$join_index   = 0;
36 12
		$where        = [];
37 12
		$where_params = [];
38 12
		foreach ($search_parameters as $key => $details) {
39 8
			if (!isset($this->data_model[$key])) {
40 2
				continue;
41
			}
42 8
			if (isset($this->data_model[$key]['data_model'])) {
43 4
				$this->search_conditions_join_table('t', $key, $details, $joins, $join_params, $join_index);
44
			} else {
45 8
				$this->search_conditions('t', $key, $details, $where, $where_params);
46
			}
47
		}
48 12
		return $this->search_do('t', @$search_parameters['total_count'], $where, $where_params, $joins, $join_params, $page, $count, $order_by, $asc);
49
	}
50
	/**
51
	 * @param string   $table_alias
52
	 * @param bool     $total_count
53
	 * @param string[] $where
54
	 * @param array    $where_params
55
	 * @param string   $joins
56
	 * @param array    $join_params
57
	 * @param int      $page
58
	 * @param int      $count
59
	 * @param string   $order_by
60
	 * @param bool     $asc
61
	 *
62
	 * @return false|int|int[]|string[]
63
	 */
64 12
	private function search_do ($table_alias, $total_count, $where, $where_params, $joins, $join_params, $page, $count, $order_by, $asc) {
65 12
		$first_column = array_keys($this->data_model)[0];
66 12
		$where        = $where ? 'WHERE '.implode(' AND ', $where) : '';
67 12
		if ($total_count) {
68 2
			return (int)$this->db()->qfs(
69 2
				"SELECT COUNT(`$table_alias`.`$first_column`)
70 2
				FROM `$this->table` AS `$table_alias`
71 2
				$joins
72 2
				$where
73 2
				GROUP BY `$table_alias`.`$first_column`",
74
				array_merge($join_params, $where_params)
75
			);
76
		}
77 12
		$where_params[] = $count;
78 12
		$where_params[] = ($page - 1) * $count;
79 12
		$order_by       = $this->search_order_by($table_alias, $order_by, $joins, $join_index);
80 12
		$asc            = $asc ? 'ASC' : 'DESC';
81 12
		$return         = $this->db()->qfas(
82 12
			"SELECT `$table_alias`.`$first_column`
83 12
			FROM `$this->table` AS `$table_alias`
84 12
			$joins
85 12
			$where
86 12
			GROUP BY `$table_alias`.`$first_column`, $order_by
87 12
			ORDER BY $order_by $asc
88 12
			LIMIT %d OFFSET %d",
89
			array_merge($join_params, $where_params)
90
		);
91 12
		return $this->read_field_post_processing($return, array_values($this->data_model)[0]);
92
	}
93
	/**
94
	 * @param string   $table_alias
95
	 * @param string   $key
96
	 * @param array    $details
97
	 * @param string[] $where
98
	 * @param array    $where_params
99
	 */
100 8
	private function search_conditions ($table_alias, $key, $details, &$where, &$where_params) {
101 8
		if (is_scalar($details)) {
102 8
			$where[]        = "`$table_alias`.`$key` = '%s'";
103 8
			$where_params[] = $details;
104 6
		} elseif (is_array($details) && $details) {
105 4
			if (is_array_indexed($details)) {
106 4
				$where_tmp = [];
107 4
				foreach ($details as $d) {
108 4
					$where_tmp[]    = "`$table_alias`.`$key` = '%s'";
109 4
					$where_params[] = $d;
110
				}
111 4
				$where[] = '('.implode(' OR ', $where_tmp).')';
112 4
				return;
113
			}
114 4
			if (isset($details['from'])) {
115 4
				$where[]        = "`$table_alias`.`$key` >= '%s'";
116 4
				$where_params[] = $details['from'];
117
			}
118 4
			if (isset($details['to'])) {
119 4
				$where[]        = "`$table_alias`.`$key` <= '%s'";
120 4
				$where_params[] = $details['to'];
121
			}
122
		}
123 8
	}
124
	/**
125
	 * @param string           $table_alias
126
	 * @param string           $table
127
	 * @param array|int|string $details
128
	 * @param string           $joins
129
	 * @param array            $join_params
130
	 * @param int              $join_index
131
	 */
132 4
	private function search_conditions_join_table ($table_alias, $table, $details, &$joins, &$join_params, &$join_index) {
133 4
		$data_model        = $this->data_model[$table];
134 4
		$first_column      = array_keys($this->data_model)[0];
135 4
		$first_column_join = array_keys($data_model['data_model'])[0];
136 4
		if (is_scalar($details)) {
137
			$details = [
138 4
				array_keys($data_model['data_model'])[1] => $details
139
			];
140
		}
141
		/**
142
		 * @var array $details
143
		 */
144 4
		++$join_index;
145
		$joins .=
146 4
			"INNER JOIN `{$this->table}_$table` AS `j$join_index`
147
			ON
148 4
				`$table_alias`.`$first_column` = `j$join_index`.`$first_column_join`";
149 4
		$language_field = isset($data_model['language_field']) ? $data_model['language_field'] : false;
150 4
		foreach ($details as $field => $value) {
151 4
			if ($language_field === $field) {
152 2
				continue;
153
			}
154 4
			$where_tmp = [];
155 4
			$this->search_conditions("j$join_index", $field, $value, $where_tmp, $join_params);
156 4
			$joins .= ' AND '.implode(' AND ', $where_tmp);
157
		}
158 4
		if ($language_field) {
159
			/** @noinspection OffsetOperationsInspection */
160 2
			$clang = isset($details[$language_field]) ? $details[$language_field] : Language::instance()->clang;
161
			$joins .=
162
				" AND
163
				(
164 2
					`j$join_index`.`lang`	= '$clang' OR
165 2
					`j$join_index`.`lang`	= ''
166 2
				)";
167
		}
168 4
	}
169
	/**
170
	 * @param string $table_alias
171
	 * @param string $order_by
172
	 * @param string $joins
173
	 * @param int    $join_index
174
	 *
175
	 * @return string
176
	 */
177 12
	private function search_order_by ($table_alias, $order_by, &$joins, &$join_index) {
178 12
		$order_by = explode(':', $order_by);
179 12
		if (!isset($this->data_model[$order_by[0]])) {
180
			/**
181
			 * Non-existing field
182
			 */
183 2
			$order_by = ['id'];
184 12
		} elseif (isset($order_by[1])) {
185
			/**
186
			 * Non-existing field in joined table
187
			 */
188 2
			if (!isset($this->data_model[$order_by[0]]['data_model'][$order_by[1]])) {
189 2
				$order_by = ['id'];
190
			}
191 12
		} elseif (is_array($this->data_model[$order_by[0]]) && isset($this->data_model[$order_by[0]]['data_model'])) {
192
			/**
193
			 * Default field in joined table
194
			 */
195 2
			$order_by[1] = array_keys($this->data_model[$order_by[0]]['data_model'])[1];
196
		}
197 12
		if (isset($order_by[1])) {
198 2
			++$join_index;
199 2
			$first_column      = array_keys($this->data_model)[0];
200 2
			$first_column_join = array_keys($this->data_model[$order_by[0]]['data_model'])[0];
201
			$joins .=
202 2
				"INNER JOIN `{$this->table}_$order_by[0]` AS `j$join_index`
203
				ON
204 2
					`$table_alias`.`$first_column`	= `j$join_index`.`$first_column_join`";
205 2
			$order_by = "`j$join_index`.`$order_by[1]`";
206
		} else {
207 12
			$order_by = "`$table_alias`.`$order_by[0]`";
208
		}
209 12
		return $order_by;
210
	}
211
}
212