first commit
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use wpdb;
|
||||
use WPML_TM_Editors;
|
||||
use WPML_TM_Jobs_Search_Params;
|
||||
|
||||
abstract class AbstractQuery implements Query {
|
||||
/** @var wpdb */
|
||||
protected $wpdb;
|
||||
|
||||
/** @var QueryBuilder */
|
||||
protected $query_builder;
|
||||
|
||||
/** @var string */
|
||||
protected $title_column = 'posts.post_title';
|
||||
|
||||
/** @var string */
|
||||
protected $batch_name_column = 'batches.batch_name';
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb
|
||||
* @param QueryBuilder $query_builder
|
||||
*/
|
||||
public function __construct( wpdb $wpdb, QueryBuilder $query_builder ) {
|
||||
$this->wpdb = $wpdb;
|
||||
$this->query_builder = $query_builder;
|
||||
}
|
||||
|
||||
|
||||
public function get_data_query( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$hasCompletedTranslationSubquery = "
|
||||
SELECT COUNT(job_id)
|
||||
FROM {$this->wpdb->prefix}icl_translate_job as copmpleted_translation_job
|
||||
WHERE copmpleted_translation_job.rid = translation_status.rid AND copmpleted_translation_job.translated = 1
|
||||
";
|
||||
|
||||
$columns = array(
|
||||
'translation_status.rid AS id',
|
||||
"'" . $this->get_type() . "' AS type",
|
||||
'translation_status.tp_id AS tp_id',
|
||||
'batches.id AS local_batch_id',
|
||||
'batches.tp_id AS tp_batch_id',
|
||||
$this->batch_name_column,
|
||||
'translation_status.status AS status',
|
||||
'original_translations.element_id AS original_element_id',
|
||||
'translations.source_language_code AS source_language',
|
||||
'translations.language_code AS target_language',
|
||||
'translation_status.translation_service AS translation_service',
|
||||
'translation_status.timestamp AS sent_date',
|
||||
'translate_job.deadline_date AS deadline_date',
|
||||
'translate_job.completed_date AS completed_date',
|
||||
"{$this->title_column} AS title",
|
||||
'source_languages.english_name AS source_language_name',
|
||||
'target_languages.english_name AS target_language_name',
|
||||
'translate_job.translator_id AS translator_id',
|
||||
'translate_job.job_id AS translate_job_id',
|
||||
'translation_status.tp_revision AS revision',
|
||||
'translation_status.ts_status AS ts_status',
|
||||
'translation_status.needs_update AS needs_update',
|
||||
'translate_job.editor AS editor',
|
||||
"({$hasCompletedTranslationSubquery}) > 0 AS has_completed_translation",
|
||||
'translate_job.editor_job_id AS editor_job_id',
|
||||
);
|
||||
|
||||
return $this->build_query( $params, $columns );
|
||||
}
|
||||
|
||||
public function get_count_query( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$columns = array( 'COUNT(translation_status.rid)' );
|
||||
|
||||
return $this->build_query( $params, $columns );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function build_query( WPML_TM_Jobs_Search_Params $params, array $columns ) {
|
||||
if ( $this->check_job_type( $params ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$query_builder = clone $this->query_builder;
|
||||
$query_builder->set_columns( $columns );
|
||||
$query_builder->set_from( "{$this->wpdb->prefix}icl_translation_status translation_status" );
|
||||
|
||||
$this->define_joins( $query_builder );
|
||||
$this->define_filters( $query_builder, $params );
|
||||
|
||||
$query_builder->set_limit( $params );
|
||||
$query_builder->set_order( $params );
|
||||
|
||||
return $query_builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function check_job_type( WPML_TM_Jobs_Search_Params $params ) {
|
||||
return $params->get_job_types() && ! in_array( $this->get_type(), $params->get_job_types(), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function get_type();
|
||||
|
||||
protected function define_joins( QueryBuilder $query_builder ) {
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_translations translations
|
||||
ON translations.translation_id = translation_status.translation_id"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_translations original_translations
|
||||
ON original_translations.trid = translations.trid AND original_translations.language_code = translations.source_language_code"
|
||||
);
|
||||
|
||||
$subquery = "
|
||||
SELECT *
|
||||
FROM {$this->wpdb->prefix}icl_translate_job as translate_job
|
||||
WHERE job_id = (
|
||||
SELECT MAX(job_id) AS job_id
|
||||
FROM {$this->wpdb->prefix}icl_translate_job as sub_translate_job
|
||||
WHERE sub_translate_job.rid = translate_job.rid
|
||||
)
|
||||
";
|
||||
$query_builder->add_join( "INNER JOIN ({$subquery}) AS translate_job ON translate_job.rid = translation_status.rid" );
|
||||
|
||||
$this->add_resource_join( $query_builder );
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_languages source_languages
|
||||
ON source_languages.code = translations.source_language_code"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_languages target_languages
|
||||
ON target_languages.code = translations.language_code"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_translation_batches batches
|
||||
ON batches.id = translation_status.batch_id"
|
||||
);
|
||||
}
|
||||
|
||||
abstract protected function add_resource_join( QueryBuilder $query_builder );
|
||||
|
||||
protected function define_filters( QueryBuilder $query_builder, WPML_TM_Jobs_Search_Params $params ) {
|
||||
$this->set_status_filter( $query_builder, $params );
|
||||
$query_builder = $this->set_scope_filter( $query_builder, $params );
|
||||
$query_builder->set_multi_value_text_filter( $this->title_column, $params->get_title() );
|
||||
$query_builder->set_multi_value_text_filter( $this->batch_name_column, $params->get_batch_name() );
|
||||
$query_builder->set_source_language( 'translations.source_language_code', $params );
|
||||
$query_builder->set_target_language( 'translations.language_code', $params );
|
||||
|
||||
$query_builder->set_translated_by_filter(
|
||||
'translate_job.translator_id',
|
||||
'translation_status.translation_service',
|
||||
$params
|
||||
);
|
||||
|
||||
if ( $params->get_sent() ) {
|
||||
$query_builder->set_date_range( 'translation_status.timestamp', $params->get_sent() );
|
||||
}
|
||||
|
||||
if ( $params->get_deadline() ) {
|
||||
$query_builder->set_date_range( 'translate_job.deadline_date', $params->get_deadline() );
|
||||
}
|
||||
|
||||
if ( $params->get_completed_date() ) {
|
||||
$query_builder->set_date_range( 'translate_job.completed_date', $params->get_completed_date() );
|
||||
}
|
||||
|
||||
$query_builder->set_numeric_value_filter( 'translation_status.rid', $params->get_local_job_ids() );
|
||||
$query_builder->set_numeric_value_filter(
|
||||
'original_translations.element_id',
|
||||
$params->get_original_element_id()
|
||||
);
|
||||
$query_builder->set_tp_id_filter( 'translation_status.tp_id', $params );
|
||||
}
|
||||
|
||||
private function set_status_filter(
|
||||
QueryBuilder $query_builder,
|
||||
WPML_TM_Jobs_Search_Params $params
|
||||
) {
|
||||
if ( $params->get_needs_update() ) {
|
||||
$statuses = array_diff( $params->get_status(), [ ICL_TM_NEEDS_UPDATE ] );
|
||||
|
||||
if ( $params->get_needs_update()->is_needs_update_excluded() ) {
|
||||
$query_builder->add_AND_where_condition( 'translation_status.needs_update != 1' );
|
||||
if ( $statuses ) {
|
||||
$query_builder->set_status_filter( 'translation_status.status', $params );
|
||||
}
|
||||
} else {
|
||||
if ( $statuses ) {
|
||||
$statuses = wpml_prepare_in( $params->get_status(), '%d' );
|
||||
$statuses = sprintf( 'translation_status.status IN (%s)', $statuses );
|
||||
|
||||
$query_builder->add_AND_where_condition( "( translation_status.needs_update = 1 OR {$statuses} )" );
|
||||
} else {
|
||||
$query_builder->add_AND_where_condition( 'translation_status.needs_update = 1' );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$query_builder->set_status_filter( 'translation_status.status', $params );
|
||||
}
|
||||
}
|
||||
|
||||
private function set_scope_filter( QueryBuilder $query_builder, WPML_TM_Jobs_Search_Params $params ) {
|
||||
switch ( $params->get_scope() ) {
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_LOCAL:
|
||||
$query_builder->add_AND_where_condition( "translation_status.translation_service = 'local'" );
|
||||
break;
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_REMOTE:
|
||||
$query_builder->add_AND_where_condition( "translation_status.translation_service != 'local'" );
|
||||
break;
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_ATE:
|
||||
$query_builder->add_AND_where_condition( "translation_status.translation_service = 'local'" );
|
||||
$query_builder->add_AND_where_condition( $this->wpdb->prepare( 'translate_job.editor = %s', WPML_TM_Editors::ATE ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return $query_builder;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \WPML_TM_Jobs_Search_Params;
|
||||
|
||||
class LimitQueryHelper {
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_limit( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$result = '';
|
||||
|
||||
if ( $params->get_limit() ) {
|
||||
if ( $params->get_offset() ) {
|
||||
$result = sprintf( 'LIMIT %d, %d', $params->get_offset(), $params->get_limit() );
|
||||
} else {
|
||||
$result = sprintf( 'LIMIT %d', $params->get_limit() );
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \WPML_TM_Jobs_Search_Params;
|
||||
|
||||
class OrderQueryHelper {
|
||||
|
||||
public function get_order( \WPML_TM_Jobs_Search_Params $params ) {
|
||||
$orders = $this->map_sort_parameters( $params );
|
||||
|
||||
if ( $orders ) {
|
||||
return 'ORDER BY ' . implode( ', ', $orders );
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function map_sort_parameters( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$orders = array();
|
||||
if ( $params->get_sorting() ) {
|
||||
foreach ( $params->get_sorting() as $order ) {
|
||||
if ( $order->get_column() === 'language' ) {
|
||||
$orders[] = 'source_language_name ' . $order->get_direction();
|
||||
$orders[] = 'target_language_name ' . $order->get_direction();
|
||||
} else {
|
||||
$orders[] = $order->get_column() . ' ' . $order->get_direction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $orders;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use WPML_TM_Job_Entity;
|
||||
|
||||
class PackageQuery extends PostQuery {
|
||||
/** @var string */
|
||||
protected $title_column = 'string_packages.title';
|
||||
|
||||
protected function add_resource_join( QueryBuilder $query_builder ) {
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_string_packages string_packages
|
||||
ON string_packages.ID = original_translations.element_id"
|
||||
);
|
||||
|
||||
$query_builder->add_AND_where_condition( "original_translations.element_type LIKE 'package%'" );
|
||||
}
|
||||
|
||||
|
||||
protected function get_type() {
|
||||
return WPML_TM_Job_Entity::PACKAGE_TYPE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use WPML_TM_Job_Entity;
|
||||
|
||||
class PostQuery extends AbstractQuery {
|
||||
/**
|
||||
* @param QueryBuilder $query_builder
|
||||
*/
|
||||
protected function add_resource_join( QueryBuilder $query_builder ) {
|
||||
$query_builder->add_join( "INNER JOIN {$this->wpdb->prefix}posts posts ON posts.ID = original_translations.element_id" );
|
||||
|
||||
$query_builder->add_AND_where_condition( "original_translations.element_type LIKE 'post%'" );
|
||||
}
|
||||
|
||||
protected function get_type() {
|
||||
return WPML_TM_Job_Entity::POST_TYPE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \WPML_TM_Jobs_Search_Params;
|
||||
|
||||
interface Query {
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_data_query( WPML_TM_Jobs_Search_Params $params );
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_count_query( WPML_TM_Jobs_Search_Params $params );
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \wpdb;
|
||||
use \WPML_TM_Jobs_Search_Params;
|
||||
use \WPML_TM_Jobs_Date_Range;
|
||||
use \InvalidArgumentException;
|
||||
|
||||
class QueryBuilder {
|
||||
/** @var wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/** @var LimitQueryHelper */
|
||||
protected $limit_helper;
|
||||
|
||||
/** @var OrderQueryHelper */
|
||||
protected $order_helper;
|
||||
|
||||
/** @var array */
|
||||
private $columns = array();
|
||||
|
||||
/** @var string */
|
||||
private $from;
|
||||
|
||||
/** @var array */
|
||||
private $joins = array();
|
||||
|
||||
/** @var array */
|
||||
private $where = array();
|
||||
|
||||
/** @var string */
|
||||
private $order;
|
||||
|
||||
/** @var string */
|
||||
private $limit;
|
||||
|
||||
/**
|
||||
* @param LimitQueryHelper $limit_helper
|
||||
* @param OrderQueryHelper $order_helper
|
||||
*/
|
||||
public function __construct(
|
||||
LimitQueryHelper $limit_helper,
|
||||
OrderQueryHelper $order_helper
|
||||
) {
|
||||
global $wpdb;
|
||||
$this->wpdb = $wpdb;
|
||||
|
||||
$this->limit_helper = $limit_helper;
|
||||
$this->order_helper = $order_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $columns
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_columns( array $columns ) {
|
||||
$this->columns = $columns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add_column( $column ) {
|
||||
$this->columns[] = $column;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $from
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_from( $from ) {
|
||||
$this->from = $from;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $join
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add_join( $join ) {
|
||||
$this->joins[] = $join;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_status_filter( $column, WPML_TM_Jobs_Search_Params $params ) {
|
||||
if ( $params->get_status() ) {
|
||||
$statuses = wpml_prepare_in( $params->get_status(), '%d' );
|
||||
$this->where[] = sprintf( $column . ' IN (%s)', $statuses );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param array|null $values
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_multi_value_text_filter( $column, $values ) {
|
||||
if ( $values ) {
|
||||
$where = \wpml_collect( $values )->map(
|
||||
function ( $value ) use ( $column ) {
|
||||
return $this->wpdb->prepare( "{$column} LIKE %s", '%' . $value . '%' );
|
||||
}
|
||||
)->toArray();
|
||||
|
||||
$this->where[] = '( ' . implode( ' OR ', $where ) . ' )';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_source_language( $column, WPML_TM_Jobs_Search_Params $params ) {
|
||||
if ( $params->get_source_language() ) {
|
||||
$this->where[] = $this->wpdb->prepare( "{$column} = %s", $params->get_source_language() );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_target_language( $column, WPML_TM_Jobs_Search_Params $params ) {
|
||||
if ( $params->get_target_language() ) {
|
||||
$this->where[] = sprintf(
|
||||
'%s IN (%s)',
|
||||
$column,
|
||||
wpml_prepare_in( $params->get_target_language() )
|
||||
);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set_translated_by_filter(
|
||||
$local_translator_column,
|
||||
$translation_service_column,
|
||||
WPML_TM_Jobs_Search_Params $params
|
||||
) {
|
||||
if ( $params->get_scope() !== WPML_TM_Jobs_Search_Params::SCOPE_ALL && $params->get_translated_by() ) {
|
||||
if ( $params->get_scope() === WPML_TM_Jobs_Search_Params::SCOPE_LOCAL ) {
|
||||
$this->where[] = $this->wpdb->prepare(
|
||||
"{$local_translator_column} = %d",
|
||||
$params->get_translated_by()
|
||||
);
|
||||
} else {
|
||||
$this->where[] = $this->wpdb->prepare(
|
||||
"{$translation_service_column} = %d",
|
||||
$params->get_translated_by()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int|int[] $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_numeric_value_filter( $column, $value ) {
|
||||
if ( $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$this->where[] = sprintf( "{$column} IN(%s)", wpml_prepare_in( $value, '%d' ) );
|
||||
} else {
|
||||
$this->where[] = sprintf( "{$column} = %d", $value );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_tp_id_filter( $column, WPML_TM_Jobs_Search_Params $params ) {
|
||||
if ( $params->get_tp_id() ) {
|
||||
$where = array();
|
||||
$tp_ids = $params->get_tp_id();
|
||||
if ( in_array( null, $tp_ids, true ) ) {
|
||||
$tp_ids = array_filter( $tp_ids );
|
||||
$where[] = $column . ' IS NULL';
|
||||
}
|
||||
|
||||
if ( $tp_ids ) {
|
||||
$where[] = sprintf( $column . ' IN (%s)', wpml_prepare_in( $tp_ids ) );
|
||||
}
|
||||
|
||||
$this->where[] = '( ' . implode( ' OR ', $where ) . ' )';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param WPML_TM_Jobs_Date_Range $date_range
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_date_range( $column, WPML_TM_Jobs_Date_Range $date_range ) {
|
||||
$sql_parts = array();
|
||||
|
||||
if ( $date_range->get_begin() ) {
|
||||
$sql_parts[] = $this->wpdb->prepare( $column . ' >= %s', $date_range->get_begin()->format( 'Y-m-d' ) );
|
||||
}
|
||||
if ( $date_range->get_end() ) {
|
||||
$sql_parts[] = $this->wpdb->prepare(
|
||||
$column . ' <= %s',
|
||||
$date_range->get_end()->format( 'Y-m-d 23:59:59' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $sql_parts ) {
|
||||
$sql = '( ' . implode( ' AND ', $sql_parts ) . ' )';
|
||||
|
||||
if ( $date_range->is_include_null_date() ) {
|
||||
$sql .= " OR $column IS NULL";
|
||||
$sql = "( $sql )";
|
||||
}
|
||||
|
||||
$this->where[] = $sql;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $where
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add_AND_where_condition( $where ) {
|
||||
$this->where[] = $where;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_order( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$this->order = $this->order_helper->get_order( $params );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_limit( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$this->limit = $this->limit_helper->get_limit( $params );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build() {
|
||||
if ( ! $this->columns ) {
|
||||
throw new InvalidArgumentException( 'You have to specify columns list' );
|
||||
}
|
||||
|
||||
if ( ! $this->from ) {
|
||||
throw new InvalidArgumentException( 'You have to specify FROM table' );
|
||||
}
|
||||
|
||||
$sql = '
|
||||
SELECT
|
||||
%s
|
||||
FROM %s
|
||||
';
|
||||
$sql = sprintf( $sql, implode( ', ', $this->columns ), $this->from );
|
||||
|
||||
if ( $this->joins ) {
|
||||
$sql .= implode( ' ', $this->joins );
|
||||
}
|
||||
if ( $this->where ) {
|
||||
$sql .= ' WHERE ' . implode( ' AND ', $this->where );
|
||||
}
|
||||
|
||||
if ( $this->order ) {
|
||||
$sql .= ' ' . $this->order;
|
||||
}
|
||||
if ( $this->limit ) {
|
||||
$sql .= ' ' . $this->limit;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* WPML_TM_Jobs_String_Query class file
|
||||
*
|
||||
* @package wpml-translation-management
|
||||
*/
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \wpdb;
|
||||
use \WPML_TM_Jobs_Search_Params;
|
||||
use \WPML_TM_Job_Entity;
|
||||
|
||||
class StringQuery implements Query {
|
||||
|
||||
/**
|
||||
* WP database instance
|
||||
*
|
||||
* @var wpdb
|
||||
*/
|
||||
protected $wpdb;
|
||||
|
||||
/**
|
||||
* Query builder instance
|
||||
*
|
||||
* @var QueryBuilder
|
||||
*/
|
||||
protected $query_builder;
|
||||
|
||||
/** @var string */
|
||||
protected $batch_name_column = 'batches.batch_name';
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb WP database instance.
|
||||
* @param QueryBuilder $query_builder Query builder instance.
|
||||
*/
|
||||
public function __construct( wpdb $wpdb, QueryBuilder $query_builder ) {
|
||||
$this->wpdb = $wpdb;
|
||||
$this->query_builder = $query_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data query
|
||||
*
|
||||
* @param WPML_TM_Jobs_Search_Params $params Job search params.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_data_query( WPML_TM_Jobs_Search_Params $params ) {
|
||||
$columns = array(
|
||||
'string_translations.id as id',
|
||||
'"' . WPML_TM_Job_Entity::STRING_TYPE . '" as type',
|
||||
'string_status.rid as tp_id',
|
||||
'batches.id as local_batch_id',
|
||||
'batches.tp_id as tp_batch_id',
|
||||
$this->batch_name_column,
|
||||
'string_translations.status as status',
|
||||
'strings.id as original_element_id',
|
||||
'strings.language as source_language',
|
||||
'string_translations.language as target_language',
|
||||
'string_translations.translation_service as translation_service',
|
||||
'string_status.timestamp as sent_date',
|
||||
'NULL as deadline_date',
|
||||
'NULL as completed_date',
|
||||
'strings.value as title',
|
||||
'source_languages.english_name as source_language_name',
|
||||
'target_languages.english_name as target_language_name',
|
||||
'string_translations.translator_id as translator_id',
|
||||
'NULL as translate_job_id',
|
||||
'core_status.tp_revision AS revision',
|
||||
'core_status.ts_status AS ts_status',
|
||||
'NULL AS needs_update',
|
||||
'NULL AS editor',
|
||||
'string_translations.status = ' . ICL_TM_COMPLETE . ' AS has_completed_translation',
|
||||
'NULL AS editor_job_id',
|
||||
);
|
||||
|
||||
return $this->build_query( $params, $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
$columns = array( 'COUNT(string_translations.id)' );
|
||||
|
||||
return $this->build_query( $params, $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build query
|
||||
*
|
||||
* @param WPML_TM_Jobs_Search_Params $params Job search params.
|
||||
* @param array $columns Database columns.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function build_query( WPML_TM_Jobs_Search_Params $params, array $columns ) {
|
||||
if ( $this->check_job_type( $params ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$query_builder = clone $this->query_builder;
|
||||
$query_builder->set_columns( $columns );
|
||||
$query_builder->set_from( "{$this->wpdb->prefix}icl_translation_batches AS translation_batches" );
|
||||
|
||||
$this->define_joins( $query_builder );
|
||||
$this->define_filters( $query_builder, $params );
|
||||
|
||||
$query_builder->set_limit( $params );
|
||||
$query_builder->set_order( $params );
|
||||
|
||||
return $query_builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check job type.
|
||||
*
|
||||
* @param WPML_TM_Jobs_Search_Params $params Job search params.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function check_job_type( WPML_TM_Jobs_Search_Params $params ) {
|
||||
return $params->get_job_types() && ! in_array( WPML_TM_Job_Entity::STRING_TYPE, $params->get_job_types(), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Define joins
|
||||
*
|
||||
* @param QueryBuilder $query_builder Query builder instance.
|
||||
*/
|
||||
private function define_joins( QueryBuilder $query_builder ) {
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_string_translations AS string_translations
|
||||
ON string_translations.batch_id = translation_batches.id"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_strings AS strings
|
||||
ON strings.id = string_translations.string_id"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_string_status AS string_status
|
||||
ON string_status.string_translation_id = string_translations.id"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_core_status AS core_status
|
||||
ON core_status.rid = string_status.rid"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_languages source_languages
|
||||
ON source_languages.code = strings.language"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"LEFT JOIN {$this->wpdb->prefix}icl_languages target_languages
|
||||
ON target_languages.code = string_translations.language"
|
||||
);
|
||||
|
||||
$query_builder->add_join(
|
||||
"INNER JOIN {$this->wpdb->prefix}icl_translation_batches batches
|
||||
ON batches.id = string_translations.batch_id"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define filters
|
||||
*
|
||||
* @param QueryBuilder $query_builder Query builder instance.
|
||||
* @param WPML_TM_Jobs_Search_Params $params Job search params.
|
||||
*/
|
||||
private function define_filters( QueryBuilder $query_builder, WPML_TM_Jobs_Search_Params $params ) {
|
||||
$query_builder->set_status_filter( 'string_translations.status', $params );
|
||||
$query_builder = $this->set_scope_filter( $query_builder, $params );
|
||||
|
||||
$query_builder->set_multi_value_text_filter( 'strings.value', $params->get_title() );
|
||||
$query_builder->set_multi_value_text_filter( $this->batch_name_column, $params->get_batch_name() );
|
||||
$query_builder->set_source_language( 'strings.language', $params );
|
||||
$query_builder->set_target_language( 'string_translations.language', $params );
|
||||
|
||||
$query_builder->set_translated_by_filter(
|
||||
'string_translations.translator_id',
|
||||
'string_translations.translation_service',
|
||||
$params
|
||||
);
|
||||
|
||||
if ( $params->get_sent() ) {
|
||||
$query_builder->set_date_range( 'string_status.timestamp', $params->get_sent() );
|
||||
}
|
||||
|
||||
$query_builder->set_numeric_value_filter( 'string_translations.id', $params->get_first_local_job_id() );
|
||||
$query_builder->set_numeric_value_filter( 'strings.id', $params->get_original_element_id() );
|
||||
$query_builder->set_tp_id_filter( 'string_status.rid', $params );
|
||||
|
||||
if ( $params->get_deadline() ) {
|
||||
$query_builder->add_AND_where_condition( '1 = 0' );
|
||||
}
|
||||
}
|
||||
|
||||
private function set_scope_filter( QueryBuilder $query_builder, WPML_TM_Jobs_Search_Params $params ) {
|
||||
switch ( $params->get_scope() ) {
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_LOCAL:
|
||||
$query_builder->add_AND_where_condition( 'string_status.rid IS NULL' );
|
||||
break;
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_REMOTE:
|
||||
$query_builder->add_AND_where_condition( 'string_status.rid IS NOT NULL' );
|
||||
break;
|
||||
case WPML_TM_Jobs_Search_Params::SCOPE_ATE:
|
||||
// we do not have string ATE jobs yet
|
||||
// @todo it must be changed when we add them
|
||||
$query_builder->add_AND_where_condition( '1 != 1' );
|
||||
break;
|
||||
}
|
||||
|
||||
return $query_builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use WPML_TM_Job_Entity;
|
||||
|
||||
class StringsBatchQuery extends AbstractQuery {
|
||||
/** @var string */
|
||||
protected $title_column = 'translation_batches.batch_name';
|
||||
|
||||
protected function add_resource_join( QueryBuilder $query_builder ) {
|
||||
$query_builder->add_join( "INNER JOIN {$this->wpdb->prefix}icl_translation_batches translation_batches ON translation_batches.id = original_translations.element_id" );
|
||||
|
||||
$query_builder->add_AND_where_condition( "original_translations.element_type = 'st-batch_strings'" );
|
||||
}
|
||||
|
||||
protected function get_type() {
|
||||
return WPML_TM_Job_Entity::STRING_BATCH;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user