Location: PHPKode > projects > Spiral > ametaireau-spiral-272a2b1/framework/persistence/classes/query/DefaultQuery.php
<?php

namespace spiral\framework\persistence\query;

/**
 * Default implementation of a Query
 * 
 * @author		Frédéric Sureau <hide@address.com>
 * @copyright	2009 Spiral-project.org <http://www.spiral-project.org>
 * @license		GNU General Public License <http://www.gnu.org/licenses/gpl.html>
 */
class DefaultQuery implements Query
{
	/**
	 * Class of objects targeted
	 * 
	 * Must contain the full name of the class including namespaces
	 * 
	 * @var	string
	 */
	private $_class = NULL;
	
	/**
	 * Offset
	 * 
	 * @var	int
	 */
	private $_offset = 0;
	
	/**
	 * Limit
	 * 
	 * @var	int
	 */
	private $_limit = NULL;
	
	/**
	 * Order
	 * 
	 * @var	array
	 */
	private $_order = array();
	
	/**
	 * Criteria
	 * 
	 * @var	Criteria
	 */
	private $_criteria = NULL;
	
	/**
	 * Criteria factory
	 * 
	 * @var	CriteriaFactory
	 */
	private $_criteriaFactory = NULL;
	
	/**
	 * Criterion factory
	 * 
	 * @var	CriterionFactory
	 */
	private $_criterionFactory = NULL;
	
	/**
	 * Define the class of objects that are targeted by the query
	 * 
	 * @param	string	$class	Class of queried objects
	 * 
	 * @return	void
	 */
	public function setClass($class)
	{
		$this->_class = $class;
	}
	
	/**
	 * Return the class of objects that are targeted by the query
	 * 
	 * @return	string	Class of queried objects
	 */
	public function getClass()
	{
		return $this->_class;
	}
	
	/**
	 * Define the range of the results
	 * 
	 * This method is a shortcut to define both the offset and the limit of results in one time.
	 * 
	 * @see		Query::setOffset()
	 * @see		Query::setLimit()
	 * 
	 * @param	int		$offset		First result index
	 * @param	int		$limit		Maximum number of results
	 * 
	 * @return	void
	 */
	public function setRange($offset, $limit)
	{
		$this->setOffset($offset);
		$this->setLimit($limit);
	}
	
	/**
	 * Define the first result index value (offset)
	 * 
	 * Define the first index from which results will be returned.
	 * 
	 * For example, if 10 objects are matching the query, if first result is 7, only the 3 last objects 
	 * will be returned.
	 * 
	 * The default value is 0.
	 * 
	 * @see		Query::setRange()
	 * @see		Query::setLimit()
	 * 
	 * @param	int		$offset		First result index
	 * 
	 * @return	void
	 */
	public function setOffset($offset)
	{
		$this->_offset = $offset;
	}
	
	/**
	 * Return the first result index value (offset)
	 * 
	 * Return the first index from which results will be returned.
	 * 
	 * For example, if 10 objects are matching the query, if first result is 7, only the 3 last objects 
	 * will be returned.
	 * 
	 * The default value is 0.
	 * 
	 * @see		Query::setRange()
	 * @see		Query::setLimit()
	 * 
	 * @return	int		First result index
	 */
	public function getOffset()
	{
		return $this->_offset;
	}
	
	/**
	 * Define the maximum number of results that will be returned.
	 * 
	 * For example, if 10 objects are matching the query, if limit is 7, only the 7 first 
	 * objects will be returned.
	 * 
	 * If the limit value is greater than the number of results, all the results will be returned.
	 * 
	 * If null, all results will be returned.
	 * 
	 * The default value is null.
	 * 
	 * @see		Query::setRange()
	 * @see		Query::setOffset()
	 * 
	 * @param	int		$limit		Maximum number of results
	 * 
	 * @return	void
	 */
	public function setLimit($limit)
	{
		$this->_limit = $limit;
	}
	
	/**
	 * Return the maximum number of results that will be returned.
	 * 
	 * For example, if 10 objects are matching the query, if limit is 7, only the 7 first 
	 * objects will be returned.
	 * 
	 * If the limit value is greater than the number of results, all the results will be returned.
	 * 
	 * If null, all results will be returned.
	 * 
	 * The default value is null.
	 * 
	 * @see		Query::setRange()
	 * @see		Query::setOffset()
	 * 
	 * @param	int		Maximum number of results
	 */
	public function getLimit()
	{
		return $this->_limit;
	}
	
	/**
	 * Set the rules for sorting objects
	 * 
	 * An array of the attributes associated to their ordering value.
	 * 
	 * Keys of the array are attribute names and values are order mode (Query::ASCENDING or Query::DESCENDING)
	 * 
	 * Example :
	 * <code>
	 * $order = array('name'=>Query::ASCENDING, 'age'=>Query::DESCENDING);
	 * 
	 * $query->setOrder($order);
	 * // Will sort objects by name from A to Z, then by age from the older to the younger
	 * </code>
	 * 
	 * @param	array		$order		Array of parameters with ordering mode
	 * 
	 * @return	void
	 */
	public function setOrder(array $order)
	{
		$this->_order = $order;
	}
	
	/**
	 * Return the rules for sorting objects
	 * 
	 * An array of the attributes associated to their ordering value.
	 * 
	 * Keys of the array are attribute names and values are order mode (Query::ASCENDING or Query::DESCENDING)
	 * 
	 * Example :
	 * <code>
	 * $order = array('name'=>Query::ASCENDING, 'age'=>Query::DESCENDING);
	 * 
	 * $query->setOrder($order);
	 * // Will sort objects by name from A to Z, then by age from the older to the younger
	 * </code>
	 * 
	 * @return	array		Array of parameters with ordering mode
	 */
	public function getOrder()
	{
		return $this->_order;
	}
	
	/**
	 * Define criteria that will be respected to filter results
	 * 
	 * Example of use:
	 * <code>
	 *	$criteria = $query->logicalAnd( $query->equals('firstName', 'James'),
	 *									$query->logicalOr( $query->greaterThan('age', 20),
	 *														$query->lowerThan('age', 50) ) );
	 *	
	 *	$query->match( $criteria );
	 * </code>
	 * 
	 * More information on criteria definition should be given in the {@link Criteria} documentation.
	 * 
	 * You could notice that since {@link Criterion} extends {@link Criteria}, a simple {@link Criterion}
	 * can be used instead of {@link Criteria}.
	 * 
	 * @see		Criteria
	 * @see		Criterion
	 * 
	 * @param	Criteria	$criteria		Criteria that the query must match
	 * 
	 * @return	void
	 */
	public function match(Criteria $criteria)
	{
		$this->_criteria = $criteria;
	}
	
	/**
	 * Return criteria that will be respected to filter results
	 * 
	 * Example of use:
	 * <code>
	 *	$criteria = $query->logicalAnd( $query->equals('firstName', 'James'),
	 *									$query->logicalOr( $query->greaterThan('age', 20),
	 *														$query->lowerThan('age', 50) ) );
	 *	
	 *	$query->match( $criteria );
	 * </code>
	 * 
	 * More information on criteria definition should be given in the {@link Criteria} documentation.
	 * 
	 * You could notice that since {@link Criterion} extends {@link Criteria}, a simple {@link Criterion}
	 * can be used instead of {@link Criteria}.
	 * 
	 * @see		Criteria
	 * @see		Criterion
	 * 
	 * @return	Criteria	Criteria that the query must match
	 */
	public function getCriteria()
	{
		return $this->_criteria;
	}
	
	/**
	 * Create a criterion of equality
	 * 
	 * Define that an attribute must be equal to a certain value.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->equals('name', 'James Brown') );
	 * // Will find all artists whose name are James Brown
	 * </code>
	 * 
	 * Attributes can be chained like this :
	 * <code>
	 * $query->setClass('Album');
	 * $query->match( $query->equals('artist->name', 'James Brown') );
	 * // Will find all albums from the artist named James Brown
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	An equality criterion
	 */
	public function equals($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::EQUAL, $attribute, $value);
	}
	
	/**
	 * Create a "like" criterion
	 * 
	 * Define that an attribute must be like a certain value.
	 * You can use the character % to replace whatever string.
	 * The character ? is used to replace any single character.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->equals('name', 'James %') );
	 * // Will find all artists whose name starts with James
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	A "like" criterion
	 */
	public function like($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::LIKE, $attribute, $value);
	}
	
	/**
	 * Create a "lower than" criterion
	 * 
	 * Define that an attribute must be strictly lower than a certain value.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->lowerThan('age', 50) );
	 * // Will find all artists that are strictly younger than 50
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	A "lower than" criterion
	 */
	public function lowerThan($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::LOWER_THAN, $attribute, $value);
	}
	
	/**
	 * Create a "lower than or equal" criterion
	 * 
	 * Define that an attribute must be lower than or equals a certain value.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->lowerThanOrEqual('age', 50) );
	 * // Will find all artists aged of 50 or younger
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	A "lower than or equal" criterion
	 */
	public function lowerThanOrEqual($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::LOWER_THAN_OR_EQUAL, $attribute, $value);
	}
	
	/**
	 * Create a "greater than" criterion
	 * 
	 * Define that an attribute must be strictly greater than a certain value.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->greaterThan('age', 50) );
	 * // Will find all the artists strictly older than 50
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	A "greater than" criterion
	 */
	public function greaterThan($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::GREATER_THAN, $attribute, $value);
	}
	
	/**
	 * Create a "greater than or equal" criterion
	 * 
	 * Define that an attribute must be greater than or equals a certain value.
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->greaterThanOrEqual('age', 50) );
	 * // Will find all the artists aged of 50 or older
	 * </code>
	 * 
	 * @param	string	$attribute		Attribute you want to match the value
	 * @param	mixed	$value			Value
	 * 
	 * @return	Criterion	A "greater than or equal" criterion
	 */
	public function greaterThanOrEqual($attribute, $value)
	{
		$this->_criterionFactory->createCriterion(Criterion::GREATER_THAN_OR_EQUAL, $attribute, $value);
	}
	
	/**
	 * Group criteria with OR logic
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->logicalOr( $query->greaterThan('age', 50),
	 * 										$query->lowerThan('age', 20) ) );
	 * // Will find all the artists older than 50 or younger than 20
	 * </code>
	 * 
	 * @see		Criteria
	 * @see		Criterion
	 * 
	 * @param	Criteria	...		Criteria instances to group in an OR logic
	 * 
	 * @return	Criteria	Criteria grouping other criteria with an OR logic
	 */
	public function logicalOr()
	{
		$this->_criteriaFactory->createCriteria(Criteria::LOGICAL_OR, func_get_args());
	}
	
	/**
	 * Group criteria with AND logic
	 * 
	 * Example :
	 * <code>
	 * $query->setClass('Artist');
	 * $query->match( $query->logicalAnd( $query->greaterThan('age', 20),
	 * 										$query->lowerThan('age', 50) ) );
	 * // Will find all the artists whose age is between 20 and 50
	 * </code>
	 * 
	 * @see		Criteria
	 * @see		Criterion
	 * 
	 * @param	Criteria	...		Criteria instances to group in an AND logic
	 * 
	 * @return	Criteria	Criteria grouping other criteria with an AND logic
	 */
	public function logicalAnd()
	{
		$this->_criteriaFactory->createCriteria(Criteria::LOGICAL_AND, func_get_args());
	}
	
	/**
	 * Define the criteria factory to use to create criteria
	 * 
	 * @param	CriteriaFactory		$criteriaFactory		Criteria factory
	 * 
	 * @return	void
	 */
	public function setCriteriaFactory(CriteriaFactory $criteriaFactory)
	{
		$this->_criteriaFactory = $criteriaFactory;
	}
	
	/**
	 * Define the criterion factory to use to create a criterion
	 * 
	 * @param	CriterionFactory		$criterionFactory		Criterion factory
	 * 
	 * @return	void
	 */
	public function setCriterionFactory(CriterionFactory $criterionFactory)
	{
		$this->_criterionFactory = $criterionFactory;
	}
}
Return current item: Spiral