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,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;
}
}

View File

@@ -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;
}
}

View File

@@ -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() );
}
}

View File

@@ -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() );
}
}

View 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();
}
}

View 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();

View File

@@ -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();

View 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();

View File

@@ -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();
}
}

View File

@@ -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
);
}
}