🏡 index : ~doyle/koselig.git

author Jordan Doyle <jordan@doyle.wf> 2016-10-16 14:02:22.0 +00:00:00
committer Jordan Doyle <jordan@doyle.wf> 2016-10-16 14:02:22.0 +00:00:00
commit
f706619ea28c763247cbf47f83f92250b1d33c36 [patch]
tree
4152fcedd8bd32887f4622a0922ca0847bb7bd34
parent
b33e69fbbba1a7841d2febc0fffe423d5cbe5a39
download
f706619ea28c763247cbf47f83f92250b1d33c36.tar.gz

Query class, fix routing and usability tweaks



Diff

 src/Facades/Query.php                      |  23 +++++++-
 src/Models/Meta.php                        |   3 +-
 src/Models/Post.php                        | 100 ++++++++++++++++++++++++++++--
 src/Models/User.php                        |  18 ++++-
 src/Models/UserMeta.php                    |   7 +-
 src/Providers/WordpressServiceProvider.php |   5 ++-
 src/Proxy/Query.php                        |  65 ++++++++++++++++++++-
 src/Routing/ArchiveRoute.php               |  12 +----
 src/Routing/AuthorRoute.php                |  81 ++++++++++++++++++++++++-
 src/Routing/PageRoute.php                  |  12 ++--
 src/Routing/Routing.php                    |  39 ++++++++++--
 src/Routing/RoutingServiceProvider.php     |   1 +-
 src/Routing/SingularRoute.php              |  12 +----
 src/Routing/TemplateRoute.php              |  23 ++++---
 src/Support/Wordpress.php                  |  51 +++++++--------
 15 files changed, 378 insertions(+), 74 deletions(-)

diff --git a/src/Facades/Query.php b/src/Facades/Query.php
new file mode 100644
index 0000000..47d6b31
--- /dev/null
+++ b/src/Facades/Query.php
@@ -0,0 +1,23 @@
<?php
namespace Koselig\Facades;

use Illuminate\Support\Facades\Facade;

/**
 * Facade for {@link Koselig\Proxy\Query} proxy. Provides access to the main query.
 *
 * @see \Koselig\Proxy\Query
 * @author Jordan Doyle <jordan@doyle.wf>
 */
class Query extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'query';
    }
}
diff --git a/src/Models/Meta.php b/src/Models/Meta.php
index 8c84c9f..d23728e 100644
--- a/src/Models/Meta.php
+++ b/src/Models/Meta.php
@@ -14,7 +14,8 @@ use Koselig\Support\Wordpress;
 */
class Meta extends Model
{
    public $table = DB_PREFIX . 'postmeta';
    protected $table = DB_PREFIX . 'postmeta';
    public $timestamps = false;

    /**
     * Cache for all meta values.
diff --git a/src/Models/Post.php b/src/Models/Post.php
index 755aa78..6512c32 100644
--- a/src/Models/Post.php
+++ b/src/Models/Post.php
@@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Koselig\Exceptions\UnsatisfiedDependencyException;
use Koselig\Support\Action;
use WP_Post;

/**
 * Table containing all the items within the CMS.
@@ -16,13 +17,11 @@ use Koselig\Support\Action;
 */
class Post extends Model
{
    public $table = DB_PREFIX . 'posts';
    public $primaryKey = 'ID';

    protected $table = DB_PREFIX . 'posts';
    protected $primaryKey = 'ID';
    protected $dates = ['post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt'];
    public $timestamps = false;

    public $dates = ['post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt'];

    /**
     * Get all the posts within a certain post type.
     *
@@ -138,6 +137,75 @@ class Post extends Model
    }

    /**
     * Get the categories of this post.
     *
     * @see get_the_category
     * @return array
     */
    public function category()
    {
        return get_the_category($this->ID);
    }

    /**
     * Get the permalink for this post.
     *
     * @see get_permalink
     * @return false|string
     */
    public function link()
    {
        return get_permalink($this->toWordpressPost());
    }

    /**
     * Get the tags of this post.
     *
     * @see get_the_tags
     * @return array|false|\WP_Error
     */
    public function tags()
    {
        return get_the_tags($this->ID);
    }

    /**
     * Get the thumbnail of this post
     *
     * @see get_the_post_thumbnail
     * @param string $size
     * @param string $attr
     * @return string
     */
    public function thumbnail($size = 'post-thumbnail', $attr = '')
    {
        return get_the_post_thumbnail($this->toWordpressPost(), $size, $attr);
    }

    /**
     * Get the excerpt of this post.
     *
     * @return string
     */
    public function excerpt()
    {
        dd($this);
        return Action::filter('get_the_excerpt', $this->post_excerpt);
    }

    /**
     * Get the all the terms of this post.
     *
     * @see get_the_terms
     * @param $taxonomy
     * @return array|false|\WP_Error
     */
    public function terms($taxonomy)
    {
        return get_the_terms($this->toWordpressPost(), $taxonomy);
    }

    /**
     * Get the author that this post belongs to.
     *
     * @return BelongsTo
@@ -146,4 +214,26 @@ class Post extends Model
    {
        return $this->belongsTo(User::class, 'post_author');
    }

    /**
     * Get the classes that should be applied to this post.
     *
     * @see get_post_class
     * @return string
     */
    public function classes()
    {
        return implode(' ', get_post_class('', $this->toWordpressPost()));
    }

    /**
     * Get the {@link WP_Post} instance for this Post.
     *
     * @deprecated
     * @return WP_Post
     */
    public function toWordpressPost()
    {
        return new WP_Post((object) $this->toArray());
    }
}
diff --git a/src/Models/User.php b/src/Models/User.php
index 98ed007..9974e88 100644
--- a/src/Models/User.php
+++ b/src/Models/User.php
@@ -15,8 +15,10 @@ class User extends Model implements AuthenticatableContract
{
    use Authenticatable;

    public $table = DB_PREFIX . 'users';
    public $primaryKey = 'ID';
    protected $table = DB_PREFIX . 'users';
    protected $primaryKey = 'ID';
    protected $dates = ['user_registered'];
    public $timestamps = false;

    /**
     * Get all the posts that belong to this user.
@@ -25,7 +27,7 @@ class User extends Model implements AuthenticatableContract
     */
    public function posts()
    {
        return $this->hasMany(self::class, 'post_author');
        return $this->hasMany(Post::class, 'post_author');
    }

    /**
@@ -37,4 +39,14 @@ class User extends Model implements AuthenticatableContract
    {
        return $this->user_pass;
    }

    /**
     * Get a link to this user's author page.
     *
     * @return string
     */
    public function link()
    {
        return get_author_posts_url($this->ID, $this->display_name);
    }
}
diff --git a/src/Models/UserMeta.php b/src/Models/UserMeta.php
index db1c581..5450068 100644
--- a/src/Models/UserMeta.php
+++ b/src/Models/UserMeta.php
@@ -12,14 +12,15 @@ use Koselig\Support\Wordpress;
 */
class UserMeta extends Model
{
    public $table = DB_PREFIX . 'usermeta';
    protected $table = DB_PREFIX . 'usermeta';
    public $timestamps = false;

    /**
     * Cache for all meta values.
     *
     * @var array
     */
    public static $cache = [];
    private static $cache = [];

    /**
     * Get metadata for a user.
@@ -37,7 +38,7 @@ class UserMeta extends Model
        }

        if ($user === null) {
            $user = Wordpress::currentUser()->ID;
            $user = auth()->id();
        }

        if (!isset(self::$cache[$user])) {
diff --git a/src/Providers/WordpressServiceProvider.php b/src/Providers/WordpressServiceProvider.php
index 6d726eb..b788c5b 100644
--- a/src/Providers/WordpressServiceProvider.php
+++ b/src/Providers/WordpressServiceProvider.php
@@ -4,6 +4,7 @@ namespace Koselig\Providers;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Koselig\Proxy\Query;
use Koselig\Support\Action;
use Koselig\Support\Wordpress;

@@ -37,6 +38,10 @@ class WordpressServiceProvider extends ServiceProvider

        // Set up the WordPress query.
        wp();

        $this->app->singleton('query', function () {
            return Query::instance($GLOBALS['wp_the_query']);
        });
    }

    /**
diff --git a/src/Proxy/Query.php b/src/Proxy/Query.php
new file mode 100644
index 0000000..fe9c4d6
--- /dev/null
+++ b/src/Proxy/Query.php
@@ -0,0 +1,65 @@
<?php
namespace Koselig\Proxy;

use Illuminate\Support\Str;
use WP_Query;

/**
 * Proxies the {@link \WP_Query} class from Wordpress for a more elegant syntax.
 *
 * @author Jordan Doyle <jordan@doyle.wf>
 */
class Query
{
    /**
     * Current query.
     *
     * @var WP_Query
     */
    private $query;

    public static function instance(WP_Query $query)
    {
        $instance = new static;
        $instance->query = $query;
        return $instance;
    }

    /**
     * Get a property from {@link WP_Query}
     *
     * @param $name
     * @return mixed
     */
    public function __get($name)
    {
        return $this->query->{Str::snake($name)};
    }

    /**
     * Pass a call to this function to {@link WP_Query}
     *
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        $name = Str::snake($name);
        $name = str_replace('has', 'have', $name);

        if (!method_exists($this->query, $name)) {
            // try and find the method that was attempted to be called. Makes for a lot nicer code when reading over
            // it.
            if (method_exists($this->query, 'the_' . $name)) {
                $name = 'the_' . $name;
            } elseif (method_exists($this->query, 'is_' . $name)) {
                $name = 'is_' . $name;
            } elseif (method_exists($this->query, 'get_' . $name)) {
                $name = 'get_' . $name;
            }
        }

        return $this->query->{$name}(...$arguments);
    }
}
diff --git a/src/Routing/ArchiveRoute.php b/src/Routing/ArchiveRoute.php
index dfb0d36..bd3f93f 100644
--- a/src/Routing/ArchiveRoute.php
+++ b/src/Routing/ArchiveRoute.php
@@ -33,17 +33,7 @@ class ArchiveRoute extends Route
        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');
        $this->uri = 'archive/' . (implode('/', $this->postTypes) ?: 'all');
    }

    /**
diff --git a/src/Routing/AuthorRoute.php b/src/Routing/AuthorRoute.php
new file mode 100644
index 0000000..ef5b26d
--- /dev/null
+++ b/src/Routing/AuthorRoute.php
@@ -0,0 +1,81 @@
<?php
namespace Koselig\Routing;

use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Koselig\Facades\Query;
use Koselig\Models\User;
use Koselig\Support\Wordpress;
use ReflectionFunction;

/**
 * Author page route, used when Wordpress reports
 * this page is an author page.
 *
 * @author Jordan Doyle <jordan@doyle.wf>
 */
class AuthorRoute extends Route
{
    /**
     * Users for this author route to hook onto.
     *
     * @var array
     */
    private $users;

    /**
     * Create a new Route instance.
     *
     * @param  array|string $methods
     * @param  array $users
     * @param  \Closure|array $action
     * @return void
     */
    public function __construct($methods, $users, $action)
    {
        parent::__construct($methods, $users, $action);

        $this->users = $this->uri;
        $this->uri = 'author/' . (implode('/', $this->users) ?: 'all');
    }

    /**
     * Run the route action and return the response.
     *
     * @return mixed
     */
    protected function runCallable()
    {
        // bind the current post to the parameters of the function
        $function = new ReflectionFunction($this->action['uses']);
        $params = $function->getParameters();

        foreach ($params as $param) {
            if ($param->getClass()
                && ($param->getClass()->isSubclassOf(User::class) || $param->getClass()->getName() === User::class)) {
                $builder = $param->getClass()->getMethod('query')->invoke(null);
                $post = $builder->find(Query::queriedObject()->ID);

                $this->setParameter($param->getName(), $post);
            }
        }

        return parent::runCallable();
    }

    /**
     * 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 (!empty($this->getAction()['domain']) && !Wordpress::multisite($this->getAction()['domain'])) {
            return false;
        }

        return Wordpress::author($this->users);
    }
}
diff --git a/src/Routing/PageRoute.php b/src/Routing/PageRoute.php
index c5a1d88..a0aa428 100644
--- a/src/Routing/PageRoute.php
+++ b/src/Routing/PageRoute.php
@@ -16,13 +16,17 @@ use ReflectionFunction;
class PageRoute extends Route
{
    /**
     * Format a nice string for php artisan route:list.
     * Create a new Route instance.
     *
     * @return string
     * @param  array|string $methods
     * @param  array $users
     * @param  \Closure|array $action
     * @return void
     */
    public function uri()
    public function __construct($methods, $users, $action)
    {
        return 'page/' . parent::uri();
        parent::__construct($methods, $users, $action);
        $this->uri = 'page/' . $this->uri();
    }

    /**
diff --git a/src/Routing/Routing.php b/src/Routing/Routing.php
index 1ff2d70..2e40806 100644
--- a/src/Routing/Routing.php
+++ b/src/Routing/Routing.php
@@ -10,7 +10,7 @@ class Routing
     * Register a new template route with the router.
     *
     * @param  string $slug slug to match
     * @param  \Closure|array|string|null $action
     * @param  callable|array|string|null $action
     * @return \Illuminate\Routing\Route
     */
    public function template($slug, $action)
@@ -30,7 +30,7 @@ class Routing
     * Register a new page route with the router.
     *
     * @param  string $slug slug to match
     * @param  \Closure|array|string|null $action
     * @param  callable|array|string|null $action
     * @return \Illuminate\Routing\Route
     */
    public function page($slug, $action)
@@ -50,8 +50,8 @@ class Routing
     * Register a new archive route with the router. Optionally supply
     * the post types you'd like to supply with this route.
     *
     * @param \Closure|string|array $postTypes
     * @param  \Closure|array|string|null $action
     * @param callable|string|array $postTypes
     * @param callable|array|string|null $action
     * @return \Illuminate\Routing\Route
     */
    public function archive($postTypes = [], $action = [])
@@ -102,6 +102,37 @@ class Routing
    }

    /**
     * Register a author route with the router. This allows the user to
     * create pages for an author or authors. Optionally supply the authors
     * you'd like to supply using this route.
     *
     * @param callable|array|int $users authors to handle by this route
     * @param callable|array|string|null $action
     * @return mixed
     */
    public function author($users, $action = [])
    {
        if (empty($action)) {
            $action = $users;
            $users = [];
        }

        if (!is_array($users)) {
            $users = [$users];
        }

        $action = $this->formatAction($action);

        $route = (new AuthorRoute($action['method'], $users, $action))
            ->setRouter(app('router'))
            ->setContainer(app(Container::class));

        $route = $this->applyStack($route);

        return Route::getRoutes()->add($route);
    }

    /**
     * Format <pre>$action</pre> in a nice way to pass to the {@link \Illuminate\Routing\RouteCollection}.
     *
     * @param $action
diff --git a/src/Routing/RoutingServiceProvider.php b/src/Routing/RoutingServiceProvider.php
index b3d79e7..356c7e5 100644
--- a/src/Routing/RoutingServiceProvider.php
+++ b/src/Routing/RoutingServiceProvider.php
@@ -28,5 +28,6 @@ class RoutingServiceProvider extends ServiceProvider
        Router::macro('page', [$routing, 'page']);
        Router::macro('archive', [$routing, 'archive']);
        Router::macro('singular', [$routing, 'singular']);
        Router::macro('author', [$routing, 'author']);
    }
}
diff --git a/src/Routing/SingularRoute.php b/src/Routing/SingularRoute.php
index 09904ec..8ba59b4 100644
--- a/src/Routing/SingularRoute.php
+++ b/src/Routing/SingularRoute.php
@@ -35,7 +35,7 @@ class SingularRoute extends Route
        parent::__construct($methods, $types, $action);

        $this->types = $this->uri;
        $this->uri = '';
        $this->uri = 'singular/' . implode('/', $this->types);
    }

    /**
@@ -63,16 +63,6 @@ class SingularRoute extends Route
    }

    /**
     * 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
diff --git a/src/Routing/TemplateRoute.php b/src/Routing/TemplateRoute.php
index 9ec26b3..55ccc3d 100644
--- a/src/Routing/TemplateRoute.php
+++ b/src/Routing/TemplateRoute.php
@@ -1,8 +1,8 @@
<?php
namespace Koselig\Routing;

use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Koselig\Http\Request;
use Koselig\Models\Post;
use Koselig\Support\Wordpress;
use ReflectionFunction;
@@ -16,13 +16,18 @@ use ReflectionFunction;
class TemplateRoute extends Route
{
    /**
     * Format a nice string for php artisan route:list.
     * Create a new Route instance.
     *
     * @return string
     * @param  array|string $methods
     * @param  array $types
     * @param  \Closure|array $action
     * @return void
     */
    public function uri()
    public function __construct($methods, $types, $action)
    {
        return 'template/' . parent::uri();
        parent::__construct($methods, $types, $action);

        $this->uri = 'template/' . parent::uri();
    }

    /**
@@ -52,19 +57,21 @@ class TemplateRoute extends Route
    /**
     * Determine if the route matches given request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  Request $request
     * @param  bool $includingMethod
     * @return bool
     */
    public function matches(Request $request, $includingMethod = true)
    {
        $slug = Wordpress::templateSlug();
        $post = $request->post();

        if (!$slug) {
        if (!$post) {
            // the page we are on either isn't in the CMS or doesn't have a template.
            return false;
        }

        $slug = $post->getMeta('_wp_page_template');

        if (!empty($this->getAction()['domain']) && !Wordpress::multisite($this->getAction()['domain'])) {
            return false;
        }
diff --git a/src/Support/Wordpress.php b/src/Support/Wordpress.php
index dec572a..6f614e6 100644
--- a/src/Support/Wordpress.php
+++ b/src/Support/Wordpress.php
@@ -1,6 +1,9 @@
<?php
namespace Koselig\Support;

use Koselig\Facades\Query;
use Koselig\Models\User;

/**
 * Provides various base Wordpress helper functionality in a nice
 * OO way.
@@ -10,17 +13,6 @@ namespace Koselig\Support;
class Wordpress
{
    /**
     * Get the current Wordpress query.
     *
     * @SuppressWarnings(PHPMD.CamelCaseVariableName)
     * @return \WP_Query
     */
    public static function query()
    {
        return $GLOBALS['wp_query'];
    }

    /**
     * Get the current page id.
     *
     * @return int
@@ -31,17 +23,6 @@ class Wordpress
    }

    /**
     * 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
@@ -49,7 +30,7 @@ class Wordpress
     */
    public static function singular($types = '')
    {
        return is_singular($types);
        return Query::singular($types);
    }

    /**
@@ -60,7 +41,28 @@ class Wordpress
     */
    public static function archive($types = null)
    {
        return $types === null || empty($types) ? is_archive() : is_post_type_archive($types);
        return $types === null || empty($types) ? Query::archive() : Query::postTypeArchive($types);
    }

    /**
     * Check if the current page is an author page.
     *
     * @param int|array|User $users
     * @return bool
     */
    public static function author($users = [])
    {
        if (!is_array($users)) {
            $users = [$users];
        }

        foreach ($users as $key => $user) {
            if ($user instanceof User) {
                $users[$key] = $user->ID;
            }
        }

        return Query::author($users);
    }

    /**
@@ -110,6 +112,7 @@ class Wordpress
     *
     * Use of WP_User is deprecated, however this method will not be removed.
     *
     * @deprecated use <code>Auth::user()</code> instead.
     * @return \WP_User
     */
    public static function currentUser()