Passed
Push — master ( a9306a...617383 )
by Adrian
01:44
created

WhereAndHavingBuilder::makeBetweenCondition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 1
eloc 13
nc 1
nop 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Adrian Dumitru
5
 * Date: 9/29/2017
6
 * Time: 4:20 PM
7
 */
8
9
namespace Qpdb\QueryBuilder\Traits;
10
11
12
use Qpdb\QueryBuilder\Dependencies\QueryException;
13
use Qpdb\QueryBuilder\Dependencies\QueryHelper;
14
use Qpdb\QueryBuilder\Dependencies\QueryStructure;
15
use Qpdb\QueryBuilder\Statements\QuerySelect;
16
17
trait WhereAndHavingBuilder
18
{
19
20
	use Objects;
21
22
	/**
23
	 * @var string|array
24
	 */
25
	private $temporaryParam;
26
27
	/**
28
	 * @var string
29
	 */
30
	private $temporaryGlue;
31
32
	/**
33
	 * @var string;
34
	 */
35
	private $temporaryClauseType;
36
37
38
	/**
39
	 * @param $param
40
	 * @param string $glue
41
	 * @param $clauseType
42
	 * @return $this
43
	 */
44
	protected function createCondition( $param, $glue = 'AND', $clauseType )
45
	{
46
47
		if ( !is_array( $param ) ) {
48
			$this->queryStructure->setElement( $clauseType, array( 'glue' => $glue, 'body' => trim( $param ), 'type' => 'cond' ) );
49
50
			return $this;
51
		}
52
53
		$this->temporaryParam = $this->validateWhereParam( $param );
54
		$this->temporaryGlue = $glue;
55
		$this->temporaryClauseType = $clauseType;
56
57
		$this->buildCondition();
58
59
		return $this;
60
	}
61
62
	private function buildCondition()
63
	{
64
		$operator = $this->temporaryParam[ 2 ];
65
66
		switch ( $operator ) {
67
			case 'BETWEEN':
68
			case 'NOT BETWEEN':
69
			case '!BETWEEN':
70
				$this->makeBetweenCondition();
71
				break;
72
			case 'IN':
73
			case 'NOT IN':
74
			case '!IN':
75
				$this->makeInCondition();
76
				break;
77
			default:
78
				$valuePdoString = $this->queryStructure->bindParam( $this->temporaryParam[ 0 ], $this->temporaryParam[ 1 ] );
79
				$body = $this->temporaryParam[ 0 ] . ' ' . $operator . ' ' . $valuePdoString;
80
				$this->registerCondition($body);
81
				break;
82
		}
83
	}
84
85
	private function makeBetweenCondition()
86
	{
87
		$field = $this->temporaryParam[ 0 ];
88
		$value = $this->temporaryParam[ 1 ];
89
		$operator = $this->temporaryParam[ 2 ];
90
91
		$min = $value[ 0 ];
92
		$max = $value[ 1 ];
93
		$body = [
94
			$field,
95
			$operator,
96
			$this->queryStructure->bindParam( 'min', $min ),
97
			'AND',
98
			$this->queryStructure->bindParam( 'max', $max )
99
		];
100
		$body = implode( ' ', $body );
101
		$this->registerCondition($body);
102
	}
103
104
	private function makeInCondition()
105
	{
106
		if ( is_a( $this->temporaryParam[ 1 ], QuerySelect::class ) )
107
			$this->inQuerySelect();
108
		elseif ( is_array( $this->temporaryParam[ 1 ] ) )
109
			$this->inArray();
110
	}
111
112
	private function inQuerySelect()
113
	{
114
		$field = $this->temporaryParam[0];
115
		/** @var QuerySelect $subquerySelect */
116
		$subquerySelect = $this->temporaryParam[1];
117
		$operator = $this->temporaryParam[2];
118
		$subquerySelectParams = $subquerySelect->getBindParams();
119
		foreach ( $subquerySelectParams as $key => $value ) {
120
			$this->queryStructure->setParams( $key, $value );
121
		}
122
		$body = [
123
			$field,
124
			$operator,
125
			'( ',
126
			$subquerySelect->getSyntax(),
127
			' )'
128
		];
129
		$body = implode( ' ', $body );
130
		$this->registerCondition($body);
131
132
	}
133
134
	private function inArray()
135
	{
136
		$field = $this->temporaryParam[0];
137
		$value = $this->temporaryParam[1];
138
		$operator = $this->temporaryParam[2];
139
140
		$pdoArray = array();
141
		foreach ( $value as $item ) {
142
			$pdoArray[] = $this->queryStructure->bindParam( 'a', $item );
143
		}
144
		$body = [
145
			$field,
146
			$operator,
147
			'( ' . implode( ', ', $pdoArray ) . ' )'
148
		];
149
		$body = implode( ' ', $body );
150
		$body = QueryHelper::clearMultipleSpaces( $body );
151
		$this->registerCondition($body);
152
	}
153
154
	/**
155
	 * @param string|array $body
156
	 */
157
	private function registerCondition( $body )
158
	{
159
		$this->queryStructure->setElement( $this->temporaryClauseType, array( 'glue' => $this->temporaryGlue, 'body' => $body, 'type' => 'cond' ) );
160
	}
161
162
163
	/**
164
	 * @return bool|mixed|string
165
	 */
166
	private function getWhereSyntax()
167
	{
168
		return $this->getWhereAndHavingSyntax( QueryStructure::WHERE );
169
	}
170
171
	/**
172
	 * @return bool|mixed|string
173
	 */
174
	private function getHavingSyntax()
175
	{
176
		return $this->getWhereAndHavingSyntax( QueryStructure::HAVING );
177
	}
178
179
	/**
180
	 * @param $clauseType
181
	 * @return bool|mixed|string
182
	 */
183
	private function getWhereAndHavingSyntax( $clauseType )
184
	{
185
		if ( count( $this->queryStructure->getElement( $clauseType ) ) == 0 )
186
			return '';
187
188
		$where = '';
189
		$last_type = 'where_start';
190
		foreach ( $this->queryStructure->getElement( $clauseType ) as $where_cond ) {
191
			$glue = $where_cond[ 'glue' ];
192
			if ( $last_type == 'where_start' || $last_type == 'start_where_group' ) {
193
				$glue = '';
194
			}
195
			$where .= ' ' . $glue . ' ' . $where_cond[ 'body' ];
196
			$last_type = $where_cond[ 'type' ];
197
		}
198
199
		if ( $this->queryStructure->getElement( $clauseType . '_invert' ) ) {
200
			$where = ' NOT ( ' . $where . ' ) ';
201
		}
202
203
		$where = strtoupper( $clauseType ) . ' ' . $where;
204
205
		return QueryHelper::clearMultipleSpaces( $where );
206
	}
207
208
	/**
209
	 * @param $param
210
	 * @return array
211
	 * @throws QueryException
212
	 */
213
	private function validateWhereParam( $param )
214
	{
215
		if ( count( $param ) < 2 )
216
			throw new QueryException( 'Invalid where array!', QueryException::QUERY_ERROR_WHERE_INVALID_PARAM_ARRAY );
217
218
		if ( count( $param ) == 2 )
219
			$param[] = '=';
220
221
		$param[ 2 ] = trim( strtoupper( $param[ 2 ] ) );
222
		$param[ 2 ] = QueryHelper::clearMultipleSpaces( $param[ 2 ] );
223
224
		return $param;
225
	}
226
227
}