Multisite & laravel -> wordpress authentication integration
Diff
config/wordpress.php | 7 +-
src/Guards/WordpressGuard.php | 205 ++++++++++++++++++++++++++++++-
src/Models/User.php | 16 +-
src/Providers/WordpressServiceProvider.php | 38 ++++++-
src/Routing/Route.php | 40 ++++++-
src/Routing/Routing.php | 1 +-
src/Support/Wordpress.php | 4 +-
7 files changed, 309 insertions(+), 2 deletions(-)
@@ -9,4 +9,11 @@ return [
'secure_auth_salt' => env('SECURE_AUTH_SALT'),
'logged_in_salt' => env('LOGGED_IN_SALT'),
'nonce_salt' => env('NONCE_SALT'),
'wp_allow_multisite' => env('WP_ALLOW_MULTISITE'),
'multisite' => env('MULTISITE'),
'subdomain_install' => env('SUBDOMAIN_INSTALL'),
'domain_current_site' => env('DOMAIN_CURRENT_SITE'),
'path_current_site' => env('PATH_CURRENT_SITE'),
'site_id_current_site' => env('SITE_ID_CURRENT_SITE'),
'blog_id_current_site' => env('BLOG_ID_CURRENT_SITE'),
];
@@ -0,0 +1,205 @@
<?php
namespace Koselig\Guards;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Support\Facades\Request;
use Koselig\Models\User;
use Koselig\Support\Action;
use WP_Error;
/**
* Wordpress user guard, provides a bridge between Laravel's authentication
* and Wordpress.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class WordpressGuard implements StatefulGuard
{
use GuardHelpers;
/**
* Get the last user we attempted to login as.
*
* @var User
*/
private $lastAttempted = null;
/**
* Determine if the current user is authenticated.
*
* @return bool
*/
public function check()
{
return is_user_logged_in();
}
/**
* Get the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (!is_null($this->user)) {
return $this->user;
}
return $this->user = ($this->check() ? User::find(get_current_user_id()) : null);
}
/**
* Validate a user's credentials.
*
* @param array $credentials
* @return bool
*/
public function validate(array $credentials = [])
{
$user = wp_authenticate($credentials['username'], $credentials['password']);
$this->lastAttempted = User::find($user->ID);
return !($user instanceof WP_Error);
}
/**
* Attempt to authenticate a user using the given credentials.
*
* @param array $credentials
* @param bool $remember
* @param bool $login
* @return bool
*/
public function attempt(array $credentials = [], $remember = false, $login = true)
{
$validate = $this->validate($credentials);
if (!$login) {
return $validate;
}
$user = $this->lastAttempted;
// check if we should use a secure cookie
wp_set_auth_cookie($user->ID, $credentials['remember'], Request::secure());
Action::trigger('wp_login', $user->user_login, $user);
$this->setUser($user);
return true;
}
/**
* Log a user into the application without sessions or cookies.
*
* @param array $credentials
* @return bool
*/
public function once(array $credentials = [])
{
if ($this->validate($credentials)) {
$this->setUser($this->lastAttempted);
return true;
}
return false;
}
/**
* Log a user into the application.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param bool $remember
* @return void
*/
public function login(Authenticatable $user, $remember = false)
{
wp_set_auth_cookie($user->ID, $remember);
Action::trigger('wp_login', $user->user_login, get_userdata($user->ID));
wp_set_current_user($user->ID);
$this->user = $user;
}
/**
* Log the given user ID into the application.
*
* @param mixed $id
* @param bool $remember
* @return \Illuminate\Contracts\Auth\Authenticatable|bool
*/
public function loginUsingId($id, $remember = false)
{
$user = User::find($id);
if (!$user) {
return false;
}
wp_set_auth_cookie($user->ID, $remember);
Action::trigger('wp_login', $user->user_login, get_userdata($user->ID));
wp_set_current_user($user->ID);
return $this->user = $user;
}
/**
* Log the given user ID into the application without sessions or cookies.
*
* @param mixed $id
* @return bool
*/
public function onceUsingId($id)
{
$user = User::find($id);
if (!$user) {
return false;
}
wp_set_current_user($id);
return $this->user = $user;
}
/**
* Determine if the user was authenticated via "remember me" cookie.
*
* @return bool
*/
public function viaRemember()
{
return Request::hasCookie(Request::secure() ? SECURE_AUTH_COOKIE : AUTH_COOKIE);
}
/**
* Log the user out of the application.
*
* @return void
*/
public function logout()
{
wp_logout();
$this->user = null;
}
/**
* Set the current user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @return $this
*/
public function setUser(Authenticatable $user)
{
wp_set_current_user($user->ID);
$this->user = $user;
return $this;
}
}
@@ -1,6 +1,8 @@
<?php
namespace Koselig\Models;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -9,8 +11,10 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class User extends Model
class User extends Model implements AuthenticatableContract
{
use Authenticatable;
public $table = DB_PREFIX . 'users';
public $primaryKey = 'ID';
@@ -23,4 +27,14 @@ class User extends Model
{
return $this->hasMany(self::class, 'post_author');
}
/**
* Get the password for the user.
*
* @return string
*/
public function getAuthPassword()
{
return $this->user_pass;
}
}
@@ -2,8 +2,10 @@
namespace Koselig\Providers;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Koselig\Guards\WordpressGuard;
use Koselig\Support\Action;
/**
@@ -39,6 +41,18 @@ class WordpressServiceProvider extends ServiceProvider
}
/**
* Register the Wordpress authentication services.
*
* @return void
*/
public function boot()
{
Auth::extend('wordpress', function ($app, $name, array $config) {
return new WordpressGuard(Auth::createUserProvider($config['provider']));
});
}
/**
* Set up the configuration values that wp-config.php
* does. Use all the values out of .env instead.
*
@@ -57,6 +71,7 @@ class WordpressServiceProvider extends ServiceProvider
$this->setDatabaseConstants($table_prefix);
$this->setAuthenticationConstants();
$this->setLocationConstants();
$this->setMultisiteConstants();
if ($this->app->runningInConsole()) {
// allow wordpress to run, even when running from console (ie. artisan compiling)
@@ -118,6 +133,29 @@ class WordpressServiceProvider extends ServiceProvider
}
/**
* Set up constants that will allow the user to use a multisite install of Wordpress.
*/
private function setMultisiteConstants()
{
$multisite = $this->app->make('config')->get('wordpress.wp_allow_multisite');
if ($multisite) {
define('WP_ALLOW_MULTISITE', $multisite);
$enabled = $this->app->make('config')->get('wordpress.multisite');
if ($enabled) {
define('MULTISITE', $enabled);
define('SUBDOMAIN_INSTALL', $this->app->make('config')->get('wordpress.subdomain_install'));
define('DOMAIN_CURRENT_SITE', $this->app->make('config')->get('wordpress.domain_current_site'));
define('PATH_CURRENT_SITE', $this->app->make('config')->get('wordpress.path_current_site'));
define('SITE_ID_CURRENT_SITE', $this->app->make('config')->get('wordpress.site_id_current_site'));
define('BLOG_ID_CURRENT_SITE', $this->app->make('config')->get('wordpress.blog_id_current_site'));
}
}
}
/**
* Wordpress core hooks needed for the main functionality of
* Koselig.
*
@@ -0,0 +1,40 @@
<?php
namespace Koselig\Routing;
use Illuminate\Http\Request;
use Illuminate\Routing\Route as LaravelRoute;
use Illuminate\Support\Facades\Input;
use Symfony\Component\Routing\Route as SymfonyRoute;
/**
* Extend the base Laravel routing functionality to add multisite support
* to Route::get, Route::post, etc methods.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class Route extends LaravelRoute
{
/**
* Determine if the route matches given request.
*
* @param \Illuminate\Http\Request $request
* @param bool $includingMethod
* @return bool
*/
public function matches(Request $request, $includingMethod = true)
{
$this->compileRoute();
foreach ($this->getValidators() as $validator) {
if (!$includingMethod && $validator instanceof MethodValidator) {
continue;
}
if (!$validator->matches($this, $request)) {
return false;
}
}
return true;
}
}
@@ -3,6 +3,7 @@ namespace Koselig\Routing;
use Illuminate\Container\Container;
use Illuminate\Support\Facades\Route;
use Koselig\Routing\Route as KoseligRoute;
class Routing
{
@@ -94,7 +94,9 @@ class Wordpress
}
/**
* Get the current logged in user.
* Get the current logged in user. Generally, you shouldn't be using this
* function and should instead be using Auth::user() from Laravel to get
* the current logged in Wordpress user.
*
* @return \WP_User
*/