first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
<?php
namespace WPML\TM\REST;
abstract class Base extends \WPML\Rest\Base {
/**
* @return string
*/
public function get_namespace() {
return 'wpml/tm/v1';
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace WPML\TM\REST;
use IWPML_Deferred_Action_Loader;
use IWPML_REST_Action_Loader;
use function WPML\Container\make;
class FactoryLoader implements IWPML_REST_Action_Loader, IWPML_Deferred_Action_Loader {
const REST_API_INIT_ACTION = 'rest_api_init';
/**
* @return string
*/
public function get_load_action() {
return self::REST_API_INIT_ACTION;
}
public function create() {
return [
\WPML\TM\ATE\REST\Sync::class => make( \WPML\TM\ATE\REST\Sync::class ),
\WPML\TM\ATE\REST\Download::class => make( \WPML\TM\ATE\REST\Download::class ),
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
class WPML_TM_REST_Apply_TP_Translation_Factory extends WPML_REST_Factory_Loader {
/**
* @return WPML_TM_REST_Apply_TP_Translation
*/
public function create() {
global $wpdb;
return new WPML_TM_REST_Apply_TP_Translation(
new WPML_TP_Apply_Translations(
wpml_tm_get_jobs_repository(),
new WPML_TP_Apply_Single_Job(
wpml_tm_get_tp_translations_repository(),
new WPML_TP_Apply_Translation_Strategies( $wpdb )
),
wpml_tm_get_tp_sync_jobs()
)
);
}
}

View File

@@ -0,0 +1,69 @@
<?php
class WPML_TM_REST_Apply_TP_Translation extends WPML_REST_Base {
/** @var WPML_TP_Apply_Translations */
private $apply_translations;
public function __construct( WPML_TP_Apply_Translations $apply_translations ) {
parent::__construct( 'wpml/tm/v1' );
$this->apply_translations = $apply_translations;
}
public function add_hooks() {
$this->register_routes();
}
public function register_routes() {
parent::register_route(
'/tp/apply-translations',
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'apply_translations' ),
)
);
}
/**
* @return WP_Error|int|array
*/
public function apply_translations( WP_REST_Request $request ) {
try {
$params = $request->get_json_params();
if ( $params ) {
if ( ! isset( $params['original_element_id'] ) ) {
$params = array_filter( $params, array( $this, 'validate_job' ) );
if ( ! $params ) {
return array();
}
}
}
return $this->apply_translations->apply( $params )->map( array( $this, 'map_jobs_to_array' ) );
} catch ( Exception $e ) {
return new WP_Error( 400, $e->getMessage() );
}
}
public function get_allowed_capabilities( WP_REST_Request $request ) {
return array( WPML_Manage_Translations_Role::CAPABILITY, WPML_Translator_Role::CAPABILITY );
}
public function map_jobs_to_array( WPML_TM_Job_Entity $job ) {
return [
'id' => $job->get_id(),
'type' => $job->get_type(),
'status' => $job->get_status(),
];
}
/**
* @param array $job
*
* @return bool
*/
private function validate_job( array $job ) {
return isset( $job['id'], $job['type'] ) && \WPML_TM_Job_Entity::is_type_valid( $job['type'] );
}
}

View File

@@ -0,0 +1,16 @@
<?php
class WPML_TM_REST_Batch_Sync_Factory extends WPML_REST_Factory_Loader {
/**
* @return WPML_TM_REST_Batch_Sync
*/
public function create() {
return new WPML_TM_REST_Batch_Sync(
new WPML_TP_Batch_Sync_API(
wpml_tm_get_tp_api_client(),
wpml_tm_get_tp_project(),
new WPML_TM_Log()
)
);
}
}

View File

@@ -0,0 +1,69 @@
<?php
class WPML_TM_REST_Batch_Sync extends WPML_REST_Base {
/** @var WPML_TP_Batch_Sync_API */
private $batch_sync_api;
public function __construct( WPML_TP_Batch_Sync_API $batch_sync_api ) {
parent::__construct( 'wpml/tm/v1' );
$this->batch_sync_api = $batch_sync_api;
}
public function add_hooks() {
$this->register_routes();
}
public function register_routes() {
parent::register_route(
'/tp/batches/sync',
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'init' ),
'args' => array(
'batchId' => array(
'required' => true,
'validate_callback' => array( $this, 'validate_batch_ids' ),
'sanitize_callback' => array( $this, 'sanitize_batch_ids' ),
),
),
)
);
parent::register_route(
'/tp/batches/status',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'check_progress' ),
)
);
}
public function init( WP_REST_Request $request ) {
try {
return $this->batch_sync_api->init_synchronization( $request->get_param( 'batchId' ) );
} catch ( Exception $e ) {
return new WP_Error( 500, $e->getMessage() );
}
}
public function check_progress() {
try {
return $this->batch_sync_api->check_progress();
} catch ( Exception $e ) {
return new WP_Error( 500, $e->getMessage() );
}
}
public function get_allowed_capabilities( WP_REST_Request $request ) {
return array( WPML_Manage_Translations_Role::CAPABILITY, WPML_Translator_Role::CAPABILITY );
}
public function validate_batch_ids( $batches ) {
return is_array( $batches );
}
public function sanitize_batch_ids( $batches ) {
return array_map( 'intval', $batches );
}
}

View File

@@ -0,0 +1,24 @@
<?php
class WPML_TM_Rest_Download_File {
public function send( $file_name, $content, $content_type = 'application/x-xliff+xml' ) {
add_filter( 'rest_pre_echo_response', array( $this, 'force_wp_rest_server_download' ) );
header( 'Content-Description: File Transfer' );
header( 'Content-Type: ' . $content_type );
header( 'Content-Disposition: attachment; filename="' . $file_name . '"' );
header( 'Content-Transfer-Encoding: binary' );
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
header( 'Pragma: public' );
header( 'Content-Length: ' . strlen( $content ) );
return $content;
}
public function force_wp_rest_server_download( $content ) {
echo $content;
exit;
}
}

View File

@@ -0,0 +1,27 @@
<?php
class WPML_TM_REST_Jobs_Factory extends WPML_REST_Factory_Loader {
/**
* @return WPML_TM_REST_Jobs
*/
public function create() {
global $sitepress, $wpdb;
return new WPML_TM_REST_Jobs(
wpml_tm_get_jobs_repository(),
new WPML_TM_Rest_Jobs_Criteria_Parser(),
new WPML_TM_Rest_Jobs_View_Model(
WPML_TM_Rest_Jobs_Translation_Service::create(),
new WPML_TM_Rest_Jobs_Element_Info(
new WPML_TM_Rest_Jobs_Package_Helper_Factory()
),
new WPML_TM_Rest_Jobs_Language_Names( $sitepress ),
new WPML_TM_Rest_Job_Translator_Name(),
new WPML_TM_Rest_Job_Progress()
),
new WPML_TP_Sync_Update_Job( $wpdb, $sitepress ),
new WPML_TM_Last_Picked_Up( $sitepress )
);
}
}

View File

@@ -0,0 +1,331 @@
<?php
/**
* WPML_TM_REST_Jobs class file.
*
* @package wpml-translation-management
*/
use WPML\FP\Obj;
use WPML\FP\Fns;
use function WPML\FP\pipe;
use function WPML\FP\partial;
use function WPML\FP\invoke;
/**
* Class WPML_TM_REST_Jobs
*/
class WPML_TM_REST_Jobs extends WPML_REST_Base {
const CAPABILITY = 'translate';
/**
* Jobs repository
*
* @var WPML_TM_Jobs_Repository
*/
private $jobs_repository;
/**
* Rest jobs criteria parser
*
* @var WPML_TM_Rest_Jobs_Criteria_Parser
*/
private $criteria_parser;
/**
* View model
*
* @var WPML_TM_Rest_Jobs_View_Model
*/
private $view_model;
/**
* Update jobs synchronisation
*
* @var WPML_TP_Sync_Update_Job
*/
private $update_jobs;
/**
* Last picked up jobs
*
* @var WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up
*/
private $wpml_tm_last_picked_up;
/**
* WPML_TM_REST_Jobs constructor.
*
* @param WPML_TM_Jobs_Repository $jobs_repository Jobs repository.
* @param WPML_TM_Rest_Jobs_Criteria_Parser $criteria_parser Rest jobs criteria parser.
* @param WPML_TM_Rest_Jobs_View_Model $view_model View model.
* @param WPML_TP_Sync_Update_Job $update_jobs Update jobs synchronisation.
* @param WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up Last picked up jobs.
*/
public function __construct(
WPML_TM_Jobs_Repository $jobs_repository,
WPML_TM_Rest_Jobs_Criteria_Parser $criteria_parser,
WPML_TM_Rest_Jobs_View_Model $view_model,
WPML_TP_Sync_Update_Job $update_jobs,
WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up
) {
parent::__construct( 'wpml/tm/v1' );
$this->jobs_repository = $jobs_repository;
$this->criteria_parser = $criteria_parser;
$this->view_model = $view_model;
$this->update_jobs = $update_jobs;
$this->wpml_tm_last_picked_up = $wpml_tm_last_picked_up;
}
/**
* Add hooks
*/
public function add_hooks() {
$this->register_routes();
}
/**
* Register routes
*/
public function register_routes() {
parent::register_route(
'/jobs',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_jobs' ),
'args' => array(
'local_job_ids' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'scope' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_TM_Jobs_Search_Params', 'is_valid_scope' ),
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'title' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'source_language' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'target_language' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'status' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'needs_update' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_TM_Jobs_Needs_Update_Param', 'is_valid' ),
),
'limit' => array(
'type' => 'integer',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'integer' ),
),
'offset' => array(
'type' => 'integer',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'integer' ),
),
'sorting' => array(
'validate_callback' => array( $this, 'validate_sorting' ),
),
'translated_by' => array(
'type' => 'string',
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
'sent_from' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'date' ),
),
'sent_to' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'date' ),
),
'deadline_from' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'date' ),
),
'deadline_to' => array(
'type' => 'string',
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'date' ),
),
),
)
);
parent::register_route(
'/jobs/assign',
array(
'methods' => 'POST',
'callback' => array( $this, 'assign_job' ),
'args' => array(
'jobId' => array(
'required' => true,
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'integer' ),
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'integer' ),
),
'type' => array(
'required' => false,
'validate_callback' => array( $this, 'validate_job_type' ),
),
'translatorId' => array(
'required' => true,
'validate_callback' => array( 'WPML_REST_Arguments_Validation', 'integer' ),
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'integer' ),
),
),
)
);
parent::register_route(
'/jobs/cancel',
array(
'methods' => 'POST',
'callback' => array( $this, 'cancel_jobs' ),
)
);
}
/**
* Get jobs
*
* @param WP_REST_Request $request REST request.
*
* @return array|WP_Error
*/
public function get_jobs( WP_REST_Request $request ) {
try {
$criteria = $this->criteria_parser->build_criteria( $request );
$model = $this->view_model->build(
$this->jobs_repository->get( $criteria ),
$this->jobs_repository->get_count( $criteria )
);
$model['last_picked_up_date'] = $this->wpml_tm_last_picked_up->get();
return $model;
} catch ( Exception $e ) {
return new WP_Error( 500, $e->getMessage() );
}
}
/**
* Assign job.
*
* @param WP_REST_Request $request REST request.
*
* @return array
* @throws \InvalidArgumentException Exception on error.
*/
public function assign_job( WP_REST_Request $request ) {
$result = null;
/**
* It can be job_id from icl_translate_job or id from icl_string_translations
*
* @var int $job_id
*/
$job_id = $request->get_param( 'jobId' );
$job_type = $request->get_param( 'type' ) ? $request->get_param( 'type' ) : WPML_TM_Job_Entity::POST_TYPE;
$translator_email = $request->get_param( 'translatorId' );
$user = get_user_by( 'ID', $translator_email );
if ( $user ) {
$assign_to = wpml_tm_assign_translation_job( $job_id, $user->ID, 'local', $job_type );
if ( $assign_to ) {
$result = array( 'assigned' => $assign_to );
}
}
return $result;
}
/**
* Cancel job
*
* @param WP_REST_Request $request REST request.
*
* @return array|WP_Error
*/
public function cancel_jobs( WP_REST_Request $request ) {
try {
// $validateParameter :: [id, type] -> bool
$validateParameter = pipe( Obj::prop( 'type' ), [ \WPML_TM_Job_Entity::class, 'is_type_valid' ] );
// $getJob :: [id, type] -> \WPML_TM_Job_Entity
$getJob = Fns::converge( [ $this->jobs_repository, 'get_job' ], [ Obj::prop( 'id' ), Obj::prop( 'type' ) ] );
// $jobEntityToArray :: \WPML_TM_Job_Entity -> [id, type]
$jobEntityToArray = function ( \WPML_TM_Job_Entity $job ) {
return [
'id' => $job->get_id(),
'type' => $job->get_type(),
];
};
return \wpml_collect( $request->get_json_params() )
->filter( $validateParameter )
->map( $getJob )
->filter()
->map( Fns::tap( invoke( 'set_status' )->with( ICL_TM_NOT_TRANSLATED ) ) )
->map( Fns::tap( [ $this->update_jobs, 'update_state' ] ) )
->map( Fns::tap( partial( 'do_action', 'wpml_tm_job_cancelled' ) ) )
->map( $jobEntityToArray )
->toArray();
} catch ( Exception $e ) {
return new WP_Error( 500, $e->getMessage() );
}
}
/**
* Get allowed capabilities
*
* @param WP_REST_Request $request REST request.
*
* @return array|string
*/
public function get_allowed_capabilities( WP_REST_Request $request ) {
return array( WPML_Manage_Translations_Role::CAPABILITY, WPML_Translator_Role::CAPABILITY );
}
/**
* Validate sorting
*
* @param mixed $sorting Sorting parameters.
*
* @return bool
*/
public function validate_sorting( $sorting ) {
if ( ! is_array( $sorting ) ) {
return false;
}
try {
foreach ( $sorting as $column => $asc_or_desc ) {
new WPML_TM_Jobs_Sorting_Param( $column, $asc_or_desc );
}
} catch ( Exception $e ) {
return false;
}
return true;
}
/**
* Validate job
*
* @param mixed $job Job.
*
* @return bool
*/
private function validate_job( $job ) {
return is_array( $job ) && isset( $job['id'] ) && isset( $job['type'] ) && \WPML_TM_Job_Entity::is_type_valid( $job['type'] );
}
}

View File

@@ -0,0 +1,10 @@
<?php
class WPML_TM_REST_Settings_Translation_Editor_Factory extends WPML_REST_Factory_Loader {
public function create() {
global $sitepress;
return new WPML_TM_REST_Settings_Translation_Editor( $sitepress );
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_REST_Settings_Translation_Editor extends WPML_REST_Base {
private $sitepress;
/**
* WPML_TM_REST_AMS_Clients constructor.
*
* @param SitePress $sitepress
*/
public function __construct( SitePress $sitepress ) {
parent::__construct( 'wpml/tm/v1' );
$this->sitepress = $sitepress;
}
function add_hooks() {
$this->register_routes();
}
function register_routes() {
parent::register_route(
'/settings/translation_editor',
array(
'methods' => 'POST',
'callback' => array( $this, 'set_translation_editor' ),
'args' => array(
'editor_type' => array(
'required' => true,
'validate_callback' => array( $this, 'validate_editor_type' ),
'sanitize_callback' => array( 'WPML_REST_Arguments_Sanitation', 'string' ),
),
),
)
);
}
public function get_allowed_capabilities( WP_REST_Request $request ) {
return array( WPML_Manage_Translations_Role::CAPABILITY, 'manage_options' );
}
/**
* @param WP_REST_Request $request
*
* @return array|WP_Error
*/
public function set_translation_editor( WP_REST_Request $request ) {
$editor_type = $request->get_param( 'editor_type' );
$tm_settings = $this->sitepress->get_setting( 'translation-management', array() );
$tm_settings['doc_translation_method'] = $editor_type;
$result = $this->sitepress->set_setting( 'translation-management', $tm_settings, true );
return array( 'saved' => (int) $result );
}
public function validate_editor_type( $value, $request, $key ) {
$valid_types = array(
strtoupper( (string) ICL_TM_TMETHOD_MANUAL ),
strtoupper( (string) ICL_TM_TMETHOD_EDITOR ),
strtoupper( ICL_TM_TMETHOD_ATE ),
);
return in_array( strtoupper( $value ), $valid_types, true );
}
}

View File

@@ -0,0 +1,14 @@
<?php
class WPML_TM_REST_TP_XLIFF_Factory extends WPML_REST_Factory_Loader {
public function create() {
return new WPML_TM_REST_TP_XLIFF(
new WPML_TP_Translations_Repository(
wpml_tm_get_tp_xliff_api(),
wpml_tm_get_jobs_repository()
),
new WPML_TM_Rest_Download_File()
);
}
}

View File

@@ -0,0 +1,100 @@
<?php
class WPML_TM_REST_TP_XLIFF extends WPML_REST_Base {
/** @var WPML_TP_Translations_Repository */
private $translation_repository;
/** @var WPML_TM_Rest_Download_File */
private $download_file;
public function __construct(
WPML_TP_Translations_Repository $translation_repository,
WPML_TM_Rest_Download_File $download_file
) {
parent::__construct( 'wpml/tm/v1' );
$this->translation_repository = $translation_repository;
$this->download_file = $download_file;
}
public function add_hooks() {
$this->register_routes();
}
public function register_routes() {
parent::register_route(
'/tp/xliff/download/(?P<job_id>\d+)/(?P<job_type>\w+)',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_job_translations_from_tp' ),
'args' => array(
'job_id' => array(
'required' => true,
),
'job_type' => array(
'required' => true,
'validate_callback' => array( $this, 'validate_job_type' ),
),
'json' => array(
'type' => 'boolean',
),
),
)
);
}
/**
* @param WP_REST_Request $request
*
* @return array|string|WP_Error
*/
public function get_job_translations_from_tp( WP_REST_Request $request ) {
try {
if ( $request->get_param( 'json' ) ) {
return $this->translation_repository->get_job_translations(
$request->get_param( 'job_id' ),
$request->get_param( 'job_type' )
)->to_array();
} else {
return $this->download_job_translation( $request );
}
} catch ( Exception $e ) {
return new WP_Error( 400, $e->getMessage() );
}
}
/**
* @param WP_REST_Request $request
*
* @return string
*/
private function download_job_translation( WP_REST_Request $request ) {
try {
$content = $this->translation_repository->get_job_translations(
$request->get_param( 'job_id' ),
$request->get_param( 'job_type' ),
false
);
} catch ( WPML_TP_API_Exception $e ) {
return new WP_Error( 500, $e->getMessage() );
}
$file_name = sprintf( 'job-%d.xliff', $request->get_param( 'job_id' ) );
return $this->download_file->send( $file_name, $content );
}
public function get_allowed_capabilities( WP_REST_Request $request ) {
return array( WPML_Manage_Translations_Role::CAPABILITY, WPML_Translator_Role::CAPABILITY );
}
public function validate_job_type( $value ) {
return in_array(
$value,
array(
WPML_TM_Job_Entity::POST_TYPE,
WPML_TM_Job_Entity::STRING_TYPE,
WPML_TM_Job_Entity::PACKAGE_TYPE,
)
);
}
}

View File

@@ -0,0 +1,45 @@
<?php
class WPML_TM_Rest_Job_Progress {
/** @var wpdb */
private $wpdb;
public function __construct() {
global $wpdb;
$this->wpdb = $wpdb;
}
/**
* @param WPML_TM_Job_Entity $job
*
* @return string
*/
public function get( WPML_TM_Job_Entity $job ) {
if ( $job->get_translation_service() !== 'local' ) {
return '';
}
if ( $job->get_status() !== ICL_TM_IN_PROGRESS ) {
return '';
}
if ( $job->get_type() === WPML_TM_Job_Entity::STRING_TYPE ) {
return '';
}
$sql = "
SELECT field_finished FROM {$this->wpdb->prefix}icl_translate translate
INNER JOIN {$this->wpdb->prefix}icl_translate_job translate_job ON translate_job.job_id = translate.job_id
INNER JOIN {$this->wpdb->prefix}icl_translation_status translation_status ON translation_status.rid = translate_job.rid
WHERE translation_status.rid = %d AND translate.field_translate = 1 AND LENGTH(translate.field_data) > 0
";
$sql = $this->wpdb->prepare( $sql, $job->get_id() );
$elements = $this->wpdb->get_col( $sql );
$translated = array_filter( $elements );
$percentage = (int) ( count( $translated ) / count( $elements ) * 100 );
return sprintf( _x( '%s completed', 'Translation jobs list', 'wpml-transation-manager' ), $percentage . '%' );
}
}

View File

@@ -0,0 +1,14 @@
<?php
class WPML_TM_Rest_Job_Translator_Name {
public function get( $translator_id ) {
$user = get_user_by( 'id', $translator_id );
if ( $user instanceof WP_User ) {
return $user->display_name;
} else {
return '';
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
class WPML_TM_Rest_Jobs_Columns {
/**
* @return array
*/
public static function get_columns() {
return array(
'id' => __( 'ID', 'wpml-translation-management' ),
'title' => __( 'Title', 'wpml-translation-management' ),
'languages' => __( 'Languages', 'wpml-translation-management' ),
'batch_name' => __( 'Batch name', 'wpml-translation-management' ),
'translator' => __( 'Translated by', 'wpml-translation-management' ),
'sent_date' => __( 'Sent on', 'wpml-translation-management' ),
'deadline' => __( 'Deadline', 'wpml-translation-management' ),
'status' => __( 'Status', 'wpml-translation-management' ),
);
}
/**
* @return array
*/
public static function get_sortable() {
return array(
'id' => __( 'ID', 'wpml-translation-management' ),
'title' => __( 'Title', 'wpml-translation-management' ),
'batch_name' => __( 'Batch name', 'wpml-translation-management' ),
'language' => __( 'Language', 'wpml-translation-management' ),
'sent_date' => __( 'Sent on', 'wpml-translation-management' ),
'deadline_date' => __( 'Deadline', 'wpml-translation-management' ),
'status' => __( 'Status', 'wpml-translation-management' ),
);
}
}

View File

@@ -0,0 +1,115 @@
<?php
class WPML_TM_Rest_Jobs_Criteria_Parser {
/**
* @param WP_REST_Request $request
*
* @return WPML_TM_Jobs_Search_Params
*/
public function build_criteria( WP_REST_Request $request ) {
$params = new WPML_TM_Jobs_Search_Params();
$params = $this->set_scope( $params, $request );
$params = $this->set_pagination( $params, $request );
$params = $this->set_filters( $params, $request );
$params = $this->set_sorting( $params, $request );
return $params;
}
/**
* @param WPML_TM_Jobs_Search_Params $params
* @param WP_REST_Request $request
*
* @return WPML_TM_Jobs_Search_Params
*/
private function set_scope( WPML_TM_Jobs_Search_Params $params, WP_REST_Request $request ) {
$scope = $request->get_param( 'scope' );
if ( WPML_TM_Jobs_Search_Params::is_valid_scope( $scope ) ) {
$params->set_scope( $scope );
}
return $params;
}
/**
* @param WPML_TM_Jobs_Search_Params $params
* @param WP_REST_Request $request
*
* @return WPML_TM_Jobs_Search_Params
*/
private function set_pagination( WPML_TM_Jobs_Search_Params $params, WP_REST_Request $request ) {
$limit = (int) $request->get_param( 'limit' );
if ( $limit > 0 ) {
$params->set_limit( $limit );
$offset = (int) $request->get_param( 'offset' );
if ( $offset > 0 ) {
$params->set_offset( $offset );
}
}
return $params;
}
private function set_filters( WPML_TM_Jobs_Search_Params $params, WP_REST_Request $request ) {
foreach ( [ 'source_language', 'translated_by' ] as $key ) {
$value = (string) $request->get_param( $key );
if ( $value ) {
$params->{'set_' . $key}( $value );
}
}
foreach ( [ 'local_job_ids', 'title', 'target_language', 'status', 'batch_name' ] as $key ) {
$value = (string) $request->get_param( $key );
if ( strlen( $value ) ) {
$params->{'set_' . $key}( explode( ',', $value ) );
}
}
if ( $request->get_param( 'needs_update' ) ) {
$params->set_needs_update( new WPML_TM_Jobs_Needs_Update_Param( $request->get_param( 'needs_update' ) ) );
}
$date_range_values = array( 'sent', 'deadline' );
foreach ( $date_range_values as $date_range_value ) {
$from = $request->get_param( $date_range_value . '_from' );
$to = $request->get_param( $date_range_value . '_to' );
if ( $from || $to ) {
$from = $from ? new DateTime( $from ) : $from;
$to = $to ? new DateTime( $to ) : $to;
if ( $from && $to && $from >= $to ) {
continue;
}
$params->{'set_' . $date_range_value}( new WPML_TM_Jobs_Date_Range( $from, $to ) );
}
}
return $params;
}
private function set_sorting( WPML_TM_Jobs_Search_Params $params, WP_REST_Request $request ) {
$sorting = $request->get_param( 'sorting' );
if ( $sorting ) {
$params->set_sorting( $this->build_sorting_params( $sorting ) );
}
return $params;
}
/**
* @param array $request_param
*
* @return WPML_TM_Jobs_Sorting_Param[]
*/
private function build_sorting_params( array $request_param ) {
return \wpml_collect( $request_param )->map(
function ( $direction, $column ) {
return new WPML_TM_Jobs_Sorting_Param( $column, $direction );
}
)->toArray();
}
}

View File

@@ -0,0 +1,110 @@
<?php
class WPML_TM_Rest_Jobs_Element_Info {
/** @var WPML_TM_Rest_Jobs_Package_Helper_Factory */
private $package_helper_factory;
/**
* @param WPML_TM_Rest_Jobs_Package_Helper_Factory $package_helper_factory
*/
public function __construct( WPML_TM_Rest_Jobs_Package_Helper_Factory $package_helper_factory ) {
$this->package_helper_factory = $package_helper_factory;
}
/**
* @param WPML_TM_Job_Entity $job
*
* @return array
*/
public function get( WPML_TM_Job_Entity $job ) {
$type = $job->get_type();
$id = $job->get_original_element_id();
$result = [];
switch ( $type ) {
case WPML_TM_Job_Entity::POST_TYPE:
$result = $this->get_for_post( $id );
break;
case WPML_TM_Job_Entity::STRING_TYPE:
case WPML_TM_Job_Entity::STRING_BATCH:
$result = $this->get_for_title( $job->get_title() );
break;
case WPML_TM_Job_Entity::PACKAGE_TYPE:
$result = $this->get_for_package( $id );
break;
}
if ( empty( $result ) ) {
$result = array(
'name' => '',
'url' => null,
);
do_action( 'wpml_tm_jobs_log', 'WPML_TM_Rest_Jobs_Element_Info::get', array( $id, $type ), 'Empty result' );
}
$result['url'] = apply_filters( 'wpml_tm_job_list_element_url', $result['url'], $id, $type );
return $result;
}
/**
* @param int $id
*
* @return array
*/
private function get_for_post( $id ) {
$result = array();
$post = get_post( $id );
if ( $post ) {
$permalink = get_permalink( $post );
$result = array(
'name' => $post->post_title,
'url' => $permalink,
);
}
return $result;
}
/**
* @param int $id
*
* @return array
*/
private function get_for_package( $id ) {
$result = array();
$helper = $this->package_helper_factory->create();
if ( ! $helper ) {
return array(
'name' => __( 'String package job', 'wpml-translation-management' ),
'url' => null,
);
}
$package = $helper->get_translatable_item( null, $id );
if ( $package ) {
$result = array(
'name' => $package->title,
'url' => $package->edit_link,
);
}
return $result;
}
/**
* @param string $title
*
* @return array
*/
private function get_for_title( $title ) {
return [
'name' => $title,
'url' => null,
];
}
}

View File

@@ -0,0 +1,40 @@
<?php
class WPML_TM_Rest_Jobs_Language_Names {
/** @var SitePress */
private $sitepress;
/** @var array */
private $active_languages;
/**
* @param SitePress $sitepress
*/
public function __construct( SitePress $sitepress ) {
$this->sitepress = $sitepress;
}
/**
* @param string $code
*
* @return string
*/
public function get( $code ) {
$languages = $this->get_active_languages();
return isset( $languages[ $code ] ) ? $languages[ $code ] : $code;
}
/**
* @return array
*/
public function get_active_languages() {
if ( ! $this->active_languages ) {
foreach ( $this->sitepress->get_active_languages() as $code => $data ) {
$this->active_languages[ $code ] = $data['display_name'];
}
}
return $this->active_languages;
}
}

View File

@@ -0,0 +1,21 @@
<?php
class WPML_TM_Rest_Jobs_Package_Helper_Factory {
/** @var WPML_Package_Helper */
private $package_helper = false;
/**
* @return null|WPML_Package_Helper
*/
public function create() {
if ( false === $this->package_helper ) {
if ( defined( 'WPML_ST_VERSION' ) && class_exists( 'WPML_Package_Helper' ) ) {
$this->package_helper = new WPML_Package_Helper();
} else {
$this->package_helper = null;
}
}
return $this->package_helper;
}
}

View File

@@ -0,0 +1,61 @@
<?php
class WPML_TM_Rest_Jobs_Translation_Service {
/** @var WPML_WP_Cache */
private $cache;
/**
* @param WPML_WP_Cache $cache
*/
public function __construct( WPML_WP_Cache $cache ) {
$this->cache = $cache;
}
/**
* @param string|int $service_id
*
* @return string
*/
public function get_name( $service_id ) {
$name = '';
if ( is_numeric( $service_id ) ) {
$service = $this->get_translation_service( (int) $service_id );
if ( $service ) {
$name = $service->name;
}
} else {
$name = __( 'Local', 'wpml-translation-management' );
}
return $name;
}
private function get_translation_service( $service_id ) {
$key = 'service_' . $service_id;
$found = false;
$service = $this->cache->get( $key, $found );
if ( ! $found ) {
$current_service = TranslationProxy::get_current_service();
if ( $current_service && $current_service->id === $service_id ) {
$service = $current_service;
} else {
$service = TranslationProxy_Service::get_service( $service_id );
}
$this->cache->set( $key, $service );
}
return $service;
}
/**
* @return WPML_TM_Rest_Jobs_Translation_Service
*/
public static function create() {
$cache = new WPML_WP_Cache( 'wpml-tm-services' );
return new WPML_TM_Rest_Jobs_Translation_Service( $cache );
}
}

View File

@@ -0,0 +1,98 @@
<?php
class WPML_TM_Rest_Jobs_View_Model {
/** @var WPML_TM_Rest_Jobs_Translation_Service */
private $translation_service;
/** @var WPML_TM_Rest_Jobs_Element_Info */
private $element_info;
/** @var WPML_TM_Rest_Jobs_Language_Names */
private $language_names;
/** @var WPML_TM_Rest_Job_Translator_Name */
private $translator_name;
/** @var WPML_TM_Rest_Job_Progress */
private $progress;
/**
* @param WPML_TM_Rest_Jobs_Translation_Service $translation_service
* @param WPML_TM_Rest_Jobs_Element_Info $element_info
* @param SitePress $sitepress
*/
public function __construct(
WPML_TM_Rest_Jobs_Translation_Service $translation_service,
WPML_TM_Rest_Jobs_Element_Info $element_info,
WPML_TM_Rest_Jobs_Language_Names $language_names,
WPML_TM_Rest_Job_Translator_Name $translator_name,
WPML_TM_Rest_Job_Progress $progress
) {
$this->translation_service = $translation_service;
$this->element_info = $element_info;
$this->language_names = $language_names;
$this->translator_name = $translator_name;
$this->progress = $progress;
}
/**
* @param WPML_TM_Jobs_Collection $jobs
* @param int $total_jobs_count
*
* @return array
*/
public function build( WPML_TM_Jobs_Collection $jobs, $total_jobs_count ) {
$result = array( 'jobs' => array() );
foreach ( $jobs as $job ) {
$result['jobs'][] = $this->map_job( $job );
}
$result['total'] = $total_jobs_count;
return $result;
}
/**
* @param WPML_TM_Job_Entity $job
*
* @return array
*/
private function map_job( WPML_TM_Job_Entity $job ) {
$extra_data = array();
if ( $job instanceof WPML_TM_Post_Job_Entity ) {
$extra_data['icl_translate_job_id'] = $job->get_translate_job_id();
}
return array(
'id' => $job->get_id(),
'type' => $job->get_type(),
'tp_id' => $job->get_tp_id(),
'status' => $job->get_status(),
'needs_update' => $job->does_need_update(),
'language_codes' => array(
'source' => $job->get_source_language(),
'target' => $job->get_target_language(),
),
'languages' => array(
'source' => $this->language_names->get( $job->get_source_language() ),
'target' => $this->language_names->get( $job->get_target_language() ),
),
'translation_service_id' => $job->get_translation_service(),
'translation_service' => $this->translation_service->get_name( $job->get_translation_service() ),
'sent_date' => $job->get_sent_date()->format( 'Y-m-d' ),
'deadline' => $job->get_deadline() ? $job->get_deadline()->format( 'Y-m-d' ) : '',
'ts_status' => (string) $job->get_ts_status(),
'element' => $this->element_info->get( $job ),
'translator_name' => $job->get_translator_id() ? $this->translator_name->get( $job->get_translator_id() ) : '',
'progress' => $this->progress->get( $job ),
'batch' => array(
'id' => $job->get_batch()->get_id(),
'name' => $job->get_batch()->get_name(),
'tp_id' => $job->get_batch()->get_tp_id(),
),
'extra_data' => $extra_data,
);
}
}