Skip to content

Instantly share code, notes, and snippets.

@carlalexander
Created September 28, 2016 12:41
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save carlalexander/66bfb197dd55be218083a351e6e4f080 to your computer and use it in GitHub Desktop.
Save carlalexander/66bfb197dd55be218083a351e6e4f080 to your computer and use it in GitHub Desktop.
WordPress query builder class
<?php
/**
* Builds a WP_Query object using a fluent interface.
*
* @author Carl Alexander <contact@carlalexander.ca>
*/
class WP_Query_Builder
{
/**
* The query arguments collected by the query builder.
*
* @var array
*/
private $query_arguments;
/**
* Constructor.
*
* @param array $query_arguments
*/
public function __construct(array $query_arguments = array())
{
$this->query_arguments = array_merge(array(
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
), $query_arguments);
}
/**
* Generates a group of query arrays using the given query arrays. The query
* result must match all the given query arrays.
*
* @param array ...$query_arrays
*
* @return array
*/
public function and_where()
{
$query_arrays = func_get_args();
$query_arrays['relation'] = 'AND';
return $query_arrays;
}
/**
* Generates a taxonomy array for a category.
*
* @param array|string $categories
* @param string $field
* @param string $operator
* @param bool $include_children
*
* @return array
*/
public function category($categories, $field = 'term_id', $operator = 'IN', $include_children = true)
{
return $this->taxonomy('category', $categories, $field, $operator, $include_children);
}
/**
* Specify the post types that the query will retrieve.
*
* Can be a comma separated string or an array. Overwrites previous
* specification criteria if called multiple times.
*
* @param string|array $from
*
* @return self
*/
public function from($from)
{
if (is_string($from)) {
$from = array_map('trim', explode(',', $from));
} elseif (!is_array($from)) {
return $this;
}
$this->query_arguments['post_type'] = $from;
return $this;
}
/**
* Query WordPress using the current specifications of the builder.
*
* @return WP_Post[]
*/
public function get_results()
{
var_dump($this->query_arguments);
$query = new WP_Query($this->query_arguments);
return $query->posts;
}
/**
* Generates a taxonomy array where posts have one of the given categories.
*
* @param array|string $categories
* @param string $field
* @param bool $include_children
*
* @return array
*/
public function in_category($categories, $field = 'term_id', $include_children = true)
{
return $this->in_taxonomy('category', $categories, $field, $include_children);
}
/**
* Generates a taxonomy array where posts have one of the given
* taxonomy terms.
*
* @param string $taxonomy
* @param array|string $terms
* @param string $field
* @param bool $include_children
*
* @return array
*/
public function in_taxonomy($taxonomy, $terms, $field = 'term_id', $include_children = true)
{
return $this->taxonomy($taxonomy, $terms, $field, 'IN', $include_children);
}
/**
* Specify the maximum number of results that the query will retrieve.
*
* Overwrites previous specification criteria if called multiple times.
*
* @param int $limit
*
* @return self
*/
public function limit($limit)
{
if (!is_numeric($limit)) {
return $this;
}
$this->query_arguments['posts_per_page'] = (int) $limit;
return $this;
}
/**
* Generates a taxonomy array where posts don't have one of the given categories.
*
* @param array|string $categories
* @param string $field
* @param bool $include_children
*
* @return array
*/
public function not_in_category($categories, $field = 'term_id', $include_children = true)
{
return $this->not_in_taxonomy('category', $categories, $field, $include_children);
}
/**
* Generates a taxonomy array where posts don't have one of the given
* taxonomy terms.
*
* @param string $taxonomy
* @param array|string $terms
* @param string $field
* @param bool $include_children
*
* @return array
*/
public function not_in_taxonomy($taxonomy, $terms, $field = 'term_id', $include_children = true)
{
return $this->taxonomy($taxonomy, $terms, $field, 'NOT IN', $include_children);
}
/**
* Generates a group of query arrays using the given query arrays. The query
* result must match one of the given query arrays.
*
* @param array ...$query_arrays
*
* @return array
*/
public function or_where()
{
$taxonomy = func_get_args();
$taxonomy['relation'] = 'OR';
return $taxonomy;
}
/**
* Specify the order of the query results.
*
* Overwrites previous specification criteria if called multiple times.
*
* @param string|array $sort
* @param string $order
*
* @return self
*/
public function order_by($sort, $order = 'DESC')
{
if (empty($sort) || (!is_array($sort) && !is_string($sort))) {
return $this;
} elseif (!is_string($order) || !in_array(strtoupper($order), array('ASC', 'DESC'))) {
$order = 'DESC';
}
$this->query_arguments['orderby'] = $sort;
$this->query_arguments['order'] = $order;
return $this;
}
/**
* Specify the columns that the query will retrieve.
*
* Overwrites previous specification criteria if called multiple times.
*
* @param string $select
*
* @return self
*/
public function select($select)
{
if (empty($select) || !is_string($select)) {
return $this;
}
$this->query_arguments['fields'] = $select;
return $this;
}
/**
* Generates a taxonomy array for a tag.
*
* @param array|string $tags
* @param string $field
* @param string $operator
* @param bool $include_children
*
* @return array
*/
public function tag($tags, $field = 'term_id', $operator = 'IN', $include_children = true)
{
return $this->taxonomy('tag', $tags, $field, $operator, $include_children);
}
/**
* Generates a taxonomy array.
*
* @param string $taxonomy
* @param array|string $terms
* @param string $field
* @param string $operator
* @param bool $include_children
*
* @return array
*/
public function taxonomy($taxonomy, $terms, $field = 'term_id', $operator = 'IN', $include_children = true)
{
if (!is_array($terms)) {
$terms = array($terms);
}
return array(
'taxonomy' => $taxonomy,
'field' => $field,
'terms' => $terms,
'operator' => $operator,
'include_children' => $include_children,
);
}
/**
* Specify the taxonomy of the posts that the query will retrieve.
*
* @param array ...$taxonomies
*
* @return self
*/
public function where_taxonomy()
{
$this->query_arguments['tax_query'] = array_reduce(func_get_args(), array($this, 'merge_query_argument'));
return $this;
}
/**
* Merges the given query array argument into the given query.
*
* @param mixed $query
* @param array $query_argument
*
* @return array
*/
private function merge_query_argument($query, array $query_argument)
{
if (!is_array($query)) {
$query = array();
}
if (!isset($query_argument['relation'])) {
$query_argument = array($query_argument);
$query_argument['relation'] = 'AND';
}
$query['relation'] = $query_argument['relation'];
unset($query_argument['relation']);
foreach ($query_argument as $query_array) {
$query[] = $query_array;
}
return $query;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment