Completed
Push — master ( 9c8538...c6f12f )
by Hong
03:20
created

ClauseTrait::processValueScalar()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 5
nop 1
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->processArrayValue($value, $settings, $between);
176
        } else {
177
            return $this->processScalarValue($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 processArrayValue(
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 processScalarValue($value)/*# : string */
215
    {
216
        if (ClauseInterface::NO_VALUE == $value) {
217
            return '?';
218
        } elseif (is_null($value) || is_bool($value)) {
219
            return var_export($value, true);
220
        } else {
221
            return $this->getBuilder()->getParameter()->getPlaceholder($value);
222
        }
223
    }
224
225
    /**
226
     * Join a clause with prefix and its parts
227
     *
228
     * @param  string $prefix
229
     * @param  string $seperator
230
     * @param  array $clause
231
     * @param  array $settings
232
     * @return string
233
     * @access protected
234
     */
235
    protected function joinClause(
236
        /*# : string */ $prefix,
237
        /*# : string */ $seperator,
238
        array $clause,
239
        array $settings
240
    )/*# : string */ {
241
        if (empty($clause)) {
242
            return '';
243
        } else {
244
            $join = $settings['seperator'] . $settings['indent'];
245
            $pref = empty($prefix) ? '' : ($prefix . $join);
246
            return $settings['seperator'] . $pref . join($seperator . $join, $clause);
247
        }
248
    }
249
250
    /**
251
     * Build a generic clause
252
     *
253
     * @param  string $clauseName
254
     * @param  string $clausePrefix
255
     * @param  array $settings
256
     * @param  array $clauseParts
257
     * @return string
258
     * @access protected
259
     */
260
    protected function buildClause(
261
        /*# string */ $clauseName,
262
        /*# string */ $clausePrefix,
263
        array $settings,
264
        array $clauseParts = []
265
    )/*# string */ {
266
        $clause = &$this->getClause($clauseName);
267
        foreach ($clause as $alias => $field) {
268
            $part =
269
                $this->quoteItem($field[0], $settings, $field[1]) .
270
                $this->quoteAlias($alias, $settings) .
271
                (isset($field[2]) ? (' ' . $field[2]) : '');
272
            $clauseParts[] = $part;
273
        }
274
        return $this->joinClause($clausePrefix, ',', $clauseParts, $settings);
275
    }
276
277
    /**
278
     * Reset settings to print flat
279
     *
280
     * @param  array $settings
281
     * @return array
282
     * @access protected
283
     */
284
    protected function flatSettings(array $settings)/*# : array */
285
    {
286
        return array_replace(
287
            $settings,
288
            ['seperator' => ' ', 'indent' => '']
289
        );
290
    }
291
292
    /**
293
     * Dealing with positioned parameters
294
     *
295
     * e.g. havingRaw('id > ?', [10]) turns into  havingRaw('id > 10')
296
     *
297
     * @param  string $rawString
298
     * @param  array $args
299
     * @param  int $num
300
     * @access protected
301
     */
302
    protected function positionedParam(
303
        /*# string */ $rawString,
304
        array $args,
305
        /*# string */ $num
306
    )/*# : string */ {
307
        $values = sizeof($args) > $num ? (array) $args[$num] : [];
308
        return $this->getBuilder()->raw($rawString, $values);
309
    }
310
311
    /**
312
     * Return the builder
313
     *
314
     * @return BuilderInterface
315
     * @access public
316
     */
317
    abstract public function getBuilder()/*# : BuilderInterface */;
318
}
319