File: //var/www/delta/wp-content/plugins/sitepress-multilingual-cms/classes/jobs/query/CompositeQuery.php
<?php
namespace WPML\TM\Jobs\Query;
use \InvalidArgumentException;
use \WPML_TM_Jobs_Search_Params;
use \RuntimeException;
class CompositeQuery implements Query {
const METHOD_UNION = 'union';
const METHOD_COUNT = 'count';
/**
* Job queries
*
* @var Query[]
*/
private $queries;
/**
* Limit query helper
*
* @var LimitQueryHelper
*/
private $limit_query_helper;
/**
* Order query helper
*
* @var OrderQueryHelper
*/
private $order_query_helper;
/**
* @param Query[] $queries Job queries.
* @param LimitQueryHelper $limit_helper Limit helper.
* @param OrderQueryHelper $order_helper Order helper.
*
* @throws InvalidArgumentException In case of error.
*/
public function __construct(
array $queries,
LimitQueryHelper $limit_helper,
OrderQueryHelper $order_helper
) {
$queries = array_filter( $queries, array( $this, 'is_query_valid' ) );
if ( empty( $queries ) ) {
throw new InvalidArgumentException( 'Collection of sub-queries is empty or contains only invalid elements' );
}
$this->queries = $queries;
$this->limit_query_helper = $limit_helper;
$this->order_query_helper = $order_helper;
}
/**
* Get data query
*
* @param WPML_TM_Jobs_Search_Params $params Job search params.
*
* @throws InvalidArgumentException In case of error.
* @return string
*/
public function get_data_query( WPML_TM_Jobs_Search_Params $params ) {
if ( ! $params->get_job_types() ) {
// We are merging subqueries here, that's why LIMIT must be applied to final query.
$params_without_pagination_and_sorting = clone $params;
$params_without_pagination_and_sorting->set_limit( 0 )->set_offset( 0 );
$params_without_pagination_and_sorting->set_sorting( array() );
$query = $this->get_sql( $params_without_pagination_and_sorting, self::METHOD_UNION );
$order = $this->order_query_helper->get_order( $params );
if ( $order ) {
$query .= ' ' . $order;
}
$limit = $this->limit_query_helper->get_limit( $params );
if ( $limit ) {
$query .= ' ' . $limit;
}
return $query;
} else {
return $this->get_sql( $params, self::METHOD_UNION );
}
}
/**
* Get count query
*
* @param WPML_TM_Jobs_Search_Params $params Job search params.
*
* @return int|string
*/
public function get_count_query( WPML_TM_Jobs_Search_Params $params ) {
$params_without_pagination_and_sorting = clone $params;
$params_without_pagination_and_sorting->set_limit( 0 )->set_offset( 0 );
$params_without_pagination_and_sorting->set_sorting( array() );
return $this->get_sql( $params_without_pagination_and_sorting, self::METHOD_COUNT );
}
/**
* Get SQL request string
*
* @param WPML_TM_Jobs_Search_Params $params Job search params.
* @param string $method Query method.
*
* @throws InvalidArgumentException In case of error.
* @throws RuntimeException In case of error.
* @return string
*/
private function get_sql( WPML_TM_Jobs_Search_Params $params, $method ) {
switch ( $method ) {
case self::METHOD_UNION:
$query_method = 'get_data_query';
break;
case self::METHOD_COUNT:
$query_method = 'get_count_query';
break;
default:
throw new InvalidArgumentException( 'Invalid method argument: ' . $method );
}
$parts = array();
foreach ( $this->queries as $query ) {
$query_string = $query->$query_method( $params );
if ( $query_string ) {
$parts[] = $query_string;
}
}
if ( ! $parts ) {
throw new RuntimeException( 'None of subqueries matches to specified search parameters' );
}
if ( 1 === count( $parts ) ) {
return current( $parts );
}
switch ( $method ) {
case self::METHOD_UNION:
return $this->get_union( $parts );
case self::METHOD_COUNT:
return $this->get_count( $parts );
}
return null;
}
/**
* Get union
*
* @param array $parts Query parts.
*
* @return string
*/
private function get_union( array $parts ) {
return '( ' . implode( ' ) UNION ( ', $parts ) . ' )';
}
/**
* Get count
*
* @param array $parts Query parts.
*
* @return string
*/
private function get_count( array $parts ) {
return 'SELECT ( ' . implode( ' ) + ( ', $parts ) . ' )';
}
/**
* Is query valid
*
* @param mixed $query SQL query.
*
* @return bool
*/
private function is_query_valid( $query ) {
return $query instanceof Query;
}
}