Make Wordpress use Laravel's database driver
Diff
src/Providers/WordpressServiceProvider.php | 16 +-
src/Proxy/WordpressDatabase.php | 225 ++++++++++++++++++++++++++++++-
2 files changed, 235 insertions(+), 6 deletions(-)
@@ -3,6 +3,7 @@ namespace Koselig\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Koselig\Proxy\WordpressDatabase;
use Koselig\Support\Action;
use Koselig\Support\Wordpress;
@@ -32,6 +33,15 @@ class WordpressServiceProvider extends ServiceProvider
);
$this->setConfig();
}
public function boot()
{
// Wordpress requires $table_prefix rather than another constant.
$table_prefix = 'wp_';
$this->setDatabaseConstants($table_prefix);
require ABSPATH . 'wp-settings.php';
$this->triggerHooks();
// Set up the WordPress query.
@@ -91,15 +101,11 @@ class WordpressServiceProvider extends ServiceProvider
*/
protected function setConfig()
{
// Wordpress requires $table_prefix rather than another constant.
$table_prefix = 'wp_';
define('WP_DEBUG', config('app.debug'));
define('WP_DEBUG_DISPLAY', WP_DEBUG);
define('WP_DEFAULT_THEME', 'koselig');
define('DISALLOW_FILE_MODS', true);
$this->setDatabaseConstants($table_prefix);
$this->setAuthenticationConstants();
$this->setLocationConstants();
$this->setMultisiteConstants();
@@ -114,8 +120,6 @@ class WordpressServiceProvider extends ServiceProvider
'function' => [$this, 'addThemeSupport'],
'accepted_args' => 0,
];
require ABSPATH . 'wp-settings.php';
}
/**
@@ -0,0 +1,225 @@
<?php
namespace Koselig\Proxy;
use DB;
use Illuminate\Database\QueryException;
use wpdb;
/**
* Replace Wordpress' database calls to Laravel's database abstraction
* to hold a single database connection, and for easier query debugging.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class WordpressDatabase extends wpdb
{
/**
* Override the constructor as the Wordpress install doesn't actually
* need our Database details since it's all handled by laravel.
*/
public function __construct()
{
parent::__construct(null, null, null, null);
}
/**
* Override the Wordpress select method as Laravel has already
* done this for us.
*
* @param string $db
* @param null $dbh
*/
public function select($db, $dbh = null)
{
// We don't need to select a table, Laravel has done it for us.
}
/**
* Set the properties Wordpress expects so it will run queries for us
* through this class.
*
* @param bool $allow_bail
* @return void
*/
public function db_connect($allow_bail = true)
{
$this->is_mysql = true;
$this->has_connected = true;
$this->ready = true;
$this->set_sql_mode();
$this->init_charset();
}
/**
* Retrieves the MySQL server version.
*
* @return null|string Null on failure, version number on success.
*/
public function db_version()
{
return DB::selectOne('SELECT version() as v')->v;
}
/**
* Change the current SQL mode, and ensure its WordPress compatibility.
*
* If no modes are passed, it will ensure the current MySQL server
* modes are compatible.
*
* @since 3.9.0
*
* @param array $modes Optional. A list of SQL modes to set.
*/
public function set_sql_mode($modes = [])
{
if (empty($modes)) {
$modes = explode(',', DB::selectOne('SELECT @@SESSION.sql_mode as sql_mode')->sql_mode);
}
$modes = array_change_key_case($modes, CASE_UPPER);
/**
* Filters the list of incompatible SQL modes to exclude.
*
* @since 3.9.0
*
* @param array $incompatible_modes An array of incompatible modes.
*/
$incompatible_modes = (array) apply_filters('incompatible_sql_modes', $this->incompatible_modes);
foreach ($modes as $i => $mode) {
if (in_array($mode, $incompatible_modes)) {
unset($modes[$i]);
}
}
DB::statement('SET SESSION sql_mode=?', [implode(',', $modes)]);
}
/**
* Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
*
* @see mysqli_real_escape_string()
* @see mysql_real_escape_string()
* @since 2.8.0
* @access private
*
* @param string $string to escape
* @return string escaped
*/
public function _real_escape($string)
{
return substr(DB::getPdo()->quote($string), 1, -1);
}
/**
* Internal function to perform the mysql_query() call.
*
* @since 3.9.0
*
* @access private
* @see wpdb::query()
*
* @param string $query The query to run.
*/
private function _do_query($query)
{
if (defined('SAVEQUERIES') && SAVEQUERIES) {
$this->timer_start();
}
if (preg_match('/^\s*(insert|create|alter|truncate|drop)\s/i', $query)) {
$this->last_result = $this->result = DB::statement($query);
} elseif (preg_match('/^\s*(delete|update|replace)\s/i', $query)) {
$this->last_result = $this->result = DB::affectingStatement($query);
} else {
$this->last_result = $this->result = DB::select($query);
}
$this->num_queries++;
if (defined('SAVEQUERIES') && SAVEQUERIES) {
$this->queries[] = array($query, $this->timer_stop(), $this->get_caller());
}
}
/**
* Perform a MySQL database query, using current database connection.
*
* More information can be found on the codex page.
*
* @since 0.71
*
* @param string $query Database query
* @return int|false Number of rows affected/selected or false on error
*/
public function query($query)
{
if (!$this->ready) {
$this->check_current_query = true;
return false;
}
/**
* Filters the database query.
*
* Some queries are made before the plugins have been loaded,
* and thus cannot be filtered with this method.
*
* @since 2.1.0
*
* @param string $query Database query.
*/
$query = apply_filters('query', $query);
$this->flush();
// Log how the function was called
$this->func_call = "\$db->query(\"$query\")";
// If we're writing to the database, make sure the query will write safely.
if ($this->check_current_query && !$this->check_ascii($query)) {
$stripped_query = $this->strip_invalid_text_from_query($query);
// strip_invalid_text_from_query() can perform queries, so we need
// to flush again, just to make sure everything is clear.
$this->flush();
if ($stripped_query !== $query) {
$this->insert_id = 0;
return false;
}
}
$this->check_current_query = true;
// Keep track of the last query for debug.
$this->last_query = $query;
try {
$this->_do_query($query);
} catch (QueryException $e) {
$this->last_error = $e->getMessage();
// Clear insert_id on a subsequent failed insert.
if ($this->insert_id && preg_match('/^\s*(insert|replace)\s/i', $query)) {
$this->insert_id = 0;
}
$this->print_error($this->last_error);
return false;
}
if (preg_match('/^\s*(create|alter|truncate|drop)\s/i', $query)) {
$return_val = $this->result;
} elseif (preg_match('/^\s*(insert|delete|update|replace)\s/i', $query)) {
$this->rows_affected = $return_val = $this->result;
} else {
// Log number of rows the query returned
// and return number of rows selected
$this->num_rows = count($this->result);
$return_val = $this->result;
}
return $return_val;
}
}