PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.1.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.1.0
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
← All changes | vendor/wpfluent/framework/src/WPFluent/Database/BaseGrammar.php +212 -45 1.212.1.0 View file →
@@ -1,9 +1,11 @@
1 1 <?php
2 2
3 3 namespace FluentBoards\Framework\Database;
4 4
5 +use RuntimeException;
5 6 use FluentBoards\Framework\Support\Helper;
7 +use FluentBoards\Framework\Database\Schema;
6 8 use FluentBoards\Framework\Support\MacroableTrait;
7 9 use FluentBoards\Framework\Database\Query\Expression;
8 10
9 11 abstract class BaseGrammar
@@ -10,8 +12,29 @@
10 12 {
11 13 use MacroableTrait;
12 14
13 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 \FluentBoards\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 + /**
14 37 * The grammar table prefix.
15 38 *
16 39 * @var string
17 40 */
@@ -17,8 +40,19 @@
17 40 */
18 41 protected $tablePrefix = '';
19 42
20 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 + /**
21 55 * Wrap an array of values.
22 56 *
23 57 * @param array $values
24 58 * @return array
@@ -28,8 +62,37 @@
28 62 return array_map([$this, 'wrap'], $values);
29 63 }
30 64
31 65 /**
66 + * Wrap a value in keyword identifiers.
67 + *
68 + * @param \FluentBoards\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 + /**
32 95 * Wrap a table in keyword identifiers.
33 96 *
34 97 * @param \FluentBoards\Framework\Database\Query\Expression|string $table
35 98 * @return string
@@ -35,74 +98,103 @@
35 98 * @return string
36 99 */
37 100 public function wrapTable($table)
38 101 {
39 - if (! $this->isExpression($table)) {
40 - return $this->wrap(
41 - $this->getTableNameWithPrefix($table), true
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
42 121 );
122 +
123 + return Helper::collect(explode('.', $table))
124 + ->map(function($value) {
125 + return $this->wrapValue($value);
126 + })
127 + ->implode('.');
43 128 }
44 129
45 - return $this->getValue($table);
130 + if ($this->isAliasedTable($table)) {
131 + return $table;
132 + }
133 +
134 + return $this->wrapValue($tablePrefix.$table);
46 135 }
47 136
48 137 /**
49 - * Get the grammar's full table name.
138 + * Resolve the table prefix based on the table name.
50 139 *
51 - * Also Handles multisite table names.
52 - *
53 - * @param string $table
54 - * @return string $tableName
140 + * @param string $table
141 + * @return string
55 142 */
56 - public function getTableNameWithPrefix($table)
143 + protected function resolveTablePrefix($table)
57 144 {
58 - global $wpdb;
145 + if ($this->isAliasedTable($table)) {
146 + return '';
147 + }
148 +
149 + if (!is_multisite()) {
150 + return $this->tablePrefix;
151 + }
59 152
60 - return isset($wpdb->{$table}) ? $wpdb->{$table} : $this->tablePrefix.$table;
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;
61 167 }
62 168
63 169 /**
64 - * Wrap a value in keyword identifiers.
170 + * Wrap a value that has an alias.
65 171 *
66 - * @param \FluentBoards\Framework\Database\Query\Expression|string $value
67 - * @param bool $prefixAlias
172 + * @param string $value
68 173 * @return string
69 174 */
70 - public function wrap($value, $prefixAlias = false)
175 + protected function wrapAliasedValue($value)
71 176 {
72 - if ($this->isExpression($value)) {
73 - return $this->getValue($value);
74 - }
177 + $segments = preg_split('/\s+as\s+/i', $value);
75 178
76 - // If the value being wrapped has a column alias we will need to separate out
77 - // the pieces so we can wrap each of the segments of the expression on its
78 - // own, and then join these both back together using the "as" connector.
79 - if (stripos($value, ' as ') !== false) {
80 - return $this->wrapAliasedValue($value, $prefixAlias);
81 - }
82 -
83 - return $this->wrapSegments(explode('.', $value));
179 + return $this->wrap(
180 + $segments[0]
181 + ) . ' as ' . $this->wrapValue($segments[1]);
84 182 }
85 183
86 184 /**
87 - * Wrap a value that has an alias.
185 + * Wrap a table that has an alias.
88 186 *
89 187 * @param string $value
90 - * @param bool $prefixAlias
91 188 * @return string
92 189 */
93 - protected function wrapAliasedValue($value, $prefixAlias = false)
190 + protected function wrapAliasedTable($value)
94 191 {
95 192 $segments = preg_split('/\s+as\s+/i', $value);
96 193
97 - // If we are wrapping a table we need to prefix the alias with the table prefix
98 - // as well in order to generate proper syntax. If this is a column of course
99 - // no prefix is necessary. The condition will be true when from wrapTable.
100 - if ($prefixAlias) {
101 - $segments[1] = $this->tablePrefix.$segments[1];
102 - }
194 + $this->alias[] = $alias = $this->wrapValue($segments[1]);
103 195
104 - return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[1]);
196 + return $this->wrapTable($segments[0]) . ' as ' . $alias;
105 197 }
106 198
107 199 /**
108 200 * Wrap the given value segments.
@@ -111,9 +203,11 @@
111 203 * @return string
112 204 */
113 205 protected function wrapSegments($segments)
114 206 {
115 - return Helper::collect($segments)->map(function ($segment, $key) use ($segments) {
207 + return Helper::collect($segments)->map(function (
208 + $segment, $key
209 + ) use ($segments) {
116 210 return $key == 0 && count($segments) > 1
117 211 ? $this->wrapTable($segment)
118 212 : $this->wrapValue($segment);
119 213 })->implode('.');
@@ -134,8 +228,34 @@
134 228 return $value;
135 229 }
136 230
137 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 + /**
138 258 * Convert an array of column names into a delimited string.
139 259 *
140 260 * @param array $columns
141 261 * @return string
@@ -182,8 +302,26 @@
182 302 return "'$value'";
183 303 }
184 304
185 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 + /**
186 324 * Determine if the given value is a raw expression.
187 325 *
188 326 * @param mixed $value
189 327 * @return bool
@@ -193,16 +331,20 @@
193 331 return $value instanceof Expression;
194 332 }
195 333
196 334 /**
197 - * Get the value of a raw expression.
335 + * Transforms expressions to their scalar types.
198 336 *
199 - * @param \FluentBoards\Framework\Database\Query\Expression $expression
200 - * @return mixed
337 + * @param \FluentBoards\Framework\Database\Query\Expression|string|int|float $expression
338 + * @return string|int|float
201 339 */
202 340 public function getValue($expression)
203 341 {
204 - return $expression->getValue();
342 + if ($this->isExpression($expression)) {
343 + return $this->getValue($expression->getValue($this));
344 + }
345 +
346 + return $expression;
205 347 }
206 348
207 349 /**
208 350 * Get the format for database stored dates.
@@ -226,14 +368,39 @@
226 368
227 369 /**
228 370 * Set the grammar's table prefix.
229 371 *
230 - * @param string $prefix
372 + * @param object $wpdb WordPress database object
231 373 * @return $this
232 374 */
233 - public function setTablePrefix($prefix)
375 + public function setTablePrefix($wpdb)
234 376 {
235 - $this->tablePrefix = $prefix;
377 + $this->basePrefix = $wpdb->base_prefix;
236 378
379 + $this->tablePrefix = $wpdb->prefix;
380 +
237 381 return $this;
382 + }
383 +
384 + /**
385 + * Set the grammar's database connection.
386 + *
387 + * @param \FluentBoards\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`";
238 405 }
239 406 }