Completed
Push — master ( 780e00...bee80f )
by Hong
02:28
created

WhereTrait::buildWhere()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 13
nc 4
nop 2
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
160
        // fix raw mode
161
        $rawMode = $this->isRaw($col, $rawMode);
162
163
        // fix operator to '='
164
        $this->fixOperator($operator, $value, $rawMode);
165
166
        $clause[] = [$rawMode, $whereNot, $logicAnd, $col, $operator, $value];
167
        return $this;
168
    }
169
170
    /**
171
     * @param  array $cols
172
     * @param  string $logicAnd
173
     * @param  string $whereNot
174
     * @param  bool $rawMode
175
     * @access protected
176
     */
177
    protected function multipleWhere(
178
        array $cols,
179
        /*# string */ $logicAnd = 'AND',
180
        /*# string */ $whereNot = '',
181
        /*# bool */ $rawMode  = false
182
    ) {
183
        foreach ($cols as $fld => $val) {
184
            if (is_array($val)) {
185
                $opr = $val[0];
186
                $val = $val[1];
187
            } else {
188
                $opr = '=';
189
            }
190
            $this->realWhere($fld, $opr, $val, $logicAnd, $whereNot, $rawMode);
191
        }
192
    }
193
194
    /**
195
     * Fix where('id', 18) to where('id', '=', 18)
196
     *
197
     * @param  mixed &$operator
198
     * @param  mixed &$value
199
     * @param  bool $rawMode
200
     * @access protected
201
     */
202
    protected function fixOperator(&$operator, &$value, $rawMode)
203
    {
204
        if (!$rawMode && WhereInterface::NO_VALUE === $value) {
205
            $value = $operator;
206
            $operator = '=';
207
        }
208
    }
209
210
    /**
211
     * Build WHERE
212
     *
213
     * @param  prefix
214
     * @param  array $settings
215
     * @return array
216
     * @access protected
217
     */
218
    protected function buildWhere(
219
        /*# string */ $prefix,
220
        array $settings
221
    )/*# : string */ {
222
        $result = [];
223
        if ('HAVING' === $prefix) {
224
            $wheres = &$this->getClause($prefix);
225
        } else {
226
            $wheres = &$this->getClause('WHERE');
227
        }
228
        foreach ($wheres as $idx => $where) {
229
            $cls = [];
230
            // build AND|OR|NOT
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
231
            $this->buildAndOr($cls, $where, $idx);
232
            // build COL = VAL
233
            $result[] = $this->buildCondition($cls, $where, $settings);
234
        }
235
        return $this->joinClause($prefix, '', $result, $settings);
236
    }
237
238
    /**
239
     * build 'AND NOT' part of the clause part
240
     *
241
     * @param  array &$cls
242
     * @param  array $where
243
     * @param  int $idx
244
     * @access protected
245
     */
246
    protected function buildAndOr(array &$cls, array $where, $idx)
247
    {
248
        // AND OR
249
        if ($idx) {
250
            $cls[] = $where[2];
251
        }
252
        // NOT
253
        if ($where[1]) {
254
            $cls[] = $where[1];
255
        }
256
    }
257
258
    /**
259
     * Build 'col = val' part
260
     *
261
     * @param  array $cls
262
     * @param  array $where
263
     * @param  array $settings
264
     * @return string
265
     * @access protected
266
     */
267
    protected function buildCondition(array $cls, array $where, array $settings)
268
    {
269
        if (!empty($where[3])) {
270
            $cls[] = $this->quoteItem(
271
                $where[3], $settings, $this->isRaw($where[3], $where[0])
272
            );
273
        }
274
        if (WhereInterface::NO_OPERATOR !== $where[4]) {
275
            $cls[] = $where[4];
276
        }
277
        if (WhereInterface::NO_VALUE !== $where[5]) {
278
            $cls[] = $this->processValue($where[5], $settings,
279
                (bool) preg_match('/\bbetween\b/i', $where[4]));
280
        }
281
        return join(' ', $cls);
282
    }
283
284
    abstract protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */;
285
    abstract protected function processValue($value, array $settings, /*# bool */ $between = false)/*# : string */;
286
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
287
    abstract protected function quoteItem($item, array $settings, /*# bool */ $rawMode = false)/*# : string */;
288
    abstract protected function joinClause(
289
        /*# : string */ $prefix,
290
        /*# : string */ $seperator,
291
        array $clause,
292
        array $settings
293
    )/*# : string */;
294
    /**
295
     * Return the builder
296
     *
297
     * @return BuilderInterface
298
     * @access public
299
     */
300
    abstract public function getBuilder()/*# : BuilderInterface */;
301
}
302