PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.11.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.11.0
2.11.0 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 All 78 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Database / Query / WPDBConnection.php

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

993 lines 25.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * WPDB Connection
5 */
6
7 namespace FluentCommunity\Framework\Database\Query;
8
9 use Closure;
10 use Exception;
11 use DateTimeInterface;
12 use FluentCommunity\Framework\Foundation\App;
13 use FluentCommunity\Framework\Database\Schema;
14 use FluentCommunity\Framework\Database\QueryException;
15 use FluentCommunity\Framework\Database\ConnectionInterface;
16 use FluentCommunity\Framework\Database\MultipleColumnsSelectedException;
17 use FluentCommunity\Framework\Database\Events\QueryExecuted;
18 use FluentCommunity\Framework\Database\Query\Expression;
19 use FluentCommunity\Framework\Database\Query\Processors\Processor;
20 use FluentCommunity\Framework\Database\Query\Processors\MySqlProcessor;
21 use FluentCommunity\Framework\Database\Query\Processors\SQLiteProcessor;
22 use FluentCommunity\Framework\Database\Query\Builder as QueryBuilder;
23 use FluentCommunity\Framework\Database\Query\Grammars\Grammar;
24 use FluentCommunity\Framework\Database\Query\Grammars\MySqlGrammar;
25 use FluentCommunity\Framework\Database\Query\Grammars\SQLiteGrammar;
26 use FluentCommunity\Framework\Database\Concerns\ManagesTransactions;
27 use FluentCommunity\Framework\Database\DetectsLostConnections;
28
29 use FluentCommunity\Framework\Database\Events\TransactionBeginning;
30 use FluentCommunity\Framework\Database\Events\TransactionCommitted;
31 use FluentCommunity\Framework\Database\Events\TransactionCommitting;
32 use FluentCommunity\Framework\Database\Events\TransactionRolledBack;
33
34 class WPDBConnection implements ConnectionInterface
35 {
36 use DetectsLostConnections, ManagesTransactions;
37
38 /**
39 * $wpdb Global $wpdb instance
40 * @var Object
41 */
42 protected $wpdb;
43
44 /**
45 * The name of the connected database.
46 *
47 * @var string
48 */
49 protected $database;
50
51 /**
52 * The table prefix for the connection.
53 *
54 * @var string
55 */
56 protected $tablePrefix = '';
57
58 /**
59 * The database connection configuration options.
60 *
61 * @var array
62 */
63 protected $config = [];
64
65 /**
66 * The query grammar implementation.
67 *
68 * @var \FluentCommunity\Framework\Database\Query\Grammars\Grammar
69 */
70 protected $queryGrammar;
71
72 /**
73 * The query post processor implementation.
74 *
75 * @var \FluentCommunity\Framework\Database\Query\Processors\Processor
76 */
77 protected $postProcessor;
78
79 /**
80 * The number of active transactions.
81 *
82 * @var int
83 */
84 protected $transactions = 0;
85
86 /**
87 * The transaction manager instance.
88 *
89 * @var \FluentCommunity\Framework\Database\DatabaseTransactionsManager|null
90 */
91 protected $transactionsManager;
92
93 /**
94 * All of the callbacks that should be invoked before a transaction is started.
95 *
96 * @var \Closure[]
97 */
98 protected $beforeStartingTransaction = [];
99
100 /**
101 * The event dispatcher.
102 *
103 * @var \FluentCommunity\Framework\Events\Dispatcher
104 */
105 protected $event = null;
106
107 /**
108 * Create a new database connection instance.
109 *
110 * @param \wpdb $wpdb The WordPress database instance.
111 * @return void
112 */
113 public function __construct($wpdb)
114 {
115 $this->setupWpdbInstance($wpdb);
116
117 $this->useDefaultQueryGrammar();
118
119 $this->useDefaultPostProcessor();
120
121 $this->event = App::make('events');
122 }
123
124 /**
125 * Populate $wpdb instance & turn off db errors
126 *
127 * @param $wpdb Global $wpdb instance
128 * @return Null
129 */
130 protected function setupWpdbInstance($wpdb)
131 {
132 $this->wpdb = $wpdb;
133
134 $this->wpdb->show_errors(
135 $this->shouldShowErrors()
136 );
137
138 $this->registerSqliteFunctions();
139 }
140
141 /**
142 * Register a PHP-backed SOUNDEX() function on the SQLite connection so
143 * phonetic ("sounds like") queries work, mirroring MySQL's native
144 * equivalent.
145 *
146 * SQLite doesn't ship the function; PHP provides it natively, so we bind
147 * it as a UDF. Using PHP's soundex() here matches the term that
148 * SQLiteGrammar encodes with the same soundex() on the binding side.
149 *
150 * No-ops on MySQL and silently skips if the underlying PDO is unreachable,
151 * so a missing SQLite layer never breaks booting.
152 *
153 * @return void
154 */
155 protected function registerSqliteFunctions()
156 {
157 if (! $this->isSqlite()) {
158 return;
159 }
160
161 if (! ($pdo = $this->resolveSqlitePdo())) {
162 return;
163 }
164
165 try {
166 $pdo->sqliteCreateFunction('soundex', 'soundex', 1);
167 } catch (\Throwable $e) {
168 // Leave the function unregistered rather than break booting;
169 // whereSoundsLike() will only surface a SQL error if it is
170 // actually used on this connection.
171 }
172 }
173
174 /**
175 * Resolve the real PDO handle behind the WordPress SQLite layer.
176 *
177 * Supports the official "SQLite Database Integration" plugin
178 * (WP_SQLite_Translator::get_pdo()), a dbh that is itself a PDO
179 * (WP-SQLite-DB's PDOEngine), and the shared $GLOBALS['@pdo'] cache.
180 *
181 * @return \PDO|null
182 */
183 protected function resolveSqlitePdo()
184 {
185 $dbh = $this->wpdb->dbh ?? null;
186
187 if ($dbh && method_exists($dbh, 'get_pdo')) {
188 $pdo = $dbh->get_pdo();
189 } elseif ($dbh instanceof \PDO) {
190 $pdo = $dbh;
191 } elseif (isset($GLOBALS['@pdo'])) {
192 $pdo = $GLOBALS['@pdo'];
193 } else {
194 $pdo = null;
195 }
196
197 return $pdo instanceof \PDO ? $pdo : null;
198 }
199
200 /**
201 * Determine if database errors should be shown.
202 *
203 * @return bool
204 */
205 protected function shouldShowErrors()
206 {
207 return strpos(App::env(), 'prod') === false;
208 }
209
210 /**
211 * Set the query grammar to the default implementation.
212 *
213 * @return void
214 */
215 public function useDefaultQueryGrammar()
216 {
217 $this->queryGrammar = $this->getDefaultQueryGrammar();
218 }
219
220 /**
221 * Get the default query grammar instance.
222 *
223 * @return \FluentCommunity\Framework\Database\Query\Grammars\Grammar
224 */
225 protected function getDefaultQueryGrammar()
226 {
227 return $this->isSqlite() ? new SQLiteGrammar : new MySqlGrammar;
228 }
229
230 /**
231 * Set the query post processor to the default implementation.
232 *
233 * @return void
234 */
235 public function useDefaultPostProcessor()
236 {
237 $this->postProcessor = $this->getDefaultPostProcessor();
238 }
239
240 /**
241 * Get the default post processor instance.
242 *
243 * @return \FluentCommunity\Framework\Database\Query\Processors\Processor
244 */
245 protected function getDefaultPostProcessor()
246 {
247 return $this->isSqlite() ? new SQLiteProcessor : new MySqlProcessor;
248 }
249
250 /**
251 * Begin a fluent query against a database table.
252 *
253 * @param \Closure|\FluentCommunity\Framework\Database\Query\Builder|string $table
254 * @param string|null $as
255 * @return \FluentCommunity\Framework\Database\Query\Builder
256 */
257 public function table($table, $as = null)
258 {
259 return $this->query()->from($table, $as);
260 }
261
262 /**
263 * Get a new query builder instance.
264 *
265 * @return \FluentCommunity\Framework\Database\Query\Builder
266 */
267 public function query()
268 {
269 return new QueryBuilder(
270 $this, $this->getQueryGrammar(), $this->getPostProcessor()
271 );
272 }
273
274 /**
275 * Run a select statement and return a single result.
276 *
277 * @param string $query
278 * @param array $bindings
279 * @return mixed
280 */
281 public function selectOne($query, $bindings = [])
282 {
283 return $this->run($query, $bindings, function ($query, $bindings) {
284 $query = $this->bindParams($query, $bindings);
285
286 $result = $this->wpdb->get_row($query);
287
288 if ($result === false || $this->wpdb->last_error) {
289 throw new QueryException(
290 $query, $bindings, new Exception($this->wpdb->last_error)
291 );
292 }
293
294 return $result;
295 });
296 }
297
298 /**
299 * Run a select statement and return the first column of the first row.
300 *
301 * @param string $query
302 * @param array $bindings
303 * @return mixed
304 *
305 * @throws \FluentCommunity\Framework\Database\MultipleColumnsSelectedException
306 */
307 public function scalar($query, $bindings = [])
308 {
309 $record = $this->selectOne($query, $bindings);
310
311 if (is_null($record)) {
312 return null;
313 }
314
315 $record = (array)$record;
316
317 if (count($record) > 1) {
318 throw new MultipleColumnsSelectedException(
319 'The query returned more than one column.'
320 );
321 }
322
323 return reset($record);
324 }
325
326 /**
327 * Run a select statement against the database.
328 *
329 * @param string $query
330 * @param array $bindings
331 * @return array
332 */
333 public function select($query, $bindings = [])
334 {
335 return $this->run($query, $bindings, function ($query, $bindings) {
336 $query = $this->bindParams($query, $bindings);
337
338 $result = $this->wpdb->get_results($query);
339
340 if ($result === false || $this->wpdb->last_error) {
341 throw new QueryException(
342 $query, $bindings, new Exception($this->wpdb->last_error)
343 );
344 }
345
346 return $result;
347 });
348 }
349
350 /**
351 * Bind the parameters into SQL query
352 *
353 * @param $query
354 * @param $bindings
355 * @return string
356 */
357 protected function bindParams(string $query, array $bindings)
358 {
359 $query = str_replace('"', '`', $query);
360
361 $bindings = $this->prepareBindings($bindings);
362
363 if (empty($bindings)) {
364 return $query;
365 }
366
367 $query = str_replace(['%', '?'], ['%%', '%s'], $query);
368
369 if ($this->wpdb->dbh instanceof \mysqli) {
370 // wpdb->prepare() casts null to '' for %s, which on TIMESTAMP
371 // columns becomes 0000-00-00 00:00:00. Splice literal NULL into
372 // the SQL for null bindings before prepare() ever sees them.
373 [$query, $bindings] = $this->spliceNullBindings($query, $bindings, '%s');
374
375 if (empty($bindings)) {
376 return $query;
377 }
378
379 return $this->wpdb->prepare($query, ...$bindings);
380 }
381
382 $bindings = array_map(function ($value) {
383 if ($value === null) return 'NULL';
384 if (is_bool($value)) return $value ? '1' : '0';
385 if (is_string($value)) return "'" . esc_sql($value) . "'";
386 return (string) $value;
387 }, $bindings);
388
389 return vsprintf($query, $bindings);
390 }
391
392 /**
393 * Replace placeholder occurrences whose binding is null with the
394 * literal SQL keyword NULL, returning the rewritten query and the
395 * remaining (non-null) bindings re-indexed.
396 *
397 * @param string $query
398 * @param array $bindings
399 * @param string $placeholder '%s' for wpdb->prepare path, '?' for mysqli native prepare
400 * @return array{0:string,1:array}
401 *
402 * @phpstan-ignore-next-line
403 */
404 protected function spliceNullBindings(string $query, array $bindings, string $placeholder): array
405 {
406 $bindings = array_values($bindings);
407
408 if (empty($bindings) || strpos($query, $placeholder) === false) {
409 return [$query, $bindings];
410 }
411
412 $parts = explode($placeholder, $query);
413 $last = count($parts) - 1;
414 $rebuilt = '';
415 $kept = [];
416
417 foreach ($parts as $idx => $part) {
418 $rebuilt .= $part;
419
420 if ($idx === $last) {
421 continue;
422 }
423
424 if (array_key_exists($idx, $bindings) && $bindings[$idx] === null) {
425 $rebuilt .= 'NULL';
426 } else {
427 $rebuilt .= $placeholder;
428 if (array_key_exists($idx, $bindings)) {
429 $kept[] = $bindings[$idx];
430 }
431 }
432 }
433
434 return [$rebuilt, $kept];
435 }
436
437 /**
438 * Run a select statement against the database and returns a generator.
439 *
440 * @param string $query
441 * @param array $bindings
442 * @return \Generator
443 * @throws \FluentAccount\Framework\Database\QueryException
444 */
445 public function cursor($query, $bindings = [])
446 {
447 // If not mysqli (e.g., SQLite), fallback to standard select
448 if (!$this->wpdb->dbh instanceof \mysqli) {
449 foreach ($this->select($query, $bindings) as $row) {
450 yield $row;
451 }
452 return;
453 }
454
455 $preparedQuery = str_replace('"', '`', $query);
456
457 $preparedQuery = str_replace('%', '%%', $preparedQuery);
458
459 $bindings = $this->prepareBindings($bindings);
460
461 // mysqli's bind_param can't bind null with type 's' (becomes '').
462 // Replace null bindings with literal NULL in the SQL itself.
463 [$preparedQuery, $bindings] = $this->spliceNullBindings($preparedQuery, $bindings, '?');
464
465 $this->wpdb->flush();
466 $this->wpdb->insert_id = 0;
467 $this->wpdb->check_current_query = true;
468
469 if (!$this->wpdb->check_connection()) {
470 throw new QueryException(
471 $query, $bindings, new Exception(
472 $this->wpdb->last_error ?: 'Error reconnecting to database.'
473 )
474 );
475 }
476
477 if (defined('SAVEQUERIES') && SAVEQUERIES) {
478 $this->wpdb->timer_start();
479 }
480
481 $statement = $this->wpdb->dbh->prepare($preparedQuery);
482
483 if ($statement === false) {
484 throw new QueryException(
485 $query, $bindings, new Exception(
486 'Failed to prepare statement: ' . $this->wpdb->dbh->error
487 )
488 );
489 }
490
491 if (!empty($bindings)) {
492 $types = '';
493 foreach ($bindings as $binding) {
494 if (is_int($binding)) {
495 $types .= 'i';
496 } elseif (is_double($binding)) {
497 $types .= 'd';
498 } else {
499 $types .= 's';
500 }
501 }
502
503 $statement->bind_param($types, ...$bindings);
504 }
505
506 if ($statement->execute()) {
507 $result = $statement->get_result();
508
509 if ($result) {
510 while ($row = $result->fetch_assoc()) {
511 yield (object) $row;
512 }
513 $result->free();
514 } else {
515 if ($statement->errno) {
516 throw new QueryException(
517 $query, $bindings, new Exception($statement->error)
518 );
519 }
520 }
521 $statement->close();
522 return;
523 }
524
525 // Error handling if statement execution fails
526 if ($statement->error || $statement->errno) {
527 $err = $statement->error
528 ? $statement->error
529 : 'Mysqli Error No: ' . $statement->errno;
530
531 $this->wpdb->last_error = $err;
532
533 throw new QueryException(
534 $query, $bindings, new Exception($err)
535 );
536 }
537 }
538
539 /**
540 * Raw cursor query for MySQLi (non-prepared).
541 *
542 * @param string $query
543 * @param array $bindings
544 * @return \Generator
545 * @throws \FluentAccount\Framework\Database\QueryException
546 */
547 public function rawCursor($query, $bindings = [])
548 {
549 if (!empty($bindings)) {
550 $query = str_replace(['%', '?'], ['%%', '%s'], $query);
551 $query = $this->wpdb->prepare($query, ...$bindings);
552 }
553
554 if (!$this->wpdb->dbh instanceof \mysqli) {
555 foreach ($this->select($query) as $row) { yield $row; }
556 return;
557 }
558
559 $stmt = $this->wpdb->dbh->query($query, MYSQLI_USE_RESULT);
560
561 if ($stmt instanceof \mysqli_result) {
562 try {
563 while ($row = $stmt->fetch_assoc()) {
564 yield (object) $row;
565 }
566 } finally {
567 $stmt->free();
568 }
569 } elseif ($this->wpdb->dbh->error) {
570 throw new QueryException(
571 $query, $bindings, new Exception($this->wpdb->dbh->error)
572 );
573 }
574 }
575
576 /**
577 * Run an insert statement against the database.
578 *
579 * @param string $query
580 * @param array $bindings
581 * @return bool
582 */
583 public function insert($query, $bindings = [])
584 {
585 return $this->statement($query, $bindings);
586 }
587
588 /**
589 * Run an update statement against the database.
590 *
591 * @param string $query
592 * @param array $bindings
593 * @return int
594 */
595 public function update($query, $bindings = [])
596 {
597 return $this->affectingStatement($query, $bindings);
598 }
599
600 /**
601 * Run a delete statement against the database.
602 *
603 * @param string $query
604 * @param array $bindings
605 * @return int
606 */
607 public function delete($query, $bindings = [])
608 {
609 return $this->affectingStatement($query, $bindings);
610 }
611
612 /**
613 * Execute an SQL statement and return the boolean result.
614 *
615 * @param string $query
616 * @param array $bindings
617 * @return bool
618 */
619 public function statement($query, $bindings = [])
620 {
621 return $this->run($query, $bindings, function ($query, $bindings) {
622 $query = $this->bindParams($query, $bindings, true);
623
624 $result = $this->unprepared($query);
625
626 if ($result === false || $this->wpdb->last_error) {
627 throw new QueryException(
628 $query, $bindings, new Exception($this->wpdb->last_error)
629 );
630 }
631
632 return $result;
633 });
634 }
635
636 /**
637 * Run an SQL statement and get the number of rows affected.
638 *
639 * @param string $query
640 * @param array $bindings
641 * @return int
642 */
643 public function affectingStatement($query, $bindings = [])
644 {
645 return $this->run($query, $bindings, function ($query, $bindings) {
646 $query = $this->bindParams($query, $bindings, true);
647
648 $result = $this->wpdb->query($query);
649
650 if ($result === false || $this->wpdb->last_error) {
651 throw new QueryException(
652 $query, $bindings, new Exception($this->wpdb->last_error)
653 );
654 }
655
656 return intval($result);
657 });
658 }
659
660 /**
661 * Run a raw, unprepared query against the PDO connection.
662 *
663 * @param string $query
664 * @return bool
665 */
666 public function unprepared($query)
667 {
668 return $this->wpdb->query($query);
669 }
670
671 /**
672 * Execute the given callback in "dry run" mode.
673 *
674 * @param \Closure $callback
675 * @return array
676 */
677 public function pretend(Closure $callback)
678 {
679 // ...
680 }
681
682 /**
683 * Prepare the query bindings for execution.
684 *
685 * @param array $bindings
686 * @return array
687 */
688 public function prepareBindings(array $bindings)
689 {
690 $grammar = $this->getQueryGrammar();
691
692 foreach ($bindings as $key => $value) {
693 // We need to transform all instances of DateTimeInterface into
694 // the actual date string. Each query grammar maintains its
695 // own date string format so we'll just ask the grammar
696 // for the format to get from the date.
697 if ($value instanceof DateTimeInterface) {
698 $bindings[$key] = $value->format($grammar->getDateFormat());
699 } elseif (is_bool($value)) {
700 $bindings[$key] = (int)$value;
701 }
702 }
703
704 return $bindings;
705 }
706
707 /**
708 * Run a SQL statement and log its execution context.
709 *
710 * @param string $query
711 * @param array $bindings
712 * @param \Closure $callback
713 * @return mixed
714 */
715 public function run($query, $bindings, $callback)
716 {
717 $start = microtime(true);
718
719 try {
720 return $callback($query, $bindings);
721 } finally {
722 $time = $this->getElapsedTime($start);
723 $this->event->dispatch(
724 new QueryExecuted($query, $bindings, $time, $this)
725 );
726 }
727 }
728
729 /**
730 * Get a new raw query expression.
731 *
732 * @param mixed $value
733 * @return \FluentCommunity\Framework\Database\Query\Expression
734 */
735 public function raw($value)
736 {
737 return new Expression($value);
738 }
739
740 /**
741 * Get the query grammar used by the connection.
742 *
743 * @return \FluentCommunity\Framework\Database\Query\Grammars\Grammar
744 */
745 public function getQueryGrammar()
746 {
747 $this->queryGrammar->setTablePrefix($this->wpdb);
748
749 return $this->queryGrammar;
750 }
751
752 /**
753 * Set the query grammar used by the connection.
754 *
755 * @param \FluentCommunity\Framework\Database\Query\Grammars\Grammar $grammar
756 * @return $this
757 */
758 public function setQueryGrammar(Grammar $grammar)
759 {
760 $this->queryGrammar = $grammar;
761
762 return $this;
763 }
764
765 /**
766 * Get the query post processor used by the connection.
767 *
768 * @return \FluentCommunity\Framework\Database\Query\Processors\Processor
769 */
770 public function getPostProcessor()
771 {
772 return $this->postProcessor;
773 }
774
775 /**
776 * Set the query post processor used by the connection.
777 *
778 * @param \FluentCommunity\Framework\Database\Query\Processors\Processor $processor
779 * @return $this
780 */
781 public function setPostProcessor(Processor $processor)
782 {
783 $this->postProcessor = $processor;
784
785 return $this;
786 }
787
788 /**
789 * Return the last insert id
790 *
791 * @param string $args
792 *
793 * @return int
794 */
795 public function lastInsertId($args)
796 {
797 return $this->wpdb->insert_id;
798 }
799
800 /**
801 * Return self as PDO, the Processor instance uses it.
802 *
803 * @return \FluentCommunity\Framework\Database\Query\WPDBConnection
804 */
805 public function getPdo()
806 {
807 return $this;
808 }
809
810 /**
811 * Returns the $wpdb object.
812 *
813 * @return Object $wpdb
814 */
815 public function getWPDB()
816 {
817 return $this->wpdb;
818 }
819
820 /**
821 * Get the database connection name.
822 *
823 * @return string|null
824 */
825 public function getName()
826 {
827 return $this->isSqlite() ? 'sqlite' : 'mysql';
828 }
829
830 /**
831 * Get the name of the connected database.
832 *
833 * @return string
834 */
835 public function getDatabaseName()
836 {
837 if ($this->isSqlite()) {
838 return 'sqlite';
839 }
840
841 return $this->wpdb->dbname;
842 }
843
844 /**
845 * Get the server version for the connection.
846 *
847 * @return string
848 *
849 * @phpstan-ignore-next-line
850 */
851 public function getServerVersion(): string
852 {
853 return $this->getWPDB()->db_version();
854 }
855
856 /**
857 * Get the column listing for a given table.
858 *
859 * @param string $table
860 * @return array
861 */
862 public function getColumnListing($table)
863 {
864 return Schema::getColumns($table);
865 }
866
867 /**
868 * Alias for getColumnListing.
869 *
870 * @param string $t
871 * @return array
872 */
873 public function getColumns($t)
874 {
875 return $this->getColumnListing($t);
876 }
877
878 /**
879 * Determine if the connected database is a sqlite database.
880 *
881 * @return bool
882 */
883 public function isSqlite()
884 {
885 return Schema::isSqlite();
886 }
887
888 /**
889 * Determine if the connected database is a mariadb database.
890 *
891 * @return bool
892 */
893 public function isMaria()
894 {
895 return Schema::isMaria();
896 }
897
898 /**
899 * Register a hook to be run just before a database transaction is started.
900 *
901 * @param \Closure $callback
902 * @return $this
903 */
904 public function beforeStartingTransaction(Closure $callback)
905 {
906 $this->beforeStartingTransaction[] = $callback;
907
908 return $this;
909 }
910
911 /**
912 * Register a database query listener with the connection.
913 *
914 * @param \Closure $callback
915 * @return void
916 */
917 public function listen(Closure $callback)
918 {
919 $this->event->listen(QueryExecuted::class, $callback);
920 }
921
922 /**
923 * Fire an event for this connection.
924 *
925 * @param string $event
926 * @return array|null
927 */
928 protected function fireConnectionEvent($event)
929 {
930 if (!$this->event) {
931 return;
932 }
933
934 switch ($event) {
935 case 'beganTransaction':
936 $payload = new TransactionBeginning($this);
937 break;
938 case 'committed':
939 $payload = new TransactionCommitted($this);
940 break;
941 case 'committing':
942 $payload = new TransactionCommitting($this);
943 break;
944 case 'rollingBack':
945 $payload = new TransactionRolledBack($this);
946 break;
947 default:
948 $payload = null;
949 break;
950 }
951
952 if ($payload !== null) {
953 return $this->event->dispatch($payload);
954 }
955 }
956
957 /**
958 * Get the elapsed time since a given starting point.
959 *
960 * @param int $start
961 * @return float
962 */
963 protected function getElapsedTime($start)
964 {
965 return round((microtime(true) - $start) * 1000, 2);
966 }
967
968 /**
969 * Get the table prefix for the connection.
970 *
971 * @return [type] [description]
972 */
973 public function getTablePrefix()
974 {
975 if (!$this->tablePrefix) {
976 $this->tablePrefix = $this->queryGrammar->getTablePrefix();
977 }
978
979 return $this->tablePrefix;
980 }
981
982 /**
983 * Get the table name with the table prefix.
984 *
985 * @param string $table
986 * @return string
987 */
988 public function getTableName($table)
989 {
990 return $this->getTablePrefix() . $table;
991 }
992 }
993