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

View File

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

View File

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

View File

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

View File

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

View File

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