first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
<?php
namespace WPML\Media;
use WPML\Element\API\PostTranslations;
use WPML\FP\Cast;
use WPML\FP\Fns;
use WPML\FP\Maybe;
use WPML\FP\Obj;
use WPML\FP\Relation;
use WPML\LIB\WP\Hooks;
use function WPML\FP\pipe;
use function WPML\FP\spreadArgs;
class FrontendHooks implements \IWPML_Frontend_Action {
public function add_hooks() {
Hooks::onFilter( 'wp_get_attachment_caption', 10, 2 )
->then( spreadArgs( Fns::withoutRecursion( Fns::identity(), [ __CLASS__, 'translateCaption' ] ) ) );
}
/**
* @param string $caption
* @param int $postId
*
* @return string
*/
public static function translateCaption( $caption, $postId ) {
// $convertId :: int -> string|int|null
$convertId = pipe( PostTranslations::getInCurrentLanguage(), Obj::prop( 'element_id' ) );
return Maybe::of( $postId )
->map( $convertId )
->map( Cast::toInt() )
->reject( Relation::equals( $postId ) )
->map( 'wp_get_attachment_caption' )
->getOrElse( $caption );
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace WPML\Media;
use WPML\Core\WP\App\Resources;
use WPML\LIB\WP\Hooks;
use WPML\Media\Option;
use WPML\Media\Setup\Endpoint\PerformSetup;
use WPML\Media\Setup\Endpoint\PrepareSetup;
use WPML\Media\Translate\Endpoint\DuplicateFeaturedImages;
use WPML\Media\Translate\Endpoint\FinishMediaTranslation;
use WPML\Media\Translate\Endpoint\PrepareForTranslation;
use WPML\Media\Translate\Endpoint\TranslateExistingMedia;
class Loader implements \IWPML_Backend_Action {
public function add_hooks() {
if ( ! Option::isSetupFinished() ) {
Hooks::onAction( 'wp_loaded' )
->then( [ self::class, 'getData' ] )
->then( Resources::enqueueApp( 'media-setup' ) );
}
}
public static function getData() {
return [
'name' => 'media_setup',
'data' => [
'endpoints' => [
'prepareForTranslation' => PrepareForTranslation::class,
'translateExistingMedia' => TranslateExistingMedia::class,
'duplicateFeaturedImages' => DuplicateFeaturedImages::class,
'finishMediaTranslation' => FinishMediaTranslation::class,
'prepareForSetup' => PrepareSetup::class,
'performSetup' => PerformSetup::class,
]
]
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* WPML_Attachment_Action_Factory
*
* @package WPML
*/
/**
* Class WPML_Attachment_Action_Factory
*/
class WPML_Attachment_Action_Factory implements
IWPML_Backend_Action_Loader, IWPML_Frontend_Action_Loader, IWPML_AJAX_Action_Loader, IWPML_Deferred_Action_Loader {
/**
* Get load action.
*
* @return string
*/
public function get_load_action() {
return 'wpml_loaded';
}
/**
* Create attachment action.
*
* @return WPML_Attachment_Action
*/
public function create() {
global $sitepress, $wpdb;
return new WPML_Attachment_Action( $sitepress, $wpdb );
}
}

View File

@@ -0,0 +1,213 @@
<?php
use WPML\FP\Str;
/**
* WPML_Attachment_Action class file.
*
* @package WPML
*/
/**
* Class WPML_Attachment_Action
*/
class WPML_Attachment_Action implements IWPML_Action {
/**
* SitePress instance.
*
* @var SitePress
*/
private $sitepress;
/**
* Wpdb instance.
*
* @var wpdb
*/
private $wpdb;
/**
* WPML_Attachment_Action constructor.
*
* @param SitePress $sitepress SitePress instance.
* @param wpdb $wpdb wpdb instance.
*/
public function __construct( SitePress $sitepress, wpdb $wpdb ) {
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
}
/**
* Add hooks.
*/
public function add_hooks() {
if ( $this->is_admin_or_xmlrpc() && ! $this->is_uploading_plugin_or_theme() ) {
$active_languages = $this->sitepress->get_active_languages();
if ( count( $active_languages ) > 1 ) {
add_filter( 'views_upload', array( $this, 'views_upload_actions' ) );
}
}
add_filter( 'attachment_link', array( $this->sitepress, 'convert_url' ), 10, 1 );
add_filter( 'wp_delete_file', array( $this, 'delete_file_filter' ) );
}
/**
* Check if we are in site console or xmlrpc request is active.
*
* @return bool
*/
private function is_admin_or_xmlrpc() {
$is_admin = is_admin();
$is_xmlrpc = ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST );
return $is_admin || $is_xmlrpc;
}
/**
* Check if we are uploading plugin or theme.
*
* @return bool
*/
private function is_uploading_plugin_or_theme() {
global $action;
return ( isset( $action ) && ( 'upload-plugin' === $action || 'upload-theme' === $action ) );
}
/**
* Filter views.
*
* @param array $views Views.
*
* @return array
*/
public function views_upload_actions( $views ) {
global $pagenow;
if ( 'upload.php' === $pagenow ) {
// Get current language.
$lang = $this->sitepress->get_current_language();
foreach ( $views as $key => $view ) {
// Extract the base URL and query parameters.
$href_count = preg_match( '/(href=["\'])([\s\S]+?)\?([\s\S]+?)(["\'])/', $view, $href_matches );
if ( $href_count && isset( $href_args ) ) {
$href_base = $href_matches[2];
wp_parse_str( $href_matches[3], $href_args );
} else {
$href_base = 'upload.php';
$href_args = array();
}
if ( 'all' !== $lang ) {
$sql = $this->wpdb->prepare(
"
SELECT COUNT(p.id)
FROM {$this->wpdb->posts} AS p
INNER JOIN {$this->wpdb->prefix}icl_translations AS t
ON p.id = t.element_id
WHERE p.post_type = 'attachment'
AND t.element_type='post_attachment'
AND t.language_code = %s ",
$lang
);
switch ( $key ) {
case 'all':
$and = " AND p.post_status != 'trash' ";
break;
case 'detached':
$and = " AND p.post_status != 'trash' AND p.post_parent = 0 ";
break;
case 'trash':
$and = " AND p.post_status = 'trash' ";
break;
default:
if ( isset( $href_args['post_mime_type'] ) ) {
$and = " AND p.post_status != 'trash' " . wp_post_mime_type_where( $href_args['post_mime_type'], 'p' );
} else {
$and = $this->wpdb->prepare( " AND p.post_status != 'trash' AND p.post_mime_type LIKE %s", $key . '%' );
}
}
// phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
$and = apply_filters( 'wpml-media_view-upload-sql_and', $and, $key, $view, $lang );
$sql_and = $sql . $and;
$sql = apply_filters( 'wpml-media_view-upload-sql', $sql_and, $key, $view, $lang );
$res = apply_filters( 'wpml-media_view-upload-count', null, $key, $view, $lang );
// phpcs:enable
if ( null === $res ) {
$res = $this->wpdb->get_col( $sql );
}
// Replace count.
$view = preg_replace( '/\((\d+)\)/', '(' . $res[0] . ')', $view );
}
// Replace href link, adding the 'lang' argument and the revised count.
$href_args['lang'] = $lang;
$href_args = array_map( 'urlencode', $href_args );
$new_href = add_query_arg( $href_args, $href_base );
$views[ $key ] = preg_replace( '/(href=["\'])([\s\S]+?)(["\'])/', '$1' . $new_href . '$3', $view );
}
}
return $views;
}
/**
* Check if the image is not duplicated to another post before deleting it physically.
*
* @param string $file Full file name.
*
* @return string|null
*/
public function delete_file_filter( $file ) {
if ( $file ) {
$file_name = $this->get_file_name( $file );
$sql = "SELECT pm.meta_id, pm.post_id FROM {$this->wpdb->postmeta} AS pm
WHERE pm.meta_value = %s AND pm.meta_key='_wp_attached_file'";
$attachment_prepared = $this->wpdb->prepare( $sql, [ $file_name ] );
$attachment = $this->wpdb->get_row( $attachment_prepared );
if ( ! empty( $attachment ) ) {
$file = null;
}
}
return $file;
}
private function get_file_name( $file ) {
$file_name = $this->get_file_name_without_size_from_full_name( $file );
$upload_dir = wp_upload_dir();
$path_parts = explode( "/", Str::replace( $upload_dir['basedir'], '', $file ) );
if ( $path_parts ) {
$path_parts[ count( $path_parts ) - 1 ] = $file_name;
}
return ltrim( implode( '/', $path_parts ), '/' );
}
/**
* Get file name without a size, i.e. 'a-600x400.png' -> 'a.png'.
*
* @param string $file Full file name.
*
* @return mixed|string|string[]|null
*/
private function get_file_name_without_size_from_full_name( $file ) {
$file_name = preg_replace( '/^(.+)\-\d+x\d+(\.\w+)$/', '$1$2', $file );
$file_name = preg_replace( '/^[\s\S]+(\/.+)$/', '$1', $file_name );
$file_name = str_replace( '/', '', $file_name );
return $file_name;
}
}

View File

@@ -0,0 +1,4 @@
<?php
class WPML_Media_Exception extends Exception {
}

View File

@@ -0,0 +1,174 @@
<?php
class WPML_Model_Attachments {
const ATTACHMENT_TYPE = 'post_attachment';
/** @var SitePress */
private $sitepress;
/**
* @var WPML_Post_Status
*/
private $status_helper;
/**
* @param SitePress $sitepress
* @param WPML_Post_Status $status_helper
*/
public function __construct( SitePress $sitepress, WPML_Post_Status $status_helper ) {
$this->sitepress = $sitepress;
$this->status_helper = $status_helper;
}
/**
* @param int $attachment_id
* @param int $duplicated_attachment_id
*/
public function duplicate_post_meta_data( $attachment_id, $duplicated_attachment_id ) {
foreach ( array( '_wp_attachment_metadata', '_wp_attached_file' ) as $meta_key ) {
$duplicated_meta_value = get_post_meta( $duplicated_attachment_id, $meta_key, true );
if ( ! $duplicated_meta_value ) {
$source_meta_value = get_post_meta( $attachment_id, $meta_key, true );
update_post_meta( $duplicated_attachment_id, $meta_key, $source_meta_value );
}
}
update_post_meta( $duplicated_attachment_id, 'wpml_media_processed', 1 );
do_action( 'wpml_media_create_duplicate_attachment', $attachment_id, $duplicated_attachment_id );
}
/**
* @param int $trid
* @param string $target_language
*
* @return null|WP_Post
*/
public function find_duplicated_attachment( $trid, $target_language ) {
$attachment_translations = $this->sitepress->get_element_translations( $trid, self::ATTACHMENT_TYPE, true, true );
if ( is_array( $attachment_translations ) ) {
foreach ( $attachment_translations as $attachment_translation ) {
if ( $attachment_translation->language_code === $target_language ) {
return get_post( $attachment_translation->element_id );
}
}
}
return null;
}
/**
* @param WP_Post|null $attachment
* @param int $parent_id_of_attachement
* @param string $target_language
*
* @return int|null
*/
public function fetch_translated_parent_id( $attachment, $parent_id_of_attachement, $target_language ) {
$translated_parent_id = null;
if ( null !== $attachment && $attachment->post_parent ) {
$translated_parent_id = $attachment->post_parent;
}
if ( $parent_id_of_attachement ) {
$parent_post = get_post( $parent_id_of_attachement );
if ( $parent_post ) {
$translated_parent_id = $parent_id_of_attachement;
$parent_id_language_code = $this->sitepress->get_language_for_element( $parent_post->ID, 'post_' . $parent_post->post_type );
if ( $parent_id_language_code !== $target_language ) {
$translated_parent_id = $this->sitepress->get_object_id( $parent_post->ID, $parent_post->post_type, false, $target_language );
}
}
}
return $translated_parent_id;
}
/**
* @param int $new_parent_id
* @param WP_Post $attachment
*/
public function update_parent_id_in_existing_attachment( $new_parent_id, $attachment ) {
if ( $this->is_valid_post_type( $attachment->post_type ) ) {
wp_update_post( array( 'ID' => $attachment->ID, 'post_parent' => $new_parent_id ) );
}
}
/**
* @param string $post_type
*
* @return bool
*/
private function is_valid_post_type( $post_type ) {
$post_types = array_keys( get_post_types( ) );
return in_array( $post_type, $post_types, true );
}
/**
* @param int $attachment_id
* @param string $target_language
* @param int $parent_id_in_target_language
* @param int $trid
*
* @return int
* @throws WPML_Media_Exception
*/
public function duplicate_attachment( $attachment_id, $target_language, $parent_id_in_target_language, $trid ) {
$post = get_post( $attachment_id );
$post->post_parent = $parent_id_in_target_language;
$post->ID = null;
update_post_meta( $parent_id_in_target_language, '_wpml_media_duplicate', true ); // add the post meta if missing
$duplicated_attachment_id = $this->insert_attachment( $post );
if ( ! $duplicated_attachment_id ) {
throw new WPML_Media_Exception( 'Error occured during inserting duplicated attachment to db' );
}
$this->add_language_information_to_attachment( $attachment_id, $duplicated_attachment_id, $target_language, $trid );
return $duplicated_attachment_id;
}
/**
* @param WP_Post $post
*
* @return int
*/
private function insert_attachment( $post ) {
$add_attachment_filters_temp = null;
if ( array_key_exists( 'add_attachment', $GLOBALS['wp_filter'] ) ) {
$add_attachment_filters_temp = $GLOBALS['wp_filter']['add_attachment'];
unset( $GLOBALS['wp_filter']['add_attachment'] );
}
$duplicated_attachment_id = wp_insert_post( $post );
if ( ! is_int( $duplicated_attachment_id ) ) {
$duplicated_attachment_id = 0;
}
if ( null !== $add_attachment_filters_temp ) {
$GLOBALS['wp_filter']['add_attachment'] = $add_attachment_filters_temp;
unset( $add_attachment_filters_temp );
}
return $duplicated_attachment_id;
}
/**
* @param int $attachment_id
* @param int $duplicated_attachment_id
* @param string $target_language
* @param int $trid
*/
private function add_language_information_to_attachment( $attachment_id, $duplicated_attachment_id, $target_language, $trid ) {
$source_language = $this->sitepress->get_language_for_element( $attachment_id, self::ATTACHMENT_TYPE );
$this->sitepress->set_element_language_details( $duplicated_attachment_id, self::ATTACHMENT_TYPE, $trid, $target_language, $source_language );
$this->status_helper->set_status( $duplicated_attachment_id, ICL_TM_DUPLICATE );
$this->status_helper->set_update_status( $duplicated_attachment_id, false );
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace WPML\Media\Duplication;
abstract class AbstractFactory implements \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader {
/**
* @return bool
*/
protected static function shouldActivateHooks() {
return \WPML_Element_Sync_Settings_Factory::createPost()->is_sync( 'attachment' );
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace WPML\Media\Duplication;
use WPML\Element\API\IfOriginalPost;
use WPML\FP\Fns;
use WPML\FP\Relation;
use WPML\LIB\WP\Post;
use WPML\LIB\WP\Hooks as WPHooks;
use function WPML\FP\pipe;
use function WPML\FP\spreadArgs;
class Hooks {
public static function add() {
WPHooks::onAction( 'update_postmeta', 10, 4 )
->then( spreadArgs( Fns::withoutRecursion( Fns::noop(), [ self::class, 'syncAttachedFile' ] ) ) );
}
public static function syncAttachedFile( $meta_id, $object_id, $meta_key, $meta_value ) {
if ( $meta_key === '_wp_attached_file' ) {
$prevValue = Post::getMetaSingle( $object_id, $meta_key );
// $isMetaSameAsPrevious :: id → bool
$isMetaSameAsPrevious = pipe( Post::getMetaSingle( Fns::__, $meta_key ), Relation::equals( $prevValue ) );
IfOriginalPost::getTranslationIds( $object_id )
->filter( Fns::unary( $isMetaSameAsPrevious ) )
->each( Fns::unary( Post::updateMeta( Fns::__, $meta_key, $meta_value ) ) );
}
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace WPML\Media\Duplication;
class HooksFactory extends AbstractFactory {
public function create() {
if ( self::shouldActivateHooks() ) {
return [ Hooks::class, 'add' ];
}
return null;
}
}

View File

@@ -0,0 +1,12 @@
<?php
class WPML_Media_Attachments_Duplication_Factory extends \WPML\Media\Duplication\AbstractFactory {
public function create() {
if ( self::shouldActivateHooks() ) {
return \WPML\Container\make( WPML_Media_Attachments_Duplication::class );
}
return null;
}
}

View File

@@ -0,0 +1,16 @@
<?php
class WPML_Media_Settings_Factory extends WPML_Current_Screen_Loader_Factory {
public function create_hooks() {
global $wpdb;
return new WPML_Media_Settings( $wpdb );
}
public function get_screen_regex() {
return defined( 'WPML_TM_FOLDER' )
? '/(' . WPML_PLUGIN_FOLDER . '\/menu\/translation-options|wpml_page_' . WPML_TM_FOLDER . '\/menu\/settings)/'
: '/' . WPML_PLUGIN_FOLDER . '\/menu\/translation-options/';
}
}

View File

@@ -0,0 +1,190 @@
<?php
class WPML_Media_Settings {
const ID = 'ml-content-setup-sec-media';
private $wpdb;
public function __construct( $wpdb ) {
$this->wpdb = $wpdb;
}
public function add_hooks() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_script' ) );
add_action( 'icl_tm_menu_mcsetup', array( $this, 'render' ) );
add_filter( 'wpml_mcsetup_navigation_links', array( $this, 'mcsetup_navigation_links' ) );
}
public function enqueue_script() {
wp_enqueue_script( 'wpml-media-settings', ICL_PLUGIN_URL . '/res/js/media/settings.js', array(), ICL_SITEPRESS_VERSION, true );
}
public function render() {
$orphan_attachments_sql = "
SELECT COUNT(*)
FROM {$this->wpdb->posts}
WHERE post_type = 'attachment'
AND ID NOT IN (
SELECT element_id
FROM {$this->wpdb->prefix}icl_translations
WHERE element_type='post_attachment'
)
";
$orphan_attachments = $this->wpdb->get_var( $orphan_attachments_sql );
?>
<div class="wpml-section" id="<?php echo esc_attr( self::ID ); ?>">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Media Translation', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<?php if ( $orphan_attachments ) : ?>
<p><?php esc_html_e( "The Media Translation plugin needs to add languages to your site's media. Without this language information, existing media files will not be displayed in the WordPress admin.", 'sitepress' ); ?></p>
<?php else : ?>
<p><?php esc_html_e( 'You can check if some attachments can be duplicated to translated content:', 'sitepress' ); ?></p>
<?php endif ?>
<form id="wpml_media_options_form">
<input type="hidden" name="no_lang_attachments" value="<?php echo $orphan_attachments; ?>"/>
<input type="hidden" id="wpml_media_options_action"/>
<table class="wpml-media-existing-content">
<tr>
<td colspan="2">
<ul class="wpml_media_options_language">
<li><label><input type="checkbox" id="set_language_info" name="set_language_info" value="1"
<?php
if ( ! empty( $orphan_attachments ) ) :
?>
checked="checked"<?php endif; ?>
<?php
if ( empty( $orphan_attachments ) ) :
?>
disabled="disabled"<?php endif ?> />&nbsp;<?php esc_html_e( 'Set language information for existing media', 'sitepress' ); ?></label></li>
<li><label><input type="checkbox" id="translate_media" name="translate_media" value="1" checked="checked"/>&nbsp;<?php esc_html_e( 'Translate existing media in all languages', 'sitepress' ); ?></label></li>
<li><label><input type="checkbox" id="duplicate_media" name="duplicate_media" value="1" checked="checked"/>&nbsp;<?php esc_html_e( 'Duplicate existing media for translated content', 'sitepress' ); ?></label></li>
<li><label><input type="checkbox" id="duplicate_featured" name="duplicate_featured" value="1" checked="checked"/>&nbsp;<?php esc_html_e( 'Duplicate the featured images for translated content', 'sitepress' ); ?></label></li>
</ul>
</td>
</tr>
<tr>
<td><a href="https://wpml.org/documentation/getting-started-guide/media-translation/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore" target="_blank"><?php esc_html_e( 'Media Translation Documentation', 'sitepress' ); ?></a></td>
<td align="right">
<?php wp_nonce_field( 'wpml_media_settings_actions', 'wpml_media_settings_nonce' ); ?>
<input class="button-primary" name="start" type="submit" value="<?php esc_attr_e( 'Start', 'sitepress' ); ?> &raquo;"/>
</td>
</tr>
<tr>
<td colspan="2">
<img class="progress" src="<?php echo ICL_PLUGIN_URL; ?>/res/img/ajax-loader.gif" width="16" height="16" alt="loading" style="display: none;"/>
&nbsp;<span class="status"> </span>
</td>
</tr>
</table>
<table class="wpml-media-new-content-settings">
<tr>
<td colspan="2">
<h4><?php esc_html_e( 'How to handle media for new content:', 'sitepress' ); ?></h4>
</td>
</tr>
<tr>
<td colspan="2">
<ul class="wpml_media_options_language">
<?php
$settings = get_option( '_wpml_media' );
$content_defaults = $settings['new_content_settings'];
$always_translate_media_html_checked = $content_defaults['always_translate_media'] ? 'checked="checked"' : '';
$duplicate_media_html_checked = $content_defaults['duplicate_media'] ? 'checked="checked"' : '';
$duplicate_featured_html_checked = $content_defaults['duplicate_featured'] ? 'checked="checked"' : '';
?>
<li>
<label><input type="checkbox" name="content_default_always_translate_media"
value="1" <?php echo $always_translate_media_html_checked; ?> />&nbsp;<?php esc_html_e( 'When uploading media to the Media library, make it available in all languages', 'sitepress' ); ?></label>
</li>
<li>
<label><input type="checkbox" name="content_default_duplicate_media"
value="1" <?php echo $duplicate_media_html_checked; ?> />&nbsp;<?php esc_html_e( 'Duplicate media attachments for translations', 'sitepress' ); ?></label>
</li>
<li>
<label><input type="checkbox" name="content_default_duplicate_featured"
value="1" <?php echo $duplicate_featured_html_checked; ?> />&nbsp;<?php esc_html_e( 'Duplicate featured images for translations', 'sitepress' ); ?></label>
</li>
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<h4><?php esc_html_e( 'How to handle media library texts:', 'sitepress' ); ?></h4>
</td>
</tr>
<tr>
<td colspan="2">
<ul class="wpml_media_options_media_library_texts">
<?php
$settings = get_option( '_wpml_media' );
$translateMediaLibraryTexts = \WPML\FP\Obj::propOr(false, 'translate_media_library_texts', $settings) ? 'checked="checked"' : '';
?>
<li>
<label><input type="checkbox" name="translate_media_library_texts"
value="1" <?php echo $translateMediaLibraryTexts; ?> />&nbsp;<?php esc_html_e( 'Translate media library texts with posts', 'sitepress' ); ?></label>
</li>
</ul>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<input class="button-secondary" name="set_defaults" type="submit" value="<?php esc_attr_e( 'Apply', 'sitepress' ); ?>"/>
</td>
</tr>
<tr>
<td colspan="2">
<img class="content_default_progress" src="<?php echo ICL_PLUGIN_URL; ?>/res/img/ajax-loader.gif" width="16" height="16" alt="loading" style="display: none;"/>
&nbsp;<span class="content_default_status"> </span>
</td>
</tr>
</table>
<div id="wpml_media_all_done" class="hidden updated">
<p><?php esc_html_e( "You're all done. From now on, all new media files that you upload to content will receive a language. You can automatically duplicate them to translations from the post-edit screen.", 'sitepress' ); ?></p>
</div>
</form>
</div>
</div>
<?php
}
public function mcsetup_navigation_links( array $mcsetup_sections ) {
$mcsetup_sections[ self::ID ] = esc_html__( 'Media Translation', 'sitepress' );
return $mcsetup_sections;
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace WPML\Media\Setup\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use WPML\FP\Right;
use WPML\FP\Left;
use function WPML\Container\make;
class PerformSetup implements IHandler {
public function run( Collection $data ) {
if ( ! defined( 'WPML_MEDIA_VERSION' ) || ! class_exists( 'WPML_Media_Set_Posts_Media_Flag_Factory' ) ) {
return Left::of( [ 'key' => false ] );
}
$offset = $data->get( 'offset' );
$mediaFlag = make( \WPML_Media_Set_Posts_Media_Flag_Factory::class )->create();
list ( , $newOffset, $continue ) = $mediaFlag->process_batch( $offset );
return Right::of( [ 'continue' => $continue, 'offset' => $newOffset, ] );
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace WPML\Media\Setup\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use WPML\Utilities\KeyedLock;
use WPML\FP\Left;
use WPML\FP\Right;
use function WPML\Container\make;
class PrepareSetup implements IHandler {
const LOCK_RELEASE_TIMEOUT = 2 * MINUTE_IN_SECONDS;
public function run( Collection $data ) {
if ( !defined( 'WPML_MEDIA_VERSION' ) || !class_exists( 'WPML_Media_Set_Posts_Media_Flag_Factory' ) ) {
return Left::of( [ 'key' => false ] );
}
$lock = make( KeyedLock::class, [ ':name' => self::class ] );
$key = $lock->create( $data->get( 'key' ), self::LOCK_RELEASE_TIMEOUT );
if ( $key ) {
$mediaFlag = make( \WPML_Media_Set_Posts_Media_Flag_Factory::class)->create();
$mediaFlag->clear_flags();
return Right::of( [ 'key' => $key, ] );
} else {
return Left::of( [ 'key' => 'in-use', ] );
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace WPML\Media\Translate;
use WPML\LIB\WP\Hooks;
use WPML\Media\Option;
class LanguagesUpdated implements \IWPML_AJAX_Action {
public function add_hooks() {
Hooks::onAction( 'wpml_update_active_languages' )
->then( function () {
Option::setSetupFinished( false );
} );
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace WPML\Media\Translate\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use WPML\FP\Obj;
use WPML\LIB\WP\Option;
use function WPML\Container\make;
use WPML\FP\Right;
class DuplicateFeaturedImages implements IHandler {
public function run( Collection $data ) {
if ( ! $this->shouldDuplicateFeaturedImages() ) {
return Right::of( 0 );
}
$numberLeft = $data->get( 'remaining', null );
return Right::of(
make( \WPML_Media_Attachments_Duplication::class )->batch_duplicate_featured_images( false, $numberLeft )
);
}
/**
* @return bool
*/
private function shouldDuplicateFeaturedImages() {
return (bool) Obj::pathOr( false, [ 'new_content_settings', 'duplicate_featured' ], Option::getOr( '_wpml_media', [] ) );
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace WPML\Media\Translate\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use function WPML\Container\make;
use WPML\FP\Right;
class FinishMediaTranslation implements IHandler {
public function run( Collection $data ) {
make( \WPML_Media_Attachments_Duplication::class )->batch_mark_processed( false );
return Right::of( true );
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace WPML\Media\Translate\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use function WPML\Container\make;
use WPML\FP\Left;
use WPML\FP\Right;
use WPML\Media\Option;
use WPML\Utilities\KeyedLock;
class PrepareForTranslation implements IHandler {
const LOCK_RELEASE_TIMEOUT = 2 * MINUTE_IN_SECONDS;
public function run( Collection $data ) {
if ( Option::isSetupFinished() ) {
return Left::of( [ 'key' => false ] );
}
$lock = make( KeyedLock::class, [ ':name' => self::class ] );
$key = $lock->create( $data->get( 'key' ), self::LOCK_RELEASE_TIMEOUT );
if ( $key ) {
make( \WPML_Media_Attachments_Duplication::class )->batch_scan_prepare( false );
return Right::of( [ 'key' => $key, ] );
} else {
return Left::of( [ 'key' => 'in-use', ] );
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace WPML\Media\Translate\Endpoint;
use WPML\Ajax\IHandler;
use WPML\Collect\Support\Collection;
use function WPML\Container\make;
use WPML\FP\Right;
class TranslateExistingMedia implements IHandler {
public function run( Collection $data ) {
return Right::of(
make( \WPML_Media_Attachments_Duplication::class )->batch_translate_media( false )
);
}
}