Completed
Push — master ( 38d909...e2a527 )
by Hong
05:34
created

ClauseTrait::getBuilder()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
c 0
b 0
f 0
nc 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 '(' . trim($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
        } elseif (is_null($value)) {
177
            return 'NULL';
178
        } else {
179
            return $this->getBuilder()->getParameter()->getPlaceholder($value);
180
        }
181
    }
182
183
    /**
184
     * Process value array
185
     *
186
     * @param  array $value
187
     * @param  array $settings
188
     * @return string
189
     * @access protected
190
     */
191
    protected function processValueArray(
192
        array $value,
193
        array $settings,
194
        /*# bool */ $between = false
195
    )/*# : string */ {
196
        if ($between) {
197
            $v1 = $this->processValue($value[0], $settings);
198
            $v2 = $this->processValue($value[1], $settings);
199
            return $v1 . ' AND ' . $v2;
200
        } else {
201
            $result = [];
202
            foreach ($value as $val) {
203
                $result[] = $this->processValue($val, $settings);
204
            }
205
            return '(' . join(', ', $result) . ')';
206
        }
207
    }
208
209
    /**
210
     * Join a clause with prefix and its parts
211
     *
212
     * @param  string $prefix
213
     * @param  string $seperator
214
     * @param  array $clause
215
     * @param  array $settings
216
     * @return string
217
     * @access protected
218
     */
219
    protected function joinClause(
220
        /*# : string */ $prefix,
221
        /*# : string */ $seperator,
222
        array $clause,
223
        array $settings
224
    )/*# : string */ {
225
        if (empty($clause)) {
226
            return '';
227
        } else {
228
            $join = $settings['seperator'] . $settings['indent'];
229
            $pref = empty($prefix) ? '' : ($prefix . $join);
230
            return $settings['seperator'] . $pref . join($seperator . $join, $clause);
231
        }
232
    }
233
234
    /**
235
     * Build a generic clause
236
     *
237
     * @param  string $clauseName
238
     * @param  string $clausePrefix
239
     * @param  array $settings
240
     * @param  array $clauseParts
241
     * @return string
242
     * @access protected
243
     */
244
    protected function buildClause(
245
        /*# string */ $clauseName,
246
        /*# string */ $clausePrefix,
247
        array $settings,
248
        array $clauseParts = []
249
    )/*# string */ {
250
        $clause = &$this->getClause($clauseName);
251
        foreach ($clause as $alias => $field) {
252
            $part =
253
                $this->quoteItem($field[0], $settings, $field[1]) .
254
                $this->quoteAlias($alias, $settings) .
255
                (isset($field[2]) ? (' ' . $field[2]) : '');
256
            $clauseParts[] = $part;
257
        }
258
        return $this->joinClause($clausePrefix, ',', $clauseParts, $settings);
259
    }
260
261
    /**
262
     * Reset settings to print flat
263
     *
264
     * @param  array $settings
265
     * @return array
266
     * @access protected
267
     */
268
    protected function flatSettings(array $settings)/*# : array */
269
    {
270
        return array_replace(
271
            $settings,
272
            ['seperator' => ' ', 'indent' => '']
273
        );
274
    }
275
276
    /**
277
     * Return the builder
278
     *
279
     * @return BuilderInterface
280
     * @access public
281
     */
282
    abstract public function getBuilder()/*# : BuilderInterface */;
283
}
284