Completed
Push — master ( 46dbb7...9c8538 )
by Hong
02:48
created

ClauseTrait::quoteItem()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 7
nc 3
nop 3
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\Interfaces\OutputInterface;
18
use Phossa2\Query\Interfaces\ClauseInterface;
19
use Phossa2\Query\Interfaces\BuilderInterface;
20
use Phossa2\Query\Interfaces\StatementInterface;
21
22
/**
23
 * ClauseTrait
24
 *
25
 * @package Phossa2\Query
26
 * @author  Hong Zhang <[email protected]>
27
 * @see     ClauseInterface
28
 * @version 2.0.0
29
 * @since   2.0.0 added
30
 */
31
trait ClauseTrait
32
{
33
    use QuoteTrait;
34
35
    /**
36
     * storage for clauses
37
     *
38
     * @var    array
39
     * @access protected
40
     */
41
    protected $clause = [];
42
43
    /**
44
     * Is $str a raw sql string ?
45
     *
46
     * @param  mixed $str
47
     * @param  bool $rawMode
48
     * @access protected
49
     */
50
    protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */
51
    {
52
        if ($rawMode) {
53
            return true;
54
        }
55
56
        if (is_string($str)) {
57
            return (bool) preg_match('/[^0-9a-zA-Z\$_.]/', $str);
58
        }
59
60
        return is_object($str);
61
    }
62
63
    /**
64
     * Quote an alias if not an int
65
     *
66
     * @param  int|string $alias
67
     * @param  array $settings
68
     * @return string
69
     * @access protected
70
     */
71
    protected function quoteAlias($alias, array $settings)/*# : string */
72
    {
73
        if (is_int($alias)) {
74
            return '';
75
        } else {
76
            $prefix = $settings['quotePrefix'];
77
            $suffix = $settings['quoteSuffix'];
78
            return ' AS ' . $this->quoteSpace($alias, $prefix, $suffix);
79
        }
80
    }
81
82
    /**
83
     * Quote an item if it is a field/column
84
     *
85
     * @param  string|StatementInterface $item
86
     * @param  array $settings
87
     * @param  bool $rawMode
88
     * @access protected
89
     */
90
    protected function quoteItem(
91
        $item,
92
        array $settings,
93
        /*# bool */ $rawMode = false
94
    )/*# : string */ {
95
        // is an object
96
        if (is_object($item)) {
97
            return $this->quoteObject($item, $settings);
98
        }
99
100
        // is a string, quote with prefix and suffix
101
        return $rawMode ? $item : $this->quote($item, $settings);
102
    }
103
104
    /**
105
     * Quote object
106
     *
107
     * @param  object $object
108
     * @param  array $settings
109
     * @return string
110
     * @access protected
111
     */
112
    protected function quoteObject($object, $settings)/*# : string */
113
    {
114
        if ($object instanceof StatementInterface) {
115
            $settings = $this->flatSettings($settings);
116
            return '(' . ltrim($object->getStatement($settings)) . ')';
117
        } elseif ($object instanceof OutputInterface) {
118
            return $object->getStatement($settings);
119
        }
120
        return (string) $object;
121
    }
122
123
    /**
124
     * Return specific clause part
125
     *
126
     * @param  string $clauseName
127
     * @param  array
128
     * @access protected
129
     */
130
    protected function &getClause(/*# string */ $clauseName)/*# : array */
131
    {
132
        if (empty($clauseName)) {
133
            return $this->clause;
134
        } else {
135
            if (!isset($this->clause[$clauseName])) {
136
                $this->clause[$clauseName] = [];
137
            }
138
            return $this->clause[$clauseName];
139
        }
140
    }
141
142
    /**
143
     * Quote string even with space inside
144
     *
145
     * @param  string $str
146
     * @param  string $prefix
147
     * @param  string $suffix
148
     * @return string
149
     * @access protected
150
     */
151
    protected function quoteSpace(
152
        /*# string */ $str,
153
        /*# string */ $prefix,
154
        /*# string */ $suffix
155
    )/*# : string */ {
156
        return sprintf('%s%s%s', $prefix, $str, $suffix);
157
    }
158
159
    /**
160
     * Process value part in the clause
161
     *
162
     * @param  mixed $value
163
     * @param  array $settings
164
     * @return string
165
     * @access protected
166
     */
167
    protected function processValue(
168
        $value,
169
        array $settings,
170
        /*# bool */ $between = false
171
    )/*# : string */ {
172
        if (is_object($value)) {
173
            return $this->quoteObject($value, $settings);
174
        } elseif (is_array($value)) {
175
            return $this->processValueArray($value, $settings, $between);
176
        } else {
177
            return $this->processValueScalar($value);
178
        }
179
    }
180
181
    /**
182
     * Process value array
183
     *
184
     * @param  array $value
185
     * @param  array $settings
186
     * @return string
187
     * @access protected
188
     */
189
    protected function processValueArray(
190
        array $value,
191
        array $settings,
192
        /*# bool */ $between = false
193
    )/*# : string */ {
194
        if ($between) {
195
            $v1 = $this->processValue($value[0], $settings);
196
            $v2 = $this->processValue($value[1], $settings);
197
            return $v1 . ' AND ' . $v2;
198
        } else {
199
            $result = [];
200
            foreach ($value as $val) {
201
                $result[] = $this->processValue($val, $settings);
202
            }
203
            return '(' . join(', ', $result) . ')';
204
        }
205
    }
206
207
    /**
208
     * Process scalar value
209
     *
210
     * @param  mixed $value
211
     * @return string
212
     * @access protected
213
     */
214
    protected function processValueScalar($value)/*# : string */
215
    {
216
        if (ClauseInterface::NO_VALUE == $value) {
217
            return '?';
218
        } elseif (is_null($value)) {
219
            return 'NULL';
220
        } elseif (is_bool($value)) {
221
            return $value ? 'TRUE' : 'FALSE';
222
        } else {
223
            return $this->getBuilder()->getParameter()->getPlaceholder($value);
224
        }
225
    }
226
227
    /**
228
     * Join a clause with prefix and its parts
229
     *
230
     * @param  string $prefix
231
     * @param  string $seperator
232
     * @param  array $clause
233
     * @param  array $settings
234
     * @return string
235
     * @access protected
236
     */
237
    protected function joinClause(
238
        /*# : string */ $prefix,
239
        /*# : string */ $seperator,
240
        array $clause,
241
        array $settings
242
    )/*# : string */ {
243
        if (empty($clause)) {
244
            return '';
245
        } else {
246
            $join = $settings['seperator'] . $settings['indent'];
247
            $pref = empty($prefix) ? '' : ($prefix . $join);
248
            return $settings['seperator'] . $pref . join($seperator . $join, $clause);
249
        }
250
    }
251
252
    /**
253
     * Build a generic clause
254
     *
255
     * @param  string $clauseName
256
     * @param  string $clausePrefix
257
     * @param  array $settings
258
     * @param  array $clauseParts
259
     * @return string
260
     * @access protected
261
     */
262
    protected function buildClause(
263
        /*# string */ $clauseName,
264
        /*# string */ $clausePrefix,
265
        array $settings,
266
        array $clauseParts = []
267
    )/*# string */ {
268
        $clause = &$this->getClause($clauseName);
269
        foreach ($clause as $alias => $field) {
270
            $part =
271
                $this->quoteItem($field[0], $settings, $field[1]) .
272
                $this->quoteAlias($alias, $settings) .
273
                (isset($field[2]) ? (' ' . $field[2]) : '');
274
            $clauseParts[] = $part;
275
        }
276
        return $this->joinClause($clausePrefix, ',', $clauseParts, $settings);
277
    }
278
279
    /**
280
     * Reset settings to print flat
281
     *
282
     * @param  array $settings
283
     * @return array
284
     * @access protected
285
     */
286
    protected function flatSettings(array $settings)/*# : array */
287
    {
288
        return array_replace(
289
            $settings,
290
            ['seperator' => ' ', 'indent' => '']
291
        );
292
    }
293
294
    /**
295
     * Dealing with positioned parameters
296
     *
297
     * e.g. havingRaw('id > ?', [10]) turns into  havingRaw('id > 10')
298
     *
299
     * @param  string $rawString
300
     * @param  array $args
301
     * @param  int $num
302
     * @access protected
303
     */
304
    protected function positionedParam(
305
        /*# string */ $rawString,
306
        array $args,
307
        /*# string */ $num
308
    )/*# : string */ {
309
        $values = sizeof($args) > $num ? (array) $args[$num] : [];
310
        return $this->getBuilder()->raw($rawString, $values);
311
    }
312
313
    /**
314
     * Return the builder
315
     *
316
     * @return BuilderInterface
317
     * @access public
318
     */
319
    abstract public function getBuilder()/*# : BuilderInterface */;
320
}
321