🏡 index : ~doyle/koselig.git

author Jordan Doyle <jordan@doyle.wf> 2016-10-02 21:23:59.0 +00:00:00
committer Jordan Doyle <jordan@doyle.wf> 2016-10-02 21:23:59.0 +00:00:00
commit
bf7ebd6d52c21291e55dd3cbf83e07ba6ced254a [patch]
tree
c81a590ba45ec533f8919c10c8ad38d912af92a7
download
bf7ebd6d52c21291e55dd3cbf83e07ba6ced254a.tar.gz

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(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..57872d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
/vendor/
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..4c498df
--- /dev/null
+++ b/composer.json
@@ -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/"
        }
    }
}
diff --git a/config/templates.php b/config/templates.php
new file mode 100644
index 0000000..4b56186
--- /dev/null
+++ b/config/templates.php
@@ -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'

];

diff --git a/config/wordpress.php b/config/wordpress.php
new file mode 100644
index 0000000..6d01ff8
--- /dev/null
+++ b/config/wordpress.php
@@ -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')
];
diff --git a/src/Models/Meta.php b/src/Models/Meta.php
new file mode 100644
index 0000000..056bb60
--- /dev/null
+++ b/src/Models/Meta.php
@@ -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);
    }
}
diff --git a/src/Models/Post.php b/src/Models/Post.php
new file mode 100644
index 0000000..7726a0a
--- /dev/null
+++ b/src/Models/Post.php
@@ -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');
    }
}
diff --git a/src/Models/User.php b/src/Models/User.php
new file mode 100644
index 0000000..1c6941e
--- /dev/null
+++ b/src/Models/User.php
@@ -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');
    }
}
diff --git a/src/Models/UserMeta.php b/src/Models/UserMeta.php
new file mode 100644
index 0000000..bd6f6ec
--- /dev/null
+++ b/src/Models/UserMeta.php
@@ -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);
    }
}
diff --git a/src/Providers/LarapressServiceProvider.php b/src/Providers/LarapressServiceProvider.php
new file mode 100644
index 0000000..7813a41
--- /dev/null
+++ b/src/Providers/LarapressServiceProvider.php
@@ -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);
    }
}
diff --git a/src/Providers/RoutingServiceProvider.php b/src/Providers/RoutingServiceProvider.php
new file mode 100644
index 0000000..eb0e0e5
--- /dev/null
+++ b/src/Providers/RoutingServiceProvider.php
@@ -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;
        });
    }
}
diff --git a/src/Providers/WordpressServiceProvider.php b/src/Providers/WordpressServiceProvider.php
new file mode 100644
index 0000000..8c8ca3a
--- /dev/null
+++ b/src/Providers/WordpressServiceProvider.php
@@ -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'));
        });
    }
}
diff --git a/src/Routing/ArchiveRoute.php b/src/Routing/ArchiveRoute.php
new file mode 100644
index 0000000..dbbaadb
--- /dev/null
+++ b/src/Routing/ArchiveRoute.php
@@ -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);
    }
}
diff --git a/src/Routing/PageRoute.php b/src/Routing/PageRoute.php
new file mode 100644
index 0000000..681dade
--- /dev/null
+++ b/src/Routing/PageRoute.php
@@ -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;
    }
}
diff --git a/src/Routing/SingularRoute.php b/src/Routing/SingularRoute.php
new file mode 100644
index 0000000..a3a2f19
--- /dev/null
+++ b/src/Routing/SingularRoute.php
@@ -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);
    }
}
diff --git a/src/Routing/TemplateRoute.php b/src/Routing/TemplateRoute.php
new file mode 100644
index 0000000..a27de85
--- /dev/null
+++ b/src/Routing/TemplateRoute.php
@@ -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;
    }
}
diff --git a/src/Support/Wordpress.php b/src/Support/Wordpress.php
new file mode 100644
index 0000000..69e45db
--- /dev/null
+++ b/src/Support/Wordpress.php
@@ -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();
    }
}