first commit
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs;
|
||||
|
||||
use WPML\Core\WP\App\Resources;
|
||||
use WPML\LIB\WP\Hooks;
|
||||
use WPML\UIPage;
|
||||
|
||||
class Loader implements \IWPML_Backend_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
if ( wpml_is_ajax() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( UIPage::isTMJobs( $_GET ) || UIPage::isTranslationQueue( $_GET ) ) {
|
||||
Hooks::onAction( 'wp_loaded' )
|
||||
->then( [ $this, 'getData' ] )
|
||||
->then( Resources::enqueueApp( 'jobs' ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function getData() {
|
||||
$data = ( new \WPML_TM_Jobs_List_Script_Data() )->get();
|
||||
$data = ( new \WPML_TM_Scripts_Factory() )->build_localize_script_data( $data );
|
||||
|
||||
return [
|
||||
'name' => 'WPML_TM_SETTINGS',
|
||||
'data' => $data,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace WPML\TM\Jobs;
|
||||
|
||||
use WPML\Element\API\PostTranslations;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Maybe;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\User;
|
||||
use WPML\Records\Translations as TranslationRecords;
|
||||
use WPML\TM\API\Jobs;
|
||||
use function WPML\FP\curryN;
|
||||
use function WPML\FP\invoke;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
class Manual {
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return \WPML_Translation_Job|null
|
||||
*/
|
||||
public function createOrReuse( array $params ) {
|
||||
$jobId = (int) filter_var( Obj::propOr( 0, 'job_id', $params ), FILTER_SANITIZE_NUMBER_INT );
|
||||
|
||||
list( $jobId, $trid, $updateNeeded, $targetLanguageCode, $elementType ) = $this->get_job_data_for_restore( $jobId, $params );
|
||||
$sourceLangCode = filter_var( Obj::prop( 'source_language_code', $params ), FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
|
||||
if ( $trid && $targetLanguageCode && ( $updateNeeded || ! $jobId ) ) {
|
||||
$postId = $this->getOriginalPostId( $trid );
|
||||
|
||||
if ( $postId && $this->can_user_translate( $sourceLangCode, $targetLanguageCode, $postId ) ) {
|
||||
return $this->markJobAsManual( $this->createLocalJob( $postId, $targetLanguageCode, $elementType ) );
|
||||
}
|
||||
}
|
||||
return $jobId ? $this->markJobAsManual( wpml_tm_load_job_factory()->get_translation_job_as_active_record( $jobId ) ) : null;
|
||||
}
|
||||
|
||||
private function getOriginalPostId( $trid ) {
|
||||
return Obj::prop( 'element_id', TranslationRecords::getSourceByTrid( $trid ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $jobId
|
||||
* @param array $params
|
||||
*
|
||||
* @return array ( job_id, trid, updated_needed, language_code, post_type )
|
||||
*/
|
||||
private function get_job_data_for_restore( $jobId, array $params ) {
|
||||
$trid = (int) filter_var( Obj::prop( 'trid', $params ), FILTER_SANITIZE_NUMBER_INT );
|
||||
$updateNeeded = (bool) filter_var( Obj::prop( 'update_needed', $params ), FILTER_SANITIZE_NUMBER_INT );
|
||||
$languageCode = (string) filter_var( Obj::prop( 'language_code', $params ), FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
|
||||
$job = null;
|
||||
if ( $jobId ) {
|
||||
$job = Jobs::get( $jobId );
|
||||
} else if ( $trid && $languageCode ) {
|
||||
$job = Jobs::getTridJob( $trid, $languageCode );
|
||||
}
|
||||
|
||||
if ( $job ) {
|
||||
return [
|
||||
$jobId,
|
||||
Obj::prop( 'trid', $job ),
|
||||
Obj::prop( 'needs_update', $job ),
|
||||
Obj::prop( 'language_code', $job ),
|
||||
Obj::prop( 'original_post_type', $job )
|
||||
];
|
||||
}
|
||||
|
||||
$elementType = $trid ? Obj::path( [ 0, 'element_type' ], TranslationRecords::getByTrid( $trid ) ) : null;
|
||||
|
||||
return [ $jobId, $trid, $updateNeeded, $languageCode, $elementType, ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sourceLangCode
|
||||
* @param string $targetLangCode
|
||||
* @param string $postId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_user_translate( $sourceLangCode, $targetLangCode, $postId ) {
|
||||
$args = [
|
||||
'lang_from' => $sourceLangCode,
|
||||
'lang_to' => $targetLangCode,
|
||||
'post_id' => $postId,
|
||||
];
|
||||
|
||||
return wpml_tm_load_blog_translators()->is_translator( User::getCurrentId(), $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $originalPostId
|
||||
* @param $targetLangCode
|
||||
* @param $elementType
|
||||
*
|
||||
* @return \WPML_Translation_Job|null
|
||||
*/
|
||||
private function createLocalJob( $originalPostId, $targetLangCode, $elementType ) {
|
||||
$jobId = wpml_tm_load_job_factory()->create_local_job( $originalPostId, $targetLangCode, null, $elementType );
|
||||
|
||||
return Maybe::fromNullable( $jobId )
|
||||
->map( [ wpml_tm_load_job_factory(), 'get_translation_job_as_active_record' ] )
|
||||
->map( $this->maybeAssignTranslator() )
|
||||
->map( $this->maybeSetJobStatus() )
|
||||
->getOrElse( null );
|
||||
}
|
||||
|
||||
private function maybeAssignTranslator() {
|
||||
return function ( $jobObject ) {
|
||||
if ( $jobObject->get_translator_id() <= 0 ) {
|
||||
$jobObject->assign_to( User::getCurrentId() );
|
||||
}
|
||||
|
||||
return $jobObject;
|
||||
};
|
||||
}
|
||||
|
||||
private function maybeSetJobStatus() {
|
||||
return function ( $jobObject ) {
|
||||
if ( $this->isDuplicate( $jobObject ) ) {
|
||||
Jobs::setStatus( (int) $jobObject->get_id(), ICL_TM_DUPLICATE );
|
||||
} elseif ( (int) $jobObject->get_status_value() !== ICL_TM_COMPLETE ) {
|
||||
Jobs::setStatus( (int) $jobObject->get_id(), ICL_TM_IN_PROGRESS );
|
||||
}
|
||||
|
||||
return $jobObject;
|
||||
};
|
||||
}
|
||||
|
||||
private function markJobAsManual( $jobObject ) {
|
||||
$jobObject && Jobs::clearAutomatic( $jobObject->get_id() );
|
||||
|
||||
return $jobObject;
|
||||
}
|
||||
|
||||
private function isDuplicate( \WPML_Translation_Job $jobObject ) {
|
||||
return Maybe::of( $jobObject->get_original_element_id() )
|
||||
->map( PostTranslations::get() )
|
||||
->map( Obj::prop( $jobObject->get_language_code() ) )
|
||||
->map( Obj::prop( 'element_id' ) )
|
||||
->map( [ wpml_get_post_status_helper(), 'is_duplicate' ] )
|
||||
->getOrElse( false );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Job_Element_Entity {
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var int */
|
||||
private $content_id;
|
||||
|
||||
/** @var int */
|
||||
private $timestamp;
|
||||
|
||||
/** @var string */
|
||||
private $type;
|
||||
|
||||
/** @var string */
|
||||
private $format;
|
||||
|
||||
/** @var bool */
|
||||
private $translatable;
|
||||
|
||||
/** @var string */
|
||||
private $data;
|
||||
|
||||
/** @var string */
|
||||
private $data_translated;
|
||||
|
||||
/** @var bool */
|
||||
private $finished;
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param int $content_id
|
||||
* @param int $timestamp
|
||||
* @param string $type
|
||||
* @param string $format
|
||||
* @param bool $is_translatable
|
||||
* @param string $data
|
||||
* @param string $data_translated
|
||||
* @param bool $finished
|
||||
*/
|
||||
public function __construct(
|
||||
$id,
|
||||
$content_id,
|
||||
$timestamp,
|
||||
$type,
|
||||
$format,
|
||||
$is_translatable,
|
||||
$data,
|
||||
$data_translated,
|
||||
$finished
|
||||
) {
|
||||
$this->id = (int) $id;
|
||||
$this->content_id = (int) $content_id;
|
||||
$this->timestamp = (int) $timestamp;
|
||||
$this->type = (string) $type;
|
||||
$this->format = (string) $format;
|
||||
$this->translatable = (bool) $is_translatable;
|
||||
$this->data = (string) $data;
|
||||
$this->data_translated = (bool) $data_translated;
|
||||
$this->finished = (bool) $finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_content_id() {
|
||||
return $this->content_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_timestamp() {
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_format() {
|
||||
return $this->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_translatable() {
|
||||
return $this->translatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_data() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_data_translated() {
|
||||
return $this->data_translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_finished() {
|
||||
return $this->finished;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Job_Elements_Repository {
|
||||
|
||||
/** @var wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb
|
||||
*/
|
||||
public function __construct( wpdb $wpdb ) {
|
||||
$this->wpdb = $wpdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Post_Job_Entity $job
|
||||
*
|
||||
* @return WPML_TM_Job_Element_Entity[]
|
||||
*/
|
||||
public function get_job_elements( WPML_TM_Post_Job_Entity $job ) {
|
||||
$sql = "
|
||||
SELECT translate.*
|
||||
FROM {$this->wpdb->prefix}icl_translate translate
|
||||
WHERE job_id = %d
|
||||
";
|
||||
|
||||
$rowset = $this->wpdb->get_results( $this->wpdb->prepare( $sql, $job->get_translate_job_id() ) );
|
||||
|
||||
return array_map( array( $this, 'build_element_entity' ), $rowset );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdClass $raw_data
|
||||
*
|
||||
* @return WPML_TM_Job_Element_Entity
|
||||
*/
|
||||
private function build_element_entity( stdClass $raw_data ) {
|
||||
return new WPML_TM_Job_Element_Entity(
|
||||
$raw_data->tid,
|
||||
$raw_data->content_id,
|
||||
$raw_data->timestamp,
|
||||
$raw_data->field_type,
|
||||
$raw_data->field_format,
|
||||
$raw_data->field_translate,
|
||||
$raw_data->field_data,
|
||||
$raw_data->field_data_translated,
|
||||
$raw_data->field_finished
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
|
||||
use WPML\FP\Lst;
|
||||
|
||||
class WPML_TM_Job_Entity {
|
||||
|
||||
const POST_TYPE = 'post';
|
||||
const STRING_TYPE = 'string';
|
||||
const STRING_BATCH = 'st-batch_strings';
|
||||
const PACKAGE_TYPE = 'package';
|
||||
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var string */
|
||||
private $type;
|
||||
|
||||
/** @var int */
|
||||
private $tp_id;
|
||||
|
||||
/** @var WPML_TM_Jobs_Batch */
|
||||
private $batch;
|
||||
|
||||
/** @var int */
|
||||
private $status;
|
||||
|
||||
/** @var int */
|
||||
private $original_element_id;
|
||||
|
||||
/** @var string */
|
||||
private $source_language;
|
||||
|
||||
/** @var string */
|
||||
private $target_language;
|
||||
|
||||
/** @var string */
|
||||
private $translation_service;
|
||||
|
||||
/** @var DateTime */
|
||||
private $sent_date;
|
||||
|
||||
/** @var DateTime|null */
|
||||
private $deadline;
|
||||
|
||||
/** @var int */
|
||||
private $translator_id;
|
||||
|
||||
/** @var int */
|
||||
private $revision;
|
||||
|
||||
/** @var WPML_TM_Job_TS_Status */
|
||||
private $ts_status;
|
||||
|
||||
/** @var bool */
|
||||
private $needs_update;
|
||||
|
||||
/** @var bool */
|
||||
private $has_completed_translation = false;
|
||||
|
||||
/** @var string */
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $type
|
||||
* @param int $tp_id
|
||||
* @param WPML_TM_Jobs_Batch $batch
|
||||
* @param int $status
|
||||
*/
|
||||
public function __construct( $id, $type, $tp_id, WPML_TM_Jobs_Batch $batch, $status ) {
|
||||
$this->id = (int) $id;
|
||||
|
||||
if ( ! self::is_type_valid( $type ) ) {
|
||||
throw new InvalidArgumentException( 'Invalid type value: ' . $type );
|
||||
}
|
||||
$this->type = $type;
|
||||
|
||||
$this->tp_id = (int) $tp_id;
|
||||
$this->batch = $batch;
|
||||
|
||||
$this->set_status( $status );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `get_rid` instead.
|
||||
*
|
||||
* This method is deprecated because it caused confusion
|
||||
* between the `job_id` and the `rid`.
|
||||
*
|
||||
* It's actually returning the `rid`.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->get_rid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_rid() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_tp_id() {
|
||||
return $this->tp_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Batch
|
||||
*/
|
||||
public function get_batch() {
|
||||
return $this->batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $status
|
||||
*/
|
||||
public function set_status( $status ) {
|
||||
$status = (int) $status;
|
||||
if ( ! in_array(
|
||||
$status,
|
||||
array(
|
||||
ICL_TM_NOT_TRANSLATED,
|
||||
ICL_TM_WAITING_FOR_TRANSLATOR,
|
||||
ICL_TM_IN_PROGRESS,
|
||||
ICL_TM_TRANSLATION_READY_TO_DOWNLOAD,
|
||||
ICL_TM_DUPLICATE,
|
||||
ICL_TM_COMPLETE,
|
||||
ICL_TM_NEEDS_UPDATE,
|
||||
ICL_TM_NEEDS_REVIEW,
|
||||
ICL_TM_ATE_CANCELLED,
|
||||
ICL_TM_ATE_NEEDS_RETRY,
|
||||
),
|
||||
true
|
||||
) ) {
|
||||
$status = ICL_TM_NOT_TRANSLATED;
|
||||
}
|
||||
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_original_element_id() {
|
||||
return $this->original_element_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $original_element_id
|
||||
*/
|
||||
public function set_original_element_id( $original_element_id ) {
|
||||
$this->original_element_id = $original_element_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_source_language() {
|
||||
return $this->source_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_language
|
||||
*/
|
||||
public function set_source_language( $source_language ) {
|
||||
$this->source_language = $source_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_target_language() {
|
||||
return $this->target_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $target_language
|
||||
*/
|
||||
public function set_target_language( $target_language ) {
|
||||
$this->target_language = $target_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_translation_service() {
|
||||
return $this->translation_service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $translation_service
|
||||
*/
|
||||
public function set_translation_service( $translation_service ) {
|
||||
$this->translation_service = $translation_service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_sent_date() {
|
||||
return $this->sent_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTime $sent_date
|
||||
*/
|
||||
public function set_sent_date( DateTime $sent_date ) {
|
||||
$this->sent_date = $sent_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tp_id
|
||||
*/
|
||||
public function set_tp_id( $tp_id ) {
|
||||
$this->tp_id = $tp_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_deadline() {
|
||||
return $this->deadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTime|null $deadline
|
||||
*/
|
||||
public function set_deadline( DateTime $deadline = null ) {
|
||||
$this->deadline = $deadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_translator_id() {
|
||||
return $this->translator_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $translator_id
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_translator_id( $translator_id ) {
|
||||
$this->translator_id = $translator_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_revision() {
|
||||
return $this->revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $revision
|
||||
*/
|
||||
public function set_revision( $revision ) {
|
||||
$this->revision = max( (int) $revision, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Job_TS_Status
|
||||
*/
|
||||
public function get_ts_status() {
|
||||
return $this->ts_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Job_TS_Status|string $ts_status
|
||||
*/
|
||||
public function set_ts_status( $ts_status ) {
|
||||
if ( is_string( $ts_status ) ) {
|
||||
$status = json_decode( $ts_status );
|
||||
if ( $status ) {
|
||||
$ts_status = new WPML_TM_Job_TS_Status( $status->ts_status->status, $status->ts_status->links );
|
||||
}
|
||||
}
|
||||
$this->ts_status = $ts_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Job_Entity $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_equal( WPML_TM_Job_Entity $job ) {
|
||||
return $this->get_id() === $job->get_id() && $this->get_type() === $job->get_type();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function does_need_update() {
|
||||
return $this->needs_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $needs_update
|
||||
*/
|
||||
public function set_needs_update( $needs_update ) {
|
||||
$this->needs_update = (bool) $needs_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function has_completed_translation() {
|
||||
return $this->has_completed_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $has_completed_translation
|
||||
*/
|
||||
public function set_has_completed_translation( $has_completed_translation ) {
|
||||
$this->has_completed_translation = (bool) $has_completed_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function set_title( $title ) {
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_type_valid( $type ) {
|
||||
return Lst::includes( $type, [ self::POST_TYPE, self::STRING_TYPE, self::PACKAGE_TYPE, self::STRING_BATCH ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Job_TS_Status {
|
||||
|
||||
/** @var string */
|
||||
private $status;
|
||||
/** @var array */
|
||||
private $links = array();
|
||||
|
||||
/**
|
||||
* WPML_TM_Job_TS_Status constructor.
|
||||
*
|
||||
* @param string $status
|
||||
* @param array $links
|
||||
*/
|
||||
public function __construct( $status, $links ) {
|
||||
$this->status = $status;
|
||||
$this->links = $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_links() {
|
||||
return $this->links;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
if ( $this->status ) {
|
||||
return wp_json_encode(
|
||||
array(
|
||||
'status' => $this->status,
|
||||
'links' => $this->links,
|
||||
)
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Batch {
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/** @var int|null */
|
||||
private $tp_id;
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $name
|
||||
* @param int|null $tp_id
|
||||
*/
|
||||
public function __construct( $id, $name, $tp_id = null ) {
|
||||
$this->id = (int) $id;
|
||||
$this->name = (string) $name;
|
||||
$this->tp_id = $tp_id ? (int) $tp_id : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_tp_id() {
|
||||
return $this->tp_id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Collection implements IteratorAggregate, Countable {
|
||||
/** @var WPML_TM_Job_Entity[] */
|
||||
private $jobs = array();
|
||||
|
||||
public function __construct( array $jobs ) {
|
||||
foreach ( $jobs as $job ) {
|
||||
if ( $job instanceof WPML_TM_Job_Entity ) {
|
||||
$this->add( $job );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Job_Entity $job
|
||||
*/
|
||||
private function add( WPML_TM_Job_Entity $job ) {
|
||||
$this->jobs[] = $job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tp_id
|
||||
*
|
||||
* @return null|WPML_TM_Job_Entity
|
||||
*/
|
||||
public function get_by_tp_id( $tp_id ) {
|
||||
foreach ( $this->jobs as $job ) {
|
||||
if ( $tp_id === $job->get_tp_id() ) {
|
||||
return $job;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback
|
||||
*
|
||||
* @return WPML_TM_Jobs_Collection
|
||||
*/
|
||||
public function filter( $callback ) {
|
||||
return new WPML_TM_Jobs_Collection( array_filter( $this->jobs, $callback ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|int $status
|
||||
* @param bool $exclude
|
||||
*
|
||||
* @return WPML_TM_Jobs_Collection
|
||||
*/
|
||||
public function filter_by_status( $status, $exclude = false ) {
|
||||
if ( ! is_array( $status ) ) {
|
||||
$status = array( $status );
|
||||
}
|
||||
|
||||
$result = array();
|
||||
if ( $exclude ) {
|
||||
foreach ( $this->jobs as $job ) {
|
||||
if ( ! in_array( $job->get_status(), $status, true ) ) {
|
||||
$result[] = $job;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ( $this->jobs as $job ) {
|
||||
if ( in_array( $job->get_status(), $status, true ) ) {
|
||||
$result[] = $job;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new WPML_TM_Jobs_Collection( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback
|
||||
* @param bool $return_job_collection
|
||||
*
|
||||
* @return array|WPML_TM_Jobs_Collection
|
||||
*/
|
||||
public function map( $callback, $return_job_collection = false ) {
|
||||
$mapped_result = array_map( $callback, $this->jobs );
|
||||
|
||||
return $return_job_collection ? new WPML_TM_Jobs_Collection( $mapped_result ) : $mapped_result;
|
||||
}
|
||||
|
||||
public function map_to_property( $property ) {
|
||||
$method = 'get_' . $property;
|
||||
$result = array();
|
||||
|
||||
foreach ( $this->jobs as $job ) {
|
||||
if ( ! method_exists( $job, $method ) ) {
|
||||
throw new InvalidArgumentException( 'Property ' . $property . ' does not exist' );
|
||||
}
|
||||
|
||||
$result[] = $job->{$method}();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $jobs
|
||||
*
|
||||
* @return WPML_TM_Jobs_Collection
|
||||
*/
|
||||
public function append( $jobs ) {
|
||||
if ( $jobs instanceof WPML_TM_Jobs_Collection ) {
|
||||
$jobs = $jobs->toArray();
|
||||
}
|
||||
|
||||
return new WPML_TM_Jobs_Collection( array_merge( $this->jobs, $jobs ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator() {
|
||||
return new ArrayIterator( $this->jobs );
|
||||
}
|
||||
|
||||
public function toArray() {
|
||||
return $this->jobs;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count() {
|
||||
return count( $this->jobs );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Date_Range {
|
||||
/** @var DateTime|null */
|
||||
private $begin;
|
||||
|
||||
/** @var DateTime|null */
|
||||
private $end;
|
||||
|
||||
/**
|
||||
* Specify how we should treat date values which are NULL
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $include_null_date;
|
||||
|
||||
/**
|
||||
* @param DateTime|null $begin
|
||||
* @param DateTime|null $end
|
||||
* @param bool $include_null_date
|
||||
*/
|
||||
public function __construct( DateTime $begin = null, DateTime $end = null, $include_null_date = false ) {
|
||||
$this->begin = $begin;
|
||||
$this->end = $end;
|
||||
$this->include_null_date = (bool) $include_null_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_begin() {
|
||||
return $this->begin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_end() {
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_include_null_date() {
|
||||
return $this->include_null_date;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Needs_Update_Param {
|
||||
|
||||
const INCLUDE_NEEDS_UPDATE = 'include';
|
||||
const EXCLUDE_NEEDS_UPDATE = 'exclude';
|
||||
|
||||
/** @var string */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct( $value ) {
|
||||
if ( ! self::is_valid( $value ) ) {
|
||||
throw new \InvalidArgumentException( 'Invalid value of NEEDS_UPDATE param: ' . $value );
|
||||
}
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_needs_update_excluded() {
|
||||
return $this->value === self::EXCLUDE_NEEDS_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_needs_update_included() {
|
||||
return $this->value === self::INCLUDE_NEEDS_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_valid( $value ) {
|
||||
return in_array(
|
||||
(string) $value,
|
||||
[
|
||||
self::INCLUDE_NEEDS_UPDATE,
|
||||
self::EXCLUDE_NEEDS_UPDATE,
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
use \WPML\TM\Jobs\Query\Query;
|
||||
use WPML\FP\Fns;
|
||||
|
||||
class WPML_TM_Jobs_Repository {
|
||||
/** @var wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/** @var Query */
|
||||
private $query_builder;
|
||||
|
||||
/** @var WPML_TM_Job_Elements_Repository */
|
||||
private $elements_repository;
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb
|
||||
* @param Query $query_builder
|
||||
* @param WPML_TM_Job_Elements_Repository $elements_repository
|
||||
*/
|
||||
public function __construct(
|
||||
wpdb $wpdb,
|
||||
Query $query_builder,
|
||||
WPML_TM_Job_Elements_Repository $elements_repository
|
||||
) {
|
||||
$this->wpdb = $wpdb;
|
||||
$this->query_builder = $query_builder;
|
||||
$this->elements_repository = $elements_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return WPML_TM_Jobs_Collection|array
|
||||
*/
|
||||
public function get( WPML_TM_Jobs_Search_Params $params ) {
|
||||
if ( $params->get_columns_to_select() ) {
|
||||
return $this->wpdb->get_results( $this->query_builder->get_data_query( $params ) );
|
||||
}
|
||||
|
||||
return new WPML_TM_Jobs_Collection( array_map(
|
||||
array( $this, 'build_job_entity' ),
|
||||
$this->wpdb->get_results( $this->query_builder->get_data_query( $params ) )
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ateJobIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function increment_ate_sync_count( array $ateJobIds ) {
|
||||
if ( empty( $ateJobIds ) ) {
|
||||
return true;
|
||||
} else {
|
||||
$query = sprintf(
|
||||
'UPDATE %sicl_translate_job SET ate_sync_count=ate_sync_count+1 WHERE editor_job_id IN( %s )',
|
||||
$this->wpdb->prefix,
|
||||
wpml_prepare_in( $ateJobIds )
|
||||
);
|
||||
|
||||
return (bool) $this->wpdb->query( $query );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Search_Params $params
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_count( WPML_TM_Jobs_Search_Params $params ) {
|
||||
return (int) $this->wpdb->get_var( $this->query_builder->get_count_query( $params ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $local_job_id
|
||||
* @param string $job_type
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @return WPML_TM_Job_Entity|false
|
||||
*/
|
||||
public function get_job( $local_job_id, $job_type ) {
|
||||
$params = new WPML_TM_Jobs_Search_Params();
|
||||
$params->set_local_job_id( $local_job_id );
|
||||
$params->set_job_types( $job_type );
|
||||
|
||||
$data = $this->wpdb->get_row( $this->query_builder->get_data_query( $params ) );
|
||||
if ( $data ) {
|
||||
$data = $this->build_job_entity( $data );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdClass $raw_data
|
||||
*
|
||||
* @return WPML_TM_Job_Entity
|
||||
*/
|
||||
private function build_job_entity( stdClass $raw_data ) {
|
||||
$types = [ WPML_TM_Job_Entity::POST_TYPE, WPML_TM_Job_Entity::PACKAGE_TYPE, WPML_TM_Job_Entity::STRING_BATCH ];
|
||||
$batch = new WPML_TM_Jobs_Batch( $raw_data->local_batch_id, $raw_data->batch_name, $raw_data->tp_batch_id );
|
||||
|
||||
if ( in_array( $raw_data->type, $types, true ) ) {
|
||||
$job = new WPML_TM_Post_Job_Entity(
|
||||
$raw_data->id,
|
||||
$raw_data->type,
|
||||
$raw_data->tp_id,
|
||||
$batch,
|
||||
(int) $raw_data->status,
|
||||
array( $this->elements_repository, 'get_job_elements' )
|
||||
);
|
||||
$job->set_translate_job_id( $raw_data->translate_job_id );
|
||||
$job->set_editor( $raw_data->editor );
|
||||
$job->set_completed_date( $raw_data->completed_date ? new DateTime( $raw_data->completed_date ) : null );
|
||||
$job->set_editor_job_id( $raw_data->editor_job_id );
|
||||
$job->set_automatic( $raw_data->automatic );
|
||||
$job->set_review_status( $raw_data->review_status );
|
||||
$job->set_trid( $raw_data->trid );
|
||||
$job->set_element_type( $raw_data->element_type );
|
||||
$job->set_element_id( $raw_data->element_id );
|
||||
$job->set_element_type_prefix( $raw_data->element_type );
|
||||
$job->set_job_title( $raw_data->job_title );
|
||||
|
||||
} else {
|
||||
$job = new WPML_TM_Job_Entity(
|
||||
$raw_data->id,
|
||||
$raw_data->type,
|
||||
$raw_data->tp_id,
|
||||
$batch,
|
||||
(int) $raw_data->status
|
||||
);
|
||||
}
|
||||
|
||||
$job->set_original_element_id( $raw_data->original_element_id );
|
||||
|
||||
$job->set_source_language( $raw_data->source_language );
|
||||
$job->set_target_language( $raw_data->target_language );
|
||||
$job->set_translation_service( $raw_data->translation_service );
|
||||
$job->set_sent_date( new DateTime( $raw_data->sent_date ) );
|
||||
$job->set_deadline( $this->get_deadline( $raw_data ) );
|
||||
$job->set_translator_id( $raw_data->translator_id );
|
||||
$job->set_revision( $raw_data->revision );
|
||||
$job->set_ts_status( $raw_data->ts_status );
|
||||
$job->set_needs_update( $raw_data->needs_update );
|
||||
$job->set_has_completed_translation( $raw_data->has_completed_translation );
|
||||
$job->set_title( $raw_data->title );
|
||||
|
||||
return $job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdClass $raw_data
|
||||
*
|
||||
* @return DateTime|null
|
||||
*/
|
||||
private function get_deadline( stdClass $raw_data ) {
|
||||
if ( $raw_data->deadline_date && '0000-00-00 00:00:00' !== $raw_data->deadline_date ) {
|
||||
return new DateTime( $raw_data->deadline_date );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Search_Params {
|
||||
|
||||
const SCOPE_REMOTE = 'remote';
|
||||
const SCOPE_LOCAL = 'local';
|
||||
const SCOPE_ALL = 'all';
|
||||
const SCOPE_ATE = 'ate';
|
||||
|
||||
private static $scopes = array(
|
||||
self::SCOPE_LOCAL,
|
||||
self::SCOPE_REMOTE,
|
||||
self::SCOPE_ALL,
|
||||
self::SCOPE_ATE,
|
||||
);
|
||||
|
||||
/** @var array */
|
||||
private $status = array();
|
||||
|
||||
/** @var WPML_TM_Jobs_Needs_Update_Param|null */
|
||||
private $needs_update;
|
||||
|
||||
/** @var string */
|
||||
private $scope = self::SCOPE_ALL;
|
||||
|
||||
/** @var array */
|
||||
private $job_types = array();
|
||||
|
||||
/** @var int[] */
|
||||
private $local_job_ids;
|
||||
|
||||
/** @var int */
|
||||
private $limit;
|
||||
|
||||
/** @var int */
|
||||
private $offset;
|
||||
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var string[] */
|
||||
private $title;
|
||||
|
||||
/** @var string[] */
|
||||
private $batch_name;
|
||||
|
||||
/** @var string */
|
||||
private $source_language;
|
||||
|
||||
/** @var string[] */
|
||||
private $target_language;
|
||||
|
||||
/** @var array */
|
||||
private $tp_id = '';
|
||||
|
||||
/** @var WPML_TM_Jobs_Sorting_Param[] */
|
||||
private $sorting = array();
|
||||
|
||||
/** @var int */
|
||||
private $translated_by;
|
||||
|
||||
/** @var WPML_TM_Jobs_Date_Range */
|
||||
private $deadline;
|
||||
|
||||
/** @var WPML_TM_Jobs_Date_Range */
|
||||
private $sent;
|
||||
|
||||
/** @var WPML_TM_Jobs_Date_Range */
|
||||
private $completed_date;
|
||||
|
||||
/** @var int */
|
||||
private $original_element_id;
|
||||
|
||||
/** @var bool|null */
|
||||
private $needs_review = null;
|
||||
|
||||
/** @var bool */
|
||||
private $exclude_hidden_jobs = true;
|
||||
|
||||
/** @var int */
|
||||
private $max_ate_retries;
|
||||
|
||||
/** @var bool */
|
||||
private $exclude_manual = false;
|
||||
|
||||
/** @var bool */
|
||||
private $exclude_longstanding = false;
|
||||
|
||||
/** @var bool */
|
||||
private $exclude_cancelled = false;
|
||||
|
||||
/**
|
||||
* Corresponds with `wp_icl_translations.element_type` column
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $element_type;
|
||||
|
||||
/** @var null|array */
|
||||
private $columns_to_select = null;
|
||||
|
||||
/** @var array */
|
||||
private $custom_where_conditions = [];
|
||||
|
||||
public function __construct( array $params = array() ) {
|
||||
if ( array_key_exists( 'limit', $params ) ) {
|
||||
$this->set_limit( $params['limit'] );
|
||||
if ( array_key_exists( 'offset', $params ) ) {
|
||||
$this->set_offset( $params['offset'] );
|
||||
}
|
||||
}
|
||||
|
||||
$fields = array(
|
||||
'status',
|
||||
'scope',
|
||||
'job_types',
|
||||
'local_job_id',
|
||||
'id',
|
||||
'title',
|
||||
'batch_name',
|
||||
'source_language',
|
||||
'target_language',
|
||||
'sorting',
|
||||
'tp_id',
|
||||
'translated_by',
|
||||
'deadline',
|
||||
'completed_date',
|
||||
'sent',
|
||||
'original_element_id',
|
||||
'exclude_manual',
|
||||
'exclude_longstanding',
|
||||
);
|
||||
foreach ( $fields as $field ) {
|
||||
if ( array_key_exists( $field, $params ) ) {
|
||||
$this->{'set_' . $field}( $params[ $field ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $status
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_status( array $status ) {
|
||||
$this->status = array_map( 'intval', array_values( array_filter( $status, 'is_numeric' ) ) );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_scope() {
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_tp_id() {
|
||||
return $this->tp_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scope
|
||||
*
|
||||
* @retun self
|
||||
*/
|
||||
public function set_scope( $scope ) {
|
||||
if ( ! $this->is_valid_scope( $scope ) ) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid scope. Accepted values: ' . implode( ', ', self::$scopes )
|
||||
);
|
||||
}
|
||||
|
||||
$this->scope = $scope;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_job_types() {
|
||||
return $this->job_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|array $tp_id
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_tp_id( $tp_id ) {
|
||||
$this->tp_id = is_array( $tp_id ) ? $tp_id : array( $tp_id );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $job_types
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_job_types( $job_types ) {
|
||||
$correct_types = [
|
||||
WPML_TM_Job_Entity::POST_TYPE,
|
||||
WPML_TM_Job_Entity::PACKAGE_TYPE,
|
||||
WPML_TM_Job_Entity::STRING_TYPE,
|
||||
WPML_TM_Job_Entity::STRING_BATCH,
|
||||
];
|
||||
|
||||
if ( ! is_array( $job_types ) ) {
|
||||
$job_types = array( $job_types );
|
||||
}
|
||||
|
||||
foreach ( $job_types as $job_type ) {
|
||||
if ( ! in_array( $job_type, $correct_types, true ) ) {
|
||||
throw new InvalidArgumentException( 'Invalid job type' );
|
||||
}
|
||||
$this->job_types[] = $job_type;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_first_local_job_id() {
|
||||
return ! empty( $this->local_job_ids ) ? current( $this->local_job_ids ) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_local_job_ids() {
|
||||
return $this->local_job_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $local_job_id
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_local_job_id( $local_job_id ) {
|
||||
$this->local_job_ids[] = (int) $local_job_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $local_job_ids
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_local_job_ids( array $local_job_ids ) {
|
||||
$this->local_job_ids = array_map( 'intval', $local_job_ids );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_limit() {
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_limit( $limit ) {
|
||||
$this->limit = $limit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_offset() {
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_offset( $offset ) {
|
||||
$this->offset = $offset;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_id( $id ) {
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $title
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_title( $title ) {
|
||||
$this->title = is_array( $title ) ? $title : array( $title );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_batch_name() {
|
||||
return $this->batch_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $batch_name
|
||||
*/
|
||||
public function set_batch_name( $batch_name ) {
|
||||
$this->batch_name = $batch_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_source_language() {
|
||||
return $this->source_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_language
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_source_language( $source_language ) {
|
||||
$this->source_language = $source_language;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_target_language() {
|
||||
return $this->target_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $target_language
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_target_language( $target_language ) {
|
||||
$this->target_language = is_array( $target_language ) ? $target_language : array( $target_language );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Sorting_Param[]
|
||||
*/
|
||||
public function get_sorting() {
|
||||
return $this->sorting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Sorting_Param[] $sorting
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_sorting( array $sorting ) {
|
||||
$this->sorting = array();
|
||||
|
||||
foreach ( $sorting as $sorting_param ) {
|
||||
if ( $sorting_param instanceof WPML_TM_Jobs_Sorting_Param ) {
|
||||
$this->sorting[] = $sorting_param;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_translated_by() {
|
||||
return $this->translated_by;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $translated_by
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_translated_by( $translated_by ) {
|
||||
$this->translated_by = (int) $translated_by;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Date_Range
|
||||
*/
|
||||
public function get_deadline() {
|
||||
return $this->deadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Date_Range $deadline
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_deadline( WPML_TM_Jobs_Date_Range $deadline ) {
|
||||
$this->deadline = $deadline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Date_Range
|
||||
*/
|
||||
public function get_sent() {
|
||||
return $this->sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Date_Range
|
||||
*/
|
||||
public function get_completed_date() {
|
||||
return $this->completed_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_original_element_id() {
|
||||
return $this->original_element_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Date_Range $sent
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_sent( WPML_TM_Jobs_Date_Range $sent ) {
|
||||
$this->sent = $sent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Date_Range $completed_date
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_completed_date( WPML_TM_Jobs_Date_Range $completed_date ) {
|
||||
$this->completed_date = $completed_date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $original_element_id
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_original_element_id( $original_element_id ) {
|
||||
$this->original_element_id = $original_element_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Jobs_Needs_Update_Param|null
|
||||
*/
|
||||
public function get_needs_update() {
|
||||
return $this->needs_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_TM_Jobs_Needs_Update_Param|null $needs_update
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_needs_update( WPML_TM_Jobs_Needs_Update_Param $needs_update = null ) {
|
||||
$this->needs_update = $needs_update;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function needs_review() {
|
||||
return $this->needs_review;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function exclude_hidden_jobs() {
|
||||
return $this->exclude_hidden_jobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $max_ate_retries
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_max_ate_retries( $max_ate_retries ) {
|
||||
$this->max_ate_retries = $max_ate_retries;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_max_ate_retries() {
|
||||
return $this->max_ate_retries;
|
||||
}
|
||||
|
||||
/**
|
||||
* If value is set to NULL then the filter is ignored
|
||||
* If value is true then we INCLUDE needs review jobs
|
||||
* If value is false then we EXCLUDE needs review jobs
|
||||
*
|
||||
* @param bool|null $needs_review
|
||||
*/
|
||||
public function set_needs_review( $needs_review = true ) {
|
||||
$this->needs_review = $needs_review;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exclude_hidden_jobs
|
||||
*/
|
||||
public function set_exclude_hidden_jobs( $exclude_hidden_jobs ) {
|
||||
$this->exclude_hidden_jobs = $exclude_hidden_jobs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_valid_scope( $value ) {
|
||||
return in_array(
|
||||
$value,
|
||||
self::$scopes,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $excludeManual
|
||||
*/
|
||||
public function set_exclude_manual( $excludeManual ) {
|
||||
$this->exclude_manual = $excludeManual;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function should_exclude_manual() {
|
||||
return $this->exclude_manual;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $excludeLongstanding
|
||||
*/
|
||||
public function set_exclude_longstanding( $excludeLongstanding ) {
|
||||
$this->exclude_longstanding = $excludeLongstanding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function should_exclude_longstanding() {
|
||||
return $this->exclude_longstanding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_columns_to_select() {
|
||||
return $this->columns_to_select;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $columns_to_select
|
||||
*
|
||||
* @retun $this
|
||||
*/
|
||||
public function set_columns_to_select( $columns_to_select ) {
|
||||
$this->columns_to_select = $columns_to_select;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_element_type() {
|
||||
return $this->element_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $element_type
|
||||
*
|
||||
* @retrun $this
|
||||
*/
|
||||
public function set_element_type( $element_type ) {
|
||||
$this->element_type = $element_type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function should_exclude_cancelled() {
|
||||
return $this->exclude_cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exclude_cancelled
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_exclude_cancelled( $exclude_cancelled = true ) {
|
||||
$this->exclude_cancelled = $exclude_cancelled;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_custom_where_conditions() {
|
||||
return $this->custom_where_conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $custom_where_conditions
|
||||
*
|
||||
* @retun $this
|
||||
*/
|
||||
public function set_custom_where_conditions( $custom_where_conditions ) {
|
||||
$this->custom_where_conditions = $custom_where_conditions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Jobs_Sorting_Param {
|
||||
/** @var string */
|
||||
private $column;
|
||||
|
||||
/** @var string */
|
||||
private $direction;
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $direction
|
||||
*/
|
||||
public function __construct( $column, $direction = 'asc' ) {
|
||||
$direction = strtolower( $direction );
|
||||
if ( 'asc' !== $direction && 'desc' !== $direction ) {
|
||||
$direction = 'asc';
|
||||
}
|
||||
|
||||
$this->column = $column;
|
||||
$this->direction = $direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_column() {
|
||||
return $this->column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_direction() {
|
||||
return $this->direction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Post_Job_Entity extends WPML_TM_Job_Entity {
|
||||
/** @var WPML_TM_Job_Element_Entity[]|callable */
|
||||
private $elements;
|
||||
|
||||
/** @var int */
|
||||
private $translate_job_id;
|
||||
|
||||
/** @var string */
|
||||
private $editor;
|
||||
|
||||
/** @var int */
|
||||
private $editor_job_id;
|
||||
|
||||
/** @var null|DateTime */
|
||||
private $completed_date;
|
||||
|
||||
/** @var bool */
|
||||
private $automatic;
|
||||
|
||||
/** @var null|string */
|
||||
private $review_status = null;
|
||||
|
||||
/** @var int */
|
||||
private $trid;
|
||||
|
||||
/** @var string */
|
||||
private $element_type;
|
||||
|
||||
/** @var int */
|
||||
private $element_id;
|
||||
|
||||
/** @var string */
|
||||
private $element_type_prefix;
|
||||
|
||||
/** @var string */
|
||||
private $job_title;
|
||||
|
||||
public function __construct( $id, $type, $tp_id, $batch, $status, $elements ) {
|
||||
parent::__construct( $id, $type, $tp_id, $batch, $status );
|
||||
|
||||
if ( is_callable( $elements ) ) {
|
||||
$this->elements = $elements;
|
||||
} elseif ( is_array( $elements ) ) {
|
||||
foreach ( $elements as $element ) {
|
||||
if ( $element instanceof WPML_TM_Job_Element_Entity ) {
|
||||
$this->elements[] = $element;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_TM_Job_Element_Entity[]
|
||||
*/
|
||||
public function get_elements() {
|
||||
if ( is_callable( $this->elements ) ) {
|
||||
return call_user_func( $this->elements, $this );
|
||||
} elseif ( is_array( $this->elements ) ) {
|
||||
return $this->elements;
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_translate_job_id() {
|
||||
return $this->translate_job_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $translate_job_id
|
||||
*/
|
||||
public function set_translate_job_id( $translate_job_id ) {
|
||||
$this->translate_job_id = (int) $translate_job_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_editor() {
|
||||
return $this->editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $editor
|
||||
*/
|
||||
public function set_editor( $editor ) {
|
||||
$this->editor = (string) $editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_editor_job_id() {
|
||||
return $this->editor_job_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $editor_job_id
|
||||
*/
|
||||
public function set_editor_job_id( $editor_job_id ) {
|
||||
$this->editor_job_id = (int) $editor_job_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_ate_job() {
|
||||
return 'local' === $this->get_translation_service() && $this->is_ate_editor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_ate_editor() {
|
||||
return WPML_TM_Editors::ATE === $this->get_editor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_completed_date() {
|
||||
return $this->completed_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTime|null $completed_date
|
||||
*/
|
||||
public function set_completed_date( DateTime $completed_date = null ) {
|
||||
$this->completed_date = $completed_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_automatic() {
|
||||
return $this->automatic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $automatic
|
||||
*/
|
||||
public function set_automatic( $automatic ) {
|
||||
$this->automatic = (bool) $automatic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_review_status() {
|
||||
return $this->review_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $review_status
|
||||
*/
|
||||
public function set_review_status( $review_status ) {
|
||||
$this->review_status = $review_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_trid() {
|
||||
return $this->trid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $trid
|
||||
*/
|
||||
public function set_trid( $trid ) {
|
||||
$this->trid = $trid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_element_type() {
|
||||
return $this->element_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $element_type
|
||||
*/
|
||||
public function set_element_type( $element_type ) {
|
||||
$this->element_type = $element_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_element_id() {
|
||||
return $this->element_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $element_id
|
||||
*/
|
||||
public function set_element_id( $element_id ) {
|
||||
$this->element_id = $element_id;
|
||||
}
|
||||
|
||||
public function get_element_type_prefix() {
|
||||
return $this->element_type_prefix;
|
||||
}
|
||||
|
||||
public function set_element_type_prefix( $element_type ) {
|
||||
$this->element_type_prefix = explode( '_', $element_type )[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_job_title() {
|
||||
return $this->job_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $job_title
|
||||
*/
|
||||
public function set_job_title( $job_title ) {
|
||||
$this->job_title = $job_title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Endpoint;
|
||||
|
||||
use WPML\Ajax\IHandler;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\FP\Either;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\TM\API\Jobs;
|
||||
|
||||
class Resign implements IHandler {
|
||||
|
||||
public function run( Collection $data ) {
|
||||
|
||||
|
||||
$result = \wpml_collect( $data->get( 'jobIds' ) )
|
||||
->filter( Jobs::get() )
|
||||
->map( Fns::tap( [ wpml_load_core_tm(), 'resign_translator' ] ) )
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
return Either::of( $result );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use wpdb;
|
||||
use WPML_TM_Editors;
|
||||
use WPML_TM_Jobs_Search_Params;
|
||||
use WPML\TM\ATE\Jobs;
|
||||
|
||||
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 ) {
|
||||
$has_completed_translation_subquery = "
|
||||
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
|
||||
";
|
||||
|
||||
if ( $params->get_columns_to_select() ) {
|
||||
$columns = $params->get_columns_to_select();
|
||||
} else {
|
||||
$columns = [
|
||||
'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',
|
||||
'translations.trid',
|
||||
'translations.element_type',
|
||||
'translations.element_id',
|
||||
'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',
|
||||
"({$has_completed_translation_subquery}) > 0 AS has_completed_translation",
|
||||
'translate_job.editor_job_id AS editor_job_id',
|
||||
'translate_job.automatic AS automatic',
|
||||
'translate_job.title AS job_title',
|
||||
'translation_status.review_status AS review_status',
|
||||
];
|
||||
}
|
||||
|
||||
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_id() );
|
||||
$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 );
|
||||
|
||||
if ( $params->needs_review() ) {
|
||||
$query_builder->set_needs_review();
|
||||
} elseif ( $params->needs_review() === false ) {
|
||||
$query_builder->set_do_not_need_review();
|
||||
}
|
||||
|
||||
if ( $params->should_exclude_manual() ) {
|
||||
$query_builder->set_automatic();
|
||||
}
|
||||
|
||||
if ( $params->should_exclude_longstanding() ) {
|
||||
$query_builder->set_max_ate_sync_count( Jobs::LONGSTANDING_AT_ATE_SYNC_COUNT );
|
||||
}
|
||||
|
||||
if ( $params->get_max_ate_retries() ) {
|
||||
$query_builder->set_max_retries( $params->get_max_ate_retries() );
|
||||
}
|
||||
|
||||
if ( $params->exclude_hidden_jobs() ) {
|
||||
$query_builder->set_set_excluded_jobs();
|
||||
}
|
||||
|
||||
if ( $params->get_element_type() ) {
|
||||
$query_builder->set_element_type( $params->get_element_type() );
|
||||
}
|
||||
|
||||
if ( $params->get_custom_where_conditions() ) {
|
||||
foreach ( $params->get_custom_where_conditions() as $whereCondition ) {
|
||||
$query_builder->add_AND_where_condition( $whereCondition );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
if ( $params->should_exclude_cancelled() ) {
|
||||
$query_builder->add_AND_where_condition( 'translation_status.status != 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( "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,42 @@
|
||||
<?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();
|
||||
} elseif ( $order->get_column() === 'sent_date' || $order->get_column() === 'deadline_date' ) {
|
||||
$orders[] = "DATE({$order->get_column()}) {$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,398 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Query;
|
||||
|
||||
use \wpdb;
|
||||
use WPML\TM\ATE\Review\ReviewStatus;
|
||||
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;
|
||||
}
|
||||
|
||||
public function set_needs_review() {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translation_status.review_status = %s OR translation_status.review_status = %s)',
|
||||
ReviewStatus::NEEDS_REVIEW,
|
||||
ReviewStatus::EDITING
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function set_do_not_need_review() {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translation_status.review_status IS NULL OR translation_status.review_status = %s)',
|
||||
ReviewStatus::ACCEPTED
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function set_max_retries( $maxRetries ) {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translation_status.ate_comm_retry_count <= %d )',
|
||||
$maxRetries
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function set_element_type( $element_type ) {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translations.element_type = %s )',
|
||||
$element_type
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $automatic
|
||||
*/
|
||||
public function set_automatic( $automatic = true ) {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translate_job.automatic = %d )',
|
||||
$automatic ? 1 : 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $maxAteSyncCount
|
||||
*/
|
||||
public function set_max_ate_sync_count( $maxAteSyncCount ) {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'(translate_job.ate_sync_count <= %d )',
|
||||
$maxAteSyncCount
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function set_set_excluded_jobs() {
|
||||
$this->add_AND_where_condition(
|
||||
$this->wpdb->prepare(
|
||||
'translation_status.status != %s',
|
||||
\WPML_TM_ATE_API::SHOULD_HIDE_STATUS
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,232 @@
|
||||
<?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',
|
||||
'0 AS automatic',
|
||||
'NULL AS review_status',
|
||||
'NULL AS trid',
|
||||
'NULL AS element_type',
|
||||
'NULL AS element_id',
|
||||
'NULL AS job_title',
|
||||
);
|
||||
|
||||
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:
|
||||
/*
|
||||
This class serves the old fashioned string jobs which did not support ATE.
|
||||
Due to that, it should return nothing when ATE Scope is set.
|
||||
*/
|
||||
$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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Utils;
|
||||
|
||||
use WPML\TM\Menu\PostLinkUrl;
|
||||
use WPML_Post_Translation;
|
||||
|
||||
class ElementLink {
|
||||
|
||||
/** @var PostLinkUrl $postLinkUrl */
|
||||
private $postLinkUrl;
|
||||
|
||||
/** @var WPML_Post_Translation $postTranslation */
|
||||
private $postTranslation;
|
||||
|
||||
public function __construct( PostLinkUrl $postLinkUrl, WPML_Post_Translation $postTranslation ) {
|
||||
$this->postLinkUrl = $postLinkUrl;
|
||||
$this->postTranslation = $postTranslation;
|
||||
}
|
||||
|
||||
public function getOriginal( \WPML_TM_Post_Job_Entity $job ) {
|
||||
return $this->get( $job, $job->get_original_element_id() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_TM_Post_Job_Entity $job
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTranslation( \WPML_TM_Post_Job_Entity $job ) {
|
||||
if ( $this->isExternalType( $job->get_element_type_prefix() ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$translatedId = $this->postTranslation->element_id_in( $job->get_original_element_id(), $job->get_target_language() );
|
||||
|
||||
if ( $translatedId ) {
|
||||
return $this->get( $job, $translatedId );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_TM_Post_Job_Entity $job
|
||||
* @param string|null $elementId
|
||||
*
|
||||
* @return mixed|string|void
|
||||
*/
|
||||
private function get( \WPML_TM_Post_Job_Entity $job, $elementId = null ) {
|
||||
$elementId = $elementId ?: $job->get_target_language();
|
||||
$elementType = preg_replace( '/^' . $job->get_element_type_prefix() . '_/', '', $job->get_element_type() );
|
||||
|
||||
if ( $this->isExternalType( $job->get_element_type_prefix() ) ) {
|
||||
$tmPostLink = apply_filters( 'wpml_external_item_url', '', $elementId );
|
||||
} else {
|
||||
$tmPostLink = $this->postLinkUrl->viewLinkUrl( $elementId );
|
||||
}
|
||||
$tmPostLink = apply_filters(
|
||||
'wpml_document_view_item_link',
|
||||
$tmPostLink,
|
||||
'',
|
||||
$job,
|
||||
$job->get_element_type_prefix(),
|
||||
$elementType
|
||||
);
|
||||
|
||||
return $tmPostLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $elementTypePrefix
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isExternalType( $elementTypePrefix ) {
|
||||
return apply_filters( 'wpml_is_external', false, $elementTypePrefix );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Utils;
|
||||
|
||||
use function WPML\Container\make;
|
||||
use WPML_Post_Translation;
|
||||
|
||||
class ElementLinkFactory {
|
||||
|
||||
public static function create() {
|
||||
/**
|
||||
* @var WPML_Post_Translation $wpml_post_translations;
|
||||
*/
|
||||
global $wpml_post_translations;
|
||||
|
||||
return make(
|
||||
ElementLink::class,
|
||||
[ ':postTranslation' => $wpml_post_translations ]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user