PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.6.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.6.01
2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 1.1.0 All 77 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Database / BaseGrammar.php

BaseGrammar.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.6.01, at vendor/wpfluent/framework/src/WPFluent/Database/BaseGrammar.php

407 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Framework\Database;
4
5 use RuntimeException;
6 use FluentCommunity\Framework\Support\Helper;
7 use FluentCommunity\Framework\Database\Schema;
8 use FluentCommunity\Framework\Support\MacroableTrait;
9 use FluentCommunity\Framework\Database\Query\Expression;
10
11 abstract class BaseGrammar
12 {
13 use MacroableTrait;
14
15 /**
16 * Cache of aliased table names.
17 *
18 * @var array
19 */
20 protected $alias = [];
21
22 /**
23 * The connection used for escaping values.
24 *
25 * @var \FluentCommunity\Framework\Database\ConnectionInterface
26 */
27 protected $connection;
28
29 /**
30 * The base prefix frpm $wpdb.
31 *
32 * @var string
33 */
34 protected $basePrefix = '';
35
36 /**
37 * The grammar table prefix.
38 *
39 * @var string
40 */
41 protected $tablePrefix = '';
42
43 /**
44 * Check if the given table is a built-in table.
45 *
46 * @param string $table
47 * @return boolean
48 */
49 public function isAliasedTable($table)
50 {
51 return in_array("`$table`", $this->alias);
52 }
53
54 /**
55 * Wrap an array of values.
56 *
57 * @param array $values
58 * @return array
59 */
60 public function wrapArray(array $values)
61 {
62 return array_map([$this, 'wrap'], $values);
63 }
64
65 /**
66 * Wrap a value in keyword identifiers.
67 *
68 * @param \FluentCommunity\Framework\Database\Query\Expression|string $value
69 * @return string
70 */
71 public function wrap($value)
72 {
73 if ($this->isExpression($value)) {
74 return $this->getValue($value);
75 }
76
77 // If the value being wrapped has a column alias we will need to separate // out the pieces so we can wrap each of the segments of the
78 // expression on its own, and then join these both
79 // back together using the "as" connector.
80 if (stripos($value, ' as ') !== false) {
81 return $this->wrapAliasedValue($value);
82 }
83
84 // If the given value is a JSON selector we will wrap it differently than a
85 // traditional value. We will need to split this path and wrap each part
86 // wrapped, etc. Otherwise, we will simply wrap the value as a string.
87 if ($this->isJsonSelector($value)) {
88 return $this->wrapJsonSelector($value);
89 }
90
91 return $this->wrapSegments(explode('.', $value));
92 }
93
94 /**
95 * Wrap a table in keyword identifiers.
96 *
97 * @param \FluentCommunity\Framework\Database\Query\Expression|string $table
98 * @return string
99 */
100 public function wrapTable($table)
101 {
102 if ($this->isExpression($table)) {
103 return $this->getValue($table);
104 }
105
106 // If the table being wrapped has an alias we'll need to separate the pieces
107 // so we can prefix the table and then wrap each of the segments on their
108 // own and then join these both back together using the "as" connector.
109 if (stripos($table, ' as ') !== false) {
110 return $this->wrapAliasedTable($table);
111 }
112
113 $tablePrefix = $this->resolveTablePrefix($table);
114
115 // If the table being wrapped has a custom schema name specified, we need to
116 // prefix the last segment as the table name then wrap each segment alone
117 // and eventually join them both back together using the dot connector.
118 if (str_contains($table, '.')) {
119 $table = substr_replace(
120 $table, '.' . $tablePrefix, strrpos($table, '.'), 1
121 );
122
123 return Helper::collect(explode('.', $table))
124 ->map(function($value) {
125 return $this->wrapValue($value);
126 })
127 ->implode('.');
128 }
129
130 if ($this->isAliasedTable($table)) {
131 return $table;
132 }
133
134 return $this->wrapValue($tablePrefix.$table);
135 }
136
137 /**
138 * Resolve the table prefix based on the table name.
139 *
140 * @param string $table
141 * @return string
142 */
143 protected function resolveTablePrefix($table)
144 {
145 if ($this->isAliasedTable($table)) {
146 return '';
147 }
148
149 if (!is_multisite()) {
150 return $this->tablePrefix;
151 }
152
153 $sharedTables = [
154 'users',
155 'usermeta',
156 'site',
157 'sitemeta',
158 'blogs',
159 'blog_versions',
160 'registration_log',
161 'signups',
162 ];
163
164 return in_array(
165 $table, $sharedTables
166 ) ? $this->basePrefix : $this->tablePrefix;
167 }
168
169 /**
170 * Wrap a value that has an alias.
171 *
172 * @param string $value
173 * @return string
174 */
175 protected function wrapAliasedValue($value)
176 {
177 $segments = preg_split('/\s+as\s+/i', $value);
178
179 return $this->wrap(
180 $segments[0]
181 ) . ' as ' . $this->wrapValue($segments[1]);
182 }
183
184 /**
185 * Wrap a table that has an alias.
186 *
187 * @param string $value
188 * @return string
189 */
190 protected function wrapAliasedTable($value)
191 {
192 $segments = preg_split('/\s+as\s+/i', $value);
193
194 $this->alias[] = $alias = $this->wrapValue($segments[1]);
195
196 return $this->wrapTable($segments[0]) . ' as ' . $alias;
197 }
198
199 /**
200 * Wrap the given value segments.
201 *
202 * @param array $segments
203 * @return string
204 */
205 protected function wrapSegments($segments)
206 {
207 return Helper::collect($segments)->map(function (
208 $segment, $key
209 ) use ($segments) {
210 return $key == 0 && count($segments) > 1
211 ? $this->wrapTable($segment)
212 : $this->wrapValue($segment);
213 })->implode('.');
214 }
215
216 /**
217 * Wrap a single string in keyword identifiers.
218 *
219 * @param string $value
220 * @return string
221 */
222 protected function wrapValue($value)
223 {
224 if ($value !== '*') {
225 return '"'.str_replace('"', '""', $value).'"';
226 }
227
228 return $value;
229 }
230
231 /**
232 * Wrap the given JSON selector.
233 *
234 * @param string $value
235 * @return string
236 *
237 * @throws \RuntimeException
238 */
239 protected function wrapJsonSelector($value)
240 {
241 throw new RuntimeException(
242 'This database engine does not support JSON operations.'
243 );
244 }
245
246 /**
247 * Determine if the given string is a JSON selector.
248 *
249 * @param string $value
250 * @return bool
251 */
252 protected function isJsonSelector($value)
253 {
254 return str_contains($value, '->');
255 }
256
257 /**
258 * Convert an array of column names into a delimited string.
259 *
260 * @param array $columns
261 * @return string
262 */
263 public function columnize(array $columns)
264 {
265 return implode(', ', array_map([$this, 'wrap'], $columns));
266 }
267
268 /**
269 * Create query parameter place-holders for an array.
270 *
271 * @param array $values
272 * @return string
273 */
274 public function parameterize(array $values)
275 {
276 return implode(', ', array_map([$this, 'parameter'], $values));
277 }
278
279 /**
280 * Get the appropriate query parameter place-holder for a value.
281 *
282 * @param mixed $value
283 * @return string
284 */
285 public function parameter($value)
286 {
287 return $this->isExpression($value) ? $this->getValue($value) : '?';
288 }
289
290 /**
291 * Quote the given string literal.
292 *
293 * @param string|array $value
294 * @return string
295 */
296 public function quoteString($value)
297 {
298 if (is_array($value)) {
299 return implode(', ', array_map([$this, __FUNCTION__], $value));
300 }
301
302 return "'$value'";
303 }
304
305 /**
306 * Escapes a value for safe SQL embedding.
307 *
308 * @param string|float|int|bool|null $value
309 * @param bool $binary
310 * @return string
311 */
312 public function escape($value, $binary = false)
313 {
314 if (is_null($this->connection)) {
315 throw new RuntimeException(
316 "The database driver's grammar implementation does not support escaping values."
317 );
318 }
319
320 return $this->connection->escape($value, $binary);
321 }
322
323 /**
324 * Determine if the given value is a raw expression.
325 *
326 * @param mixed $value
327 * @return bool
328 */
329 public function isExpression($value)
330 {
331 return $value instanceof Expression;
332 }
333
334 /**
335 * Transforms expressions to their scalar types.
336 *
337 * @param \FluentCommunity\Framework\Database\Query\Expression|string|int|float $expression
338 * @return string|int|float
339 */
340 public function getValue($expression)
341 {
342 if ($this->isExpression($expression)) {
343 return $this->getValue($expression->getValue($this));
344 }
345
346 return $expression;
347 }
348
349 /**
350 * Get the format for database stored dates.
351 *
352 * @return string
353 */
354 public function getDateFormat()
355 {
356 return 'Y-m-d H:i:s';
357 }
358
359 /**
360 * Get the grammar's table prefix.
361 *
362 * @return string
363 */
364 public function getTablePrefix()
365 {
366 return $this->tablePrefix;
367 }
368
369 /**
370 * Set the grammar's table prefix.
371 *
372 * @param object $wpdb WordPress database object
373 * @return $this
374 */
375 public function setTablePrefix($wpdb)
376 {
377 $this->basePrefix = $wpdb->base_prefix;
378
379 $this->tablePrefix = $wpdb->prefix;
380
381 return $this;
382 }
383
384 /**
385 * Set the grammar's database connection.
386 *
387 * @param \FluentCommunity\Framework\Database\ConnectionInterface $connection
388 * @return $this
389 */
390 public function setConnection($connection)
391 {
392 $this->connection = $connection;
393
394 return $this;
395 }
396
397 /**
398 * Track table aliases.
399 *
400 * @param void
401 */
402 public function addAlias($alias)
403 {
404 $this->alias[] = "`$alias`";
405 }
406 }
407