src/Model/CustomPostType/QueriableEntityTrait.php
<?php
namespace Strata\Model\CustomPostType;
use Strata\Model\CustomPostType\Query;
use Exception;
/**
* The QueriableEntity trait allows for more object-oriented database queries
* by adding a layer of abstraction with WP_Query.
* @link https://codex.wordpress.org/Class_Reference/WP_Query
*/
trait QueriableEntityTrait
{
/**
* Returns an instantiated QueriableEntity to access the repository.
* @return QueriableEntity
*/
public static function repo()
{
$ref = self::staticFactory();
return $ref->query();
}
/**
* Saves a pointer to the currently active query adapter.
* @var Query
*/
protected $activeQuery = null;
/**
* Return an object inheriting from Query on which requests
* will be ran. Inheriting classes can modify this to suit their needs.
* @return Query
*/
public function getQueryAdapter()
{
return new Query();
}
/**
* Resets (forgets) the active query.
*/
public function resetCurrentQuery()
{
$this->activeQuery = null;
}
/**
* Starts a wrapped wp_query pattern object. Used to chain parameters
* It resets the query.
* @return QueriableEntity;
*/
public function query()
{
$this->resetCurrentQuery();
$this->reloadQueryAdapter();
return $this;
}
/**
* Applies a date query to the querier.
* @link https://codex.wordpress.org/Class_Reference/WP_Query#Date_Parameters
* @param array $dateQuery An array of the date query parameters for WP_Query
* @return QueriableEntity
*/
public function date($dateQuery)
{
$this->reloadQueryAdapter();
$this->activeQuery->date($dateQuery);
return $this;
}
/**
* Defines fields on which to order the current query.
* @param string $orderBy
* @return QueriableEntity
*/
public function orderby($orderBy)
{
$this->reloadQueryAdapter();
$this->activeQuery->orderby($orderBy);
return $this;
}
/**
* Defines the direction on which the orderby() field
* will be sorted.
* @param string $dir
* @return QueriableEntity
*/
public function direction($dir)
{
$this->reloadQueryAdapter();
$this->activeQuery->direction($dir);
return $this;
}
/**
* Shorthand for setting conditions on the post_status
* column.
* @param string $status
* @return QueriableEntity
*/
public function status($status = null)
{
$this->reloadQueryAdapter();
$this->activeQuery->status($status);
return $this;
}
/**
* The default catch all wrapper for WP_Query parameters.
* @param string $field
* @param mixed $value
* @return QueriableEntity
*/
public function where($field, $value)
{
$this->reloadQueryAdapter();
$this->activeQuery->where($field, $value);
return $this;
}
/**
* Allows the branching of different conditions in the same
* Wordpress query.
* @param string $field
* @param mixed $value
* @return QueriableEntity
*/
public function orWhere($field, $value)
{
$this->reloadQueryAdapter();
$this->activeQuery->orWhere($field, $value);
return $this;
}
/**
* Sets the maximum number of results the current query may
* return.
* @param integer $qty
* @return QueriableEntity
*/
public function limit($qty)
{
$this->reloadQueryAdapter();
$this->activeQuery->limit($qty);
return $this;
}
/**
* Sets the starting offset of the current queries result set.
* @param index $index
* @return QueriableEntity
*/
public function offset($index)
{
$this->reloadQueryAdapter();
$this->activeQuery->offset($index);
return $this;
}
/**
* Adds a 'author' condition to the current query.
* @param integer $authorID
* @return QueriableEntity
*/
public function byAuthorID($authorID)
{
return $this->where('author', $authorID);
}
public function byName()
{
return $this
->orderby("post_title")
->direction("ASC");
}
public function published()
{
return $this->status("publish");
}
public function byRecency()
{
return $this
->orderby("creation_date")
->direction("DESC");
}
public function byPlublication()
{
return $this
->orderby("date")
->direction("DESC");
}
public function byMenuOrder()
{
return $this
->orderby("menu_order")
->direction("ASC");
}
/**
* Fetches the number of results the current queries returned.
* This ends the current query.
* @return integer
*/
public function count()
{
$this->throwIfContextInvalid();
$this->reloadQueryAdapter();
$results = $this->activeQuery->fetch();
$this->resetCurrentQuery();
return count($results);
}
/**
* Executes the query and resets it anew.
* @return array posts
*/
public function fetch()
{
$this->throwIfContextInvalid();
$this->reloadQueryAdapter();
$results = $this->activeQuery->fetch();
$this->resetCurrentQuery();
if (!is_array($results) && get_class($results) === "WP_Error") {
throw new Exception(json_encode($results));
}
return $this->wrapInEntities($results);
}
/**
* Executes the query and resets it anew.
* This is useful for returning a list of
* [ID => post_title] elements.
* @return hash of $key => $label values
*/
public function listing($key, $label)
{
$this->throwIfContextInvalid();
$this->reloadQueryAdapter();
$results = $this->activeQuery->listing($key, $label);
$this->resetCurrentQuery();
return $results;
}
/**
* Fetches the first element matching the current query and
* resets it anew.
* @return Strata\Model\CustomPostType\ModelEntity
*/
public function first()
{
$result = $this->limit(1)->fetch();
return array_shift($result);
}
/**
* Returns all the possible entities and ends the query.
* @return array
*/
public function findAll()
{
return $this->query()->fetch();
}
/**
* Finds a model entity by it's ID.
* @param integer $id
* @return Strata\Model\CustomPostType\ModelEntity
*/
public function findById($id)
{
$post = get_post($id);
if (!is_null($post)) {
return self::getEntity($post);
}
}
/**
* Returns the total number of entities of the current type.
* Unlike count() this does not take additional filtering
* and maps to wp_count_posts().
* @return integer
*/
public function countTotal()
{
return wp_count_posts($this->getWordpressKey());
}
/**
* Paginates the current query. Must be called before
* the result set has been generated.
* Maps to paginate_links()
* @param array $config A configuration array that will be sent to paginate_links()
* @return string A pagination HTML block
*/
public function paginate($config = array())
{
$this->reloadQueryAdapter();
return $this->activeQuery->paginate($config);
}
/**
* Wraps the resultset into entities of the current object type.
* @param array $entities
* @return array
*/
protected function wrapInEntities(array $entities)
{
$results = array();
foreach ($entities as $entity) {
$results[] = self::getEntity($entity);
}
return $results;
}
/**
* Reloads the query adapter when it has not been initialized.
* Should none be set, it instantiates it with the correct default values.
* @return Query
*/
private function reloadQueryAdapter()
{
if (is_null($this->activeQuery)) {
$this->activeQuery = $this->getQueryAdapter();
$this->activeQuery->type($this->getWordpressKey());
}
return $this->activeQuery;
}
/**
* Throws an exception when the query is manipulated
* after a resultset has been generated.
* @throws Exception
*/
private function throwIfContextInvalid()
{
if (is_null($this->activeQuery)) {
throw new Exception("No active query to fetch.");
}
}
}