first commit
This commit is contained in:
60
wp-content/plugins/sitepress-multilingual-cms/API/ATE.php
Normal file
60
wp-content/plugins/sitepress-multilingual-cms/API/ATE.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Relation;
|
||||
use WPML\LIB\WP\Post;
|
||||
use WPML_TM_ATE_API;
|
||||
use WPML_TM_ATE_Jobs;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
class ATE {
|
||||
/** @var WPML_TM_ATE_API $ateApi */
|
||||
private $ateApi;
|
||||
|
||||
/** @var WPML_TM_ATE_Jobs $ateJobs */
|
||||
private $ateJobs;
|
||||
|
||||
public function __construct( WPML_TM_ATE_API $ateApi, WPML_TM_ATE_Jobs $ateJobs ) {
|
||||
$this->ateApi = $ateApi;
|
||||
$this->ateJobs = $ateJobs;
|
||||
}
|
||||
|
||||
public function checkJobStatus( $wpmlJobId ) {
|
||||
$ateJobId = $this->ateJobs->get_ate_job_id( $wpmlJobId );
|
||||
$response = $this->ateApi->get_job_status_with_priority( $ateJobId );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return wpml_collect( json_decode( wp_json_encode( $response ), true ) )->first(
|
||||
pipe(
|
||||
Obj::prop( 'ate_job_id' ),
|
||||
Relation::equals( $ateJobId )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function applyTranslation( $wpmlJobId, $postId, $xliffUrl ) {
|
||||
$ateJobId = $this->ateJobs->get_ate_job_id( $wpmlJobId );
|
||||
$xliffContent = $this->ateApi->get_remote_xliff_content( $xliffUrl, [ 'jobId' => $wpmlJobId, 'ateJobId' => $ateJobId ] );
|
||||
|
||||
if ( ! function_exists( 'wpml_tm_save_data' ) ) {
|
||||
require_once WPML_TM_PATH . '/inc/wpml-private-actions.php';
|
||||
}
|
||||
|
||||
$prevPostStatus = Post::getStatus( $postId );
|
||||
if ( $this->ateJobs->apply( $xliffContent ) ) {
|
||||
if ( Post::getStatus( $postId ) !== $prevPostStatus ) {
|
||||
Post::setStatus( $postId, $prevPostStatus );
|
||||
}
|
||||
$response = $this->ateApi->confirm_received_job( $ateJobId );
|
||||
|
||||
return ! is_wp_error( $response );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API\ATE;
|
||||
|
||||
use WPML\FP\Either;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\WordPress;
|
||||
use WPML\WP\OptionManager;
|
||||
use function WPML\Container\make;
|
||||
|
||||
class Account {
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getCredits() {
|
||||
return WordPress::handleError( make( \WPML_TM_AMS_API::class )->getCredits() )
|
||||
->filter( Fns::identity() )
|
||||
->map( Fns::tap( OptionManager::update( 'TM', 'Account::credits' ) ) )
|
||||
->alt( Either::of( [ 'error' => 'communication error' ] ) )
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $creditInfo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasActiveSubscription( array $creditInfo ) {
|
||||
return (bool) Obj::propOr( false, 'active_subscription', $creditInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $creditInfo
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getAvailableBalance( array $creditInfo ) {
|
||||
return (int) Obj::propOr( 0, 'available_balance', $creditInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAbleToTranslateAutomatically() {
|
||||
$creditInfo = OptionManager::getOr( [], 'TM', 'Account::credits' );
|
||||
|
||||
if ( ! array_key_exists( 'active_subscription', $creditInfo ) ) {
|
||||
$creditInfo = self::getCredits();
|
||||
}
|
||||
|
||||
return self::hasActiveSubscription( $creditInfo ) || self::getAvailableBalance( $creditInfo ) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API\ATE;
|
||||
|
||||
use WPML\TM\ATE\API\CachedATEAPI;
|
||||
use WPML\TM\ATE\API\CacheStorage\Transient;
|
||||
use function WPML\Container\make;
|
||||
|
||||
class CachedLanguageMappings extends LanguageMappings {
|
||||
/**
|
||||
* @return CachedATEAPI
|
||||
*/
|
||||
protected static function getATEAPI() {
|
||||
return new CachedATEAPI( make( \WPML_TM_ATE_API::class ), new Transient() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API\ATE;
|
||||
|
||||
use WPML\Element\API\Languages;
|
||||
use WPML\FP\Either;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Logic;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Maybe;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Relation;
|
||||
use WPML\FP\Wrapper;
|
||||
use WPML\LIB\WP\Option;
|
||||
use WPML\Element\API\Entity\LanguageMapping;
|
||||
use WPML\TM\ATE\API\CacheStorage\StaticVariable;
|
||||
use WPML\TM\ATE\API\CachedATEAPI;
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\curryN;
|
||||
use function WPML\FP\invoke;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
class LanguageMappings {
|
||||
const IGNORE_MAPPING_OPTION = 'wpml-languages-ignore-mapping';
|
||||
const IGNORE_MAPPING_ID = - 1;
|
||||
|
||||
public static function withCanBeTranslatedAutomatically( $languages = null ) {
|
||||
$fn = curryN( 1, function ( $languages ) {
|
||||
$ateAPI = static::getATEAPI();
|
||||
$targetCodes = Lst::pluck( 'code', Obj::values( $languages ) );
|
||||
$supportedLanguages = $ateAPI->get_languages_supported_by_automatic_translations( $targetCodes )->getOrElse( [] );
|
||||
|
||||
$areThereAnySupportedLanguages = Lst::find( Logic::isNotNull(), $supportedLanguages );
|
||||
$isSupportedCode = pipe( Obj::prop( Fns::__, $supportedLanguages ), Logic::isNotNull() );
|
||||
$isNotMarkedAsDontMap = Logic::complement( Lst::includes( Fns::__, Option::getOr( self::IGNORE_MAPPING_OPTION, [] ) ) );
|
||||
|
||||
$isDefaultCode = Relation::equals( Languages::getDefaultCode() );
|
||||
$isSupportedByAnyEngine = pipe(
|
||||
pipe( [ $ateAPI, 'get_language_details' ], invoke( 'getOrElse' )->with( [] ) ),
|
||||
Logic::anyPass( [ Obj::prop( 'ms_api_iso' ), Obj::prop( 'google_api_iso' ), Obj::prop( 'deepl_api_iso' ) ] )
|
||||
);
|
||||
$isDefaultLangSupported = Logic::anyPass( [ Fns::always( $areThereAnySupportedLanguages ), $isSupportedByAnyEngine ] );
|
||||
|
||||
$isSupported = pipe( Obj::prop( 'code' ), Logic::both(
|
||||
$isNotMarkedAsDontMap,
|
||||
Logic::ifElse( $isDefaultCode, $isDefaultLangSupported, $isSupportedCode )
|
||||
) );
|
||||
|
||||
return Fns::map( Obj::addProp( 'can_be_translated_automatically', $isSupported ), $languages );
|
||||
} );
|
||||
|
||||
return call_user_func_array( $fn, func_get_args() );
|
||||
}
|
||||
|
||||
public static function isCodeEligibleForAutomaticTranslations( $languageCode = null ) {
|
||||
$fn = Lst::includes( Fns::__, static::geCodesEligibleForAutomaticTranslations() );
|
||||
|
||||
return call_user_func_array( $fn, func_get_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LanguageMapping[] $mappings
|
||||
*/
|
||||
public static function get() {
|
||||
$ignoredMappings = Fns::map( function ( $code ) {
|
||||
return new LanguageMapping( $code, '', self::IGNORE_MAPPING_ID );
|
||||
}, Option::getOr( self::IGNORE_MAPPING_OPTION, [] ) );
|
||||
|
||||
$mappingInATE = Fns::map( function ( $record ) {
|
||||
return new LanguageMapping(
|
||||
Obj::prop( 'source_code', $record ),
|
||||
Obj::path( [ 'source_language', 'name' ], $record ),
|
||||
Obj::path( [ 'target_language', 'id' ], $record ),
|
||||
Obj::prop( 'target_code', $record )
|
||||
);
|
||||
}, static::getATEAPI()->get_language_mapping()->getOrElse( [] ) );
|
||||
|
||||
return Lst::concat( $ignoredMappings, $mappingInATE );
|
||||
}
|
||||
|
||||
public static function withMapping( $languages = null ) {
|
||||
$fn = curryN( 1, function ( $languages ) {
|
||||
$mapping = self::get();
|
||||
$findMappingByCode = function ( $language ) use ( $mapping ) {
|
||||
return Lst::find( invoke( 'matches' )->with( Obj::prop( 'code', $language ) ), $mapping );
|
||||
};
|
||||
|
||||
return Fns::map( Obj::addProp( 'mapping', $findMappingByCode ), $languages );
|
||||
} );
|
||||
|
||||
return call_user_func_array( $fn, func_get_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getAvailable() {
|
||||
$mapping = static::getATEAPI()->get_available_languages();
|
||||
|
||||
return Relation::sortWith( [ Fns::ascend( Obj::prop( 'name' ) ) ], $mapping );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param LanguageMapping[] $mappings
|
||||
*
|
||||
* @return Either
|
||||
*/
|
||||
public static function saveMapping( array $mappings ) {
|
||||
list( $ignoredMapping, $mappingSet ) = \wpml_collect( $mappings )->partition( Relation::propEq( 'targetId', self::IGNORE_MAPPING_ID ) );
|
||||
|
||||
$ignoredCodes = $ignoredMapping->pluck( 'sourceCode' )->toArray();
|
||||
Option::update( self::IGNORE_MAPPING_OPTION, $ignoredCodes );
|
||||
|
||||
$ateAPI = static::getATEAPI();
|
||||
if ( count( $ignoredCodes ) ) {
|
||||
$ateAPI->get_language_mapping()
|
||||
->map( Fns::filter( pipe( Obj::prop( 'source_code' ), Lst::includes( Fns::__, $ignoredCodes ) ) ) )
|
||||
->map( Lst::pluck( 'id' ) )
|
||||
->filter( Logic::complement( Logic::isEmpty() ) )
|
||||
->map( [ $ateAPI, 'remove_language_mapping' ] );
|
||||
}
|
||||
|
||||
return $ateAPI->create_language_mapping( $mappingSet->values()->toArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getLanguagesEligibleForAutomaticTranslations() {
|
||||
return Wrapper::of( Languages::getSecondaries() )
|
||||
->map( static::withCanBeTranslatedAutomatically() )
|
||||
->map( Fns::filter( Obj::prop( 'can_be_translated_automatically' ) ) )
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function geCodesEligibleForAutomaticTranslations() {
|
||||
return Lst::pluck( 'code', static::getLanguagesEligibleForAutomaticTranslations() );
|
||||
}
|
||||
|
||||
public static function hasTheSameMappingAsDefaultLang( $language = null ) {
|
||||
$fn = curryN( 1, function ( $language ) {
|
||||
$defaultLanguage = Lst::last( static::withMapping( [ Languages::getDefault() ] ) );
|
||||
$defaultLanguageMappingTargetCode = Obj::pathOr( Obj::prop( 'code', $defaultLanguage ), [ 'mapping', 'targetCode' ], $defaultLanguage );
|
||||
|
||||
return Obj::pathOr( null, [ 'mapping', 'targetCode' ], $language ) === $defaultLanguageMappingTargetCode;
|
||||
} );
|
||||
|
||||
return call_user_func_array( $fn, func_get_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CachedATEAPI
|
||||
*/
|
||||
protected static function getATEAPI() {
|
||||
return new CachedATEAPI( make( \WPML_TM_ATE_API::class ), StaticVariable::getInstance() );
|
||||
}
|
||||
}
|
||||
38
wp-content/plugins/sitepress-multilingual-cms/API/Basket.php
Normal file
38
wp-content/plugins/sitepress-multilingual-cms/API/Basket.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
use WPML\LIB\WP\User;
|
||||
use WPML\Setup\Option;
|
||||
use function WPML\Container\make;
|
||||
|
||||
class Basket {
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function shouldUse() {
|
||||
$doesNotHaveUserForEachLanguage = function () {
|
||||
global $sitepress;
|
||||
|
||||
$translator_records = make( \WPML_Translator_Records::class );
|
||||
$current_language = $sitepress->get_current_language();
|
||||
$active_languages = $sitepress->get_active_languages();
|
||||
unset( $active_languages[ $current_language ] );
|
||||
$active_languages = array_keys( $active_languages );
|
||||
foreach ( $active_languages as $active_language ) {
|
||||
$translators = $translator_records->get_users_with_languages( $current_language, [ $active_language ] );
|
||||
$number_of_translators = count( $translators );
|
||||
|
||||
if ( 1 !== $number_of_translators ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return ! \WPML_TM_ATE_Status::is_enabled_and_activated()
|
||||
|| \TranslationProxy::is_current_service_active_and_authenticated()
|
||||
|| ! Option::shouldTranslateEverything() && $doesNotHaveUserForEachLanguage();
|
||||
}
|
||||
|
||||
}
|
||||
68
wp-content/plugins/sitepress-multilingual-cms/API/Batch.php
Normal file
68
wp-content/plugins/sitepress-multilingual-cms/API/Batch.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
|
||||
use WPML\FP\Curryable;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\TM\Jobs\Dispatch\Messages;
|
||||
use function WPML\Container\make;
|
||||
|
||||
/**
|
||||
* Class Batch
|
||||
* @package WPML\TM\API
|
||||
*
|
||||
* @method static callable|void rollback( ...$batchName ) - Curried :: string->void
|
||||
*
|
||||
* It rollbacks just sent batch.
|
||||
*/
|
||||
class Batch {
|
||||
|
||||
use Curryable;
|
||||
|
||||
public static function init() {
|
||||
|
||||
self::curryN( 'rollback', 1, function ( $basketName ) {
|
||||
$batch = make( \WPML_Translation_Basket::class )->get_basket_batch( $basketName );
|
||||
$batch->cancel_all_jobs();
|
||||
$batch->clear_batch_data();
|
||||
} );
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static function sendPosts( Messages $messages, $batch, $sendFrom = Jobs::SENT_VIA_BASKET ) {
|
||||
$dispatchActions = function ( $batch ) use ( $sendFrom ) {
|
||||
$allowedTypes = array_keys( \TranslationProxy_Basket::get_basket_items_types() );
|
||||
|
||||
foreach ( $allowedTypes as $type ) {
|
||||
do_action( 'wpml_tm_send_' . $type . '_jobs', $batch, $type, $sendFrom );
|
||||
}
|
||||
};
|
||||
|
||||
self::send( $dispatchActions, [ $messages, 'showForPosts' ], $batch );
|
||||
}
|
||||
|
||||
public static function sendStrings( Messages $messages, $batch ) {
|
||||
$dispatchActions = function ( $batch ) {
|
||||
do_action( 'wpml_tm_send_st-batch_jobs', $batch, 'st-batch' );
|
||||
};
|
||||
|
||||
self::send( $dispatchActions, [ $messages, 'showForStrings' ], $batch );
|
||||
}
|
||||
|
||||
private static function send( callable $dispatchAction, callable $displayErrors, $batch ) {
|
||||
$dispatchAction( $batch );
|
||||
|
||||
$errors = wpml_load_core_tm()->messages_by_type( 'error' );
|
||||
|
||||
if ( $errors ) {
|
||||
self::rollback( $batch->get_basket_name() );
|
||||
|
||||
$displayErrors( Fns::map( Obj::prop( 'text' ), $errors ), 'error' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Batch::init();
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API\Job;
|
||||
|
||||
use WPML\Collect\Support\Traits\Macroable;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Obj;
|
||||
use function WPML\FP\curryN;
|
||||
|
||||
/**
|
||||
* @method static callable|int fromJobId( ...$job_id )
|
||||
* @method static callable|int|null fromRid( ...$rid )
|
||||
*/
|
||||
class Map {
|
||||
use Macroable;
|
||||
|
||||
private static $rid_to_jobId = [];
|
||||
|
||||
public static function init() {
|
||||
self::macro( 'fromJobId', curryN( 1, Fns::memorize( function ( $jobId ) {
|
||||
$rid = Obj::prop( $jobId, array_flip( array_filter( self::$rid_to_jobId ) ) );
|
||||
if ( $rid ) {
|
||||
return $rid;
|
||||
}
|
||||
|
||||
$rid = self::ridFromDB( $jobId );
|
||||
self::$rid_to_jobId[$rid] = $jobId;
|
||||
|
||||
return $rid;
|
||||
})));
|
||||
|
||||
self::macro( 'fromRid', curryN( 1, function ( $rid ) {
|
||||
$jobId = Obj::prop( $rid, self::$rid_to_jobId );
|
||||
if ( $jobId ) {
|
||||
return $jobId;
|
||||
}
|
||||
|
||||
$jobId = self::jobIdFromDB( $rid );
|
||||
self::$rid_to_jobId[ $rid ] = $jobId;
|
||||
|
||||
return $jobId;
|
||||
} ) );
|
||||
}
|
||||
|
||||
public static function jobIdFromDB( $rid ) {
|
||||
global $wpdb;
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT MAX(job_id) FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d",
|
||||
$rid
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function ridFromDB( $jobId ) {
|
||||
global $wpdb;
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT rid FROM {$wpdb->prefix}icl_translate_job WHERE job_id=%d",
|
||||
$jobId
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map::init();
|
||||
238
wp-content/plugins/sitepress-multilingual-cms/API/Jobs.php
Normal file
238
wp-content/plugins/sitepress-multilingual-cms/API/Jobs.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
use WPML\Collect\Support\Traits\Macroable;
|
||||
use WPML\Element\API\PostTranslations;
|
||||
use WPML\Element\API\TranslationsRepository;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Logic;
|
||||
use WPML\FP\Maybe;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Str;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\Settings\PostType\Automatic;
|
||||
use WPML\TM\API\ATE\LanguageMappings;
|
||||
use WPML\TM\API\Job\Map;
|
||||
use WPML\TM\Records\UpdateTranslationReviewStatus;
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\curryN;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
/**
|
||||
* Class Jobs
|
||||
* @package WPML\TM\API
|
||||
*
|
||||
* @method static callable|null|\stdClass getPostJob( ...$postId, ...$postType, ...$language ) : Curried:: int->string->string->null|\stdClass
|
||||
* @method static callable|null|\stdClass getElementJob( ...$postId, ...$elementType, ...$language ) : Curried:: int->string->string->null|\stdClass
|
||||
* @method static callable|null|\stdClass getTridJob( ...$trid, ...$language ) : Curried:: int->string->null|\stdClass
|
||||
* @method static callable|false|\stdClass get( ...$jobId ) : Curried:: int->false|\stdClass
|
||||
* @method static callable|void setStatus( ...$jobId, $jobStatus ) : Curried:: int->int->int
|
||||
* @method static callable|void setNotTranslatedStatus( ...$jobId ) : Curried:: int->int
|
||||
* @method static callable|void setReviewStatus( ...$jobId, $reviewStatus ) : Curried:: int->int->int
|
||||
* @method static callable|void setTranslationService( ...$jobId, $translationService ) : Curried:: int->int|string->int
|
||||
* @method static callable|void clearReviewStatus( ...$jobId ) : Curried:: int->int->int
|
||||
* @method static callable|array getTranslation( ...$job ) - Curried :: \stdClass->array
|
||||
* @method static callable|int getTranslatedPostId( ...$job ) - Curried :: \stdClass->int
|
||||
* @method static callable|string getEditUrl( ...$returnUrl, ...$job ) - Curried :: string->int->string
|
||||
* @method static callable|void incrementRetryCount( ...$jobId ) : Curried:: int->void
|
||||
* @method static callable|void setTranslated( ...$jobId, ...$status ) - Curried :: int->bool->int
|
||||
* @method static callable|void clearTranslated( ...$jobId ) - Curried :: int->int
|
||||
* @method static callable|int clearAutomatic( ...$jobId ) - Curried :: int->int
|
||||
* @method static callable|void delete( ...$jobId ) - Curried :: int->void
|
||||
* @method static callable|bool isEligibleForAutomaticTranslations( ...$jobId ) - Curried :: int->bool
|
||||
*/
|
||||
class Jobs {
|
||||
use Macroable;
|
||||
|
||||
const SENT_MANUALLY = 1;
|
||||
const SENT_VIA_BASKET = 2;
|
||||
const SENT_AUTOMATICALLY = 3;
|
||||
const SENT_FROM_REVIEW = 4;
|
||||
const SENT_RETRY = 5;
|
||||
|
||||
public static function init() {
|
||||
|
||||
self::macro( 'getPostJob', curryN( 3, function ( $postId, $postType, $language ) {
|
||||
return self::getElementJob( $postId, 'post_' . $postType, $language );
|
||||
} ) );
|
||||
|
||||
self::macro( 'getElementJob', curryN( 3, function ( $postId, $elementType, $language ) {
|
||||
global $sitepress;
|
||||
|
||||
$trid = $sitepress->get_element_trid( $postId, $elementType );
|
||||
|
||||
return self::getTridJob( $trid, $language );
|
||||
} ) );
|
||||
|
||||
self::macro( 'getTridJob', curryN( 2, function ( $trid, $language ) {
|
||||
$result = TranslationsRepository::getByTridAndLanguage( $trid, $language );
|
||||
if ( $result ) {
|
||||
return $result;
|
||||
}
|
||||
$jobId = wpml_load_core_tm()->get_translation_job_id( $trid, $language );
|
||||
|
||||
return $jobId ? wpml_tm_load_job_factory()->get_translation_job_as_stdclass( $jobId ) : null;
|
||||
} ) );
|
||||
|
||||
self::macro( 'get', curryN( 1, function ( $jobId ) {
|
||||
return wpml_tm_load_job_factory()->get_translation_job_as_stdclass( $jobId );
|
||||
} ) );
|
||||
|
||||
self::macro( 'setStatus', curryN( 2, function ( $jobId, $status ) {
|
||||
return self::updateTranslationStatusField( $jobId, 'status', $status );
|
||||
} ) );
|
||||
|
||||
self::macro( 'setNotTranslatedStatus', self::setStatus( Fns::__, ICL_TM_NOT_TRANSLATED ) );
|
||||
|
||||
self::macro( 'setReviewStatus', curryN( 2, function ( $jobId, $status ) {
|
||||
return self::updateTranslationStatusField( $jobId, 'review_status', $status, '%s' );
|
||||
} ) );
|
||||
|
||||
self::macro( 'setTranslationService', curryN( 2, function ( $jobId, $translationService ) {
|
||||
return self::updateTranslationStatusField( $jobId, 'translation_service', $translationService, '%s' );
|
||||
} ) );
|
||||
|
||||
self::macro( 'clearReviewStatus', self::setReviewStatus( Fns::__, null ) );
|
||||
|
||||
self::macro( 'incrementRetryCount', curryN( 1, function ( $jobId ) {
|
||||
$job = self::get( $jobId );
|
||||
|
||||
return $job ? self::updateTranslationStatusField(
|
||||
$jobId,
|
||||
'ate_comm_retry_count',
|
||||
$job->ate_comm_retry_count + 1 ) : null;
|
||||
} ) );
|
||||
|
||||
self::macro( 'getTranslation', curryN( 1, Fns::converge( Obj::prop(), [
|
||||
Obj::prop( 'language_code' ),
|
||||
pipe( Obj::prop( 'original_doc_id' ), Fns::memorize( PostTranslations::get() ) )
|
||||
] ) ) );
|
||||
|
||||
self::macro( 'getTranslatedPostId', curryN( 1, pipe( self::getTranslation(), Obj::prop( 'element_id' ) ) ) );
|
||||
|
||||
self::macro( 'getEditUrl', curryN( 2, function ( $returnUrl, $jobId ) {
|
||||
$jobEditUrl = admin_url( 'admin.php?page='
|
||||
. WPML_TM_FOLDER
|
||||
. '/menu/translations-queue.php&job_id='
|
||||
. $jobId
|
||||
. '&return_url=' . urlencode( $returnUrl ) );
|
||||
|
||||
return apply_filters( 'icl_job_edit_url', $jobEditUrl, $jobId );
|
||||
} ) );
|
||||
|
||||
self::macro( 'setTranslated', curryN( 2, function ( $jobId, $status ) {
|
||||
return self::updateTranslateJobField( $jobId, 'translated', $status );
|
||||
} ) );
|
||||
|
||||
self::macro( 'clearTranslated', self::setTranslated( Fns::__, false ) );
|
||||
|
||||
self::macro( 'clearAutomatic', curryN( 1, function ( $jobId ) {
|
||||
return self::updateTranslateJobField( $jobId, 'automatic', 0 );
|
||||
} ) );
|
||||
|
||||
self::macro( 'delete', curryN( 1, function ( $jobId ) {
|
||||
/** @var \wpdb $wpdb */
|
||||
global $wpdb;
|
||||
|
||||
$rid = Map::fromJobId( $jobId );
|
||||
$previousState = \WPML_TM_ICL_Translation_Status::makeByRid( $rid )
|
||||
->previous()
|
||||
->getOrElse( null );
|
||||
if ( $previousState ) {
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'icl_translation_status',
|
||||
Obj::pick( [ 'status', 'translator_id', 'needs_update', 'md5 ' ], $previousState ),
|
||||
[ 'rid' => $rid ]
|
||||
);
|
||||
} else {
|
||||
$wpdb->delete(
|
||||
$wpdb->prefix . 'icl_translation_status',
|
||||
[ 'rid' => $rid ],
|
||||
[ 'rid' => '%d' ]
|
||||
);
|
||||
}
|
||||
$wpdb->delete(
|
||||
$wpdb->prefix . 'icl_translate_job',
|
||||
[ 'job_id' => $jobId ],
|
||||
[ 'job_id' => '%d' ]
|
||||
);
|
||||
} ) );
|
||||
|
||||
self::macro( 'isEligibleForAutomaticTranslations', curryN( 1, Fns::memorize( function ( $wpmlJobId ) {
|
||||
$getPostType = pipe( Obj::prop( 'original_post_type' ), Str::replace( 'post_', '' ) );
|
||||
|
||||
return Maybe::of( $wpmlJobId )
|
||||
->map( Jobs::get() )
|
||||
->map( Logic::both(
|
||||
pipe( $getPostType, [ Automatic::class, 'shouldTranslate' ] ),
|
||||
pipe( Obj::prop( 'language_code' ), LanguageMappings::isCodeEligibleForAutomaticTranslations() )
|
||||
) )
|
||||
->getOrElse( false );
|
||||
} ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getCurrentUrl() {
|
||||
$protocol = ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != 'off' ) || Obj::prop( 'SERVER_PORT', $_SERVER ) == 443 ) ? "https://" : "http://";
|
||||
|
||||
return $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
|
||||
/**
|
||||
* It checks whether the job must be synced with ATE or not
|
||||
*
|
||||
* @param array{status: int, editor: string}|\stdClass{status: int, editor: string} $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function shouldBeATESynced( $job ) {
|
||||
$statuses = [ ICL_TM_WAITING_FOR_TRANSLATOR, ICL_TM_IN_PROGRESS ];
|
||||
|
||||
return Lst::includes( (int) Obj::prop( 'status', $job ), $statuses ) &&
|
||||
Obj::prop( 'editor', $job ) === \WPML_TM_Editors::ATE;
|
||||
}
|
||||
|
||||
private static function updateTranslationStatusField( $jobId, $fieldName, $newValue, $fieldType = '%d' ) {
|
||||
global $wpdb;
|
||||
|
||||
$newValueSqlString = null === $newValue ? 'NULL' : $fieldType;
|
||||
$unpreparedQuery = "
|
||||
UPDATE {$wpdb->prefix}icl_translation_status
|
||||
SET `{$fieldName}` = {$newValueSqlString}
|
||||
WHERE rid = (
|
||||
SELECT rid FROM {$wpdb->prefix}icl_translate_job
|
||||
WHERE job_id = %d
|
||||
)
|
||||
";
|
||||
|
||||
if ( null === $newValue ) {
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$query = $wpdb->prepare( $unpreparedQuery, $jobId );
|
||||
} else {
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$query = $wpdb->prepare( $unpreparedQuery, $newValue, $jobId );
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$wpdb->query( $query );
|
||||
|
||||
return $jobId;
|
||||
}
|
||||
|
||||
private static function updateTranslateJobField( $jobId, $fieldName, $newValue ) {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'icl_translate_job',
|
||||
[ $fieldName => $newValue ],
|
||||
[ 'job_id' => $jobId ]
|
||||
);
|
||||
|
||||
return $jobId;
|
||||
}
|
||||
}
|
||||
|
||||
Jobs::init();
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
use WPML\FP\Either;
|
||||
use WPML\TM\TranslationProxy\Services\AuthorizationFactory;
|
||||
|
||||
class TranslationServices {
|
||||
|
||||
/**
|
||||
* @var AuthorizationFactory
|
||||
*/
|
||||
private $authorizationFactory;
|
||||
|
||||
/**
|
||||
* @param AuthorizationFactory $authorizationFactory
|
||||
*/
|
||||
public function __construct( AuthorizationFactory $authorizationFactory ) {
|
||||
$this->authorizationFactory = $authorizationFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $suid
|
||||
*
|
||||
* @return Either
|
||||
*/
|
||||
public function selectBySUID( $suid ) {
|
||||
try {
|
||||
$service = \TranslationProxy_Service::get_service_by_suid( $suid );
|
||||
|
||||
return $this->selectByServiceId( $service->id );
|
||||
} catch ( \Exception $e ) {
|
||||
return Either::left( sprintf( __( 'Service with SUID=%s cannot be found', ' sitepress-multilingual-cms' ), $suid ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $serviceId
|
||||
*
|
||||
* @return Either
|
||||
*/
|
||||
public function selectByServiceId( $serviceId ) {
|
||||
$result = \TranslationProxy::select_service( $serviceId );
|
||||
|
||||
return \is_wp_error( $result ) ? Either::left( $result->get_error_message() ) : Either::of( $serviceId );
|
||||
}
|
||||
|
||||
public function deselect() {
|
||||
if ( \TranslationProxy::get_current_service_id() ) {
|
||||
\TranslationProxy::clear_preferred_translation_service();
|
||||
\TranslationProxy::deselect_active_service();
|
||||
}
|
||||
}
|
||||
|
||||
public function authorize( $apiToken ) {
|
||||
$authorization = $this->authorizationFactory->create();
|
||||
try {
|
||||
$authorization->authorize( (object) [ 'api_token' => $apiToken ] );
|
||||
|
||||
return Either::of( true );
|
||||
} catch ( \Exception $e ) {
|
||||
$authorization->deauthorize();
|
||||
|
||||
return Either::left( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|\TranslationProxy_Service
|
||||
*/
|
||||
public function getCurrentService() {
|
||||
$service = \TranslationProxy::get_current_service();
|
||||
|
||||
return ! is_wp_error( $service ) ? $service : null;
|
||||
}
|
||||
|
||||
public function isAnyActive() {
|
||||
return $this->getCurrentService() !== null;
|
||||
}
|
||||
|
||||
public function isAuthorized() {
|
||||
return \TranslationProxy::is_current_service_active_and_authenticated();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\API;
|
||||
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\User;
|
||||
|
||||
class Translators {
|
||||
/**
|
||||
* @return \WPML_Translator
|
||||
*/
|
||||
public static function getCurrent() {
|
||||
$translator = wpml_load_core_tm()->get_current_translator();
|
||||
|
||||
if ( ! $translator->ID ) {
|
||||
return $translator;
|
||||
}
|
||||
|
||||
if (
|
||||
empty( $translator->language_pairs )
|
||||
&& User::getCurrent()->has_cap( \WPML_Manage_Translations_Role::CAPABILITY )
|
||||
) {
|
||||
return Obj::assoc( 'language_pairs', \WPML_All_Language_Pairs::get(), $translator );
|
||||
}
|
||||
|
||||
return Obj::over(
|
||||
Obj::lensProp( 'language_pairs' ),
|
||||
Fns::map( Obj::keys() ),
|
||||
$translator
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user