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

CRUD_helpers::search_do()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 29
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 4
eloc 24
c 1
b 1
f 1
nc 6
nop 10
dl 0
loc 29
ccs 23
cts 23
cp 1
crap 4
rs 8.5806

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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