first commit
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user