first commit
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
use WPML\FP\Curryable;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Str;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
/**
|
||||
* Class BatchBuilder
|
||||
*
|
||||
* @method static callable|\WPML_TM_Translation_Batch|null buildPostsBatch( ...$data, ...$sourceLanguage, ...$translators ) - Curried :: array->string->array->\WPML_TM_Translation_Batch|null
|
||||
* @method static callable|\WPML_TM_Translation_Batch|null buildStringsBatch( ...$data, ...$sourceLanguage, ...$translators ) - Curried :: array->string->array->\WPML_TM_Translation_Batch|null
|
||||
* @method static callable|array getPostElements( ...$postsForTranslation, ...$sourceLanguage ) - Curried :: array->string->array
|
||||
* @method static callable|array getStringElements( ...$stringsForTranslation, ...$sourceLanguage ) - Curried :: array->string->array
|
||||
*/
|
||||
class BatchBuilder {
|
||||
use Curryable;
|
||||
|
||||
public static function init() {
|
||||
|
||||
self::curryN( 'buildPostsBatch', 3, function ( array $data, $sourceLanguage, array $translators ) {
|
||||
return self::build(
|
||||
'Translation-%s-%s',
|
||||
self::getPostElements(),
|
||||
$data,
|
||||
$sourceLanguage,
|
||||
$translators
|
||||
);
|
||||
} );
|
||||
|
||||
self::curryN( 'buildStringsBatch', 3, function ( array $data, $sourceLanguage, array $translators ) {
|
||||
return self::build(
|
||||
'Strings translation-%s-%s',
|
||||
self::getStringElements(),
|
||||
$data,
|
||||
$sourceLanguage,
|
||||
$translators
|
||||
);
|
||||
} );
|
||||
|
||||
self::curryN( 'getPostElements', 2, function ( $postsForTranslation, $sourceLanguage ) {
|
||||
$elements = [];
|
||||
|
||||
foreach ( $postsForTranslation as $postId => $postData ) {
|
||||
$elements[] = new \WPML_TM_Translation_Batch_Element(
|
||||
$postId,
|
||||
$postData['type'],
|
||||
$sourceLanguage,
|
||||
array_fill_keys( $postData['target_languages'], \TranslationManagement::TRANSLATE_ELEMENT_ACTION ),
|
||||
Obj::propOr( [], 'media', $postData )
|
||||
);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
} );
|
||||
|
||||
self::curryN( 'getStringElements', 2, function ( $stringsForTranslation, $sourceLanguage ) {
|
||||
$elements = [];
|
||||
|
||||
$setTranslateAction = pipe(
|
||||
Fns::map( pipe( Lst::makePair( \TranslationManagement::TRANSLATE_ELEMENT_ACTION ), Lst::reverse() ) ),
|
||||
Lst::fromPairs()
|
||||
);
|
||||
|
||||
foreach ( $stringsForTranslation as $stringId => $targetLanguages ) {
|
||||
$elements[] = new \WPML_TM_Translation_Batch_Element(
|
||||
$stringId,
|
||||
'string',
|
||||
$sourceLanguage,
|
||||
$setTranslateAction( $targetLanguages )
|
||||
);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $batchNameTemplate
|
||||
* @param callable $buildElementStrategy
|
||||
* @param array $data
|
||||
* @param string $sourceLanguage
|
||||
* @param array $translators
|
||||
*
|
||||
* @return \WPML_TM_Translation_Batch|null
|
||||
*/
|
||||
private static function build( $batchNameTemplate, callable $buildElementStrategy, array $data, $sourceLanguage, array $translators ) {
|
||||
$targetLanguagesString = pipe( Lst::flatten(), 'array_unique', Lst::join( '|' ) );
|
||||
$idsHash = pipe( 'array_keys', Lst::join( '-' ), 'md5', Str::sub( 16 ) );
|
||||
|
||||
$batchName = sprintf(
|
||||
$batchNameTemplate,
|
||||
$targetLanguagesString( $data ),
|
||||
$idsHash( $data )
|
||||
);
|
||||
|
||||
$elements = apply_filters(
|
||||
'wpml_tm_batch_factory_elements',
|
||||
$buildElementStrategy( $data, $sourceLanguage ),
|
||||
$batchName
|
||||
);
|
||||
|
||||
return $elements ? new \WPML_TM_Translation_Batch( $elements, $batchName, $translators, null ) : null;
|
||||
}
|
||||
}
|
||||
|
||||
BatchBuilder::init();
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
use Exception;
|
||||
use WPML\API\Sanitize;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\User;
|
||||
use WPML\TM\API\Jobs;
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
abstract class Elements {
|
||||
/**
|
||||
* @param callable $sendBatch
|
||||
* @param Messages $messages
|
||||
* @param callable $buildBatch
|
||||
* @param array $data
|
||||
* @param string $type
|
||||
*/
|
||||
public static function dispatch(
|
||||
callable $sendBatch,
|
||||
Messages $messages,
|
||||
callable $buildBatch,
|
||||
$data,
|
||||
$type
|
||||
) {
|
||||
$translationActions = filter_var_array(
|
||||
Obj::propOr( [], 'tr_action', $data ),
|
||||
FILTER_SANITIZE_NUMBER_INT
|
||||
);
|
||||
$sourceLanguage = Sanitize::stringProp( 'translate_from', $data );
|
||||
|
||||
$targetLanguages = self::getTargetLanguages( $translationActions );
|
||||
$translators = self::getTranslators( $sourceLanguage, $targetLanguages );
|
||||
|
||||
$elementsForTranslation = self::getElements( $messages, $data[ $type ], $targetLanguages );
|
||||
|
||||
$batch = $buildBatch( $elementsForTranslation, $sourceLanguage, $translators );
|
||||
$batch && $sendBatch( $messages, $batch );
|
||||
}
|
||||
|
||||
private static function getTargetLanguages( $translationActions ) {
|
||||
return array_keys(
|
||||
array_filter( $translationActions, function ( $action ) {
|
||||
return (int) $action === \TranslationManagement::TRANSLATE_ELEMENT_ACTION;
|
||||
} )
|
||||
);
|
||||
}
|
||||
|
||||
private static function getTranslators( $sourceLanguage, $targetLanguages ) {
|
||||
$records = make( \WPML_Translator_Records::class );
|
||||
$getTranslator = function ( $lang ) use ( $sourceLanguage, $records ) {
|
||||
$translators = $records->get_users_with_languages( $sourceLanguage, [ $lang ] );
|
||||
return count( $translators ) ? $translators[0] : User::getCurrent();
|
||||
};
|
||||
|
||||
$translators = wpml_collect( $targetLanguages )
|
||||
->map( $getTranslator )
|
||||
->map( Obj::prop( 'ID') );
|
||||
|
||||
return Lst::zipObj( $targetLanguages, $translators->toArray() );
|
||||
}
|
||||
|
||||
private static function getElements(
|
||||
Messages $messages,
|
||||
$data,
|
||||
$targetLanguages
|
||||
) {
|
||||
$getElementsToTranslate = pipe( Fns::filter( Obj::prop( 'checked' ) ), Lst::keyBy( 'checked' ) );
|
||||
$elementsIds = $getElementsToTranslate( $data );
|
||||
|
||||
list( $elementsToTranslation, $ignoredElementsMessages ) = static::filterElements(
|
||||
$messages,
|
||||
$elementsIds,
|
||||
$targetLanguages
|
||||
);
|
||||
|
||||
$messages->showForPosts( $ignoredElementsMessages, 'information' );
|
||||
|
||||
return array_filter( $elementsToTranslation, pipe( Obj::prop( 'target_languages' ), Lst::length() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $elementId
|
||||
* @param string $elementType
|
||||
* @param string $language
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function hasInProgressJob( $elementId, $elementType, $language ) {
|
||||
$job = Jobs::getElementJob( $elementId, $elementType, $language );
|
||||
|
||||
return $job && ICL_TM_IN_PROGRESS === (int) $job->status && ! $job->needs_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Messages $messages
|
||||
* @param array $elementsData
|
||||
* @param array $targetLanguages
|
||||
*
|
||||
* phpcs:disable Squiz.Commenting.FunctionComment.InvalidNoReturn
|
||||
* @return array
|
||||
* @throws Exception Throws an exception if the method is not properly extended.
|
||||
*/
|
||||
protected static function filterElements( Messages $messages, $elementsData, $targetLanguages ) {
|
||||
throw new Exception( ' this method is mandatory' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
class Messages {
|
||||
|
||||
/**
|
||||
* @param \WP_Post $post
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ignoreOriginalPostMessage( $post, $language ) {
|
||||
return sprintf(
|
||||
__(
|
||||
'Post "%1$s" will be ignored for %2$s, because it is an original post.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$post->post_title,
|
||||
$language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Post $post
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ignoreInProgressPostMessage( $post, $language ) {
|
||||
return sprintf(
|
||||
__(
|
||||
'Post "%1$s" will be ignored for %2$s, because translation is already in progress.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$post->post_title,
|
||||
$language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_ST_String $string
|
||||
* @param $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ignoreInProgressStringMessage( \WPML_ST_String $string, $language ) {
|
||||
return sprintf(
|
||||
__(
|
||||
'String "%1$s" will be ignored for %2$s, because translation is already waiting for translator.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$string->get_value(),
|
||||
$language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_Package $package
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ignoreInProgressPackageMessage( $package, $language ) {
|
||||
return sprintf(
|
||||
__(
|
||||
'Package "%1$s" will be ignored for %2$s, because translation is already in progress.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$package->title,
|
||||
$language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_Package $package
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ignoreOriginalPackageMessage( $package, $language ) {
|
||||
return sprintf(
|
||||
__(
|
||||
'Package "%1$s" will be ignored for %2$s, because it is an original post.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$package->title,
|
||||
$language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $messages
|
||||
* @param string $type
|
||||
*/
|
||||
public function showForPosts( array $messages, $type ) {
|
||||
$this->show(
|
||||
'translation-basket-notification',
|
||||
[ WPML_TM_FOLDER . '/menu/main.php' ],
|
||||
'translation-basket-notification',
|
||||
$messages,
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $messages
|
||||
* @param string $type
|
||||
*/
|
||||
public function showForStrings( array $messages, $type ) {
|
||||
if ( defined( 'WPML_ST_FOLDER' ) ) {
|
||||
$this->show(
|
||||
'string-translation-top',
|
||||
[ WPML_ST_FOLDER . '/menu/string-translation.php' ],
|
||||
'string-translation-top',
|
||||
$messages,
|
||||
$type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param array $pages
|
||||
* @param string $group
|
||||
* @param array $messages
|
||||
* @param string $type
|
||||
*/
|
||||
private function show( $id, array $pages, $group, array $messages, $type ) {
|
||||
if ( $messages ) {
|
||||
$messageArgs = [
|
||||
'id' => $id,
|
||||
'text' => '<ul><li>' . implode( '</li><li>', $messages ) . '</li></ul>',
|
||||
'classes' => 'small',
|
||||
'type' => $type,
|
||||
'group' => $group,
|
||||
'admin_notice' => true,
|
||||
'hide_per_user' => false,
|
||||
'dismiss_per_user' => false,
|
||||
'limit_to_page' => $pages,
|
||||
'show_once' => true,
|
||||
];
|
||||
\ICL_AdminNotifier::add_message( $messageArgs );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
use WPML\Element\API\Languages;
|
||||
|
||||
class Packages extends Elements {
|
||||
|
||||
public static function dispatch(
|
||||
callable $sendBatch,
|
||||
Messages $messages,
|
||||
callable $buildBatch,
|
||||
$data,
|
||||
$type = 'package'
|
||||
) {
|
||||
parent::dispatch( $sendBatch, $messages, $buildBatch, $data, $type );
|
||||
}
|
||||
|
||||
protected static function filterElements( Messages $messages, $packagesData, $targetLanguages ) {
|
||||
|
||||
$ignoredPackagesMessages = [];
|
||||
$packagesToTranslation = [];
|
||||
|
||||
foreach ( $packagesData as $packageId => $packageData ) {
|
||||
$packagesToTranslation[ $packageId ] = [
|
||||
'type' => $packageData['type'],
|
||||
'target_languages' => []
|
||||
];
|
||||
|
||||
$package = apply_filters( 'wpml_get_translatable_item', null, $packageId, 'package' );
|
||||
$packageLang = apply_filters( 'wpml_language_for_element', Languages::getDefaultCode(), $package );
|
||||
|
||||
foreach ( $targetLanguages as $language ) {
|
||||
if ( $packageLang === $language ) {
|
||||
$ignoredPackagesMessages [] = $messages->ignoreOriginalPackageMessage( $package, $language );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( self::hasInProgressJob(
|
||||
$package->ID,
|
||||
$package->get_element_type_prefix() . '_' . $package->kind_slug,
|
||||
$language
|
||||
) ) {
|
||||
$ignoredPackagesMessages [] = $messages->ignoreInProgressPackageMessage( $package, $language );
|
||||
continue;
|
||||
}
|
||||
|
||||
$packagesToTranslation[ $packageId ]['target_languages'] [] = $language;
|
||||
}
|
||||
}
|
||||
|
||||
return [ $packagesToTranslation, $ignoredPackagesMessages ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
use WPML\Element\API\Post;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Str;
|
||||
|
||||
class Posts extends Elements {
|
||||
|
||||
public static function dispatch(
|
||||
callable $sendBatch,
|
||||
Messages $messages,
|
||||
callable $buildBatch,
|
||||
$data,
|
||||
$type = 'post'
|
||||
) {
|
||||
parent::dispatch( $sendBatch, $messages, $buildBatch, $data, $type );
|
||||
}
|
||||
|
||||
protected static function filterElements( Messages $messages, $postsData, $targetLanguages ) {
|
||||
$ignoredPostsMessages = [];
|
||||
$postsToTranslation = [];
|
||||
|
||||
foreach ( $postsData as $postId => $postData ) {
|
||||
$postsToTranslation[ $postId ] = [
|
||||
'type' => $postData['type'],
|
||||
'media' => Obj::propOr( [], 'media-translation', $postData ),
|
||||
'target_languages' => []
|
||||
];
|
||||
|
||||
$post = self::getPost( $postId );
|
||||
$postLang = Post::getLang( $postId );
|
||||
|
||||
|
||||
foreach ( $targetLanguages as $language ) {
|
||||
if ( $postLang === $language ) {
|
||||
$ignoredPostsMessages [] = $messages->ignoreOriginalPostMessage( $post, $language );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( self::hasInProgressJob( $post->ID, $post->post_type, $language ) ) {
|
||||
$ignoredPostsMessages [] = $messages->ignoreInProgressPostMessage( $post, $language );
|
||||
continue;
|
||||
}
|
||||
|
||||
$postsToTranslation[ $postId ]['target_languages'] [] = $language;
|
||||
}
|
||||
}
|
||||
|
||||
return [ $postsToTranslation, $ignoredPostsMessages ];
|
||||
}
|
||||
|
||||
private static function getPost( $postId ) {
|
||||
return Str::includes( 'external_', $postId ) ?
|
||||
apply_filters( 'wpml_get_translatable_item', null, $postId ) :
|
||||
get_post( $postId );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Jobs\Dispatch;
|
||||
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\User;
|
||||
use function WPML\Container\make;
|
||||
|
||||
class Strings {
|
||||
/**
|
||||
* @param callable $sendBatch
|
||||
* @param \WPML\TM\Jobs\Dispatch\Messages $messages
|
||||
* @param callable $buildBatch
|
||||
* @param $stringIds
|
||||
* @param $sourceLanguage
|
||||
* @param $targetLanguages
|
||||
*/
|
||||
public static function dispatch(
|
||||
callable $sendBatch,
|
||||
Messages $messages,
|
||||
callable $buildBatch,
|
||||
$stringIds,
|
||||
$sourceLanguage,
|
||||
$targetLanguages
|
||||
) {
|
||||
$stringsForTranslation = self::filterStringsForTranslation( $messages, $stringIds, $targetLanguages );
|
||||
$translators = array_fill_keys( $targetLanguages, User::getCurrentId() );
|
||||
|
||||
$batch = $buildBatch( $stringsForTranslation, $sourceLanguage, $translators );
|
||||
$batch && $sendBatch( $messages, $batch );
|
||||
}
|
||||
|
||||
|
||||
private static function filterStringsForTranslation( Messages $messages, $stringIds, $targetLanguages ) {
|
||||
$stringsToTranslation = [];
|
||||
$ignoredStringsMessages = [];
|
||||
|
||||
/** @var \WPML_ST_String_Factory $stringFactory */
|
||||
$stringFactory = make( \WPML_ST_String_Factory::class );
|
||||
|
||||
foreach ( $stringIds as $stringId ) {
|
||||
$stringsToTranslation[ $stringId ] = [];
|
||||
|
||||
$string = $stringFactory->find_by_id( $stringId );
|
||||
$statuses = wpml_collect( $string->get_translation_statuses() )->keyBy( 'language' )->map( Obj::prop( 'status' ) );
|
||||
|
||||
foreach ( $targetLanguages as $language ) {
|
||||
if ( (int) Obj::prop( $language, $statuses ) === ICL_TM_WAITING_FOR_TRANSLATOR ) {
|
||||
$ignoredStringsMessages[] = $messages->ignoreInProgressStringMessage( $string, $language );
|
||||
} else {
|
||||
$stringsToTranslation[ $stringId ] [] = $language;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$messages->showForStrings( $ignoredStringsMessages, 'information' );
|
||||
|
||||
return array_filter( $stringsToTranslation, Lst::length() );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user