wpml
Signed-off-by: Jeff <jeff@gotenzing.com>
Showing
1000 changed files
with
4472 additions
and
0 deletions
Too many changes to show.
To preserve performance only 1000 of 1000+ files are displayed.
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use WPML\LIB\WP\Post; | ||
| 8 | use WPML_TM_ATE_API; | ||
| 9 | use WPML_TM_ATE_Jobs; | ||
| 10 | use function WPML\FP\pipe; | ||
| 11 | |||
| 12 | class ATE { | ||
| 13 | /** @var WPML_TM_ATE_API $ateApi */ | ||
| 14 | private $ateApi; | ||
| 15 | |||
| 16 | /** @var WPML_TM_ATE_Jobs $ateJobs */ | ||
| 17 | private $ateJobs; | ||
| 18 | |||
| 19 | public function __construct( WPML_TM_ATE_API $ateApi, WPML_TM_ATE_Jobs $ateJobs ) { | ||
| 20 | $this->ateApi = $ateApi; | ||
| 21 | $this->ateJobs = $ateJobs; | ||
| 22 | } | ||
| 23 | |||
| 24 | public function checkJobStatus( $wpmlJobId ) { | ||
| 25 | $ateJobId = $this->ateJobs->get_ate_job_id( $wpmlJobId ); | ||
| 26 | $response = $this->ateApi->get_job_status_with_priority( $ateJobId ); | ||
| 27 | |||
| 28 | if ( is_wp_error( $response ) ) { | ||
| 29 | return []; | ||
| 30 | } | ||
| 31 | |||
| 32 | $encoded = wp_json_encode( $response ); | ||
| 33 | if ( ! $encoded ) { | ||
| 34 | return []; | ||
| 35 | } | ||
| 36 | |||
| 37 | return wpml_collect( json_decode( $encoded, true ) )->first( | ||
| 38 | pipe( | ||
| 39 | Obj::prop( 'ate_job_id' ), | ||
| 40 | Relation::equals( $ateJobId ) | ||
| 41 | ) | ||
| 42 | ); | ||
| 43 | } | ||
| 44 | |||
| 45 | public function applyTranslation( $wpmlJobId, $postId, $xliffUrl ) { | ||
| 46 | $ateJobId = $this->ateJobs->get_ate_job_id( $wpmlJobId ); | ||
| 47 | $xliffContent = $this->ateApi->get_remote_xliff_content( $xliffUrl, [ 'jobId' => $wpmlJobId, 'ateJobId' => $ateJobId ] ); | ||
| 48 | |||
| 49 | if ( ! function_exists( 'wpml_tm_save_data' ) ) { | ||
| 50 | require_once WPML_TM_PATH . '/inc/wpml-private-actions.php'; | ||
| 51 | } | ||
| 52 | |||
| 53 | $prevPostStatus = Post::getStatus( $postId ); | ||
| 54 | if ( $this->ateJobs->apply( $xliffContent ) ) { | ||
| 55 | if ( Post::getStatus( $postId ) !== $prevPostStatus ) { | ||
| 56 | Post::setStatus( $postId, $prevPostStatus ); | ||
| 57 | } | ||
| 58 | $response = $this->ateApi->confirm_received_job( $ateJobId ); | ||
| 59 | |||
| 60 | return ! is_wp_error( $response ); | ||
| 61 | } | ||
| 62 | |||
| 63 | return false; | ||
| 64 | } | ||
| 65 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API\ATE; | ||
| 4 | |||
| 5 | use WPML\FP\Either; | ||
| 6 | use WPML\FP\Fns; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | use WPML\LIB\WP\WordPress; | ||
| 9 | use WPML\WP\OptionManager; | ||
| 10 | use function WPML\Container\make; | ||
| 11 | |||
| 12 | class Account { | ||
| 13 | /** | ||
| 14 | * @return Either<array> | ||
| 15 | */ | ||
| 16 | public static function getCredits() { | ||
| 17 | return WordPress::handleError( make( \WPML_TM_AMS_API::class )->getCredits() ) | ||
| 18 | ->filter( Fns::identity() ) | ||
| 19 | /** @phpstan-ignore-next-line */ | ||
| 20 | ->map( Fns::tap( OptionManager::update( 'TM', 'Account::credits' ) ) ) | ||
| 21 | ->bimap( Fns::always( [ 'error' => 'communication error' ] ), Fns::identity() ); | ||
| 22 | } | ||
| 23 | |||
| 24 | /** | ||
| 25 | * @param array $creditInfo | ||
| 26 | * | ||
| 27 | * @return bool | ||
| 28 | */ | ||
| 29 | public static function hasActiveSubscription( array $creditInfo ) { | ||
| 30 | return (bool) Obj::propOr( false, 'active_subscription', $creditInfo ); | ||
| 31 | } | ||
| 32 | |||
| 33 | /** | ||
| 34 | * @param array $creditInfo | ||
| 35 | * | ||
| 36 | * @return int | ||
| 37 | */ | ||
| 38 | public static function getAvailableBalance( array $creditInfo ) { | ||
| 39 | return (int) Obj::propOr( 0, 'available_balance', $creditInfo ); | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * @return bool | ||
| 44 | */ | ||
| 45 | public static function isAbleToTranslateAutomatically() { | ||
| 46 | $creditInfo = OptionManager::getOr( [], 'TM', 'Account::credits' ); | ||
| 47 | |||
| 48 | if ( ! array_key_exists( 'active_subscription', $creditInfo ) ) { | ||
| 49 | $creditInfo = self::getCredits()->getOrElse( [] ); | ||
| 50 | } | ||
| 51 | |||
| 52 | return self::hasActiveSubscription( $creditInfo ) || self::getAvailableBalance( $creditInfo ) > 0; | ||
| 53 | } | ||
| 54 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API\ATE; | ||
| 4 | |||
| 5 | use WPML\TM\ATE\API\CachedATEAPI; | ||
| 6 | use WPML\TM\ATE\API\CacheStorage\Transient; | ||
| 7 | use function WPML\Container\make; | ||
| 8 | |||
| 9 | class CachedLanguageMappings extends LanguageMappings { | ||
| 10 | /** | ||
| 11 | * @return CachedATEAPI | ||
| 12 | */ | ||
| 13 | protected static function getATEAPI() { | ||
| 14 | return new CachedATEAPI( make( \WPML_TM_ATE_API::class ), new Transient() ); | ||
| 15 | } | ||
| 16 | |||
| 17 | public static function clearCache() { | ||
| 18 | $transientStorage = new Transient(); | ||
| 19 | $transientStorage->delete( CachedATEAPI::CACHE_OPTION ); | ||
| 20 | } | ||
| 21 | } | ||
| 22 |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API\ATE; | ||
| 4 | |||
| 5 | use WPML\Element\API\Languages; | ||
| 6 | use WPML\FP\Either; | ||
| 7 | use WPML\FP\Fns; | ||
| 8 | use WPML\FP\Logic; | ||
| 9 | use WPML\FP\Lst; | ||
| 10 | use WPML\FP\Maybe; | ||
| 11 | use WPML\FP\Obj; | ||
| 12 | use WPML\FP\Relation; | ||
| 13 | use WPML\FP\Wrapper; | ||
| 14 | use WPML\LIB\WP\Option; | ||
| 15 | use WPML\Element\API\Entity\LanguageMapping; | ||
| 16 | use WPML\TM\ATE\API\CacheStorage\StaticVariable; | ||
| 17 | use WPML\TM\ATE\API\CachedATEAPI; | ||
| 18 | use function WPML\Container\make; | ||
| 19 | use function WPML\FP\curryN; | ||
| 20 | use function WPML\FP\invoke; | ||
| 21 | use function WPML\FP\pipe; | ||
| 22 | |||
| 23 | class LanguageMappings { | ||
| 24 | const IGNORE_MAPPING_OPTION = 'wpml-languages-ignore-mapping'; | ||
| 25 | const IGNORE_MAPPING_ID = - 1; | ||
| 26 | |||
| 27 | public static function withCanBeTranslatedAutomatically( $languages = null ) { | ||
| 28 | $fn = curryN( 1, function ( $languages ) { | ||
| 29 | if ( ! is_object( $languages ) && ! is_array( $languages ) ) { | ||
| 30 | return $languages; | ||
| 31 | } | ||
| 32 | $ateAPI = static::getATEAPI(); | ||
| 33 | $targetCodes = Lst::pluck( 'code', Obj::values( $languages ) ); | ||
| 34 | $supportedLanguages = $ateAPI->get_languages_supported_by_automatic_translations( $targetCodes )->getOrElse( [] ); | ||
| 35 | |||
| 36 | $areThereAnySupportedLanguages = Lst::find( Logic::isNotNull(), $supportedLanguages ); | ||
| 37 | $isSupportedCode = pipe( Obj::prop( Fns::__, $supportedLanguages ), Logic::isNotNull() ); | ||
| 38 | $isNotMarkedAsDontMap = Logic::complement( Lst::includes( Fns::__, Option::getOr( self::IGNORE_MAPPING_OPTION, [] ) ) ); | ||
| 39 | |||
| 40 | $isDefaultCode = Relation::equals( Languages::getDefaultCode() ); | ||
| 41 | $isSupportedByAnyEngine = pipe( | ||
| 42 | pipe( [ $ateAPI, 'get_language_details' ], invoke( 'getOrElse' )->with( [] ) ), | ||
| 43 | Logic::anyPass( [ Obj::prop( 'ms_api_iso' ), Obj::prop( 'google_api_iso' ), Obj::prop( 'deepl_api_iso' ) ] ) | ||
| 44 | ); | ||
| 45 | $isDefaultLangSupported = Logic::anyPass( [ Fns::always( $areThereAnySupportedLanguages ), $isSupportedByAnyEngine ] ); | ||
| 46 | |||
| 47 | $isSupported = pipe( Obj::prop( 'code' ), Logic::both( | ||
| 48 | $isNotMarkedAsDontMap, | ||
| 49 | Logic::ifElse( $isDefaultCode, $isDefaultLangSupported, $isSupportedCode ) | ||
| 50 | ) ); | ||
| 51 | |||
| 52 | return Fns::map( Obj::addProp( 'can_be_translated_automatically', $isSupported ), $languages ); | ||
| 53 | } ); | ||
| 54 | |||
| 55 | return call_user_func_array( $fn, func_get_args() ); | ||
| 56 | } | ||
| 57 | |||
| 58 | public static function isCodeEligibleForAutomaticTranslations( $languageCode = null ) { | ||
| 59 | $fn = Lst::includes( Fns::__, static::geCodesEligibleForAutomaticTranslations() ); | ||
| 60 | |||
| 61 | return call_user_func_array( $fn, func_get_args() ); | ||
| 62 | } | ||
| 63 | |||
| 64 | /** | ||
| 65 | * @return LanguageMapping[] $mappings | ||
| 66 | */ | ||
| 67 | public static function get() { | ||
| 68 | $ignoredMappings = Fns::map( function ( $code ) { | ||
| 69 | return new LanguageMapping( $code, '', self::IGNORE_MAPPING_ID ); | ||
| 70 | }, Option::getOr( self::IGNORE_MAPPING_OPTION, [] ) ); | ||
| 71 | |||
| 72 | $mappingInATE = Fns::map( function ( $record ) { | ||
| 73 | return new LanguageMapping( | ||
| 74 | Obj::prop( 'source_code', $record ), | ||
| 75 | Obj::path( [ 'source_language', 'name' ], $record ), | ||
| 76 | Obj::path( [ 'target_language', 'id' ], $record ), | ||
| 77 | Obj::prop( 'target_code', $record ) | ||
| 78 | ); | ||
| 79 | }, static::getATEAPI()->get_language_mapping()->getOrElse( [] ) ); | ||
| 80 | |||
| 81 | return Lst::concat( $ignoredMappings, $mappingInATE ); | ||
| 82 | } | ||
| 83 | |||
| 84 | public static function withMapping( $languages = null ) { | ||
| 85 | $fn = curryN( 1, function ( $languages ) { | ||
| 86 | $mapping = self::get(); | ||
| 87 | $findMappingByCode = function ( $language ) use ( $mapping ) { | ||
| 88 | return Lst::find( invoke( 'matches' )->with( Obj::prop( 'code', $language ) ), $mapping ); | ||
| 89 | }; | ||
| 90 | |||
| 91 | return Fns::map( Obj::addProp( 'mapping', $findMappingByCode ), $languages ); | ||
| 92 | } ); | ||
| 93 | |||
| 94 | return call_user_func_array( $fn, func_get_args() ); | ||
| 95 | } | ||
| 96 | |||
| 97 | /** | ||
| 98 | * @return array | ||
| 99 | */ | ||
| 100 | public static function getAvailable() { | ||
| 101 | $mapping = static::getATEAPI()->get_available_languages(); | ||
| 102 | |||
| 103 | return Relation::sortWith( [ Fns::ascend( Obj::prop( 'name' ) ) ], $mapping ); | ||
| 104 | } | ||
| 105 | |||
| 106 | |||
| 107 | /** | ||
| 108 | * @param LanguageMapping[] $mappings | ||
| 109 | * | ||
| 110 | * @return Either | ||
| 111 | */ | ||
| 112 | public static function saveMapping( array $mappings ) { | ||
| 113 | list( $ignoredMapping, $mappingSet ) = \wpml_collect( $mappings )->partition( Relation::propEq( 'targetId', self::IGNORE_MAPPING_ID ) ); | ||
| 114 | |||
| 115 | $ignoredCodes = $ignoredMapping->pluck( 'sourceCode' )->toArray(); | ||
| 116 | Option::update( self::IGNORE_MAPPING_OPTION, $ignoredCodes ); | ||
| 117 | |||
| 118 | $ateAPI = static::getATEAPI(); | ||
| 119 | if ( count( $ignoredCodes ) ) { | ||
| 120 | $ateAPI->get_language_mapping() | ||
| 121 | ->map( Fns::filter( pipe( Obj::prop( 'source_code' ), Lst::includes( Fns::__, $ignoredCodes ) ) ) ) | ||
| 122 | ->map( Lst::pluck( 'id' ) ) | ||
| 123 | ->filter( Logic::complement( Logic::isEmpty() ) ) | ||
| 124 | ->map( [ $ateAPI, 'remove_language_mapping' ] ); | ||
| 125 | } | ||
| 126 | |||
| 127 | return $ateAPI->create_language_mapping( $mappingSet->values()->toArray() ); | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * @return array | ||
| 132 | */ | ||
| 133 | public static function getLanguagesEligibleForAutomaticTranslations() { | ||
| 134 | return Wrapper::of( Languages::getSecondaries() ) | ||
| 135 | ->map( static::withCanBeTranslatedAutomatically() ) | ||
| 136 | ->map( Fns::filter( Obj::prop( 'can_be_translated_automatically' ) ) ) | ||
| 137 | ->get(); | ||
| 138 | } | ||
| 139 | |||
| 140 | /** | ||
| 141 | * @return string[] | ||
| 142 | */ | ||
| 143 | public static function geCodesEligibleForAutomaticTranslations() { | ||
| 144 | return Lst::pluck( 'code', static::getLanguagesEligibleForAutomaticTranslations() ); | ||
| 145 | } | ||
| 146 | |||
| 147 | public static function hasTheSameMappingAsDefaultLang( $language = null ) { | ||
| 148 | $fn = curryN( 1, function ( $language ) { | ||
| 149 | $defaultLanguage = Lst::last( static::withMapping( [ Languages::getDefault() ] ) ); | ||
| 150 | if ( ! is_object( $defaultLanguage ) && ! is_array( $defaultLanguage ) ) { | ||
| 151 | return false; | ||
| 152 | } | ||
| 153 | $defaultLanguageMappingTargetCode = Obj::pathOr( Obj::prop( 'code', $defaultLanguage ), [ 'mapping', 'targetCode' ], $defaultLanguage ); | ||
| 154 | |||
| 155 | return Obj::pathOr( null, [ 'mapping', 'targetCode' ], $language ) === $defaultLanguageMappingTargetCode; | ||
| 156 | } ); | ||
| 157 | |||
| 158 | return call_user_func_array( $fn, func_get_args() ); | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * @return CachedATEAPI | ||
| 163 | */ | ||
| 164 | protected static function getATEAPI() { | ||
| 165 | return new CachedATEAPI( make( \WPML_TM_ATE_API::class ), StaticVariable::getInstance() ); | ||
| 166 | } | ||
| 167 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API; | ||
| 4 | |||
| 5 | use WPML\Element\API\Languages; | ||
| 6 | use WPML\LIB\WP\User; | ||
| 7 | use WPML\Setup\Option; | ||
| 8 | use function WPML\Container\make; | ||
| 9 | |||
| 10 | class Basket { | ||
| 11 | /** | ||
| 12 | * @return bool | ||
| 13 | */ | ||
| 14 | public static function shouldUse( $currentLanguageCode = null ) { | ||
| 15 | $doesNotHaveUserForEachLanguage = function () use ( $currentLanguageCode ) { | ||
| 16 | global $sitepress; | ||
| 17 | |||
| 18 | $theCurrentUserId = User::getCurrentId(); | ||
| 19 | |||
| 20 | $translator_records = make( \WPML_Translator_Records::class ); | ||
| 21 | $current_language = $currentLanguageCode ?: Languages::getCurrentCode(); | ||
| 22 | $active_languages = $sitepress->get_active_languages(); | ||
| 23 | unset( $active_languages[ $current_language ] ); | ||
| 24 | $active_languages = array_keys( $active_languages ); | ||
| 25 | foreach ( $active_languages as $active_language ) { | ||
| 26 | $translators = $translator_records->get_users_with_languages( $current_language, [ $active_language ] ); | ||
| 27 | $number_of_translators = count( $translators ); | ||
| 28 | |||
| 29 | $hasOneTranslatorButHeIsNotACurrentUser = $number_of_translators === 1 && $translators[0]->ID !== $theCurrentUserId; | ||
| 30 | if ( $hasOneTranslatorButHeIsNotACurrentUser || $number_of_translators !== 1 ) { | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | return false; | ||
| 36 | }; | ||
| 37 | |||
| 38 | /** @var TranslationServices $translationService */ | ||
| 39 | $translationService = make(TranslationServices::class); | ||
| 40 | |||
| 41 | return $translationService->isAuthorized() || ! Option::shouldTranslateEverything() && $doesNotHaveUserForEachLanguage(); | ||
| 42 | } | ||
| 43 | |||
| 44 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API; | ||
| 4 | |||
| 5 | |||
| 6 | use WPML\FP\Curryable; | ||
| 7 | use WPML\FP\Fns; | ||
| 8 | use WPML\FP\Obj; | ||
| 9 | use WPML\TM\Jobs\Dispatch\Messages; | ||
| 10 | use function WPML\Container\make; | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Class Batch | ||
| 14 | * @package WPML\TM\API | ||
| 15 | * | ||
| 16 | * @method static callable|void rollback( ...$batchName ) - Curried :: string->void | ||
| 17 | * | ||
| 18 | * It rollbacks just sent batch. | ||
| 19 | */ | ||
| 20 | class Batch { | ||
| 21 | |||
| 22 | use Curryable; | ||
| 23 | |||
| 24 | public static function init() { | ||
| 25 | |||
| 26 | self::curryN( 'rollback', 1, function ( $basketName ) { | ||
| 27 | $batch = make( \WPML_Translation_Basket::class )->get_basket_batch( $basketName ); | ||
| 28 | $batch->cancel_all_jobs(); | ||
| 29 | $batch->clear_batch_data(); | ||
| 30 | } ); | ||
| 31 | |||
| 32 | |||
| 33 | } | ||
| 34 | |||
| 35 | public static function sendPosts( Messages $messages, $batch, $sendFrom = Jobs::SENT_VIA_BASKET ) { | ||
| 36 | $dispatchActions = function ( $batch ) use ( $sendFrom ) { | ||
| 37 | $allowedTypes = array_keys( \TranslationProxy_Basket::get_basket_items_types() ); | ||
| 38 | |||
| 39 | foreach ( $allowedTypes as $type ) { | ||
| 40 | do_action( 'wpml_tm_send_' . $type . '_jobs', $batch, $type, $sendFrom ); | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | |||
| 44 | self::send( $dispatchActions, [ $messages, 'showForPosts' ], $batch ); | ||
| 45 | } | ||
| 46 | |||
| 47 | public static function sendStrings( Messages $messages, $batch ) { | ||
| 48 | $dispatchActions = function ( $batch ) { | ||
| 49 | do_action( 'wpml_tm_send_st-batch_jobs', $batch, 'st-batch' ); | ||
| 50 | }; | ||
| 51 | |||
| 52 | self::send( $dispatchActions, [ $messages, 'showForStrings' ], $batch ); | ||
| 53 | } | ||
| 54 | |||
| 55 | private static function send( callable $dispatchAction, callable $displayErrors, $batch ) { | ||
| 56 | $dispatchAction( $batch ); | ||
| 57 | |||
| 58 | $errors = wpml_load_core_tm()->messages_by_type( 'error' ); | ||
| 59 | |||
| 60 | if ( $errors ) { | ||
| 61 | self::rollback( $batch->get_basket_name() ); | ||
| 62 | |||
| 63 | $displayErrors( Fns::map( Obj::prop( 'text' ), $errors ), 'error' ); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | Batch::init(); |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API\Job; | ||
| 4 | |||
| 5 | use WPML\Collect\Support\Traits\Macroable; | ||
| 6 | use WPML\FP\Fns; | ||
| 7 | use WPML\FP\Lst; | ||
| 8 | use WPML\FP\Obj; | ||
| 9 | use function WPML\FP\curryN; | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @method static callable|int fromJobId( ...$job_id ) | ||
| 13 | * @method static callable|int|null fromRid( ...$rid ) | ||
| 14 | */ | ||
| 15 | class Map { | ||
| 16 | use Macroable; | ||
| 17 | |||
| 18 | private static $rid_to_jobId = []; | ||
| 19 | |||
| 20 | public static function init() { | ||
| 21 | self::$rid_to_jobId = []; | ||
| 22 | |||
| 23 | self::macro( 'fromJobId', curryN( 1, Fns::memorize( function ( $jobId ) { | ||
| 24 | $rid = Obj::prop( $jobId, array_flip( array_filter( self::$rid_to_jobId ) ) ); | ||
| 25 | if ( $rid ) { | ||
| 26 | return $rid; | ||
| 27 | } | ||
| 28 | |||
| 29 | $rid = self::ridFromDB( $jobId ); | ||
| 30 | self::$rid_to_jobId[$rid] = $jobId; | ||
| 31 | |||
| 32 | return $rid; | ||
| 33 | }))); | ||
| 34 | |||
| 35 | self::macro( 'fromRid', curryN( 1, function ( $rid ) { | ||
| 36 | $jobId = Obj::prop( $rid, self::$rid_to_jobId ); | ||
| 37 | if ( $jobId ) { | ||
| 38 | return $jobId; | ||
| 39 | } | ||
| 40 | |||
| 41 | $jobId = self::jobIdFromDB( $rid ); | ||
| 42 | self::$rid_to_jobId[ $rid ] = $jobId; | ||
| 43 | |||
| 44 | return $jobId; | ||
| 45 | } ) ); | ||
| 46 | } | ||
| 47 | |||
| 48 | public static function jobIdFromDB( $rid ) { | ||
| 49 | global $wpdb; | ||
| 50 | return (int) $wpdb->get_var( | ||
| 51 | $wpdb->prepare( | ||
| 52 | "SELECT MAX(job_id) FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d", | ||
| 53 | $rid | ||
| 54 | ) | ||
| 55 | ); | ||
| 56 | } | ||
| 57 | |||
| 58 | public static function ridFromDB( $jobId ) { | ||
| 59 | global $wpdb; | ||
| 60 | return (int) $wpdb->get_var( | ||
| 61 | $wpdb->prepare( | ||
| 62 | "SELECT rid FROM {$wpdb->prefix}icl_translate_job WHERE job_id=%d", | ||
| 63 | $jobId | ||
| 64 | ) | ||
| 65 | ); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | Map::init(); |
This diff is collapsed.
Click to expand it.
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API; | ||
| 4 | |||
| 5 | use WPML\FP\Either; | ||
| 6 | use WPML\TM\TranslationProxy\Services\AuthorizationFactory; | ||
| 7 | |||
| 8 | class TranslationServices { | ||
| 9 | |||
| 10 | /** | ||
| 11 | * @var AuthorizationFactory | ||
| 12 | */ | ||
| 13 | private $authorizationFactory; | ||
| 14 | |||
| 15 | /** | ||
| 16 | * @param AuthorizationFactory $authorizationFactory | ||
| 17 | */ | ||
| 18 | public function __construct( AuthorizationFactory $authorizationFactory ) { | ||
| 19 | $this->authorizationFactory = $authorizationFactory; | ||
| 20 | } | ||
| 21 | |||
| 22 | /** | ||
| 23 | * @param string $suid | ||
| 24 | * | ||
| 25 | * @return Either | ||
| 26 | */ | ||
| 27 | public function selectBySUID( $suid ) { | ||
| 28 | try { | ||
| 29 | $service = \TranslationProxy_Service::get_service_by_suid( $suid ); | ||
| 30 | |||
| 31 | return $this->selectByServiceId( $service->id ); | ||
| 32 | } catch ( \Exception $e ) { | ||
| 33 | return Either::left( sprintf( __( 'Service with SUID=%s cannot be found', ' sitepress-multilingual-cms' ), $suid ) ); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | /** | ||
| 38 | * @param int $serviceId | ||
| 39 | * | ||
| 40 | * @return Either | ||
| 41 | */ | ||
| 42 | public function selectByServiceId( $serviceId ) { | ||
| 43 | $result = \TranslationProxy::select_service( $serviceId ); | ||
| 44 | |||
| 45 | return \is_wp_error( $result ) ? Either::left( $result->get_error_message() ) : Either::of( $serviceId ); | ||
| 46 | } | ||
| 47 | |||
| 48 | public function deselect() { | ||
| 49 | if ( \TranslationProxy::get_current_service_id() ) { | ||
| 50 | \TranslationProxy::clear_preferred_translation_service(); | ||
| 51 | \TranslationProxy::deselect_active_service(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | public function authorize( $apiToken ) { | ||
| 56 | $authorization = $this->authorizationFactory->create(); | ||
| 57 | try { | ||
| 58 | $authorization->authorize( (object) [ 'api_token' => $apiToken ] ); | ||
| 59 | |||
| 60 | return Either::of( true ); | ||
| 61 | } catch ( \Exception $e ) { | ||
| 62 | $authorization->deauthorize(); | ||
| 63 | |||
| 64 | return Either::left( $e->getMessage() ); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /** | ||
| 69 | * @return null|\TranslationProxy_Service | ||
| 70 | */ | ||
| 71 | public function getCurrentService() { | ||
| 72 | $service = \TranslationProxy::get_current_service(); | ||
| 73 | |||
| 74 | return ! is_wp_error( $service ) ? $service : null; | ||
| 75 | } | ||
| 76 | |||
| 77 | public function isAnyActive() { | ||
| 78 | return $this->getCurrentService() !== null; | ||
| 79 | } | ||
| 80 | |||
| 81 | public function isAuthorized() { | ||
| 82 | return \TranslationProxy::is_current_service_active_and_authenticated(); | ||
| 83 | } | ||
| 84 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\TM\API; | ||
| 4 | |||
| 5 | use WPML\FP\Fns; | ||
| 6 | use WPML\FP\Obj; | ||
| 7 | use WPML\LIB\WP\User; | ||
| 8 | |||
| 9 | class Translators { | ||
| 10 | /** | ||
| 11 | * @return \WPML_Translator | ||
| 12 | */ | ||
| 13 | public static function getCurrent() { | ||
| 14 | $translator = wpml_load_core_tm()->get_current_translator(); | ||
| 15 | |||
| 16 | if ( ! $translator->ID ) { | ||
| 17 | return $translator; | ||
| 18 | } | ||
| 19 | |||
| 20 | if ( empty( $translator->language_pairs ) && User::canManageTranslations() ) { | ||
| 21 | return Obj::assoc( 'language_pairs', \WPML_All_Language_Pairs::get(), $translator ); | ||
| 22 | } | ||
| 23 | |||
| 24 | return Obj::over( | ||
| 25 | Obj::lensProp( 'language_pairs' ), | ||
| 26 | Fns::map( Obj::keys() ), | ||
| 27 | $translator | ||
| 28 | ); | ||
| 29 | } | ||
| 30 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | if ( ! defined( 'WPML_PAGE_BUILDERS_LOADED' ) ) { | ||
| 4 | throw new Exception( 'This file should be called from the loader only.' ); | ||
| 5 | } | ||
| 6 | |||
| 7 | require_once __DIR__ . '/classes/OldPlugin.php'; | ||
| 8 | if ( WPML\PB\OldPlugin::handle() ) { | ||
| 9 | return; | ||
| 10 | } | ||
| 11 | |||
| 12 | define( 'WPML_PAGE_BUILDERS_VERSION', '2.1.2' ); | ||
| 13 | define( 'WPML_PAGE_BUILDERS_PATH', __DIR__ ); | ||
| 14 | |||
| 15 | if ( ! class_exists( 'WPML_Core_Version_Check' ) ) { | ||
| 16 | require_once WPML_PAGE_BUILDERS_PATH . '/vendor/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php'; | ||
| 17 | } | ||
| 18 | |||
| 19 | if ( ! WPML_Core_Version_Check::is_ok( WPML_PAGE_BUILDERS_PATH . '/wpml-dependencies.json' ) ) { | ||
| 20 | return; | ||
| 21 | } | ||
| 22 | |||
| 23 | require_once WPML_PAGE_BUILDERS_PATH . '/vendor/autoload.php'; | ||
| 24 | |||
| 25 | \WPML\PB\App::run(); | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
wp-content/plugins/sitepress-multilingual-cms 2/addons/wpml-page-builders/classes/App.php
0 → 100644
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB; | ||
| 4 | |||
| 5 | class App { | ||
| 6 | |||
| 7 | public static function run() { | ||
| 8 | global $sitepress, $wpdb; | ||
| 9 | |||
| 10 | LegacyIntegration::load(); | ||
| 11 | |||
| 12 | if ( | ||
| 13 | $sitepress->is_setup_complete() | ||
| 14 | && has_action( 'wpml_before_init', 'load_wpml_st_basics' ) | ||
| 15 | ) { | ||
| 16 | if ( self::shouldLoadTMHooks() ) { | ||
| 17 | $page_builder_hooks = new \WPML_TM_Page_Builders_Hooks( | ||
| 18 | new \WPML_TM_Page_Builders( $sitepress ), | ||
| 19 | $sitepress | ||
| 20 | ); | ||
| 21 | |||
| 22 | $page_builder_hooks->init_hooks(); | ||
| 23 | } | ||
| 24 | |||
| 25 | $app = new \WPML_Page_Builders_App( new \WPML_Page_Builders_Defined() ); | ||
| 26 | $app->add_hooks(); | ||
| 27 | |||
| 28 | new \WPML_PB_Loader( new \WPML_ST_Settings() ); | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | /** | ||
| 33 | * @return bool | ||
| 34 | */ | ||
| 35 | private static function shouldLoadTMHooks() { | ||
| 36 | return defined( 'WPML_TM_VERSION' ) | ||
| 37 | && ( | ||
| 38 | is_admin() | ||
| 39 | || ( defined( 'XMLRPC_REQUEST' ) && constant( 'XMLRPC_REQUEST' ) ) | ||
| 40 | || wpml_is_rest_request() | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\BeaverThemer; | ||
| 4 | |||
| 5 | class HooksFactory implements \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader { | ||
| 6 | |||
| 7 | public function create() { | ||
| 8 | |||
| 9 | if ( self::isActive() ) { | ||
| 10 | return [ | ||
| 11 | new LocationHooks(), | ||
| 12 | ]; | ||
| 13 | } | ||
| 14 | |||
| 15 | return null; | ||
| 16 | } | ||
| 17 | |||
| 18 | /** | ||
| 19 | * @return bool | ||
| 20 | */ | ||
| 21 | public static function isActive() { | ||
| 22 | return defined( 'FL_THEME_BUILDER_VERSION' ); | ||
| 23 | } | ||
| 24 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\BeaverThemer; | ||
| 4 | |||
| 5 | use WPML\Convert\Ids; | ||
| 6 | use WPML\LIB\WP\Hooks; | ||
| 7 | use function WPML\FP\spreadArgs; | ||
| 8 | |||
| 9 | class LocationHooks implements \IWPML_Backend_Action { | ||
| 10 | |||
| 11 | const LAYOUT_CPT = 'fl-theme-layout'; | ||
| 12 | |||
| 13 | const LOCATIONS_RULES_KEY = '_fl_theme_builder_locations'; | ||
| 14 | |||
| 15 | const EXCLUSIONS_RULES_KEY = '_fl_theme_builder_exclusions'; | ||
| 16 | |||
| 17 | public function add_hooks() { | ||
| 18 | Hooks::onFilter( 'wpml_pb_copy_meta_field', 10, 4 ) | ||
| 19 | ->then( spreadArgs( [ $this, 'translateLocationRulesMeta' ] ) ); | ||
| 20 | } | ||
| 21 | |||
| 22 | /** | ||
| 23 | * @param mixed $copiedValue | ||
| 24 | * @param int $translatedPostId | ||
| 25 | * @param int $originalPostId | ||
| 26 | * @param string $metaKey | ||
| 27 | * | ||
| 28 | * @return mixed | ||
| 29 | */ | ||
| 30 | public function translateLocationRulesMeta( $copiedValue, $translatedPostId, $originalPostId, $metaKey ) { | ||
| 31 | if ( in_array( $metaKey, [ self::LOCATIONS_RULES_KEY, self::EXCLUSIONS_RULES_KEY ], true ) ) { | ||
| 32 | $targetLang = self::getLayoutLanguage( $translatedPostId ); | ||
| 33 | |||
| 34 | foreach ( $copiedValue as &$rule ) { | ||
| 35 | $rule = $this->translateRule( $rule, $targetLang ); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | return $copiedValue; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Translate IDs in locations rules. | ||
| 44 | * | ||
| 45 | * Location rules are an array of rules. Each rule is separated by (:). | ||
| 46 | * General rules can be like: | ||
| 47 | * 'general:site' | ||
| 48 | * 'general:archive' | ||
| 49 | * 'general:single' | ||
| 50 | * 'general:404' | ||
| 51 | * 'post:post' | ||
| 52 | * 'post:page' | ||
| 53 | * | ||
| 54 | * This translates the cases for posts and taxonomies. Their rules can be like: | ||
| 55 | * 'post:page:12' | ||
| 56 | * 'post:post:taxonomy:category:45' | ||
| 57 | * | ||
| 58 | * @param string $rule | ||
| 59 | * @param string $targetLangCode | ||
| 60 | * | ||
| 61 | * @return string | ||
| 62 | */ | ||
| 63 | private function translateRule( $rule, $targetLangCode ) { | ||
| 64 | $parts = explode( ':', $rule ); | ||
| 65 | |||
| 66 | if ( 3 === count( $parts ) ) { | ||
| 67 | $rule = implode( ':', [ $parts[0], $parts[1], self::translateElement( $parts[2], $parts[1], $targetLangCode ) ] ); | ||
| 68 | } elseif ( 5 === count( $parts ) ) { | ||
| 69 | $rule = implode( ':', [ $parts[0], $parts[1], $parts[2], $parts[3], self::translateElement( $parts[4], $parts[3], $targetLangCode ) ] ); | ||
| 70 | } | ||
| 71 | |||
| 72 | return $rule; | ||
| 73 | } | ||
| 74 | |||
| 75 | /** | ||
| 76 | * @param int $translatedPostId | ||
| 77 | * | ||
| 78 | * @return string|null | ||
| 79 | */ | ||
| 80 | private static function getLayoutLanguage( $translatedPostId ) { | ||
| 81 | return apply_filters( 'wpml_element_language_code', null, [ | ||
| 82 | 'element_id' => $translatedPostId, | ||
| 83 | 'element_type' => self::LAYOUT_CPT, | ||
| 84 | ] ); | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * @param string $elementId | ||
| 89 | * @param string $elementType | ||
| 90 | * @param string $targetLangCode | ||
| 91 | * | ||
| 92 | * @return string | ||
| 93 | */ | ||
| 94 | private static function translateElement( $elementId, $elementType, $targetLangCode ) { | ||
| 95 | return Ids::convert( $elementId, $elementType, true, $targetLangCode ); | ||
| 96 | } | ||
| 97 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\Config; | ||
| 4 | |||
| 5 | class Factory extends \WPML\PB\Config\Factory { | ||
| 6 | |||
| 7 | const DATA = [ | ||
| 8 | 'configRoot' => 'beaver-builder-widgets', | ||
| 9 | 'defaultConditionKey' => 'type', | ||
| 10 | 'pbKey' => 'beaver-builder', | ||
| 11 | 'translatableWidgetsHook' => 'wpml_beaver_builder_modules_to_translate', | ||
| 12 | ]; | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @inheritDoc | ||
| 16 | */ | ||
| 17 | protected function getPbData( $key ) { | ||
| 18 | return self::DATA[ $key ]; | ||
| 19 | } | ||
| 20 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\LIB\WP\Hooks; | ||
| 7 | use function WPML\FP\spreadArgs; | ||
| 8 | |||
| 9 | class Editor implements \IWPML_Frontend_Action { | ||
| 10 | |||
| 11 | public function add_hooks() { | ||
| 12 | Hooks::onFilter( 'wpml_pb_is_editing_translation_with_native_editor', 10, 2 ) | ||
| 13 | ->then( spreadArgs( function( $isTranslationWithNativeEditor, $translatedPostId ) { | ||
| 14 | return $isTranslationWithNativeEditor | ||
| 15 | || ( | ||
| 16 | Obj::path( [ 'fl_builder_data', 'action' ], $_POST ) === 'save_layout' | ||
| 17 | && (int) Obj::path( [ 'fl_builder_data', 'post_id' ], $_POST ) === $translatedPostId | ||
| 18 | ); | ||
| 19 | |||
| 20 | } ) ); | ||
| 21 | } | ||
| 22 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\Hooks; | ||
| 4 | |||
| 5 | class Menu implements \IWPML_Frontend_Action { | ||
| 6 | const TERM_TAXONOMY = 'nav_menu'; | ||
| 7 | |||
| 8 | public function add_hooks() { | ||
| 9 | add_filter( 'fl_builder_menu_module_core_menu', [ $this, 'adjustTranslatedMenu' ], 10, 2 ); | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param string $menu | ||
| 14 | * @param object $settings module settings object. | ||
| 15 | * | ||
| 16 | * @return string | ||
| 17 | */ | ||
| 18 | public function adjustTranslatedMenu( $menu, $settings ) { | ||
| 19 | $targetMenuSlug = $settings->menu; | ||
| 20 | |||
| 21 | $targetMenu = get_term_by( 'slug', $targetMenuSlug, self::TERM_TAXONOMY ); | ||
| 22 | if ( $targetMenu ) { | ||
| 23 | $menu = $targetMenu->slug; | ||
| 24 | } | ||
| 25 | |||
| 26 | return $menu; | ||
| 27 | } | ||
| 28 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\TranslationJob; | ||
| 4 | |||
| 5 | use WPML_Beaver_Builder_Data_Settings; | ||
| 6 | |||
| 7 | class Hooks implements \IWPML_Backend_Action, \IWPML_Frontend_Action, \IWPML_DIC_Action { | ||
| 8 | |||
| 9 | /** @var WPML_Beaver_Builder_Data_Settings $dataSettings */ | ||
| 10 | private $dataSettings; | ||
| 11 | |||
| 12 | public function __construct( WPML_Beaver_Builder_Data_Settings $dataSettings ) { | ||
| 13 | $this->dataSettings = $dataSettings; | ||
| 14 | } | ||
| 15 | |||
| 16 | public function add_hooks() { | ||
| 17 | add_filter( 'wpml_tm_translation_job_data', [ $this, 'filterFieldsByPageBuilderKind' ], PHP_INT_MAX, 2 ); | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * @param array $translationPackage | ||
| 22 | * @param \stdClass|\WP_Post $post | ||
| 23 | * | ||
| 24 | * @return array | ||
| 25 | */ | ||
| 26 | public function filterFieldsByPageBuilderKind( array $translationPackage, $post ) { | ||
| 27 | if ( ! $this->isPostPackage( $translationPackage, $post ) ) { | ||
| 28 | return $translationPackage; | ||
| 29 | } | ||
| 30 | |||
| 31 | if ( $this->dataSettings->is_handling_post( $post->ID ) ) { | ||
| 32 | return $this->removeFieldsFromKind( $translationPackage, $post->ID, 'gutenberg' ); | ||
| 33 | } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * | ||
| 37 | */ | ||
| 38 | return $this->removeFieldsFromKind( $translationPackage, $post->ID, 'beaver-builder' ); | ||
| 39 | } | ||
| 40 | |||
| 41 | /** | ||
| 42 | * @param array $translationPackage | ||
| 43 | * @param \stdClass|\WP_Post $post | ||
| 44 | * | ||
| 45 | * @return bool | ||
| 46 | */ | ||
| 47 | private function isPostPackage( array $translationPackage, $post ) { | ||
| 48 | return 'external' !== $translationPackage['type'] && isset( $post->ID ); | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | ||
| 52 | * @param array $translationPackage | ||
| 53 | * @param int $postId | ||
| 54 | * @param string $kindSlug | ||
| 55 | * | ||
| 56 | * @return array | ||
| 57 | */ | ||
| 58 | private function removeFieldsFromKind( array $translationPackage, $postId, $kindSlug ) { | ||
| 59 | $packageIdToRemove = wpml_collect( apply_filters( 'wpml_st_get_post_string_packages', [], $postId ) ) | ||
| 60 | ->pluck( 'ID', 'kind_slug' ) | ||
| 61 | ->get( $kindSlug ); | ||
| 62 | |||
| 63 | if ( $packageIdToRemove ) { | ||
| 64 | $isFieldFromPackageToRemove = function( $value, $key ) use ( $packageIdToRemove ) { | ||
| 65 | return preg_match( '/^package-string-' . $packageIdToRemove . '-/', $key ); | ||
| 66 | }; | ||
| 67 | |||
| 68 | $translationPackage['contents'] = wpml_collect( $translationPackage['contents'] ) | ||
| 69 | ->reject( $isFieldFromPackageToRemove ) | ||
| 70 | ->toArray(); | ||
| 71 | } | ||
| 72 | |||
| 73 | return $translationPackage; | ||
| 74 | } | ||
| 75 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | use WPML\PB\BeaverBuilder\BeaverThemer\HooksFactory as BeaverThemer; | ||
| 4 | |||
| 5 | class WPML_Beaver_Builder_Data_Settings implements IWPML_Page_Builders_Data_Settings { | ||
| 6 | |||
| 7 | /** | ||
| 8 | * @return string | ||
| 9 | */ | ||
| 10 | public function get_meta_field() { | ||
| 11 | return '_fl_builder_data'; | ||
| 12 | } | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @return string | ||
| 16 | */ | ||
| 17 | public function get_node_id_field() { | ||
| 18 | return 'node'; | ||
| 19 | } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @return array | ||
| 23 | */ | ||
| 24 | public function get_fields_to_copy() { | ||
| 25 | $fields = [ | ||
| 26 | '_fl_builder_draft_settings', | ||
| 27 | '_fl_builder_data_settings', | ||
| 28 | '_fl_builder_enabled', | ||
| 29 | ]; | ||
| 30 | |||
| 31 | if ( BeaverThemer::isActive() ) { | ||
| 32 | return array_merge( | ||
| 33 | $fields, | ||
| 34 | [ | ||
| 35 | '_fl_theme_builder_locations', | ||
| 36 | '_fl_theme_builder_exclusions', | ||
| 37 | '_fl_theme_builder_edit_mode', | ||
| 38 | ] | ||
| 39 | ); | ||
| 40 | } | ||
| 41 | |||
| 42 | return $fields; | ||
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 46 | * @param array $data | ||
| 47 | * | ||
| 48 | * @return array | ||
| 49 | */ | ||
| 50 | public function convert_data_to_array( $data ) { | ||
| 51 | return $data; | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * @param array $data | ||
| 56 | * | ||
| 57 | * @return array | ||
| 58 | */ | ||
| 59 | public function prepare_data_for_saving( array $data ) { | ||
| 60 | return $this->slash( $data ); | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * @return string | ||
| 65 | */ | ||
| 66 | public function get_pb_name() { | ||
| 67 | return 'Beaver builder'; | ||
| 68 | } | ||
| 69 | |||
| 70 | /** | ||
| 71 | * @return array | ||
| 72 | */ | ||
| 73 | public function get_fields_to_save() { | ||
| 74 | return array( '_fl_builder_data', '_fl_builder_draft' ); | ||
| 75 | } | ||
| 76 | |||
| 77 | public function add_hooks(){} | ||
| 78 | |||
| 79 | /** | ||
| 80 | * Adds slashes to data going into the database as WordPress | ||
| 81 | * removes them when we save using update_metadata. This is done | ||
| 82 | * to ensure slashes in user input aren't removed. | ||
| 83 | * | ||
| 84 | * Inspired by `\FLBuilderModel::slash_settings` | ||
| 85 | * | ||
| 86 | * @param mixed $data The data to slash. | ||
| 87 | * | ||
| 88 | * @return mixed The slashed data. | ||
| 89 | */ | ||
| 90 | private function slash( $data ) { | ||
| 91 | if ( is_array( $data ) ) { | ||
| 92 | foreach ( $data as $key => $val ) { | ||
| 93 | $data[ $key ] = $this->slash( $val ); | ||
| 94 | } | ||
| 95 | } elseif ( is_object( $data ) ) { | ||
| 96 | foreach ( $data as $key => $val ) { | ||
| 97 | $data->$key = $this->slash( $val ); | ||
| 98 | } | ||
| 99 | } elseif ( is_string( $data ) ) { | ||
| 100 | $data = wp_slash( $data ); | ||
| 101 | } | ||
| 102 | |||
| 103 | return $data; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * @param int $postId | ||
| 108 | * | ||
| 109 | * @return bool | ||
| 110 | */ | ||
| 111 | public function is_handling_post( $postId ) { | ||
| 112 | return (bool) get_post_meta( $postId, '_fl_builder_enabled', true ); | ||
| 113 | } | ||
| 114 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_PB_Beaver_Builder_Handle_Custom_Fields_Factory implements IWPML_Backend_Action_Loader, IWPML_AJAX_Action_Loader, IWPML_Frontend_Action_Loader { | ||
| 4 | |||
| 5 | public function create() { | ||
| 6 | return new WPML_PB_Handle_Custom_Fields( new WPML_Beaver_Builder_Data_Settings() ); | ||
| 7 | } | ||
| 8 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Integration_Factory { | ||
| 4 | |||
| 5 | const SLUG = 'beaver-builder'; | ||
| 6 | |||
| 7 | public function create() { | ||
| 8 | $action_filter_loader = new WPML_Action_Filter_Loader(); | ||
| 9 | $action_filter_loader->load( | ||
| 10 | array( | ||
| 11 | 'WPML_PB_Beaver_Builder_Handle_Custom_Fields_Factory', | ||
| 12 | 'WPML_Beaver_Builder_Media_Hooks_Factory', | ||
| 13 | \WPML\PB\BeaverBuilder\TranslationJob\Hooks::class, | ||
| 14 | \WPML\PB\BeaverBuilder\Config\Factory::class, | ||
| 15 | \WPML\PB\BeaverBuilder\Hooks\Editor::class, | ||
| 16 | \WPML\PB\BeaverBuilder\Hooks\Menu::class, | ||
| 17 | |||
| 18 | // BeaverThemer. | ||
| 19 | \WPML\PB\BeaverBuilder\BeaverThemer\HooksFactory::class, | ||
| 20 | ) | ||
| 21 | ); | ||
| 22 | |||
| 23 | $nodes = new WPML_Beaver_Builder_Translatable_Nodes(); | ||
| 24 | $data_settings = new WPML_Beaver_Builder_Data_Settings(); | ||
| 25 | |||
| 26 | $string_registration_factory = new WPML_String_Registration_Factory( $data_settings->get_pb_name() ); | ||
| 27 | $string_registration = $string_registration_factory->create(); | ||
| 28 | |||
| 29 | $register_strings = new WPML_Beaver_Builder_Register_Strings( $nodes, $data_settings, $string_registration ); | ||
| 30 | $update_translation = new WPML_Beaver_Builder_Update_Translation( $nodes, $data_settings ); | ||
| 31 | |||
| 32 | return new WPML_Page_Builders_Integration( $register_strings, $update_translation, $data_settings ); | ||
| 33 | } | ||
| 34 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | /** | ||
| 4 | * Class WPML_Beaver_Builder_Register_Strings | ||
| 5 | */ | ||
| 6 | class WPML_Beaver_Builder_Register_Strings extends WPML_Page_Builders_Register_Strings { | ||
| 7 | |||
| 8 | /** | ||
| 9 | * @param array $data_array | ||
| 10 | * @param array $package | ||
| 11 | */ | ||
| 12 | protected function register_strings_for_modules( array $data_array, array $package ) { | ||
| 13 | foreach ( $data_array as $data ) { | ||
| 14 | if ( is_array( $data ) ) { | ||
| 15 | $data = $this->sort_modules_before_string_registration( $data ); | ||
| 16 | $this->register_strings_for_modules( $data, $package ); | ||
| 17 | } elseif ( is_object( $data ) ) { | ||
| 18 | if ( isset( $data->type, $data->node, $data->settings ) && 'module' === $data->type && ! $this->is_embedded_global_module( $data ) ) { | ||
| 19 | $this->register_strings_for_node( $data->node, $data->settings, $package ); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | /** | ||
| 26 | * The modules are not in the order they appear on the page, | ||
| 27 | * so we need to sort it before to register the strings. | ||
| 28 | * | ||
| 29 | * @param array $modules | ||
| 30 | * | ||
| 31 | * @return array | ||
| 32 | */ | ||
| 33 | private function sort_modules_before_string_registration( array $modules ) { | ||
| 34 | if ( count( $modules ) > 1 ) { | ||
| 35 | uasort( $modules, array( $this, 'sort_modules_by_position_only' ) ); | ||
| 36 | return $this->sort_modules_by_parent_and_child( $modules ); | ||
| 37 | } | ||
| 38 | |||
| 39 | return $modules; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * We receive all modules as a flat tree and we need to reorder from: | ||
| 44 | * - child A | ||
| 45 | * - child A | ||
| 46 | * - parent A | ||
| 47 | * - child B | ||
| 48 | * - parent B | ||
| 49 | * - child B | ||
| 50 | * - child C | ||
| 51 | * | ||
| 52 | * To: | ||
| 53 | * - parent A | ||
| 54 | * - child A | ||
| 55 | * - child B | ||
| 56 | * - parent B | ||
| 57 | * - child A | ||
| 58 | * - child B | ||
| 59 | * - child C | ||
| 60 | * | ||
| 61 | * The relative positions are already sorted by `sort_modules_by_position_only` | ||
| 62 | * | ||
| 63 | * @param array $all_modules | ||
| 64 | * @param string|null $parent_hash | ||
| 65 | * @param array $sorted_modules | ||
| 66 | * | ||
| 67 | * @return array | ||
| 68 | */ | ||
| 69 | private function sort_modules_by_parent_and_child( array $all_modules, $parent_hash = null, array $sorted_modules = array() ){ | ||
| 70 | foreach ( $all_modules as $hash => $module ) { | ||
| 71 | |||
| 72 | if ( $module->parent === $parent_hash ) { | ||
| 73 | $sorted_modules[ $hash ] = $module; | ||
| 74 | unset( $all_modules[ $hash ] ); | ||
| 75 | $sorted_modules = $this->sort_modules_by_parent_and_child( $all_modules, $module->node, $sorted_modules ); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | return $sorted_modules; | ||
| 80 | } | ||
| 81 | |||
| 82 | /** | ||
| 83 | * @param stdClass $a | ||
| 84 | * @param stdClass $b | ||
| 85 | * | ||
| 86 | * @return int | ||
| 87 | */ | ||
| 88 | private function sort_modules_by_position_only( stdClass $a, stdClass $b ) { | ||
| 89 | return ( (int) $a->position < (int) $b->position ) ? -1 : 1; | ||
| 90 | } | ||
| 91 | |||
| 92 | /** | ||
| 93 | * @param object $data | ||
| 94 | * | ||
| 95 | * @return bool | ||
| 96 | */ | ||
| 97 | private function is_embedded_global_module( $data ) { | ||
| 98 | return ! empty( $data->template_node_id ) && isset( $data->node ) && $data->template_node_id !== $data->node; | ||
| 99 | } | ||
| 100 | } |
This diff is collapsed.
Click to expand it.
| 1 | <?php | ||
| 2 | |||
| 3 | /** | ||
| 4 | * Class WPML_Beaver_Builder_Update_Translation | ||
| 5 | */ | ||
| 6 | class WPML_Beaver_Builder_Update_Translation extends WPML_Page_Builders_Update_Translation { | ||
| 7 | |||
| 8 | /** @param array $data_array */ | ||
| 9 | public function update_strings_in_modules( array &$data_array ) { | ||
| 10 | foreach ( $data_array as &$data ) { | ||
| 11 | if ( is_array( $data ) ) { | ||
| 12 | $this->update_strings_in_modules( $data ); | ||
| 13 | } elseif ( is_object( $data ) ) { | ||
| 14 | if ( isset( $data->type, $data->node, $data->settings ) && 'module' === $data->type ) { | ||
| 15 | $data->settings = $this->update_strings_in_node( $data->node, $data->settings ); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @param string $node_id | ||
| 23 | * @param array $settings | ||
| 24 | * | ||
| 25 | * @return mixed | ||
| 26 | */ | ||
| 27 | public function update_strings_in_node( $node_id, $settings ) { | ||
| 28 | $strings = $this->translatable_nodes->get( $node_id, $settings ); | ||
| 29 | foreach ( $strings as $string ) { | ||
| 30 | $translation = $this->get_translation( $string ); | ||
| 31 | $settings = $this->translatable_nodes->update( $node_id, $settings, $translation ); | ||
| 32 | } | ||
| 33 | return $settings; | ||
| 34 | } | ||
| 35 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Hooks_Factory implements IWPML_Backend_Action_Loader, IWPML_Frontend_Action_Loader { | ||
| 4 | |||
| 5 | public function create() { | ||
| 6 | return new WPML_Page_Builders_Media_Hooks( | ||
| 7 | new WPML_Beaver_Builder_Update_Media_Factory(), | ||
| 8 | WPML_Beaver_Builder_Integration_Factory::SLUG | ||
| 9 | ); | ||
| 10 | } | ||
| 11 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Node_Provider { | ||
| 4 | |||
| 5 | /** @var WPML_Page_Builders_Media_Translate $media_translate */ | ||
| 6 | private $media_translate; | ||
| 7 | |||
| 8 | /** @var WPML_Beaver_Builder_Media_Node[] */ | ||
| 9 | private $nodes = array(); | ||
| 10 | |||
| 11 | public function __construct( WPML_Page_Builders_Media_Translate $media_translate ) { | ||
| 12 | $this->media_translate = $media_translate; | ||
| 13 | } | ||
| 14 | |||
| 15 | /** | ||
| 16 | * @param string $type | ||
| 17 | * | ||
| 18 | * @return WPML_Beaver_Builder_Media_Node|null | ||
| 19 | */ | ||
| 20 | public function get( $type ) { | ||
| 21 | if ( ! array_key_exists( $type, $this->nodes ) ) { | ||
| 22 | switch ( $type ) { | ||
| 23 | case 'photo': | ||
| 24 | $node = new WPML_Beaver_Builder_Media_Node_Photo( $this->media_translate ); | ||
| 25 | break; | ||
| 26 | |||
| 27 | case 'gallery': | ||
| 28 | $node = new WPML_Beaver_Builder_Media_Node_Gallery( $this->media_translate ); | ||
| 29 | break; | ||
| 30 | |||
| 31 | case 'content-slider': | ||
| 32 | $node = new WPML_Beaver_Builder_Media_Node_Content_Slider( $this->media_translate ); | ||
| 33 | break; | ||
| 34 | |||
| 35 | case 'slideshow': | ||
| 36 | $node = new WPML_Beaver_Builder_Media_Node_Slideshow( $this->media_translate ); | ||
| 37 | break; | ||
| 38 | |||
| 39 | default: | ||
| 40 | $node = null; | ||
| 41 | } | ||
| 42 | |||
| 43 | $this->nodes[ $type ] = $node; | ||
| 44 | } | ||
| 45 | |||
| 46 | return $this->nodes[ $type ]; | ||
| 47 | } | ||
| 48 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Nodes_Iterator implements IWPML_PB_Media_Nodes_Iterator { | ||
| 4 | |||
| 5 | /** @var WPML_Beaver_Builder_Media_Node_Provider $node_provider */ | ||
| 6 | private $node_provider; | ||
| 7 | |||
| 8 | public function __construct( WPML_Beaver_Builder_Media_Node_Provider $node_provider ) { | ||
| 9 | $this->node_provider = $node_provider; | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param array $data_array | ||
| 14 | * @param string $lang | ||
| 15 | * @param string $source_lang | ||
| 16 | * | ||
| 17 | * @return array | ||
| 18 | */ | ||
| 19 | public function translate( $data_array, $lang, $source_lang ) { | ||
| 20 | foreach ( $data_array as &$data ) { | ||
| 21 | if ( is_array( $data ) ) { | ||
| 22 | $data = $this->translate( $data, $lang, $source_lang ); | ||
| 23 | } elseif ( is_object( $data ) | ||
| 24 | && isset( $data->type ) && 'module' === $data->type | ||
| 25 | && isset( $data->settings ) && isset( $data->settings->type ) | ||
| 26 | ) { | ||
| 27 | $data->settings = $this->translate_node( $data->settings, $lang, $source_lang ); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | return $data_array; | ||
| 32 | } | ||
| 33 | |||
| 34 | /** | ||
| 35 | * @param stdClass $settings | ||
| 36 | * @param string $lang | ||
| 37 | * @param string $source_lang | ||
| 38 | * | ||
| 39 | * @return stdClass | ||
| 40 | */ | ||
| 41 | private function translate_node( $settings, $lang, $source_lang ) { | ||
| 42 | $node = $this->node_provider->get( $settings->type ); | ||
| 43 | |||
| 44 | if ( $node ) { | ||
| 45 | $settings = $node->translate( $settings, $lang, $source_lang ); | ||
| 46 | } | ||
| 47 | |||
| 48 | return $settings; | ||
| 49 | } | ||
| 50 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Update_Media_Factory implements IWPML_PB_Media_Update_Factory { | ||
| 4 | |||
| 5 | |||
| 6 | public function create() { | ||
| 7 | global $sitepress; | ||
| 8 | |||
| 9 | $media_translate = new WPML_Page_Builders_Media_Translate( | ||
| 10 | new WPML_Translation_Element_Factory( $sitepress ), | ||
| 11 | new WPML_Media_Image_Translate( $sitepress, new WPML_Media_Attachment_By_URL_Factory(), new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory() ) | ||
| 12 | ); | ||
| 13 | |||
| 14 | return new WPML_Page_Builders_Update_Media( | ||
| 15 | new WPML_Page_Builders_Update( new WPML_Beaver_Builder_Data_Settings_For_Media() ), | ||
| 16 | new WPML_Translation_Element_Factory( $sitepress ), | ||
| 17 | new WPML_Beaver_Builder_Media_Nodes_Iterator( | ||
| 18 | new WPML_Beaver_Builder_Media_Node_Provider( $media_translate ) | ||
| 19 | ), | ||
| 20 | new WPML_Page_Builders_Media_Usage( $media_translate, new WPML_Media_Usage_Factory() ) | ||
| 21 | ); | ||
| 22 | } | ||
| 23 | } | ||
| 24 |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Node_Content_Slider extends WPML_Beaver_Builder_Media_Node { | ||
| 4 | |||
| 5 | private $property_prefixes = array( | ||
| 6 | 'bg_', // i.e. `bg_photo` for an ID or `bg_photo_src` for a URL | ||
| 7 | 'fg_', | ||
| 8 | 'r_', | ||
| 9 | ); | ||
| 10 | |||
| 11 | public function translate( $node_data, $target_lang, $source_lang ) { | ||
| 12 | if ( ! isset( $node_data->slides ) || ! is_array( $node_data->slides ) ) { | ||
| 13 | return $node_data; | ||
| 14 | } | ||
| 15 | |||
| 16 | foreach ( $node_data->slides as &$slide ) { | ||
| 17 | |||
| 18 | foreach ( $this->property_prefixes as $prefix ) { | ||
| 19 | $id_prop = $prefix . 'photo'; | ||
| 20 | $src_prop = $prefix . 'photo_src'; | ||
| 21 | |||
| 22 | if ( isset( $slide->{$id_prop} ) && $slide->{$id_prop} ) { | ||
| 23 | $slide->{$id_prop} = $this->media_translate->translate_id( $slide->{$id_prop}, $target_lang ); | ||
| 24 | } | ||
| 25 | |||
| 26 | if ( isset( $slide->{$src_prop} ) && $slide->{$src_prop} ) { | ||
| 27 | $slide->{$src_prop} = $this->media_translate->translate_image_url( $slide->{$src_prop}, $target_lang, $source_lang ); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | return $node_data; | ||
| 33 | } | ||
| 34 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Node_Gallery extends WPML_Beaver_Builder_Media_Node { | ||
| 4 | |||
| 5 | public function translate( $node_data, $target_lang, $source_lang ) { | ||
| 6 | foreach ( $node_data->photos as &$photo ) { | ||
| 7 | $photo = $this->media_translate->translate_id( $photo, $target_lang ); | ||
| 8 | } | ||
| 9 | |||
| 10 | foreach ( $node_data->photo_data as &$photo_data ) { | ||
| 11 | $translated_id = $this->media_translate->translate_id( $photo_data->id, $target_lang ); | ||
| 12 | |||
| 13 | if ( $translated_id !== $photo_data->id ) { | ||
| 14 | $translation_data = wp_prepare_attachment_for_js( $translated_id ); | ||
| 15 | $photo_data->id = $translated_id; | ||
| 16 | $photo_data->alt = $translation_data['alt']; | ||
| 17 | $photo_data->caption = $translation_data['caption']; | ||
| 18 | $photo_data->description = $translation_data['description']; | ||
| 19 | $photo_data->title = $translation_data['title']; | ||
| 20 | $photo_data->src = $translation_data['url']; | ||
| 21 | $photo_data->link = $translation_data['url']; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | return $node_data; | ||
| 26 | } | ||
| 27 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Media_Node_Photo extends WPML_Beaver_Builder_Media_Node { | ||
| 4 | |||
| 5 | public function translate( $node_data, $target_lang, $source_lang ) { | ||
| 6 | $translated_id = $this->media_translate->translate_id( $node_data->photo, $target_lang ); | ||
| 7 | |||
| 8 | if ( $translated_id !== $node_data->photo ) { | ||
| 9 | $node_data->photo = $translated_id; | ||
| 10 | $node_data->photo_src = $this->media_translate->translate_image_url( $node_data->photo_src, $target_lang, $source_lang ); | ||
| 11 | $node_data->data = wp_prepare_attachment_for_js( $translated_id ); | ||
| 12 | } | ||
| 13 | |||
| 14 | return $node_data; | ||
| 15 | } | ||
| 16 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | /** | ||
| 4 | * @group media | ||
| 5 | */ | ||
| 6 | class WPML_Beaver_Builder_Media_Node_Slideshow extends WPML_Beaver_Builder_Media_Node { | ||
| 7 | |||
| 8 | private $url_properties = array( | ||
| 9 | 'largeURL', | ||
| 10 | 'x3largeURL', | ||
| 11 | 'thumbURL', | ||
| 12 | ); | ||
| 13 | |||
| 14 | public function translate( $node_data, $target_lang, $source_lang ) { | ||
| 15 | if ( ! isset( $node_data->photos, $node_data->photo_data ) || ! is_array( $node_data->photos ) ) { | ||
| 16 | return $node_data; | ||
| 17 | } | ||
| 18 | |||
| 19 | foreach ( $node_data->photos as &$photo ) { | ||
| 20 | $photo = $this->media_translate->translate_id( $photo, $target_lang ); | ||
| 21 | } | ||
| 22 | |||
| 23 | foreach ( $node_data->photo_data as $photo_id => $photo_data ) { | ||
| 24 | $translated_id = $this->media_translate->translate_id( $photo_id, $target_lang ); | ||
| 25 | |||
| 26 | if ( $translated_id !== $photo_id ) { | ||
| 27 | $translation_data = wp_prepare_attachment_for_js( $translated_id ); | ||
| 28 | $photo_data->caption = $translation_data['caption']; | ||
| 29 | |||
| 30 | foreach ( $this->url_properties as $property ) { | ||
| 31 | |||
| 32 | if ( isset( $photo_data->{$property} ) && $photo_data->{$property} ) { | ||
| 33 | $photo_data->{$property} = $this->media_translate->translate_image_url( $photo_data->{$property}, $target_lang, $source_lang ); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | $node_data->photo_data[ $translated_id ] = $photo_data; | ||
| 38 | unset( $node_data->photo_data[ $photo_id ] ); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | return $node_data; | ||
| 43 | } | ||
| 44 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | abstract class WPML_Beaver_Builder_Media_Node { | ||
| 4 | |||
| 5 | /** @var WPML_Page_Builders_Media_Translate $media_translate */ | ||
| 6 | protected $media_translate; | ||
| 7 | |||
| 8 | public function __construct( WPML_Page_Builders_Media_Translate $media_translate ) { | ||
| 9 | $this->media_translate = $media_translate; | ||
| 10 | } | ||
| 11 | |||
| 12 | abstract function translate( $node_data, $target_lang, $source_lang ); | ||
| 13 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\BeaverBuilder\Modules; | ||
| 4 | |||
| 5 | use WPML\FP\Fns; | ||
| 6 | use WPML\FP\Lst; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | |||
| 9 | class ModuleWithItemsFromConfig extends \WPML_Beaver_Builder_Module_With_Items { | ||
| 10 | |||
| 11 | /** @var array $fieldDefinitions */ | ||
| 12 | private $fieldDefinitions = []; | ||
| 13 | |||
| 14 | /** @var string $itemsField */ | ||
| 15 | private $itemsField; | ||
| 16 | |||
| 17 | /** | ||
| 18 | * @param string $itemsField | ||
| 19 | * @param array $config | ||
| 20 | */ | ||
| 21 | public function __construct( $itemsField, array $config ) { | ||
| 22 | $this->itemsField = $itemsField; | ||
| 23 | $this->init( $config ); | ||
| 24 | } | ||
| 25 | |||
| 26 | private function init( array $config ) { | ||
| 27 | $keyByField = Fns::converge( Lst::zipObj(), [ Lst::pluck( 'field' ), Fns::identity() ] ); | ||
| 28 | $this->fieldDefinitions = $keyByField( $config ); | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * @inheritDoc | ||
| 33 | */ | ||
| 34 | public function get_title( $field ) { | ||
| 35 | return Obj::path( [ $field, 'type' ], $this->fieldDefinitions ); | ||
| 36 | } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * @inheritDoc | ||
| 40 | */ | ||
| 41 | public function get_fields() { | ||
| 42 | return array_keys( $this->fieldDefinitions ); | ||
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 46 | * @inheritDoc | ||
| 47 | */ | ||
| 48 | public function get_editor_type( $field ) { | ||
| 49 | return Obj::path( [ $field, 'editor_type' ], $this->fieldDefinitions ); | ||
| 50 | } | ||
| 51 | |||
| 52 | /** | ||
| 53 | * @inheritDoc | ||
| 54 | */ | ||
| 55 | public function &get_items( $settings ) { | ||
| 56 | return $settings->{$this->itemsField}; | ||
| 57 | } | ||
| 58 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Accordion extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | protected function get_title( $field ) { | ||
| 6 | switch( $field ) { | ||
| 7 | case 'label': | ||
| 8 | return esc_html__( 'Accordion Item Label', 'sitepress' ); | ||
| 9 | |||
| 10 | case 'content': | ||
| 11 | return esc_html__( 'Accordion Item Content', 'sitepress' ); | ||
| 12 | |||
| 13 | default: | ||
| 14 | return ''; | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Content_Slider extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | public function &get_items( $settings ) { | ||
| 6 | return $settings->slides; | ||
| 7 | } | ||
| 8 | |||
| 9 | public function get_fields() { | ||
| 10 | return array( 'title', 'text', 'cta_text', 'link' ); | ||
| 11 | } | ||
| 12 | |||
| 13 | protected function get_title( $field ) { | ||
| 14 | switch( $field ) { | ||
| 15 | case 'title': | ||
| 16 | return esc_html__( 'Content Slider: Slide heading', 'sitepress' ); | ||
| 17 | |||
| 18 | case 'text': | ||
| 19 | return esc_html__( 'Content Slider: Slide content', 'sitepress' ); | ||
| 20 | |||
| 21 | case 'cta_text': | ||
| 22 | return esc_html__( 'Content Slider: Slide call to action text', 'sitepress' ); | ||
| 23 | |||
| 24 | case 'link': | ||
| 25 | return esc_html__( 'Content Slider: Slide call to action link', 'sitepress' ); | ||
| 26 | |||
| 27 | default: | ||
| 28 | return ''; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | protected function get_editor_type( $field ) { | ||
| 33 | switch( $field ) { | ||
| 34 | case 'title': | ||
| 35 | case 'cta_text': | ||
| 36 | return 'LINE'; | ||
| 37 | |||
| 38 | case 'link': | ||
| 39 | return 'LINK'; | ||
| 40 | |||
| 41 | case 'text': | ||
| 42 | return 'VISUAL'; | ||
| 43 | |||
| 44 | default: | ||
| 45 | return ''; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Icon_Group extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | public function &get_items( $settings ) { | ||
| 6 | return $settings->icons; | ||
| 7 | } | ||
| 8 | |||
| 9 | public function get_fields() { | ||
| 10 | return array( 'link' ); | ||
| 11 | } | ||
| 12 | |||
| 13 | protected function get_title( $field ) { | ||
| 14 | switch ( $field ) { | ||
| 15 | case 'link': | ||
| 16 | return esc_html__( 'Icon link', 'sitepress' ); | ||
| 17 | |||
| 18 | default: | ||
| 19 | return ''; | ||
| 20 | |||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | protected function get_editor_type( $field ) { | ||
| 25 | switch ( $field ) { | ||
| 26 | case 'link': | ||
| 27 | return 'LINK'; | ||
| 28 | |||
| 29 | default: | ||
| 30 | return ''; | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | /** | ||
| 4 | * Class WPML_Beaver_Builder_Module_With_Items | ||
| 5 | */ | ||
| 6 | abstract class WPML_Beaver_Builder_Module_With_Items implements IWPML_Page_Builders_Module { | ||
| 7 | |||
| 8 | /** | ||
| 9 | * @param string $field | ||
| 10 | * | ||
| 11 | * @return string | ||
| 12 | */ | ||
| 13 | abstract protected function get_title( $field ); | ||
| 14 | |||
| 15 | /** @return array */ | ||
| 16 | protected function get_fields() { | ||
| 17 | return array( 'label', 'content' ); | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * @param string $field | ||
| 22 | * | ||
| 23 | * @return string | ||
| 24 | */ | ||
| 25 | protected function get_editor_type( $field ) { | ||
| 26 | switch( $field ) { | ||
| 27 | case 'label': | ||
| 28 | return 'LINE'; | ||
| 29 | |||
| 30 | case 'content': | ||
| 31 | return 'VISUAL'; | ||
| 32 | |||
| 33 | default: | ||
| 34 | return ''; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * @param object $settings | ||
| 40 | * | ||
| 41 | * @return array | ||
| 42 | */ | ||
| 43 | protected function &get_items( $settings ) { | ||
| 44 | return $settings->items; | ||
| 45 | } | ||
| 46 | |||
| 47 | /** | ||
| 48 | * @param string|int $node_id | ||
| 49 | * @param object $settings | ||
| 50 | * @param WPML_PB_String[] $strings | ||
| 51 | * | ||
| 52 | * @return WPML_PB_String[] | ||
| 53 | */ | ||
| 54 | public function get( $node_id, $settings, $strings ) { | ||
| 55 | foreach ( $this->get_items( $settings ) as $item ) { | ||
| 56 | foreach( $this->get_fields() as $field ) { | ||
| 57 | if ( is_array( $item->$field ) ) { | ||
| 58 | foreach ( $item->$field as $key => $value ) { | ||
| 59 | $strings[] = new WPML_PB_String( | ||
| 60 | $value, | ||
| 61 | $this->get_string_name( $node_id, $value, $field, $key ), | ||
| 62 | $this->get_title( $field ), | ||
| 63 | $this->get_editor_type( $field ) | ||
| 64 | ); | ||
| 65 | } | ||
| 66 | } else { | ||
| 67 | $strings[] = new WPML_PB_String( | ||
| 68 | $item->$field, | ||
| 69 | $this->get_string_name( $node_id, $item->$field, $field ), | ||
| 70 | $this->get_title( $field ), | ||
| 71 | $this->get_editor_type( $field ) | ||
| 72 | ); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | return $strings; | ||
| 77 | } | ||
| 78 | |||
| 79 | /** | ||
| 80 | * @param string|int $node_id | ||
| 81 | * @param object $settings | ||
| 82 | * @param WPML_PB_String $string | ||
| 83 | * | ||
| 84 | * @return null | ||
| 85 | */ | ||
| 86 | public function update( $node_id, $settings, WPML_PB_String $string ) { | ||
| 87 | foreach ( $this->get_items( $settings ) as &$item ) { | ||
| 88 | foreach( $this->get_fields() as $field ) { | ||
| 89 | if ( is_array( $item->$field ) ) { | ||
| 90 | foreach ( $item->$field as $key => &$value ) { | ||
| 91 | if ( $this->get_string_name( $node_id, $value, $field, $key ) == $string->get_name() ) { | ||
| 92 | $value = $string->get_value(); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } else { | ||
| 96 | if ( $this->get_string_name( $node_id, $item->$field, $field ) == $string->get_name() ) { | ||
| 97 | $item->$field = $string->get_value(); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | return null; | ||
| 104 | } | ||
| 105 | |||
| 106 | private function get_string_name( $node_id, $value, $type, $key = '' ) { | ||
| 107 | return md5( $value ) . '-' . $type . $key . '-' . $node_id; | ||
| 108 | } | ||
| 109 | |||
| 110 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Pricing_Table extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | public function &get_items( $settings ) { | ||
| 6 | return $settings->pricing_columns; | ||
| 7 | } | ||
| 8 | |||
| 9 | public function get_fields() { | ||
| 10 | return array( 'title', 'button_text', 'button_url', 'features', 'price', 'duration' ); | ||
| 11 | } | ||
| 12 | |||
| 13 | protected function get_title( $field ) { | ||
| 14 | switch ( $field ) { | ||
| 15 | case 'title': | ||
| 16 | return esc_html__( 'Pricing table: Title', 'sitepress' ); | ||
| 17 | |||
| 18 | case 'button_text': | ||
| 19 | return esc_html__( 'Pricing table: Button text', 'sitepress' ); | ||
| 20 | |||
| 21 | case 'button_url': | ||
| 22 | return esc_html__( 'Pricing table: Button link', 'sitepress' ); | ||
| 23 | |||
| 24 | case 'features': | ||
| 25 | return esc_html__( 'Pricing table: Feature', 'sitepress' ); | ||
| 26 | |||
| 27 | case 'price': | ||
| 28 | return esc_html__( 'Pricing table: Price', 'sitepress' ); | ||
| 29 | |||
| 30 | case 'duration': | ||
| 31 | return esc_html__( 'Pricing table: Duration', 'sitepress' ); | ||
| 32 | |||
| 33 | default: | ||
| 34 | return ''; | ||
| 35 | |||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | protected function get_editor_type( $field ) { | ||
| 40 | switch ( $field ) { | ||
| 41 | case 'title': | ||
| 42 | case 'button_text': | ||
| 43 | case 'price': | ||
| 44 | case 'duration': | ||
| 45 | return 'LINE'; | ||
| 46 | |||
| 47 | case 'button_url': | ||
| 48 | return 'LINK'; | ||
| 49 | |||
| 50 | case 'features': | ||
| 51 | return 'VISUAL'; | ||
| 52 | |||
| 53 | default: | ||
| 54 | return ''; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Tab extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | protected function get_title( $field ) { | ||
| 6 | switch( $field ) { | ||
| 7 | case 'label': | ||
| 8 | return esc_html__( 'Tab Item Label', 'sitepress' ); | ||
| 9 | |||
| 10 | case 'content': | ||
| 11 | return esc_html__( 'Tab Item Content', 'sitepress' ); | ||
| 12 | |||
| 13 | default: | ||
| 14 | return ''; | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Beaver_Builder_Testimonials extends WPML_Beaver_Builder_Module_With_Items { | ||
| 4 | |||
| 5 | public function &get_items( $settings ) { | ||
| 6 | return $settings->testimonials; | ||
| 7 | } | ||
| 8 | |||
| 9 | public function get_fields() { | ||
| 10 | return array( 'testimonial' ); | ||
| 11 | } | ||
| 12 | |||
| 13 | protected function get_title( $field ) { | ||
| 14 | switch( $field ) { | ||
| 15 | case 'testimonial': | ||
| 16 | return esc_html__( 'Testimonial content', 'sitepress' ); | ||
| 17 | |||
| 18 | default: | ||
| 19 | return ''; | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | protected function get_editor_type( $field ) { | ||
| 24 | switch( $field ) { | ||
| 25 | case 'testimonial': | ||
| 26 | return 'VISUAL'; | ||
| 27 | |||
| 28 | default: | ||
| 29 | return ''; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Cornerstone\Config; | ||
| 4 | |||
| 5 | class Factory extends \WPML\PB\Config\Factory { | ||
| 6 | |||
| 7 | const DATA = [ | ||
| 8 | 'configRoot' => 'cornerstone-widgets', | ||
| 9 | 'defaultConditionKey' => '_type', | ||
| 10 | 'pbKey' => 'cornerstone', | ||
| 11 | 'translatableWidgetsHook' => 'wpml_cornerstone_modules_to_translate', | ||
| 12 | ]; | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @inheritDoc | ||
| 16 | */ | ||
| 17 | protected function getPbData( $key ) { | ||
| 18 | return self::DATA[ $key ]; | ||
| 19 | } | ||
| 20 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Cornerstone\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Cast; | ||
| 6 | use WPML\FP\Maybe; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | use WPML\FP\Str; | ||
| 9 | use WPML\LIB\WP\Hooks; | ||
| 10 | use function WPML\FP\spreadArgs; | ||
| 11 | |||
| 12 | class Editor implements \IWPML_Frontend_Action { | ||
| 13 | |||
| 14 | public function add_hooks() { | ||
| 15 | Hooks::onFilter( 'wpml_pb_is_editing_translation_with_native_editor', 10, 2 ) | ||
| 16 | ->then( spreadArgs( function( $isTranslationWithNativeEditor, $translatedPostId ) { | ||
| 17 | return $isTranslationWithNativeEditor | ||
| 18 | || ( | ||
| 19 | Str::includes( 'themeco/data/save', Obj::prop( 'REQUEST_URI', $_SERVER ) ) | ||
| 20 | && self::getEditedId() === $translatedPostId | ||
| 21 | ); | ||
| 22 | } ) ); | ||
| 23 | } | ||
| 24 | |||
| 25 | /** | ||
| 26 | * @return int|null | ||
| 27 | */ | ||
| 28 | private static function getEditedId() { | ||
| 29 | /** | ||
| 30 | * @see \Cornerstone_Routing::process_params | ||
| 31 | * $decodeCornerstoneData :: string -> array | ||
| 32 | */ | ||
| 33 | $decodeCornerstoneData = function( $data ) { | ||
| 34 | $request = Obj::prop( 'request', $data ); | ||
| 35 | |||
| 36 | if ( Obj::prop( 'gzip', $data ) ) { | ||
| 37 | return (array) json_decode( gzdecode( base64_decode( $request, true ) ), true ); | ||
| 38 | } | ||
| 39 | |||
| 40 | return (array) $request; | ||
| 41 | }; | ||
| 42 | |||
| 43 | $key = version_compare( constant( 'CS_VERSION' ), '7.1.3', '>=' ) ? 'document' : 'builder'; | ||
| 44 | $getId = Obj::path( [ 'requests', $key, 'id' ] ); | ||
| 45 | |||
| 46 | return Maybe::fromNullable( \WP_REST_Server::get_raw_data() ) | ||
| 47 | ->map( 'json_decode' ) | ||
| 48 | ->map( $decodeCornerstoneData ) | ||
| 49 | ->map( $getId ) | ||
| 50 | ->map( Cast::toInt() ) | ||
| 51 | ->getOrElse( null ); | ||
| 52 | } | ||
| 53 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Cornerstone\Styles; | ||
| 4 | |||
| 5 | use WPML\FP\Fns; | ||
| 6 | use WPML\FP\Logic; | ||
| 7 | use WPML\FP\Maybe; | ||
| 8 | use WPML\LIB\WP\Post; | ||
| 9 | |||
| 10 | class Hooks implements \IWPML_Backend_Action, \IWPML_Frontend_Action, \IWPML_DIC_Action { | ||
| 11 | |||
| 12 | const META_KEY_OLD = '_cs_generated_styles'; | ||
| 13 | const META_KEY_V6 = '_cs_generated_tss'; | ||
| 14 | |||
| 15 | /** @var callable $shouldInvalidateStyle */ | ||
| 16 | private $shouldInvalidateStyles; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Hooks constructor. | ||
| 20 | * | ||
| 21 | * @param \WPML_PB_Last_Translation_Edit_Mode $lastEditMode | ||
| 22 | * @param \WPML_Cornerstone_Data_Settings $dataSettings | ||
| 23 | */ | ||
| 24 | public function __construct( | ||
| 25 | \WPML_PB_Last_Translation_Edit_Mode $lastEditMode, | ||
| 26 | \WPML_Cornerstone_Data_Settings $dataSettings | ||
| 27 | ) { | ||
| 28 | $this->shouldInvalidateStyles = Logic::both( [ $dataSettings, 'is_handling_post' ], [ $lastEditMode, 'is_translation_editor' ] ); | ||
| 29 | } | ||
| 30 | |||
| 31 | |||
| 32 | public function add_hooks() { | ||
| 33 | add_action( 'save_post', [ $this, 'invalidateStylesInTranslation' ] ); | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * @param int $postId | ||
| 38 | */ | ||
| 39 | public function invalidateStylesInTranslation( $postId ) { | ||
| 40 | Maybe::of( $postId ) | ||
| 41 | ->filter( $this->shouldInvalidateStyles ) | ||
| 42 | ->map( Fns::tap( Post::deleteMeta( Fns::__, self::META_KEY_V6 ) ) ) | ||
| 43 | ->map( Fns::tap( Post::deleteMeta( Fns::__, self::META_KEY_OLD ) ) ); | ||
| 44 | } | ||
| 45 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Data_Settings implements IWPML_Page_Builders_Data_Settings { | ||
| 4 | |||
| 5 | /** | ||
| 6 | * @return string | ||
| 7 | */ | ||
| 8 | public function get_meta_field() { | ||
| 9 | return '_cornerstone_data'; | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @return string | ||
| 14 | */ | ||
| 15 | public function get_node_id_field() { | ||
| 16 | return '_type'; | ||
| 17 | } | ||
| 18 | |||
| 19 | /** | ||
| 20 | * @return array | ||
| 21 | */ | ||
| 22 | public function get_fields_to_copy() { | ||
| 23 | return array( '_cornerstone_settings', '_cornerstone_version', 'post_content' ); | ||
| 24 | } | ||
| 25 | |||
| 26 | /** | ||
| 27 | * @param array $data | ||
| 28 | * | ||
| 29 | * @return array | ||
| 30 | */ | ||
| 31 | public function convert_data_to_array( $data ) { | ||
| 32 | $converted_data = $data; | ||
| 33 | if ( is_array( $data ) ) { | ||
| 34 | $converted_data = $data[0]; | ||
| 35 | } | ||
| 36 | |||
| 37 | return json_decode( $converted_data, true ); | ||
| 38 | } | ||
| 39 | |||
| 40 | /** | ||
| 41 | * @param array $data | ||
| 42 | * | ||
| 43 | * @return string | ||
| 44 | */ | ||
| 45 | public function prepare_data_for_saving( array $data ) { | ||
| 46 | return wp_slash( wp_json_encode( $data ) ); | ||
| 47 | } | ||
| 48 | |||
| 49 | /** | ||
| 50 | * @return string | ||
| 51 | */ | ||
| 52 | public function get_pb_name() { | ||
| 53 | return 'Cornerstone'; | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * @return array | ||
| 58 | */ | ||
| 59 | public function get_fields_to_save() { | ||
| 60 | return array( '_cornerstone_data' ); | ||
| 61 | } | ||
| 62 | |||
| 63 | public function add_hooks() { | ||
| 64 | } | ||
| 65 | |||
| 66 | /** | ||
| 67 | * @param int $postId | ||
| 68 | * | ||
| 69 | * @return bool | ||
| 70 | */ | ||
| 71 | public function is_handling_post( $postId ) { | ||
| 72 | return get_post_meta( $postId, $this->get_meta_field(), true ) | ||
| 73 | && ! get_post_meta( $postId, '_cornerstone_override', true ); | ||
| 74 | } | ||
| 75 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_PB_Cornerstone_Handle_Custom_Fields_Factory implements IWPML_Backend_Action_Loader, IWPML_AJAX_Action_Loader, IWPML_Frontend_Action_Loader { | ||
| 4 | |||
| 5 | public function create() { | ||
| 6 | return new WPML_PB_Handle_Custom_Fields( new WPML_Cornerstone_Data_Settings() ); | ||
| 7 | } | ||
| 8 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | use function WPML\Container\make; | ||
| 4 | |||
| 5 | class WPML_Cornerstone_Integration_Factory { | ||
| 6 | |||
| 7 | const SLUG = 'cornerstone'; | ||
| 8 | |||
| 9 | public function create() { | ||
| 10 | $action_filter_loader = new WPML_Action_Filter_Loader(); | ||
| 11 | $action_filter_loader->load( | ||
| 12 | [ | ||
| 13 | 'WPML_PB_Cornerstone_Handle_Custom_Fields_Factory', | ||
| 14 | 'WPML_Cornerstone_Media_Hooks_Factory', | ||
| 15 | \WPML\PB\Cornerstone\Config\Factory::class, | ||
| 16 | \WPML\PB\Cornerstone\Styles\Hooks::class, | ||
| 17 | \WPML\PB\Cornerstone\Hooks\Editor::class, | ||
| 18 | ] | ||
| 19 | ); | ||
| 20 | |||
| 21 | $nodes = new WPML_Cornerstone_Translatable_Nodes(); | ||
| 22 | $data_settings = new WPML_Cornerstone_Data_Settings(); | ||
| 23 | |||
| 24 | $string_registration_factory = new WPML_String_Registration_Factory( $data_settings->get_pb_name() ); | ||
| 25 | $string_registration = $string_registration_factory->create(); | ||
| 26 | |||
| 27 | $factory = make( WPML_PB_Factory::class ); | ||
| 28 | $strategy = make( WPML_PB_API_Hooks_Strategy::class, [ ':name' => $data_settings->get_pb_name() ] ); | ||
| 29 | $strategy->set_factory( $factory ); | ||
| 30 | |||
| 31 | $reuse_translation = make( WPML_PB_Reuse_Translations_By_Strategy::class, [ ':strategy' => $strategy ] ); | ||
| 32 | |||
| 33 | $register_strings = new WPML_Cornerstone_Register_Strings( $nodes, $data_settings, $string_registration, $reuse_translation ); | ||
| 34 | $update_translation = new WPML_Cornerstone_Update_Translation( $nodes, $data_settings ); | ||
| 35 | |||
| 36 | return new WPML_Page_Builders_Integration( $register_strings, $update_translation, $data_settings ); | ||
| 37 | } | ||
| 38 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | use WPML\PB\Cornerstone\Utils; | ||
| 4 | |||
| 5 | class WPML_Cornerstone_Register_Strings extends WPML_Page_Builders_Register_Strings { | ||
| 6 | |||
| 7 | /** | ||
| 8 | * @param array $data_array | ||
| 9 | * @param array $package | ||
| 10 | */ | ||
| 11 | protected function register_strings_for_modules( array $data_array, array $package ) { | ||
| 12 | foreach ( $data_array as $data ) { | ||
| 13 | if ( isset( $data['_type'] ) && ! Utils::typeIsLayout( $data['_type'] ) ) { | ||
| 14 | $this->register_strings_for_node( Utils::getNodeId( $data ), $data, $package ); | ||
| 15 | } elseif ( is_array( $data ) ) { | ||
| 16 | $this->register_strings_for_modules( $data, $package ); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | } |
This diff is collapsed.
Click to expand it.
| 1 | <?php | ||
| 2 | |||
| 3 | use WPML\PB\Cornerstone\Utils; | ||
| 4 | |||
| 5 | class WPML_Cornerstone_Update_Translation extends WPML_Page_Builders_Update_Translation { | ||
| 6 | |||
| 7 | /** @param array $data_array */ | ||
| 8 | public function update_strings_in_modules( array &$data_array ) { | ||
| 9 | foreach ( $data_array as $key => &$data ) { | ||
| 10 | if ( isset( $data['_type'] ) && ! Utils::typeIsLayout( $data['_type'] ) ) { | ||
| 11 | $data = $this->update_strings_in_node( Utils::getNodeId( $data ), $data ); | ||
| 12 | } elseif ( is_array( $data ) ) { | ||
| 13 | $this->update_strings_in_modules( $data ); | ||
| 14 | } | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | /** | ||
| 19 | * @param string $node_id | ||
| 20 | * @param array $settings | ||
| 21 | * | ||
| 22 | * @return mixed | ||
| 23 | */ | ||
| 24 | protected function update_strings_in_node( $node_id, $settings ) { | ||
| 25 | $strings = $this->translatable_nodes->get( $node_id, $settings ); | ||
| 26 | foreach ( $strings as $string ) { | ||
| 27 | $translation = $this->get_translation( $string ); | ||
| 28 | $settings = $this->translatable_nodes->update( $node_id, $settings, $translation ); | ||
| 29 | } | ||
| 30 | |||
| 31 | return $settings; | ||
| 32 | } | ||
| 33 | |||
| 34 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Cornerstone; | ||
| 4 | |||
| 5 | class Utils { | ||
| 6 | |||
| 7 | const MODULE_TYPE_PREFIX = 'classic:'; | ||
| 8 | const LAYOUT_TYPES = [ | ||
| 9 | 'bar', | ||
| 10 | 'container', | ||
| 11 | 'section', | ||
| 12 | 'row', | ||
| 13 | 'column', | ||
| 14 | 'layout-row', | ||
| 15 | 'layout-column', | ||
| 16 | 'layout-grid', | ||
| 17 | 'layout-cell', | ||
| 18 | 'layout-div', | ||
| 19 | ]; | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @param array $data | ||
| 23 | * @return string | ||
| 24 | */ | ||
| 25 | public static function getNodeId( $data ) { | ||
| 26 | return md5( serialize( $data ) ); | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * Check if the type is a layout type. | ||
| 31 | * | ||
| 32 | * @param string $type The type to check. | ||
| 33 | * @return bool | ||
| 34 | */ | ||
| 35 | public static function typeIsLayout( $type ) { | ||
| 36 | // Remove the classic prefix before checking. | ||
| 37 | $type = preg_replace( '/^' . self::MODULE_TYPE_PREFIX . '/', '', $type ); | ||
| 38 | |||
| 39 | return in_array( $type, self::LAYOUT_TYPES, true ); | ||
| 40 | } | ||
| 41 | |||
| 42 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Media_Hooks_Factory implements IWPML_Backend_Action_Loader, IWPML_Frontend_Action_Loader { | ||
| 4 | public function create() { | ||
| 5 | return new WPML_Page_Builders_Media_Hooks( | ||
| 6 | new WPML_Cornerstone_Update_Media_Factory(), | ||
| 7 | WPML_Cornerstone_Integration_Factory::SLUG | ||
| 8 | ); | ||
| 9 | } | ||
| 10 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Media_Node_Provider { | ||
| 4 | |||
| 5 | private $media_translate; | ||
| 6 | |||
| 7 | private $nodes = array(); | ||
| 8 | |||
| 9 | public function __construct( WPML_Page_Builders_Media_Translate $media_translate ) { | ||
| 10 | $this->media_translate = $media_translate; | ||
| 11 | } | ||
| 12 | |||
| 13 | /** | ||
| 14 | * @param string $type | ||
| 15 | * | ||
| 16 | * @return WPML_Cornerstone_Media_Node|null | ||
| 17 | */ | ||
| 18 | public function get( $type ) { | ||
| 19 | if ( ! array_key_exists( $type, $this->nodes ) ) { | ||
| 20 | $this->add( $type ); | ||
| 21 | } | ||
| 22 | |||
| 23 | return $this->nodes[ $type ]; | ||
| 24 | } | ||
| 25 | |||
| 26 | /** | ||
| 27 | * @param string $type | ||
| 28 | */ | ||
| 29 | private function add( $type ) { | ||
| 30 | switch ( $type ) { | ||
| 31 | case 'image': | ||
| 32 | $node = new WPML_Cornerstone_Media_Node_Image( $this->media_translate ); | ||
| 33 | break; | ||
| 34 | |||
| 35 | case 'classic:creative-cta': | ||
| 36 | $node = new WPML_Cornerstone_Media_Node_Classic_Creative_CTA( $this->media_translate ); | ||
| 37 | break; | ||
| 38 | |||
| 39 | case 'classic:feature-box': | ||
| 40 | $node = new WPML_Cornerstone_Media_Node_Classic_Feature_Box( $this->media_translate ); | ||
| 41 | break; | ||
| 42 | |||
| 43 | case 'classic:card': | ||
| 44 | $node = new WPML_Cornerstone_Media_Node_Classic_Card( $this->media_translate ); | ||
| 45 | break; | ||
| 46 | |||
| 47 | case 'classic:image': | ||
| 48 | $node = new WPML_Cornerstone_Media_Node_Classic_Image( $this->media_translate ); | ||
| 49 | break; | ||
| 50 | |||
| 51 | case 'classic:promo': | ||
| 52 | $node = new WPML_Cornerstone_Media_Node_Classic_Promo( $this->media_translate ); | ||
| 53 | break; | ||
| 54 | |||
| 55 | default: | ||
| 56 | $node = null; | ||
| 57 | } | ||
| 58 | |||
| 59 | $this->nodes[ $type ] = $node; | ||
| 60 | } | ||
| 61 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Media_Nodes_Iterator implements IWPML_PB_Media_Nodes_Iterator { | ||
| 4 | |||
| 5 | const ITEMS_FIELD = WPML_Cornerstone_Module_With_Items::ITEMS_FIELD; | ||
| 6 | |||
| 7 | /** @var WPML_Cornerstone_Media_Node_Provider $node_provider */ | ||
| 8 | private $node_provider; | ||
| 9 | public function __construct( WPML_Cornerstone_Media_Node_Provider $node_provider ) { | ||
| 10 | $this->node_provider = $node_provider; | ||
| 11 | } | ||
| 12 | |||
| 13 | /** | ||
| 14 | * @param array $data_array | ||
| 15 | * @param string $lang | ||
| 16 | * @param string $source_lang | ||
| 17 | * | ||
| 18 | * @return array | ||
| 19 | */ | ||
| 20 | public function translate( $data_array, $lang, $source_lang ) { | ||
| 21 | foreach ( $data_array as $key => &$data ) { | ||
| 22 | if ( isset( $data[ self::ITEMS_FIELD ] ) && $data[ self::ITEMS_FIELD ] ) { | ||
| 23 | $data[ self::ITEMS_FIELD ] = $this->translate( $data[ self::ITEMS_FIELD ], $lang, $source_lang ); | ||
| 24 | } elseif ( is_numeric( $key ) && isset( $data['_type'] ) ) { | ||
| 25 | $data = $this->translate_node( $data, $lang, $source_lang ); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | return $data_array; | ||
| 30 | } | ||
| 31 | |||
| 32 | /** | ||
| 33 | * @param stdClass $settings | ||
| 34 | * @param string $lang | ||
| 35 | * @param string $source_lang | ||
| 36 | * | ||
| 37 | * @return stdClass | ||
| 38 | */ | ||
| 39 | private function translate_node( $settings, $lang, $source_lang ) { | ||
| 40 | $node = $this->node_provider->get( $settings['_type'] ); | ||
| 41 | |||
| 42 | if ( $node ) { | ||
| 43 | $settings = $node->translate( $settings, $lang, $source_lang ); | ||
| 44 | } | ||
| 45 | |||
| 46 | return $settings; | ||
| 47 | } | ||
| 48 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Update_Media_Factory implements IWPML_PB_Media_Update_Factory { | ||
| 4 | |||
| 5 | /** @var WPML_Page_Builders_Media_Translate|null $media_translate */ | ||
| 6 | private $media_translate; | ||
| 7 | |||
| 8 | public function create() { | ||
| 9 | global $sitepress; | ||
| 10 | return new WPML_Page_Builders_Update_Media( | ||
| 11 | new WPML_Page_Builders_Update( new WPML_Cornerstone_Data_Settings() ), | ||
| 12 | new WPML_Translation_Element_Factory( $sitepress ), | ||
| 13 | new WPML_Cornerstone_Media_Nodes_Iterator( | ||
| 14 | new WPML_Cornerstone_Media_Node_Provider( $this->get_media_translate() ) | ||
| 15 | ), | ||
| 16 | new WPML_Page_Builders_Media_Usage( $this->get_media_translate(), new WPML_Media_Usage_Factory() ) | ||
| 17 | ); | ||
| 18 | } | ||
| 19 | |||
| 20 | /** @return WPML_Page_Builders_Media_Translate */ | ||
| 21 | private function get_media_translate() { | ||
| 22 | global $sitepress; | ||
| 23 | |||
| 24 | if ( ! $this->media_translate ) { | ||
| 25 | $this->media_translate = new WPML_Page_Builders_Media_Translate( | ||
| 26 | new WPML_Translation_Element_Factory( $sitepress ), | ||
| 27 | new WPML_Media_Image_Translate( $sitepress, new WPML_Media_Attachment_By_URL_Factory(), new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory() ) | ||
| 28 | ); | ||
| 29 | } | ||
| 30 | |||
| 31 | return $this->media_translate; | ||
| 32 | } | ||
| 33 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | abstract class WPML_Cornerstone_Media_Node_With_URLs extends WPML_Cornerstone_Media_Node { | ||
| 4 | |||
| 5 | /** @return array */ | ||
| 6 | abstract protected function get_keys(); | ||
| 7 | |||
| 8 | /** | ||
| 9 | * @param array $node_data | ||
| 10 | * @param string $target_lang | ||
| 11 | * @param string $source_lang | ||
| 12 | * | ||
| 13 | * @return array | ||
| 14 | */ | ||
| 15 | public function translate( $node_data, $target_lang, $source_lang ) { | ||
| 16 | foreach ( $this->get_keys() as $key ) { | ||
| 17 | if ( ! empty( $node_data[ $key ] ) ) { | ||
| 18 | list( $attachment_id, $type ) = explode( ':', $node_data[ $key ], 2 ); | ||
| 19 | if ( is_numeric( $attachment_id ) ) { | ||
| 20 | $attachment_id = apply_filters( 'wpml_object_id', $attachment_id, 'attachment', true, $target_lang ); | ||
| 21 | $node_data[ $key ] = $attachment_id . ':' . $type; | ||
| 22 | } else { | ||
| 23 | $node_data[ $key ] = $this->media_translate->translate_image_url( $node_data[ $key ], $target_lang, $source_lang ); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | return $node_data; | ||
| 29 | } | ||
| 30 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | abstract class WPML_Cornerstone_Media_Node { | ||
| 4 | |||
| 5 | /** @var WPML_Page_Builders_Media_Translate $media_translate */ | ||
| 6 | protected $media_translate; | ||
| 7 | |||
| 8 | public function __construct( WPML_Page_Builders_Media_Translate $media_translate ) { | ||
| 9 | $this->media_translate = $media_translate; | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param array $node_data | ||
| 14 | * @param string $target_lang | ||
| 15 | * @param string $source_lang | ||
| 16 | * | ||
| 17 | * @return array | ||
| 18 | */ | ||
| 19 | abstract function translate( $node_data, $target_lang, $source_lang ); | ||
| 20 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Cornerstone\Modules; | ||
| 4 | |||
| 5 | use WPML\FP\Fns; | ||
| 6 | use WPML\FP\Lst; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | |||
| 9 | class ModuleWithItemsFromConfig extends \WPML_Cornerstone_Module_With_Items { | ||
| 10 | |||
| 11 | /** @var array $fieldDefinitions */ | ||
| 12 | private $fieldDefinitions; | ||
| 13 | |||
| 14 | public function __construct( array $config ) { | ||
| 15 | $keyByField = Fns::converge( Lst::zipObj(), [ Lst::pluck( 'field' ), Fns::identity() ] ); | ||
| 16 | $this->fieldDefinitions = $keyByField( $config ); | ||
| 17 | } | ||
| 18 | |||
| 19 | /** | ||
| 20 | * @inheritDoc | ||
| 21 | */ | ||
| 22 | public function get_title( $field ) { | ||
| 23 | return Obj::path( [ $field, 'type' ], $this->fieldDefinitions ); | ||
| 24 | } | ||
| 25 | |||
| 26 | /** | ||
| 27 | * @inheritDoc | ||
| 28 | */ | ||
| 29 | public function get_fields() { | ||
| 30 | return array_keys( $this->fieldDefinitions ); | ||
| 31 | } | ||
| 32 | |||
| 33 | /** | ||
| 34 | * @inheritDoc | ||
| 35 | */ | ||
| 36 | public function get_editor_type( $field ) { | ||
| 37 | return Obj::path( [ $field, 'editor_type' ], $this->fieldDefinitions ); | ||
| 38 | } | ||
| 39 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Accordion extends WPML_Cornerstone_Module_With_Items { | ||
| 4 | |||
| 5 | /** | ||
| 6 | * @return array | ||
| 7 | */ | ||
| 8 | public function get_fields() { | ||
| 9 | return array( 'accordion_item_header_content', 'accordion_item_content' ); | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param string $field | ||
| 14 | * | ||
| 15 | * @return string | ||
| 16 | */ | ||
| 17 | protected function get_title( $field ) { | ||
| 18 | if ( 'accordion_item_header_content' === $field ) { | ||
| 19 | return esc_html__( 'Accordion: header content', 'sitepress' ); | ||
| 20 | } | ||
| 21 | |||
| 22 | if ( 'accordion_item_content' === $field ) { | ||
| 23 | return esc_html__( 'Accordion: content', 'sitepress' ); | ||
| 24 | } | ||
| 25 | |||
| 26 | return ''; | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * @param string $field | ||
| 31 | * | ||
| 32 | * @return string | ||
| 33 | */ | ||
| 34 | protected function get_editor_type( $field ) { | ||
| 35 | if ( 'accordion_item_header_content' === $field ) { | ||
| 36 | return 'LINE'; | ||
| 37 | } else { | ||
| 38 | return 'VISUAL'; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | /** | ||
| 4 | * Class WPML_Cornerstone_Module_With_Items | ||
| 5 | */ | ||
| 6 | abstract class WPML_Cornerstone_Module_With_Items implements IWPML_Page_Builders_Module { | ||
| 7 | |||
| 8 | const ITEMS_FIELD = WPML_Cornerstone_Translatable_Nodes::SETTINGS_FIELD; | ||
| 9 | |||
| 10 | /** | ||
| 11 | * @param string $field | ||
| 12 | * | ||
| 13 | * @return string | ||
| 14 | */ | ||
| 15 | abstract protected function get_title( $field ); | ||
| 16 | |||
| 17 | /** @return array */ | ||
| 18 | abstract protected function get_fields(); | ||
| 19 | |||
| 20 | /** | ||
| 21 | * @param string $field | ||
| 22 | * | ||
| 23 | * @return string | ||
| 24 | */ | ||
| 25 | abstract protected function get_editor_type( $field ); | ||
| 26 | |||
| 27 | /** | ||
| 28 | * @param array $settings | ||
| 29 | * | ||
| 30 | * @return array | ||
| 31 | */ | ||
| 32 | protected function get_items( $settings ) { | ||
| 33 | return $settings[ self::ITEMS_FIELD ]; | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * @param string|int $node_id | ||
| 38 | * @param array $settings | ||
| 39 | * @param WPML_PB_String[] $strings | ||
| 40 | * | ||
| 41 | * @return WPML_PB_String[] | ||
| 42 | */ | ||
| 43 | public function get( $node_id, $settings, $strings ) { | ||
| 44 | foreach ( $this->get_items( $settings ) as $item ) { | ||
| 45 | foreach ( $this->get_fields() as $field ) { | ||
| 46 | if ( is_array( $item[ $field ] ) ) { | ||
| 47 | foreach ( $item[ $field ] as $key => $value ) { | ||
| 48 | $strings[] = new WPML_PB_String( | ||
| 49 | $value, | ||
| 50 | $this->get_string_name( $node_id, $value, $field, $key ), | ||
| 51 | $this->get_title( $field ), | ||
| 52 | $this->get_editor_type( $field ) | ||
| 53 | ); | ||
| 54 | } | ||
| 55 | } else { | ||
| 56 | $strings[] = new WPML_PB_String( | ||
| 57 | $item[ $field ], | ||
| 58 | $this->get_string_name( $node_id, $item[ $field ], $field ), | ||
| 59 | $this->get_title( $field ), | ||
| 60 | $this->get_editor_type( $field ) | ||
| 61 | ); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | return $strings; | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * @param string|int $node_id | ||
| 71 | * @param array $settings | ||
| 72 | * @param WPML_PB_String $string | ||
| 73 | * | ||
| 74 | * @return array | ||
| 75 | */ | ||
| 76 | public function update( $node_id, $settings, WPML_PB_String $string ) { | ||
| 77 | foreach ( $this->get_items( $settings ) as $key => $item ) { | ||
| 78 | foreach ( $this->get_fields() as $field ) { | ||
| 79 | if ( $this->get_string_name( $node_id, $item[ $field ], $field ) === $string->get_name() ) { | ||
| 80 | $settings[ self::ITEMS_FIELD ][ $key ][ $field ] = $string->get_value(); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | return $settings; | ||
| 86 | } | ||
| 87 | |||
| 88 | private function get_string_name( $node_id, $value, $type, $key = '' ) { | ||
| 89 | return md5( $value ) . '-' . $type . $key . '-' . $node_id; | ||
| 90 | } | ||
| 91 | |||
| 92 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Cornerstone_Tabs extends WPML_Cornerstone_Module_With_Items { | ||
| 4 | |||
| 5 | /** | ||
| 6 | * @return array | ||
| 7 | */ | ||
| 8 | public function get_fields() { | ||
| 9 | return array( 'tab_label_content', 'tab_content' ); | ||
| 10 | } | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param string $field | ||
| 14 | * | ||
| 15 | * @return string | ||
| 16 | */ | ||
| 17 | protected function get_title( $field ) { | ||
| 18 | if ( 'tab_label_content' === $field ) { | ||
| 19 | return esc_html__( 'Tabs: label', 'sitepress' ); | ||
| 20 | } | ||
| 21 | |||
| 22 | if ( 'tab_content' === $field ) { | ||
| 23 | return esc_html__( 'Tabs: content', 'sitepress' ); | ||
| 24 | } | ||
| 25 | |||
| 26 | return ''; | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * @param string $field | ||
| 31 | * | ||
| 32 | * @return string | ||
| 33 | */ | ||
| 34 | protected function get_editor_type( $field ) { | ||
| 35 | if ( 'tab_label_content' === $field ) { | ||
| 36 | return 'LINE'; | ||
| 37 | } else { | ||
| 38 | return 'VISUAL'; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | use WPML\LIB\WP\Hooks; | ||
| 6 | use function WPML\FP\spreadArgs; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | |||
| 9 | class DisplayConditions implements \IWPML_Frontend_Action { | ||
| 10 | |||
| 11 | const BASE64_EMPTY_ARRAY = 'W10='; | ||
| 12 | |||
| 13 | public function add_hooks() { | ||
| 14 | Hooks::onFilter( 'et_pb_module_shortcode_attributes' ) | ||
| 15 | ->then( spreadArgs( [ $this, 'translateAttributes' ] ) ); | ||
| 16 | } | ||
| 17 | |||
| 18 | /** | ||
| 19 | * @param array $atts | ||
| 20 | * @return array | ||
| 21 | */ | ||
| 22 | public function translateAttributes( $atts ) { | ||
| 23 | $displayConditions = Obj::prop( 'display_conditions', $atts ); | ||
| 24 | |||
| 25 | if ( $displayConditions && self::BASE64_EMPTY_ARRAY !== $displayConditions ) { | ||
| 26 | /* phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode */ | ||
| 27 | $conditions = json_decode( base64_decode( $atts['display_conditions'] ), true ); | ||
| 28 | |||
| 29 | foreach ( $conditions as &$condition ) { | ||
| 30 | if ( 'categoryPage' === $condition['condition'] ) { | ||
| 31 | foreach ( $condition['conditionSettings']['categories'] as &$category ) { | ||
| 32 | $category['value'] = (string) apply_filters( 'wpml_object_id', $category['value'], $category['groupSlug'] ); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | /* phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode */ | ||
| 38 | $atts['display_conditions'] = base64_encode( wp_json_encode( $conditions ) ); | ||
| 39 | } | ||
| 40 | |||
| 41 | return $atts; | ||
| 42 | } | ||
| 43 | |||
| 44 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | /** | ||
| 6 | * Divi replaces double quotes with %22 when saving shortcode attributes. | ||
| 7 | * ATE needs valid HTML so we temporarily decode the double quotes. | ||
| 8 | * When we receive the translation we undo the change. | ||
| 9 | * | ||
| 10 | * @package WPML\Compatibility\Divi | ||
| 11 | */ | ||
| 12 | class DoubleQuotes implements \IWPML_Backend_Action, \IWPML_Frontend_Action { | ||
| 13 | |||
| 14 | public function add_hooks() { | ||
| 15 | add_filter( 'wpml_pb_shortcode_decode', [ $this, 'decode' ], -PHP_INT_MAX, 2 ); | ||
| 16 | add_filter( 'wpml_pb_shortcode_encode', [ $this, 'encode' ], PHP_INT_MAX, 2 ); | ||
| 17 | } | ||
| 18 | |||
| 19 | /** | ||
| 20 | * @param string $string | ||
| 21 | * @param string $encoding | ||
| 22 | * | ||
| 23 | * @return string | ||
| 24 | */ | ||
| 25 | public function decode( $string, $encoding ) { | ||
| 26 | if ( self::canHaveDoubleQuotes( $string, $encoding ) ) { | ||
| 27 | $string = str_replace( '%22', '"', $string ); | ||
| 28 | } | ||
| 29 | |||
| 30 | return $string; | ||
| 31 | } | ||
| 32 | |||
| 33 | /** | ||
| 34 | * @param string $string | ||
| 35 | * @param string $encoding | ||
| 36 | * | ||
| 37 | * @return string | ||
| 38 | */ | ||
| 39 | public function encode( $string, $encoding ) { | ||
| 40 | if ( self::canHaveDoubleQuotes( $string, $encoding ) ) { | ||
| 41 | $string = str_replace( '"', '%22', $string ); | ||
| 42 | } | ||
| 43 | |||
| 44 | return $string; | ||
| 45 | } | ||
| 46 | |||
| 47 | /** | ||
| 48 | * @param string $string | ||
| 49 | * @param string $encoding | ||
| 50 | * | ||
| 51 | * @return bool | ||
| 52 | */ | ||
| 53 | private static function canHaveDoubleQuotes( $string, $encoding ) { | ||
| 54 | return is_string( $string ) && 'allow_html_tags' === $encoding; | ||
| 55 | } | ||
| 56 | |||
| 57 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\LIB\WP\Hooks; | ||
| 7 | use function WPML\FP\spreadArgs; | ||
| 8 | use WPML\PB\Helper\LanguageNegotiation; | ||
| 9 | |||
| 10 | class DomainsBackendEditor implements \IWPML_Backend_Action { | ||
| 11 | |||
| 12 | public function add_hooks() { | ||
| 13 | if ( LanguageNegotiation::isUsingDomains() | ||
| 14 | && self::isPostEditor() | ||
| 15 | && self::getDomainByCurrentPostLanguage() !== $_SERVER['HTTP_HOST'] | ||
| 16 | ) { | ||
| 17 | Hooks::onAction( 'admin_notices' ) | ||
| 18 | ->then( spreadArgs( [ $this, 'displayNotice' ] ) ); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | public function displayNotice() { | ||
| 23 | $url = ( is_ssl() ? 'https://' : 'http://' ) . self::getDomainByCurrentPostLanguage() . $_SERVER['REQUEST_URI']; | ||
| 24 | ?> | ||
| 25 | <div class="notice notice-warning is-dismissible"> | ||
| 26 | <p> | ||
| 27 | <?php | ||
| 28 | echo sprintf( | ||
| 29 | // translators: placeholders are opening and closing <a> tag. | ||
| 30 | esc_html__( "It is not possible to use Divi's backend builder to edit a post in a different language than your domain. Please use Divi's frontend builder to edit this post or %1\$s switch to the correct domain %2\$s to use the backend builder.", 'sitepress' ), | ||
| 31 | sprintf( '<a href="%s">', esc_url( $url ) ), | ||
| 32 | '</a>' | ||
| 33 | ); | ||
| 34 | ?> | ||
| 35 | </p> | ||
| 36 | <button type="button" class="notice-dismiss"> | ||
| 37 | <span class="screen-reader-text">Dismiss this notice.</span> | ||
| 38 | </button> | ||
| 39 | </div> | ||
| 40 | <?php | ||
| 41 | } | ||
| 42 | |||
| 43 | /** | ||
| 44 | * @return bool | ||
| 45 | */ | ||
| 46 | private static function isPostEditor() { | ||
| 47 | global $pagenow; | ||
| 48 | |||
| 49 | return 'post.php' === $pagenow | ||
| 50 | && self::getPostId(); | ||
| 51 | } | ||
| 52 | |||
| 53 | /** | ||
| 54 | * @return int | ||
| 55 | */ | ||
| 56 | private static function getPostId() { | ||
| 57 | /* phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification */ | ||
| 58 | return (int) Obj::prop( 'post', $_GET ); | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | ||
| 62 | * @return string|null | ||
| 63 | */ | ||
| 64 | private static function getDomainByCurrentPostLanguage() { | ||
| 65 | $postDetails = apply_filters( 'wpml_post_language_details', null, self::getPostId() ); | ||
| 66 | $language = Obj::prop( 'language_code', $postDetails ); | ||
| 67 | |||
| 68 | return LanguageNegotiation::getDomainByLanguage( $language ); | ||
| 69 | } | ||
| 70 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use WPML\LIB\WP\Hooks; | ||
| 8 | use function WPML\FP\spreadArgs; | ||
| 9 | |||
| 10 | class Editor implements \IWPML_Backend_Action { | ||
| 11 | |||
| 12 | public function add_hooks() { | ||
| 13 | Hooks::onFilter( 'wpml_pb_is_editing_translation_with_native_editor', 10, 2 ) | ||
| 14 | ->then( spreadArgs( function( $isTranslationWithNativeEditor, $translatedPostId ) { | ||
| 15 | return $isTranslationWithNativeEditor | ||
| 16 | || ( | ||
| 17 | Relation::propEq( 'action', 'et_fb_ajax_save', $_POST ) | ||
| 18 | && (int) Obj::prop( 'post_id', $_POST ) === $translatedPostId | ||
| 19 | ); | ||
| 20 | } ) ); | ||
| 21 | } | ||
| 22 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi\Hooks; | ||
| 4 | |||
| 5 | use WPML\LIB\WP\Hooks; | ||
| 6 | use function WPML\FP\spreadArgs; | ||
| 7 | |||
| 8 | class GutenbergUpdate implements \IWPML_Backend_Action { | ||
| 9 | |||
| 10 | public function add_hooks() { | ||
| 11 | Hooks::onFilter( 'wpml_pb_is_post_built_with_shortcodes', 10, 2 ) | ||
| 12 | ->then( spreadArgs( [ $this, 'isPostBuiltWithShortcodes' ] ) ); | ||
| 13 | } | ||
| 14 | |||
| 15 | /** | ||
| 16 | * @param string $builtWithShortcodes | ||
| 17 | * @param \WP_Post $post | ||
| 18 | * | ||
| 19 | * @return bool | ||
| 20 | */ | ||
| 21 | public static function isPostBuiltWithShortcodes( $builtWithShortcodes, $post ) { | ||
| 22 | return self::isDiviPost( $post->ID ) || $builtWithShortcodes; | ||
| 23 | } | ||
| 24 | |||
| 25 | /** | ||
| 26 | * @param int $postId | ||
| 27 | * | ||
| 28 | * @return bool | ||
| 29 | */ | ||
| 30 | private static function isDiviPost( $postId ) { | ||
| 31 | return 'on' === get_post_meta( $postId, '_et_pb_use_builder', true ); | ||
| 32 | } | ||
| 33 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | |||
| 7 | class TinyMCE implements \IWPML_Backend_Action { | ||
| 8 | |||
| 9 | public function add_hooks() { | ||
| 10 | if ( defined( 'WPML_TM_FOLDER' ) ) { | ||
| 11 | add_filter( 'tiny_mce_before_init', [ $this, 'filterEditorAutoTags' ] ); | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | /** | ||
| 16 | * @param array $config | ||
| 17 | * | ||
| 18 | * @return array | ||
| 19 | */ | ||
| 20 | public function filterEditorAutoTags( $config ) { | ||
| 21 | if ( did_action( 'admin_init' ) ) { | ||
| 22 | $screen = get_current_screen(); | ||
| 23 | $cteUrl = 'wpml_page_' . constant( 'WPML_TM_FOLDER' ) . '/menu/translations-queue'; | ||
| 24 | |||
| 25 | if ( Obj::prop( 'id', $screen ) === $cteUrl ) { | ||
| 26 | $config['wpautop'] = false; | ||
| 27 | $config['indent'] = true; | ||
| 28 | $config['tadv_noautop'] = true; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | return $config; | ||
| 33 | } | ||
| 34 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | use WPML\LIB\WP\Hooks; | ||
| 6 | use function WPML\FP\spreadArgs; | ||
| 7 | use WPML\FP\Obj; | ||
| 8 | |||
| 9 | class WooShortcodes implements \IWPML_Frontend_Action { | ||
| 10 | |||
| 11 | const WOO_SHORTCODES = [ | ||
| 12 | 'et_pb_wc_description', | ||
| 13 | 'et_pb_wc_title', | ||
| 14 | ]; | ||
| 15 | |||
| 16 | public function add_hooks() { | ||
| 17 | Hooks::onFilter( 'et_pb_module_shortcode_attributes', 10, 3 ) | ||
| 18 | ->then( spreadArgs( [ $this, 'translateAttributes' ] ) ); | ||
| 19 | } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @param array $shortcodeAttrs | ||
| 23 | * @param array $attrs | ||
| 24 | * @param string $slug | ||
| 25 | * | ||
| 26 | * @return array | ||
| 27 | */ | ||
| 28 | public function translateAttributes( $shortcodeAttrs, $attrs, $slug ) { | ||
| 29 | if ( in_array( $slug, self::WOO_SHORTCODES, true ) && (int) Obj::prop( 'product', $shortcodeAttrs ) ) { | ||
| 30 | $shortcodeAttrs['product'] = apply_filters( 'wpml_object_id', $shortcodeAttrs['product'], 'product', true ); | ||
| 31 | } | ||
| 32 | return $shortcodeAttrs; | ||
| 33 | } | ||
| 34 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | class Builder implements \IWPML_Frontend_Action, \IWPML_Backend_Action, \IWPML_AJAX_Action { | ||
| 6 | |||
| 7 | public function add_hooks() { | ||
| 8 | add_filter( 'theme_locale', [ $this, 'switch_to_user_language' ] ); | ||
| 9 | } | ||
| 10 | |||
| 11 | public function switch_to_user_language( $locale ) { | ||
| 12 | if ( isset( $_POST['action'] ) && ( 'et_fb_update_builder_assets' === $_POST['action'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification | ||
| 13 | return get_user_locale(); | ||
| 14 | } | ||
| 15 | |||
| 16 | return $locale; | ||
| 17 | } | ||
| 18 | |||
| 19 | } | ||
| 20 |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Compatibility_Divi implements \IWPML_DIC_Action, \IWPML_Backend_Action, \IWPML_Frontend_Action { | ||
| 4 | |||
| 5 | const REGEX_REMOVE_OPENING_PARAGRAPH = '/(<p>[\n\r]*)([\n\r]{1}\[\/et_)/m'; | ||
| 6 | const REGEX_REMOVE_CLOSING_PARAGRAPH = '/(\[et_.*\][\n\r]{1})([\n\r]*<\/p>)/m'; | ||
| 7 | |||
| 8 | /** @var SitePress */ | ||
| 9 | private $sitepress; | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @param SitePress $sitepress | ||
| 13 | */ | ||
| 14 | public function __construct( SitePress $sitepress ) { | ||
| 15 | $this->sitepress = $sitepress; | ||
| 16 | } | ||
| 17 | |||
| 18 | public function add_hooks() { | ||
| 19 | if ( $this->sitepress->is_setup_complete() ) { | ||
| 20 | add_action( 'init', [ $this, 'load_resources_if_they_are_required' ], 10, 0 ); | ||
| 21 | add_filter( 'et_builder_load_actions', [ $this, 'load_builder_for_ajax_actions' ] ); | ||
| 22 | |||
| 23 | add_action( 'admin_init', [ $this, 'display_warning_notice' ], 10, 0 ); | ||
| 24 | |||
| 25 | add_filter( 'wpml_pb_should_handle_content', [ $this, 'should_handle_shortcode_content' ], 10, 2 ); | ||
| 26 | add_filter( 'wpml_pb_shortcode_content_for_translation', [ $this, 'cleanup_global_layout_content' ], 10, 2 ); | ||
| 27 | |||
| 28 | add_filter( 'icl_job_elements', [ $this, 'remove_old_content_from_translation' ], 10, 2 ); | ||
| 29 | add_filter( 'wpml_words_count_custom_fields_to_count', [ $this, 'remove_old_content_from_words_count' ], 10, 2 ); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | /** | ||
| 34 | * @return bool | ||
| 35 | */ | ||
| 36 | private function is_standard_editor_used() { | ||
| 37 | $tm_settings = $this->sitepress->get_setting( 'translation-management', [] ); | ||
| 38 | |||
| 39 | return ! isset( $tm_settings['doc_translation_method'] ) || | ||
| 40 | ICL_TM_TMETHOD_MANUAL === $tm_settings['doc_translation_method']; | ||
| 41 | } | ||
| 42 | |||
| 43 | public function display_warning_notice() { | ||
| 44 | $notices = wpml_get_admin_notices(); | ||
| 45 | |||
| 46 | if ( $this->is_standard_editor_used() ) { | ||
| 47 | $notices->add_notice( new WPML_Compatibility_Divi_Notice() ); | ||
| 48 | } elseif ( $notices->get_notice( WPML_Compatibility_Divi_Notice::ID, WPML_Compatibility_Divi_Notice::GROUP ) ) { | ||
| 49 | $notices->remove_notice( WPML_Compatibility_Divi_Notice::GROUP, WPML_Compatibility_Divi_Notice::ID ); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | /** | ||
| 54 | * These actions require the custom widget area to be initialized. | ||
| 55 | * | ||
| 56 | * @param array $actions | ||
| 57 | * @return array | ||
| 58 | */ | ||
| 59 | public function load_builder_for_ajax_actions( $actions ) { | ||
| 60 | $actions[] = 'save-widget'; | ||
| 61 | $actions[] = 'widgets-order'; | ||
| 62 | $actions[] = 'wpml-ls-save-settings'; | ||
| 63 | |||
| 64 | return $actions; | ||
| 65 | } | ||
| 66 | |||
| 67 | public function load_resources_if_they_are_required() { | ||
| 68 | if ( ! isset( $_GET['page'] ) || ! is_admin() ) { /* phpcs:ignore */ | ||
| 69 | return; | ||
| 70 | } | ||
| 71 | |||
| 72 | $pages = [ self::get_duplication_action_page() ]; | ||
| 73 | if ( self::is_tm_active() ) { | ||
| 74 | $pages[] = self::get_translation_dashboard_page(); | ||
| 75 | $pages[] = self::get_translation_editor_page(); | ||
| 76 | } | ||
| 77 | if ( self::is_sl_active() ) { | ||
| 78 | $pages[] = self::get_sl_page(); | ||
| 79 | } | ||
| 80 | |||
| 81 | if ( in_array( $_GET['page'], $pages, true ) ) { /* phpcs:ignore */ | ||
| 82 | $this->register_layouts(); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | private static function get_translation_dashboard_page() { | ||
| 87 | return constant( 'WPML_TM_FOLDER' ) . '/menu/main.php'; | ||
| 88 | } | ||
| 89 | |||
| 90 | private static function get_translation_editor_page() { | ||
| 91 | return constant( 'WPML_TM_FOLDER' ) . '/menu/translations-queue.php'; | ||
| 92 | } | ||
| 93 | |||
| 94 | private static function get_duplication_action_page() { | ||
| 95 | return constant( 'WPML_PLUGIN_FOLDER' ) . '/menu/languages.php'; | ||
| 96 | } | ||
| 97 | |||
| 98 | private static function get_sl_page() { | ||
| 99 | return 'wpml-sticky-links'; | ||
| 100 | } | ||
| 101 | |||
| 102 | private static function is_tm_active() { | ||
| 103 | return defined( 'WPML_TM_FOLDER' ); | ||
| 104 | } | ||
| 105 | |||
| 106 | private static function is_sl_active() { | ||
| 107 | return defined( 'WPML_STICKY_LINKS_VERSION' ); | ||
| 108 | } | ||
| 109 | |||
| 110 | private function register_layouts() { | ||
| 111 | /** | ||
| 112 | * @phpstan-ignore-next-line | ||
| 113 | */ | ||
| 114 | if ( function_exists( 'et_builder_should_load_framework' ) && ! et_builder_should_load_framework() ) { | ||
| 115 | if ( function_exists( 'et_builder_register_layouts' ) ) { | ||
| 116 | /** | ||
| 117 | * @phpstan-ignore-next-line | ||
| 118 | */ | ||
| 119 | et_builder_register_layouts(); | ||
| 120 | } else { | ||
| 121 | $lib_file = ET_BUILDER_DIR . 'feature/Library.php'; | ||
| 122 | |||
| 123 | if ( ! class_exists( 'ET_Builder_Library' ) | ||
| 124 | && defined( 'ET_BUILDER_DIR' ) | ||
| 125 | && file_exists( $lib_file ) | ||
| 126 | ) { | ||
| 127 | require_once $lib_file; | ||
| 128 | } | ||
| 129 | |||
| 130 | if ( class_exists( 'ET_Builder_Library' ) ) { | ||
| 131 | ET_Builder_Library::instance(); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * The global layout is not properly extracted from the page | ||
| 139 | * because it adds <p> tags either not opened or not closed. | ||
| 140 | * | ||
| 141 | * See the global content below as an example: | ||
| 142 | * | ||
| 143 | * [et_pb_section prev_background_color="#000000" next_background_color="#000000"][et_pb_text] | ||
| 144 | * | ||
| 145 | * </p> | ||
| 146 | * <p>Global text 1 EN5</p> | ||
| 147 | * <p> | ||
| 148 | * | ||
| 149 | * [/et_pb_text][/et_pb_section] | ||
| 150 | * | ||
| 151 | * We also need to remove `prev_background` and `next_background` attributes which are added from the page. | ||
| 152 | * | ||
| 153 | * @param string $content | ||
| 154 | * @param int $post_id | ||
| 155 | */ | ||
| 156 | public function cleanup_global_layout_content( $content, $post_id ) { | ||
| 157 | if ( 'et_pb_layout' === get_post_type( $post_id ) ) { | ||
| 158 | $content = preg_replace( self::REGEX_REMOVE_OPENING_PARAGRAPH, '$2', $content ); | ||
| 159 | $content = preg_replace( self::REGEX_REMOVE_CLOSING_PARAGRAPH, '$1', $content ); | ||
| 160 | $content = preg_replace( '/( prev_background_color="#[0-9a-f]*")/', '', $content ); | ||
| 161 | $content = preg_replace( '/( next_background_color="#[0-9a-f]*")/', '', $content ); | ||
| 162 | } | ||
| 163 | |||
| 164 | return $content; | ||
| 165 | } | ||
| 166 | |||
| 167 | public function should_handle_shortcode_content( $handle_content, $shortcode ) { | ||
| 168 | if ( | ||
| 169 | strpos( $shortcode['tag'], 'et_' ) === 0 && | ||
| 170 | strpos( $shortcode['attributes'], 'global_module=' ) !== false | ||
| 171 | ) { | ||
| 172 | // If a translatable attribute has been excluded from sync, we need to handle it. | ||
| 173 | $handle_content = $this->is_excluded_from_sync( $shortcode ); | ||
| 174 | } | ||
| 175 | return $handle_content; | ||
| 176 | } | ||
| 177 | |||
| 178 | /** | ||
| 179 | * Check if a global module has excluded any translatable text that we need to handle | ||
| 180 | * | ||
| 181 | * @param array $shortcode | ||
| 182 | * { | ||
| 183 | * @type string $tag. | ||
| 184 | * @type string $content. | ||
| 185 | * @type string $attributes. | ||
| 186 | * } | ||
| 187 | * @return bool | ||
| 188 | */ | ||
| 189 | private function is_excluded_from_sync( $shortcode ) { | ||
| 190 | $handle_content = false; | ||
| 191 | |||
| 192 | preg_match( '/global_module="([0-9]+)"/', $shortcode['attributes'], $matches ); | ||
| 193 | $excluded = json_decode( get_post_meta( $matches[1], '_et_pb_excluded_global_options', true ), true ); | ||
| 194 | |||
| 195 | if ( is_array( $excluded ) && count( $excluded ) > 0 ) { | ||
| 196 | $attributes = $this->get_translatable_shortcode_attributes( $shortcode['tag'] ); | ||
| 197 | |||
| 198 | foreach ( $excluded as $field ) { | ||
| 199 | if ( in_array( $field, $attributes, true ) ) { | ||
| 200 | $handle_content = true; | ||
| 201 | break; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | return $handle_content; | ||
| 207 | } | ||
| 208 | |||
| 209 | /** | ||
| 210 | * Get a list of translatable attributes for a shortcode tag. | ||
| 211 | * This includes the inner content and any attributes found in XML configuration. | ||
| 212 | * | ||
| 213 | * @param string $tag The shortcode tag. | ||
| 214 | * @return array | ||
| 215 | */ | ||
| 216 | private function get_translatable_shortcode_attributes( $tag ) { | ||
| 217 | $attributes = [ 'et_pb_content_field' ]; | ||
| 218 | $settings = get_option( 'icl_st_settings', [] ); | ||
| 219 | |||
| 220 | if ( ! isset( $settings['pb_shortcode'] ) ) { | ||
| 221 | return $attributes; | ||
| 222 | } | ||
| 223 | |||
| 224 | foreach ( $settings['pb_shortcode'] as $setting ) { | ||
| 225 | if ( $tag === $setting['tag']['value'] ) { | ||
| 226 | foreach ( $setting['attributes'] as $attribute ) { | ||
| 227 | if ( empty( $attribute['type'] ) ) { | ||
| 228 | $attributes[] = $attribute['value']; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | break; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | return $attributes; | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | ||
| 239 | * Remove the `_et_pb_old_content` meta field from translation jobs, except for products. | ||
| 240 | * | ||
| 241 | * @param array $fields Array of fields to translate. | ||
| 242 | * @param object $post_id The ID of the post being translated. | ||
| 243 | * | ||
| 244 | * @return array | ||
| 245 | */ | ||
| 246 | public function remove_old_content_from_translation( $fields, $post_id ) { | ||
| 247 | // Bail out early if its a product. | ||
| 248 | if ( 'product' === get_post_type( $post_id ) ) { | ||
| 249 | return $fields; | ||
| 250 | } | ||
| 251 | |||
| 252 | // Search for the _et_pb_old_content element and empty it. | ||
| 253 | $field_types = wp_list_pluck( $fields, 'field_type' ); | ||
| 254 | $index = array_search( 'field-_et_pb_old_content-0', $field_types, true ); | ||
| 255 | if ( false !== $index ) { | ||
| 256 | $fields[ $index ]->field_data = ''; | ||
| 257 | $fields[ $index ]->field_data_translated = ''; | ||
| 258 | } | ||
| 259 | |||
| 260 | return $fields; | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * Remove the `_et_pb_old_content` meta field from words count, except for products. | ||
| 265 | * | ||
| 266 | * @param array $fields_to_count Array of custom fields to count. | ||
| 267 | * @param object $post_id The ID of the post for which we are counting the words. | ||
| 268 | * | ||
| 269 | * @return array | ||
| 270 | */ | ||
| 271 | public function remove_old_content_from_words_count( $fields_to_count, $post_id ) { | ||
| 272 | if ( 'product' !== get_post_type( $post_id ) ) { | ||
| 273 | $index = array_search( '_et_pb_old_content', $fields_to_count, true ); | ||
| 274 | if ( false !== $index ) { | ||
| 275 | unset( $fields_to_count[ $index ] ); | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | return $fields_to_count; | ||
| 280 | } | ||
| 281 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | class WPML_Compatibility_Divi_Notice extends WPML_Notice { | ||
| 4 | |||
| 5 | const ID = 'wpml-compatibility-divi-editor-warning'; | ||
| 6 | const GROUP = 'wpml-compatibility-divi'; | ||
| 7 | |||
| 8 | public function __construct() { | ||
| 9 | parent::__construct( self::ID, $this->get_message(), self::GROUP ); | ||
| 10 | $this->set_dismissible( true ); | ||
| 11 | $this->set_css_class_types( 'warning' ); | ||
| 12 | } | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @return string | ||
| 16 | */ | ||
| 17 | private function get_message() { | ||
| 18 | $msg = esc_html_x( | ||
| 19 | 'You are using DIVI theme, and you have chosen to use the standard editor for translating content.', | ||
| 20 | 'Use Translation Editor notice 1/3', | ||
| 21 | 'sitepress' | ||
| 22 | ); | ||
| 23 | |||
| 24 | $msg .= ' ' . esc_html_x( | ||
| 25 | 'Some functionalities may not work properly. We encourage you to switch to use the Translation Editor.', | ||
| 26 | 'Use Translation Editor notice 2/3', | ||
| 27 | 'sitepress' | ||
| 28 | ); | ||
| 29 | |||
| 30 | $msg .= ' ' . sprintf( | ||
| 31 | /* translators: %s will be replaced with a URL. */ | ||
| 32 | esc_html_x( | ||
| 33 | 'You can find more information here: %s', | ||
| 34 | 'Use Translation Editor notice 2/3', | ||
| 35 | 'sitepress' | ||
| 36 | ), | ||
| 37 | '<a href="https://wpml.org/errata/some-internal-taxonomies-will-be-missing-when-you-translate-divi-layouts/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore">Some internal taxonomies will be missing when you translate Divi layouts</a>' | ||
| 38 | ); | ||
| 39 | |||
| 40 | return $msg; | ||
| 41 | } | ||
| 42 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | class DiviOptionsEncoding implements \IWPML_Backend_Action, \IWPML_Frontend_Action { | ||
| 6 | |||
| 7 | const CHARS_ENCODED = [ '%22', '%91', '%93' ]; | ||
| 8 | const CHARS_DECODED = [ '"', '[', ']' ]; | ||
| 9 | const DELIMITER = '_'; | ||
| 10 | const TRANSLATABLE_KEYS = [ 'value', 'link_url', 'link_text' ]; | ||
| 11 | |||
| 12 | public function add_hooks() { | ||
| 13 | add_filter( 'wpml_pb_shortcode_decode', [ $this, 'decode_divi_options' ], 10, 2 ); | ||
| 14 | add_filter( 'wpml_pb_shortcode_encode', [ $this, 'encode_divi_options' ], 10, 2 ); | ||
| 15 | } | ||
| 16 | |||
| 17 | public function decode_divi_options( $string, $encoding ) { | ||
| 18 | if ( 'divi_options' === $encoding ) { | ||
| 19 | $options = str_replace( self::CHARS_ENCODED, self::CHARS_DECODED, $string ); | ||
| 20 | $options = json_decode( $options, true ); | ||
| 21 | $string = []; | ||
| 22 | foreach ( $options as $index => $option ) { | ||
| 23 | foreach ( $option as $key => $value ) { | ||
| 24 | $string[ $key . self::DELIMITER . $index ] = [ | ||
| 25 | 'value' => $value, | ||
| 26 | 'translate' => in_array( $key, self::TRANSLATABLE_KEYS, true ), | ||
| 27 | ]; | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | return $string; | ||
| 33 | } | ||
| 34 | |||
| 35 | public function encode_divi_options( $string, $encoding ) { | ||
| 36 | if ( 'divi_options' === $encoding ) { | ||
| 37 | $output = []; | ||
| 38 | foreach ( $string as $combined_key => $value ) { | ||
| 39 | $parts = explode( self::DELIMITER, $combined_key ); | ||
| 40 | $index = array_pop( $parts ); | ||
| 41 | $key = implode( self::DELIMITER, $parts ); | ||
| 42 | $output[ $index ][ $key ] = $value; | ||
| 43 | } | ||
| 44 | $output = wp_json_encode( $output, JSON_UNESCAPED_UNICODE ); | ||
| 45 | $string = str_replace( self::CHARS_DECODED, self::CHARS_ENCODED, $output ); | ||
| 46 | |||
| 47 | } | ||
| 48 | |||
| 49 | return $string; | ||
| 50 | } | ||
| 51 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | use WPML\Compatibility\BaseDynamicContent; | ||
| 6 | |||
| 7 | class DynamicContent extends BaseDynamicContent { | ||
| 8 | |||
| 9 | const ENCODED_CONTENT_START = '@ET-DC@'; | ||
| 10 | const ENCODED_CONTENT_END = '@'; | ||
| 11 | |||
| 12 | /** @var array */ | ||
| 13 | protected $positions = [ 'before', 'after' ]; | ||
| 14 | |||
| 15 | /** | ||
| 16 | * Sets $positions dynamic content to be translatable. | ||
| 17 | * | ||
| 18 | * @param string $string The decoded string so far. | ||
| 19 | * @param string $encoding The encoding used. | ||
| 20 | * | ||
| 21 | * @return string|array | ||
| 22 | */ | ||
| 23 | public function decode_dynamic_content( $string, $encoding ) { | ||
| 24 | if ( $this->is_dynamic_content( $string ) ) { | ||
| 25 | $field = $this->decode_field( $string ); | ||
| 26 | |||
| 27 | $decodedContent = [ | ||
| 28 | 'et-dynamic-content' => [ | ||
| 29 | 'value' => $string, | ||
| 30 | 'translate' => false, | ||
| 31 | ], | ||
| 32 | ]; | ||
| 33 | |||
| 34 | foreach ( $this->positions as $position ) { | ||
| 35 | if ( ! empty( $field['settings'][ $position ] ) ) { | ||
| 36 | $decodedContent[ $position ] = [ | ||
| 37 | 'value' => $field['settings'][ $position ], | ||
| 38 | 'translate' => true, | ||
| 39 | ]; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | return $decodedContent; | ||
| 44 | } | ||
| 45 | |||
| 46 | return $string; | ||
| 47 | } | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Rebuilds dynamic content with translated strings. | ||
| 51 | * | ||
| 52 | * @param string|array $string The field array or string. | ||
| 53 | * @param string $encoding The encoding used. | ||
| 54 | * | ||
| 55 | * @return string | ||
| 56 | */ | ||
| 57 | public function encode_dynamic_content( $string, $encoding ) { | ||
| 58 | if ( is_array( $string ) && isset( $string['et-dynamic-content'] ) ) { | ||
| 59 | $field = $this->decode_field( $string['et-dynamic-content'] ); | ||
| 60 | |||
| 61 | foreach ( $this->positions as $position ) { | ||
| 62 | if ( isset( $string[ $position ] ) ) { | ||
| 63 | $field['settings'][ $position ] = $string[ $position ]; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | return $this->encode_field( $field ); | ||
| 68 | } | ||
| 69 | |||
| 70 | return $string; | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Decode a dynamic-content field. | ||
| 75 | * | ||
| 76 | * @param string $string The string to decode. | ||
| 77 | * | ||
| 78 | * @return bool | ||
| 79 | */ | ||
| 80 | protected function is_dynamic_content( $string ) { | ||
| 81 | return substr( $string, 0, strlen( self::ENCODED_CONTENT_START ) ) === self::ENCODED_CONTENT_START; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Decode a dynamic-content field. | ||
| 86 | * | ||
| 87 | * @param string $string The string to decode. | ||
| 88 | * | ||
| 89 | * @return array | ||
| 90 | */ | ||
| 91 | protected function decode_field( $string ) { | ||
| 92 | $start = strlen( self::ENCODED_CONTENT_START ); | ||
| 93 | $end = strlen( self::ENCODED_CONTENT_END ); | ||
| 94 | |||
| 95 | // phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode | ||
| 96 | return json_decode( base64_decode( substr( $string, $start, -$end ) ), true ); | ||
| 97 | } | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Encode a dynamic-content field. | ||
| 101 | * | ||
| 102 | * @param array $field The field to encode. | ||
| 103 | * | ||
| 104 | * @return string | ||
| 105 | */ | ||
| 106 | protected function encode_field( $field ) { | ||
| 107 | // phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode | ||
| 108 | return self::ENCODED_CONTENT_START | ||
| 109 | . base64_encode( wp_json_encode( $field ) ) | ||
| 110 | . self::ENCODED_CONTENT_END; | ||
| 111 | } | ||
| 112 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | class Search implements \IWPML_Frontend_Action { | ||
| 6 | |||
| 7 | public function add_hooks() { | ||
| 8 | add_action( 'et_search_form_fields', [ $this, 'add_language_form_field' ] ); | ||
| 9 | } | ||
| 10 | |||
| 11 | public function add_language_form_field() { | ||
| 12 | do_action( 'wpml_add_language_form_field' ); | ||
| 13 | } | ||
| 14 | |||
| 15 | } | ||
| 16 |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | class ThemeBuilderFactory implements \IWPML_Deferred_Action_Loader, \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader { | ||
| 6 | |||
| 7 | public function get_load_action() { | ||
| 8 | return 'init'; | ||
| 9 | } | ||
| 10 | |||
| 11 | public function create() { | ||
| 12 | global $sitepress; | ||
| 13 | |||
| 14 | return new ThemeBuilder( $sitepress ); | ||
| 15 | } | ||
| 16 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\Compatibility\Divi; | ||
| 4 | |||
| 5 | use SitePress; | ||
| 6 | |||
| 7 | class ThemeBuilder implements \IWPML_Action { | ||
| 8 | |||
| 9 | /** @var SitePress */ | ||
| 10 | private $sitepress; | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @param SitePress $sitepress | ||
| 14 | */ | ||
| 15 | public function __construct( SitePress $sitepress ) { | ||
| 16 | $this->sitepress = $sitepress; | ||
| 17 | } | ||
| 18 | |||
| 19 | /** | ||
| 20 | * Add filters and actions. | ||
| 21 | */ | ||
| 22 | public function add_hooks() { | ||
| 23 | if ( ! defined( 'ET_THEME_BUILDER_DIR' ) ) { | ||
| 24 | return; | ||
| 25 | } | ||
| 26 | |||
| 27 | if ( $this->sitepress->is_setup_complete() ) { | ||
| 28 | if ( is_admin() ) { | ||
| 29 | add_action( 'init', [ $this, 'make_layouts_editable' ], 1000 ); // Before WPML_Sticky_Links::init. | ||
| 30 | add_filter( 'wpml_document_view_item_link', [ $this, 'document_view_layout_link' ], 10, 5 ); | ||
| 31 | } else { | ||
| 32 | add_filter( 'get_post_metadata', [ $this, 'translate_layout_ids' ], 10, 4 ); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | /** | ||
| 38 | * Gets all post types that are layouts. | ||
| 39 | */ | ||
| 40 | private static function get_types() { | ||
| 41 | return [ | ||
| 42 | ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE, | ||
| 43 | ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE, | ||
| 44 | ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE, | ||
| 45 | ]; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Access the global post types array to tweak the settings for layouts | ||
| 50 | */ | ||
| 51 | public function make_layouts_editable() { | ||
| 52 | global $wp_post_types; | ||
| 53 | |||
| 54 | foreach ( $this->get_types() as $type ) { | ||
| 55 | $wp_post_types[ $type ]->show_ui = true; | ||
| 56 | $wp_post_types[ $type ]->show_in_menu = false; | ||
| 57 | $wp_post_types[ $type ]->_edit_link = 'post.php?post=%d'; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Translate theme builder layout ids in the frontend. | ||
| 63 | * | ||
| 64 | * @param string $value The layout id. | ||
| 65 | * @param int $post_id The post it belongs to. | ||
| 66 | * @param string $key The meta key we are handling. | ||
| 67 | * @param bool $single Fetch a single row or an array. | ||
| 68 | * @return string | ||
| 69 | */ | ||
| 70 | public function translate_layout_ids( $value, $post_id, $key, $single ) { | ||
| 71 | |||
| 72 | if ( in_array( $key, [ '_et_header_layout_id', '_et_body_layout_id', '_et_footer_layout_id' ], true ) ) { | ||
| 73 | /** | ||
| 74 | * The `get_post_metadata` filter provides `null` as the initial `$value`. | ||
| 75 | * When we return a different $value it is used directly, to avoid a second query. | ||
| 76 | * This means that we have to get the original value first, removing ourselves so | ||
| 77 | * we don't fall into an infinite loop. | ||
| 78 | */ | ||
| 79 | remove_filter( 'get_post_metadata', [ $this, 'translate_layout_ids' ], 10 ); | ||
| 80 | $original_id = get_post_meta( $post_id, $key, true ); | ||
| 81 | add_filter( 'get_post_metadata', [ $this, 'translate_layout_ids' ], 10, 4 ); | ||
| 82 | |||
| 83 | $type = substr( $key, 1, -3 ); | ||
| 84 | $value = $this->sitepress->get_object_id( $original_id, $type, true ); | ||
| 85 | |||
| 86 | if ( ! $single ) { | ||
| 87 | $value = [ $value ]; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | return $value; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Remove the 'View' link because you can't view layouts alone. | ||
| 96 | * | ||
| 97 | * @param string $link The complete link. | ||
| 98 | * @param string $text The text to link. | ||
| 99 | * @param object $job The corresponding translation job. | ||
| 100 | * @param string $prefix The prefix of the element type. | ||
| 101 | * @param string $type The element type. | ||
| 102 | * | ||
| 103 | * @return string | ||
| 104 | */ | ||
| 105 | public function document_view_layout_link( $link, $text, $job, $prefix, $type ) { | ||
| 106 | if ( 'post' === $prefix && $this->is_theme_layout( $type ) ) { | ||
| 107 | $link = ''; | ||
| 108 | } | ||
| 109 | |||
| 110 | return $link; | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Check if a certain Type is a theme builder layout. | ||
| 115 | * | ||
| 116 | * @param string $type The type to check. | ||
| 117 | * | ||
| 118 | * @return bool | ||
| 119 | */ | ||
| 120 | private function is_theme_layout( $type ) { | ||
| 121 | return in_array( $type, $this->get_types(), true ); | ||
| 122 | } | ||
| 123 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements\EssentialAddons; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use function WPML\FP\compose; | ||
| 8 | |||
| 9 | /** | ||
| 10 | * @see https://essential-addons.com/elementor/docs/creative-elements/content-timeline/ | ||
| 11 | */ | ||
| 12 | class ContentTimeline { | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @return array | ||
| 16 | */ | ||
| 17 | public static function get() { | ||
| 18 | // $isEAContentTimeline :: array -> bool | ||
| 19 | $isEAContentTimeline = Relation::propEq( 'widgetType', 'eael-content-timeline' ); | ||
| 20 | |||
| 21 | // $contentTimelineLinksLens :: callable -> callable -> mixed | ||
| 22 | $contentTimelineLinksLens = compose( | ||
| 23 | Obj::lensProp( 'settings' ), | ||
| 24 | Obj::lensMappedProp( 'eael_coustom_content_posts' ), | ||
| 25 | Obj::lensPath( [ '__dynamic__', 'eael_read_more_text_link' ] ) | ||
| 26 | ); | ||
| 27 | |||
| 28 | return [ $isEAContentTimeline, $contentTimelineLinksLens, 'popup', 'popup' ]; | ||
| 29 | } | ||
| 30 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Logic; | ||
| 6 | use WPML\FP\Obj; | ||
| 7 | use WPML\FP\Relation; | ||
| 8 | |||
| 9 | class FormPopup { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @return array | ||
| 13 | */ | ||
| 14 | public static function get() { | ||
| 15 | $popupIdPath = [ 'settings', 'popup_action_popup_id' ]; | ||
| 16 | |||
| 17 | $isFormWithPopup = Logic::allPass( [ | ||
| 18 | Relation::propEq( 'widgetType', 'form' ), | ||
| 19 | Obj::path( $popupIdPath ), | ||
| 20 | ] ); | ||
| 21 | |||
| 22 | $popupIdLens = Obj::lensPath( $popupIdPath ); | ||
| 23 | |||
| 24 | return [ $isFormWithPopup, $popupIdLens ]; | ||
| 25 | } | ||
| 26 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use function WPML\FP\compose; | ||
| 8 | |||
| 9 | class Hotspot{ | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @return array | ||
| 13 | */ | ||
| 14 | public static function get() { | ||
| 15 | $isHotspot = Relation::propEq( 'widgetType', 'hotspot' ); | ||
| 16 | |||
| 17 | // $hotspotLinksLens :: callable -> callable -> mixed | ||
| 18 | $hotspotLinksLens = compose( | ||
| 19 | Obj::lensProp( 'settings' ), | ||
| 20 | Obj::lensMappedProp( 'hotspot' ), | ||
| 21 | Obj::lensPath( [ '__dynamic__', 'hotspot_link' ] ) | ||
| 22 | ); | ||
| 23 | |||
| 24 | return [ $isHotspot, $hotspotLinksLens, 'popup', 'popup' ]; | ||
| 25 | } | ||
| 26 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use function WPML\FP\compose; | ||
| 8 | |||
| 9 | |||
| 10 | class IconList { | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @return array | ||
| 14 | */ | ||
| 15 | public static function get() { | ||
| 16 | // $isIconList :: array -> bool | ||
| 17 | $isIconList = Relation::propEq( 'widgetType', 'icon-list' ); | ||
| 18 | |||
| 19 | $iconListLinksLens = compose( | ||
| 20 | Obj::lensProp( 'settings' ), | ||
| 21 | Obj::lensMappedProp( 'icon_list' ), | ||
| 22 | Obj::lensPath( [ '__dynamic__', 'link' ] ) | ||
| 23 | ); | ||
| 24 | |||
| 25 | return [ $isIconList, $iconListLinksLens, 'popup', 'popup' ]; | ||
| 26 | } | ||
| 27 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Logic; | ||
| 6 | use WPML\FP\Obj; | ||
| 7 | use WPML\FP\Relation; | ||
| 8 | |||
| 9 | class LoopCarousel { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @return array | ||
| 13 | */ | ||
| 14 | public static function get() { | ||
| 15 | $loopCarouselIdPath = [ 'settings', 'template_id' ]; | ||
| 16 | |||
| 17 | $hasLoopCarousel = Logic::allPass( [ | ||
| 18 | Relation::propEq( 'widgetType', 'loop-carousel' ), | ||
| 19 | Obj::path( $loopCarouselIdPath ), | ||
| 20 | ] ); | ||
| 21 | |||
| 22 | $loopCarouselIdLens = Obj::lensPath( $loopCarouselIdPath ); | ||
| 23 | |||
| 24 | return [ $hasLoopCarousel, $loopCarouselIdLens ]; | ||
| 25 | } | ||
| 26 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Logic; | ||
| 6 | use WPML\FP\Obj; | ||
| 7 | use WPML\FP\Relation; | ||
| 8 | |||
| 9 | class LoopGrid { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * @return array | ||
| 13 | */ | ||
| 14 | public static function get() { | ||
| 15 | $loopIdPath = [ 'settings', 'template_id' ]; | ||
| 16 | |||
| 17 | $hasLoop = Logic::allPass( [ | ||
| 18 | Relation::propEq( 'widgetType', 'loop-grid' ), | ||
| 19 | Obj::path( $loopIdPath ), | ||
| 20 | ] ); | ||
| 21 | |||
| 22 | $loopIdLens = Obj::lensPath( $loopIdPath ); | ||
| 23 | |||
| 24 | return [ $hasLoop, $loopIdLens ]; | ||
| 25 | } | ||
| 26 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Relation; | ||
| 7 | use WPML\FP\Logic; | ||
| 8 | |||
| 9 | |||
| 10 | class Popup { | ||
| 11 | |||
| 12 | /** | ||
| 13 | * @return array | ||
| 14 | */ | ||
| 15 | public static function get() { | ||
| 16 | $popupPath = [ 'settings', '__dynamic__', 'link' ]; | ||
| 17 | |||
| 18 | // $isDynamicLink :: array -> bool | ||
| 19 | $isDynamicLink = Logic::allPass( [ | ||
| 20 | Relation::propEq( 'elType', 'widget' ), | ||
| 21 | Obj::path( $popupPath ), | ||
| 22 | ] ); | ||
| 23 | |||
| 24 | $lens = Obj::lensPath( $popupPath ); | ||
| 25 | |||
| 26 | return [ $isDynamicLink, $lens, 'popup', 'popup' ]; | ||
| 27 | } | ||
| 28 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | class Provider { | ||
| 6 | |||
| 7 | /** | ||
| 8 | * @return array | ||
| 9 | */ | ||
| 10 | public static function get() { | ||
| 11 | return [ | ||
| 12 | EssentialAddons\ContentTimeline::get(), | ||
| 13 | LoopGrid::get(), | ||
| 14 | LoopCarousel::get(), | ||
| 15 | Hotspot::get(), | ||
| 16 | Popup::get(), | ||
| 17 | IconList::get(), | ||
| 18 | FormPopup::get(), | ||
| 19 | WooProduct::get( 'title' ), | ||
| 20 | WooProduct::get( 'short-description' ), | ||
| 21 | ]; | ||
| 22 | } | ||
| 23 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config\DynamicElements; | ||
| 4 | |||
| 5 | use WPML\FP\Fns; | ||
| 6 | use WPML\FP\Obj; | ||
| 7 | use WPML\FP\Relation; | ||
| 8 | use WPML\FP\Logic; | ||
| 9 | |||
| 10 | |||
| 11 | class WooProduct { | ||
| 12 | |||
| 13 | /** | ||
| 14 | * @param string $widgetName | ||
| 15 | * | ||
| 16 | * @return callable(string): string | ||
| 17 | */ | ||
| 18 | private static function getConfig( $widgetName ) { | ||
| 19 | $widgetConfig = wpml_collect( [ | ||
| 20 | 'title' => [ | ||
| 21 | 'dynamicKey' => 'title', | ||
| 22 | 'widgetType' => 'heading', | ||
| 23 | 'shortcodeName' => 'woocommerce-product-title-tag', | ||
| 24 | ], | ||
| 25 | 'short-description' => [ | ||
| 26 | 'dynamicKey' => 'editor', | ||
| 27 | 'widgetType' => 'text-editor', | ||
| 28 | 'shortcodeName' => 'woocommerce-product-short-description-tag', | ||
| 29 | ], | ||
| 30 | ] )->get( $widgetName ); | ||
| 31 | |||
| 32 | return Obj::prop( Fns::__, $widgetConfig ); | ||
| 33 | } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * @param string $widget | ||
| 37 | * | ||
| 38 | * @return array | ||
| 39 | */ | ||
| 40 | public static function get( $widget ) { | ||
| 41 | $get = self::getConfig( $widget ); | ||
| 42 | |||
| 43 | $widgetPath = [ 'settings', '__dynamic__', $get( 'dynamicKey' ) ]; | ||
| 44 | |||
| 45 | // $isWooWidget :: array -> bool | ||
| 46 | $isWooWidget = Logic::allPass( [ | ||
| 47 | Relation::propEq( 'widgetType', $get( 'widgetType' ) ), | ||
| 48 | Obj::path( $widgetPath ), | ||
| 49 | ] ); | ||
| 50 | |||
| 51 | // $widgetLens :: callable -> callable -> mixed | ||
| 52 | $widgetLens = Obj::lensPath( $widgetPath ); | ||
| 53 | |||
| 54 | return [ $isWooWidget, $widgetLens, $get( 'shortcodeName' ), 'product_id' ]; | ||
| 55 | } | ||
| 56 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Config; | ||
| 4 | |||
| 5 | class Factory extends \WPML\PB\Config\Factory { | ||
| 6 | |||
| 7 | const DATA = [ | ||
| 8 | 'configRoot' => 'elementor-widgets', | ||
| 9 | 'defaultConditionKey' => 'widgetType', | ||
| 10 | 'pbKey' => 'elementor', | ||
| 11 | 'translatableWidgetsHook' => 'wpml_elementor_widgets_to_translate', | ||
| 12 | ]; | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @inheritDoc | ||
| 16 | */ | ||
| 17 | protected function getPbData( $key ) { | ||
| 18 | return self::DATA[ $key ]; | ||
| 19 | } | ||
| 20 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor; | ||
| 4 | |||
| 5 | class DataConvert { | ||
| 6 | |||
| 7 | /** | ||
| 8 | * @param array $data | ||
| 9 | * | ||
| 10 | * @return string | ||
| 11 | */ | ||
| 12 | public static function serialize( array $data ) { | ||
| 13 | return wp_slash( wp_json_encode( $data ) ); | ||
| 14 | } | ||
| 15 | |||
| 16 | /** | ||
| 17 | * @param array|string $data | ||
| 18 | * | ||
| 19 | * @return array | ||
| 20 | */ | ||
| 21 | public static function unserialize( $data ) { | ||
| 22 | if ( self::isElementorArray( $data ) ) { | ||
| 23 | return $data; | ||
| 24 | } | ||
| 25 | |||
| 26 | $value = is_array( $data ) ? $data[0] : $data; | ||
| 27 | |||
| 28 | if ( self::isElementorArray( $value ) ) { | ||
| 29 | return $value; | ||
| 30 | } | ||
| 31 | |||
| 32 | return self::unserializeString( $value ); | ||
| 33 | } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * @param string $string | ||
| 37 | * | ||
| 38 | * @return array | ||
| 39 | */ | ||
| 40 | private static function unserializeString( $string ) { | ||
| 41 | // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize | ||
| 42 | return is_serialized( $string ) ? unserialize( $string ) : json_decode( $string, true ); | ||
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 46 | * @param mixed $data | ||
| 47 | * | ||
| 48 | * @return bool | ||
| 49 | */ | ||
| 50 | private static function isElementorArray( $data ) { | ||
| 51 | return is_array( $data ) && count( $data ) > 0 && isset( $data[0]['id'] ); | ||
| 52 | } | ||
| 53 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\DynamicContent; | ||
| 4 | |||
| 5 | use WPML_PB_String; | ||
| 6 | |||
| 7 | class Field { | ||
| 8 | |||
| 9 | /** | ||
| 10 | * e.g. '[elementor-tag id="cc0b6c6" name="post-title" settings="ENCODED_STRING"]' | ||
| 11 | * | ||
| 12 | * @var string $tagValue | ||
| 13 | */ | ||
| 14 | public $tagValue; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * e.g. 'title' | ||
| 18 | * | ||
| 19 | * @var string $tagKey | ||
| 20 | */ | ||
| 21 | public $tagKey; | ||
| 22 | |||
| 23 | /** | ||
| 24 | * The node ID. | ||
| 25 | * | ||
| 26 | * @var string $nodeId | ||
| 27 | */ | ||
| 28 | public $nodeId; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The item ID inside the node with items. | ||
| 32 | * | ||
| 33 | * @var string $itemId | ||
| 34 | */ | ||
| 35 | public $itemId; | ||
| 36 | |||
| 37 | /** | ||
| 38 | * @param string $tagValue | ||
| 39 | * @param string $tagKey | ||
| 40 | * @param string $nodeId | ||
| 41 | * @param string $itemId | ||
| 42 | */ | ||
| 43 | public function __construct( $tagValue, $tagKey, $nodeId, $itemId = '' ) { | ||
| 44 | $this->tagValue = $tagValue; | ||
| 45 | $this->tagKey = $tagKey; | ||
| 46 | $this->nodeId = $nodeId; | ||
| 47 | $this->itemId = $itemId; | ||
| 48 | } | ||
| 49 | |||
| 50 | /** | ||
| 51 | * @see \WPML_Elementor_Translatable_Nodes::get_string_name() | ||
| 52 | * @see \WPML_Elementor_Module_With_Items::get_string_name() | ||
| 53 | * | ||
| 54 | * @param WPML_PB_String $string | ||
| 55 | * | ||
| 56 | * @return bool | ||
| 57 | */ | ||
| 58 | public function isMatchingStaticString( WPML_PB_String $string ) { | ||
| 59 | $pattern = '/^' . $this->tagKey . '-.*-' . $this->nodeId . '$/'; | ||
| 60 | |||
| 61 | if ( $this->itemId ) { | ||
| 62 | $pattern = '/^' . $this->tagKey . '-.*-' . $this->nodeId . '-' . $this->itemId . '$/'; | ||
| 63 | } | ||
| 64 | |||
| 65 | return (bool) preg_match( $pattern, $string->get_name() ); | ||
| 66 | } | ||
| 67 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\DynamicContent; | ||
| 4 | |||
| 5 | use WPML\Collect\Support\Collection; | ||
| 6 | use WPML_Elementor_Translatable_Nodes; | ||
| 7 | use WPML_PB_String; | ||
| 8 | |||
| 9 | class Strings { | ||
| 10 | |||
| 11 | const KEY_SETTINGS = WPML_Elementor_Translatable_Nodes::SETTINGS_FIELD; | ||
| 12 | const KEY_DYNAMIC = '__dynamic__'; | ||
| 13 | const KEY_NODE_ID = 'id'; | ||
| 14 | const KEY_ITEM_ID = '_id'; | ||
| 15 | |||
| 16 | const SETTINGS_REGEX = '/settings="(.*?(?="]))/'; | ||
| 17 | const NAME_PREFIX = 'dynamic'; | ||
| 18 | const DELIMITER = '-'; | ||
| 19 | const TRANSLATABLE_SETTINGS = [ | ||
| 20 | 'before', | ||
| 21 | 'after', | ||
| 22 | 'fallback', | ||
| 23 | 'video_url', | ||
| 24 | ]; | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Remove the strings overwritten with dynamic content | ||
| 28 | * and add the extra strings "before", "after" and "fallback". | ||
| 29 | * | ||
| 30 | * @param WPML_PB_String[] $strings | ||
| 31 | * @param string $nodeId | ||
| 32 | * @param array $element | ||
| 33 | * | ||
| 34 | * @return WPML_PB_String[] | ||
| 35 | */ | ||
| 36 | public static function filter( array $strings, $nodeId, array $element ) { | ||
| 37 | |||
| 38 | $dynamicFields = self::getDynamicFields( $element ); | ||
| 39 | |||
| 40 | $updateFromDynamicFields = function( WPML_PB_String $string ) use ( &$dynamicFields ) { | ||
| 41 | $matchingField = $dynamicFields->first( | ||
| 42 | function( Field $field ) use ( $string ) { | ||
| 43 | return $field->isMatchingStaticString( $string ); | ||
| 44 | } | ||
| 45 | ); | ||
| 46 | |||
| 47 | if ( $matchingField ) { | ||
| 48 | return self::addBeforeAfterAndFallback( wpml_collect( [ $dynamicFields->pull( $dynamicFields->search( $matchingField ) ) ] ) ); | ||
| 49 | } | ||
| 50 | |||
| 51 | return $string; | ||
| 52 | }; | ||
| 53 | |||
| 54 | return wpml_collect( $strings ) | ||
| 55 | ->map( $updateFromDynamicFields ) | ||
| 56 | ->merge( self::addBeforeAfterAndFallback( $dynamicFields ) ) | ||
| 57 | ->flatten() | ||
| 58 | ->toArray(); | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | ||
| 62 | * @param array $element | ||
| 63 | * | ||
| 64 | * @return Collection | ||
| 65 | */ | ||
| 66 | private static function getDynamicFields( array $element ) { | ||
| 67 | if ( self::isModuleWithItems( $element ) ) { | ||
| 68 | return self::getDynamicFieldsForModuleWithItems( $element ); | ||
| 69 | } elseif ( isset( $element[ self::KEY_SETTINGS ][ self::KEY_DYNAMIC ] ) ) { | ||
| 70 | return self::getFields( | ||
| 71 | $element[ self::KEY_SETTINGS ][ self::KEY_DYNAMIC ], | ||
| 72 | $element[ self::KEY_NODE_ID ] | ||
| 73 | ); | ||
| 74 | } | ||
| 75 | |||
| 76 | return wpml_collect(); | ||
| 77 | } | ||
| 78 | |||
| 79 | /** | ||
| 80 | * @param array $element | ||
| 81 | * | ||
| 82 | * @return Collection | ||
| 83 | */ | ||
| 84 | private static function getDynamicFieldsForModuleWithItems( array $element ) { | ||
| 85 | $isDynamic = function( $item ) { | ||
| 86 | return isset( $item[ self::KEY_DYNAMIC ] ); | ||
| 87 | }; | ||
| 88 | $getFields = function( array $item ) use ( $element ) { | ||
| 89 | return self::getFields( | ||
| 90 | $item[ self::KEY_DYNAMIC ], | ||
| 91 | $element[ self::KEY_NODE_ID ], | ||
| 92 | $item[ self::KEY_ITEM_ID ] | ||
| 93 | ); | ||
| 94 | }; | ||
| 95 | |||
| 96 | return wpml_collect( reset( $element[ self::KEY_SETTINGS ] ) ) | ||
| 97 | ->filter( $isDynamic ) | ||
| 98 | ->map( $getFields ) | ||
| 99 | ->flatten(); | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * @param array $data | ||
| 104 | * @param string $nodeId | ||
| 105 | * @param string $itemId | ||
| 106 | * | ||
| 107 | * @return Collection | ||
| 108 | */ | ||
| 109 | private static function getFields( array $data, $nodeId, $itemId = '' ) { | ||
| 110 | $buildField = function( $tagValue, $tagKey ) use ( $nodeId, $itemId ) { | ||
| 111 | return new Field( $tagValue, $tagKey, $nodeId, $itemId ); | ||
| 112 | }; | ||
| 113 | |||
| 114 | return wpml_collect( $data )->map( $buildField ); | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * @param array $element | ||
| 119 | * | ||
| 120 | * @return bool | ||
| 121 | */ | ||
| 122 | private static function isModuleWithItems( array $element ) { | ||
| 123 | if ( isset( $element[ self::KEY_SETTINGS ] ) ) { | ||
| 124 | $firstSettingElement = reset( $element[ self::KEY_SETTINGS ] ); | ||
| 125 | return is_array( $firstSettingElement ) && 0 === key( $firstSettingElement ); | ||
| 126 | } | ||
| 127 | |||
| 128 | return false; | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 132 | * @param Collection $dynamicFields | ||
| 133 | * | ||
| 134 | * @return Collection | ||
| 135 | */ | ||
| 136 | private static function addBeforeAfterAndFallback( Collection $dynamicFields ) { | ||
| 137 | $dynamicFieldToSettingStrings = function( Field $field ) { | ||
| 138 | preg_match( self::SETTINGS_REGEX, $field->tagValue, $matches ); | ||
| 139 | |||
| 140 | $isTranslatableSetting = function( $value, $settingField ) { | ||
| 141 | return $value && is_string( $value ) && in_array( $settingField, self::TRANSLATABLE_SETTINGS, true ); | ||
| 142 | }; | ||
| 143 | |||
| 144 | $buildStringFromSetting = function( $value, $settingField ) use ( $field ) { | ||
| 145 | return new WPML_PB_String( | ||
| 146 | $value, | ||
| 147 | self::getStringName( $field->nodeId, $field->itemId, $field->tagKey, $settingField ), | ||
| 148 | sprintf( __( 'Dynamic content string: %s', 'sitepress' ), $field->tagKey ), | ||
| 149 | 'LINE' | ||
| 150 | ); | ||
| 151 | }; | ||
| 152 | |||
| 153 | return wpml_collect( isset( $matches[1] ) ? self::decodeSettings( $matches[1] ) : [] ) | ||
| 154 | ->filter( $isTranslatableSetting ) | ||
| 155 | ->map( $buildStringFromSetting ); | ||
| 156 | }; | ||
| 157 | |||
| 158 | return $dynamicFields->map( $dynamicFieldToSettingStrings ); | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * @param array $element | ||
| 163 | * @param WPML_PB_String $string | ||
| 164 | * | ||
| 165 | * @return array | ||
| 166 | */ | ||
| 167 | public static function updateNode( array $element, WPML_PB_String $string ) { | ||
| 168 | $stringNameParts = explode( self::DELIMITER, $string->get_name() ); | ||
| 169 | |||
| 170 | if ( count( $stringNameParts ) !== 5 || self::NAME_PREFIX !== $stringNameParts[0] ) { | ||
| 171 | return $element; | ||
| 172 | } | ||
| 173 | |||
| 174 | list( , , $itemId, $dynamicField, $settingField ) = $stringNameParts; | ||
| 175 | |||
| 176 | if ( $itemId && self::isModuleWithItems( $element ) ) { | ||
| 177 | $element = self::updateNodeWithItems( $element, $string, $stringNameParts ); | ||
| 178 | } elseif ( isset( $element[ self::KEY_SETTINGS ][ self::KEY_DYNAMIC ][ $dynamicField ] ) ) { | ||
| 179 | $element[ self::KEY_SETTINGS ][ self::KEY_DYNAMIC ][ $dynamicField ] = self::replaceSettingString( | ||
| 180 | $element[ self::KEY_SETTINGS ][ self::KEY_DYNAMIC ][ $dynamicField ], | ||
| 181 | $string, | ||
| 182 | $settingField | ||
| 183 | ); | ||
| 184 | } | ||
| 185 | |||
| 186 | return $element; | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * @param string $encodedSettings | ||
| 191 | * @param WPML_PB_String $string | ||
| 192 | * @param string $settingField | ||
| 193 | * | ||
| 194 | * @return string|null | ||
| 195 | */ | ||
| 196 | private static function replaceSettingString( $encodedSettings, WPML_PB_String $string, $settingField ) { | ||
| 197 | $replace = function( array $matches ) use ( $string, $settingField ) { | ||
| 198 | $settings = self::decodeSettings( $matches[1] ); | ||
| 199 | $settings[ $settingField ] = $string->get_value(); | ||
| 200 | $replace = urlencode( json_encode( $settings ) ); | ||
| 201 | |||
| 202 | return str_replace( $matches[1], $replace, $matches[0] ); | ||
| 203 | }; | ||
| 204 | |||
| 205 | return preg_replace_callback( self::SETTINGS_REGEX, $replace, $encodedSettings ); | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 209 | * @param array $element | ||
| 210 | * @param WPML_PB_String $string | ||
| 211 | * @param array $stringNameParts | ||
| 212 | * | ||
| 213 | * @return array | ||
| 214 | */ | ||
| 215 | private static function updateNodeWithItems( array $element, WPML_PB_String $string, array $stringNameParts ) { | ||
| 216 | list( , , $itemId, $dynamicField, $settingField ) = $stringNameParts; | ||
| 217 | |||
| 218 | $items = wpml_collect( reset( $element[ self::KEY_SETTINGS ] ) ); | ||
| 219 | $mainKey = key( $element[ self::KEY_SETTINGS ] ); | ||
| 220 | |||
| 221 | $replaceStringInItem = function( array $item ) use ( $itemId, $string, $dynamicField, $settingField ) { | ||
| 222 | if ( | ||
| 223 | isset( $item[ self::KEY_DYNAMIC ][ $dynamicField ], $item[ self::KEY_ITEM_ID ] ) | ||
| 224 | && $item[ self::KEY_ITEM_ID ] === $itemId | ||
| 225 | ) { | ||
| 226 | $item[ self::KEY_DYNAMIC ][ $dynamicField ] = self::replaceSettingString( $item[ self::KEY_DYNAMIC ][ $dynamicField ], $string, $settingField ); | ||
| 227 | } | ||
| 228 | |||
| 229 | return $item; | ||
| 230 | }; | ||
| 231 | |||
| 232 | $element[ self::KEY_SETTINGS ][ $mainKey ] = $items->map( $replaceStringInItem )->toArray(); | ||
| 233 | |||
| 234 | return $element; | ||
| 235 | } | ||
| 236 | |||
| 237 | /** | ||
| 238 | * @param string $settingsString | ||
| 239 | * | ||
| 240 | * @return array | ||
| 241 | */ | ||
| 242 | private static function decodeSettings( $settingsString ) { | ||
| 243 | return json_decode( urldecode( $settingsString ), true ); | ||
| 244 | } | ||
| 245 | |||
| 246 | /** | ||
| 247 | * @param string $nodeId | ||
| 248 | * @param string $itemId | ||
| 249 | * @param string $tagKey | ||
| 250 | * @param string $settingField | ||
| 251 | * | ||
| 252 | * @return string | ||
| 253 | */ | ||
| 254 | public static function getStringName( $nodeId, $itemId, $tagKey, $settingField ) { | ||
| 255 | return self::NAME_PREFIX . self::DELIMITER | ||
| 256 | . $nodeId . self::DELIMITER | ||
| 257 | . $itemId . self::DELIMITER | ||
| 258 | . $tagKey . self::DELIMITER | ||
| 259 | . $settingField; | ||
| 260 | } | ||
| 261 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Helper; | ||
| 4 | |||
| 5 | class Node { | ||
| 6 | |||
| 7 | /** | ||
| 8 | * @param array $element | ||
| 9 | * | ||
| 10 | * @return bool | ||
| 11 | */ | ||
| 12 | public static function isTranslatable( $element ) { | ||
| 13 | return isset( $element['elType'] ) && in_array( $element['elType'], [ 'widget', 'container' ], true ); | ||
| 14 | } | ||
| 15 | |||
| 16 | /** | ||
| 17 | * @param array $element | ||
| 18 | * | ||
| 19 | * @return bool | ||
| 20 | */ | ||
| 21 | public static function hasChildren( $element ) { | ||
| 22 | return isset( $element['elements'] ) && count( $element['elements'] ); | ||
| 23 | } | ||
| 24 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Helper; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\FP\Str; | ||
| 7 | |||
| 8 | class StringFormat { | ||
| 9 | |||
| 10 | /** | ||
| 11 | * @param array $settings | ||
| 12 | * @param \WPML_PB_String $string | ||
| 13 | * | ||
| 14 | * @return bool | ||
| 15 | */ | ||
| 16 | public static function useWpAutoP( $settings, $string ) { | ||
| 17 | return 'VISUAL' === $string->get_editor_type() && self::isOneLine( self::getOriginalString( $settings, $string ) ); | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * @param string $content | ||
| 22 | * | ||
| 23 | * @return bool | ||
| 24 | */ | ||
| 25 | private static function isOneLine( $content ) { | ||
| 26 | return ! Str::includes( PHP_EOL, $content ); | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * @param array $settings | ||
| 31 | * @param \WPML_PB_String $string | ||
| 32 | * | ||
| 33 | * @return string | ||
| 34 | */ | ||
| 35 | private static function getOriginalString( $settings, $string ) { | ||
| 36 | if ( 'text-editor' === $settings['widgetType'] ) { | ||
| 37 | return Obj::path( [ 'settings', 'editor' ], $settings ); | ||
| 38 | } elseif ( 'hotspot' === $settings['widgetType'] ) { | ||
| 39 | $items = Obj::path( [ 'settings', 'hotspot' ], $settings ); | ||
| 40 | $found = wpml_collect( $items )->first( function( $item ) use ( $string ) { | ||
| 41 | return Str::endsWith( $item['_id'], $string->get_name() ); | ||
| 42 | }); | ||
| 43 | return Obj::prop( 'hotspot_tooltip_content', $found ); | ||
| 44 | } | ||
| 45 | return ''; | ||
| 46 | } | ||
| 47 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\LIB\WP\Hooks; | ||
| 7 | use function WPML\FP\spreadArgs; | ||
| 8 | |||
| 9 | class CssCache implements \IWPML_Frontend_Action, \IWPML_Backend_Action { | ||
| 10 | |||
| 11 | const TEMPLATES_POST_TYPE = 'elementor_library'; | ||
| 12 | |||
| 13 | /** | ||
| 14 | * @return void | ||
| 15 | */ | ||
| 16 | public function add_hooks() { | ||
| 17 | Hooks::onAction( 'wpml_translation_job_saved' ) | ||
| 18 | ->then( spreadArgs( [ self::class, 'flushCache' ] ) ); | ||
| 19 | } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @param int $postId | ||
| 23 | * | ||
| 24 | * @return void | ||
| 25 | */ | ||
| 26 | public static function flushCache( $postId ) { | ||
| 27 | $post = get_post( $postId ); | ||
| 28 | if ( self::TEMPLATES_POST_TYPE === Obj::prop( 'post_type', $post ) ) { | ||
| 29 | try { | ||
| 30 | $fileManager = \WPML\Container\make( \Elementor\Core\Files\Manager::class ); | ||
| 31 | if ( $fileManager && method_exists( $fileManager, 'clear_cache' ) ) { | ||
| 32 | $fileManager->clear_cache(); | ||
| 33 | } | ||
| 34 | } catch ( \Exception $e ) {} | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } |
| 1 | <?php | ||
| 2 | |||
| 3 | namespace WPML\PB\Elementor\Hooks; | ||
| 4 | |||
| 5 | use WPML\FP\Obj; | ||
| 6 | use WPML\LIB\WP\Hooks; | ||
| 7 | use function WPML\FP\spreadArgs; | ||
| 8 | use WPML\PB\Helper\LanguageNegotiation; | ||
| 9 | |||
| 10 | class DomainsWithMultisite implements \IWPML_Backend_Action { | ||
| 11 | |||
| 12 | public function add_hooks() { | ||
| 13 | if ( is_multisite() && LanguageNegotiation::isUsingDomains() ) { | ||
| 14 | Hooks::onAction( 'elementor/editor/init' ) | ||
| 15 | ->then( spreadArgs( [ $this, 'onElementorEditor' ] ) ); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | public function onElementorEditor() { | ||
| 20 | $isCurrentLangDifferentThanDefault = apply_filters( 'wpml_current_language', null ) !== apply_filters( 'wpml_default_language', null ); | ||
| 21 | |||
| 22 | if ( $isCurrentLangDifferentThanDefault ) { | ||
| 23 | Hooks::onFilter( 'admin_url' ) | ||
| 24 | ->then( spreadArgs( [ $this, 'filterUrl' ] ) ); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 29 | * @param string $url The admin area URL. | ||
| 30 | */ | ||
| 31 | public function filterUrl( $url ) { | ||
| 32 | $parsedUrl = wpml_parse_url( $url ); | ||
| 33 | |||
| 34 | if ( is_array( $parsedUrl ) && ! empty( $parsedUrl['host'] ) ) { | ||
| 35 | return http_build_url( Obj::assoc( 'host', $_SERVER['HTTP_HOST'], $parsedUrl ) ); | ||
| 36 | } | ||
| 37 | |||
| 38 | return $url; | ||
| 39 | } | ||
| 40 | |||
| 41 | private static function isUsingDomains() { | ||
| 42 | return apply_filters( 'wpml_setting', [], 'language_domains' ) | ||
| 43 | && constant( 'WPML_LANGUAGE_NEGOTIATION_TYPE_DOMAIN' ) === (int) apply_filters( 'wpml_setting', 1, 'language_negotiation_type' ); | ||
| 44 | } | ||
| 45 | } |
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/addons/wpml-page-builders/classes/OldPlugin.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/addons/wpml-page-builders/vendor/autoload.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/addons/wpml-page-builders/vendor/composer/LICENSE
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/addons/wpml-page-builders/wpml-dependencies.json
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/Hooks/class-wpml-api-hook-links.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/Hooks/class-wpml-api-hook-permalink.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/Hooks/class-wpml-api-hooks-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/Hooks/class-wpml-tm-api-hook-links.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/CustomXMLConfig/Actions.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/CustomXMLConfig/Factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-ate-proxy-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-ate-proxy.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-rest-base.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-rest-extend-args.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-rest-factory-loader.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-tm-rest-batch-sync.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-tm-rest-jobs-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-tm-rest-jobs.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/API/REST/class-wpml-tm-rest-tp-xliff.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/CacheStorage/StaticVariable.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/CacheStorage/Transient.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/ClonedSites/ApiCommunication.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/ClonedSites/Endpoints/Copy.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/ClonedSites/Endpoints/GetCredits.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/ClonedSites/Endpoints/Move.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/class-wpml-tm-ams-api.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/class-wpml-tm-ate-api.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/API/class-wpml-tm-ate-authentication.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Hooks/LanguageMappingCache.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Hooks/ReturnedJobActionsFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Hooks/class-wpml-tm-ate-api-error.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Hooks/class-wpml-tm-ate-jobs-actions.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Hooks/class-wpml-tm-old-editor.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/REST/class-wpml-tm-rest-ams-clients.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/REST/class-wpml-tm-rest-ate-api.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/REST/class-wpml-tm-rest-ate-jobs.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/REST/class-wpml-tm-rest-xliff.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Review/ApproveTranslations.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Review/NextTranslationLink.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Review/NonPublicCPTPreview.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/Review/ReviewCompletedNotice.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/TranslateEverything/Pause/View.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/CancelJobs.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/EnableATE.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/GetCredits.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/Languages.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/ResumeAll.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/auto-translate/endpoints/SyncLock.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/class-wpml-tm-ams-ate-factories.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/class-wpml-tm-ate-ams-endpoints.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ATE/models/class-wpml-tm-job-created.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ICL-20-migration/res/migration-required.js
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/Installer/class-wpml-installer-gateway.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/REST-hooks/class-wpml-rest-posts-hooks.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/abstract/class-wpml-tm-job-factory-user.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/abstract/class-wpml-tm-record-user.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/admin-menu/class-wpml-admin-menu-item.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/admin-menu/class-wpml-admin-menu-root.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ajax/class-wpml-ajax-response.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/ajax/interface-wpml-ajax-action-run.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/automatic-translation/Actions.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/automatic-translation/ActionsFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/background-task/AbstractTaskEndpoint.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/background-task/BackgroundTaskLoader.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/background-task/BackgroundTaskViewModel.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/block-editor/Blocks/LanguageSwitcher.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/canonicals/class-wpml-canonicals-hooks.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/canonicals/class-wpml-canonicals.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-active-plugin-provider.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-config-update-integrator.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-theme-localization-type.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-tm-resources-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-tm-service-activation-ajax.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-tm-translated-field.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-tm-translators-dropdown.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-tm-troubleshooting-clear-ts.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-translate-independently.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-translation-job-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-translation-management.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/class-wpml-translation-proxy-api.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/container/class-wpml-container.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/cookie/class-wpml-cookie-admin-scripts.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/cookie/class-wpml-cookie-admin-ui.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/cookie/class-wpml-cookie-scripts.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/cookie/class-wpml-cookie-setting-ajax.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/cookie/class-wpml-cookie-setting.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/core-abstract-classes/class-wpml-sp-user.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/core-abstract-classes/class-wpml-tm-user.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/database-queries/translated-posts.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/editor/ATEDetailedErrorMessage.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/editor/ManualJobCreationErrorNotice.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/editor/class-wpml-tm-old-jobs-editor.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/emails/report/class-wpml-tm-batch-report.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/emails/wpml-tm-mail-notification.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/filters/class-wpml-tm-translation-status.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/full-site-editing/BlockTemplates.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/helpers/class-wpml-tm-post-data.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/icl-to-ate-migration/ICLStatus.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-job-element-entity.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-job-entity.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-job-ts-status.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-batch.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-collection.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-date-range.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-repository.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-search-params.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-jobs-sorting-param.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/class-wpml-tm-post-job-entity.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/jobs/utils/ElementLinkFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/AjaxNavigation/Hooks.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-admin-ui.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-assets.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-render.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-settings.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-template.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language-switcher/class-wpml-ls-widget.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language/Detection/CookieLanguage.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/language/class-wpml-all-language-pairs.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/languages/class-wpml-language-collection.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/languages/class-wpml-language-records.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/languages/class-wpml-language.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/languages/class-wpml-languages-ajax.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaAttachmentByUrl.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaCaption.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaCaptionTagsParse.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaImgParse.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaSettings.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/MediaTranslationStatus.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media-translation/PostWithMediaFiles.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/class-wpml-attachment-action.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/class-wpml-media-exception.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/class-wpml-model-attachments.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/duplication/AbstractFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/duplication/HooksFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/settings/class-wpml-media-settings.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/setup/endpoints/PerformSetup.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/media/setup/endpoints/PrepareSetup.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu-elements/class-wpml-custom-columns.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu-elements/class-wpml-support-page.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu-elements/class-wpml-tm-post-link.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/class-wpml-tm-admin-sections.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/class-wpml-tm-scripts-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/dashboard/PostJobsRepository.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/dashboard/class-wpml-tm-wp-query.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/iwpml-tm-admin-section-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/mcsetup/class-wpml-tm-mcs-ate.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/mcsetup/class-wpml-tm-options-ajax.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/tp-polling/wpml-tm-last-picked-up.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-basket/Strings.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-basket/Utility.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-queue/CloneJobs.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-queue/PostTypeFilters.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-roles/RoleValidator.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-services/ActivationAjax.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-services/Resources.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-services/Section.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-services/SectionFactory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/translation-services/ServiceMapper.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/wpml-tm-admin-menus-factory.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/menu/wpml-tm-admin-menus-hooks.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/notices/class-wpml-notice-action.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/notices/class-wpml-notice-render.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/notices/wpml-tm-post-edit-notices.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/options/class-wpml-multilingual-options.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/post-edit-screen/endpoints/SetEditorMode.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/post-translation/SpecialPage/Hooks.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/post-translation/class-wpml-post-status.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/post-types/class-wpml-post-types.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/post-types/class-wpml-translation-modes.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/privacy/class-wpml-core-privacy-content.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/privacy/class-wpml-privacy-content.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/privacy/class-wpml-tm-privacy-content.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/query-filtering/class-wpml-404-guess.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/query-filtering/class-wpml-query-parser.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/query-filtering/class-wpml-term-clauses.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/query-filtering/wpml-query-filter.class.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/query-filtering/wpml-query-utils.class.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/records/class-wpml-tm-icl-translate-job.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/records/class-wpml-tm-icl-translations.php
0 → 100644
This diff is collapsed.
Click to expand it.
wp-content/plugins/sitepress-multilingual-cms 2/classes/records/class-wpml-tm-records.php
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment