Completed
Push — master ( bee80f...77f155 )
by Hong
02:34
created

WhereTrait::realWhere()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
cc 2
eloc 16
nc 2
nop 7
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Query
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Query\Traits\Clause;
16
17
use Phossa2\Query\Misc\Template;
18
use Phossa2\Query\Interfaces\Clause\WhereInterface;
19
20
/**
21
 * WhereTrait
22
 *
23
 * Implementation of WhereInterface
24
 *
25
 * @package Phossa2\Query
26
 * @author  Hong Zhang <[email protected]>
27
 * @see     WhereInterface
28
 * @version 2.0.0
29
 * @since   2.0.0 added
30
 */
31
trait WhereTrait
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    public function where(
37
        $col,
38
        $operator = WhereInterface::NO_OPERATOR,
39
        $value = WhereInterface::NO_VALUE
40
    ) {
41
        return $this->realWhere($col, $operator, $value);
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     */
47
    public function whereTpl(/*# string */ $template, $col)
48
    {
49
        return $this->realWhere(new Template($template, $col),
50
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
51
            'AND', '');
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public function orWhereTpl(/*# string */ $template, $col)
58
    {
59
        return $this->realWhere(new Template($template, $col),
60
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
61
            'OR', '');
62
    }
63
64
    /**
65
     * {@inheritDoc}
66
     */
67 View Code Duplication
    public function whereRaw(/*# string */ $rawString)
1 ignored issue
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...
68
    {
69
        if (func_num_args() > 1) {
70
            $rawString = $this->getBuilder()->raw($rawString, func_get_arg(1));
71
        }
72
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
73
            WhereInterface::NO_VALUE, 'AND', '', true);
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79 View Code Duplication
    public function orWhereRaw(/*# string */ $rawString)
1 ignored issue
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...
80
    {
81
        if (func_num_args() > 1) {
82
            $rawString = $this->getBuilder()->raw($rawString, func_get_arg(1));
83
        }
84
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
85
            WhereInterface::NO_VALUE, 'OR', '', true);
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     */
91
    public function andWhere(
92
        $col,
93
        $operator = WhereInterface::NO_OPERATOR,
94
        $value = WhereInterface::NO_VALUE
95
    ) {
96
        return $this->realWhere($col, $operator, $value);
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     */
102
    public function orWhere(
103
        $col,
104
        $operator = WhereInterface::NO_OPERATOR,
105
        $value = WhereInterface::NO_VALUE
106
    ) {
107
        return $this->realWhere($col, $operator, $value, 'OR');
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113
    public function whereNot(
114
        $col,
115
        $operator = WhereInterface::NO_OPERATOR,
116
        $value = WhereInterface::NO_VALUE
117
    ) {
118
        return $this->realWhere($col, $operator, $value, 'AND', 'NOT');
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     */
124
    public function orWhereNot(
125
        $col,
126
        $operator = WhereInterface::NO_OPERATOR,
127
        $value = WhereInterface::NO_VALUE
128
    ) {
129
        return $this->realWhere($col, $operator, $value, 'OR', 'NOT');
130
    }
131
132
    /**
133
     * Real where
134
     *
135
     * @param  string|string[]|Template $col col or cols
136
     * @param  mixed $operator
137
     * @param  mixed $value
138
     * @param  string $logicAnd 'AND'
139
     * @param  string $whereNot 'WHERE NOT'
140
     * @param  bool $rawMode
141
     * @param  string $clause 'where' or 'having'
142
     * @return $this
143
     * @access protected
144
     */
145
    protected function realWhere(
146
        $col,
147
        $operator = WhereInterface::NO_OPERATOR,
148
        $value    = WhereInterface::NO_VALUE,
149
        /*# string */ $logicAnd = 'AND',
150
        /*# string */ $whereNot = '',
151
        /*# bool */ $rawMode = false,
152
        /*# string */ $clause = 'WHERE'
153
    ) {
154
        $clause = &$this->getClause($clause);
155
        if (is_array($col)) {
156
            $this->multipleWhere($col, $logicAnd, $whereNot, $rawMode);
157
            return $this;
158
        }
159
        // fix raw mode
160
        $rawMode = $this->isRaw($col, $rawMode);
161
        // fix operator to '='
162
        $this->fixOperator($operator, $value, $rawMode);
163
        $clause[] = [$rawMode, $whereNot, $logicAnd, $col, $operator, $value];
164
        return $this;
165
    }
166
167
    /**
168
     * @param  array $cols
169
     * @param  string $logicAnd
170
     * @param  string $whereNot
171
     * @param  bool $rawMode
172
     * @access protected
173
     */
174
    protected function multipleWhere(
175
        array $cols,
176
        /*# string */ $logicAnd = 'AND',
177
        /*# string */ $whereNot = '',
178
        /*# bool */ $rawMode  = false
179
    ) {
180
        foreach ($cols as $fld => $val) {
181
            if (is_array($val)) {
182
                $opr = $val[0];
183
                $val = $val[1];
184
            } else {
185
                $opr = '=';
186
            }
187
            $this->realWhere($fld, $opr, $val, $logicAnd, $whereNot, $rawMode);
188
        }
189
    }
190
191
    /**
192
     * Fix where('id', 18) to where('id', '=', 18)
193
     *
194
     * @param  mixed &$operator
195
     * @param  mixed &$value
196
     * @param  bool $rawMode
197
     * @access protected
198
     */
199
    protected function fixOperator(&$operator, &$value, $rawMode)
200
    {
201
        if (!$rawMode && WhereInterface::NO_VALUE === $value) {
202
            $value = $operator;
203
            $operator = '=';
204
        }
205
    }
206
207
    /**
208
     * Build WHERE
209
     *
210
     * @param  prefix
211
     * @param  array $settings
212
     * @return array
213
     * @access protected
214
     */
215
    protected function buildWhere(
216
        /*# string */ $prefix,
217
        array $settings
218
    )/*# : string */ {
219
        $result = [];
220
        if ('HAVING' === $prefix) {
221
            $wheres = &$this->getClause($prefix);
222
        } else {
223
            $wheres = &$this->getClause('WHERE');
224
        }
225
        foreach ($wheres as $idx => $where) {
226
            $cls = [];
227
            // build AND part
228
            $this->buildAndOr($cls, $where, $idx);
229
            // build COL = VAL
230
            $result[] = $this->buildCondition($cls, $where, $settings);
231
        }
232
        return $this->joinClause($prefix, '', $result, $settings);
233
    }
234
235
    /**
236
     * build 'AND NOT' part of the clause part
237
     *
238
     * @param  array &$cls
239
     * @param  array $where
240
     * @param  int $idx
241
     * @access protected
242
     */
243
    protected function buildAndOr(array &$cls, array $where, $idx)
244
    {
245
        // AND OR
246
        if ($idx) {
247
            $cls[] = $where[2];
248
        }
249
        // NOT
250
        if ($where[1]) {
251
            $cls[] = $where[1];
252
        }
253
    }
254
255
    /**
256
     * Build 'col = val' part
257
     *
258
     * @param  array $cls
259
     * @param  array $where
260
     * @param  array $settings
261
     * @return string
262
     * @access protected
263
     */
264
    protected function buildCondition(array $cls, array $where, array $settings)
265
    {
266
        if (!empty($where[3])) {
267
            $cls[] = $this->quoteItem(
268
                $where[3], $settings, $this->isRaw($where[3], $where[0])
269
            );
270
        }
271
        if (WhereInterface::NO_OPERATOR !== $where[4]) {
272
            $cls[] = $where[4];
273
        }
274
        if (WhereInterface::NO_VALUE !== $where[5]) {
275
            $cls[] = $this->processValue($where[5], $settings,
276
                (bool) preg_match('/\bbetween\b/i', $where[4]));
277
        }
278
        return join(' ', $cls);
279
    }
280
281
    abstract protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */;
282
    abstract protected function processValue($value, array $settings, /*# bool */ $between = false)/*# : string */;
283
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
284
    abstract protected function quoteItem($item, array $settings, /*# bool */ $rawMode = false)/*# : string */;
285
    abstract protected function joinClause(
286
        /*# : string */ $prefix,
287
        /*# : string */ $seperator,
288
        array $clause,
289
        array $settings
290
    )/*# : string */;
291
    /**
292
     * Return the builder
293
     *
294
     * @return BuilderInterface
295
     * @access public
296
     */
297
    abstract public function getBuilder()/*# : BuilderInterface */;
298
}
299