Initial commit
Diff
.gitignore | 1 +-
composer.json | 19 +++++-
config/templates.php | 17 +++++-
config/wordpress.php | 12 +++-
src/Models/Meta.php | 73 ++++++++++++++++++++-
src/Models/Post.php | 37 ++++++++++-
src/Models/User.php | 26 +++++++-
src/Models/UserMeta.php | 67 ++++++++++++++++++-
src/Providers/LarapressServiceProvider.php | 27 +++++++-
src/Providers/RoutingServiceProvider.php | 110 ++++++++++++++++++++++++++++++-
src/Providers/WordpressServiceProvider.php | 101 ++++++++++++++++++++++++++++-
src/Routing/ArchiveRoute.php | 60 ++++++++++++++++-
src/Routing/PageRoute.php | 44 ++++++++++++-
src/Routing/SingularRoute.php | 65 ++++++++++++++++++-
src/Routing/TemplateRoute.php | 44 ++++++++++++-
src/Support/Wordpress.php | 75 ++++++++++++++++++++-
16 files changed, 778 insertions(+)
@@ -0,0 +1 @@
/vendor/
@@ -0,0 +1,19 @@
{
"name": "w4/larapress",
"description": "Integrate Wordpress into Laravel seamlessly",
"license": "GPL-3.0+",
"authors": [
{
"name": "Jordan Doyle",
"email": "jordan@doyle.wf"
}
],
"require": {
"illuminate/support": "5.3.*"
},
"autoload": {
"psr-4": {
"JordanDoyle\\Larapress\\": "src/"
}
}
}
@@ -0,0 +1,17 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Wordpress Templates
|--------------------------------------------------------------------------
|
| Here you can set all the Wordpress templates that will be used in this
| application. This should be in slug => friendly name format.
*/
'home' => 'Homepage'
];
@@ -0,0 +1,12 @@
<?php
return [
'auth_key' => env('AUTH_KEY'),
'secure_auth_key' => env('SECURE_AUTH_KEY'),
'logged_in_key' => env('LOGGED_IN_KEY'),
'nonce_key' => env('NONCE_KEY'),
'auth_salt' => env('AUTH_SALT'),
'secure_auth_salt' => env('SECURE_AUTH_SALT'),
'logged_in_salt' => env('LOGGED_IN_SALT'),
'nonce_salt' => env('NONCE_SALT')
];
@@ -0,0 +1,73 @@
<?php
namespace JordanDoyle\Larapress\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Table containing all metadata about a post.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class Meta extends Model
{
public $table = DB_PREFIX . 'postmeta';
/**
* Cache for all meta values.
*
* @var array
*/
public static $cache = [];
/**
* Get metadata for a page (or the current page)
*
* <code>Meta::get('my_meta_key');</code>
* or
* <code>Meta::get(7, 'my_meta_key');</code>
*
* @param int|string|null $page page to get meta for (or name of the meta item to get
* if you want to get the current page's meta)
* @param string|null $name
* @return mixed
*/
public static function get($page = null, $name = null)
{
if (!ctype_digit((string) $page) && $name === null) {
$name = $page;
$page = null;
}
if ($page === null) {
$page = Wordpress::id();
}
if (!isset(self::$cache[$page])) {
// get all the meta values for a post, it's more than likely we're going to
// need this again query, so we'll just grab all the results and cache them.
self::$cache[$page] = Meta::where('post_id', $page)->get();
}
if ($name === null) {
return self::$cache[$page]->mapWithKeys(function ($item) {
return [$item->meta_key => $item->meta_value];
})->all();
}
$value = self::$cache[$page]->where('meta_key', $name)->first();
return empty($value) ? null : $value->meta_value;
}
/**
* Get the post that this meta value belongs to.
*
* @return BelongsTo
*/
public function post()
{
return $this->belongsTo(Post::class);
}
}
@@ -0,0 +1,37 @@
<?php
namespace JordanDoyle\Larapress\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Table containing all the items within the CMS.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class Post extends Model
{
public $table = DB_PREFIX . 'posts';
public $primaryKey = 'ID';
/**
* Get all the meta values that belong to this post.
*
* @return HasMany
*/
public function meta()
{
return $this->hasMany(Meta::class);
}
/**
* Get the author that this post belongs to.
*
* @return BelongsTo
*/
public function author()
{
return $this->belongsTo(User::class, 'post_author');
}
}
@@ -0,0 +1,26 @@
<?php
namespace JordanDoyle\Larapress\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Table containing all the users within the CMS.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class User extends Model
{
public $table = DB_PREFIX . 'users';
public $primaryKey = 'ID';
/**
* Get all the posts that belong to this user.
*
* @return HasMany
*/
public function posts()
{
return $this->hasMany(User::class, 'post_author');
}
}
@@ -0,0 +1,67 @@
<?php
namespace JordanDoyle\Larapress\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Table containing the metadata about users in the CMS.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class UserMeta extends Model
{
public $table = DB_PREFIX . 'usermeta';
/**
* Cache for all meta values.
*
* @var array
*/
public static $cache = [];
/**
* Get metadata for a user
*
* @param int|string|null $user user to get meta for (or name of the meta item to get
* if you want to get the current user's meta)
* @param string|null $name
* @return mixed
*/
public static function get($user = null, $name = null)
{
if (!ctype_digit((string) $user) && $name === null) {
$name = $user;
$page = null;
}
if ($user === null) {
$user = Wordpress::currentUser()->ID;
}
if (!isset(self::$cache[$user])) {
// get all the meta values for a post, it's more than likely we're going to
// need this again query, so we'll just grab all the results and cache them.
self::$cache[$user] = UserMeta::where('user_id', $user)->get();
}
if ($name === null) {
return self::$cache[$user]->mapWithKeys(function ($item) {
return [$item->meta_key => $item->meta_value];
})->all();
}
return self::$cache[$user]->where('meta_key', $name)->first()->meta_value;
}
/**
* Get the user that this meta value belongs to.
*
* @return BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
@@ -0,0 +1,27 @@
<?php
namespace JordanDoyle\Larapress\Providers;
use Illuminate\Container\Container;
use Illuminate\Routing\Router;
use Illuminate\Support\ServiceProvider;
use JordanDoyle\Larapress\Support\TemplateRoute;
use Route;
/**
* Registers all the other service providers used by this package.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class LarapressServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function register()
{
$this->app->register(WordpressServiceProvider::class);
$this->app->register(RoutingServiceProvider::class);
}
}
@@ -0,0 +1,110 @@
<?php
namespace JordanDoyle\Larapress\Providers;
use Illuminate\Container\Container;
use Illuminate\Routing\Router;
use Illuminate\Support\ServiceProvider;
use JordanDoyle\Larapress\Routing\ArchiveRoute;
use JordanDoyle\Larapress\Routing\PageRoute;
use JordanDoyle\Larapress\Routing\SingularRoute;
use JordanDoyle\Larapress\Routing\TemplateRoute;
use Route;
/**
* Provides routing methods for Wordpress-related routes.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class RoutingServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function register()
{
// Router methods
Router::macro('template', function ($slug, $action) {
$action = $this->formatAction($action);
$route = (new TemplateRoute($action['method'], $slug, $action))
->setRouter(app('router'))
->setContainer(app(Container::class));
return Route::getRoutes()->add($route);
});
Router::macro('page', function ($slug, $action) {
$action = $this->formatAction($action);
$route = (new PageRoute($action['method'], $slug, $action))
->setRouter(app('router'))
->setContainer(app(Container::class));
return Route::getRoutes()->add($route);
});
Router::macro('archive', function ($postTypes = [], $action = []) {
if (empty($action)) {
$action = $postTypes;
$postTypes = [];
}
if (!is_array($postTypes)) {
$postTypes = [$postTypes];
}
$action = $this->formatAction($action);
$route = (new ArchiveRoute($action['method'], $postTypes, $action))
->setRouter(app('router'))
->setContainer(app(Container::class));
return Route::getRoutes()->add($route);
});
Router::macro('singular', function ($types, $action) {
if (!is_array($types)) {
$types = [$types];
}
$action = $this->formatAction($action);
$route = (new SingularRoute($action['method'], $types, $action))
->setRouter(app('router'))
->setContainer(app(Container::class));
return Route::getRoutes()->add($route);
});
// Router helpers
Router::macro('formatAction', function ($action) {
if (!($action instanceof $action) && (is_string($action) || (isset($action['uses'])
&& is_string($action['uses'])))) {
if (is_string($action)) {
$action = ['uses' => $action];
}
if (!empty($this->groupStack)) {
$group = end($this->groupStack);
$action['uses'] = isset($group['namespace']) && strpos($action['uses'], '\\') !== 0 ?
$group['namespace'] . '\\' . $action['uses'] : $action['uses'];
}
$action['controller'] = $action['uses'];
}
if (!is_array($action)) {
$action = ['uses' => $action];
}
if (!isset($action['method'])) {
$action['method'] = ['GET'];
}
return $action;
});
}
}
@@ -0,0 +1,101 @@
<?php
namespace JordanDoyle\Larapress\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
/**
* Service provider for everything Wordpress, configures
* everything that needs configuring then boots the backend
* of Wordpress.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class WordpressServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function register()
{
// get the path wordpress is installed in
define('WP_PATH',
json_decode(file_get_contents(base_path('composer.json')), true)['extra']['wordpress-install-dir'] . '/');
$this->setConfig();
$this->triggerHooks();
// Set up the WordPress query.
wp();
}
/**
* Set up the configuration values that wp-config.php
* does. Use all the values out of .env instead.
*
* @return void
*/
protected function setConfig()
{
$table_prefix = 'wp_';
$db = DB::getConfig(null);
define('DB_NAME', $db['database']);
define('DB_USER', $db['username']);
define('DB_PASSWORD', $db['password']);
define('DB_HOST', $db['host']);
define('DB_CHARSET', $db['charset']);
define('DB_COLLATE', $db['collation']);
define('DB_PREFIX', $table_prefix);
define('AUTH_KEY', config('app.auth_key'));
define('SECURE_AUTH_KEY', config('app.secure_auth_key'));
define('LOGGED_IN_KEY', config('app.logged_in_key'));
define('NONCE_KEY', config('app.nonce_key'));
define('AUTH_SALT', config('app.auth_salt'));
define('SECURE_AUTH_SALT', config('app.secure_auth_salt'));
define('LOGGED_IN_SALT', config('app.logged_in_salt'));
define('NONCE_SALT', config('app.nonce_salt'));
define('WP_DEBUG', config('app.debug'));
define('SAVEQUERIES', WP_DEBUG);
define('WP_DEBUG_DISPLAY', WP_DEBUG);
define('SCRIPT_DEBUG', WP_DEBUG);
define('DISALLOW_FILE_EDIT', true);
if (!defined('ABSPATH')) {
define('ABSPATH', base_path(WP_PATH));
}
define('WP_SITEURL', url(str_replace('public/', '', WP_PATH)));
define('WP_HOME', url('/'));
define('WP_CONTENT_DIR', base_path('public/content'));
define('WP_CONTENT_URL', url('content'));
if (App::runningInConsole()) {
$_SERVER['SERVER_PROTOCOL'] = 'https';
}
require ABSPATH . 'wp-settings.php';
}
/**
* Wordpress core hooks needed for the main functionality of
* Larapress.
*
* @return void
*/
protected function triggerHooks()
{
add_filter('theme_page_templates', function ($page_templates) {
return array_merge($page_templates, config('templates'));
});
}
}
@@ -0,0 +1,60 @@
<?php
namespace JordanDoyle\Larapress\Routing;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Archive page route, used when Wordpress reports
* this page is an archive page.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class ArchiveRoute extends Route
{
/**
* Post types for this archive route to hook onto
*
* @var array
*/
private $postTypes;
/**
* Create a new Route instance.
*
* @param array|string $methods
* @param array $postTypes
* @param \Closure|array $action
* @return void
*/
public function __construct($methods, $postTypes, $action)
{
parent::__construct($methods, $postTypes, $action);
$this->postTypes = $this->uri;
$this->uri = '';
}
/**
* Format a nice string for php artisan route:list
*
* @return string
*/
public function uri()
{
return 'archive/' . (implode('/', $this->postTypes) ?: 'all');
}
/**
* Determine if the route matches given request.
*
* @param \Illuminate\Http\Request $request
* @param bool $includingMethod
* @return bool
*/
public function matches(Request $request, $includingMethod = true)
{
return Wordpress::archive($this->postTypes);
}
}
@@ -0,0 +1,44 @@
<?php
namespace JordanDoyle\Larapress\Routing;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Single page route, this route is matched when the
* Wordpress page id is equal to the slug of this route.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class PageRoute extends Route
{
/**
* Format a nice string for php artisan route:list
*
* @return string
*/
public function uri()
{
return 'page/' . parent::uri();
}
/**
* Determine if the route matches given request.
*
* @param \Illuminate\Http\Request $request
* @param bool $includingMethod
* @return bool
*/
public function matches(Request $request, $includingMethod = true)
{
$id = Wordpress::id();
if (!$id) {
// we're not on a Wordpress page
return false;
}
return $this->uri === $id;
}
}
@@ -0,0 +1,65 @@
<?php
namespace JordanDoyle\Larapress\Routing;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Singular route, this route is matched when the user
* hits a page that is owned by a certain Wordpress post type.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class SingularRoute extends Route
{
/**
* Entry types this route should hook onto.
*
* @var array
*/
private $types;
/**
* Create a new Route instance.
*
* @param array|string $methods
* @param array $types
* @param \Closure|array $action
* @return void
*/
public function __construct($methods, $types, $action)
{
parent::__construct($methods, $types, $action);
$this->types = $this->uri;
$this->uri = '';
}
/**
* Format a nice string for php artisan route:list
*
* @return string
*/
public function uri()
{
return 'singular/' . implode('/', $this->types);
}
/**
* Determine if the route matches given request.
*
* @param \Illuminate\Http\Request $request
* @param bool $includingMethod
* @return bool
*/
public function matches(Request $request, $includingMethod = true)
{
if (!Wordpress::id()) {
// this isn't a wordpress-controlled page
return false;
}
return Wordpress::singular($this->types);
}
}
@@ -0,0 +1,44 @@
<?php
namespace JordanDoyle\Larapress\Routing;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use JordanDoyle\Larapress\Support\Wordpress;
/**
* Template route, this route is matched then the Wordpress
* template set in the backend equals the slug of this route.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class TemplateRoute extends Route
{
/**
* Format a nice string for php artisan route:list
*
* @return string
*/
public function uri()
{
return 'template/' . parent::uri();
}
/**
* Determine if the route matches given request.
*
* @param \Illuminate\Http\Request $request
* @param bool $includingMethod
* @return bool
*/
public function matches(Request $request, $includingMethod = true)
{
$slug = Wordpress::templateSlug();
if (!$slug) {
// the page we are on either isn't in the CMS or doesn't have a template.
return false;
}
return $this->uri === $slug;
}
}
@@ -0,0 +1,75 @@
<?php
namespace JordanDoyle\Larapress\Support;
/**
* Provides various base Wordpress helper functionality in a nice
* OO way.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class Wordpress
{
/**
* Get the current Wordpress query.
*
* @return \WP_Query
*/
public static function query()
{
global $wp_query;
return $wp_query;
}
/**
* Get the current page id.
*
* @return int
*/
public static function id()
{
return get_the_ID();
}
/**
* Get the slug of the template of a page.
*
* @param string $page
* @return false|string
*/
public static function templateSlug($page = null)
{
return get_page_template_slug($page);
}
/**
* Check if the current page is a singular item (eg. a news post)
*
* @param array|string $types
* @return bool
*/
public static function singular($types = '')
{
return is_singular($types);
}
/**
* Check if the current page is an archive page
*
* @param string|array|null $types check if the archive page is for this type
* @return bool
*/
public static function archive($types = null)
{
return $types === null || empty($types) ? is_archive() : is_post_type_archive($types);
}
/**
* Get the current logged in user.
*
* @return \WP_User
*/
public static function currentUser()
{
return wp_get_current_user();
}
}