203 lines
6.8 KiB
PHP
203 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace WPML\ST\Shortcode;
|
|
|
|
use WPML\Collect\Support\Traits\Macroable;
|
|
use WPML\FP\Fns;
|
|
use WPML\FP\Lst;
|
|
use WPML\FP\Obj;
|
|
use WPML\FP\Str;
|
|
use function WPML\FP\curryN;
|
|
use function WPML\FP\pipe;
|
|
use function WPML\FP\spreadArgs;
|
|
|
|
/**
|
|
* Class TranslationHandler
|
|
*
|
|
* @package WPML\ST\Shortcode
|
|
*
|
|
* @method static callable|mixed appendId(callable ...$getStringRowByItsDomainAndValue, mixed ...$fieldData) - Curried :: (string->string->array)->mixed->mixed
|
|
*
|
|
* It appends "id" attribute to [wpml-string] shortcode.
|
|
*
|
|
* $getStringRowByItsDomainAndValue :: string->string->array
|
|
*
|
|
* @method static callable|mixed registerStringTranslation(callable ...$lens, mixed ...$data, callable ...$getTargetLanguage) - Curried :: callable->mixed->(mixed->string)->mixed
|
|
*
|
|
* It detects all [wpml-string] shortcodes in $jobData and registers string translations
|
|
*
|
|
* $getTargetLanguage :: mixed->string
|
|
*
|
|
* @method static callable|mixed restoreOriginalShortcodes(callable ...$getStringById, callable ...$lens, mixed ...$data) - Curried :: (int->string)->callable->mixed->mixed
|
|
*
|
|
* It detects all [wpml-string] shortcodes in $jobData and
|
|
* - removes "id" attribute
|
|
* - replaces translated inner text by its original value
|
|
*
|
|
* $getStringById :: int->array
|
|
*/
|
|
class TranslationHandler {
|
|
use Macroable;
|
|
|
|
const SHORTCODE_PATTERN = '/\[wpml-string.*?\[\/wpml-string\]/';
|
|
|
|
public static function init() {
|
|
|
|
self::macro(
|
|
'appendId',
|
|
curryN(
|
|
2,
|
|
function ( callable $getStringRowByItsDomainAndValue, $fieldData ) {
|
|
// $getStringId :: [ domain, value ] → id
|
|
$getStringId = spreadArgs( pipe( $getStringRowByItsDomainAndValue, Obj::prop( 'id' ) ) );
|
|
// appendStringId :: [ _, domain, value ] → [ _, domain, value, id ]
|
|
$appendStringId = self::appendToData( pipe( Lst::takeLast( 2 ), $getStringId ) );
|
|
|
|
// $getShortcode :: [shortcode, domain, id] -> shortcode
|
|
$getShortcode = Lst::nth( 0 );
|
|
// $getShortcode :: [shortcode, domain, id] -> id
|
|
$getId = Lst::last();
|
|
|
|
// $extractDomain :: string -> string
|
|
$extractDomain = self::firstMatchingGroup( '/context="(.*?)"/', 'wpml-shortcode' );
|
|
|
|
// $forceRegisterShortcodeString :: string -> void
|
|
$forceRegisterShortcodeString = pipe( $getShortcode, 'do_shortcode' );
|
|
|
|
// $newShortcode :: [shortcode, domain, id] -> string
|
|
$newShortcode = function ( $data ) use ( $getId, $getShortcode ) {
|
|
$pattern = '/\[wpml-string(.*)\]/';
|
|
$replace = '[wpml-string id="' . $getId( $data ) . '"${1}]';
|
|
|
|
return preg_replace( $pattern, $replace, $getShortcode( $data ) );
|
|
};
|
|
// $updateSingleShortcode :: [shortcode, domain, id] -> [shortcode, newShortcode]
|
|
$updateSingleShortcode = Fns::converge( Lst::makePair(), [ $getShortcode, $newShortcode ] );
|
|
|
|
// $updateFieldData :: string, [shortcode, newShortcode] -> string
|
|
$updateFieldData = function ( $fieldData, $shortCodePairs ) {
|
|
list( $shortcode, $newShortcode ) = $shortCodePairs;
|
|
|
|
return str_replace( $shortcode, $newShortcode, $fieldData );
|
|
};
|
|
|
|
return \wpml_collect( Str::matchAll( self::SHORTCODE_PATTERN, $fieldData ) )
|
|
->map( self::appendToData( pipe( $getShortcode, $extractDomain ) ) )
|
|
->map( self::appendToData( pipe( $getShortcode, self::extractInnerText() ) ) )
|
|
->each( $forceRegisterShortcodeString )
|
|
->map( $appendStringId )
|
|
->filter( $getId )
|
|
->map( $updateSingleShortcode )
|
|
->reduce( $updateFieldData, $fieldData );
|
|
}
|
|
)
|
|
);
|
|
|
|
self::macro(
|
|
'registerStringTranslation',
|
|
curryN(
|
|
3,
|
|
function ( callable $lens, $data, callable $getTargetLanguage ) {
|
|
$targetLanguage = $getTargetLanguage( $data );
|
|
if ( ! $targetLanguage ) {
|
|
return $data;
|
|
}
|
|
|
|
$registerStringTranslation = curryN( 4, 'icl_add_string_translation' );
|
|
// $registerStringTranslation :: stringId, translationValue -> translationId
|
|
$registerStringTranslation = $registerStringTranslation(
|
|
Fns::__,
|
|
$targetLanguage,
|
|
Fns::__,
|
|
ICL_STRING_TRANSLATION_COMPLETE
|
|
);
|
|
|
|
// $getStringIdAndTranslations :: [shortcode, id, translation] -> [id, translation]
|
|
$getStringIdAndTranslations = Lst::drop( 1 );
|
|
|
|
// $registerTranslationOfSingleString :: [shortcode, id, translation] -> void
|
|
$registerTranslationOfSingleString = pipe(
|
|
$getStringIdAndTranslations,
|
|
spreadArgs( $registerStringTranslation )
|
|
);
|
|
|
|
// $registerStringsFromFieldData :: string -> void
|
|
$registerStringsFromFieldData = pipe(
|
|
self::findShortcodesInJobData(),
|
|
Fns::each( $registerTranslationOfSingleString )
|
|
);
|
|
|
|
Fns::each( $registerStringsFromFieldData, Obj::view( $lens, $data ) );
|
|
|
|
return $data;
|
|
}
|
|
)
|
|
);
|
|
|
|
self::macro(
|
|
'restoreOriginalShortcodes',
|
|
curryN(
|
|
3,
|
|
function ( callable $getStringById, callable $lens, $data ) {
|
|
// $getOriginalStringValue :: int -> string
|
|
$getOriginalStringValue = pipe( $getStringById, Obj::prop( 'value' ) );
|
|
// $restoreSingleShortcode :: string, [string, id] -> string
|
|
$restoreSingleShortcode = function ( $fieldData, $shortcodeMatches ) use ( $getOriginalStringValue ) {
|
|
list( , $stringId ) = $shortcodeMatches;
|
|
|
|
$pattern = '/\[wpml-string id="' . $stringId . '"(.*?)\](.*?)\[\/wpml-string\]/';
|
|
$replacement = '[wpml-string${1}]' . $getOriginalStringValue( $stringId ) . '[/wpml-string]';
|
|
|
|
return preg_replace( $pattern, $replacement, $fieldData );
|
|
};
|
|
|
|
// $updateFieldData :: string -> string
|
|
$updateFieldData = Fns::map(
|
|
Fns::converge(
|
|
Fns::reduce( $restoreSingleShortcode ),
|
|
[
|
|
Fns::identity(),
|
|
self::findShortcodesInJobData(),
|
|
]
|
|
)
|
|
);
|
|
|
|
return Obj::over( $lens, $updateFieldData, $data );
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
// findShortcodesInJobData :: void → ( string → [shortcode, id, translation] )
|
|
private static function findShortcodesInJobData() {
|
|
return function ( $str ) {
|
|
$getId = Lst::nth( 1 );
|
|
$extractId = self::firstMatchingGroup( '/id="(.*?)"/' );
|
|
|
|
return \wpml_collect( Str::matchAll( self::SHORTCODE_PATTERN, $str ) )
|
|
->map( self::appendToData( pipe( Lst::nth( 0 ), $extractId ) ) )
|
|
->map( self::appendToData( pipe( Lst::nth( 0 ), self::extractInnerText() ) ) )
|
|
->filter( $getId );
|
|
};
|
|
}
|
|
|
|
// appendToData :: callable -> ( array -> array )
|
|
private static function appendToData( callable $fn ) {
|
|
return Fns::converge( Lst::append(), [ $fn, Fns::identity() ] );
|
|
}
|
|
|
|
// firstMatchingGroup :: string, string|null -> ( string -> string )
|
|
private static function firstMatchingGroup( $pattern, $fallback = null ) {
|
|
return function ( $str ) use ( $pattern, $fallback ) {
|
|
return Lst::nth( 1, Str::match( $pattern, $str ) ) ?: $fallback;
|
|
};
|
|
}
|
|
|
|
// extractInnerText :: void -> ( string -> string )
|
|
private static function extractInnerText() {
|
|
return self::firstMatchingGroup( '/\](.*)\[/' );
|
|
}
|
|
}
|
|
|
|
TranslationHandler::init();
|