d8e970ab by Jeff Balicki

stuff

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent bdf10794
Showing 143 changed files with 11354 additions and 5 deletions
<?php if ( ! defined( 'ABSPATH' ) ) {
exit;
} ?>
<div class="wrap dpp_page_settings">
<h1><?php _e( 'Plugin Settings', 'duplicate-wp-page-post' ) ?></h1>
<?php
$dpp_options = array();
$opt = get_option( 'dpp_wpp_page_options' );
$getinstruct = sanitize_text_field($_GET['instruct']);
$instruct = isset( $getinstruct ) ? $getinstruct : '';
if ( isset( $_POST['submit_dpp_wpp_page'] ) && wp_verify_nonce( $_POST['dpp_nonce_field'], 'dpp_page_action' ) ):
_e( "<strong>changes saving..</strong>", 'duplicate-wp-page-post' );
$dpp_nosave = array( 'submit_dpp_wpp_page' );
foreach ( $dpp_nosave as $noneed ):
unset( $_POST[ $noneed ] );
endforeach;
foreach ( $_POST as $key => $val ):
$dpp_options[ $key ] = sanitize_text_field( $val );
endforeach;
$dpp_settings_save = update_option( 'dpp_wpp_page_options', $dpp_options );
if ( $dpp_settings_save ) {
dpp_wpp_page::dp_redirect( 'options-general.php?page=dpp_page_settings&instruct=1' );
} else {
dpp_wpp_page::dp_redirect( 'options-general.php?page=dpp_page_settings&instruct=2' );
}endif;
if ( ! empty( $instruct ) && $instruct == 1 ):
_e( '<div id="message" class="updated notice notice-success is-dismissible">
<p>Changes Saved!</p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Ignore this notice.</span>
</button>
</div>', 'duplicate-wp-page-post' );
elseif ( ! empty( $instruct ) && $instruct == 2 ):
_e( '<div id="message" class="error notice notice-error is-dismissible">
<p>Changes not saved!</p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Ignore this notice.</span>
</button>
</div>', 'duplicate-wp-page-post' );
endif;
?>
<div id="dpp-stuff">
<div id="dpp-post-body" class="metabox-holder columns-2">
<div id="dpp-post-body-content" style="position: relative;">
<form style="padding: 10px; border: 1px solid #333;" action="" method="post" name="dpp_wpp_page_form">
<?php wp_nonce_field( 'dpp_page_action', 'dpp_nonce_field' ); ?>
<table class="form-table">
<tbody>
<tr>
<th scope="row"><label
for="dpp_posteditor">Select Editor<br><em>Default: Classic Editor</em></label>
</th>
<td>
<select id="dpp_posteditor" name="dpp_posteditor">
<option value="classic" <?php echo ( isset( $opt['dpp_posteditor'] ) && $opt['dpp_posteditor'] == 'classic' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Classic Editor', 'duplicate-wp-page-post' ); ?></option>
<option value="gutenberg" <?php echo ( isset( $opt['dpp_posteditor'] ) && $opt['dpp_posteditor'] == 'gutenberg' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Gutenberg Editor', 'duplicate-wp-page-post' ); ?></option>
</select>
<p>Please select which editor you are using.<br> If you are using Gutenberg, select
gutenberg editor otherwise it will not show Duplicate button on edit screen.</p>
</td>
</tr>
<tr>
<th scope="row"><label
for="dpp_post_status">Post Status<br><em>Default: Draft</em></label>
</th>
<td>
<select id="dpp_post_status" name="dpp_post_status">
<option value="draft" <?php echo ( $opt['dpp_post_status'] == 'draft' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Draft', 'duplicate-wp-page-post' ); ?></option>
<option value="publish" <?php echo ( $opt['dpp_post_status'] == 'publish' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Publish', 'duplicate-wp-page-post' ); ?></option>
<option value="private" <?php echo ( $opt['dpp_post_status'] == 'private' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Private', 'duplicate-wp-page-post' ); ?></option>
<option value="pending" <?php echo ( $opt['dpp_post_status'] == 'pending' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Pending', 'duplicate-wp-page-post' ); ?></option>
</select>
<p>Please select any post status you want to assign for duplicate post.</p>
</td>
</tr>
<tr>
<th scope="row"><label
for="dpp_post_redirect">Redirect<br><em>Default: To current list.</em><br>(After
click on <strong>Duplicate</strong></label>
</th>
<td>
<select id="dpp_post_redirect" name="dpp_post_redirect">
<option value="to_list" <?php echo ( $opt['dpp_post_redirect'] == 'to_list' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'All Post List', 'duplicate-wp-page-post' ); ?></option>
<option value="to_page" <?php echo ( $opt['dpp_post_redirect'] == 'to_page' ) ? "selected = 'selected'" : ''; ?>><?php _e( 'Direct Edit', 'duplicate-wp-page-post' ); ?></option>
</select>
<p>Please select any post redirection, redirect you to selected after click on
duplicate.</p>
</td>
</tr>
<tr>
<th scope="row"><label
for="dpp_post_suffix">Duplicate Post Suffix<br><em>Default: Empty</em></label>
</th>
<td>
<input type="text" class="regular-text"
value="<?php echo ! empty( $opt['dpp_post_suffix'] ) ? esc_attr( $opt['dpp_post_suffix'] ) : '' ?>"
id="dpp_post_suffix" name="dpp_post_suffix">
<p>Add a suffix for duplicate page and post. It will show after title.</p>
</td>
</tr>
<tr>
<th scope="row"><label
for="dpp_post_link_title">Duplicate Link Text<br><em>Default:
Duplicate</em></label>
</th>
<td>
<input type="text" class="regular-text"
value="<?php echo ! empty( $opt['dpp_post_link_title'] ) ? esc_attr( $opt['dpp_post_link_title'] ) : '' ?>"
id="dpp_post_link_title" name="dpp_post_link_title">
<p>It will show above text on duplicate page/post link button instead of default
(Duplicate)</p>
</td>
</tr>
</tbody>
</table>
<p class="submit"><input type="submit" value="Save Settings" class="button button-primary"
id="submit" name="submit_dpp_wpp_page"></p>
</form>
</div>
</div>
<div>
<h3><a href="https://wordpress.org/support/plugin/duplicate-wp-page-post/reviews/?filter=5#new-post">Please
review us</a> if you like the plugin.</h3>
</div>
</div>
</div>
\ No newline at end of file
<?php
/*
Plugin Name: Duplicate Page and Post
Plugin URI: https://wordpress.org/plugins/duplicate-wp-page-post/
Description: Quickly clone a page, post or custom post and supports Gutenberg.
Author: Arjun Thakur
Author URI: https://profiles.wordpress.org/arjunthakur#content-plugins
Version: 2.9.3
License: GPLv2 or later
Text Domain: dpp_wpp_page
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! defined( 'DPP_BASE_NAME' ) ) {
define( 'DPP_BASE_NAME', plugin_basename( __FILE__ ) );
}
if ( ! class_exists( 'dcc_dpp_wpp_page' ) ):
class dpp_wpp_page {
/*AutoLoad Hooks*/
public function __construct() {
$opt = get_option( 'dpp_wpp_page_options' );
register_activation_hook( __FILE__, array( &$this, 'dpp_wpp_page_install' ) );
add_action( 'admin_menu', array( &$this, 'dpp_page_options_page' ) );
add_filter( 'plugin_action_links', array( &$this, 'dpp_settings_link' ), 10, 2 );
add_action( 'admin_action_dt_dpp_post_as_draft', array( &$this, 'dt_dpp_post_as_draft' ) );
add_filter( 'post_row_actions', array( &$this, 'dt_dpp_post_link' ), 10, 2 );
add_filter( 'page_row_actions', array( &$this, 'dt_dpp_post_link' ), 10, 2 );
if ( isset( $opt['dpp_posteditor'] ) && $opt['dpp_posteditor'] == 'gutenberg' ) {
add_action( 'admin_head', array( &$this, 'dpp_wpp_button_guten' ) );
} else {
add_action( 'post_submitbox_misc_actions', array( &$this, 'dpp_wpp_page_custom_button' ) );
}
add_action( 'wp_before_admin_bar_render', array( &$this, 'dpp_wpp_page_admin_bar_link' ) );
}
/*Activation plugin Hook*/
public function dpp_wpp_page_install() {
$defaultsettings = array(
'dpp_post_status' => 'draft',
'dpp_post_redirect' => 'to_list',
'dpp_post_suffix' => '',
'dpp_posteditor' => 'classic',
'dpp_post_link_title' => '',
);
$opt = get_option( 'dpp_wpp_page_options' );
if ( ! $opt['dpp_post_status'] ) {
update_option( 'dpp_wpp_page_options', $defaultsettings );
}
}
/* Page Title and Dashboard Menu (Setting options) */
public function dpp_page_options_page() {
add_options_page( __( 'Duplicate Page and Post', 'dpp_wpp_page' ), __( 'Duplicate post', 'dpp_wpp_page' ), 'manage_options', 'dpp_page_settings', array(
&$this,
'dpp_page_settings'
) );
}
/*Include plugin setting file*/
public function dpp_page_settings() {
if ( current_user_can( 'manage_options' ) ) {
include( 'duplicate-wp-page-post-setting.php' );
}
}
/*Important function*/
public function dt_dpp_post_as_draft() {
$nonce = sanitize_text_field( $_REQUEST['nonce'] );
$getpost = sanitize_text_field( $_GET['post'] );
$post_id = ( isset( $getpost ) ? intval( $getpost ) : intval( $getpost ) );
if ( wp_verify_nonce( $nonce, 'dt-duplicate-page-' . $post_id ) && current_user_can( 'edit_posts' ) ) {
global $wpdb;
/*sanitize_GET POST REQUEST*/
//$post_copy = sanitize_text_field( $_POST["post"] );
//$get_copy = sanitize_text_field( $_GET['post'] );
$request_copy = sanitize_text_field( $_REQUEST['action'] );
$opt = get_option( 'dpp_wpp_page_options' );
$suffix = ! empty( $opt['dpp_post_suffix'] ) ? ' -- ' . esc_attr( $opt['dpp_post_suffix'] ) : '';
$post_status = ! empty( $opt['dpp_post_status'] ) ? esc_attr( $opt['dpp_post_status'] ) : 'draft';
$redirectit = ! empty( $opt['dpp_post_redirect'] ) ? esc_attr( $opt['dpp_post_redirect'] ) : 'to_list';
if ( ! ( isset( $getpost ) || isset( $getpost ) || ( isset( $request_copy ) && 'dt_dpp_post_as_draft' == $request_copy ) ) ) {
wp_die( 'No post!' );
}
$returnpage = '';
$post = get_post( $post_id );
$current_user = wp_get_current_user();
$new_post_author = $current_user->ID;
/*Create the post Copy */
if ( isset( $post ) && $post != null ) {
/* Post data array */
$args = array(
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_author' => $new_post_author,
'post_content' => ( isset( $opt['dpp_posteditor'] ) && $opt['dpp_posteditor'] == 'gutenberg' ) ? wp_slash( $post->post_content ) : $post->post_content,
'post_excerpt' => $post->post_excerpt,
//'post_name' => $post->post_name,
'post_parent' => $post->post_parent,
'post_password' => $post->post_password,
'post_status' => $post_status,
'post_title' => $post->post_title . $suffix,
'post_type' => $post->post_type,
'to_ping' => $post->to_ping,
'menu_order' => $post->menu_order
);
$new_post_id = wp_insert_post( $args );
$taxonomies = array_map( 'sanitize_text_field', get_object_taxonomies( $post->post_type ) );
if ( ! empty( $taxonomies ) && is_array( $taxonomies ) ):
foreach ( $taxonomies as $taxonomy ) {
$post_terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
wp_set_object_terms( $new_post_id, $post_terms, $taxonomy, false );
}
endif;
$post_meta_infos = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=%d", $post_id ) );
if ( count( $post_meta_infos ) != 0 ) {
$sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
foreach ( $post_meta_infos as $meta_info ) {
$meta_key = sanitize_text_field( $meta_info->meta_key );
$meta_value = addslashes( $meta_info->meta_value );
$sql_query_sel[] = "SELECT $new_post_id, '$meta_key', '$meta_value'";
}
$sql_query .= implode( " UNION ALL ", $sql_query_sel );
$wpdb->query( $sql_query );
}
/*choice redirect */
if ( $post->post_type != 'post' ):$returnpage = '?post_type=' . $post->post_type; endif;
if ( ! empty( $redirectit ) && $redirectit == 'to_list' ):esc_url_raw( wp_redirect( admin_url( 'edit.php' . $returnpage ) ) );
elseif ( ! empty( $redirectit ) && $redirectit == 'to_page' ):esc_url_raw( wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) ) );
else:
wp_redirect( esc_url_raw( admin_url( 'edit.php' . $returnpage ) ) );
endif;
exit;
} else {
wp_die( 'Error! Post creation failed: ' . $post_id );
}
} else {
wp_die( 'Security check issue, Please try again.' );
}
}
/*Add link to action*/
public function dt_dpp_post_link( $actions, $post ) {
$opt = get_option( 'dpp_wpp_page_options' );
$link_title = ! empty( $opt['dpp_post_link_title'] ) ? esc_attr( $opt['dpp_post_link_title'] ) : 'Duplicate';
$opt = get_option( 'dpp_wpp_page_options' );
$post_status = ! empty( $opt['dpp_post_status'] ) ? esc_attr( $opt['dpp_post_status'] ) : 'draft';
if ( current_user_can( 'edit_posts' ) ) {
$actions['dpp'] = '<a href="admin.php?action=dt_dpp_post_as_draft&amp;post=' . $post->ID . '&amp;nonce=' . wp_create_nonce( 'dt-duplicate-page-' . $post->ID ) . '" title="Clone this as ' . $post_status . '" rel="permalink">' . $link_title . '</a>';
}
return $actions;
}
/*Add link to edit Post*/
public function dpp_wpp_page_custom_button() {
$opt = get_option( 'dpp_wpp_page_options' );
$link_title = ! empty( $opt['dpp_post_link_title'] ) ? esc_attr( $opt['dpp_post_link_title'] ) : 'Duplicate';
global $post;
$opt = get_option( 'dpp_wpp_page_options' );
$post_status = ! empty( $opt['duplicate_post_status'] ) ? esc_attr( $opt['duplicate_post_status'] ) : 'draft';
$html = '<div id="major-publishing-actions">';
$html .= '<div id="export-action">';
$html .= '<a href="admin.php?action=dt_dpp_post_as_draft&amp;post=' . $post->ID . '&amp;nonce=' . wp_create_nonce( 'dt-duplicate-page-' . $post->ID ) . '" title="Duplicate this as ' . $post_status . '" rel="permalink">' . $link_title . '</a>';
$html .= '</div>';
$html .= '</div>';
echo $html;
}
/*
* Add the duplicate link to edit screen - gutenberg
*/
public function dpp_wpp_button_guten() {
global $post;
if ( $post ) {
$opt = get_option( 'dpp_wpp_page_options' );
$post_status = ! empty( $opt['dpp_post_status'] ) ? esc_attr( $opt['dpp_post_status'] ) : 'draft';
if ( isset( $opt['dpp_posteditor'] ) && $opt['dpp_posteditor'] == 'gutenberg' ) {
?>
<style> .link_gutenberg {
text-align: center;
margin-top: 15px;
}
.link_gutenberg a {
text-decoration: none;
display: block;
height: 40px;
line-height: 28px;
padding: 3px 12px 2px;
background: #0073AA;
border-radius: 3px;
border-width: 1px;
border-style: solid;
color: #ffffff;
font-size: 16px;
}
.link_gutenberg a:hover {
background: #23282D;
border-color: #23282D;
}</style>
<script>jQuery(window).load(function (e) {
var dpp_postid = "<?php echo esc_attr( $post->ID ); ?>";
var dtnonce = "<?php echo wp_create_nonce( 'dt-duplicate-page-' . $post->ID );?>";
var dpp_posttitle = "Duplicate this as <?php echo esc_attr( $post_status ); ?>";
var dpp_duplicatelink = '<div class="link_gutenberg">';
dpp_duplicatelink += '<a href="admin.php?action=dt_dpp_post_as_draft&amp;post=' + dpp_postid + '&amp;nonce=' + dtnonce + '" title="' + dpp_posttitle + '">Duplicate</a>';
dpp_duplicatelink += '</div>';
jQuery('.edit-post-post-status').append(dpp_duplicatelink);
});</script>
<?php
}
}
}
/*Click here to clone Admin Bar*/
public function dpp_wpp_page_admin_bar_link() {
global $wp_admin_bar;
global $post;
$opt = get_option( 'dpp_wpp_page_options' );
$post_status = ! empty( $opt['dpp_post_status'] ) ? esc_attr( $opt['dpp_post_status'] ) : 'draft';
$current_object = get_queried_object();
if ( empty( $current_object ) ) {
return;
}
if ( ! empty( $current_object->post_type ) && ( $post_type_object = get_post_type_object( $current_object->post_type ) ) && ( $post_type_object->show_ui || $current_object->post_type == 'attachment' ) ) {
$wp_admin_bar->add_menu( array(
'parent' => 'edit',
'id' => 'dpp_this',
'title' => __( "Clone this as " . $post_status . "", 'duplicate-wp-page-post' ),
'href' => admin_url() . 'admin.php?action=dt_dpp_post_as_draft&amp;post=' . $post->ID . '&amp;nonce=' . wp_create_nonce( 'dt-duplicate-page-' . $post->ID )
) );
}
}
/*WP Url Redirect*/
static function dp_redirect( $url ) {
$result = '<script>window.location.href="' . $url . '"</script>';
print( $result );
}
/*plugin settings page link*/
function dpp_settings_link( $links, $file ) {
if ( $file == DPP_BASE_NAME ) {
$links[] = '<a href="' .
admin_url( 'options-general.php?page=dpp_page_settings' ) .
'">' . __( 'Settings' ) . '</a>';
}
return $links;
}
}
new dpp_wpp_page();
endif;
?>
\ No newline at end of file
=== Duplicate Page and Post ===
Contributors: arjunthakur, efficientninja
Tags: duplicate post, duplicate page, clone page, clone post, duplicate custom posts, clone custom post, wordpress page duplicator, wordpress post duplicator, page duplicate, clone page and post, wp post clone.
Requires at least: 3.5
Tested up to: 6.2
Requires PHP: 5.2.4
Stable tag: 2.9.3
Version: 2.9.3
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Duplicate post, Duplicate page and Duplicate custom post or clone page and clone post.
== Description ==
Duplicate page and post plugin provides functionality to create a clone of page or posts. You can duplicate pages, posts and custom post by single click and it will be saved as draft.
Duplicate page and post doesn't have a lot of features that other plugins have, but it also is lightning fast by comparison.
= Major features of this plugin include =
* Create a clone of particular page.
* Create a clone of particular post.
* Create a clone of particular custom post(CPT).
* Option to select editor (Classic and Gutenberg)
* Option to add Post Suffix.
* Option to add custom text for duplicate link button.
* Option to select Duplicate Posts Status.
* Option to Redirect after click on Duplicate.
= Like the plugin? =
<a href="https://wordpress.org/support/plugin/duplicate-wp-page-post/reviews/?rate=5#new-post">Please Vote</a>, Your votes really make a difference! Thanks.
== Installation ==
The plugin is simple to install:
* Download duplicate-wp-page-post.zip
* Unzip
* Upload duplicate-wp-page-post directory to your /wp-content/plugins directory
* Go to the plugin menu page and activate the plugin
== Frequently asked questions ==
= How to create the duplicate of a page or a post? =
1. Activate the plugin through the 'Plugins' menu in WordPress.
2. Then Create New Post/Page Or you can use old one.
3. Now go to all pages or all posts page on your dashboard.
4. Hover your cursor over any page or any post on dashboard section, you'll see a "Click here to clone" Button.
5. After you click on "Duplicate" link, then duplicate post/page will be created and saved as draft, make the changes you wish and hit publish.
= What is the benefit of using this plugin? =
User can easily duplicate the posts, pages or the custom posts with single click. It saves user's time to re-create the same post or page again.
== Screenshots ==
1. screenshot1.png
2. screenshot2.png
3. screenshot3.png
4. screenshot4.png
\ No newline at end of file
<?php
namespace WPML\Media\Widgets\Block;
use WPML\Element\API\Languages;
use WPML\LIB\WP\Hooks;
use function WPML\FP\spreadArgs;
class DisplayTranslation implements \IWPML_Frontend_Action, \IWPML_DIC_Action {
/**
* @var \WPML_Media_Translated_Images_Update $translatedImageUpdate
*/
private $translatedImageUpdate;
public function __construct( \WPML_Media_Translated_Images_Update $translatedImageUpdate ) {
$this->translatedImageUpdate = $translatedImageUpdate;
}
public function add_hooks() {
Hooks::onFilter( 'widget_block_content' )
->then( spreadArgs( function ( $content ) {
return $this->translatedImageUpdate->replace_images_with_translations( $content, Languages::getCurrentCode() );
} ) );
}
}
<?php
/**
* Class WPML_Media_Batch_Url_Translation
*/
abstract class WPML_Media_Batch_Url_Translation {
const BATCH_SIZE = 10;
const BATCH_SIZE_FACTOR_ALL_MEDIA = 1;
const BATCH_SIZE_FACTOR_SPECIFIC_MEDIA = 10;
/**
* @var wpdb
*/
protected $wpdb;
/**
* WPML_Media_Batch_Url_Translation constructor.
*
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function add_hooks() {
add_action( 'wp_ajax_' . $this->get_ajax_action(), array( $this, 'run_batch' ) );
}
public function run_batch() {
$offset = isset( $_POST['offset'] ) ? (int) $_POST['offset'] : 0;
$attachment_id = isset( $_POST['attachment_id'] ) ? (int) $_POST['attachment_id'] : 0;
$all_media = ! empty( $_POST['global'] );
if ( $all_media ) {
$number_of_elements_left = $this->process_batch( $offset );
} else {
$number_of_elements_left = $this->process_batch_for_selected_media( $offset, $attachment_id );
}
$batch_size_factor = $all_media ? self::BATCH_SIZE_FACTOR_ALL_MEDIA : self::BATCH_SIZE_FACTOR_SPECIFIC_MEDIA;
$response = array(
'offset' => $offset + $this->get_batch_size( $batch_size_factor ),
'continue' => (int) ( $number_of_elements_left > 0 ),
'message' => $this->get_response_message( $number_of_elements_left ),
);
wp_send_json_success( $response );
}
/**
* @param int $number_of_elements_left
*
* @return string
*/
abstract protected function get_response_message( $number_of_elements_left );
/**
* @param int $offset
*
* @return int
*/
abstract protected function process_batch( $offset );
/**
* @param int $offset
* @param int $attachment_id
*
* @return int
*/
abstract protected function process_batch_for_selected_media( $offset, $attachment_id );
/**
* @return array
*/
abstract protected function get_ajax_error_message();
/**
* @param int $batch_size_factor
*
* @return int
*/
protected function get_batch_size( $batch_size_factor = self::BATCH_SIZE_FACTOR_ALL_MEDIA ) {
return $batch_size_factor * self::BATCH_SIZE;
}
/**
* @return string
*/
abstract protected function get_ajax_action();
}
<?php
/**
* Class WPML_Media_Custom_Field_Batch_Url_Translation_Factory
*/
class WPML_Media_Custom_Field_Batch_Url_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb, $sitepress;
if ( WPML_Media_Custom_Field_Batch_Url_Translation::is_ajax_request() ) {
$translatable_custom_fields = $sitepress->get_custom_fields_translation_settings(
$sitepress->get_wp_api()->constant( 'WPML_TRANSLATE_CUSTOM_FIELD' )
);
$custom_field_images_translation_factory = new WPML_Media_Custom_Field_Images_Translation_Factory();
return new WPML_Media_Custom_Field_Batch_Url_Translation(
$custom_field_images_translation_factory->create(),
$wpdb,
$translatable_custom_fields
);
}
return null;
}
}
<?php
/**
* Class WPML_Media_Custom_Field_Batch_Url_Translation
*/
class WPML_Media_Custom_Field_Batch_Url_Translation extends WPML_Media_Batch_Url_Translation implements IWPML_Action {
const AJAX_ACTION = 'wpml_media_translate_media_url_in_custom_fields';
/**
* @var WPML_Media_Custom_Field_Images_Translation
*/
private $custom_field_translation;
/**
* @var array
*/
private $translatable_custom_fields;
/**
* WPML_Media_Custom_Field_Batch_Url_Translation constructor.
*
* @param WPML_Media_Custom_Field_Images_Translation $custom_field_translation
* @param wpdb $wpdb
* @param array $translatable_custom_fields
*/
public function __construct(
WPML_Media_Custom_Field_Images_Translation $custom_field_translation,
wpdb $wpdb,
array $translatable_custom_fields
) {
parent::__construct( $wpdb );
$this->custom_field_translation = $custom_field_translation;
$this->translatable_custom_fields = $translatable_custom_fields;
}
/**
* @return string
*/
protected function get_ajax_action() {
return self::AJAX_ACTION;
}
public static function is_ajax_request() {
return isset( $_POST['action'] ) && self::AJAX_ACTION === $_POST['action'];
}
/**
* @param int $number_of_custom_fields_left
*
* @return string
*/
protected function get_response_message( $number_of_custom_fields_left ) {
return sprintf(
__( 'Translating media urls in custom field translations: %s', 'wpml-media' ),
$number_of_custom_fields_left > 0 ?
sprintf( __( '%d left', 'wpml-media' ), $number_of_custom_fields_left ) :
__( 'done!', 'wpml-media' )
);
}
protected function get_ajax_error_message() {
return array(
'key' => 'wpml_media_batch_urls_update_error_custom_fields',
'value' => esc_js( __( 'Translating media urls in custom fields translations failed: Please try again (%s)', 'wpml-media' ) ),
);
}
protected function process_batch( $offset ) {
if ( $this->translatable_custom_fields ) {
$translatable_custom_fields_where_in = wpml_prepare_in( $this->translatable_custom_fields );
$custom_fields = $this->wpdb->get_results(
"
SELECT SQL_CALC_FOUND_ROWS t.element_id AS post_id, p.meta_id, p.meta_key, p.meta_value
FROM {$this->wpdb->prefix}icl_translations t
JOIN {$this->wpdb->prefix}postmeta p ON t.element_id = p.post_id
WHERE t.element_type LIKE 'post_%'
AND t.element_type <> 'post_attachment'
AND t.source_language_code IS NULL
AND p.meta_key IN ({$translatable_custom_fields_where_in})
ORDER BY t.element_id ASC
LIMIT {$offset}, " . self::BATCH_SIZE
);
$number_of_all_custom_fields = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' );
foreach ( $custom_fields as $custom_field ) {
$this->custom_field_translation->translate_images(
$custom_field->meta_id,
$custom_field->post_id,
$custom_field->meta_key,
$custom_field->meta_value
);
}
} else {
$number_of_all_custom_fields = 0;
}
return $number_of_all_custom_fields - $offset - self::BATCH_SIZE;
}
protected function process_batch_for_selected_media( $offset, $attachment_id ) {
$media_url = wpml_like_escape( wp_get_attachment_url( $attachment_id ) );
if ( ! $media_url ) {
return 0;
}
preg_match( '/(.+)\.([a-z]+)$/', $media_url, $match );
$media_url_no_extension = wpml_like_escape( $match[1] );
$extension = wpml_like_escape( $match[2] );
$batch_size = $this->get_batch_size( parent::BATCH_SIZE_FACTOR_SPECIFIC_MEDIA );
if ( $this->translatable_custom_fields ) {
$translatable_custom_fields_where_in = wpml_prepare_in( $this->translatable_custom_fields );
$custom_fields = $this->wpdb->get_results(
"
SELECT SQL_CALC_FOUND_ROWS t.element_id AS post_id, p.meta_id, p.meta_key, p.meta_value
FROM {$this->wpdb->prefix}icl_translations t
JOIN {$this->wpdb->prefix}postmeta p ON t.element_id = p.post_id
WHERE t.element_type LIKE 'post_%'
AND t.element_type <> 'post_attachment'
AND t.source_language_code IS NULL
AND p.meta_key IN ({$translatable_custom_fields_where_in})
AND (
p.meta_value LIKE '%{$media_url}%' OR
p.meta_value LIKE '%{$media_url_no_extension}-%x%.{$extension}%'
)
ORDER BY t.element_id ASC
LIMIT {$offset}, " . $batch_size
);
$number_of_all_custom_fields = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' );
foreach ( $custom_fields as $custom_field ) {
$this->custom_field_translation->translate_images(
$custom_field->meta_id,
$custom_field->post_id,
$custom_field->meta_key,
$custom_field->meta_value
);
}
} else {
$number_of_all_custom_fields = 0;
}
return $number_of_all_custom_fields - $offset - $batch_size;
}
}
<?php
/**
* Class WPML_Media_Post_Batch_Url_Translation_Factory
*/
class WPML_Media_Post_Batch_Url_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb;
if ( WPML_Media_Post_Batch_Url_Translation::is_ajax_request() ) {
$post_images_translation_factory = new WPML_Media_Post_Images_Translation_Factory();
return new WPML_Media_Post_Batch_Url_Translation( $post_images_translation_factory->create(), $wpdb );
}
return null;
}
}
\ No newline at end of file
<?php
/**
* Class WPML_Media_Post_Batch_Url_Translation
*/
class WPML_Media_Post_Batch_Url_Translation extends WPML_Media_Batch_Url_Translation implements IWPML_Action {
const AJAX_ACTION = 'wpml_media_translate_media_url_in_posts';
/**
* @var WPML_Media_Post_Images_Translation
*/
private $post_image_translation;
/**
* WPML_Media_Post_Batch_Url_Translation constructor.
*
* @param WPML_Media_Post_Images_Translation $post_image_translation
* @param wpdb $wpdb
*/
public function __construct( WPML_Media_Post_Images_Translation $post_image_translation, wpdb $wpdb ) {
parent::__construct( $wpdb );
$this->post_image_translation = $post_image_translation;
$this->wpdb = $wpdb;
}
/**
* @return string
*/
protected function get_ajax_action() {
return self::AJAX_ACTION;
}
public static function is_ajax_request() {
return isset( $_POST['action'] ) && self::AJAX_ACTION === $_POST['action'];
}
/**
* @param int $number_of_posts_left
*
* @return string
*/
protected function get_response_message( $number_of_posts_left ) {
return sprintf(
__( 'Translating media urls in post translations: %s', 'wpml-media' ),
$number_of_posts_left > 0 ?
sprintf( __( '%d left', 'wpml-media' ), $number_of_posts_left ) :
__( 'done!', 'wpml-media' )
);
}
protected function get_ajax_error_message() {
return array(
'key' => 'wpml_media_batch_urls_update_errors_posts',
'value' => esc_js( __( 'Translating media urls in posts translations failed: Please try again (%s)', 'wpml-media' ) )
);
}
/**
* @param int $offset
*
* @return int
*/
protected function process_batch( $offset ) {
$posts = $this->wpdb->get_col( "
SELECT SQL_CALC_FOUND_ROWS element_id AS id
FROM {$this->wpdb->prefix}icl_translations
WHERE element_type LIKE 'post_%'
AND element_type <> 'post_attachment'
AND source_language_code IS NULL
ORDER BY element_id ASC
LIMIT {$offset}, " . self::BATCH_SIZE );
$number_of_all_posts = (int) $this->wpdb->get_var( "SELECT FOUND_ROWS()" );
foreach ( $posts as $post_id ) {
$this->post_image_translation->translate_images( $post_id );
}
return $number_of_all_posts - $offset - self::BATCH_SIZE;
}
protected function process_batch_for_selected_media( $offset, $attachment_id ) {
$media_url = wpml_like_escape( wp_get_attachment_url( $attachment_id ) );
if ( ! $media_url ) {
return 0;
}
preg_match( "/(.+)\.([a-z]+)$/", $media_url, $match );
$media_url_no_extension = wpml_like_escape( $match[1] );
$extension = wpml_like_escape( $match[2] );
$batch_size = $this->get_batch_size( parent::BATCH_SIZE_FACTOR_SPECIFIC_MEDIA );
$posts = $this->wpdb->get_col( "
SELECT SQL_CALC_FOUND_ROWS element_id AS id
FROM {$this->wpdb->prefix}icl_translations t
JOIN {$this->wpdb->posts} p ON t.element_id = p.ID
WHERE element_type LIKE 'post_%'
AND element_type <> 'post_attachment'
AND source_language_code IS NULL
AND (
post_content LIKE '%{$media_url}%' OR
post_content LIKE '%{$media_url_no_extension}-%x%.{$extension}%'
)
ORDER BY element_id ASC
LIMIT {$offset}, " . $batch_size );
$number_of_all_posts = (int) $this->wpdb->get_var( "SELECT FOUND_ROWS()" );
foreach ( $posts as $post_id ) {
$this->post_image_translation->translate_images( $post_id );
}
return $number_of_all_posts - $offset - $batch_size;
}
}
\ No newline at end of file
<?php
/**
* Class WPML_Media_String_Batch_Url_Translation
*/
class WPML_Media_String_Batch_Url_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb;
if ( WPML_Media_String_Batch_Url_Translation::is_ajax_request() ) {
$string_factory = new WPML_ST_String_Factory( $wpdb );
return new WPML_Media_String_Batch_Url_Translation( $wpdb, $string_factory );
}
return null;
}
}
<?php
/**
* Class WPML_Media_String_Batch_Url_Translation
*/
class WPML_Media_String_Batch_Url_Translation extends WPML_Media_Batch_Url_Translation implements IWPML_Action {
const BATCH_SIZE = 500;
const AJAX_ACTION = 'wpml_media_translate_media_url_in_strings';
/**
* @var WPML_ST_String_Factory
*/
private $string_factory;
/**
* WPML_Media_String_Batch_Url_Translation constructor.
*
* @param wpdb $wpdb
* @param WPML_ST_String_Factory $string_factory
*/
public function __construct(
wpdb $wpdb,
WPML_ST_String_Factory $string_factory
) {
parent::__construct( $wpdb );
$this->string_factory = $string_factory;
}
/**
* @param int $batch_size_factor
*
* @return int
*/
protected function get_batch_size( $batch_size_factor = self::BATCH_SIZE_FACTOR_ALL_MEDIA ) {
return $batch_size_factor * self::BATCH_SIZE;
}
/**
* @return string
*/
protected function get_ajax_action() {
return self::AJAX_ACTION;
}
public static function is_ajax_request() {
return isset( $_POST['action'] ) && self::AJAX_ACTION === $_POST['action'];
}
/**
* @param int $number_of_strings_left
*
* @return string
*/
protected function get_response_message( $number_of_strings_left ) {
return sprintf(
__( 'Translating media urls in string translations: %s', 'wpml-media' ),
$number_of_strings_left > 0 ?
sprintf( __( '%d left', 'wpml-media' ), $number_of_strings_left ) :
__( 'done!', 'wpml-media' )
);
}
protected function get_ajax_error_message() {
return array(
'key' => 'wpml_media_batch_urls_update_error_strings',
'value' => esc_js( __( 'Translating media urls in string translations failed: Please try again (%s)', 'wpml-media' ) ),
);
}
/**
* @param int $offset
*
* @return int
*/
protected function process_batch( $offset ) {
$original_strings = $this->wpdb->get_col(
"
SELECT SQL_CALC_FOUND_ROWS id, language
FROM {$this->wpdb->prefix}icl_strings
ORDER BY id ASC
LIMIT {$offset}, " . self::BATCH_SIZE
);
$number_of_all_strings = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' );
foreach ( $original_strings as $string_id ) {
$string = $this->string_factory->find_by_id( $string_id );
$string_translations = $string->get_translations();
foreach ( $string_translations as $string_translation ) {
if ( $string_translation->value ) {
$string->set_translation( $string_translation->language, $string_translation->value );
}
}
}
return $number_of_all_strings - $offset - self::BATCH_SIZE;
}
protected function process_batch_for_selected_media( $offset, $attachment_id ) {
$media_url = wpml_like_escape( wp_get_attachment_url( $attachment_id ) );
if ( ! $media_url ) {
return 0;
}
preg_match( '/(.+)\.([a-z]+)$/', $media_url, $match );
$media_url_no_extension = wpml_like_escape( $match[1] );
$extension = wpml_like_escape( $match[2] );
$batch_size = $this->get_batch_size( parent::BATCH_SIZE_FACTOR_SPECIFIC_MEDIA );
$original_strings = $this->wpdb->get_col(
"
SELECT SQL_CALC_FOUND_ROWS id, language
FROM {$this->wpdb->prefix}icl_strings
WHERE (
value LIKE '%{$media_url}%' OR
value LIKE '%{$media_url_no_extension}-%x%.{$extension}%'
)
ORDER BY id ASC
LIMIT {$offset}, " . $batch_size
);
$number_of_all_strings = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' );
foreach ( $original_strings as $string_id ) {
$string = $this->string_factory->find_by_id( $string_id );
$string_translations = $string->get_translations();
foreach ( $string_translations as $string_translation ) {
if ( $string_translation->value ) {
$string->set_translation( $string_translation->language, $string_translation->value );
}
}
}
return $number_of_all_strings - $offset - $batch_size;
}
}
<?php
class WPML_Media_Attachment_By_URL_Factory {
public function create( $url, $language, \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query $media_attachment_by_url_query ) {
global $wpdb;
return new WPML_Media_Attachment_By_URL( $wpdb, $url, $language, $media_attachment_by_url_query );
}
}
<?php
namespace WPML\Media\Factories;
class WPML_Media_Attachment_By_URL_Query_Factory {
public function create() {
global $wpdb;
return new \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query( $wpdb );
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Obj;
class WPML_Media_Attachment_By_URL_Query {
/**
* @var wpdb
*/
private $wpdb;
/**
* @var array
*/
private $id_from_guid_cache = [];
/**
* @var array
*/
private $id_from_meta_cache = [];
/**
* @var boolean Used in tests
*/
private $was_last_fetch_from_cache = false;
/**
* \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query constructor.
*
* @param \wpdb $wpdb
*/
public function __construct( \wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
/**
* @return boolean
*/
public function getWasLastFetchFromCache() {
return $this->was_last_fetch_from_cache;
}
/**
* Sometimes multiple rows are returned for one language(language_code field)/url(guid field) or language(language_code field)/relativePath(meta_value field) pair.
* We should set only first result in such cases same as with original get_var call, otherwise code with cache will not work in the same way as the original code.
* Example: [[post_id = 1, lang = en, url = otgs.com], [post_id = 2, lang = en, url = otgs.com]] => only first entry should be set to cache, second should be ignored.
*
* @param array $item
* @param string $cache_prop
* @param string $item_index_in_cache
*/
private function setItemToCache( $item, $cache_prop, $item_index_in_cache ) {
if ( array_key_exists( $item_index_in_cache, $this->$cache_prop ) ) {
return;
}
$this->{$cache_prop}[$item_index_in_cache] = $item;
}
/**
* @param array $source_items
*/
private function filterItems( $source_items ) {
return array_values( array_filter( array_unique( $source_items ) ) );
}
/**
* @param string $language
* @param array $urls
*/
public function prefetchAllIdsFromGuids( $language, $urls ) {
$urls = $this->filterItems( $urls );
$urls = array_filter( $urls, function( $url ) use ( $language ) {
$index = md5( $language . $url );
return ! array_key_exists( $index, $this->id_from_guid_cache );
} );
if ( 0 === count( $urls ) ) {
return;
}
$sql = '';
$sql .= "SELECT p.ID AS post_id, p.guid, t.language_code FROM {$this->wpdb->posts} p ";
$sql .= "JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID ";
$sql .= "WHERE t.element_type='post_attachment' AND t.language_code=%s ";
$sql .= 'AND p.guid IN (' . wpml_prepare_in( $urls ) . ')';
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
$results = $this->wpdb->get_results( $this->wpdb->prepare( $sql, $language ), ARRAY_A );
foreach ( $results as $result ) {
$index = md5( $result['language_code'] . $result['guid'] );
$this->setItemToCache( $result, 'id_from_guid_cache', $index );
}
// We should put not found values into the cache too, otherwise they will be still queried later.
$urls_count = count( $urls );
for ( $i = 0; $i < $urls_count; $i++ ) {
$index = md5( $language . $urls[ $i ] );
$this->setItemToCache( null, 'id_from_guid_cache', $index );
}
}
/**
* @param string $language
* @param string $url
*/
public function getIdFromGuid( $language, $url ) {
$this->was_last_fetch_from_cache = false;
$index = md5( $language . $url );
if ( array_key_exists( $index, $this->id_from_guid_cache ) ) {
$this->was_last_fetch_from_cache = true;
return ( $this->id_from_guid_cache[ $index ] ) ? $this->id_from_guid_cache[ $index ]['post_id'] : null;
}
$attachment_id = $this->wpdb->get_var(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
$this->wpdb->prepare(
"
SELECT ID FROM {$this->wpdb->posts} p
JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID
WHERE t.element_type='post_attachment' AND t.language_code=%s AND p.guid=%s
",
$language,
$url
)
);
return $attachment_id;
}
/**
* @param string $language
* @param array $pathes
*/
public function prefetchAllIdsFromMetas( $language, $pathes ) {
$pathes = $this->filterItems( $pathes );
$pathes = array_filter( $pathes, function( $path ) use ( $language ) {
$index = md5( $language . $path );
return ! array_key_exists( $index, $this->id_from_meta_cache );
} );
if ( 0 === count( $pathes ) ) {
return;
}
$sql = '';
$sql .= "SELECT p.post_id, t.language_code, p.meta_value FROM {$this->wpdb->postmeta} p ";
$sql .= "JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.post_id ";
$sql .= "WHERE p.meta_key='_wp_attached_file' AND t.element_type='post_attachment' AND t.language_code=%s ";
$sql .= 'AND p.meta_value IN (' . wpml_prepare_in( $pathes ) . ')';
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
$results = $this->wpdb->get_results( $this->wpdb->prepare( $sql, $language ), ARRAY_A );
foreach ( $results as $result ) {
$index = md5( $result['language_code'] . $result['meta_value'] );
$this->setItemToCache( $result, 'id_from_meta_cache', $index );
}
// We should put not found values into the cache too, otherwise they will be still queried later.
$pathes_count = count( $pathes );
for ( $i = 0; $i < $pathes_count; $i++ ) {
$index = md5( $language . $pathes[ $i ] );
$this->setItemToCache( null, 'id_from_meta_cache', $index );
}
}
/**
* @param string $relative_path
* @param string $language
*/
public function getIdFromMeta( $relative_path, $language ) {
$this->was_last_fetch_from_cache = false;
$index = md5( $language . $relative_path );
if ( array_key_exists( $index, $this->id_from_meta_cache ) ) {
$this->was_last_fetch_from_cache = true;
return ( $this->id_from_meta_cache[ $index ] ) ? $this->id_from_meta_cache[ $index ]['post_id'] : null;
}
$attachment_id = $this->wpdb->get_var(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
$this->wpdb->prepare(
"
SELECT post_id
FROM {$this->wpdb->postmeta} p
JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.post_id
WHERE p.meta_key='_wp_attached_file' AND p.meta_value=%s
AND t.element_type='post_attachment' AND t.language_code=%s
",
$relative_path,
$language
)
);
return $attachment_id;
}
}
<?php
class WPML_Media_Attachment_By_URL {
/**
* @var wpdb
*/
private $wpdb;
/**
* @var string
*/
private $url;
/**
* @var string
*/
private $language;
/**
* @var \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query
*/
private $media_attachment_by_url_query;
const SIZE_SUFFIX_REGEXP = '/-([0-9]+)x([0-9]+)\.([a-z]{3,4})$/';
const CACHE_KEY_PREFIX = 'attachment-id-from-guid-';
const CACHE_GROUP = 'wpml-media-setup';
const CACHE_EXPIRATION = 1800;
/** @var null|boolean */
public $cache_hit_flag = null;
/**
* WPML_Media_Attachment_By_URL constructor.
*
* @param wpdb $wpdb
* @param string $url
* @param string $language
* @param \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query $media_attachment_by_url_query
*/
public function __construct(
wpdb $wpdb,
$url,
$language,
\WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query $media_attachment_by_url_query
) {
$this->url = $url;
$this->language = $language;
$this->wpdb = $wpdb;
$this->media_attachment_by_url_query = $media_attachment_by_url_query;
}
/**
* @param string $url
*
* @return string
*/
public static function getUrl( $url ) {
$url = preg_replace( self::SIZE_SUFFIX_REGEXP, '.$3', $url );
return $url;
}
/**
* @param string $url
*
* @return string
*/
public static function getUrlNotScaled( $url ) {
$url = preg_replace( self::SIZE_SUFFIX_REGEXP, '.$3', $url );
$url = str_replace( '-scaled', '', $url );
return $url;
}
/**
* @param string $url
*
* @return string
*/
public static function getUrlRelativePath( $url ) {
$uploads_dir = wp_get_upload_dir();
$relative_path = ltrim( preg_replace( '@^' . $uploads_dir['baseurl'] . '@', '', $url ), '/' );
return $relative_path;
}
/**
* @param string $relative_path
*
* @return string
*/
public static function getUrlRelativePathOriginal( $relative_path ) {
return preg_replace( self::SIZE_SUFFIX_REGEXP, '.$3', $relative_path );
}
/**
* @param string $url
*
* @return string
*/
public static function getUrlRelativePathScaled( $url ) {
$relative_path = self::getUrlRelativePath( $url );
$relative_path = str_replace( '-scaled', '', $relative_path );
$relative_path = preg_replace( '/(\.[^.]+)$/', '-scaled$1', $relative_path );
return $relative_path;
}
public function get_id() {
if ( ! $this->url ) {
return 0;
}
$cache_key = self::CACHE_KEY_PREFIX . md5( $this->language . '#' . $this->url );
$attachment_id = wp_cache_get( $cache_key, self::CACHE_GROUP, false, $this->cache_hit_flag );
if ( ! $this->cache_hit_flag ) {
$attachment_id = $this->get_id_from_guid();
if ( ! $attachment_id ) {
$attachment_id = $this->get_id_from_meta();
}
wp_cache_add( $cache_key, $attachment_id, self::CACHE_GROUP, self::CACHE_EXPIRATION );
}
return $attachment_id;
}
private function get_id_from_guid() {
$attachment_id = $this->media_attachment_by_url_query->getIdFromGuid( $this->language, $this->url );
if ( ! $attachment_id ) {
$attachment_id = $this->media_attachment_by_url_query->getIdFromGuid( $this->language, self::getUrlNotScaled( $this->url ) );
}
return $attachment_id;
}
private function get_id_from_meta() {
$relative_path = self::getUrlRelativePath( $this->url );
$relative_path_scaled = self::getUrlRelativePathScaled( $this->url );
// Using _wp_attached_file.
$attachment_id = $this->media_attachment_by_url_query->getIdFromMeta( $relative_path, $this->language );
if ( ! $attachment_id ) {
$attachment_id = $this->media_attachment_by_url_query->getIdFromMeta( $relative_path_scaled, $this->language );
}
// Using attachment meta (fallback).
if ( ! $attachment_id && preg_match( self::SIZE_SUFFIX_REGEXP, $relative_path ) ) {
$attachment_id = $this->get_attachment_image_from_meta_fallback( $relative_path );
}
return $attachment_id;
}
private function get_attachment_image_from_meta_fallback( $relative_path ) {
$attachment_id = null;
$relative_path_original = self::getUrlRelativePathOriginal( $relative_path );
$attachment_id_original = $this->media_attachment_by_url_query->getIdFromMeta( $relative_path_original, $this->language );
// Validate size.
if ( $attachment_id_original ) {
$attachment_meta_data = wp_get_attachment_metadata( $attachment_id_original );
if ( $this->validate_image_size( $relative_path, $attachment_meta_data ) ) {
$attachment_id = $attachment_id_original;
}
}
return $attachment_id;
}
private function validate_image_size( $path, $attachment_meta_data ) {
$valid = false;
$file_name = basename( $path );
foreach ( $attachment_meta_data['sizes'] as $size ) {
if ( $file_name === $size['file'] ) {
$valid = true;
break;
}
}
return $valid;
}
}
<?php
/**
* Class WPML_Media_Attachments_Query_Factory
*/
class WPML_Media_Attachments_Query_Factory implements IWPML_Frontend_Action_Loader, IWPML_Backend_Action_Loader {
/**
* @return IWPML_Action|WPML_Media_Attachments_Query
*/
public function create() {
return new WPML_Media_Attachments_Query();
}
}
<?php
/**
* Class WPML_Media_Attachments_Query
*/
class WPML_Media_Attachments_Query implements IWPML_Action {
public function add_hooks() {
add_action( 'pre_get_posts', array( $this, 'adjust_attachment_query_action' ), 10 );
}
public function adjust_attachment_query_action( $query ) {
return $this->adjust_attachment_query( $query );
}
/**
* Set `suppress_filters` to false if attachment is displayed.
*
* @param WP_Query $query
*
* @return WP_Query
*/
public function adjust_attachment_query( $query ) {
if ( isset( $query->query['post_type'] ) && 'attachment' === $query->query['post_type'] ) {
$query->set( 'suppress_filters', false );
}
return $query;
}
}
<?php
/**
* Class WPML_Media_Factory
*/
class WPML_Media_Factory implements IWPML_Frontend_Action_Loader, IWPML_Backend_Action_Loader {
public function create() {
global $sitepress, $wpdb;
$wpml_wp_api = $sitepress->get_wp_api();
$template_service_loader = new WPML_Twig_Template_Loader(
array( $wpml_wp_api->constant( 'WPML_MEDIA_PATH' ) . '/templates/menus/' )
);
$wpml_media_menus_factory = new WPML_Media_Menus_Factory();
return new WPML_Media( $sitepress, $wpdb, $wpml_media_menus_factory );
}
}
<?php
/**
* Class WPML_Media_File_Factory
*/
class WPML_Media_File_Factory {
/**
* @param $attachment_id
*
* @return WPML_Media_File
*/
public function create( $attachment_id ) {
global $wpdb;
return new WPML_Media_File( $attachment_id, $this->get_wp_filesystem(), $wpdb );
}
private function get_wp_filesystem() {
global $wp_filesystem;
if ( null === $wp_filesystem ) {
WP_Filesystem();
}
return $wp_filesystem;
}
}
<?php
class WPML_Media_File {
/**
* @var int
*/
private $attachment_id;
/**
* @var WP_Filesystem_Base
*/
private $wp_filesystem;
/**
* @var wpdb
*/
private $wpdb;
public function __construct( $attachment_id, WP_Filesystem_Base $wp_filesystem, wpdb $wpdb ) {
$this->wp_filesystem = $wp_filesystem;
$this->attachment_id = $attachment_id;
$this->wpdb = $wpdb;
}
public function delete() {
$relative_file_path = get_post_meta( $this->attachment_id, '_wp_attached_file', true );
if ( $relative_file_path && ! $this->file_is_shared( $relative_file_path, $this->attachment_id ) ) {
$file_path = $this->get_full_file_upload_path( $relative_file_path );
$this->wp_filesystem->delete( $file_path, false, 'f' );
$attachment_meta_data = wp_get_attachment_metadata( $this->attachment_id );
if ( $attachment_meta_data && isset( $attachment_meta_data['file'] ) ) {
$subdir = dirname( $attachment_meta_data['file'] );
foreach ( $attachment_meta_data['sizes'] as $key => $size ) {
$file_path = $this->get_full_file_upload_path( $subdir . '/' . $size['file'] );
$this->wp_filesystem->delete( $file_path, false, 'f' );
}
}
}
}
private function get_full_file_upload_path( $relative_file_path ) {
$upload_dir = wp_upload_dir();
$relative_file_path = trim( $relative_file_path, ' /' );
$file_path = $upload_dir['basedir'] . '/' . $relative_file_path;
return $file_path;
}
private function file_is_shared( $relative_file_path, $attachment_id ) {
$sql = "SELECT post_id FROM {$this->wpdb->postmeta}
WHERE post_id <> %d AND meta_key='_wp_attached_file' AND meta_value=%s";
return $this->wpdb->get_var( $this->wpdb->prepare( $sql, $attachment_id, $relative_file_path ) );
}
}
<?php
/**
* Class WPML_Media
*/
class WPML_Media implements IWPML_Action {
const SETUP_RUN = 'setup_run';
const SETUP_STARTED = 'setup_started';
private static $settings;
private static $settings_option_key = '_wpml_media';
private static $default_settings = array(
'version' => false,
'media_files_localization' => array(
'posts' => true,
'custom_fields' => true,
'strings' => true,
),
'wpml_media_2_3_migration' => true,
self::SETUP_RUN => false,
);
public $languages;
public $parents;
public $unattached;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var WPML_Media_Menus_Factory
*/
private $menus_factory;
/**
* WPML_Media constructor.
*
* @param SitePress $sitepress
* @param wpdb $wpdb
* @param WPML_Media_Menus_Factory $menus_factory
*/
public function __construct( SitePress $sitepress, wpdb $wpdb, WPML_Media_Menus_Factory $menus_factory ) {
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->menus_factory = $menus_factory;
}
public function add_hooks() {
add_action( 'wpml_loaded', array( $this, 'loaded' ), 2 );
}
public static function has_settings() {
return get_option( self::$settings_option_key );
}
public function loaded() {
global $sitepress;
if ( ! isset( $sitepress ) || ! $sitepress->get_setting( 'setup_complete' ) ) {
return null;
}
$this->plugin_localization();
if ( is_admin() ) {
WPML_Media_Upgrade::run();
}
self::init_settings();
global $sitepress_settings, $pagenow;
$active_languages = $sitepress->get_active_languages();
$this->languages = null;
if ( $this->is_admin_or_xmlrpc() && ! $this->is_uploading_plugin_or_theme() ) {
add_action( 'wpml_admin_menu_configure', array( $this, 'menu' ) );
if ( 1 < count( $active_languages ) ) {
if ( $pagenow == 'media-upload.php' ) {
add_action( 'pre_get_posts', array( $this, 'filter_media_upload_items' ), 10, 1 );
}
if ( $pagenow == 'media.php' ) {
add_action( 'admin_footer', array( $this, 'media_language_options' ) );
}
add_action( 'wp_ajax_wpml_media_scan_prepare', array( $this, 'batch_scan_prepare' ) );
add_action( 'wp_ajax_find_posts', array( $this, 'find_posts_filter' ), 0 );
}
} else {
if ( WPML_LANGUAGE_NEGOTIATION_TYPE_DOMAIN === (int) $sitepress_settings['language_negotiation_type'] ) {
// Translate media url when in front-end and only when using custom domain
add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 10, 2 );
}
}
add_filter( 'WPML_filter_link', array( $this, 'filter_link' ), 10, 2 );
add_filter( 'icl_ls_languages', array( $this, 'icl_ls_languages' ), 10, 1 );
return null;
}
function is_admin_or_xmlrpc() {
$is_admin = is_admin();
$is_xmlrpc = ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST );
return $is_admin || $is_xmlrpc;
}
function is_uploading_plugin_or_theme() {
global $action;
return ( isset( $action ) && ( $action == 'upload-plugin' || $action == 'upload-theme' ) );
}
function plugin_localization() {
load_plugin_textdomain( 'wpml-media', false, WPML_MEDIA_FOLDER . '/locale' );
}
/**
* Needed by class init and by all static methods that use self::$settings
*/
public static function init_settings() {
if ( ! self::$settings ) {
self::$settings = get_option( self::$settings_option_key, array() );
}
self::$settings = array_merge( self::$default_settings, self::$settings );
}
public static function has_setup_run() {
return self::get_setting( self::SETUP_RUN );
}
public static function set_setup_run( $value = 1 ) {
return self::update_setting( self::SETUP_RUN, $value );
}
public static function has_setup_started() {
return self::get_setting( self::SETUP_STARTED );
}
public static function set_setup_started( $value = 1 ) {
return self::update_setting( self::SETUP_STARTED, $value );
}
public static function get_setting( $name, $default = false ) {
self::init_settings();
if ( ! isset( self::$settings[ $name ] ) || ! self::$settings[ $name ] ) {
return $default;
}
return self::$settings[ $name ];
}
public static function update_setting( $name, $value ) {
self::init_settings();
self::$settings[ $name ] = $value;
return update_option( self::$settings_option_key, self::$settings );
}
function batch_scan_prepare() {
global $wpdb;
$response = array();
$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => 'wpml_media_processed' ) );
$response['message'] = __( 'Started...', 'wpml-media' );
echo wp_json_encode( $response );
exit;
}
static function is_valid_post_type( $post_type ) {
global $wp_post_types;
$post_types = array_keys( (array) $wp_post_types );
return in_array( $post_type, $post_types );
}
function find_posts_filter() {
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
}
function pre_get_posts( $query ) {
$query->query['suppress_filters'] = 0;
$query->query_vars['suppress_filters'] = 0;
}
function media_language_options() {
global $sitepress;
$att_id = filter_input( INPUT_GET, 'attachment_id', FILTER_SANITIZE_NUMBER_INT, FILTER_NULL_ON_FAILURE );
$translations = $sitepress->get_element_translations( $att_id, 'post_attachment' );
$current_lang = '';
foreach ( $translations as $lang => $id ) {
if ( $id == $att_id ) {
$current_lang = $lang;
unset( $translations[ $lang ] );
break;
}
}
$active_languages = icl_get_languages( 'orderby=id&order=asc&skip_missing=0' );
$lang_links = '';
if ( $current_lang ) {
$lang_links = '<strong>' . $active_languages[ $current_lang ]['native_name'] . '</strong>';
}
foreach ( $translations as $lang => $id ) {
$lang_links .= ' | <a href="' . admin_url( 'media.php?attachment_id=' . $id . '&action=edit' ) . '">' . $active_languages[ $lang ]['native_name'] . '</a>';
}
echo '<div id="icl_lang_options" style="display:none">' . $lang_links . '</div>';
}
/**
* Synchronizes _wpml_media_* meta fields with all translations
*
* @param int $meta_id
* @param int $object_id
* @param string $meta_key
* @param string|mixed $meta_value
*/
function updated_postmeta( $meta_id, $object_id, $meta_key, $meta_value ) {
if ( in_array( $meta_key, array( '_wpml_media_duplicate', '_wpml_media_featured' ) ) ) {
global $sitepress;
$el_type = 'post_' . get_post_type( $object_id );
$trid = $sitepress->get_element_trid( $object_id, $el_type );
$translations = $sitepress->get_element_translations( $trid, $el_type, true, true );
foreach ( $translations as $translation ) {
if ( $translation->element_id != $object_id ) {
$t_meta_value = get_post_meta( $translation->element_id, $meta_key, true );
if ( $t_meta_value != $meta_value ) {
update_post_meta( $translation->element_id, $meta_key, $meta_value );
}
}
}
}
}
/**
* Add a filter to fix the links for attachments in the language switcher so
* they point to the corresponding pages in different languages.
*/
function filter_link( $url, $lang_info ) {
return $url;
}
function wp_get_attachment_url( $url, $post_id ) {
global $sitepress;
return $sitepress->convert_url( $url );
}
function icl_ls_languages( $w_active_languages ) {
static $doing_it = false;
if ( is_attachment() && ! $doing_it ) {
$doing_it = true;
// Always include missing languages.
$w_active_languages = icl_get_languages( 'skip_missing=0' );
$doing_it = false;
}
return $w_active_languages;
}
function get_post_metadata( $value, $object_id, $meta_key, $single ) {
if ( $meta_key == '_thumbnail_id' ) {
global $wpdb;
$thumbnail_prepared = $wpdb->prepare(
"SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = %s",
array(
$object_id,
$meta_key,
)
);
$thumbnail = $wpdb->get_var( $thumbnail_prepared );
if ( $thumbnail == null ) {
// see if it's available in the original language.
$post_type_prepared = $wpdb->prepare( "SELECT post_type FROM {$wpdb->posts} WHERE ID = %d", array( $object_id ) );
$post_type = $wpdb->get_var( $post_type_prepared );
$trid_prepared = $wpdb->prepare(
"SELECT trid, source_language_code FROM {$wpdb->prefix}icl_translations WHERE element_id=%d AND element_type = %s",
array(
$object_id,
'post_' . $post_type,
)
);
$trid = $wpdb->get_row( $trid_prepared );
if ( $trid ) {
global $sitepress;
$translations = $sitepress->get_element_translations( $trid->trid, 'post_' . $post_type );
if ( isset( $translations[ $trid->source_language_code ] ) ) {
$translation = $translations[ $trid->source_language_code ];
// see if the original has a thumbnail.
$thumbnail_prepared = $wpdb->prepare(
"SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = %s",
array(
$translation->element_id,
$meta_key,
)
);
$thumbnail = $wpdb->get_var( $thumbnail_prepared );
if ( $thumbnail ) {
$value = $thumbnail;
}
}
}
} else {
$value = $thumbnail;
}
}
return $value;
}
/**
* @param string $menu_id
*/
public function menu( $menu_id ) {
if ( 'WPML' !== $menu_id ) {
return;
}
$menu_label = __( 'Media Translation', 'wpml-media' );
$menu = array();
$menu['order'] = 600;
$menu['page_title'] = $menu_label;
$menu['menu_title'] = $menu_label;
$menu['capability'] = 'edit_others_posts';
$menu['menu_slug'] = 'wpml-media';
$menu['function'] = array( $this, 'menu_content' );
do_action( 'wpml_admin_menu_register_item', $menu );
}
public function menu_content() {
$menus = $this->menus_factory->create();
$menus->display();
}
/**
* @param $ids
* @param $target_language
*
* @return array|string
*/
public function translate_attachment_ids( $ids, $target_language ) {
global $sitepress;
$return_string = false;
if ( ! is_array( $ids ) ) {
$attachment_ids = explode( ',', $ids );
$return_string = true;
}
$translated_ids = array();
if ( ! empty( $attachment_ids ) ) {
foreach ( $attachment_ids as $attachment_id ) {
// Fallback to the original ID
$translated_id = $attachment_id;
// Find the ID translation
$trid = $sitepress->get_element_trid( $attachment_id, 'post_attachment' );
if ( $trid ) {
$id_translations = $sitepress->get_element_translations( $trid, 'post_attachment', false, true );
foreach ( $id_translations as $language_code => $id_translation ) {
if ( $language_code == $target_language ) {
$translated_id = $id_translation->element_id;
break;
}
}
}
$translated_ids[] = $translated_id;
}
}
if ( $return_string ) {
return implode( ',', $translated_ids );
}
return $translated_ids;
}
/**
* Update query for media-upload.php page.
*
* @param object $query WP_Query
*/
public function filter_media_upload_items( $query ) {
$current_lang = $this->sitepress->get_current_language();
$ids = icl_cache_get( '_media_upload_attachments' . $current_lang );
if ( false === $ids ) {
$tbl = $this->wpdb->prefix . 'icl_translations';
$db_query = "
SELECT posts.ID
FROM {$this->wpdb->posts} as posts, $tbl as icl_translations
WHERE posts.post_type = 'attachment'
AND icl_translations.element_id = posts.ID
AND icl_translations.language_code = %s
";
$posts = $this->wpdb->get_results( $this->wpdb->prepare( $db_query, $current_lang ) );
$ids = array();
if ( ! empty( $posts ) ) {
foreach ( $posts as $post ) {
$ids[] = absint( $post->ID );
}
}
icl_cache_set( '_media_upload_attachments' . $current_lang, $ids );
}
$query->set( 'post__in', $ids );
}
}
<?php
class WPML_Media_Add_To_Basket_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress;
if ( isset( $_POST['icl_tm_action'] ) && 'add_jobs' === $_POST['icl_tm_action'] ) {
return new WPML_Media_Add_To_Basket( $sitepress );
}
return null;
}
}
<?php
class WPML_Media_Add_To_Basket implements IWPML_Action {
/**
* @var SitePress
*/
private $sitepress;
/**
* WPML_Media_Add_To_Basket constructor.
*/
public function __construct( SitePress $sitepress ) {
$this->sitepress = $sitepress;
}
public function add_hooks() {
add_filter(
'pre_update_option_' . $this->sitepress->get_wp_api()->constant( 'TranslationProxy_Basket::ICL_TRANSLATION_JOBS_BASKET' ),
array( $this, 'add_media' )
);
}
public function add_media( $data ) {
if ( ! empty( $data['post'] ) ) {
foreach ( $data['post'] as $post_id => $post ) {
if ( $media = $this->get_post_media( $post_id ) ) {
$data['post'][ $post_id ]['media-translation'] = $media;
}
}
}
return $data;
}
private function get_post_media( $post_id ) {
return isset( $_POST['post'][ $post_id ]['media-translation'] ) ?
array_map( 'intval', $_POST['post'][ $post_id ]['media-translation'] ) :
array();
}
}
<?php
class WPML_Media_Selector_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress;
$wpml_wp_api = $sitepress->get_wp_api();
$wpml_media_path = $wpml_wp_api->constant( 'WPML_MEDIA_PATH' );
return new WPML_Media_Selector(
$sitepress,
new WPML_Twig_Template_Loader( array( $wpml_media_path . '/templates/media-selector/' ) ),
new WPML_Media_Post_With_Media_Files_Factory(),
new WPML_Translation_Element_Factory( $sitepress )
);
}
}
<?php
use WPML\UIPage;
class WPML_Media_Selector implements IWPML_Action {
/**
* @var SitePress
*/
private $sitepress;
/**
* @var WPML_Twig_Template_Loader
*/
private $template_loader;
/**
* @var WPML_Media_Post_With_Media_Files_Factory
*/
private $post_with_media_files_factory;
/**
* @var WPML_Media_Post_With_Media_Files_Factory
*/
private $translation_element_factory;
const USER_META_HIDE_POST_MEDIA_SELECTOR = '_wpml_media_hide_post_media_selector';
public function __construct(
SitePress $sitepress,
WPML_Twig_Template_Loader $template_loader,
WPML_Media_Post_With_Media_Files_Factory $post_with_media_files_factory,
WPML_Translation_Element_Factory $translation_element_factory
) {
$this->sitepress = $sitepress;
$this->template_loader = $template_loader;
$this->post_with_media_files_factory = $post_with_media_files_factory;
$this->translation_element_factory = $translation_element_factory;
}
public function add_hooks() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_res' ) );
add_action( 'wp_ajax_wpml_media_load_image_selector', array( $this, 'load_images_selector' ) );
add_action( 'wp_ajax_wpml_media_toogle_show_media_selector', array( $this, 'toggle_show_media_selector' ) );
add_filter( 'wpml_translation_dashboard_row_data', array( $this, 'add_media_data_to_dashboard_row' ), 10, 2 );
add_action( 'wpml_tm_after_translation_dashboard_documents', array( $this, 'add_media_selector_preloader' ) );
}
public function enqueue_res() {
if ( UIPage::isTMDashboard( $_GET ) ) {
$wpml_media_url = $this->sitepress->get_wp_api()->constant( 'WPML_MEDIA_URL' );
wp_enqueue_script( 'wpml-media-selector', $wpml_media_url . '/res/js/media-selector.js', array( 'jquery' ), false, true );
wp_enqueue_style( 'wpml-media-selector', $wpml_media_url . '/res/css/media-selector.css', array() );
}
}
public function load_images_selector() {
$post_id = (int) $_POST['post_id'];
if ( isset( $_POST['languages'] ) && is_array( $_POST['languages'] ) ) {
$languages = array_map( 'sanitize_text_field', $_POST['languages'] );
} else {
$languages = array();
}
$media_files_list = $this->get_media_files_list( $post_id, $languages );
$media_files_count = count( $media_files_list );
$model = array(
'files' => $media_files_list,
'post_id' => $post_id,
);
$html = $this->template_loader->get_template()->show( $model, 'media-selector.twig' );
wp_send_json_success(
array(
'html' => $html,
'media_files_count' => $media_files_count,
)
);
}
/**
* @param int $post_id
* @param array $languages
*
* @return array
*/
private function get_media_files_list( $post_id, $languages ) {
$media_files_list = array();
$post_with_media = $this->post_with_media_files_factory->create( $post_id );
$media_ids = $post_with_media->get_media_ids();
foreach ( $media_ids as $attachment_id ) {
$media_files_list[ $attachment_id ] = array(
'thumbnail' => wp_get_attachment_thumb_url( $attachment_id ),
'name' => get_post_field( 'post_title', $attachment_id ),
'translated' => $this->media_file_is_translated( $attachment_id, $languages ),
);
}
return $media_files_list;
}
private function media_file_is_translated( $attachment_id, $languages ) {
$post_element = $this->translation_element_factory->create( $attachment_id, 'post' );
foreach ( $languages as $language ) {
$translation = $post_element->get_translation( $language );
if ( null === $translation || get_post_meta( $attachment_id, '_wp_attached_file', true )
=== get_post_meta( $translation->get_id(), '_wp_attached_file', true ) ) {
return false;
}
}
return true;
}
public function toggle_show_media_selector() {
$current_value = get_user_meta( get_current_user_id(), self::USER_META_HIDE_POST_MEDIA_SELECTOR, true );
update_user_meta( get_current_user_id(), self::USER_META_HIDE_POST_MEDIA_SELECTOR, ! $current_value );
wp_send_json_success();
}
/**
* @param array $row_data
* @param stdClass $doc_data
*
* @return array
*/
public function add_media_data_to_dashboard_row( $row_data, $doc_data ) {
if ( 0 !== strpos( $doc_data->translation_element_type, 'post_' ) ) {
return $row_data;
}
$row_data = $this->add_post_has_media_flag( $row_data, $doc_data->ID );
$row_data = $this->add_post_type_attribute_data( $row_data, $doc_data->ID );
return $row_data;
}
/**
* @param array $data
* @param int $post_id
*
* @return array
*/
private function add_post_has_media_flag( array $data, $post_id ) {
$data['has-media'] = get_post_meta( $post_id, WPML_Media_Set_Posts_Media_Flag::HAS_MEDIA_POST_FLAG, true );
return $data;
}
/**
* @param array $data
* @param int $post_id
*
* @return array
*/
private function add_post_type_attribute_data( $data, $post_id ) {
$post_type = get_post_type( $post_id );
$post_type_object = get_post_type_object( $post_type );
$data['post-type'] = strtolower( $post_type_object->labels->singular_name );
return $data;
}
public function add_media_selector_preloader() {
$model = array(
'strings' => array(
'has_posts' => sprintf(
__(
'Choose which media to translate with this %s',
'wpml-media'
),
'%POST_TYPE%'
),
'loading' => __( 'Loading...', 'wpml-media' ),
),
'hide_selector' => get_user_meta( get_current_user_id(), self::USER_META_HIDE_POST_MEDIA_SELECTOR, true ),
);
echo $this->template_loader->get_template()->show( $model, 'media-selector-preloader.twig' );
}
}
<?php
class WPML_Media_Submitted_Basket_Notice_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress;
if ( $sitepress->get_wp_api()->is_tm_page( 'basket' ) && $this->basket_has_media() ) {
$template_loader = new WPML_Twig_Template_Loader( array( WPML_MEDIA_PATH . '/templates/media-selector/' ) );
return new WPML_Media_Submitted_Basket_Notice( $template_loader );
}
return null;
}
private function basket_has_media() {
$basket = TranslationProxy_Basket::get_basket( true );
$item_types = TranslationProxy_Basket::get_basket_items_types();
foreach ( $item_types as $item_type => $type_type ) {
if ( isset( $basket[ $item_type ] ) ) {
foreach ( $basket[ $item_type ] as $item ) {
if ( ! empty( $item['media-translation'] ) ) {
return true;
}
}
}
}
return false;
}
}
<?php
class WPML_Media_Submitted_Basket_Notice implements IWPML_Action {
/**
* @var WPML_Twig_Template_Loader
*/
private $template_loader;
public function __construct( WPML_Twig_Template_Loader $template_loader ) {
$this->template_loader = $template_loader;
}
public function add_hooks() {
add_action( 'wpml_tm_scripts_enqueued', array( $this, 'load_js' ) );
add_action( 'wpml_translation_basket_page_after', array( $this, 'load_dialog_template' ) );
}
public function load_js() {
$script_handle = 'submitted-basket-notice';
wp_enqueue_script(
$script_handle,
WPML_MEDIA_URL . '/res/js/submitted-basket-notice.js',
array( 'jquery-ui-dialog' ),
WPML_MEDIA_VERSION,
false
);
$wpml_media_basket_notice_data = array(
'button_label' => __( 'Continue', 'wpml_media' ),
);
wp_localize_script( $script_handle, 'wpml_media_basket_notice_data', $wpml_media_basket_notice_data );
}
public function load_dialog_template() {
/* translators: WPML plugin name */
$wpml_plugin_name = __( 'WPML', 'wpml-media' );
/* translators: WPML Media Translation saddon/section name */
$media_translation_name = __( 'Media Translation', 'wpml-media' );
$media_translation_url = admin_url( 'admin.php?page=wpml-media' );
$media_translation_link = sprintf(
'<a href="%s" target="_blank" rel="noopener" class="wpml-external-link">%s &raquo; %s</a>',
$media_translation_url,
$wpml_plugin_name,
$media_translation_name
);
/* translators: media file string used in "if you want to use a different media file for each language..." */
$media_file_string = __( 'media file', 'wpml-media' );
$redirect_url = add_query_arg( 'page', \WPML\UIPage::TM_PAGE, admin_url( 'admin.php' ) );
$model = array(
'strings' => array(
'dialog_title' => __( 'Media sent to translation', 'wpml-media' ),
'content_with_media_sent' => __( 'You have sent content which contains media attachments for translation.', 'wpml-media' ),
'media_texts_translated' => sprintf( __( 'Translators will translate all your %1$smedia texts%2$s.', 'wpml-media' ), '<strong>', '</strong>' ),
'use_different_media' => sprintf(
__( 'If you want to use a different %1$s for each language, you can set them in: %2$s.', 'wpml-media' ),
'<strong>' . $media_file_string . '</strong>',
$media_translation_link
),
'learn_more' => __( 'Learn more about Media Translation', 'wpml-media' ),
'wpml' => _x( 'WPML', 'plugin name', 'wpml-media' ),
'media_translation' => _x( 'Media Translation', 'wpml addon name', 'wpml-media' ),
),
'learn_more_url' => 'https://wpml.org/documentation/getting-started-guide/media-translation/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlmedia',
'redirect_url' => $redirect_url,
);
echo $this->template_loader->get_template()->show( $model, 'submitted-basket-notice.twig' );
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Obj;
use WPML\FP\Str;
/**
* Media file block parser
*/
class WPML_Non_Embedded_Pdf_Parser extends WPML_Media_Element_Parser {
/**
* @var string
*/
private static $non_embedded_pdf_expression = '/wp:file.*class="wp-block-file".*(href=".*\.pdf")>.*\/wp:file/s';
public function getMediaElements() {
return $this->getFromTags();
}
public function getMediaSrcFromAttributes( $attrs ) {
return Obj::propOr( '', 'href', $attrs );
}
protected function getFromTags() {
// phpcs:disable WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
return preg_match_all( self::$non_embedded_pdf_expression, $this->blockText, $matches ) ?
$this->getAttachments( $matches ) : [];
}
/**
* Checks if media element is File Block and has pdf.
*
* @return bool
*/
public function validate() {
return Str::includes( '<!-- wp:file', $this->blockText )
|| Str::includes( 'pdf', $this->blockText );
}
}
<?php
/**
* Class WPML_Media_Attachment_Image_Update_Factory
*/
class WPML_Media_Attachment_Image_Update_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb;
return new WPML_Media_Attachment_Image_Update( $wpdb );
}
}
<?php
/**
* Class WPML_Media_Attachment_Image_Update
* Allows adding a custom image to a translated attachment
*/
class WPML_Media_Attachment_Image_Update implements IWPML_Action {
const TRANSIENT_FILE_UPLOAD_PREFIX = 'wpml_media_file_update_';
/**
* @var wpdb
*/
private $wpdb;
/**
* WPML_Media_Attachment_Image_Update constructor.
*
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function add_hooks() {
add_action( 'wp_ajax_wpml_media_upload_file', array( $this, 'handle_upload' ) );
}
public function handle_upload() {
if ( $this->is_valid_action() ) {
$original_attachment_id = (int) $_POST['original-attachment-id'];
$attachment_id = (int) $_POST['attachment-id'];
$file_array = $_FILES['file'];
$target_language = $_POST['language'];
$thumb_path = '';
$thumb_url = '';
$upload_overrides = apply_filters( 'wpml_media_wp_upload_overrides', array( 'test_form' => false ) );
$file = wp_handle_upload( $file_array, $upload_overrides );
if ( ! isset( $file['error'] ) ) {
if ( wp_image_editor_supports( array( 'mime_type' => $file['type'] ) ) ) {
$editor = wp_get_image_editor( $file['file'] );
if ( ! is_wp_error( $editor ) ) {
if ( 'application/pdf' === $file['type'] || stripos( $file['type'], 'video' ) !== false ) {
$dirname = dirname( $file['file'] ) . '/';
$ext = pathinfo( $file['file'], PATHINFO_EXTENSION );
$preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file['file'], '.' . $ext ) . "-{$ext}.jpg" );
$editor->save( $preview_file, 'image/jpeg' );
$thumb = $this->resize_thumbnail( $editor );
$attachment_metadata = wp_get_attachment_metadata( $attachment_id );
$attachment_size = [
'file' => basename( $preview_file ),
'width' => $thumb['width'],
'height' => $thumb['height'],
'mime-type' => 'image/jpeg',
];
$attachment_metadata['sizes']['thumbnail'] = $attachment_size;
$attachment_metadata['sizes']['full'] = $attachment_size;
wp_update_attachment_metadata( $attachment_id, $attachment_metadata );
} else {
$thumb = $this->resize_thumbnail( $editor );
}
if ( ! is_wp_error( $thumb ) ) {
$uploads_dir = wp_get_upload_dir();
$thumb_url = $uploads_dir['baseurl'] . $uploads_dir['subdir'] . '/' . $thumb['file'];
$thumb_path = $thumb['path'];
}
} else {
$thumb_url = wp_mime_type_icon( $file['type'] );
if ( $thumb_url ) {
$thumb_path = $file['file'];
} else {
wp_send_json_error( __( 'Failed to load the image editor', 'wpml-media' ) );
}
}
} elseif ( 0 === strpos( $file['type'], 'image/' ) ) {
$thumb_url = $file['url'];
$thumb_path = $file['file'];
} else {
$thumb_url = wp_mime_type_icon( $original_attachment_id );
}
set_transient(
self::TRANSIENT_FILE_UPLOAD_PREFIX . $original_attachment_id . '_' . $target_language,
array(
'upload' => $file,
'thumb' => $thumb_path,
),
HOUR_IN_SECONDS
);
wp_send_json_success(
array(
'attachment_id' => $attachment_id,
'thumb' => $thumb_url,
'name' => basename( $file['file'] ),
)
);
} else {
wp_send_json_error( $file['error'] );
}
} else {
wp_send_json_error( 'invalid action' );
}
}
/**
* Resize the thumbnail if it is larger than the settings size
*
* @param WP_Image_Editor $editor
* @return array|WP_Error
*/
private function resize_thumbnail( $editor ) {
$size = $editor->get_size();
if ( $size['width'] > get_option( 'thumbnail_size_w' ) || $size['height'] > get_option( 'thumbnail_size_h' ) ) {
$resizing = $editor->resize( get_option( 'thumbnail_size_w' ), get_option( 'thumbnail_size_h' ), true );
if ( is_wp_error( $resizing ) ) {
wp_send_json_error( $resizing->get_error_message() );
}
}
return $editor->save();
}
private function is_valid_action() {
$is_attachment_id = isset( $_POST['attachment-id'] );
$is_post_action = isset( $_POST['action'] ) && 'wpml_media_upload_file' === $_POST['action'];
return $is_attachment_id && $is_post_action && wp_verify_nonce( $_POST['wpnonce'], 'media-translation' );
}
}
<?php
/**
* Class WPML_Media_Caption_Tags_Parse
*/
class WPML_Media_Caption_Tags_Parse {
/**
* @param string $text
*
* @return array
*/
public function get_captions( $text ) {
$captions = array();
if ( preg_match_all( '/\[caption (.+)\](.+)\[\/caption\]/sU', $text, $matches ) ) {
for ( $i = 0; $i < count( $matches[0] ); $i++ ) {
$captions[] = new WPML_Media_Caption( $matches[0][ $i ], $matches[1][ $i ], $matches[2][ $i ] );
}
}
return $captions;
}
}
<?php
/**
* Class WPML_Media_Caption
*/
class WPML_Media_Caption {
private $shortcode;
private $content_string;
private $attributes;
private $attachment_id;
private $link;
private $img;
private $caption;
public function __construct( $caption_shortcode, $attributes_data, $content_string ) {
$this->shortcode = $caption_shortcode;
$this->content_string = $content_string;
$this->attributes = $this->find_attributes_array( $attributes_data );
$this->attachment_id = $this->find_attachment_id( $this->attributes );
$this->link = $this->find_link( $content_string );
$mediaParsers = ( new \WPML\Media\Factories\WPML_Media_Element_Parser_Factory() )->create( $content_string );
$mediaElements = [];
foreach ( $mediaParsers as $parser ) {
if ( $parser instanceof \WPML\Media\Classes\WPML_Media_Image_Parser
|| $parser instanceof \WPML\Media\Classes\WPML_Media_Classic_Video_Parser
) {
$mediaElements = array_merge( $mediaElements, $parser->getMediaElements() );
}
}
if ( ! empty( $mediaElements ) ) {
$this->img = current( $mediaElements );
$this->caption = trim( strip_tags( $content_string ) );
}
}
/**
* @return int
*/
public function get_id() {
return $this->attachment_id;
}
public function get_caption() {
return $this->caption;
}
public function get_shortcode_string() {
return $this->shortcode;
}
public function get_content() {
return $this->content_string;
}
public function get_image_alt() {
if ( isset( $this->img['attributes']['alt'] ) ) {
return $this->img['attributes']['alt'];
} else {
return '';
}
}
public function get_link() {
return $this->link;
}
/**
* @param string $attributes_list
*
* @return array
*/
private function find_attributes_array( $attributes_list ) {
$attributes = array();
if ( preg_match_all( '/(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?/', $attributes_list, $attribute_matches ) ) {
foreach ( $attribute_matches[1] as $k => $key ) {
$attributes[ $key ] = $attribute_matches[2][ $k ];
}
}
return $attributes;
}
/**
* @param array $attributes
*
* @return null|int
*/
private function find_attachment_id( $attributes ) {
$attachment_id = null;
if ( isset( $attributes['id'] ) ) {
if ( preg_match( '/attachment_([0-9]+)\b/', $attributes['id'], $id_match ) ) {
if ( 'attachment' === get_post_type( (int) $id_match[1] ) ) {
$attachment_id = (int) $id_match[1];
}
}
}
return $attachment_id;
}
/**
* @param $string
*
* @return array
*/
private function find_link( $string ) {
$link = array();
if ( preg_match( '/<a ([^>]+)>(.+)<\/a>/s', $string, $a_match ) ) {
if ( preg_match( '/href=["\']([^"]+)["\']/', $a_match[1], $url_match ) ) {
$link['url'] = $url_match[1];
}
}
return $link;
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Str;
/**
* Classic audio parser
*/
class WPML_Media_Classic_Audio_Parser extends WPML_Media_Classic_Element_Parser {
const Media_Element_Expression = '/\[audio ([^]]+)\]/s';
const Media_Extension_Expression = '/\[audio.+?(?=="http)/';
/**
* Extracts the extension of the classic audio media element, defaults to mp3.
*
* @return false|string
*/
protected function extractExtension() {
$matches = $this->getExtensionMatches();
return ! empty( $matches ) ? substr( $matches[0], - 3 ) : 'mp3';
}
protected function getMediaElementRegex() {
return self::Media_Element_Expression;
}
protected function getMediaExtensionExpression() {
return self::Media_Extension_Expression;
}
/**
* Checks if media element is classic audio (audio uploaded in classic editor).
*
* @return bool
*/
public function validate() {
return Str::includes( '[audio', $this->blockText );
}
}
<?php
namespace WPML\Media\Classes;
abstract class WPML_Media_Classic_Element_Parser extends WPML_Media_Element_Parser {
/**
* Gets string out of the video element, this string should be ending with the video extension, then last 3 characters from string are returned.
*
* @return false|string
*/
abstract protected function extractExtension();
/**
* Returns regular expression used to detect matches of the media element in a string.
*
* @return string
*/
abstract protected function getMediaElementRegex();
/**
* Returns regular expression used to detect the extension of media element in a string.
*
* @return string
*/
abstract protected function getMediaExtensionExpression();
public function getMediaElements() {
return preg_match_all( $this->getMediaElementRegex(), $this->blockText, $matches )
? $this->getAttachments( $matches ) : [];
}
/**
* Returns the source of the media element according to its extension in the attrs array (for example : mp3, mp4., ...).
*
* @param array $attrs
*
* @return string
*/
public function getMediaSrcFromAttributes( $attrs ) {
$extension = $this->extractExtension();
return ( $extension && isset( $attrs[ $extension ] ) ) ? $attrs[ $extension ] : '';
}
/**
* Applies regular expression match to get the media element extension and returns the matches.
*
* @return mixed
*/
protected function getExtensionMatches() {
preg_match( $this->getMediaExtensionExpression(), $this->blockText, $matches );
return $matches;
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Str;
/**
* Classic video parser
*/
class WPML_Media_Classic_Video_Parser extends WPML_Media_Classic_Element_Parser {
const Media_Element_Expression = '/\[video ([^]]+)\]/s';
const Media_Extension_Expression = '/\[video.+?(?=="http)/';
/**
* Extracts the extension of the classic video media element, defaults to mp4.
*
* @return false|string
*/
protected function extractExtension() {
$matches = $this->getExtensionMatches();
return ! empty( $matches ) ? substr( $matches[0], - 3 ) : 'mp4';
}
protected function getMediaElementRegex() {
return self::Media_Element_Expression;
}
protected function getMediaExtensionExpression() {
return self::Media_Extension_Expression;
}
/**
* Checks if media element is classic video (video uploaded in classic editor).
*
* @return bool
*/
public function validate() {
return Str::includes( '[video', $this->blockText );
}
}
<?php
/**
* Class WPML_Media_Custom_Field_Images_Translation_Factory
*/
class WPML_Media_Custom_Field_Images_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress, $iclTranslationManagement;
$media_localization_settings = WPML_Media::get_setting( 'media_files_localization' );
if ( $media_localization_settings['custom_fields'] || WPML_Media_Custom_Field_Batch_Url_Translation::is_ajax_request() ) {
$image_translator = new WPML_Media_Image_Translate(
$sitepress,
new WPML_Media_Attachment_By_URL_Factory(),
new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory()
);
$image_updater = new WPML_Media_Translated_Images_Update( new \WPML\Media\Factories\WPML_Media_Element_Parser_Factory(), $image_translator, new WPML_Media_Sizes() );
return new WPML_Media_Custom_Field_Images_Translation( $image_updater, $sitepress, $iclTranslationManagement );
}
return null;
}
}
<?php
/**
* Class WPML_Media_Custom_Field_Images_Translation
* Translate images in posts custom fields translations when a custom field is created or updated
*/
class WPML_Media_Custom_Field_Images_Translation implements IWPML_Action {
/**
* @var WPML_Media_Custom_Field_Images_Translation
*/
private $images_updater;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var TranslationManagement
*/
private $iclTranslationManagement;
/**
* WPML_Media_Custom_Field_Images_Translation constructor.
*
* @param WPML_Media_Translated_Images_Update $images_updater
* @param SitePress $sitepress
* @param TranslationManagement $iclTranslationManagement
*/
public function __construct(
WPML_Media_Translated_Images_Update $images_updater,
SitePress $sitepress,
TranslationManagement $iclTranslationManagement
) {
$this->images_updater = $images_updater;
$this->sitepress = $sitepress;
$this->iclTranslationManagement = $iclTranslationManagement;
}
public function add_hooks() {
add_action( 'updated_post_meta', array( $this, 'translate_images' ), PHP_INT_MAX, 4 );
add_action( 'added_post_meta', array( $this, 'translate_images' ), PHP_INT_MAX, 4 );
}
/**
* @param int $meta_id
* @param int $object_id
* @param string $meta_key
* @param string $meta_value
*/
public function translate_images( $meta_id, $object_id, $meta_key, $meta_value ) {
$settings_factory = new WPML_Custom_Field_Setting_Factory( $this->iclTranslationManagement );
$setting = $settings_factory->post_meta_setting( $meta_key );
$is_custom_field_translatable = $this->sitepress->get_wp_api()
->constant( 'WPML_TRANSLATE_CUSTOM_FIELD' ) === $setting->status();
$post_type = get_post_type( $object_id );
$is_post_translatable = $this->sitepress->is_translated_post_type( $post_type );
if ( is_string( $meta_value ) && $is_post_translatable && $is_custom_field_translatable ) {
$post_element = new WPML_Post_Element( $object_id, $this->sitepress );
$source_language = $post_element->get_source_language_code();
if ( null !== $source_language ) {
$this->filter_meta_value_and_update(
$meta_value,
$meta_key,
$post_element->get_language_code(),
$source_language,
$object_id
);
} else {
foreach ( array_keys( $this->sitepress->get_active_languages() ) as $language ) {
$translation = $post_element->get_translation( $language );
if ( $translation ) {
$this->filter_meta_value_and_update(
$meta_value,
$meta_key,
$language,
$source_language,
$translation->get_id()
);
}
}
}
}
}
/**
* @param string $meta_value
* @param string $meta_key
* @param string $target_language
* @param string $source_language
* @param int $post_id
*
* @return string
*/
private function filter_meta_value_and_update( $meta_value, $meta_key, $target_language, $source_language, $post_id ) {
$meta_value_filtered = $this->images_updater->replace_images_with_translations(
$meta_value,
$target_language,
$source_language
);
if ( $meta_value_filtered !== $meta_value ) {
remove_action( 'updated_post_meta', array( $this, 'translate_images' ), PHP_INT_MAX );
update_post_meta( $post_id, $meta_key, wp_slash( $meta_value_filtered ), $meta_value );
add_action( 'updated_post_meta', array( $this, 'translate_images' ), PHP_INT_MAX, 4 );
}
return $meta_value_filtered;
}
}
<?php
namespace WPML\Media\Classes;
use WPML\LIB\WP\Attachment;
abstract class WPML_Media_Element_Parser {
private static $getAttachmentsRegex = '/(\S+)\\s*=\\s*["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?/';
protected $blockText;
public function __construct( $blockText ) {
$this->blockText = $blockText;
}
abstract public function getMediaElements();
abstract public function getMediaSrcFromAttributes( $attrs );
abstract public function validate();
protected function getAttachments( $matches ) {
$attachments = [];
foreach ( $matches[1] as $i => $match ) {
if ( preg_match_all( self::$getAttachmentsRegex, $match, $attribute_matches ) ) {
$attributes = [];
foreach ( $attribute_matches[1] as $k => $key ) {
$attributes[ $key ] = $attribute_matches[2][ $k ];
}
$attachments[ $i ]['attributes'] = $attributes;
}
}
return $attachments;
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Obj;
use WPML\FP\Str;
/**
* Media file block parser
*/
class WPML_Media_File_Parser extends WPML_Media_Element_Parser {
private static $objectElementExpression = '/<object ([^>]+)>/s';
public function getMediaElements() {
return $this->getFromTags();
}
public function getMediaSrcFromAttributes( $attrs ) {
return Obj::propOr( '', 'data', $attrs );
}
protected function getFromTags() {
return preg_match_all( self::$objectElementExpression, $this->blockText, $matches ) ?
$this->getAttachments( $matches ) : [];
}
/**
* Checks if media element is File Block and 'parse_blocks' function exists.
*
* @return bool
*/
public function validate() {
return Str::includes( '<!-- wp:file', $this->blockText ) && function_exists( 'parse_blocks' );
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Obj;
use WPML\FP\Str;
/**
* Media in href parser (basically for files included in classic editor)
*/
class WPML_Media_Href_Parser extends WPML_Media_Element_Parser {
private static $allAnchorsRegex = '/<a.*?>.*?<\/a>/s'; // gets any anchor tag
private static $hrefElementRegex = '/<a ([^>]+)/s'; // to get matches for anchors after filtering them (filtering means that we get only anchors without nested tags)
public function getMediaElements() {
return $this->getFromTags();
}
public function getMediaSrcFromAttributes( $attrs ) {
return Obj::propOr('', 'href', $attrs);
}
protected function getFromTags() {
$anchorsWithoutTags = $this->getAnchorsWithoutNestedTags();
return preg_match_all( self::$hrefElementRegex, implode( '', $anchorsWithoutTags ), $matches ) ? $this->getAttachments( $matches ) : [];
}
/**
* Checks if media element is only anchor with href (basically for files uploaded in classic editor).
*
* @return bool
*/
public function validate() {
return Str::includes( '<a href=', $this->blockText ) && ! empty( $this->getAnchorsWithoutNestedTags() );
}
/**
* Gets anchor tags from WP editor that contain neither nested tags not 'wp-block' string in it.
*
* @return array
*/
public function getAnchorsWithoutNestedTags() {
$anchorHasNestedTags = function ( $anchorTag ) {
$pattern = '/<a .*?>.*?<.*?<\/a>/s';
preg_match( $pattern, $anchorTag, $matches );
return ! empty( $matches );
};
$isBlockAnchor = Str::includes( 'wp-block' );
preg_match_all( self::$allAnchorsRegex, $this->blockText, $allAnchorTags );
return wpml_collect( current( $allAnchorTags ) )
->reject( $anchorHasNestedTags )
->reject( $isBlockAnchor )
->toArray();
}
}
<?php
namespace WPML\Media\Classes;
use WPML\FP\Obj;
use WPML\FP\Str;
/**
* Image block parser
*/
class WPML_Media_Image_Parser extends WPML_Media_Element_Parser {
protected static $getFromCssBackgroundImagesRegex = '/<\w+[^>]+style\s?=\s?"[^"]*?background-image:url\(\s?([^\s\)]+)\s?\)/';
protected static $mediaElementsRegex = [
'/<img ([^>]+)>/s',
'/<video ([^>]+)>/s',
'/<audio ([^>]+)>/s',
];
public function getMediaElements() {
$mediaElements = $this->getFromTags();
$blocks = parse_blocks( $this->blockText );
return $blocks ? array_merge( $mediaElements, $this->getFromCssBackgroundImagesInBlocks( $blocks ) )
: array_merge( $mediaElements, $this->getFromCssBackgroundImages( $this->blockText ) );
}
public function getMediaSrcFromAttributes( $attrs ) {
return Obj::propOr( '', 'src', $attrs );
}
protected function getFromTags() {
$mediaElements = wpml_collect( [] );
foreach ( self::$mediaElementsRegex as $mediaElementExpression ) {
if ( preg_match_all( $mediaElementExpression, $this->blockText, $matches ) ) {
$mediaElements = $mediaElements->merge( $this->getAttachments( $matches ) );
}
}
return $mediaElements->toArray();
}
/**
* Checks if media element is Image Block and 'parse_blocks' function exists.
*
* @return bool
*/
public function validate() {
return (
( function_exists( 'parse_blocks' ) &&
( Str::includes( '<!-- wp:image', $this->blockText )
|| Str::includes( '<!-- wp:video', $this->blockText )
|| Str::includes( '<!-- wp:audio', $this->blockText )
)
)
||
Str::includes( '<img', $this->blockText )
||
Str::includes( '<video', $this->blockText )
||
Str::includes( '<audio', $this->blockText )
);
}
/**
* `parse_blocks` does not specify which kind of collection it should return
* (not always an array of `WP_Block_Parser_Block`) and the block parser can be filtered,
* so we'll cast it to a standard object for now.
*
* @param mixed $block
*
* @return \stdClass|\WP_Block_Parser_Block
*/
protected function sanitizeBlock( $block ) {
$block = (object) $block;
if ( isset( $block->attrs ) ) {
/** Sometimes `$block->attrs` is an object or an array, so we'll use an object */
$block->attrs = (object) $block->attrs;
}
return $block;
}
/**
* @param string $text
*
* @return array
*/
protected function getFromCssBackgroundImages( $text ) {
$images = [];
if ( preg_match_all( self::$getFromCssBackgroundImagesRegex, $text, $matches ) ) {
foreach ( $matches[1] as $src ) {
$images[] = [
'attributes' => [ 'src' => $src ],
];
}
}
return $images;
}
/**
* @param array $blocks
*
* @return array
*/
protected function getFromCssBackgroundImagesInBlocks( $blocks ) {
$images = [];
foreach ( $blocks as $block ) {
$block = $this->sanitizeBlock( $block );
if ( ! empty( $block->innerBlocks ) ) {
$inner_images = $this->getFromCssBackgroundImagesInBlocks( $block->innerBlocks );
$images = array_merge( $images, $inner_images );
continue;
}
if ( ! isset( $block->innerHTML, $block->attrs->id ) ) {
continue;
}
$background_images = $this->getFromCssBackgroundImages( $block->innerHTML );
$image = reset( $background_images );
if ( $image ) {
$images[] = $image;
}
}
return $images;
}
}
<?php
use WPML\Element\API\PostTranslations;
/**
* Class WPML_Media_Image_Translate
* Allows getting translated images in a give language from an attachment
*/
class WPML_Media_Image_Translate {
/**
* @var SitePress
*/
private $sitepress;
/**
* @var WPML_Media_Attachment_By_URL_Factory
*/
private $attachment_by_url_factory;
/**
* @var \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query
*/
private $media_attachment_by_url_query;
/**
* WPML_Media_Image_Translate constructor.
*
* @param SitePress $sitepress
* @param WPML_Media_Attachment_By_URL_Factory $attachment_by_url_factory
* @param \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory $media_attachment_by_url_query_factory
*/
public function __construct(
SitePress $sitepress,
WPML_Media_Attachment_By_URL_Factory $attachment_by_url_factory,
\WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory $media_attachment_by_url_query_factory
) {
$this->sitepress = $sitepress;
$this->attachment_by_url_factory = $attachment_by_url_factory;
$this->media_attachment_by_url_query = $media_attachment_by_url_query_factory->create();
}
/**
* @param string $source_language
* @param array $items_to_translate
*/
public function prefetchDataForFutureGetTranslatedImageCalls( $source_language, $items_to_translate ) {
$this->media_attachment_by_url_query->prefetchAllIdsFromGuids(
$source_language,
array_merge(
array_map(
function( $item ) {
return WPML_Media_Attachment_By_URL::getUrl( $item['url'] );
},
$items_to_translate
),
array_map(
function( $item ) {
return WPML_Media_Attachment_By_URL::getUrlNotScaled( $item['url'] );
},
$items_to_translate
)
)
);
$this->media_attachment_by_url_query->prefetchAllIdsFromMetas(
$source_language,
array_merge(
array_map(
function( $item ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePath( $item['url'] );
},
$items_to_translate
),
array_map(
function( $item ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePathOriginal(
WPML_Media_Attachment_By_URL::getUrlRelativePath( $item['url'] )
);
},
$items_to_translate
),
array_map(
function( $item ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePathScaled( $item['url'] );
},
$items_to_translate
)
)
);
}
/**
* @param int $attachment_id
* @param string $language
* @param string $size
*
* @return string
*/
public function get_translated_image( $attachment_id, $language, $size = null ) {
$image_url = '';
$attachment = new WPML_Post_Element( $attachment_id, $this->sitepress );
$attachment_translation = $attachment->get_translation( $language );
if ( $attachment_translation ) {
$uploads_dir = wp_get_upload_dir();
$attachment_id = $attachment_translation->get_id();
if ( null === $size ) {
$image_url = $uploads_dir['baseurl'] . '/' . get_post_meta( $attachment_id, '_wp_attached_file', true );
} else {
$image_url = $this->get_sized_image_url( $attachment_id, $size, $uploads_dir );
}
}
return $image_url;
}
/**
* @param string $img_src
* @param string $source_language
* @param string $target_language
*
* @return string|bool
*/
public function get_translated_image_by_url( $img_src, $source_language, $target_language ) {
$attachment_id = $this->get_attachment_id_by_url( $img_src, $source_language );
if ( $attachment_id ) {
$size = $this->get_image_size_from_url( $img_src, $attachment_id );
try {
$img_src = $this->get_translated_image( $attachment_id, $target_language, $size );
} catch ( Exception $e ) {
$img_src = false;
}
} else {
$img_src = false;
}
return $img_src;
}
/**
* @param string $img_src
* @param string $source_language
*
* @return int
*/
public function get_attachment_id_by_url( $img_src, $source_language ) {
$attachment_by_url = $this->attachment_by_url_factory->create( $img_src, $source_language, $this->media_attachment_by_url_query );
return (int) $attachment_by_url->get_id();
}
/**
* @param string $url
* @param int $attachment_id
*
* @return string
*/
private function get_image_size_from_url( $url, $attachment_id ) {
$media_sizes = new WPML_Media_Sizes();
return $media_sizes->get_image_size_from_url( $url, $attachment_id );
}
/**
* @param int $attachment_id
* @param string $size
* @param string $uploads_dir
*
* @return string
*/
private function get_sized_image_url( $attachment_id, $size, $uploads_dir ) {
$image_url = '';
$meta_data = wp_get_attachment_metadata( $attachment_id );
$image_url_parts = array( $uploads_dir['baseurl'] );
if ( is_array( $meta_data ) && array_key_exists( 'file', $meta_data ) ) {
$file_subdirectory = $meta_data['file'];
$file_subdirectory_parts = explode( '/', $file_subdirectory );
$filename = array_pop( $file_subdirectory_parts );
$image_url_parts[] = implode( '/', $file_subdirectory_parts );
if ( array_key_exists( $size, $meta_data['sizes'] ) ) {
$image_url_parts[] = $meta_data['sizes'][ $size ]['file'];
} else {
$image_url_parts[] = $filename;
}
$image_url = implode( '/', $image_url_parts );
}
return $image_url;
}
}
<?php
/**
* Class WPML_Media_Post_Images_Translation_Factory
*/
class WPML_Media_Post_Images_Translation_Factory implements IWPML_REST_Action_Loader, IWPML_Backend_Action_Loader {
/**
* @return IWPML_Action|null|WPML_Media_Post_Images_Translation
*/
public function create() {
global $wpdb, $sitepress;
$media_localization_settings = WPML_Media::get_setting( 'media_files_localization' );
if ( $media_localization_settings['posts'] ) {
$image_translator = new WPML_Media_Image_Translate(
$sitepress,
new WPML_Media_Attachment_By_URL_Factory(),
new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory()
);
$image_updater = new WPML_Media_Translated_Images_Update( new \WPML\Media\Factories\WPML_Media_Element_Parser_Factory(), $image_translator, new WPML_Media_Sizes() );
return new WPML_Media_Post_Images_Translation(
$image_updater,
$sitepress,
$wpdb,
new WPML_Translation_Element_Factory( $sitepress ),
new WPML_Media_Custom_Field_Images_Translation_Factory(),
new WPML_Media_Usage_Factory()
);
}
return null;
}
}
<?php
/**
* Class WPML_Media_Post_Images_Translation
* Translate images in posts translations when a post is created or updated
*/
class WPML_Media_Post_Images_Translation implements IWPML_Action {
const ALT_PLACEHOLDER = '{%ALT_TEXT%}';
const CAPTION_PLACEHOLDER = '{%CAPTION%}';
/**
* @var WPML_Media_Translated_Images_Update
*/
private $images_updater;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var WPML_Translation_Element_Factory
*/
private $translation_element_factory;
/**
* @var WPML_Media_Custom_Field_Images_Translation_Factory
*/
private $custom_field_images_translation_factory;
/**
* @var WPML_Media_Usage_Factory
*/
private $media_usage_factory;
private $captions_map = array();
private $translate_locks = array();
public function __construct(
WPML_Media_Translated_Images_Update $images_updater,
SitePress $sitepress,
wpdb $wpdb,
WPML_Translation_Element_Factory $translation_element_factory,
WPML_Media_Custom_Field_Images_Translation_Factory $custom_field_images_translation_factory,
WPML_Media_Usage_Factory $media_usage_factory
) {
$this->images_updater = $images_updater;
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->translation_element_factory = $translation_element_factory;
$this->custom_field_images_translation_factory = $custom_field_images_translation_factory;
$this->media_usage_factory = $media_usage_factory;
}
public function add_hooks() {
add_action( 'save_post', array( $this, 'translate_images' ), PHP_INT_MAX, 1 );
add_filter( 'wpml_pre_save_pro_translation', array( $this, 'translate_images_in_content' ), PHP_INT_MAX, 2 );
add_filter( 'wpml_pre_save_pro_translation', array(
$this,
'replace_placeholders_and_id_in_caption_shortcode'
), PHP_INT_MAX, 2 );
add_action( 'wpml_tm_job_fields',
array( $this, 'replace_caption_placeholders_in_fields' ), 10, 2 );
add_filter( 'wpml_tm_job_data_post_content', array(
$this,
'restore_placeholders_in_translated_job_body'
), 10, 1 );
add_action( 'icl_make_duplicate', array( $this, 'translate_images_in_duplicate' ), PHP_INT_MAX, 4 );
add_action( 'wpml_added_media_file_translation', array( $this, 'translate_url_in_post' ), PHP_INT_MAX, 1 );
add_action( 'wpml_pro_translation_completed', array( $this, 'translate_images' ), PHP_INT_MAX, 1 );
add_action( 'wpml_restored_media_file_translation', array( $this, 'translate_url_in_post' ), PHP_INT_MAX, 2 );
}
/**
* @param int $post_id
*/
public function translate_images( $post_id ) {
if ( isset( $this->translate_locks[ $post_id ] ) ) {
return;
}
$this->translate_locks[ $post_id ] = true;
$post = get_post( $post_id );
if ( ! $post ) {
return;
}
/** @var WPML_Post_Element $post_element */
$post_element = $this->translation_element_factory->create( $post_id, 'post' );
$source_language = $post_element->get_source_language_code();
if ( null !== $source_language ) {
$this->translate_images_in_post_content( $post, $post_element );
$this->translate_images_in_custom_fields( $post_id );
} else { // is original
foreach ( array_keys( $this->sitepress->get_active_languages() ) as $target_language ) {
/** @var WPML_Post_Element $translation */
$translation = $post_element->get_translation( $target_language );
if ( null !== $translation && $post_id !== $translation->get_id() ) {
$translatedPost = get_post( $translation->get_id() );
if ( $translatedPost ) {
$this->translate_images_in_post_content( $translatedPost, $translation );
$this->translate_images_in_custom_fields( $translation->get_id() );
}
}
}
}
unset( $this->translate_locks[ $post_id ] );
}
/**
* @param int $master_post_id
* @param string $language
* @param array $post_array
* @param int $post_id
*/
public function translate_images_in_duplicate( $master_post_id, $language, $post_array, $post_id ) {
$this->translate_images( $post_id );
}
/**
* @param WP_Post $post
* @param WPML_Post_Element $post_element
*/
private function translate_images_in_post_content( WP_Post $post, WPML_Post_Element $post_element ) {
if ( (bool) apply_filters( 'wpml_pb_should_body_be_translated', true, $post, 'translate_images_in_post_content' ) ) {
$post_content_filtered = $this->images_updater->replace_images_with_translations(
$post->post_content,
$post_element->get_language_code(),
$post_element->get_source_language_code()
);
if ( $post_content_filtered !== $post->post_content ) {
$this->wpdb->update(
$this->wpdb->posts,
array( 'post_content' => $post_content_filtered ),
array( 'ID' => $post->ID ),
array( '%s' ),
array( '%d' )
);
}
} elseif ( $this->is_updated_from_media_translation_menu() ) {
do_action( 'wpml_pb_resave_post_translation', $post_element );
}
}
private function is_updated_from_media_translation_menu() {
$allowed_actions = array(
'wpml_media_save_translation',
'wpml_media_translate_media_url_in_posts',
);
return isset( $_POST['action'] ) && in_array( $_POST['action'], $allowed_actions, true );
}
/**
* @param int $post_id
*/
private function translate_images_in_custom_fields( $post_id ) {
$custom_fields_image_translation = $this->custom_field_images_translation_factory->create();
if ( $custom_fields_image_translation ) {
$post_meta = get_metadata( 'post', $post_id );
foreach ( $post_meta as $meta_key => $meta_value ) {
$custom_fields_image_translation->translate_images( null, $post_id, $meta_key, $meta_value[0] );
}
}
}
/**
* @param array $postarr
* @param stdClass $job
*
* @return array
*/
public function translate_images_in_content( array $postarr, stdclass $job ) {
$postarr['post_content'] = $this->images_updater->replace_images_with_translations(
$postarr['post_content'],
$job->language_code,
$job->source_language_code
);
return $postarr;
}
public function translate_url_in_post( $attachment_id, $posts = array() ) {
if ( ! $posts ) {
$media_usage = $this->media_usage_factory->create( $attachment_id );
$posts = $media_usage->get_posts();
}
foreach ( $posts as $post_id ) {
$this->translate_images( $post_id );
}
}
public function replace_placeholders_and_id_in_caption_shortcode( array $postarr, stdClass $job ) {
$media = $this->find_media_in_job( $job );
$postarr['post_content'] = $this->replace_caption_placeholders_in_string(
$postarr['post_content'],
$media,
$job->language_code
);
return $postarr;
}
public function replace_caption_placeholders_in_string( $text, $media, $language ) {
$caption_parser = new WPML_Media_Caption_Tags_Parse();
$captions = $caption_parser->get_captions( $text );
foreach ( $captions as $caption ) {
$attachment_id = $caption->get_id();
$caption_shortcode = $new_caption_shortcode = $caption->get_shortcode_string();
if ( isset( $media[ $attachment_id ] ) ) {
if ( isset( $media[ $attachment_id ]['caption'] ) ) {
$new_caption_shortcode = $this->replace_placeholder_with_caption( $new_caption_shortcode, $caption, $media[ $attachment_id ]['caption'] );
}
if ( isset( $media[ $attachment_id ]['alt'] ) ) {
$new_caption_shortcode = $this->replace_placeholder_with_alt_text( $new_caption_shortcode, $caption, $media[ $attachment_id ]['alt'] );
}
}
if ( $attachment_id ) {
$new_caption_shortcode = $this->replace_caption_id_with_translated_id(
$new_caption_shortcode,
$attachment_id,
$language
);
}
if ( $new_caption_shortcode !== $caption_shortcode ) {
$text = str_replace( $caption_shortcode, $new_caption_shortcode, $text );
$this->captions_map[ $caption_shortcode ] = $new_caption_shortcode;
}
}
return $text;
}
/**
* @param int $new_post_id
* @param array $fields
* @param stdClass $job
*/
public function replace_caption_placeholders_in_fields( array $fields, stdClass $job ) {
$media = $this->find_media_in_job( $job );
foreach ( $fields as $field_id => $field ) {
$fields[ $field_id ]['data'] = $this->replace_caption_placeholders_in_string(
$field['data'],
$media,
$job->language_code
);
}
return $fields;
}
private function replace_placeholder_with_caption( $caption_shortcode, WPML_Media_Caption $caption, $new_caption ) {
$caption_content = $caption->get_content();
$new_caption_content = str_replace( self::CAPTION_PLACEHOLDER, $new_caption, $caption_content );
return str_replace( $caption_content, $new_caption_content, $caption_shortcode );
}
private function replace_placeholder_with_alt_text( $caption_shortcode, WPML_Media_Caption $caption, $new_alt_text ) {
return str_replace( 'alt="' . self::ALT_PLACEHOLDER . '"', 'alt="' . $new_alt_text . '"', $caption_shortcode );
}
private function replace_caption_id_with_translated_id( $caption_shortcode, $attachment_id, $language ) {
$post_element = $this->translation_element_factory->create( $attachment_id, 'post' );
$translation = $post_element->get_translation( $language );
if ( $translation ) {
$translated_id = $translation->get_id();
$caption_shortcode = str_replace(
'id="attachment_' . $attachment_id . '"',
'id="attachment_' . $translated_id . '"',
$caption_shortcode
);
}
return $caption_shortcode;
}
private function find_media_in_job( stdClass $job ) {
$media = array();
foreach ( $job->elements as $element ) {
$field_type = explode( '_', $element->field_type );
if ( 'media' === $field_type[0] ) {
if ( ! isset( $media[ $field_type[1] ] ) ) {
$media[ $field_type[1] ] = array();
}
$media[ $field_type[1] ][ $field_type[2] ] = base64_decode( $element->field_data_translated );
}
}
return $media;
}
public function restore_placeholders_in_translated_job_body( $new_body ) {
/**
* Translation management is updating the translated job data with the post_content
* from the translated post.
* We want the translated job data to contain the placeholders so we need to
* find the captions we replaced and restore it with the version with the placeholders
*/
foreach ( $this->captions_map as $caption_with_placeholder => $caption_in_post ) {
$new_body = str_replace( $caption_in_post, $caption_with_placeholder, $new_body );
}
$this->captions_map = array();
return $new_body;
}
}
\ No newline at end of file
<?php
class WPML_Media_Post_With_Media_Files_Factory {
/**
* @param $post_id
*
* @return WPML_Media_Post_With_Media_Files
*/
public function create( $post_id ) {
global $sitepress, $iclTranslationManagement;
return new WPML_Media_Post_With_Media_Files(
$post_id,
new \WPML\Media\Factories\WPML_Media_Element_Parser_Factory(),
new WPML_Media_Attachment_By_URL_Factory(),
$sitepress,
new WPML_Custom_Field_Setting_Factory( $iclTranslationManagement ),
new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory()
);
}
}
<?php
use WPML\FP\Fns;
use WPML\LIB\WP\Post;
class WPML_Media_Post_With_Media_Files {
/**
* @var int
*/
private $post_id;
/**
* @var WPML_Media_Img_Parse
*/
private $media_parser_factory;
/**
* @var WPML_Media_Attachment_By_URL_Factory
*/
private $attachment_by_url_factory;
/**
* @var SitePress $sitepress
*/
private $sitepress;
/**
* @var WPML_Custom_Field_Setting_Factory
*/
private $cf_settings_factory;
/**
* @var \WPML\Media\Classes\WPML_Media_Attachment_By_URL_Query
*/
private $mediaAttachmentByURLQuery;
/**
* WPML_Media_Post_With_Media_Files constructor.
*
* @param $post_id
* @param \WPML\Media\Factories\WPML_Media_Element_Parser_Factory $media_parser_factory
* @param WPML_Media_Attachment_By_URL_Factory $attachment_by_url_factory
* @param SitePress $sitepress
* @param WPML_Custom_Field_Setting_Factory $cf_settings_factory
* @param \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory $mediaAttachmentByURLQueryFactory
*/
public function __construct(
$post_id,
\WPML\Media\Factories\WPML_Media_Element_Parser_Factory $media_parser_factory,
WPML_Media_Attachment_By_URL_Factory $attachment_by_url_factory,
SitePress $sitepress,
WPML_Custom_Field_Setting_Factory $cf_settings_factory,
\WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory $mediaAttachmentByURLQueryFactory
) {
$this->post_id = $post_id;
$this->media_parser_factory = $media_parser_factory;
$this->attachment_by_url_factory = $attachment_by_url_factory;
$this->sitepress = $sitepress;
$this->cf_settings_factory = $cf_settings_factory;
$this->mediaAttachmentByURLQuery = $mediaAttachmentByURLQueryFactory->create();
}
public function get_media_ids() {
$media_ids = array();
if ( $post = get_post( $this->post_id ) ) {
$content_to_parse = apply_filters( 'wpml_media_content_for_media_usage', $post->post_content, $post );
$media_parsers = $this->media_parser_factory->create( $content_to_parse );
$this->prefetchDataForFutureAttachmentByUrlGetIdCalls( $media_parsers );
foreach ( $media_parsers as $media_parser ) {
$media_ids = $this->unique_array_merge( $media_ids, $this->_get_ids_from_media_array( $media_parser, $media_parser->getMediaElements() ) );
if ( $featured_image = get_post_meta( $this->post_id, '_thumbnail_id', true ) ) {
$media_ids[] = $featured_image;
}
}
$media_localization_settings = WPML_Media::get_setting( 'media_files_localization' );
if ( $media_localization_settings['custom_fields'] ) {
$custom_fields_content = $this->get_content_in_translatable_custom_fields();
$media_parsers = $this->media_parser_factory->create( $custom_fields_content );
foreach ( $media_parsers as $media_parser ) {
$media_ids = $this->unique_array_merge( $media_ids, $this->_get_ids_from_media_array( $media_parser, $media_parser->getMediaElements() ) );
}
}
if ( $gallery_media_ids = $this->get_gallery_media_ids( $content_to_parse ) ) {
$media_ids = array_unique( array_values( array_merge( $media_ids, $gallery_media_ids ) ) );
$media_ids = $this->unique_array_merge( $media_ids, $gallery_media_ids );
}
if ( $attached_media_ids = $this->get_attached_media_ids( $this->post_id ) ) {
$media_ids = $this->unique_array_merge( $media_ids, $attached_media_ids );
}
}
return Fns::filter( Post::get(), apply_filters( 'wpml_ids_of_media_used_in_post', $media_ids, $this->post_id ) );
}
/**
* @param array $first_array
* @param array $second_array
*
* @return array
*/
private function unique_array_merge( $first_array, $second_array) {
return array_unique( array_values( array_merge( $first_array, $second_array ) ) );
}
/**
* @param \WPML\Media\Classes\WPML_Media_Element_Parser $media_parser
* @param array $media_array
*
* @return array
*/
private function _get_ids_from_media_array( $media_parser, $media_array ) {
$media_ids = array();
foreach ( $media_array as $media ) {
if ( isset( $media['attachment_id'] ) ) {
$media_ids[] = $media['attachment_id'];
} else {
$attachment_by_url = $this->attachment_by_url_factory->create(
$media_parser->getMediaSrcFromAttributes( $media['attributes'] ),
wpml_get_current_language(),
$this->mediaAttachmentByURLQuery
);
if ( $attachment_by_url->get_id() ) {
$media_ids[] = $attachment_by_url->get_id();
}
}
}
return $media_ids;
}
/**
* @param WPML_Media_Element_Parser[] $mediaParsers
*/
private function prefetchDataForFutureAttachmentByUrlGetIdCalls( $mediaParsers ) {
$urls = [];
foreach ( $mediaParsers as $mediaParser ) {
foreach( $mediaParser->getMediaElements() as $media ) {
if ( isset( $media['attachment_id'] ) ) {
continue;
}
$urls[] = $mediaParser->getMediaSrcFromAttributes( $media['attributes'] );
}
}
$this->mediaAttachmentByURLQuery->prefetchAllIdsFromGuids(
wpml_get_current_language(),
array_merge(
array_map(
function( $url ) {
return WPML_Media_Attachment_By_URL::getUrl( $url );
},
$urls
),
array_map(
function( $url ) {
return WPML_Media_Attachment_By_URL::getUrlNotScaled( $url );
},
$urls
)
)
);
$this->mediaAttachmentByURLQuery->prefetchAllIdsFromMetas(
wpml_get_current_language(),
array_merge(
array_map(
function( $url ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePath( $url );
},
$urls
),
array_map(
function( $url ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePathOriginal(
WPML_Media_Attachment_By_URL::getUrlRelativePath( $url )
);
},
$urls
),
array_map(
function( $url ) {
return WPML_Media_Attachment_By_URL::getUrlRelativePathScaled( $url );
},
$urls
)
)
);
}
/**
* @param string $post_content
*
* @return array
*/
private function get_gallery_media_ids( $post_content ) {
$galleries_media_ids = array();
$gallery_shortcode_regex = '/\[gallery [^[]*ids=["\']([0-9,\s]+)["\'][^[]*\]/m';
if ( preg_match_all( $gallery_shortcode_regex, $post_content, $matches ) ) {
foreach ( $matches[1] as $gallery_ids_string ) {
$media_ids_array = explode( ',', $gallery_ids_string );
$media_ids_array = Fns::map( Fns::unary( 'intval' ), $media_ids_array );
foreach ( $media_ids_array as $media_id ) {
if ( 'attachment' === get_post_type( $media_id ) ) {
$galleries_media_ids[] = $media_id;
}
}
}
}
return $galleries_media_ids;
}
/**
* @param $languages
*
* @return array
*/
public function get_untranslated_media( $languages ) {
$untranslated_media = array();
$post_media = $this->get_media_ids();
foreach ( $post_media as $attachment_id ) {
$post_element = new WPML_Post_Element( $attachment_id, $this->sitepress );
foreach ( $languages as $language ) {
$translation = $post_element->get_translation( $language );
if ( null === $translation || ! $this->media_file_is_translated( $attachment_id, $translation->get_id() ) ) {
$untranslated_media[] = $attachment_id;
break;
}
}
}
return $untranslated_media;
}
private function media_file_is_translated( $attachment_id, $translated_attachment_id ) {
return get_post_meta( $attachment_id, '_wp_attached_file', true )
!== get_post_meta( $translated_attachment_id, '_wp_attached_file', true );
}
private function get_content_in_translatable_custom_fields() {
$content = '';
$post_meta = get_metadata( 'post', $this->post_id );
if ( is_array( $post_meta ) ) {
foreach ( $post_meta as $meta_key => $meta_value ) {
$setting = $this->cf_settings_factory->post_meta_setting( $meta_key );
$is_translatable = $this->sitepress->get_wp_api()
->constant( 'WPML_TRANSLATE_CUSTOM_FIELD' ) === $setting->status();
if ( is_string( $meta_value[0] ) && $is_translatable ) {
$content .= $meta_value[0];
}
}
}
return $content;
}
private function get_attached_media_ids( $post_id ) {
$attachments = get_children(
array(
'post_parent' => $post_id,
'post_status' => 'inherit',
'post_type' => 'attachment',
)
);
return array_keys( $attachments );
}
}
<?php
/**
* Class WPML_Media_Save_Translation_Factory
*/
class WPML_Media_Save_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress, $wpdb;
return new WPML_Media_Save_Translation( $sitepress, $wpdb, new WPML_Media_File_Factory(), new WPML_Translation_Element_Factory( $sitepress ) );
}
}
<?php
class WPML_Media_Save_Translation implements IWPML_Action {
/**
* @var SitePress
*/
private $sitepress;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var WPML_Media_File_Factory
*/
private $media_file_factory;
/**
* @var array
*/
private $post_data;
/**
* @var WPML_Translation_Element_Factory
*/
private $translation_element_factory;
/**
* WPML_Media_Save_Translation constructor.
*
* @param SitePress $sitepress
* @param wpdb $wpdb
* @param WPML_Media_File_Factory $media_file_factory
* @param WPML_Translation_Element_Factory $translation_element_factory
*/
public function __construct( SitePress $sitepress, wpdb $wpdb, WPML_Media_File_Factory $media_file_factory, WPML_Translation_Element_Factory $translation_element_factory ) {
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->media_file_factory = $media_file_factory;
$this->translation_element_factory = $translation_element_factory;
}
public function add_hooks() {
add_action( 'wp_ajax_wpml_media_save_translation', array( $this, 'save_media_translation' ) );
}
public function save_media_translation() {
if ( wp_verify_nonce( $_POST['wpnonce'], 'media-translation' ) ) {
$post_array['ID'] = (int) $_POST['translated-attachment-id'];
$original_attachment_id = (int) $_POST['original-attachment-id'];
$translated_language = sanitize_text_field( $_POST['translated-language'] );
if ( isset( $_POST['translation']['title'] ) ) {
$post_array['post_title'] = sanitize_text_field( $_POST['translation']['title'] );
}
if ( isset( $_POST['translation']['caption'] ) ) {
$post_array['post_excerpt'] = sanitize_text_field( $_POST['translation']['caption'] );
}
if ( isset( $_POST['translation']['description'] ) ) {
$post_array['post_content'] = sanitize_text_field( $_POST['translation']['description'] );
}
if ( $post_array['ID'] ) {
$attachment_id = wp_update_post( $post_array );
if ( $this->should_restore_media() ) {
$this->restore_media_file( $attachment_id, $original_attachment_id, $translated_language );
}
} else {
$post_array['post_type'] = 'attachment';
$post_array['post_status'] = 'inherit';
$post_array['guid'] = get_post_field( 'guid', $original_attachment_id );
$post_array['post_mime_type'] = get_post_field( 'post_mime_type', $original_attachment_id );
$attachment_id = $this->create_attachment_translation( $original_attachment_id, $post_array );
$this->sitepress->set_element_language_details(
$attachment_id,
'post_attachment',
$this->get_post_trid_value(),
$this->get_post_lang_value()
);
if ( ! $this->has_media_upload() ) {
$this->copy_attached_file_info_from_original( $attachment_id, $original_attachment_id );
}
$this->mark_media_as_not_translated( $attachment_id, $translated_language );
}
$translation_status = WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION;
if ( $this->has_media_upload() ) {
$this->update_media_file( $attachment_id, $original_attachment_id, $translated_language );
$translation_status = WPML_Media_Translation_Status::TRANSLATED;
}
if ( isset( $_POST['translation']['alt-text'] ) ) {
update_post_meta(
$attachment_id,
'_wp_attachment_image_alt',
sanitize_text_field( $_POST['translation']['alt-text'] )
);
}
if ( 0 === strpos( get_post_field( 'post_mime_type', $original_attachment_id ), 'image/' ) ) {
$translated_thumb = wp_get_attachment_thumb_url( $attachment_id );
$original_thumb = wp_get_attachment_thumb_url( $original_attachment_id );
$media_file_is_translated = $translated_thumb !== $original_thumb;
} else {
$media_file_is_translated = get_attached_file( $attachment_id ) !== get_attached_file( $original_attachment_id );
$translated_thumb = wp_mime_type_icon( $original_attachment_id );
}
$media_usage = get_post_meta( $original_attachment_id, WPML_Media_Usage::FIELD_NAME, true );
$posts_list = array();
if ( isset( $media_usage['posts'] ) ) {
foreach ( $media_usage['posts'] as $post_id ) {
$post_element = $this->translation_element_factory->create( $post_id, 'post' );
$post_translation = $post_element->get_translation( $translated_language );
if ( $post_translation ) {
$posts_list[] = array(
'url' => get_edit_post_link( $post_translation->get_id() ),
'title' => get_post_field( 'post_title', $post_translation->get_id() ),
);
}
}
}
if ( isset( $media_usage['posts'] ) && $this->should_restore_media() ) {
do_action( 'wpml_restored_media_file_translation', $attachment_id, $media_usage['posts'] );
}
$response = array(
'attachment_id' => $attachment_id,
'thumb' => $media_file_is_translated ? $translated_thumb : false,
'status' => $translation_status,
'usage' => $posts_list,
);
wp_send_json_success( $response );
} else {
wp_send_json_error( array( 'error' => __( 'Invalid nonce', 'wpml-media' ) ) );
}
}
private function has_media_upload() {
return ! empty( $_POST['update-media-file'] );
}
private function should_restore_media() {
return ! empty( $_POST['restore-media'] );
}
/**
* @param int $original_attachment_id
* @param array $post_array
*
* @return int
*/
private function create_attachment_translation( $original_attachment_id, $post_array ) {
$post_element = $this->translation_element_factory->create( $original_attachment_id, 'post' );
$this->set_post_trid_value( $post_element->get_trid() );
$this->set_post_lang_value( $_POST['translated-language'] );
add_filter( 'wpml_tm_save_post_trid_value', array( $this, 'get_post_trid_value' ) );
add_filter( 'wpml_tm_save_post_lang_value', array( $this, 'get_post_lang_value' ) );
$attachment_id = wp_insert_post( $post_array );
remove_filter( 'wpml_tm_save_post_trid_value', array( $this, 'get_post_trid_value' ) );
remove_filter( 'wpml_tm_save_post_lang_value', array( $this, 'get_post_lang_value' ) );
return $attachment_id;
}
private function set_post_trid_value( $value ) {
$this->post_data['post_icl_trid'] = $value;
}
public function get_post_trid_value() {
return $this->post_data['post_icl_trid'];
}
private function set_post_lang_value( $value ) {
$this->post_data['post_icl_language'] = $value;
}
public function get_post_lang_value() {
return $this->post_data['post_icl_language'];
}
private function restore_media_file( $attachment_id, $original_attachment_id, $language ) {
$media_file = $this->media_file_factory->create( $attachment_id );
$media_file->delete();
$this->copy_attached_file_info_from_original( $attachment_id, $original_attachment_id );
$this->mark_media_as_not_translated( $original_attachment_id, $language );
}
private function copy_attached_file_info_from_original( $attachment_id, $original_attachment_id ) {
$meta_keys = array(
'_wp_attachment_metadata',
'_wp_attached_file',
'_wp_attachment_backup_sizes',
);
foreach ( $meta_keys as $meta_key ) {
update_post_meta(
$attachment_id,
$meta_key,
get_post_meta( $original_attachment_id, $meta_key, true )
);
}
/**
* Fires after attachment post meta is copied
*
* @since 4.1.0
*
* @param int $original_attachment_id The ID of the source/original attachment.
* @param int $attachment_id The ID of the duplicated attachment.
*/
do_action( 'wpml_after_copy_attached_file_postmeta', $original_attachment_id, $attachment_id );
}
private function mark_media_as_not_translated( $attachment_id, $language ) {
update_post_meta( $attachment_id, WPML_Media_Translation_Status::STATUS_PREFIX . $language, WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION );
}
private function mark_media_as_translated( $attachment_id, $language ) {
update_post_meta( $attachment_id, WPML_Media_Translation_Status::STATUS_PREFIX . $language, WPML_Media_Translation_Status::TRANSLATED );
}
/**
* @param array $file
*
* @return array
*/
private function get_attachment_post_data( $file ) {
$postarr = array(
'post_mime_type' => $file['type'],
'guid' => $file['url'],
'post_modified' => current_time( 'mysql' ),
'post_modified_gmt' => current_time( 'mysql', 1 ),
);
return $postarr;
}
private function update_media_file( $attachment_id, $original_attachment_id, $translated_language_code ) {
$transient_key = WPML_Media_Attachment_Image_Update::TRANSIENT_FILE_UPLOAD_PREFIX . $original_attachment_id . '_' . $translated_language_code;
$media_file_upload = get_transient( $transient_key );
if ( $media_file_upload ) {
$file = $media_file_upload['upload'];
// delete previous media file + sizes.
$media_file = $this->media_file_factory->create( $attachment_id );
$media_file->delete();
// Saving the GUID of media before updating it so it can be used in WPML_Media_Translated_Images_Update::replace_images_with_translations
// The reason for that is the update function in line 270 here is running before replace_images_with_translations.,
// So when replace_images_with_translations tries to get attachment ID of media with its GUID from DB it fails.,
// and this is causing media update in post fails if it's done more than one time.
$_POST['pre-update-translated-media-guid'] = get_post_field( 'guid', $attachment_id );
$post_data = $this->get_attachment_post_data( $file );
$this->wpdb->update( $this->wpdb->posts, $post_data, array( 'ID' => $attachment_id ) );
update_attached_file( $attachment_id, $file['file'] );
/**
* Fires after attached file is updated
*
* @since 4.1.0
*
* @param int $attachment_id The ID of uploaded attachment.
* @param array $file {
* Uploaded file data.
*
* @type string file Absolute path to file.
*
* @type string url File URL.
*
* @type string type File type.
* }
* @param string $translated_language_code Attachment language code.
*/
do_action( 'wpml_updated_attached_file', $attachment_id, $file, $translated_language_code );
$attachment_metadata = wp_generate_attachment_metadata( $attachment_id, $file['file'] );
$current_attachment_metadata = wp_get_attachment_metadata( $attachment_id );
if ( $current_attachment_metadata && isset( $current_attachment_metadata['sizes'] ) ) {
$attachment_metadata['sizes'] = $current_attachment_metadata['sizes'];
}
wp_update_attachment_metadata( $attachment_id, $attachment_metadata );
if ( 'application/pdf' === $file['type'] ) {
wp_delete_file( $media_file_upload['thumb'] );
}
$this->mark_media_as_translated( $original_attachment_id, $translated_language_code );
do_action( 'wpml_added_media_file_translation', $original_attachment_id, $file, $translated_language_code );
delete_transient( $transient_key );
}
}
}
<?php
class WPML_Media_Set_Posts_Media_Flag_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb;
$post_media_usage_factory = new WPML_Media_Post_Media_Usage_Factory();
return new WPML_Media_Set_Posts_Media_Flag(
$wpdb,
wpml_get_admin_notices(),
$post_media_usage_factory->create(),
new WPML_Media_Post_With_Media_Files_Factory()
);
}
}
\ No newline at end of file
<?php
class WPML_Media_Set_Posts_Media_Flag implements IWPML_Action {
const HAS_MEDIA_POST_FLAG = '_wpml_media_has_media';
const BATCH_SIZE = 100;
/**
* @var wpdb $wpdb
*/
private $wpdb;
/**
* @var WPML_Notices
*/
private $wpml_notices;
/**
* @var WPML_Media_Post_Media_Usage
*/
private $post_media_usage;
/**
* @var WPML_Media_Post_With_Media_Files_Factory
*/
private $post_with_media_files_factory;
public function __construct(
wpdb $wpdb,
WPML_Notices $wpml_notices,
WPML_Media_Post_Media_Usage $post_media_usage,
WPML_Media_Post_With_Media_Files_Factory $post_with_media_files_factory
) {
$this->wpdb = $wpdb;
$this->wpml_notices = $wpml_notices;
$this->post_media_usage = $post_media_usage;
$this->post_with_media_files_factory = $post_with_media_files_factory;
}
public function add_hooks() {
add_action( 'wp_ajax_' . WPML_Media_Posts_Media_Flag_Notice::PREPARE_ACTION, [ $this, 'clear_flags_action' ] );
add_action( 'wp_ajax_' . WPML_Media_Posts_Media_Flag_Notice::PROCESS_ACTION, [ $this, 'process_batch_action' ] );
add_action( 'save_post', array( $this, 'update_post_flag' ) );
}
public function clear_flags_action() {
if ( $this->verify_nonce( WPML_Media_Posts_Media_Flag_Notice::PREPARE_ACTION ) ) {
$this->clear_flags();
wp_send_json_success( array( 'status' => __( 'Running setup...', 'wpml-media' ) ) );
} else {
wp_send_json_error( array( 'status' => 'Invalid nonce' ) );
}
}
public function clear_flags() {
if ( ! WPML_Media::has_setup_started() ) {
$this->wpdb->delete( $this->wpdb->postmeta, array( 'meta_key' => self::HAS_MEDIA_POST_FLAG ), array( '%s' ) );
}
}
public function process_batch_action() {
if ( $this->verify_nonce( WPML_Media_Posts_Media_Flag_Notice::PROCESS_ACTION ) ) {
$offset = isset( $_POST['offset'] ) ? (int) $_POST['offset'] : 0;
list( $status, $offset, $continue ) = $this->process_batch( $offset );
wp_send_json_success( array(
'status' => $status,
'offset' => $offset,
'continue' => $continue
) );
} else {
wp_send_json_error( array( 'status' => 'Invalid nonce' ) );
}
}
public function process_batch( $offset ) {
$this->mark_started();
$continue = false;
$status = __( 'Setup complete!', 'wpml-media' );
if ( ! WPML_Media::has_setup_run() ) {
$sql = $this->wpdb->prepare( "
SELECT SQL_CALC_FOUND_ROWS ID, post_content FROM {$this->wpdb->posts} p
JOIN {$this->wpdb->prefix}icl_translations t
ON t.element_id = p.ID AND t.element_type LIKE 'post_%'
LEFT JOIN {$this->wpdb->prefix}postmeta m ON p.ID = m.post_id AND m.meta_key='%s'
WHERE p.post_type NOT IN ( 'auto-draft', 'attachment', 'revision' )
AND t.source_language_code IS NULL AND m.meta_id IS NULL
ORDER BY ID ASC
LIMIT %d, %d
", self::HAS_MEDIA_POST_FLAG, $offset, self::BATCH_SIZE );
$posts = $this->wpdb->get_results( $sql );
$total_posts_found = $this->wpdb->get_var( 'SELECT FOUND_ROWS()' );
if ( $continue = ( count( $posts ) > 0 ) ) {
$this->flag_posts( $posts );
$this->record_media_usage( $posts );
$progress = round( 100 * min( $offset, $total_posts_found ) / $total_posts_found );
$status = sprintf( __( 'Setup in progress: %d%% complete...', 'wpml-media' ), $progress );
}
}
if ( ! $continue ) {
$this->mark_complete();
}
return [ $status, $offset + self::BATCH_SIZE, $continue ];
}
private function verify_nonce( $action ) {
return isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], $action );
}
/**
* @param array $posts
*/
private function flag_posts( $posts ) {
foreach ( $posts as $post ) {
$this->update_post_flag( $post->ID );
}
}
public function update_post_flag( $post_id ) {
$post_with_media_files = $this->post_with_media_files_factory->create( $post_id );
if ( $post_with_media_files->get_media_ids() ) {
update_post_meta( $post_id, self::HAS_MEDIA_POST_FLAG, 1 );
} else {
delete_post_meta( $post_id, self::HAS_MEDIA_POST_FLAG );
}
}
/**
* @param array $posts
*/
private function record_media_usage( $posts ) {
foreach ( $posts as $post ) {
$this->post_media_usage->update_media_usage( $post->ID );
}
}
private function mark_complete() {
WPML_Media::set_setup_run();
$this->wpml_notices->remove_notice(
WPML_Media_Posts_Media_Flag_Notice::NOTICE_GROUP,
WPML_Media_Posts_Media_Flag_Notice::NOTICE_ID
);
}
private function mark_started() {
WPML_Media::set_setup_started();
}
}
<?php
/**
* @author OnTheGo Systems
*/
class WPML_Media_Sizes {
/**
* @param array $img
*
* @return null|string
*/
public function get_size_from_class( array $img ) {
if ( array_key_exists( 'attributes', $img ) && array_key_exists( 'class', $img['attributes'] ) ) {
$classes = explode( ' ', $img['attributes']['class'] );
foreach ( $classes as $class ) {
if ( strpos( $class, 'size-' ) === 0 ) {
$class_parts = explode( '-', $class );
if ( count( $class_parts ) >= 2 ) {
unset( $class_parts[0] );
return implode( '-', $class_parts );
}
}
}
}
return null;
}
/**
* @param array $img
*
* @return null|string
*/
public function get_size_from_attributes( array $img ) {
if (
array_key_exists( 'attributes', $img )
&& array_key_exists( 'width', $img['attributes'] )
&& array_key_exists( 'height', $img['attributes'] )
) {
$width = $img['attributes']['width'];
$height = $img['attributes']['height'];
$size_name = $this->get_image_size_name( $width, $height );
if ( $size_name ) {
return $size_name;
}
}
return null;
}
/**
* @param array $img
*
* @return null|string
*/
public function get_attachment_size( array $img ) {
$size = null;
if ( array_key_exists( 'size', $img ) ) {
$size = $img['size'];
}
if ( ! $size ) {
$size = $this->get_size_from_class( $img );
}
if ( ! $size ) {
$size = $this->get_size_from_attributes( $img );
}
if ( ! $size ) {
$size = $this->get_size_from_url( $img );
}
return $size;
}
/**
* @param string $width
* @param string $height
*
* @return null|string
*/
private function get_image_size_name( $width, $height ) {
global $_wp_additional_image_sizes;
foreach ( get_intermediate_image_sizes() as $size ) {
if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
if ( $width == $_wp_additional_image_sizes[ $size ]['width'] && $height == $_wp_additional_image_sizes[ $size ]['height'] ) {
return $size;
}
} elseif ( in_array( $size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
if ( $width == get_option( "{$size}_size_w" ) && $height == get_option( "{$size}_size_h" ) ) {
return $size;
}
}
}
return null;
}
/**
* @param array $img
*
* @return null|string
*/
private function get_size_from_url( array $img ) {
$size = null;
if ( isset( $img['attributes']['src'], $img['attachment_id'] ) ) {
$size = $this->get_image_size_from_url( $img['attributes']['src'], $img['attachment_id'] );
}
return $size;
}
/**
* @param $url
* @param $attachment_id
*
* @return null|string
*/
public function get_image_size_from_url( $url, $attachment_id ) {
$size = null;
$thumb_file_name = basename( $url );
$attachment_meta_data = wp_get_attachment_metadata( $attachment_id );
if ( isset( $attachment_meta_data['sizes'] ) ) {
foreach ( $attachment_meta_data['sizes'] as $key => $size_array ) {
if ( $thumb_file_name === $size_array['file'] ) {
$size = $key;
break;
}
}
}
return $size;
}
}
<?php
/**
* Class WPML_Media_String_Images_Translation_Factory
*/
class WPML_Media_String_Images_Translation_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $wpdb, $sitepress;
$media_localization_settings = WPML_Media::get_setting( 'media_files_localization' );
if ( $media_localization_settings['strings'] ) {
$image_translator = new WPML_Media_Image_Translate(
$sitepress,
new WPML_Media_Attachment_By_URL_Factory(),
new \WPML\Media\Factories\WPML_Media_Attachment_By_URL_Query_Factory()
);
$image_updater = new WPML_Media_Translated_Images_Update( new \WPML\Media\Factories\WPML_Media_Element_Parser_Factory(), $image_translator, new WPML_Media_Sizes() );
$string_factory = new WPML_ST_String_Factory( $wpdb );
return new WPML_Media_String_Images_Translation( $image_updater, $string_factory );
}
return null;
}
}
<?php
/**
* Class WPML_Media_String_Images_Translation
* Translate images in posts strings translations when a string translation is created or updated
*/
class WPML_Media_String_Images_Translation implements IWPML_Action {
/**
* @var WPML_Media_String_Images_Translation
*/
private $images_updater;
/**
* @var WPML_ST_String_Factory
*/
private $string_factory;
/**
* WPML_Media_String_Images_Translation constructor.
*
* @param WPML_Media_Translated_Images_Update $images_updater
* @param WPML_ST_String_Factory $string_factory
*/
public function __construct( WPML_Media_Translated_Images_Update $images_updater, WPML_ST_String_Factory $string_factory ) {
$this->images_updater = $images_updater;
$this->string_factory = $string_factory;
}
public function add_hooks() {
add_filter( 'wpml_st_string_translation_before_save', array( $this, 'translate_images' ), PHP_INT_MAX, 3 );
}
/**
* @param array $translation_data
* @param string $target_language
* @param int $string_id
*
* @return array
*/
public function translate_images( $translation_data, $target_language, $string_id ) {
if ( ! empty( $translation_data['value'] ) ) {
$original_string = $this->string_factory->find_by_id( $string_id );
$translation_data['value'] = $this->images_updater->replace_images_with_translations(
$translation_data['value'],
$target_language,
$original_string->get_language()
);
}
return $translation_data;
}
}
<?php
/**
* Class WPML_Media_Translated_Images_Update
* Translates images in a given text
*/
class WPML_Media_Translated_Images_Update {
/**
* @var \WPML\Media\Factories\WPML_Media_Element_Parser_Factory
*/
private $media_parser_factory;
/**
* @var \WPML_Media_Image_Translate
*/
private $image_translator;
/**
* @var \WPML_Media_Sizes
*/
private $media_sizes;
/**
* WPML_Media_Translated_Images_Update constructor.
*
* @param \WPML\Media\Factories\WPML_Media_Element_Parser_Factory $media_parser_factory
* @param WPML_Media_Image_Translate $image_translator
* @param WPML_Media_Sizes $media_sizes
*/
public function __construct(
\WPML\Media\Factories\WPML_Media_Element_Parser_Factory $media_parser_factory,
WPML_Media_Image_Translate $image_translator,
WPML_Media_Sizes $media_sizes
) {
$this->media_parser_factory = $media_parser_factory;
$this->image_translator = $image_translator;
$this->media_sizes = $media_sizes;
}
/**
* @param string $text
* @param string $target_language
* @param string $source_language
*
* @return string
*/
public function replace_images_with_translations( $text, $target_language, $source_language = null ) {
$media_parsers = $this->media_parser_factory->create( $text );
// We have original and translated attachment IDs already saved in the $_POST variable.
// So I started using them instead of grabbing them again.
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification
$attachment_id = isset( $_POST['original-attachment-id'] ) ? $_POST['original-attachment-id'] : null;
$translated_id = isset( $_POST['translated-attachment-id'] ) ? $_POST['translated-attachment-id'] : null;
$pre_update_translated_media_guid = isset( $_POST['pre-update-translated-media-guid'] ) ? $_POST['pre-update-translated-media-guid'] : '';
/**
* Checks if media src in post content (not updated yet) is equal to old media that was uploaded but now its guid replaced in database.
*
* @param $media_src
*
* @return bool
*/
$media_src_same_as_pre_update = function ( $media_src ) use ( $pre_update_translated_media_guid ) {
return $media_src === $pre_update_translated_media_guid;
};
/**
* Checks if media src in post content (not updated yet) contains old media that was uploaded but now its guid replaced in database.
*
* @param $media_src
*
* @return bool
*/
$media_src_contains_pre_update = function ( $media_src ) use ( $pre_update_translated_media_guid ) {
$thumb_file_name = basename( $pre_update_translated_media_guid );
$pre_update_translated_media_parts = explode( '.', $thumb_file_name );
$media_src_extension = pathinfo( $media_src, PATHINFO_EXTENSION );
$pre_update_translated_media_extension = is_array( $pre_update_translated_media_parts ) ? end( $pre_update_translated_media_parts ) : null;
return $pre_update_translated_media_parts[0] && false !== strpos( $media_src, $pre_update_translated_media_parts[0] ) && $media_src_extension === $pre_update_translated_media_extension;
};
if ( ! empty( $media_parsers ) ) {
$items_to_translate = [];
foreach ( $media_parsers as $media_parser ) {
$media_items = $media_parser->getMediaElements();
foreach ( $media_items as $media ) {
$media_src = $media_parser->getMediaSrcFromAttributes( $media['attributes'] );
$original_media_guid = isset( $attachment_id ) ? $this->getSizedOriginalMediaGuid( $attachment_id, $source_language ) : $media_src;
// This if condition checks that the value for media GUID saved in $_POST is same as media subject to get updated.
// OR if the media src is equal to original src (in case of translated post contains same already uploaded media) so media that exists will be replaced with the translated one.
if (
( $media_src_same_as_pre_update( $media_src ) || $media_src_contains_pre_update( $media_src ) ) || ( $media_src === $original_media_guid )
) {
$items_to_translate[] = [
'attachment_id' => $attachment_id,
'translated_id' => $translated_id,
'media' => $media,
'mediaParser' => $media_parser,
'mediaSrc' => $media_src,
'target_language' => $target_language,
];
} else { // to handle reverting media to original.
if ( empty( $pre_update_translated_media_guid ) && $this->mediaSrcContainsMediaFileName( $translated_id, $media_src ) ) {
$text = $this->replace_image_src( $text, $media_src, $original_media_guid );
$text = $this->replace_att_class( $text, $translated_id, $attachment_id );
$text = $this->replace_att_in_block( $text, $translated_id, $attachment_id );
}
}
}
}
$this->image_translator->prefetchDataForFutureGetTranslatedImageCalls(
$this->getSourceLanguage( $source_language ),
array_map(
function( $source_item ) {
$item = $source_item;
$item['url'] = $this->getMediaParserImgSrc( $item['mediaParser'], $item['media'] );
return $item;
},
$items_to_translate
)
);
foreach ( $items_to_translate as $item_to_translate ) {
$attachment_id = $item_to_translate['attachment_id'];
$translated_id = $item_to_translate['translated_id'];
$media = $item_to_translate['media'];
$media_parser = $item_to_translate['mediaParser'];
$media_src = $item_to_translate['mediaSrc'];
$target_language = $item_to_translate['target_language'];
if ( isset( $attachment_id ) && $attachment_id ) {
$size = $this->media_sizes->get_attachment_size( $media );
$translated_src = $this->image_translator->get_translated_image( $attachment_id, $target_language, $size );
} else {
$translated_src = $this->get_translated_image_by_url( $media_parser, $target_language, $source_language, $media );
}
if ( $translated_src ) {
if ( $translated_src !== $media_src ) {
$text = $this->replace_image_src( $text, $media_src, $translated_src );
}
// to replace value in href if it couldn't be replaced in replace_image_src.
$text = $this->replaceAttributeInHref( $text, $media_src, $translated_src, $source_language );
}
if ( $attachment_id && $attachment_id !== $translated_id ) {
$text = $this->replace_att_class( $text, $attachment_id, $translated_id );
$text = $this->replace_att_in_block( $text, $attachment_id, $translated_id );
}
}
}
return $text;
}
private function getMediaGuid( $id ) {
return get_post_field( 'guid', $id );
}
private function mediaSrcContainsMediaFileName( $attachment_id, $media_src ) {
$guid = $this->getMediaGuid( $attachment_id );
$media_extension = substr( $guid, - 4 );
$media_filename = explode( $media_extension, basename( $guid ) )[0];
return \WPML\FP\Str::includes( $media_filename, $media_src );
}
private function getSizedOriginalMediaGuid( $attachment_id, $source_lang ) {
$original_media_guid = $this->getMediaGuid( $attachment_id );
$original_media_size = $this->media_sizes->get_image_size_from_url( $original_media_guid, $attachment_id );
return $this->image_translator->get_translated_image( $attachment_id, $source_lang, $original_media_size );
}
/**
* @param string $text
* @param string $from
* @param string $to
*
* @return string
*/
private function replace_image_src( $text, $from, $to ) {
return str_replace( $from, $to, $text );
}
/**
* @param string $text
* @param string $from
* @param string $to
*
* @return string
*/
private function replace_att_class( $text, $from, $to ) {
$pattern = '/\bwp-image-' . $from . '\b/u';
$replacement = 'wp-image-' . $to;
return preg_replace( $pattern, $replacement, $text );
}
/**
* @param string $text
* @param string $from
* @param string $to
*
* @return string
*/
private function replace_att_in_block( $text, $from, $to ) {
$pattern = '';
$blocks = [ 'wp:image', 'wp:file', 'wp:audio', 'wp:video' ];
foreach ( $blocks as $block ) {
if ( \WPML\FP\Str::startsWith( '<!-- ' . $block, $text ) ) {
// phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found
$pattern = '/<!-- ' . $block . ' ' . '{.*?"id":(' . $from . '),.*?-->/u';
}
}
$replacement = function ( $matches ) use ( $to ) {
return str_replace( '"id":' . $matches[1], '"id":' . $to, $matches[0] );
};
return (bool) strlen( $pattern ) ? preg_replace_callback( $pattern, $replacement, $text ) : $text;
}
/**
* Replaces value in href for classic images and files added in classic editor
*
* @param string $text
* @param string $from
* @param string $to
* @param string $source_lang
*
* @return array|string|string[]|null
*/
private function replaceAttributeInHref( $text, $from, $to, $source_lang ) {
$pattern = '/<a.*?href="(.*?)".*?>/u';
$attach_id = $this->image_translator->get_attachment_id_by_url( $from, $source_lang );
$from = get_post_field( 'guid', $attach_id );
$replacement = function ( $matches ) use ( $from, $to ) {
return str_replace( 'href="' . $from . '"', 'href="' . $to . '"', $matches[0] );
};
return preg_replace_callback( $pattern, $replacement, $text );
}
/**
* @param null|string $source_language
*
* @return string
*/
private function getSourceLanguage( $source_language ) {
if ( null === $source_language ) {
$source_language = wpml_get_current_language();
}
return $source_language;
}
/**
* @param WPML_Media_Element_Parser $media_parser
* @param array $img
*
* @return string
*/
private function getMediaParserImgSrc( $media_parser, $img ) {
return $media_parser->getMediaSrcFromAttributes( $img['attributes'] );
}
/**
* @param WPML_Media_Element_Parser $media_parser
* @param string $target_language
* @param string $source_language
* @param array $img
*
* @return bool|string
*/
private function get_translated_image_by_url( $media_parser, $target_language, $source_language, $img ) {
$source_language = $this->getSourceLanguage( $source_language );
$translated_src = $this->image_translator->get_translated_image_by_url(
$this->getMediaParserImgSrc( $media_parser, $img ),
$source_language,
$target_language
);
return $translated_src;
}
}
<?php
class WPML_Media_Translation_Status {
const NOT_TRANSLATED = 'media-not-translated';
const IN_PROGRESS = 'in-progress';
const TRANSLATED = 'media-translated';
const NEEDS_MEDIA_TRANSLATION = 'needs-media-translation';
const STATUS_PREFIX = '_translation_status_';
}
<?php
namespace WPML\Media\Factories;
use WPML\Media\Classes\WPML_Media_Classic_Audio_Parser;
use WPML\Media\Classes\WPML_Media_Classic_Video_Parser;
use WPML\Media\Classes\WPML_Media_File_Parser;
use WPML\Media\Classes\WPML_Media_Href_Parser;
use WPML\Media\Classes\WPML_Media_Image_Parser;
use WPML\Media\Classes\WPML_Non_Embedded_Pdf_Parser;
class WPML_Media_Element_Parser_Factory {
/**
* @var array[]
*/
private $availableMediaParsers = [
'img-block' => [ 'class-name' => WPML_Media_Image_Parser::class ],
'audio-block' => [ 'class-name' => WPML_Media_Image_Parser::class ],
'video-block' => [ 'class-name' => WPML_Media_Image_Parser::class ],
'file-block' => [ 'class-name' => WPML_Media_File_Parser::class ],
'non-embedded-pdf' => [ 'class-name' => WPML_Non_Embedded_Pdf_Parser::class ],
'classic-audio' => [ 'class-name' => WPML_Media_Classic_Audio_Parser::class ],
'classic-Video' => [ 'class-name' => WPML_Media_Classic_Video_Parser::class ],
'href' => [ 'class-name' => WPML_Media_Href_Parser::class ],
];
/**
* Returns array of media parsers according to post content.
*
* @param string $post_content
*
* @return array
*/
public function create( $post_content ) {
$parsers = [];
foreach ( $this->availableMediaParsers as $mediaParser ) {
$parserInstance = new $mediaParser['class-name']( $post_content );
if ( $parserInstance->validate() ) {
$parsers [ $mediaParser['class-name'] ] = $parserInstance;
}
}
return $parsers;
}
}
<?php
class WPML_Media_Populate_Media_Strings_Translations_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress;
if ( class_exists( 'WPML_Element_Translation_Package' ) ) {
return new WPML_Media_Populate_Media_Strings_Translations(
new WPML_Translation_Element_Factory( $sitepress ),
new WPML_Element_Translation_Package()
);
}
}
}
\ No newline at end of file
<?php
class WPML_Media_Populate_Media_Strings_Translations implements IWPML_Action {
/**
* @var WPML_Translation_Element_Factory
*/
private $translation_element_factory;
/**
* @var WPML_Element_Translation_Package
*/
private $translation_package;
public function __construct(
WPML_Translation_Element_Factory $translation_element_factory,
WPML_Element_Translation_Package $translation_package
) {
$this->translation_element_factory = $translation_element_factory;
$this->translation_package = $translation_package;
}
public function add_hooks() {
add_filter( 'wpml_tm_populate_prev_translation', array( $this, 'populate' ), 10, 3 );
}
public function populate( $prev_translation, $package, $lang ) {
if ( ! $prev_translation ) {
foreach ( $package['contents'] as $field => $data ) {
if ( $media_field = $this->is_media_field( $field ) ) {
$attachment = $this->translation_element_factory->create( $media_field['id'], 'post' );
$attachment_translation = $attachment->get_translation( $lang );
if ( $attachment_translation ) {
$original_id = (int) $media_field['id'];
$translation_id = $attachment_translation->get_id();
switch ( $media_field['field'] ) {
case 'title':
$translated_value = $this->get_post_field( 'post_title', $original_id, $translation_id );
break;
case 'caption':
$translated_value = $this->get_post_field( 'post_excerpt', $original_id, $translation_id );
break;
case 'description':
$translated_value = $this->get_post_field( 'post_content', $original_id, $translation_id );
break;
case 'alt_text':
$translated_value = get_post_meta( $translation_id, '_wp_attachment_image_alt', true );
if ( ! $translated_value ) {
$translated_value = get_post_meta( $original_id, '_wp_attachment_image_alt', true );
}
break;
default:
$translated_value = false;
}
if ( $translated_value ) {
$prev_translation[ $field ] = wpml_tm_create_translated_field(
'', $this->translation_package->encode_field_data( $translated_value ), true
);
}
}
}
}
}
return $prev_translation;
}
private function is_media_field( $field ) {
$media_field = array();
if ( preg_match( '#^media_([0-9]+)_([a-z_]+)$#', $field, $matches ) ) {
$media_field['id'] = $matches[1];
$media_field['field'] = $matches[2];
}
return $media_field;
}
/**
* @param string $field
* @param int $original_id
* @param int $translation_id
*
* @return string
*/
private function get_post_field( $field, $original_id, $translation_id ) {
$value = get_post_field( $field, $translation_id );
if ( ! $value ) {
$value = get_post_field( $field, $original_id );
}
return $value;
}
}
\ No newline at end of file
<?php
class WPML_Media_Post_Media_Usage_Factory implements IWPML_Backend_Action_Loader, IWPML_Frontend_Action_Loader {
public function create(){
global $sitepress;
return new WPML_Media_Post_Media_Usage(
$sitepress,
new WPML_Media_Post_With_Media_Files_Factory(),
new WPML_Media_Usage_Factory()
);
}
}
\ No newline at end of file
<?php
class WPML_Media_Post_Media_Usage implements IWPML_Action {
/** @see WPML_Post_Translation::save_post_actions() */
const PRIORITY_AFTER_CORE_SAVE_POST_ACTIONS = 200;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var WPML_Media_Post_With_Media_Files_Factory
*/
private $post_with_media_files_factory;
/**
* @var WPML_Media_Usage_Factory
*/
private $media_usage_factory;
public function __construct(
SitePress $sitepress,
WPML_Media_Post_With_Media_Files_Factory $post_with_media_files_factory,
WPML_Media_Usage_Factory $media_usage_factory
) {
$this->sitepress = $sitepress;
$this->post_with_media_files_factory = $post_with_media_files_factory;
$this->media_usage_factory = $media_usage_factory;
}
public function add_hooks() {
add_action( 'save_post', array( $this, 'update_media_usage' ), self::PRIORITY_AFTER_CORE_SAVE_POST_ACTIONS, 2 );
}
/**
* @param int $post_id
* @param WP_Post|null $post
*/
public function update_media_usage( $post_id, $post = null ) {
if ( null === $post ) {
$post = get_post( $post_id );
}
if ( $this->sitepress->get_wp_api()->constant( 'DOING_AUTOSAVE' )
|| ! $this->sitepress->is_translated_post_type( $post->post_type )
|| $post_id !== (int) $this->sitepress->get_original_element_id( $post_id, 'post_' . $post->post_type )
) {
return;
}
$media_ids = $this->post_with_media_files_factory->create( $post_id )->get_media_ids();
foreach ( $media_ids as $media_id ) {
$this->media_usage_factory->create( $media_id )->add_post( $post->ID );
}
}
}
\ No newline at end of file
<?php
class WPML_Media_Usage_Factory {
public function create( $attachment_id ) {
return new WPML_Media_Usage( $attachment_id );
}
}
<?php
class WPML_Media_Usage {
const FIELD_NAME = '_wpml_media_usage';
/**
* @var int
*/
private $attachment_id;
/**
* @var array
*/
private $usage;
/**
* @param int $attachment_id
*/
public function __construct( $attachment_id ) {
$this->attachment_id = $attachment_id;
$usage = get_post_meta( $this->attachment_id, self::FIELD_NAME, true );
$this->usage = empty( $usage ) ? array() : $usage;
}
/**
* @return array
*/
public function get_posts() {
return empty( $this->usage['posts'] ) ? array() : $this->usage['posts'];
}
/**
* @param int $post_id
*/
public function add_post( $post_id ) {
$posts = $this->get_posts();
$posts[] = $post_id;
$this->usage['posts'] = array_unique( $posts );
$this->update_usage();
}
/**
* @param int $post_id
*/
public function remove_post( $post_id ) {
$this->usage['posts'] = array_values( array_diff( (array) $this->usage['posts'], array( $post_id ) ) );
$this->update_usage();
}
private function update_usage() {
update_post_meta( $this->attachment_id, self::FIELD_NAME, $this->usage );
}
}
<?php
class WPML_Media_Help_Tab_Factory implements IWPML_Backend_Action_Loader {
public function create() {
return new WPML_Media_Help_Tab();
}
}
<?php
class WPML_Media_Help_Tab implements IWPML_Action {
public function add_hooks() {
add_action( 'admin_head', array( $this, 'add' ) );
}
public function add() {
$current_screen = get_current_screen();
if ( $this->is_media_related_screen( $current_screen ) ) {
$media_translation_dashboard = esc_html__( 'WPML &raquo; Media Translation', 'wpml-media' );
$wpml_translation_dashboard = esc_html__( 'WPML &raquo; Translation Management', 'wpml-media' );
$current_screen->add_help_tab(
array(
'id' => 'wpml-media-translation',
'title' => esc_html__( 'Translating Media', 'wpml-media' ),
'content' =>
'<p>' . esc_html__( 'There are two ways for you to translate Media:', 'wpml-media' ) . '</p>' .
'<ul>' .
'<li>' . sprintf(
esc_html__( 'Use the dashboard on the %s page to translate your images and other media files.', 'wpml-media' ),
$media_translation_dashboard
) . '</li>' .
'<li>' . sprintf(
esc_html__( 'Use the dashboard on the %s page to send pages that contain media, for translation.', 'wpml-media' ),
$wpml_translation_dashboard
) . '</li>' .
'</ul>' .
'</ul>' .
'<a href="https://wpml.org/documentation/getting-started-guide/media-translation/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlmedia">' . esc_html__( 'Learn more about WPML Media Translation', 'wpml-media' ) . '</a>',
)
);
}
}
private function is_media_related_screen( $current_screen ) {
$accepted_bases = array(
'wpml_page_wpml-media',
'upload',
'media',
'wpml_page_wpml-translation-management/menu/main',
);
return $current_screen && in_array( $current_screen->base, $accepted_bases );
}
}
<?php
/**
* Class WPML_Media_Menus_Factory
*/
class WPML_Media_Menus_Factory {
public function create() {
global $sitepress, $wpdb;
$wpml_wp_api = $sitepress->get_wp_api();
$wpml_media_path = $wpml_wp_api->constant( 'WPML_MEDIA_PATH' );
$template_service_loader = new WPML_Twig_Template_Loader( array( $wpml_media_path . '/templates/menus/' ) );
$pagination = new WPML_Admin_Pagination();
return new WPML_Media_Menus( $template_service_loader, $sitepress, $wpdb, $pagination );
}
}
<?php
class WPML_Media_Menus {
/**
* @var IWPML_Template_Service
*/
private $template_service;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var WPML_Admin_Pagination
*/
private $pagination;
/**
* WPML_Media_Menus constructor.
*
* @param WPML_Twig_Template_Loader $template_service
* @param SitePress $sitepress
* @param wpdb $wpdb
*/
public function __construct( WPML_Twig_Template_Loader $template_service, SitePress $sitepress, wpdb $wpdb, WPML_Admin_Pagination $pagination = null ) {
$this->template_service = $template_service;
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->pagination = $pagination;
}
public function display() {
global $wp_locale, $wpml_query_filter;
do_action( 'wpml_media_messages' );
do_action( 'wpml_media_menu' );
$menu_overrides = apply_filters( 'wpml_media_menu_overrides', array() );
if ( $menu_overrides ) {
foreach ( $menu_overrides as $menu_override ) {
call_user_func( $menu_override );
}
return;
}
$wpml_media_url = $this->sitepress->get_wp_api()->constant( 'WPML_MEDIA_URL' );
$wpml_media_version = $this->sitepress->get_wp_api()->constant( 'WPML_MEDIA_VERSION' );
wp_enqueue_style( OTGS_Assets_Handles::POPOVER_TOOLTIP );
wp_enqueue_script( OTGS_Assets_Handles::POPOVER_TOOLTIP );
wp_enqueue_style( 'wpml-media', $wpml_media_url . '/res/css/media-translation.css', array(), $wpml_media_version );
wp_enqueue_script(
'wpml-media',
$wpml_media_url . '/res/js/media-translation-popup.js',
array(
'jquery',
'jquery-ui-dialog',
),
$wpml_media_version,
true
);
$wpml_media_popup_strings = array(
'title' => esc_js( __( 'Media Translation', 'wpml-media' ) ),
'cancel' => esc_js( __( 'Cancel', 'wpml-media' ) ),
'save' => esc_js( __( 'Save media translation', 'wpml-media' ) ),
'status_labels' => WPML_Media_Translations_UI::get_translation_status_labels(),
);
wp_localize_script( 'wpml-media', 'wpml_media_popup', $wpml_media_popup_strings );
wp_enqueue_script( 'wpml-media-batch-url-translation', $wpml_media_url . '/res/js/batch-url-translation.js', array( 'jquery' ), $wpml_media_version, true );
$batch_translation_vars = array(
'complete' => esc_js( __( 'Scan complete!', 'wpml-media' ) ),
'is_st_enabled' => (bool) $this->sitepress->get_wp_api()->constant( 'WPML_ST_VERSION' ),
);
wp_localize_script( 'wpml-media-batch-url-translation', 'wpml_media_batch_translation', $batch_translation_vars );
wp_enqueue_script( OTGS_Assets_Handles::TABLE_STICKY_HEADER );
$media_translations_ui = new WPML_Media_Translations_UI(
$this->sitepress,
$this->wpdb,
$wp_locale,
$wpml_query_filter,
$this->pagination
);
$media_translations_ui->show();
}
}
<?php
class WPML_Media_Posts_Media_Flag_Notice_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress;
if ( current_user_can( 'manage_options' ) && ! WPML_Media::has_setup_run() && $sitepress->is_setup_complete()) {
return new WPML_Media_Posts_Media_Flag_Notice( $sitepress );
}
return null;
}
}
<?php
class WPML_Media_Posts_Media_Flag_Notice implements IWPML_Action {
const PREPARE_ACTION = 'wpml-media-has-media-flag-prepare';
const PROCESS_ACTION = 'wpml-media-has-media-flag';
const NOTICE_ID = 'wpml-media-posts-media-flag';
const NOTICE_GROUP = 'wpml-media';
/**
* @var SitePress
*/
private $sitepress;
/**
* WPML_Media_Has_Media_Notice constructor.
*
* @param SitePress $sitepress
*/
public function __construct( SitePress $sitepress ) {
$this->sitepress = $sitepress;
}
public function add_hooks() {
if ( $this->is_wpml_media_screen() ) {
add_filter( 'wpml_media_menu_overrides', array( $this, 'override_default_menu' ) );
} else {
add_action( 'admin_head', array( $this, 'add_top_notice' ) );
}
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_js' ) );
}
public function override_default_menu( $menu_elements ) {
$menu_elements[] = array( $this, 'render_menu' );
return $menu_elements;
}
public function enqueue_js() {
$wpml_media_url = $this->sitepress->get_wp_api()->constant( 'WPML_MEDIA_URL' );
wp_enqueue_script( 'wpml-media-setup', $wpml_media_url . '/res/js/wpml-media-posts-media-flag.js', array( 'jquery' ), false, true );
}
private function is_wpml_media_screen() {
return isset( $_GET['page'] ) && 'wpml-media' === $_GET['page'];
}
public function add_top_notice() {
/* translators: name ot WPML-Media plugin */
$wpml_media = '<strong>' . __( 'WPML Media Translation', 'wpml-media' ) . '</strong>';
/* translators: used to build a link in the "Click here to finish the setup" */
$here_text = _x( 'here', 'Used to build a link in the "Click here to finish the setup"', 'wpml-media' );
$here_link = '<a href="' . admin_url( 'admin.php?page=wpml-media' ) . '">' . $here_text . '</a>';
/* translators: %1$s will be replaced with a translation of "WPML Media Translation", while %2$s is a link with the translation of the word "here" */
$text = vsprintf(
esc_html__( 'The %1$s setup is almost complete. Click %2$s to finish the setup.', 'wpml-media' ),
array(
$wpml_media,
$here_link
)
);
$notice = new WPML_Notice( self::NOTICE_ID, $text, self::NOTICE_GROUP );
$notice->set_css_class_types( 'notice-warning' );
$notice->set_hideable( false );
$notice->set_dismissible( false );
$notice->set_collapsable( false );
$notice->add_exclude_from_page( 'wpml-media' );
$notice->add_capability_check( array( 'manage_options' ) );
$wpml_admin_notices = wpml_get_admin_notices();
$wpml_admin_notices->add_notice( $notice );
}
public function render_menu() {
?>
<div class="wrap wpml-media-setup">
<h2><?php esc_html_e( 'Setup required', 'wpml-media' ) ?></h2>
<div
id="wpml-media-posts-media-flag"
class="notice notice-warning"
style="padding-bottom:8px"
data-prepare-action="<?php echo esc_attr( self::PREPARE_ACTION ); ?>"
data-prepare-nonce="<?php echo wp_create_nonce( self::PREPARE_ACTION ); ?>"
data-process-action="<?php echo esc_attr( self::PROCESS_ACTION ); ?>"
data-process-nonce="<?php echo wp_create_nonce( self::PROCESS_ACTION ); ?>"
>
<p>
<?php esc_html_e( 'In order to get WPML Media Translation fully working, you need to run this set up which takes only a few moments depending on the total number of posts in your WordPress install.', 'wpml-media' ); ?>
</p>
<input type="button" class="button-primary alignright"
value="<?php esc_attr_e( 'Finish setup', 'wpml-media' ) ?>"/>
<span class="spinner"> </span>
<p class="alignleft status description"></p>
<br clear="all"/>
</div>
</div>
<?php
}
}
<?php
/**
* Class WPML_Media_Screen_Options_Factory
*/
class WPML_Media_Screen_Options_Factory implements IWPML_Backend_Action_Loader {
/**
* @return IWPML_Action|WPML_Media_Screen_Options
*/
public function create() {
$options = array();
if ( $this->is_translation_dashboard() ) {
$option_name = 'wpml_media_translation_dashboard_items_per_page';
$options[] = array(
'key' => 'per_page',
'args' => array(
'label' => __( 'Number of items per page:', 'wpml-media' ),
'default' => get_option( $option_name, 20 ),
'option' => $option_name,
),
);
}
if ( $options ) {
return new WPML_Media_Screen_Options( $options );
}
return null;
}
/**
* @return bool
*/
private function is_translation_dashboard() {
return ! isset( $_GET['sm'] ) || 'media-translation' === $_GET['sm'];
}
}
<?php
class WPML_Media_Screen_Options implements IWPML_Action {
/**
* @var array
*/
private $options = array();
/**
* WPML_Media_Screen_Options constructor.
*
* @param array $options
*/
public function __construct( $options ) {
$this->options = $options;
}
public function add_hooks() {
add_action( 'load-wpml_page_wpml-media', array( $this, 'add_options' ) );
add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );
}
public function add_options() {
foreach ( $this->options as $option ) {
add_screen_option( $option['key'], $option['args'] );
}
}
public function set_screen_option( $status, $option_name, $value ) {
if ( $this->is_valid_option( $option_name ) ) {
update_option( $option_name, $value );
}
}
private function is_valid_option( $option_name ) {
$valid = false;
foreach ( $this->options as $option ) {
if ( $option_name === $option['args']['option'] ) {
$valid = true;
break;
}
}
return $valid;
}
}
<?php
/**
* Class WPML_Media_Editor_Notices_Factory
*/
class WPML_Media_Editor_Notices_Factory implements IWPML_Backend_Action_Loader {
public function create() {
return new WPML_Media_Editor_Notices();
}
}
<?php
/**
* Class WPML_Media_Editor_Notices
*/
class WPML_Media_Editor_Notices implements IWPML_Action {
const TEXT_EDIT_NOTICE_DISMISSED = '_wpml_media_editor_text_edit_notice_dismissed';
public function add_hooks() {
add_action( 'wp_ajax_wpml_media_editor_text_edit_notice_dismissed', array( $this, 'dismiss_texts_change_notice' ) );
}
public function dismiss_texts_change_notice() {
update_user_meta( get_current_user_id(), self::TEXT_EDIT_NOTICE_DISMISSED, 1 );
wp_send_json_success();
}
}
<?php
/**
* Class WPML_Media_Translations_UI
*/
class WPML_Media_Translations_UI extends WPML_Templates_Factory {
const PREVIEW_MAX_WIDTH = 800;
const PREVIEW_MAX_HEIGHT = 600;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var WP_Locale
*/
private $wp_locale;
/**
* @var WPML_Query_Filter
*/
private $wpml_query_filter;
/**
* @var WPML_Admin_Pagination
*/
private $pagination;
/**
* @var array
*/
private $query_args = array();
/**
* WPML_Media_Translations_UI constructor.
*
* @param SitePress $sitepress
* @param wpdb $wpdb
* @param WP_Locale $wp_locale
* @param WPML_Query_Filter $wpml_query_filter
* @param WPML_Admin_Pagination $pagination
*/
public function __construct(
SitePress $sitepress,
wpdb $wpdb,
WP_Locale $wp_locale,
WPML_Query_Filter $wpml_query_filter,
WPML_Admin_Pagination $pagination
) {
parent::__construct();
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->wp_locale = $wp_locale;
$this->wpml_query_filter = $wpml_query_filter;
$this->pagination = $pagination;
}
/**
* @return array
*/
public function get_model() {
$this->set_query_args();
$languages = $this->get_languages();
$model = array(
'strings' => array(
'heading' => __( 'Media Translation', 'wpml-media' ),
'filter_by_date' => __( 'Filter by date', 'wpml-media' ),
'all_dates' => __( 'All dates', 'wpml-media' ),
'in' => __( 'in', 'wpml_media' ),
'to' => __( 'to', 'wpml_media' ),
'filter_by_status' => __( 'Filter by translation status', 'wpml-media' ),
'status_all' => __( 'All translation statuses', 'wpml-media' ),
'status_not' => __( 'Media file not translated', 'wpml-media' ),
'status_translated' => __( 'Translated media uploaded', 'wpml-media' ),
'status_in_progress' => __( 'Translation in progress', 'wpml-media' ),
'status_needs_translation' => __( 'Needs media file translation', 'wpml-media' ),
'filter_by_language' => __( 'Filter by language', 'wpml-media' ),
'any_language' => __( 'Any language', 'wpml-media' ),
'search_media' => __( 'Search Media:', 'wpml-media' ),
'search_placeholder' => __( 'Title, caption or description', 'wpml-media' ),
'search_button_label' => __( 'Filter', 'wpml-media' ),
'original_language' => __( 'Original language', 'wpml-media' ),
'no_attachments' => __( 'No attachments found', 'wpml-media' ),
'add_translation' => __( 'Add media file translation', 'wpml-media' ),
'edit_translation' => __( 'Edit %s translation', 'wpml-media' ),
'original' => __( 'Original:', 'wpml-media' ),
'translation' => __( 'Translation:', 'wpml-media' ),
'file' => __( 'File', 'wpml-media' ),
'name' => __( 'Name', 'wpml-media' ),
'caption' => __( 'Caption', 'wpml-media' ),
'alt_text' => __( 'Alt text', 'wpml-media' ),
'description' => __( 'Description', 'wpml-media' ),
'copy_from_original' => __( 'Copy from original', 'wpml-media' ),
'upload_translated_media' => __( 'Upload translated media file', 'wpml-media' ),
'use_different_file' => __( 'Use a different file', 'wpml-media' ),
'revert_to_original' => __( 'Revert to original', 'wpml-media' ),
'restore_original_media' => __( 'Restore original media file', 'wpml-media' ),
'statuses' => self::get_translation_status_labels(),
'texts_change_notice' => __( 'Any changes you make to the text here will not affect any previous publications of this media on your website. This edited version will only appear if you select it from the library to be embedded.', 'wpml-media' ),
),
'months' => $this->get_months(),
'selected_month' => isset( $this->query_args['m'] ) ? (int) $this->query_args['m'] : 0,
'selected_status' => isset( $this->query_args['status'] ) ? $this->query_args['status'] : '',
'from_language' => isset( $this->query_args['slang'] ) ? $this->query_args['slang'] : '',
'to_language' => isset( $this->query_args['tlang'] ) ? $this->query_args['tlang'] : '',
'statuses' => array(
'not_translated' => WPML_Media_Translation_Status::NOT_TRANSLATED,
'in_progress' => WPML_Media_Translation_Status::IN_PROGRESS,
'translated' => WPML_Media_Translation_Status::TRANSLATED,
'needs_translation' => WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION,
),
'search' => isset( $this->query_args['s'] ) ? $this->query_args['s'] : '',
'languages' => $languages,
'attachments' => $this->get_attachments( $languages ),
'nonce' => wp_nonce_field( 'media-translation', 'wpnonce', false, false ),
'pagination' => $this->get_pagination(),
'target_language' => $this->should_filter_by_target_language() ? $this->query_args['tlang'] : '',
'batch_translation' => $this->get_batch_translation(),
'show_text_change_notice' => ! get_user_meta( get_current_user_id(), WPML_Media_Editor_Notices::TEXT_EDIT_NOTICE_DISMISSED, true ),
);
return $model;
}
public static function get_translation_status_labels() {
return array(
WPML_Media_Translation_Status::NOT_TRANSLATED => __( 'Not translated', 'wpml-media' ),
WPML_Media_Translation_Status::IN_PROGRESS => __( 'In progress', 'wpml-media' ),
WPML_Media_Translation_Status::TRANSLATED => __( 'Translated', 'wpml-media' ),
WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION => __( 'Needs translation', 'wpml-media' ),
);
}
private function set_query_args() {
$arg_keys = array( 'm', 'status', 'slang', 'tlang', 's', 'paged' );
foreach ( $arg_keys as $key ) {
if ( isset( $_GET[ $key ] ) ) {
$this->query_args[ $key ] = sanitize_text_field( $_GET[ $key ] );
}
}
}
/**
* @return array
*/
private function get_months() {
$months = array();
$month_results = $this->wpdb->get_results(
"
SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
FROM {$this->wpdb->posts}
WHERE post_type = 'attachment'
ORDER BY post_date DESC
"
);
foreach ( $month_results as $month ) {
$months[] = array(
'id' => $month->year . zeroise( $month->month, 2 ),
'label' => sprintf( __( '%1$s %2$d' ), $this->wp_locale->get_month( $month->month ), $month->year ),
);
}
return $months;
}
/**
* @return array
*/
private function get_languages() {
$languages = array();
$active_languages = $this->sitepress->get_active_languages();
foreach ( $active_languages as $language ) {
$languages[ $language['code'] ] = array(
'name' => $language['display_name'],
'flag' => $this->sitepress->get_flag_url( $language['code'] ),
);
}
return $languages;
}
private function get_items_per_page() {
return get_option( 'wpml_media_translation_dashboard_items_per_page', 20 );
}
/**
* @param array $languages
*
* @return array
*/
private function get_attachments( $languages ) {
$attachments = array();
$args = array(
'post_type' => 'attachment',
'orderby' => 'ID',
'order' => 'DESC',
'posts_per_page' => $this->get_items_per_page(),
);
$args = array_merge( $args, $this->query_args );
if ( $this->should_filter_by_status() ) {
$args['meta_query'] = array(
'key' => '_media_translation_status',
'value' => $this->query_args['status'],
);
}
$this->add_query_filters();
$attachment_posts = get_posts( $args );
$this->remove_query_filters();
foreach ( $attachment_posts as $attachment ) {
$attachment_id = $attachment->ID;
$post_element = new WPML_Post_Element( $attachment_id, $this->sitepress );
$media_file_original = get_post_meta( $attachment_id, '_wp_attached_file', true );
$translations = array();
$is_image = (int) ( 0 === strpos( $attachment->post_mime_type, 'image/' ) );
foreach ( $languages as $code => $language ) {
$translation = $post_element->get_translation( $code );
if ( $translation ) {
$translation_post = $translation->get_wp_object();
$media_file_translated = get_post_meta( $translation->get_id(), '_wp_attached_file', true );
$translations[ $code ] = array(
'id' => $translation->get_id(),
'file_name' => basename( $media_file_translated ),
'title' => $translation_post->post_title,
'caption' => $translation_post->post_excerpt,
'description' => $translation_post->post_content,
'alt' => get_post_meta( $translation->get_id(), '_wp_attachment_image_alt', true ),
'thumb' => $this->get_attachment_thumb( $translation->get_id(), $is_image ),
'media_is_translated' => $media_file_translated && $media_file_translated !== $media_file_original,
'status' => $this->get_translation_status( $attachment_id, $translation ),
);
} else {
$translations[ $code ] = array(
'status' => WPML_Media_Translation_Status::NOT_TRANSLATED,
);
}
}
$attachments[] = array(
'post' => $attachment,
'mime_type' => $is_image ? 'image/*' : $attachment->post_mime_type,
'is_image' => $is_image,
'file_name' => basename( $media_file_original ),
'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
'meta' => get_post_meta( $attachment_id, '_wp_attachment_metadata', true ),
'language' => $post_element->get_language_code(),
'thumb' => $this->get_attachment_thumb( $attachment_id, $is_image ),
'url' => $is_image ? $this->get_attachment_url( $attachment_id ) : '',
'translations' => $translations,
'preview' => [
'width' => self::PREVIEW_MAX_WIDTH,
'height' => self::PREVIEW_MAX_HEIGHT,
],
);
}
return $attachments;
}
/**
* @param int $attachment_id
*
* @return array
*/
private function get_attachment_url( $attachment_id ) {
$image = wp_get_attachment_image_src( $attachment_id, [ self::PREVIEW_MAX_WIDTH, self::PREVIEW_MAX_HEIGHT ] );
return $image[0];
}
/**
* @param int $attachment_id
* @param bool $is_image
*
* @return array
*/
private function get_attachment_thumb( $attachment_id, $is_image = true ) {
$image = wp_get_attachment_image_src( $attachment_id, 'thumbnail', true );
$thumb = array(
'src' => $image ? $image[0] : '',
'width' => $is_image ? 60 : $image[1],
'height' => $is_image ? 60 : $image[2],
);
return $thumb;
}
public function set_total_items_in_pagination( $query ) {
$query_count = preg_replace(
'/^SELECT /',
'SELECT SQL_CALC_FOUND_ROWS ',
trim( $query )
);
$this->wpdb->get_results( $query_count );
$this->pagination->set_total_items( $this->wpdb->get_var( 'SELECT FOUND_ROWS()' ) );
return $query;
}
private function get_pagination() {
$this->pagination->set_items_per_page( $this->get_items_per_page() );
$current_page = isset( $this->query_args['paged'] ) ? $this->query_args['paged'] : 1;
$this->pagination->set_current_page( $current_page );
$model = array(
'strings' => array(
'list_navigation' => __( 'Navigation', 'wpml-media' ),
'of' => __( 'of', 'wpml-media' ),
),
'pagination' => array(
'get_first_page_url' => $this->pagination->get_first_page_url(),
'first_page' => __( 'First page', 'wpml-media' ),
'get_previous_page_url' => $this->pagination->get_previous_page_url(),
'previous_page' => __( 'Previous page', 'wpml-media' ),
'get_current_page' => $this->pagination->get_current_page(),
'get_total_pages' => $this->pagination->get_total_pages(),
'get_next_page_url' => $this->pagination->get_next_page_url(),
'next_page' => __( 'Next page', 'wpml-media' ),
'get_last_page_url' => $this->pagination->get_last_page_url(),
'last_page' => __( 'Last page', 'wpml-media' ),
),
'total_items' => sprintf(
_n( '%s item', '%s items', $this->pagination->get_total_items() ),
$this->pagination->get_total_items()
),
);
return $model;
}
private function get_batch_translation() {
$model = array(
'strings' => array(
'close' => __( 'Close', 'wpml-media' ),
'was_replaced' => __( 'The media that you uploaded was replaced in these translated posts:', 'wpml-media' ),
'other_posts' => __( 'The same media might be used in other posts too. Do you want to scan and replace it?', 'wpml-media' ),
'without_usage' => __( 'The media that you uploaded will be used in future post translations. The same media might be used in already existing posts. Do you want to scan and replace it now?', 'wpml-media' ),
'scan_for_this_media' => __( 'Scan for content that has specifically this media (faster)', 'wpml-media' ),
'scan_for_all_media' => __( 'Scan for content that has any of the media files that I translated (takes more time)', 'wpml-media' ),
'button_label' => _x( 'Scan & Replace', 'Button label (verb)', 'wpml-media' ),
),
);
return $model;
}
private function add_query_filters() {
remove_filter( 'posts_join', array( $this->wpml_query_filter, 'posts_join_filter' ), 10 );
remove_filter( 'posts_where', array( $this->wpml_query_filter, 'posts_where_filter' ), 10 );
add_filter( 'posts_join', array( $this, 'filter_request_clause_join' ), PHP_INT_MAX );
add_filter( 'posts_where', array( $this, 'filter_request_clause_where' ), PHP_INT_MAX );
add_filter( 'posts_request', array( $this, 'set_total_items_in_pagination' ), - PHP_INT_MAX );
}
private function remove_query_filters() {
add_filter( 'posts_join', array( $this->wpml_query_filter, 'posts_join_filter' ), 10, 2 );
add_filter( 'posts_where', array( $this->wpml_query_filter, 'posts_where_filter' ), 10, 2 );
remove_filter( 'posts_join', array( $this, 'filter_request_clause_join' ), PHP_INT_MAX );
remove_filter( 'posts_where', array( $this, 'filter_request_clause_where' ), PHP_INT_MAX );
remove_filter( 'posts_request', array( $this, 'set_total_items_in_pagination' ), - PHP_INT_MAX );
}
public function filter_request_clause_join( $join ) {
$join .= " LEFT JOIN {$this->wpdb->prefix}icl_translations icl_translations_source
ON icl_translations_source.element_id = {$this->wpdb->posts}.ID ";
if ( $this->should_filter_by_status() ) {
if ( $this->should_filter_by_target_language() ) {
$join .= $this->wpdb->prepare(
" LEFT JOIN {$this->wpdb->postmeta} post_meta
ON icl_translations_source.element_id = post_meta.post_id
AND post_meta.meta_key = %s
",
WPML_Media_Translation_Status::STATUS_PREFIX . $this->query_args['tlang']
);
} else {
$active_language = $this->sitepress->get_active_languages();
$default_lanuage = $this->sitepress->get_default_language();
foreach ( $active_language as $language ) {
if ( $language['code'] !== $default_lanuage ) {
$sanitized_code = str_replace( '-', '_', $language['code'] );
$join .= $this->wpdb->prepare(
" LEFT JOIN {$this->wpdb->postmeta} post_meta_{$sanitized_code}
ON {$this->wpdb->posts}.ID = post_meta_{$sanitized_code}.post_id
AND post_meta_{$sanitized_code}.meta_key=%s",
WPML_Media_Translation_Status::STATUS_PREFIX . $language['code']
);
}
}
}
} else {
if ( $this->should_filter_by_target_language() ) {
$join .= " JOIN {$this->wpdb->prefix}icl_translations icl_translations_target
ON icl_translations_target.trid = icl_translations_source.trid
AND icl_translations_target.language_code='{$this->query_args['tlang']}'";
}
}
return $join;
}
public function filter_request_clause_where( $where ) {
$where .= " AND icl_translations_source.element_type='post_attachment'
AND icl_translations_source.source_language_code IS NULL ";
if ( ! empty( $this->query_args['slang'] ) && $this->query_args['slang'] !== 'all' ) {
$where .= $this->wpdb->prepare( ' AND icl_translations_source.language_code = %s ', $this->query_args['slang'] );
}
if ( $this->should_filter_by_status() ) {
if ( $this->should_filter_by_target_language() ) {
if ( $this->query_args['status'] === WPML_Media_Translation_Status::NOT_TRANSLATED ) {
$where .= $this->wpdb->prepare(
' AND (
post_meta.meta_value IS NULL OR
post_meta.meta_value = %s OR
post_meta.meta_value = %s OR
post_meta.meta_value = %s
)',
WPML_Media_Translation_Status::NOT_TRANSLATED,
WPML_Media_Translation_Status::IN_PROGRESS,
WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION
);
} else {
$where .= $this->wpdb->prepare( ' AND post_meta.meta_value = %s', $this->query_args['status'] );
}
} else {
$active_language = $this->sitepress->get_active_languages();
$default_language = $this->sitepress->get_default_language();
if ( $this->query_args['status'] === WPML_Media_Translation_Status::TRANSLATED ) {
foreach ( $active_language as $language ) {
$sanitized_code = str_replace( '-', '_', $language['code'] );
if ( $language['code'] !== $default_language ) {
$where .= $this->wpdb->prepare(
"AND post_meta_{$sanitized_code}.meta_value = %s",
WPML_Media_Translation_Status::TRANSLATED
);
}
}
} elseif ( $this->query_args['status'] === WPML_Media_Translation_Status::NOT_TRANSLATED ) {
$where .= 'AND ( 0 ';
foreach ( $active_language as $language ) {
$sanitized_code = str_replace( '-', '_', $language['code'] );
if ( $language['code'] !== $default_language ) {
$where .= $this->wpdb->prepare(
"
OR post_meta_{$sanitized_code}.meta_value = %s
OR post_meta_{$sanitized_code}.meta_value IS NULL",
$this->query_args['status']
);
}
}
$where .= ') ';
} else {
$where .= 'AND ( 0 ';
foreach ( $active_language as $language ) {
$sanitized_code = str_replace( '-', '_', $language['code'] );
if ( $language['code'] !== $default_language ) {
$where .= $this->wpdb->prepare(
"
OR post_meta_{$sanitized_code}.meta_value = %s",
$this->query_args['status']
);
}
}
$where .= ') ';
}
}
}
return $where;
}
private function should_filter_by_status() {
return isset( $this->query_args['status'] ) && $this->query_args['status'] !== '';
}
private function should_filter_by_target_language() {
return isset( $this->query_args['tlang'] ) && $this->query_args['tlang'] !== '';
}
protected function init_template_base_dir() {
$this->template_paths = array(
WPML_MEDIA_PATH . '/templates/menus/',
WPML_PLUGIN_PATH . '/templates/pagination/',
);
}
/**
* @return string
*/
public function get_template() {
return 'media-translation.twig';
}
/**
* @param $attachment_id
* @param $translation
*
* @return mixed|string
*/
private function get_translation_status( $attachment_id, $translation ) {
$translation_status = get_post_meta(
$attachment_id,
WPML_Media_Translation_Status::STATUS_PREFIX . $translation->get_language_code(),
true
);
if ( ! $translation_status ) {
$translation_status = WPML_Media_Translation_Status::NOT_TRANSLATED;
}
return $translation_status;
}
}
<?php
/**
* @author OnTheGo Systems
*/
class WPML_Media_Privacy_Content_Factory implements IWPML_Backend_Action_Loader {
/**
* @return IWPML_Action
*/
public function create() {
return new WPML_Media_Privacy_Content();
}
}
<?php
/**
* @author OnTheGo Systems
*/
class WPML_Media_Privacy_Content extends WPML_Privacy_Content {
/**
* @return string
*/
protected function get_plugin_name() {
return 'WPML Media Translation';
}
/**
* @return string|array
*/
protected function get_privacy_policy() {
return __( 'WPML Media Translation will send the email address and name of each manager and assigned translator as well as the content itself to Advanced Translation Editor and to the translation services which are used.', 'wpml-media' );
}
}
<?php
class WPML_Media_Set_Initial_Language_Factory implements IWPML_Backend_Action_Loader {
public function create() {
global $sitepress, $wpdb;
return new WPML_Media_Set_Initial_Language( $wpdb, $sitepress->get_default_language() );
}
}
<?php
/**
* Class WPML_Media_Set_Initial_Language
*/
class WPML_Media_Set_Initial_Language implements IWPML_Action {
/**
* @var wpdb
*/
private $wpdb;
/**
* @var string
*/
private $language;
/**
* WPML_Media_Set_Initial_Language constructor.
*
* @param wpdb $wpdb
* @param string $language
*/
public function __construct( wpdb $wpdb, $language ) {
$this->wpdb = $wpdb;
$this->language = $language;
}
public function add_hooks() {
add_action( 'wp_ajax_wpml_media_set_initial_language', array( $this, 'set' ) );
}
public function set() {
$this->update_db();
$message = __( 'Setting language to media: done!', 'wpml-media' );
wp_send_json_success(
array(
'message' => $message,
)
);
}
public function update_db() {
$maxtrid = $this->wpdb->get_var( "SELECT MAX(trid) FROM {$this->wpdb->prefix}icl_translations" );
$this->wpdb->query(
$this->wpdb->prepare(
"
INSERT INTO {$this->wpdb->prefix}icl_translations
(element_type, element_id, trid, language_code, source_language_code)
SELECT 'post_attachment', ID, %d + ID, %s, NULL
FROM {$this->wpdb->posts} p
LEFT JOIN {$this->wpdb->prefix}icl_translations t
ON p.ID = t.element_id AND t.element_type = 'post_attachment'
WHERE post_type = 'attachment' AND t.translation_id IS NULL",
$maxtrid,
$this->language
)
);
}
}
<?php
class WPML_Media_2_3_0_Migration {
const FLAG = 'wpml_media_2_3_migration';
const BATCH_SIZE = 200;
const MAX_BATCH_REQUEST_TIME = 5;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var SitePress
*/
private $sitepress;
/**
* WPML_Media_2_3_0_Migration constructor.
*
* @param wpdb $wpdb
* @param SitePress $sitepress
*/
public function __construct( wpdb $wpdb, SitePress $sitepress ) {
$this->wpdb = $wpdb;
$this->sitepress = $sitepress;
}
public static function migration_complete() {
return WPML_Media::get_setting( self::FLAG );
}
private function mark_migration_complete() {
return WPML_Media::update_setting( self::FLAG, 1 );
}
public function is_required() {
if ( $this->wpdb->get_var( "SELECT COUNT(ID) FROM {$this->wpdb->posts} WHERE post_type='attachment'" ) ) {
return true;
}
self::mark_migration_complete();
return false;
}
public function add_hooks() {
add_filter( 'wpml_media_menu_overrides', array( $this, 'override_default_menu' ) );
add_action( 'wp_ajax_wpml_media_2_3_0_upgrade', array( $this, 'run_upgrade' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_js' ) );
}
public function override_default_menu( $menu_elements ) {
$menu_elements[] = array( $this, 'render_menu' );
return $menu_elements;
}
public function maybe_show_admin_notice() {
if ( is_admin() && ! $this->is_wpml_media_screen() ) {
add_action( 'admin_notices', array( $this, 'render_menu' ) );
}
}
private function is_wpml_media_screen() {
return isset( $_GET['page'] ) && $_GET['page'] === 'wpml-media';
}
public function enqueue_js() {
$wpml_media_url = $this->sitepress->get_wp_api()->constant( 'WPML_MEDIA_URL' );
wp_enqueue_script( 'wpml-media-2-3-0-upgrade', $wpml_media_url . '/res/js/upgrade/upgrade-2-3-0.js', array( 'jquery' ), false, true );
}
public function render_menu() {
if ( $this->is_wpml_media_screen() ) : ?>
<div class="wrap wrap-wpml-media-upgrade">
<h2><?php esc_html_e( 'Upgrade required', 'wpml-media' ); ?></h2>
<?php endif; ?>
<div class="notice notice-warning" id="wpml-media-2-3-0-update" style="padding-bottom:8px">
<p>
<?php
printf(
esc_html__( 'The %1$sWPML Media%2$s database needs updating. Please run the updater and leave the tab open until it completes.', 'wpml-media' ),
'<strong>',
'</strong>'
);
?>
</p>
<input type="button" class="button-primary alignright" value="<?php echo esc_attr_x( 'Update', 'Update button label', 'wpml-media' ); ?>" />
<input type="hidden" name="nonce" value="<?php echo wp_create_nonce( 'wpml-media-2-3-0-update' ); ?>" />
<span class="spinner"></span>
<p class="alignleft status description"></p><br clear="all" />
</div>
<?php if ( $this->is_wpml_media_screen() ) : ?>
</div>
<?php
endif;
}
private function reset_new_content_settings() {
$wpml_media_settings = get_option( '_wpml_media' );
// reset (will not remove since it's used by WCML)
$wpml_media_settings['new_content_settings']['always_translate_media'] = 0;
$wpml_media_settings['new_content_settings']['duplicate_media'] = 0;
$wpml_media_settings['new_content_settings']['duplicate_featured'] = 0;
update_option( '_wpml_media', $wpml_media_settings );
}
public function run_upgrade() {
if ( isset( $_POST['nonce'] ) && ( $_POST['nonce'] === wp_create_nonce( 'wpml-media-2-3-0-update' ) ) ) {
$step = isset( $_POST['step'] ) ? $_POST['step'] : '';
if ( 'reset-new-content-settings' === $step ) {
$this->reset_new_content_settings();
wp_send_json_success(
array( 'status' => esc_html__( 'Reset new content duplication settings', 'wpml-media' ) )
);
} elseif ( 'migrate-attachments' === $step ) {
$offset = isset( $_POST['offset'] ) ? (int) $_POST['offset'] : 0;
$batch_size = $this->get_dynamic_batch_size( $_POST );
$left = $this->migrate_attachments( $offset, $batch_size );
if ( $left ) {
$status = sprintf(
esc_html__( 'Updating attachments translation status: %d remaining.', 'wpml-media' ),
$left
);
$continue = 1;
$offset += $batch_size;
} else {
$this->mark_migration_complete();
$status = esc_html__( 'Update complete!', 'wpml-media' );
$continue = 0;
$offset = 0;
}
wp_send_json_success(
array(
'status' => $status,
'goon' => $continue,
'offset' => $offset,
'timestamp' => microtime( true ),
)
);
} else {
wp_send_json_error( array( 'error' => 'Invalid step' ) );
}
} else {
wp_send_json_error( array( 'error' => 'Invalid nonce' ) );
}
}
private function migrate_attachments( $offset = 0, $batch_size = self::BATCH_SIZE ) {
$sql = "SELECT SQL_CALC_FOUND_ROWS p.ID
FROM {$this->wpdb->posts} p
JOIN {$this->wpdb->prefix}icl_translations t
ON t.element_id = p.ID AND p.post_type='attachment'
WHERE t.source_language_code IS NULL
LIMIT %d, %d";
$sql_prepared = $this->wpdb->prepare( $sql, $offset, $batch_size );
$original_attachments = $this->wpdb->get_results( $sql_prepared );
$total_attachments = $this->wpdb->get_var( 'SELECT FOUND_ROWS() ' );
if ( $original_attachments ) {
foreach ( $original_attachments as $attachment ) {
$post_element = new WPML_Post_Element( $attachment->ID, $this->sitepress );
$translations = $post_element->get_translations();
$media_file = get_post_meta( $attachment->ID, '_wp_attached_file', true );
foreach ( $translations as $translation ) {
if ( (int) $attachment->ID !== $translation->get_id() ) {
$media_translation_status = WPML_Media_Translation_Status::NOT_TRANSLATED;
$media_file_translation = get_post_meta( $translation->get_id(), '_wp_attached_file', true );
if ( $media_file_translation !== $media_file ) {
$media_translation_status = WPML_Media_Translation_Status::TRANSLATED;
}
update_post_meta(
$attachment->ID,
WPML_Media_Translation_Status::STATUS_PREFIX . $translation->get_language_code(),
$media_translation_status
);
}
}
}
}
$left = max( 0, $total_attachments - $offset );
return $left;
}
private function get_dynamic_batch_size( $request ) {
$batch_size_factor = isset( $request['batch_size_factor'] ) ? (int) $request['batch_size_factor'] : 1;
if ( ! empty( $request['timestamp'] ) ) {
$elapsed_time = microtime( true ) - (float) $request['timestamp'];
if ( $elapsed_time < self::MAX_BATCH_REQUEST_TIME ) {
$batch_size_factor ++;
} else {
$batch_size_factor = max( 1, $batch_size_factor - 1 );
}
}
return self::BATCH_SIZE * $batch_size_factor;
}
}
<?php
define( 'WPML_MEDIA_FOLDER', basename( WPML_MEDIA_PATH ) );
define( 'WPML_MEDIA_URL', plugins_url( '', dirname( __FILE__ ) ) );
<?php
class WPML_Media_Dependencies {
function check() {
$all_ok = true;
// Check if WPML is active. If not display warning message and don't load WPML-media
if ( ! defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE ) {
add_action( 'admin_notices', array( $this, '_no_wpml_warning' ) );
$all_ok = false;
}
if ( ! WPML_Core_Version_Check::is_ok( WPML_MEDIA_PATH . '/wpml-dependencies.json' ) ) {
$all_ok = false;
}
if ( ! $all_ok ) {
return false;
}
return true;
}
function _no_wpml_warning() { ?>
<div class="message error wpml-media-inactive"><p>
<?php
printf(
__( 'WPML Media is enabled but not effective. It requires <a href="%s">WPML</a> in order to work.', 'wpml-media' ),
'https://wpml.org/'
);
?>
</p></div>
<?php
}
}
<?php
class WPML_Media_Upgrade {
private static $versions = array(
'2.0',
'2.0.1',
);
static function run() {
global $wpdb;
// Workaround, as for some reasons, get_option() doesn't work only in this case
$wpml_media_settings_prepared = $wpdb->prepare( "select option_value from {$wpdb->prefix}options where option_name = %s", '_wpml_media' );
$wpml_media_settings = $wpdb->get_col( $wpml_media_settings_prepared );
$needs_version_update = true;
// Do not run upgrades if this is a new install (i.e.: plugin has no settings)
if ( $wpml_media_settings || get_option( '_wpml_media_starting_help' ) ) {
$current_version = WPML_Media::get_setting( 'version', null );
if ( $current_version ) {
$needs_version_update = version_compare( $current_version, WPML_MEDIA_VERSION, '<' );
self::run_upgrades_before_2_3_0( $current_version );
} elseif ( self::is_media_version_older_than_2_0() ) {
$needs_version_update = true;
self::run_upgrades_before_2_3_0( '1.6' );
}
}
if ( $needs_version_update ) {
WPML_Media::update_setting( 'version', WPML_MEDIA_VERSION );
}
// Blocking database migration
self::upgrade_2_3_0();
}
/** @param int $current_version */
private static function run_upgrades_before_2_3_0( $current_version ) {
if ( version_compare( $current_version, '2.3.0', '<' ) ) {
foreach ( self::$versions as $version ) {
if ( version_compare( $version, WPML_MEDIA_VERSION, '<=' ) && version_compare( $version, $current_version, '>' ) ) {
$upgrade_method = 'upgrade_' . str_replace( '.', '_', $version );
if ( method_exists( __CLASS__, $upgrade_method ) ) {
self::$upgrade_method();
}
}
}
update_option( 'wpml_media_upgraded_from_prior_2_3_0', 1 );
}
}
/** @return bool */
private static function is_media_version_older_than_2_0() {
global $wpdb;
return (bool) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = 'wpml_media_duplicate_of'" );
}
private static function upgrade_2_0() {
global $wpdb;
global $sitepress;
// Check if the old options are set and in case move them to the new plugin settings, then delete the old ones
$old_starting_help = get_option( '_wpml_media_starting_help' );
if ( $old_starting_help ) {
WPML_Media::update_setting( 'starting_help', $old_starting_help );
delete_option( '_wpml_media_starting_help' );
}
// Create translated media
$target_language = $sitepress->get_default_language();
$attachment_ids_prepared = $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s", 'attachment' );
$attachment_ids = $wpdb->get_col( $attachment_ids_prepared );
// Let's first set the language of all images in default languages
foreach ( $attachment_ids as $attachment_id ) {
$wpml_media_lang = get_post_meta( $attachment_id, 'wpml_media_lang', true );
$wpml_media_duplicate_of = get_post_meta( $attachment_id, 'wpml_media_duplicate_of', true );
if ( ! $wpml_media_duplicate_of && ( ! $wpml_media_lang || $wpml_media_lang == $target_language ) ) {
$trid = $sitepress->get_element_trid( $attachment_id, 'post_attachment' );
if ( $trid ) {
// Since trid exists, get the language from there
$target_language = $sitepress->get_language_for_element( $attachment_id, 'post_attachment' );
}
$sitepress->set_element_language_details( $attachment_id, 'post_attachment', $trid, $target_language );
}
}
// Then all the translations
foreach ( $attachment_ids as $attachment_id ) {
$wpml_media_lang = get_post_meta( $attachment_id, 'wpml_media_lang', true );
$wpml_media_duplicate_of = get_post_meta( $attachment_id, 'wpml_media_duplicate_of', true );
if ( $wpml_media_duplicate_of ) {
$source_language = null;
$trid = $sitepress->get_element_trid( $wpml_media_duplicate_of, 'post_attachment' );
$source_language = false;
if ( $trid ) {
// Get the source language of the attachment, just in case is from a language different than the default
$source_language = $sitepress->get_language_for_element( $wpml_media_duplicate_of, 'post_attachment' );
// Fix bug on 1.6, where duplicated images are set to the default language
if ( $wpml_media_lang == $source_language ) {
$wpml_media_lang = false;
$attachment = get_post( $attachment_id );
if ( $attachment->post_parent ) {
$parent_post = get_post( $attachment->post_parent );
$post_parent_language = $sitepress->get_language_for_element( $parent_post->ID, 'post_' . $parent_post->post_type );
if ( $post_parent_language ) {
$wpml_media_lang = $post_parent_language;
}
}
if ( ! $wpml_media_lang ) {
// Trash orphan image
wp_delete_attachment( $attachment_id );
}
}
}
if ( $wpml_media_lang ) {
$sitepress->set_element_language_details( $attachment_id, 'post_attachment', $trid, $wpml_media_lang, $target_language, $source_language );
}
}
}
// Remove old media translation meta
// Remove both meta just in case
$attachment_ids = $wpdb->get_col( $attachment_ids_prepared );
foreach ( $attachment_ids as $attachment_id ) {
delete_post_meta( $attachment_id, 'wpml_media_duplicate_of' );
delete_post_meta( $attachment_id, 'wpml_media_lang' );
}
}
private static function upgrade_2_0_1() {
global $wpdb;
global $sitepress;
// Fixes attachments metadata among translations
$sql = "
SELECT t.element_id, t.trid, t.language_code
FROM {$wpdb->prefix}icl_translations t
LEFT JOIN {$wpdb->postmeta} pm
ON t.element_id = pm.post_id AND pm.meta_key=%s
WHERE t.element_type = %s AND pm.meta_id IS NULL AND element_id IS NOT NULL
";
$sql_prepared = $wpdb->prepare( $sql, array( '_wp_attachment_metadata', 'post_attachment' ) );
$original_attachments = $wpdb->get_results( $sql_prepared );
foreach ( $original_attachments as $original_attachment ) {
$attachment_metadata = get_post_meta( $original_attachment->element_id, '_wp_attachment_metadata', true );
if ( ! $attachment_metadata ) {
$attachment_translations = $sitepress->get_element_translations( $original_attachment->trid, 'post_attachment', true, true );
// Get _wp_attachment_metadata first translation available
foreach ( $attachment_translations as $attachment_translation ) {
if ( $attachment_translation->language_code != $original_attachment->language_code ) {
$attachment_metadata = get_post_meta( $attachment_translation->element_id, '_wp_attachment_metadata', true );
// _wp_attachment_metadata found: save it in the original and go to the next attachment
if ( $attachment_metadata ) {
update_post_meta( $original_attachment->element_id, '_wp_attachment_metadata', $attachment_metadata );
break;
}
}
}
}
}
return true;
}
private static function upgrade_2_3_0() {
global $wpdb, $sitepress;
if ( ! WPML_Media_2_3_0_Migration::migration_complete() ) {
$migration = new WPML_Media_2_3_0_Migration( $wpdb, $sitepress );
if ( $migration->is_required() ) {
$migration->maybe_show_admin_notice();
$migration->add_hooks();
}
}
}
}
# This file was generated by WPML
# WPML is a WordPress plugin that can turn any WordPress or WordPressMU site into a full featured multilingual content management system.
# https://wpml.org
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Project-Id-Version:WPML_EXPORT\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language:en\n"
"MIME-Version: 1.0\n"
# return sprintf(
# __( 'Translating media urls in custom field translations: %s', 'wpml-media' ),
# $number_of_custom_fields_left > 0 ?
msgid "Translating media urls in custom field translations: %s"
msgstr ""
# $number_of_custom_fields_left > 0 ?
# sprintf( __( '%d left', 'wpml-media' ), $number_of_custom_fields_left ) :
# __( 'done!', 'wpml-media' )
msgid "%d left"
msgstr ""
# sprintf( __( '%d left', 'wpml-media' ), $number_of_custom_fields_left ) :
# __( 'done!', 'wpml-media' )
# );
msgid "done!"
msgstr ""
# 'key' => 'wpml_media_batch_urls_update_error_custom_fields',
# 'value' => esc_js( __( 'Translating media urls in custom fields translations failed: Please try again (%s)', 'wpml-media' ) )
# );
msgid "Translating media urls in custom fields translations failed: Please try again (%s)"
msgstr ""
# return sprintf(
# __( 'Translating media urls in post translations: %s', 'wpml-media' ),
# $number_of_posts_left > 0 ?
msgid "Translating media urls in post translations: %s"
msgstr ""
# 'key' => 'wpml_media_batch_urls_update_errors_posts',
# 'value' => esc_js( __( 'Translating media urls in posts translations failed: Please try again (%s)', 'wpml-media' ) )
# );
msgid "Translating media urls in posts translations failed: Please try again (%s)"
msgstr ""
# return sprintf(
# __( 'Translating media urls in string translations: %s', 'wpml-media' ),
# $number_of_strings_left > 0 ?
msgid "Translating media urls in string translations: %s"
msgstr ""
# 'key' => 'wpml_media_batch_urls_update_error_strings',
# 'value' => esc_js( __( 'Translating media urls in string translations failed: Please try again (%s)', 'wpml-media' ) )
# );
msgid "Translating media urls in string translations failed: Please try again (%s)"
msgstr ""
# 'has_posts' => sprintf(
# __(
# 'Choose which media to translate with this %s',
msgid "Choose which media to translate with this %s"
msgstr ""
# ),
# 'loading' => __( 'Loading...', 'wpml-media' )
# ),
msgid "Loading..."
msgstr ""
# /* translators: WPML plugin name */
# $wpml_plugin_name = __( 'WPML', 'wpml-media' );
# /* translators: WPML Media Translation saddon/section name */
msgid "WPML"
msgstr ""
# /* translators: WPML Media Translation saddon/section name */
# $media_translation_name = __( 'Media Translation', 'wpml-media' );
#
msgid "Media Translation"
msgstr ""
# /* translators: media file string used in "if you want to use a different media file for each language..." */
# $media_file_string = __( 'media file', 'wpml-media' );
# $redirect_url = '#';
msgid "media file"
msgstr ""
# 'strings' => array(
# 'dialog_title' => __( 'Media sent to translation', 'wpml-media' ),
# 'content_with_media_sent' => __( 'You have sent content which contains media attachments for translation.', 'wpml-media' ),
msgid "Media sent to translation"
msgstr ""
# 'dialog_title' => __( 'Media sent to translation', 'wpml-media' ),
# 'content_with_media_sent' => __( 'You have sent content which contains media attachments for translation.', 'wpml-media' ),
# 'media_texts_translated' => sprintf( __( 'Translators will translate all your %smedia texts%s.', 'wpml-media' ), '<strong>', '</strong>' ),
msgid "You have sent content which contains media attachments for translation."
msgstr ""
# 'content_with_media_sent' => __( 'You have sent content which contains media attachments for translation.', 'wpml-media' ),
# 'media_texts_translated' => sprintf( __( 'Translators will translate all your %smedia texts%s.', 'wpml-media' ), '<strong>', '</strong>' ),
# 'use_different_media' => sprintf( __( 'If you want to use a different %s for each language, you can set them in: %s.', 'wpml-media' ),
msgid "Translators will translate all your %smedia texts%s."
msgstr ""
# 'media_texts_translated' => sprintf( __( 'Translators will translate all your %smedia texts%s.', 'wpml-media' ), '<strong>', '</strong>' ),
# 'use_different_media' => sprintf( __( 'If you want to use a different %s for each language, you can set them in: %s.', 'wpml-media' ),
# '<strong>' . $media_file_string . '</strong>', $media_translation_link ),
msgid "If you want to use a different %s for each language, you can set them in: %s."
msgstr ""
# '<strong>' . $media_file_string . '</strong>', $media_translation_link ),
# 'learn_more' => __( 'Learn more about Media Translation', 'wpml-media' ),
# 'wpml' => _x( 'WPML', 'plugin name', 'wpml-media' ),
msgid "Learn more about Media Translation"
msgstr ""
# 'learn_more' => __( 'Learn more about Media Translation', 'wpml-media' ),
# 'wpml' => _x( 'WPML', 'plugin name', 'wpml-media' ),
# 'media_translation' => _x( 'Media Translation', 'wpml addon name', 'wpml-media' )
msgctxt "plugin name"
msgid "WPML"
msgstr ""
# 'wpml' => _x( 'WPML', 'plugin name', 'wpml-media' ),
# 'media_translation' => _x( 'Media Translation', 'wpml addon name', 'wpml-media' )
# ),
msgctxt "wpml addon name"
msgid "Media Translation"
msgstr ""
# } else {
# wp_send_json_error( __( 'Failed to load the image editor', 'wpml-media' ) );
# }
msgid "Failed to load the image editor"
msgstr ""
# } else {
# wp_send_json_error( array( 'error' => __( 'Invalid nonce', 'wpml-media' ) ) );
# }
msgid "Invalid nonce"
msgstr ""
# }
# wp_send_json_success( array( 'status' => __( 'Running setup...', 'wpml-media' ) ) );
#
msgid "Running setup..."
msgstr ""
# $continue = false;
# $status = __( 'Setup complete!', 'wpml-media' );
# $offset = isset( $_POST['offset'] ) ? (int) $_POST['offset'] : 0;
msgid "Setup complete!"
msgstr ""
# $progress = round( 100*min( $offset, $total_posts_found )/$total_posts_found );
# $status = sprintf( __( 'Setup in progress: %d%% complete...', 'wpml-media' ), $progress );
# }
msgid "Setup in progress: %d%% complete..."
msgstr ""
# if ( $this->is_media_related_screen( $current_screen ) ) {
# $media_translation_dashboard = esc_html__( 'WPML &raquo; Media Translation', 'wpml-media' );
# $wpml_translation_dashboard = esc_html__( 'WPML &raquo; Translation Management', 'wpml-media' );
msgid "WPML &raquo; Media Translation"
msgstr ""
# $media_translation_dashboard = esc_html__( 'WPML &raquo; Media Translation', 'wpml-media' );
# $wpml_translation_dashboard = esc_html__( 'WPML &raquo; Translation Management', 'wpml-media' );
# $current_screen->add_help_tab( array(
msgid "WPML &raquo; Translation Management"
msgstr ""
# 'id' => 'wpml-media-translation',
# 'title' => esc_html__( 'Translating Media', 'wpml-media' ),
# 'content' =>
msgid "Translating Media"
msgstr ""
# 'content' =>
# '<p>' . esc_html__( 'There are two ways for you to translate Media:', 'wpml-media' ) . '</p>' .
# '<ul>' .
msgid "There are two ways for you to translate Media:"
msgstr ""
# '<li>' . sprintf(
# esc_html__( 'Use the dashboard on the %s page to translate your images and other media files.', 'wpml-media' ),
# $media_translation_dashboard
msgid "Use the dashboard on the %s page to translate your images and other media files."
msgstr ""
# '<li>' . sprintf(
# esc_html__( 'Use the dashboard on the %s page to send pages that contain media, for translation.', 'wpml-media' ),
# $wpml_translation_dashboard
msgid "Use the dashboard on the %s page to send pages that contain media, for translation."
msgstr ""
# '</ul>' .
# '<a href="https://wpml.org/?page_id=113610">' . esc_html__( 'Learn more about WPML Media Translation', 'wpml-media' ) . '</a>'
# ) );
msgid "Learn more about WPML Media Translation"
msgstr ""
# 'title' => esc_js( __( 'Media Translation', 'wpml-media' ) ),
# 'cancel' => esc_js( __( 'Cancel', 'wpml-media' ) ),
# 'save' => esc_js( __( 'Save media translation', 'wpml-media' ) ),
msgid "Cancel"
msgstr ""
# 'cancel' => esc_js( __( 'Cancel', 'wpml-media' ) ),
# 'save' => esc_js( __( 'Save media translation', 'wpml-media' ) ),
# 'status_labels' => WPML_Media_Translations_UI::get_translation_status_labels()
msgid "Save media translation"
msgstr ""
# $batch_translation_vars = array(
# 'complete' => esc_js( __( 'Scan complete!', 'wpml-media' ) ),
# 'is_st_enabled' => (bool) $this->sitepress->get_wp_api()->constant( 'WPML_ST_VERSION' ),
msgid "Scan complete!"
msgstr ""
# /* translators: name ot WPML-Media plugin */
# $wpml_media = '<strong>' . __( 'WPML Media Translation', 'wpml-media' ) . '</strong>';
#
msgid "WPML Media Translation"
msgstr ""
# $text = vsprintf(
# esc_html__( 'The %1$s setup is almost complete. Click %2$s to finish the setup.', 'wpml-media' ),
# array(
msgid "The %1$s setup is almost complete. Click %2$s to finish the setup."
msgstr ""
# <input type="button" class="button-primary alignright"
# value="<?php esc_attr_e( 'Finish setup', 'wpml-media' ) ?>"/>
#
msgid "Finish setup"
msgstr ""
# <div class="wrap wpml-media-setup">
# <h2><?php esc_html_e( 'Setup required', 'wpml-media' ) ?></h2>
# <div
msgid "Setup required"
msgstr ""
# <p>
# <?php esc_html_e( 'In order to get WPML Media Translation fully working, you need to run this set up which takes only a few moments depending on the total number of posts in your WordPress install.', 'wpml-media' ); ?>
# </p>
msgid "In order to get WPML Media Translation fully working, you need to run this set up which takes only a few moments depending on the total number of posts in your WordPress install."
msgstr ""
# /* translators: used to build a link in the "Click here to finish the setup" */
# $here_text = _x( 'here', 'Used to build a link in the "Click here to finish the setup"', 'wpml-media' );
# $here_link = '<a href="' . admin_url( 'admin.php?page=wpml-media' ) . '">' . $here_text . '</a>';
msgctxt "Used to build a link in the \"Click here to finish the setup\""
msgid "here"
msgstr ""
# 'args' => array(
# 'label' => __( 'Number of items per page:', 'wpml-media' ),
# 'default' => get_option( $option_name, 20 ),
msgid "Number of items per page:"
msgstr ""
# 'heading' => __( 'Media Translation', 'wpml-media' ),
# 'filter_by_date' => __( 'Filter by date', 'wpml-media' ),
# 'all_dates' => __( 'All dates', 'wpml-media' ),
msgid "Filter by date"
msgstr ""
# 'filter_by_date' => __( 'Filter by date', 'wpml-media' ),
# 'all_dates' => __( 'All dates', 'wpml-media' ),
# 'in' => __( 'in', 'wpml_media' ),
msgid "All dates"
msgstr ""
# 'to' => __( 'to', 'wpml_media' ),
# 'filter_by_status' => __( 'Filter by translation status', 'wpml-media' ),
# 'status_all' => __( 'All translation statuses', 'wpml-media' ),
msgid "Filter by translation status"
msgstr ""
# 'filter_by_status' => __( 'Filter by translation status', 'wpml-media' ),
# 'status_all' => __( 'All translation statuses', 'wpml-media' ),
# 'status_not' => __( 'Media file not translated', 'wpml-media' ),
msgid "All translation statuses"
msgstr ""
# 'status_all' => __( 'All translation statuses', 'wpml-media' ),
# 'status_not' => __( 'Media file not translated', 'wpml-media' ),
# 'status_translated' => __( 'Translated media uploaded', 'wpml-media' ),
msgid "Media file not translated"
msgstr ""
# 'status_not' => __( 'Media file not translated', 'wpml-media' ),
# 'status_translated' => __( 'Translated media uploaded', 'wpml-media' ),
# 'status_in_progress' => __( 'Translation in progress', 'wpml-media' ),
msgid "Translated media uploaded"
msgstr ""
# 'status_translated' => __( 'Translated media uploaded', 'wpml-media' ),
# 'status_in_progress' => __( 'Translation in progress', 'wpml-media' ),
# 'status_needs_translation' => __( 'Needs media file translation', 'wpml-media' ),
msgid "Translation in progress"
msgstr ""
# 'status_in_progress' => __( 'Translation in progress', 'wpml-media' ),
# 'status_needs_translation' => __( 'Needs media file translation', 'wpml-media' ),
# 'filter_by_language' => __( 'Filter by language', 'wpml-media' ),
msgid "Needs media file translation"
msgstr ""
# 'status_needs_translation' => __( 'Needs media file translation', 'wpml-media' ),
# 'filter_by_language' => __( 'Filter by language', 'wpml-media' ),
# 'any_language' => __( 'Any language', 'wpml-media' ),
msgid "Filter by language"
msgstr ""
# 'filter_by_language' => __( 'Filter by language', 'wpml-media' ),
# 'any_language' => __( 'Any language', 'wpml-media' ),
# 'search_media' => __( 'Search Media:', 'wpml-media' ),
msgid "Any language"
msgstr ""
# 'any_language' => __( 'Any language', 'wpml-media' ),
# 'search_media' => __( 'Search Media:', 'wpml-media' ),
# 'search_placeholder' => __( 'Title, caption or description', 'wpml-media' ),
msgid "Search Media:"
msgstr ""
# 'search_media' => __( 'Search Media:', 'wpml-media' ),
# 'search_placeholder' => __( 'Title, caption or description', 'wpml-media' ),
# 'search_button_label' => __( 'Filter', 'wpml-media' ),
msgid "Title, caption or description"
msgstr ""
# 'search_placeholder' => __( 'Title, caption or description', 'wpml-media' ),
# 'search_button_label' => __( 'Filter', 'wpml-media' ),
# 'original_language' => __( 'Original language', 'wpml-media' ),
msgid "Filter"
msgstr ""
# 'search_button_label' => __( 'Filter', 'wpml-media' ),
# 'original_language' => __( 'Original language', 'wpml-media' ),
# 'no_attachments' => __( 'No attachments found', 'wpml-media' ),
msgid "Original language"
msgstr ""
# 'original_language' => __( 'Original language', 'wpml-media' ),
# 'no_attachments' => __( 'No attachments found', 'wpml-media' ),
# 'add_translation' => __( 'Add media file translation', 'wpml-media' ),
msgid "No attachments found"
msgstr ""
# 'no_attachments' => __( 'No attachments found', 'wpml-media' ),
# 'add_translation' => __( 'Add media file translation', 'wpml-media' ),
# 'edit_translation' => __( 'Edit %s translation', 'wpml-media' ),
msgid "Add media file translation"
msgstr ""
# 'add_translation' => __( 'Add media file translation', 'wpml-media' ),
# 'edit_translation' => __( 'Edit %s translation', 'wpml-media' ),
# 'original' => __( 'Original:', 'wpml-media' ),
msgid "Edit %s translation"
msgstr ""
# 'edit_translation' => __( 'Edit %s translation', 'wpml-media' ),
# 'original' => __( 'Original:', 'wpml-media' ),
# 'translation' => __( 'Translation:', 'wpml-media' ),
msgid "Original:"
msgstr ""
# 'original' => __( 'Original:', 'wpml-media' ),
# 'translation' => __( 'Translation:', 'wpml-media' ),
# 'file' => __( 'File', 'wpml-media' ),
msgid "Translation:"
msgstr ""
# 'translation' => __( 'Translation:', 'wpml-media' ),
# 'file' => __( 'File', 'wpml-media' ),
# 'name' => __( 'Name', 'wpml-media' ),
msgid "File"
msgstr ""
# 'file' => __( 'File', 'wpml-media' ),
# 'name' => __( 'Name', 'wpml-media' ),
# 'caption' => __( 'Caption', 'wpml-media' ),
msgid "Name"
msgstr ""
# 'name' => __( 'Name', 'wpml-media' ),
# 'caption' => __( 'Caption', 'wpml-media' ),
# 'alt_text' => __( 'Alt text', 'wpml-media' ),
msgid "Caption"
msgstr ""
# 'caption' => __( 'Caption', 'wpml-media' ),
# 'alt_text' => __( 'Alt text', 'wpml-media' ),
# 'description' => __( 'Description', 'wpml-media' ),
msgid "Alt text"
msgstr ""
# 'alt_text' => __( 'Alt text', 'wpml-media' ),
# 'description' => __( 'Description', 'wpml-media' ),
# 'copy_from_original' => __( 'Copy from original', 'wpml-media' ),
msgid "Description"
msgstr ""
# 'description' => __( 'Description', 'wpml-media' ),
# 'copy_from_original' => __( 'Copy from original', 'wpml-media' ),
# 'upload_translated_media' => __( 'Upload translated media file', 'wpml-media' ),
msgid "Copy from original"
msgstr ""
# 'copy_from_original' => __( 'Copy from original', 'wpml-media' ),
# 'upload_translated_media' => __( 'Upload translated media file', 'wpml-media' ),
# 'use_different_file' => __( 'Use a different file', 'wpml-media' ),
msgid "Upload translated media file"
msgstr ""
# 'upload_translated_media' => __( 'Upload translated media file', 'wpml-media' ),
# 'use_different_file' => __( 'Use a different file', 'wpml-media' ),
# 'revert_to_original' => __( 'Revert to original', 'wpml-media' ),
msgid "Use a different file"
msgstr ""
# 'use_different_file' => __( 'Use a different file', 'wpml-media' ),
# 'revert_to_original' => __( 'Revert to original', 'wpml-media' ),
# 'restore_original_media' => __( 'Restore original media file', 'wpml-media' ),
msgid "Revert to original"
msgstr ""
# 'revert_to_original' => __( 'Revert to original', 'wpml-media' ),
# 'restore_original_media' => __( 'Restore original media file', 'wpml-media' ),
# 'statuses' => self::get_translation_status_labels(),
msgid "Restore original media file"
msgstr ""
# 'statuses' => self::get_translation_status_labels(),
# 'texts_change_notice' => __( 'Any changes you make to the text here will not affect any previous publications of this media on your website. This edited version will only appear if you select it from the library to be embedded.', 'wpml-media' )
# ),
msgid "Any changes you make to the text here will not affect any previous publications of this media on your website. This edited version will only appear if you select it from the library to be embedded."
msgstr ""
# return array(
# WPML_Media_Translation_Status::NOT_TRANSLATED => __( 'Not translated', 'wpml-media' ),
# WPML_Media_Translation_Status::IN_PROGRESS => __( 'In progress', 'wpml-media' ),
msgid "Not translated"
msgstr ""
# WPML_Media_Translation_Status::NOT_TRANSLATED => __( 'Not translated', 'wpml-media' ),
# WPML_Media_Translation_Status::IN_PROGRESS => __( 'In progress', 'wpml-media' ),
# WPML_Media_Translation_Status::TRANSLATED => __( 'Translated', 'wpml-media' ),
msgid "In progress"
msgstr ""
# WPML_Media_Translation_Status::IN_PROGRESS => __( 'In progress', 'wpml-media' ),
# WPML_Media_Translation_Status::TRANSLATED => __( 'Translated', 'wpml-media' ),
# WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION => __( 'Needs translation', 'wpml-media' )
msgid "Translated"
msgstr ""
# WPML_Media_Translation_Status::TRANSLATED => __( 'Translated', 'wpml-media' ),
# WPML_Media_Translation_Status::NEEDS_MEDIA_TRANSLATION => __( 'Needs translation', 'wpml-media' )
# );
msgid "Needs translation"
msgstr ""
# 'strings' => array(
# 'list_navigation' => __( 'Navigation', 'wpml-media' ),
# 'of' => __( 'of', 'wpml-media' )
msgid "Navigation"
msgstr ""
# 'list_navigation' => __( 'Navigation', 'wpml-media' ),
# 'of' => __( 'of', 'wpml-media' )
# ),
msgid "of"
msgstr ""
# 'get_first_page_url' => $this->pagination->get_first_page_url(),
# 'first_page' => __( 'First page', 'wpml-media' ),
#
msgid "First page"
msgstr ""
# 'get_previous_page_url' => $this->pagination->get_previous_page_url(),
# 'previous_page' => __( 'Previous page', 'wpml-media' ),
#
msgid "Previous page"
msgstr ""
# 'get_next_page_url' => $this->pagination->get_next_page_url(),
# 'next_page' => __( 'Next page', 'wpml-media' ),
#
msgid "Next page"
msgstr ""
# 'get_last_page_url' => $this->pagination->get_last_page_url(),
# 'last_page' => __( 'Last page', 'wpml-media' )
# ),
msgid "Last page"
msgstr ""
# 'strings' => array(
# 'close' => __( 'Close', 'wpml-media' ),
# 'was_replaced' => __( 'The media that you uploaded was replaced in these translated posts:', 'wpml-media' ),
msgid "Close"
msgstr ""
# 'close' => __( 'Close', 'wpml-media' ),
# 'was_replaced' => __( 'The media that you uploaded was replaced in these translated posts:', 'wpml-media' ),
# 'other_posts' => __( 'The same media might be used in other posts too. Do you want to scan and replace it?', 'wpml-media' ),
msgid "The media that you uploaded was replaced in these translated posts:"
msgstr ""
# 'was_replaced' => __( 'The media that you uploaded was replaced in these translated posts:', 'wpml-media' ),
# 'other_posts' => __( 'The same media might be used in other posts too. Do you want to scan and replace it?', 'wpml-media' ),
# 'without_usage' => __( 'The media that you uploaded will be used in future post translations. The same media might be used in already existing posts. Do you want to scan and replace it now?', 'wpml-media' ),
msgid "The same media might be used in other posts too. Do you want to scan and replace it?"
msgstr ""
# 'other_posts' => __( 'The same media might be used in other posts too. Do you want to scan and replace it?', 'wpml-media' ),
# 'without_usage' => __( 'The media that you uploaded will be used in future post translations. The same media might be used in already existing posts. Do you want to scan and replace it now?', 'wpml-media' ),
# 'scan_for_this_media' => __( 'Scan for content that has specifically this media (faster)', 'wpml-media' ),
msgid "The media that you uploaded will be used in future post translations. The same media might be used in already existing posts. Do you want to scan and replace it now?"
msgstr ""
# 'without_usage' => __( 'The media that you uploaded will be used in future post translations. The same media might be used in already existing posts. Do you want to scan and replace it now?', 'wpml-media' ),
# 'scan_for_this_media' => __( 'Scan for content that has specifically this media (faster)', 'wpml-media' ),
# 'scan_for_all_media' => __( 'Scan for content that has any of the media files that I translated (takes more time)', 'wpml-media' ),
msgid "Scan for content that has specifically this media (faster)"
msgstr ""
# 'scan_for_this_media' => __( 'Scan for content that has specifically this media (faster)', 'wpml-media' ),
# 'scan_for_all_media' => __( 'Scan for content that has any of the media files that I translated (takes more time)', 'wpml-media' ),
# 'button_label' => _x( 'Scan & Replace', 'Button label (verb)', 'wpml-media' )
msgid "Scan for content that has any of the media files that I translated (takes more time)"
msgstr ""
# 'scan_for_all_media' => __( 'Scan for content that has any of the media files that I translated (takes more time)', 'wpml-media' ),
# 'button_label' => _x( 'Scan & Replace', 'Button label (verb)', 'wpml-media' )
# )
msgctxt "Button label (verb)"
msgid "Scan & Replace"
msgstr ""
# $link = '<a href="' . $url . '" target="_blank" class="wpml-external-link">' .
# esc_html__( 'Media Translation documentation', 'wpml-media' ) . '</a>';
# $button = '<a href="' . $url . '" target="_blank" class="button button-primary button-wpml button-lg">' .
msgid "Media Translation documentation"
msgstr ""
# $button = '<a href="' . $url . '" target="_blank" class="button button-primary button-wpml button-lg">' .
# esc_html__( 'Learn more', 'wpml-media' ) . '</a>';
#
msgid "Learn more"
msgstr ""
# if ( $this->is_new_install() ) {
# $title = esc_html__( 'Learn how to translate media', 'wpml-media' );
# $body1 = esc_html__( 'WPML allows you to use different media (images, etc.) for translated content. The Media Translation process is integrated with WPML’s content translation, but requires additional steps.', 'wpml-media' );
msgid "Learn how to translate media"
msgstr ""
# $title = esc_html__( 'Learn how to translate media', 'wpml-media' );
# $body1 = esc_html__( 'WPML allows you to use different media (images, etc.) for translated content. The Media Translation process is integrated with WPML’s content translation, but requires additional steps.', 'wpml-media' );
# $body2 = sprintf( esc_html__( 'Before you start, we highly recommend that you review the %s. Then, you’ll be able to close this message.', 'wpml-media' ), $link );
msgid "WPML allows you to use different media (images, etc.) for translated content. The Media Translation process is integrated with WPML’s content translation, but requires additional steps."
msgstr ""
# $body1 = esc_html__( 'WPML allows you to use different media (images, etc.) for translated content. The Media Translation process is integrated with WPML’s content translation, but requires additional steps.', 'wpml-media' );
# $body2 = sprintf( esc_html__( 'Before you start, we highly recommend that you review the %s. Then, you’ll be able to close this message.', 'wpml-media' ), $link );
# } else {
msgid "Before you start, we highly recommend that you review the %s. Then, you’ll be able to close this message."
msgstr ""
# } else {
# $title = esc_html__( 'Media Translation is completely different now', 'wpml-media' );
# $body1 = esc_html__( 'This release of Media Translation includes a complete new workflow, with complete new features and possibilities.', 'wpml-media' );
msgid "Media Translation is completely different now"
msgstr ""
# $title = esc_html__( 'Media Translation is completely different now', 'wpml-media' );
# $body1 = esc_html__( 'This release of Media Translation includes a complete new workflow, with complete new features and possibilities.', 'wpml-media' );
# $body2 = sprintf( esc_html__( 'Even if you’re already familiar with WPML, you should read the new %s. Then, you’ll be able to close this message.', 'wpml-media' ), $link );
msgid "This release of Media Translation includes a complete new workflow, with complete new features and possibilities."
msgstr ""
# $body1 = esc_html__( 'This release of Media Translation includes a complete new workflow, with complete new features and possibilities.', 'wpml-media' );
# $body2 = sprintf( esc_html__( 'Even if you’re already familiar with WPML, you should read the new %s. Then, you’ll be able to close this message.', 'wpml-media' ), $link );
# }
msgid "Even if you’re already familiar with WPML, you should read the new %s. Then, you’ll be able to close this message."
msgstr ""
# }
# $minimize_label = esc_html__( 'Minimize', 'wpml-media' );
# $maximize_label = esc_html__( 'Maximize', 'wpml-media' );
msgid "Minimize"
msgstr ""
# $minimize_label = esc_html__( 'Minimize', 'wpml-media' );
# $maximize_label = esc_html__( 'Maximize', 'wpml-media' );
# $is_minimized = $this->is_minimized();
msgid "Maximize"
msgstr ""
# <a class="js-dismiss notice-dismiss<?php if ( ! $this->can_dismiss() ): ?> hidden<?php endif ?>">
# <span class="screen-reader-text"><?php esc_html_e( 'Dismiss', 'wpml-media' ) ?></span></a>
# <div class="wpml-media-welcome-notice-bg"><i class="otgs-ico-wpml"></i></div>
msgid "Dismiss"
msgstr ""
# protected function get_privacy_policy() {
# return __( 'WPML Media Translation will send the email address and name of each manager and assigned translator as well as the content itself to Advanced Translation Editor and to the translation services which are used.', 'wpml-media' );
# }
msgid "WPML Media Translation will send the email address and name of each manager and assigned translator as well as the content itself to Advanced Translation Editor and to the translation services which are used."
msgstr ""
#
# $message = __( 'Setting language to media: done!', 'wpml-media' );
#
msgid "Setting language to media: done!"
msgstr ""
# 'field_type' => 'tm-section',
# 'title' => __( 'Media', 'wpml-media' ),
# 'fields' => array(),
msgid "Media"
msgstr ""
# case 'title':
# $label = __( 'Title', 'wpml-media' );
# break;
msgid "Title"
msgstr ""
# case 'alt_text':
# $label = __( 'Alt Text', 'wpml-media' );
# break;
msgid "Alt Text"
msgstr ""
# <p>
# <?php printf( esc_html__( 'The %sWPML Media%s database needs updating. Please run the updater and leave the tab open until it completes.', 'wpml-media' ),
# '<strong>', '</strong>' ); ?>
msgid "The %sWPML Media%s database needs updating. Please run the updater and leave the tab open until it completes."
msgstr ""
# wp_send_json_success(
# array( 'status' => esc_html__( 'Reset new content duplication settings', 'wpml-media' ), )
# );
msgid "Reset new content duplication settings"
msgstr ""
# $status = sprintf(
# esc_html__( 'Updating attachments translation status: %d remaining.', 'wpml-media' ),
# $left );
msgid "Updating attachments translation status: %d remaining."
msgstr ""
# $this->mark_migration_complete();
# $status = esc_html__( 'Update complete!', 'wpml-media' );
# $continue = 0;
msgid "Update complete!"
msgstr ""
# <div class="wrap wrap-wpml-media-upgrade">
# <h2><?php esc_html_e( 'Upgrade required', 'wpml-media' ) ?></h2>
# <?php endif; ?>
msgid "Upgrade required"
msgstr ""
# </p>
# <input type="button" class="button-primary alignright" value="<?php echo esc_attr_x( 'Update', 'Update button label', 'wpml-media' ); ?>" />
# <input type="hidden" name="nonce" value="<?php echo wp_create_nonce( 'wpml-media-2-3-0-update' ); ?>" />
msgctxt "Update button label"
msgid "Update"
msgstr ""
#
# $response['message'] = __( 'Started...', 'wpml-media' );
#
msgid "Started..."
msgstr ""
# ?>
# <div class="message error wpml-media-inactive"><p><?php printf( __( 'WPML Media is enabled but not effective. It requires <a href="%s">WPML</a> in order to work.', 'wpml-media' ),
# 'https://wpml.org/' ); ?></p></div>
msgid "WPML Media is enabled but not effective. It requires <a href=\"%s\">WPML</a> in order to work."
msgstr ""
<?php
/**
* Plugin Name: WPML Media
* Plugin URI: https://wpml.org/
* Description: Add multilingual support for Media files | <a href="https://wpml.org/documentation/getting-started-guide/media-translation/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlmedia">Documentation</a> | <a href="https://wpml.org/version/media-translation-2-7-3/">WPML Media Translation 2.7.3 release notes</a>
* Author: OnTheGoSystems
* Author URI: http://www.onthegosystems.com/
* Version: 2.7.3
* Plugin Slug: wpml-media-translation
*
* @package wpml/media
*/
if ( defined( 'WPML_MEDIA_VERSION' ) ) {
return;
}
define( 'WPML_MEDIA_VERSION', '2.7.3' );
define( 'WPML_MEDIA_PATH', dirname( __FILE__ ) );
require_once WPML_MEDIA_PATH . '/vendor/autoload.php';
require WPML_MEDIA_PATH . '/inc/constants.inc';
require WPML_MEDIA_PATH . '/inc/wpml-media-dependencies.class.php';
require WPML_MEDIA_PATH . '/inc/wpml-media-upgrade.class.php';
if ( is_admin() ) {
require_once ABSPATH . 'wp-admin/includes/image.php';
}
function wpml_media_remove_flag_notice() {
$wpml_admin_notices = wpml_get_admin_notices();
$wpml_admin_notices->remove_notice(
WPML_Media_Posts_Media_Flag_Notice::NOTICE_GROUP,
WPML_Media_Posts_Media_Flag_Notice::NOTICE_ID
);
}
global $WPML_media, $wpdb, $sitepress, $iclTranslationManagement;
$media_dependencies = new WPML_Media_Dependencies();
if ( $media_dependencies->check() ) {
add_action( 'plugins_loaded', 'wpml_media_core_action_filter_loader', 0 );
function wpml_media_core_action_filter_loader() {
$loaders = array(
'WPML_Media_Factory',
'WPML_Media_Save_Translation_Factory',
'WPML_Media_Attachment_Image_Update_Factory',
'WPML_Media_Screen_Options_Factory',
'WPML_Media_Posts_Media_Flag_Notice_Factory',
'WPML_Media_Set_Posts_Media_Flag_Factory',
'WPML_Media_Set_Initial_Language_Factory',
'WPML_Media_Selector_Factory',
'WPML_Media_Post_Media_Usage_Factory',
'WPML_Media_Privacy_Content_Factory',
WPML\Media\Widgets\Block\DisplayTranslation::class,
);
$action_filter_loader = new WPML_Action_Filter_Loader();
$action_filter_loader->load( $loaders );
}
add_action( 'wpml_loaded', 'wpml_media_load_components' );
function wpml_media_load_components() {
if ( class_exists( 'WPML_Current_Screen_Loader_Factory' ) ) {
$loaders = array(
'WPML_Media_Attachments_Query_Factory',
'WPML_Media_Post_Images_Translation_Factory',
'WPML_Media_Post_Batch_Url_Translation_Factory',
'WPML_Media_Custom_Field_Images_Translation_Factory',
'WPML_Media_Custom_Field_Batch_Url_Translation_Factory',
'WPML_Media_Editor_Notices_Factory',
'WPML_Media_Help_Tab_Factory',
);
$action_filter_loader = new WPML_Action_Filter_Loader();
$action_filter_loader->load( $loaders );
}
}
add_action( 'wpml_st_loaded', 'wpml_media_load_components_st' );
function wpml_media_load_components_st() {
$loaders = array(
'WPML_Media_String_Images_Translation_Factory',
'WPML_Media_String_Batch_Url_Translation_Factory',
);
$action_filter_loader = new WPML_Action_Filter_Loader();
$action_filter_loader->load( $loaders );
}
add_action( 'wpml_after_tm_loaded', 'wpml_media_load_components_tm' );
function wpml_media_load_components_tm() {
$loaders = [
WPML_Media_Add_To_Basket_Factory::class,
WPML_Media_Submitted_Basket_Notice_Factory::class,
WPML_Media_Populate_Media_Strings_Translations_Factory::class,
];
$action_filter_loader = new WPML_Action_Filter_Loader();
$action_filter_loader->load( $loaders );
}
}
add_action( 'deactivate_' . WPML_MEDIA_FOLDER . '/plugin.php', 'wpml_media_deactivation_actions' );
function wpml_media_deactivation_actions() {
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
wpml_media_remove_flag_notice();
}
}
=== WPML Media Translation ===
Stable tag: 2.7.3
\ No newline at end of file
.wpml-media-selector td{padding-top:0}.wpml-media-selector a{cursor:pointer}.wpml-media-selector-wrapper-inner{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.wpml-media-selector-wrapper .explanation-text{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}.wpml-media-selector-wrapper label{display:block;text-align:center;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:.8em}.wpml-media-selector-wrapper label+label{-webkit-margin-start:5px;-moz-webkit-start:5px;margin-start:5px}.wpml-media-selector-wrapper input[type="checkbox"]{margin-top:0}.wpml-media-selector-zoom{display:block;margin:0 auto 3px;position:relative;height:60px;width:60px}.wpml-media-selector-zoom.translated::before{position:absolute;top:3px;right:3px;color:#fff;content:"\63";font-family:otgs-icons;font-size:9px;background:#46b450;border-radius:30px;width:13px;height:13px;line-height:13px}.wpml-media-selector-zoom.translated::before .rtl{right:auto;left:3px}.wpml-media-selector-zoom::after{content:"\f179";font-family:Dashicons;font-size:24px;color:rgba(255,255,255,0.45);position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}.wpml-media-selector-zoom img{max-width:100%;height:auto;-webkit-transition:-webkit-transform .1s linear;transition:-webkit-transform .1s linear;transition:transform .1s linear;transition:transform .1s linear, -webkit-transform .1s linear}.wpml-media-selector-placeholder{width:60px;height:60px;background:#e0e0e0}.wpml-media-selector-placeholder+.wpml-media-selector-placeholder{-webkit-margin-start:5px;-moz-webkit-start:5px;margin-start:5px}.wpml-media-selector-wrapper label:hover img,.wpml-media-selector-wrapper label:focus img{-webkit-transform:scale(2.5);transform:scale(2.5);z-index:10;position:absolute;bottom:45px;left:-2px;-webkit-box-shadow:0 0 10px 0 rgba(0,0,0,0.3);box-shadow:0 0 10px 0 rgba(0,0,0,0.3);background-color:#fff}.wpml-media-selector-wrapper label:hover .wpml-media-selector-zoom::after,.wpml-media-selector-wrapper label:focus .wpml-media-selector-zoom::after{display:none}.wpml-media-selector-toggle{color:#666;margin-bottom:.6em;display:inline-block}.wpml-media-selector-toggle::after{content:"\f140";font-family:Dashicons;font-size:18px;vertical-align:bottom;line-height:1}.wpml-media-selector-toggle.collapsed::after{content:"\f139"}
.wpml-media-tablenav{height:auto}.wpml-media-table thead{background:#fff}.wpml-media-dialog .wpml-media-translation-image,.wpml-media-table a{cursor:pointer}.wpml-col-media-title{-webkit-padding-start:0;-moz-padding-start:0;padding-start:0}.wpml-col-media-translations>span,td.wpml-col-media-title>span{width:60px;display:flex;align-items:center;justify-content:center;float:left;padding:1px}td.wpml-col-media-title>span,td.wpml-col-media-translations>span{height:60px}td.wpml-col-media-title .is-non-image,td.wpml-col-media-translations .is-non-image{height:45px;width:32px}td.wpml-col-media-title>span.wpml-col-media-filename{width:auto;padding-left:10px}.wpml-media-translation-image{position:relative;transition:.15s}.wpml-media-translation-image img{display:block;transition:.15s}.wpml-media-translation-image::before{content:'\68';font-family:otgs-icons;color:#fff;opacity:0;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}.wpml-media-translation-image .wpml-media-upload-text{opacity:1;position:absolute;bottom:0;left:0;right:0;padding:7px 3px;color:#fff;font-size:.9em;text-align:center;background:#21759b;transition:.15s}.wpml-media-translation-image .wpml-media-upload-text::before{content:"\f317";font-family:dashicons;font-size:20px;vertical-align:top;-webkit-margin-end:6px;moz-margin-end:6px;margin-end:6px}.wpml-media-translation-image:hover{background:#21759b}.wpml-media-translation-image:hover .wpml-media-upload-text,.wpml-media-translation-image:hover img{opacity:0}.wpml-media-translation-image:hover::before{opacity:1}.wpml-media-dialog .wpml-header-original,.wpml-media-dialog .wpml-header-translation{font-size:1.2em;text-align:center}.wpml-media-dialog .wpml-header-translation{width:calc(50% - 5% - 30px - 15px - 35px - 5px)}.wpml-media-dialog .wpml-media-wrapper{width:calc(50% - 5% - 30px - 15px - 35px - 7px);margin:7px 15px;display:inline-block;box-sizing:border-box;vertical-align:top;text-align:center}.wpml-media-dialog .wpml-media-wrapper.wpml-media-upload-handle{-moz-margin-start:83px;-webkit-margin-start:83px;margin-start:83px}.wpml-media-dialog .wpml-media-original-image,.wpml-media-dialog .wpml-media-translation-image{display:inline-block;position:relative;box-shadow:inset 0 0 15px rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.05);box-sizing:border-box;width:150px;height:150px}.wpml-media-dialog .wpml-media-original-image img,.wpml-media-dialog .wpml-media-translation-image img{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-width:100%;height:150px;width:auto}.wpml-media-dialog .wpml-media-original-image img[src$=".svg"],.wpml-media-dialog .wpml-media-translation-image img[src$=".svg"]{max-height:80%}.wpml-media-dialog .wpml-media-translation-image:before{font-size:50px;content:"\f317";font-family:dashicons}.wpml-media-dialog .wpml-media-original-title,.wpml-media-dialog .wpml-media-translated-title{font-size:.95em;line-height:1.3;margin:0;padding:8px;color:#666;word-break:break-all;word-wrap:break-word;position:absolute;background:#fff;left:0;right:0;bottom:0;overflow:hidden;max-height:100%;text-align:center;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}.wpml-media-dialog .wpml-media-original-title:empty,.wpml-media-dialog .wpml-media-translated-title:empty{display:none}.wpml-media-dialog .ui-dialog-buttonpane{padding:8px 16px}.wpml-media-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:none}.wpml-media-dialog .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button{margin-left:0}.wpml-media-dialog .notice.text-change-notice{margin-top:30px}#wpml-media-upload-progress-animation{border:1px solid #09c;padding:1px;position:relative;height:16px;border-radius:1px;margin:10px;text-align:left;background:#ddd;box-shadow:inset 1px 3px 6px rgba(0,0,0,.12);display:none}#wpml-media-upload-progress-animation .upload-progress-bar{height:100%;border-radius:3px;background-color:#0073aa;width:0;box-shadow:inset 1px 1px 10px rgba(0,0,0,.11)}#wpml-media-upload-progress-animation .status{left:50%;margin-top:-16px;position:absolute;display:inline-block;color:#fff}@media (min-width:783px){.batch-media-translation-action-wrap{display:flex;align-items:center;justify-content:space-between;margin-bottom:1em}}.batch-media-translation-action-wrap .button-primary{margin:0!important}.batch-media-translation-post-list{list-style:disc;margin-top:-.5em;margin-inline-start:30px}.batch-media-translation-post-list a{text-decoration:none}.batch-media-translation-action-list{margin:0 13px}
\ No newline at end of file
.wpml-media-welcome-notice{padding:0;padding-right:30px;position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;border:1px solid #ccd0d4}.rtl .wpml-media-welcome-notice{padding:0;padding-left:30px}.wrap .wpml-media-welcome-notice{margin:15px 0 40px}@media (max-width: 480px){.wpml-media-welcome-notice{display:block}}.wpml-media-welcome-notice *{-webkit-transition:all .2s linear;transition:all .2s linear}.wpml-media-welcome-notice-bg{-webkit-box-flex:0;-ms-flex:0 0 85px;flex:0 0 85px;background:#21759b url("../img/welcome-notice-bg.jpg") no-repeat;background-position:-80px -20px;padding:15px;-webkit-margin-end:20px;margin-inline-end:20px;position:relative}.minimized .wpml-media-welcome-notice-bg{-webkit-box-flex:0;-ms-flex:0 0 60px;flex:0 0 60px;background-position:-80px -105px}@media (max-width: 640px){.wpml-media-welcome-notice-bg{display:none}}.wpml-media-welcome-notice-bg i{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}.wpml-media-welcome-notice-bg i::before{color:#fff;font-size:80px}.minimized .wpml-media-welcome-notice-bg i::before{font-size:50px}.wpml-media-welcome-notice-content{padding:20px;color:#666}.minimized .wpml-media-welcome-notice-content{-ms-flex-item-align:center;align-self:center;padding:15px}.wpml-media-welcome-notice-header{margin-top:0;color:#555}@media (max-width: 480px){.wpml-media-welcome-notice-header{text-align:center}}.minimized .wpml-media-welcome-notice-header{margin-bottom:0}.minimized .wpml-media-welcome-notice-body{display:none}.wpml-media-welcome-notice-action{-ms-flex-item-align:center;align-self:center;padding:15px}@media (max-width: 480px){.wpml-media-welcome-notice-action{text-align:center;padding:0 15px 20px}}.wpml-media-welcome-notice .button-wpml{background:#21759b;border-color:#1d6586;-webkit-box-shadow:0 1px 0 #1d6586;box-shadow:0 1px 0 #1d6586;color:#fff;text-shadow:0 -1px 1px #1d6586,1px 0 1px #1d6586,0 1px 1px #1d6586,-1px 0 1px #1d6586}.wpml-media-welcome-notice .button-wpml:hover,.wpml-media-welcome-notice .button-wpml:focus,.wpml-media-welcome-notice .button-wpml:active{background:#1d688a;border-color:#1d6586}.wpml-media-welcome-notice-toggle{font-size:.85em;position:absolute;bottom:5px;right:15px;color:#aaa;cursor:pointer}.rtl .wpml-media-welcome-notice-toggle{right:auto;left:15px}@media (max-width: 640px){.wpml-media-welcome-notice-toggle{bottom:0}}.wpml-media-welcome-notice-toggle::after{content:'';vertical-align:middle;-webkit-margin-start:.3em;margin-inline-start:.3em;display:inline-block;border:.3em solid transparent}.expanded .wpml-media-welcome-notice-toggle::after{border-bottom:.45em solid;margin-top:-.25em}.minimized .wpml-media-welcome-notice-toggle::after{border-left:.5em solid}.rtl .minimized .wpml-media-welcome-notice-toggle::after{border-left:.3em solid transparent;border-right:.5em solid}.icl_tm_wrap{position:relative}.icl_tm_wrap .overlay{position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(255,255,255,0.95);z-index:10}.icl_tm_wrap .wpml-media-welcome-notice{position:absolute;top:105px;left:50%;width:80%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}
var WPML_Media_Batch_Url_Translation = WPML_Media_Batch_Url_Translation || {
hasDialog: false,
dialog: jQuery('#batch-media-translation-wrap'),
form: jQuery('#batch-media-translation-form'),
globalScope: 0,
attachmentId: 0,
createDialog: function (attachmentId, postsList) {
this.hasDialog = true;
this.attachmentId = attachmentId;
if (postsList.length > 0) {
this.dialog.find('.usage').show();
var ul = this.dialog.find('.usage ul');
for (var i in postsList) {
var li = postsList[i].url ?
'<a href="' + postsList[i].url + '">' + postsList[i].title + '</a>' :
postsList[i].title;
ul.append('<li>' + li + '</li>');
}
} else {
this.dialog.find('.no-usage').show();
}
},
showDialog: function () {
this.dialog.show();
this.dialog.scrollTop(0);
},
closeDialog: function (event) {
var self = WPML_Media_Batch_Url_Translation;
if (typeof event !== 'undefined') {
event.preventDefault();
}
self.dialog.hide();
self.reset();
},
setInProgress: function (on) {
this.form.find('input.button-primary:submit').prop('disabled', on);
this.form.find('input[name=global-scan-scope]').prop('disabled', on);
},
runScan: function () {
var self = WPML_Media_Batch_Url_Translation;
var form = jQuery(this);
self.globalScope = form.find('input[name=global-scan-scope]:checked').val();
var nextAction = [];
nextAction['wpml_media_translate_media_url_in_posts'] = 'wpml_media_translate_media_url_in_custom_fields';
if ( wpml_media_batch_translation.is_st_enabled ) {
nextAction['wpml_media_translate_media_url_in_custom_fields'] = 'wpml_media_translate_media_url_in_strings';
}
self.setInProgress(true);
jQuery.ajax({
url: ajaxurl,
type: 'post',
dataType: 'json',
data: form.serialize(),
success: function (response) {
self.setStatus(response.message);
self.scan(null, 'wpml_media_translate_media_url_in_posts', nextAction);
}
})
return false;
},
reset: function () {
this.dialog.find('.usage').hide();
this.dialog.find('.no-usage').hide();
this.dialog.find('.usage ul').html('');
this.attachmentId = 0;
this.setStatus('');
this.dialog.hide();
this.hasDialog = false;
},
setStatus: function (text) {
this.dialog.find('.status').html(text);
},
setComplete: function (text) {
this.setStatus(text);
this.setInProgress(false);
this.form.hide();
this.dialog.removeClass('notice-info').addClass('notice-success');
window.setTimeout(this.closeDialog, 3000);
},
scan: function (offset, action, nextAction) {
var self = WPML_Media_Batch_Url_Translation;
if (typeof offset === 'undefined') {
offset = 0;
}
jQuery.ajax(
{
url: ajaxurl,
type: 'POST',
data: {
action: action,
global: self.globalScope,
attachment_id: self.attachmentId,
offset: offset
},
dataType: 'json',
success: function (response) {
self.setStatus(response.data.message);
if (response.data.continue > 0) {
self.scan(response.data.offset, action, nextAction);
} else {
if (nextAction[action]) {
self.scan(null, nextAction[action], nextAction);
} else {
self.setComplete(wpml_media_batch_translation.complete);
}
}
}
}
);
}
};
jQuery(function ($) {
"use strict";
WPML_Media_Batch_Url_Translation.form.on('submit', WPML_Media_Batch_Url_Translation.runScan);
WPML_Media_Batch_Url_Translation.dialog.on('click', '.js-close', WPML_Media_Batch_Url_Translation.closeDialog);
});
\ No newline at end of file
var WPML_Media_Selector = WPML_Media_Selector || {};
jQuery(function ($) {
"use strict";
var dashboardTable = $('#icl-tm-translation-dashboard');
dashboardTable.find('tbody :checkbox').on('change', showMediaSelector);
function showMediaSelector() {
var hasMedia = $(this).closest('tr').data('has-media');
if (hasMedia) {
var checkbox = $(this);
var postSelected = checkbox.prop('checked');
var currentRow = $(this).closest('tr');
var postId = currentRow.attr('id').replace(/^row_/, '');
var mediaSelectorRow = $('#js-wpml-media-selector-' + postId);
}
if (postSelected) {
if (mediaSelectorRow.length) {
mediaSelectorRow.show();
} else {
loadMediaSelectorContent(currentRow, postId, checkbox);
}
} else if ( mediaSelectorRow ) {
mediaSelectorRow.find('label :checkbox').prop('checked', false);
mediaSelectorRow.hide();
}
}
function loadMediaSelectorContent(currentRow, postId, checkbox) {
var mediaSelectorContainer = {};
var rowWidth = currentRow.find('td:visible').length;
var data = {
action: "wpml_media_load_image_selector",
post_id: postId,
languages: getTargetLanguages()
};
var mediaSelectorRow = $(
'<tr class="hidden"><td colspan="' + rowWidth + '"></td></tr>' +
'<tr id="js-wpml-media-selector-' + postId + '" class="wpml-media-selector">' +
'<td colspan="' + rowWidth + '"></td>' +
'</tr>'
);
mediaSelectorRow.insertAfter(currentRow);
var postType = currentRow.data('post-type');
var preLoader = $('#wpml-media-selector-preloader').html().replace(/%POST_TYPE%/, postType);
mediaSelectorContainer = $('#js-wpml-media-selector-' + postId).find('td');
mediaSelectorContainer.html(preLoader);
checkbox.prop('disabled', true);
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
if (response.success && response.data.media_files_count) {
mediaSelectorContainer.find('.wpml-media-selector-wrapper-inner').html(response.data.html);
} else {
mediaSelectorRow.remove();
}
checkbox.prop('disabled', false);
}
});
}
function getTargetLanguages() {
var languages = [];
$(':radio[name^="tr_action"][value="1"]:checked', '#icl_tm_languages').each(function () {
languages.push($(this).attr('name').replace(/^tr_action\[/, '').replace(/\]$/, ''));
});
return languages;
}
$('#wpml-media-basket-notice').on('click', hideBasketNotice);
function hideBasketNotice() {
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: {action: 'dismiss_media_basket_notice'},
success: function (response) {
if (response.data.status) {
$('#wpml-media-basket-notice').fadeOut();
}
}
});
}
$('body').on('click', '.js-wpml-media-selector-toggle', toogleMediaList);
function toogleMediaList(event) {
event.preventDefault();
$(this).toggleClass('collapsed');
$('.wpml-media-selector-wrapper').toggle();
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: {action: 'wpml_media_toogle_show_media_selector'}
});
return false;
}
});
\ No newline at end of file
/* globals wpml_media_popup */
jQuery(function ($) {
var dialogBox = $('#wpml-media-dialog');
var dialogForm = $('#wpml-media-dialog-form');
var mediaFileUploadForm = $('#wpml-media-file-upload-form');
dialogBox.dialog({
resizable: false,
draggable: false,
height : 'auto',
width : 800,
autoOpen : false,
modal: true,
closeOnEscape: false,
dialogClass: 'otgs-ui-dialog wpml-media-dialog wpml-dialog-translate',
title: wpml_media_popup.title,
create: function () {
$('#jquery-ui-style-css').prop('disabled', true);
},
open: function (event, ui) {
$('.ui-dialog-titlebar-close', ui.dialog | ui).hide();
repositionDialog();
if (WPML_Media_Batch_Url_Translation.hasDialog) {
WPML_Media_Batch_Url_Translation.reset();
}
},
close: function () {
$('#jquery-ui-style-css').prop('disabled', false);
if (WPML_Media_Batch_Url_Translation.hasDialog) {
WPML_Media_Batch_Url_Translation.showDialog();
}
},
buttons: [
{
text: wpml_media_popup.cancel,
class: 'alignleft',
click: function () {
$(this).find('.spinner').remove();
$(this).dialog('close');
}
},
{
text: wpml_media_popup.save,
class: 'button-primary alignright',
disabled: true,
click: function () {
var thisDialog = $(this);
disableFormSave();
var ajaxLoader = $('<span class="spinner"></span>');
var translationForm = thisDialog.find('form');
ajaxLoader.insertBefore('.wpml-media-dialog .button-primary').css({
visibility: 'visible',
float: 'none'
});
$.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: translationForm.serialize(),
success: function (response) {
if (response.success) {
var originalAttachmentId = translationForm.find('input[name="original-attachment-id"]').val();
var translatedLanguage = translationForm.find('input[name="translated-language"]').val();
var mediaTranslationWrap = $('#media-attachment-' + originalAttachmentId + '-' + translatedLanguage);
var batchMediaTranslationWrap = $('#batch-media-translation-wrap');
var isMediaUpload = false;
var isRestoreMedia = false;
if (response.data.thumb) {
mediaTranslationWrap.find('img').attr('src', response.data.thumb).fadeIn();
mediaTranslationWrap.data('thumb', response.data.thumb);
mediaTranslationWrap.data('media-is-translated', 1);
mediaTranslationWrap.find('.otgs-ico-edit').hide();
isMediaUpload = translationForm.find('input[name=update-media-file]').val();
} else {
mediaTranslationWrap.find('img').attr('src', '').hide();
mediaTranslationWrap.data('thumb', '');
mediaTranslationWrap.find('.otgs-ico-edit').show();
mediaTranslationWrap.find('img')
.closest('.js-open-media-translation-dialog')
.removeClass('wpml-media-translation-image');
mediaTranslationWrap.data('media-is-translated', 0);
isRestoreMedia = translationForm.find('input[name=restore-media]').val();
}
if (isMediaUpload || isRestoreMedia) {
WPML_Media_Batch_Url_Translation.createDialog(originalAttachmentId, response.data.usage);
batchMediaTranslationWrap.find('#batch-media-translation-form').show();
batchMediaTranslationWrap.removeClass('notice-success');
batchMediaTranslationWrap.addClass('notice-info');
}
mediaTranslationWrap.attr('title', mediaTranslationWrap.data('language-name') + ': ' +
wpml_media_popup.status_labels[response.data.status]);
mediaTranslationWrap.data('title', $('#media-title-translation').val());
mediaTranslationWrap.data('caption', $('#media-caption-translation').val());
mediaTranslationWrap.data('alt_text', $('#media-alt-text-translation').val());
mediaTranslationWrap.data('description', $('#media-description-translation').val());
if (response.data.attachment_id) {
mediaTranslationWrap.data('attachment-id', response.data.attachment_id);
}
if (mediaTranslationWrap.find('.otgs-ico-add:visible').length) {
var addIcon = mediaTranslationWrap.find('.otgs-ico-add');
addIcon.removeClass('otgs-ico-add').addClass('otgs-ico-edit');
if (response.data.thumb) {
addIcon.hide();
}
if (response.data.thumb) {
mediaTranslationWrap.find('img')
.closest('.js-open-media-translation-dialog')
.addClass('wpml-media-translation-image');
}
}
thisDialog.dialog('close');
ajaxLoader.remove();
translationForm.find('input[name=restore-media]').val(0);
translationForm.find('input[name=update-media-file]').val(0);
}
}
});
}
}
]
});
function disableFormSave() {
$('.wpml-media-dialog .ui-dialog-buttonset .button-primary').prop('disabled', true);
}
function enableFormSave(e) {
if (typeof e !== 'undefined') {
var charCode = (e.which) ? e.which : e.keyCode;
}
if (typeof e === 'undefined' || charCode >= 32 || charCode === 8) {
$('.wpml-media-dialog .ui-dialog-buttonset .button-primary').prop('disabled', false);
}
}
dialogForm.on('keyup', 'input, textarea', enableFormSave);
$(window).resize(repositionDialog);
function repositionDialog() {
var winH = $(window).height() - 180;
$('.wpml-media-dialog').css({
'max-width': '95%'
});
$('.wpml-media-dialog .ui-dialog-content').css({
'max-height': winH
});
dialogBox.dialog('option', 'position', {
my: 'center',
at: 'center',
of: window
});
}
$('.js-open-media-translation-dialog').click(function () {
var attachmentRow = $(this).closest('.wpml-media-attachment-row');
var translatedMedia = $(this).closest('.wpml-media-wrapper');
hideAllMediaTextFields();
resetProgressAnimation();
updateDialogImages(attachmentRow, translatedMedia);
if (translatedMedia.data('media-is-translated')) {
enableUsingTranslatedMediaFile();
} else {
enableUsingOriginalMediaFile();
}
updateDialogFormFields(attachmentRow, translatedMedia);
updateDialogHiddenFormFields(attachmentRow, translatedMedia);
dialogBox.dialog('open');
});
function updateDialogImages(attachmentRow, translatedMedia) {
dialogBox.find('.wpml-header-original .wpml-title-flag img').attr('src', attachmentRow.data('flag'));
dialogBox.find('.wpml-header-translation .wpml-title-flag img').attr('src', translatedMedia.data('flag'));
$('.wpml-media-original-image .wpml-media-original-title')
.html(attachmentRow.data('is-image') ? '' : attachmentRow.data('file-name'));
$('.wpml-media-upload-handle .wpml-media-translated-title')
.html(attachmentRow.data('is-image') || !translatedMedia.data('media-is-translated') ? '' : translatedMedia.data('file-name'));
dialogBox.find('.wpml-header-original strong').html(attachmentRow.data('language-name'));
dialogBox.find('.wpml-header-translation strong').html(translatedMedia.data('language-name'));
var originalImg = dialogBox.find('.wpml-form-row .wpml-media-original-image img');
var translatedImg = dialogBox.find('.wpml-form-row .wpml-media-upload-handle img');
originalImg.attr('src', attachmentRow.data('thumb')).attr('alt', attachmentRow.data('language-code'));
translatedImg.attr('src', translatedMedia.data('thumb') ? translatedMedia.data('thumb') : attachmentRow.data('thumb')).attr('alt', translatedMedia.data('language-code'));
if (!attachmentRow.data('is-image')) {
originalImg.addClass('is-non-image');
translatedImg.addClass('is-non-image');
} else {
originalImg.removeClass('is-non-image');
translatedImg.removeClass('is-non-image');
}
mediaFileUploadForm.find('input:file').attr('accept', attachmentRow.data('mime-type'));
}
function updateDialogFormFields(attachmentRow, translatedMedia) {
if (attachmentRow.data('title')) {
$('#media-title-original').val(attachmentRow.data('title'));
$('#media-title-translation').val(translatedMedia.data('title'));
$('.wpml-form-row-title').show();
}
if (attachmentRow.data('caption')) {
$('#media-caption-original').val(attachmentRow.data('caption'));
$('#media-caption-translation').val(translatedMedia.data('caption'));
$('.wpml-form-row-caption').show();
}
if (attachmentRow.data('alt_text')) {
$('#media-alt-text-original').val(attachmentRow.data('alt_text'));
$('#media-alt-text-translation').val(translatedMedia.data('alt_text'));
$('.wpml-form-row-alt-text').show();
}
if (attachmentRow.data('description')) {
$('#media-description-original').val(attachmentRow.data('description'));
$('#media-description-translation').val(translatedMedia.data('description'));
$('.wpml-form-row-description').show();
}
}
function updateDialogHiddenFormFields(attachmentRow, translatedMedia) {
dialogForm.find('input[name=original-attachment-id]').val(attachmentRow.data('attachment-id'));
dialogForm.find('input[name=translated-attachment-id]').val(translatedMedia.data('attachment-id'));
dialogForm.find('input[name=translated-language]').val(translatedMedia.data('language-code'));
dialogForm.find('input[name=restore-media]').val(0);
mediaFileUploadForm.find('input[name=attachment-id]').val(translatedMedia.data('attachment-id'));
mediaFileUploadForm.find('input[name=original-attachment-id]').val(attachmentRow.data('attachment-id'));
mediaFileUploadForm.find('input[name=language]').val(translatedMedia.data('language-code'));
}
function enableUsingTranslatedMediaFile() {
dialogForm.find('.wpml-media-upload-text').hide();
dialogForm.find('.js-wpml-media-revert').show();
}
function enableUsingOriginalMediaFile() {
dialogForm.find('.wpml-media-upload-text').show();
dialogForm.find('.js-wpml-media-revert').hide();
}
function hideAllMediaTextFields() {
dialogBox
.find('.wpml-form-row-title, .wpml-form-row-caption, .wpml-form-row-alt-text, .wpml-form-row-description')
.hide();
}
function resetProgressAnimation() {
$('.wpml-media-dialog').find('.spinner').remove();
}
dialogBox.find('.js-button-copy').click(function (event) {
event.preventDefault();
var formRow = $(this).closest('.wpml-form-row');
var originalInput = formRow.find('input[id$="original"],textarea[id$="original"]');
var translationInput = formRow.find('input[id$="translation"],textarea[id$="translation"]');
if (translationInput.val() !== originalInput.val()) {
translationInput.val(originalInput.val());
enableFormSave();
}
return false;
});
function triggerMediaUpload(event) {
event.preventDefault();
mediaFileUploadForm.find('input[type=file]').trigger('click');
return false;
}
function restoreMediaFile(event) {
event.preventDefault();
var imagesRow = $(this).closest('.wpml-form-row');
var originalImage = imagesRow.find('.wpml-media-original-image img');
var translatedImage = imagesRow.find('.wpml-media-translation-image img');
dialogForm.find('input[name=update-media-file]').val(0);
translatedImage.attr('src', originalImage.attr('src'));
dialogForm.find('input[name=restore-media]').val(1);
enableUsingOriginalMediaFile();
enableFormSave();
return false;
}
$('.js-wpml-media-revert').on('click', 'a', restoreMediaFile);
dialogBox.find('.wpml-form-row').on('click', '.wpml-media-translation-image', triggerMediaUpload);
mediaFileUploadForm.find('input[type=file]').change(
function () {
var file = $(this)[0].files[0];
var upload = new Upload(file);
upload.doUpload();
}
);
// Async file upload
var Upload = function (file) {
this.file = file;
this.progressBar = $('#wpml-media-upload-progress-animation');
};
Upload.prototype.getType = function () {
return this.file.type;
};
Upload.prototype.getSize = function () {
return this.file.size;
};
Upload.prototype.getName = function () {
return this.file.name;
};
Upload.prototype.doUpload = function () {
var that = this;
var formData = new FormData();
this.resetError();
var attachmentId = 0;
formData.append('file', this.file, this.getName());
var fields = mediaFileUploadForm.serializeArray();
$.each(fields, function (i, field) {
formData.append(field.name, field.value);
if (field.name === 'attachment-id') {
attachmentId = field.value;
}
});
that.progressBar.show();
$.ajax({
type: 'POST',
url: ajaxurl,
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', that.progressHandling, false);
}
return myXhr;
},
success: function (response) {
that.progressBar.hide();
if (response.success) {
var translatedImgTag = dialogBox.find('.wpml-form-row .wpml-media-upload-handle img');
translatedImgTag.attr('src', response.data.thumb);
dialogForm.find('input[name=translated-attachment-id]').val(response.data.attachment_id);
if (translatedImgTag.hasClass('is-non-image')) {
dialogForm.find('.wpml-media-translated-title').html(response.data.name);
}
enableFormSave();
dialogForm.find('input[name=update-media-file]').val(1);
enableUsingTranslatedMediaFile();
// Reset 'file' field
mediaFileUploadForm.find('input[type=file]').val('');
} else {
that.setError(response.data);
}
},
async: true,
data: formData,
cache: false,
contentType: false,
processData: false,
timeout: 60000
});
};
Upload.prototype.progressHandling = function (event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total;
var progress_bar_id = '#wpml-media-upload-progress-animation';
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
$(progress_bar_id + ' .upload-progress-bar').css('width', +percent + '%');
$(progress_bar_id + ' .status').text(percent + '%');
};
Upload.prototype.setError = function (text) {
$('#wpml-media-upload-error').html(text);
};
Upload.prototype.resetError = function () {
this.setError('');
};
function showTextsChangedNotice(e) {
var charCode = (e.which) ? e.which : e.keyCode;
if (charCode >= 32 || charCode === 8) {
dialogBox.find('.text-change-notice').show();
}
}
dialogForm.on('keyup', 'input, textarea', showTextsChangedNotice);
function dismissTextsChangedNotice() {
dialogBox.find('.text-change-notice').fadeOut();
$.ajax({
type: 'POST',
url: ajaxurl,
data: {action: 'wpml_media_editor_text_edit_notice_dismissed'},
success: function () {
},
});
return false;
}
dialogBox.find('.text-change-notice').on('click', '.notice-dismiss', dismissTextsChangedNotice);
});
jQuery(function ($) {
"use strict";
var notice = $('#wpml-media-welcome-notice');
notice.on('click', '.js-toggle', toggleWelcomeNotice);
notice.on('click', '.js-dismiss', dismissWelcomeNotice);
function toggleWelcomeNotice() {
notice.toggleClass('minimized expanded');
var a = $(this);
var altText = a.html();
a.html(a.data('alt-text'));
a.data('alt-text', altText);
jQuery.ajax({
url: ajaxurl,
type: 'post',
data: {
action: wpmlMediaWelcomeNotice.toggleAjaxAction,
nonce: wpmlMediaWelcomeNotice.nonce
}
})
return false;
}
function dismissWelcomeNotice() {
notice.fadeOut(function () {
$(this).remove();
$('.icl_tm_wrap .overlay').remove();
});
jQuery.ajax({
url: ajaxurl,
type: 'post',
data: {
action: wpmlMediaWelcomeNotice.dismissAjaxAction,
nonce: wpmlMediaWelcomeNotice.nonce
}
})
return false;
}
if (!notice.is(':visible')) {
var overlay = $('<div class="overlay"></div>');
var tmWrap = $('.icl_tm_wrap');
overlay.append(notice)
tmWrap.prepend(overlay);
notice.show();
}
notice.on('click', '.wpml-external-link, .button-lg', function (event) {
var url = $(this).attr('href');
window.open(url, $(this).attr('target'));
notice.find('.js-dismiss').show();
event.preventDefault();
return false;
})
});
\ No newline at end of file
/* globals wpml_media_basket_notice_data */
var WPML_Media_Submitted_Basket_Notice = WPML_Media_Submitted_Basket_Notice || {};
jQuery(function ($) {
"use strict";
var form = jQuery('#translation-jobs-translators-form');
form.on('wpml-tm-basket-submitted', function(){
var dialogBox = $('#submitted-basket-notice-dialog');
dialogBox.dialog({
modal:true,
closeOnEscape: false,
dialogClass: "no-close otgs-ui-dialog",
resizable: false,
draggable: false,
width: 600,
open: function() {
repositionDialog();
wpmlTMBasket.dialogs.push( 'media' );
wpmlTMBasket.redirect = false;
},
buttons: [
{
text: wpml_media_basket_notice_data.button_label,
class: 'button-primary',
click: function() {
dialogBox.dialog('close');
}
}
],
close: function() {
wpmlTMBasket.dialogs.splice( wpmlTMBasket.dialogs.indexOf( 'media' ), 1 );
if(0 === wpmlTMBasket.dialogs.length) {
location.href = dialogBox.data('redirect-url');
}
}
});
$(window).resize(repositionDialog);
function repositionDialog() {
var winH = $(window).height() - 180;
$(".otgs-ui-dialog .ui-dialog-content").css({
"max-height": winH
});
$(".otgs-ui-dialog").css({
"max-width": "95%"
});
dialogBox.dialog("option", "position", {
my: "center",
at: "center",
of: window
});
}
});
});
var WPML_Media_2_3_0_Upgrade = WPML_Media_2_3_0_Upgrade || {};
jQuery(function ($) {
"use strict";
var updateContainer = $("#wpml-media-2-3-0-update");
var updateButton = updateContainer.find(".button-primary");
var spinner = updateContainer.find(".spinner");
var nonce = updateContainer.find("input[name=nonce]").val();
var statusContainer = updateContainer.find('.status');
var mediaFlagNoticeContainer = false;
if ($('#wpml-media-posts-media-flag').length) {
mediaFlagNoticeContainer = $('#wpml-media-posts-media-flag');
} else if ($('.otgs-notice[data-id=wpml-media-posts-media-flag]').length) {
mediaFlagNoticeContainer = $('.otgs-notice[data-id=wpml-media-posts-media-flag]');
}
if (mediaFlagNoticeContainer) {
mediaFlagNoticeContainer.hide();
$('.wrap-wpml-media-upgrade h2').hide();
}
updateButton.on("click", function () {
showProgress();
runUpgrade();
});
function showProgress() {
spinner.css({visibility: "visible"});
updateButton.prop("disabled", true);
}
function hideProgress() {
spinner.css({visibility: "hidden"});
updateButton.prop("disabled", false);
}
function setStatus(statusText) {
statusContainer.html(statusText);
}
function runUpgrade() {
var data = {
action: "wpml_media_2_3_0_upgrade",
nonce: nonce,
step: "reset-new-content-settings"
};
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
if (response.data.status) {
setStatus(response.data.status);
}
runAttachmentMigration(0, 1, 0);
}
});
}
function runAttachmentMigration(offset, batchSizeFactor, timestamp) {
var data = {
action: "wpml_media_2_3_0_upgrade",
nonce: nonce,
step: "migrate-attachments",
offset: offset,
batch_size_factor: batchSizeFactor,
timestamp: timestamp
};
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
if (response.data.status) {
setStatus(response.data.status);
}
if (response.data.goon) {
runAttachmentMigration(response.data.offset, response.data.batch_size_factor, response.data.timestamp);
} else {
if (mediaFlagNoticeContainer) {
$('#wpml-media-2-3-0-update').hide();
if (mediaFlagNoticeContainer.find('input.button-primary').length) {
mediaFlagNoticeContainer.show();
mediaFlagNoticeContainer.find('input.button-primary').trigger('click');
} else {
location.href = mediaFlagNoticeContainer.find('a').attr('href')+'&run_setup=1&redirect_to='+location.href;
}
} else {
hideProgress();
location.reload();
}
}
}
});
}
});
var WPML_Media_Posts_Media_Flag = WPML_Media_Posts_Media_Flag || {};
jQuery(function ($) {
"use strict";
var updateContainer = $('#wpml-media-posts-media-flag');
var updateButton = updateContainer.find('.button-primary');
var spinner = updateContainer.find('.spinner');
var prepareAction = updateContainer.data('prepareAction');
var prepareNonce = updateContainer.data('prepareNonce');
var processAction = updateContainer.data('processAction');
var processNonce = updateContainer.data('processNonce');
var statusContainer = updateContainer.find('.status');
function getQueryParams(qs) {
qs = qs.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
var queryParams = getQueryParams(location.search);
if (queryParams.run_setup) {
showProgress();
runSetup();
}
updateButton.on("click", function () {
showProgress();
runSetup();
});
function showProgress() {
spinner.css({visibility: "visible"});
updateButton.prop("disabled", true);
}
function hideProgress() {
spinner.css({visibility: "hidden"});
updateButton.prop("disabled", false);
}
function setStatus(statusText) {
statusContainer.html(statusText);
}
function runSetup() {
var data = {
action: prepareAction,
nonce: prepareNonce
};
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
handleResponse(response);
if (!response.success) {
return;
}
if (response.data.status) {
setStatus(response.data.status);
}
setInitialLanguage();
},
error: function (jqXHR, status, error) {
statusContainer.html(jqXHR.statusText || status || error);
}
});
}
function handleResponse(response) {
var error = [];
if (response.error) {
error.push(response.error);
}
if (!response.success && response.data) {
error.push(response.data);
}
if (error.length) {
statusContainer.html('<pre>' + error.join('</pre><pre>') + '</pre>');
}
}
function setInitialLanguage() {
var data = {
action: processAction,
nonce: processNonce
};
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
handleResponse(response);
if (!response.success) {
return;
}
var message = response.message ? response.message : response.data.message;
setStatus(message);
setHasMediaFlag(0);
},
error: function (jqXHR, status, error) {
statusContainer.html(jqXHR.statusText || status || error);
}
});
}
function setHasMediaFlag(offset) {
var data = {
action: processAction,
nonce: processNonce,
offset: offset
};
$.ajax({
url: ajaxurl,
type: "POST",
dataType: "json",
data: data,
success: function (response) {
handleResponse(response);
if (!response.success) {
return;
}
if (response.data.status) {
setStatus(response.data.status);
}
if (response.data.continue) {
setHasMediaFlag(response.data.offset);
} else {
if (queryParams.redirect_to) {
location.href = queryParams.redirect_to;
} else {
location.reload();
}
}
},
error: function (jqXHR, status, error) {
statusContainer.html(jqXHR.statusText || status || error);
}
});
}
});
<div id="wpml-media-selector-preloader" class="hidden">
<a class="js-wpml-media-selector-toggle wpml-media-selector-toggle {% if hide_selector %}collapsed{% endif %}">{{ strings.has_posts }}</a>
<div class="wpml-media-selector-wrapper" {% if hide_selector %}style="display: none"{% endif %}>
<div class="wpml-media-selector-wrapper-inner">
<div class="wpml-media-selector-placeholder">&nbsp;</div>
<div class="wpml-media-selector-placeholder">&nbsp;</div>
<div class="wpml-media-selector-placeholder">&nbsp;</div>
<p class="explanation-text small"><i>{{ strings.loading }}</i></p>
</div>
</div>
</div>
\ No newline at end of file
{% for id, file in files %}
<label>
<span class="wpml-media-selector-zoom{% if file.translated %} translated{% endif %}">
<img src="{{ file.thumbnail }}" title="{{ file.name }}" alt="{{ file.name }}"/>
</span>
<input type="checkbox" name="post[{{ post_id }}][media-translation][]" value="{{ id }}"/>
</label>
{% endfor %}
<div id="submitted-basket-notice-dialog" class="otgs-confirmation-dialog" data-redirect-url="{{ redirect_url }}" title="{{ strings.dialog_title }}" style="display: none">
<div class="otgs-confirmation-dialog-icon">
<span class="otgs-ico-media"></span>
</div>
<div class="otgs-confirmation-dialog-content">
<p>
<strong>{{ strings.content_with_media_sent }}</strong>
{{ strings.media_texts_translated|raw }}
</p>
<p>
{{ strings.use_different_media|raw }}
</p>
<p>
<a href="{{ learn_more_url }}" class="wpml-external-link" target="_blank">{{ strings.learn_more }}</a>
</p>
</div>
</div>
<div id="batch-media-translation-wrap" class="batch-media-translation-wrap notice otgs-notice notice-info otgs-is-dismissible" style="display: none">
<span class="notice-dismiss js-close"><span class="screen-reader-text">{{ strings.close }}</span></span>
<form id="batch-media-translation-form" method="post" action="">
<input type="hidden" name="action" value="wpml_media_scan_prepare" />
<div class="usage" style="display: none">
<p>{{ strings.was_replaced }}</p>
<ul class="batch-media-translation-post-list"></ul>
<p>{{ strings.other_posts }}</p>
</div>
<div class="no-usage" style="display: none">
<p>{{ strings.without_usage }}</p>
</div>
<div class="batch-media-translation-action-wrap">
<ul class="batch-media-translation-action-list">
<li>
<label>
<input type="radio" name="global-scan-scope" value="0" checked/>{{ strings.scan_for_this_media }}
</label>
</li>
<li>
<label>
<input type="radio" name="global-scan-scope" value="1"/>{{ strings.scan_for_all_media }}
</label>
</li>
</ul>
<p class="text-right">
<input type="submit" class="button-primary" value="{{ strings.button_label }}"/>
</p>
</div>
</form>
<p class="status"></p>
</div>
\ No newline at end of file
<form id="posts-filter" method="get">
<input type="hidden" name="page" value="wpml-media"/>
<input type="hidden" name="sm" value="media-translation"/>
{{ nonce|raw }}
<label for="filter-by-date" class="screen-reader-text">{{ strings.filter_by_date }}</label>
<select id="filter-by-date" name="m">
<option {% if( selected_month == 0 ) %}selected="selected"{% endif %}
value="0">{{ strings.all_dates }}</option>
{% for month in months %}
<option {% if( selected_month == month.id ) %}selected="selected"{% endif %}
value="{{ month.id }}">{{ month.label }}</option>
{% endfor %}
</select>
{{ strings.in }}
<label for="filter-by-language" class="screen-reader-text">{{ strings.filter_by_language }}</label>
<select id="filter-by-language" name="slang">
<option value="">{{ strings.any_language }}</option>
{% for code, language in languages %}
<option {% if( from_language == code ) %}selected="selected"{% endif %}
value="{{ code }}">{{ language.name }}</option>
{% endfor %}
</select>
{{ strings.to }}
<select id="filter-by-language" name="tlang">
<option value="">{{ strings.any_language }}</option>
{% for code, language in languages %}
<option {% if( to_language == code ) %}selected="selected"{% endif %}
value="{{ code }}">{{ language.name }}</option>
{% endfor %}
</select>
<label for="filter-by-translation-status" class="screen-reader-text">{{ strings.filter_by_status }}</label>
<select id="filter-by-translation-status" name="status">
<option {% if( selected_status|length == 0 ) %}selected="selected"{% endif %}
value="">{{ strings.status_all }}</option>
<option {% if( selected_status == statuses.not_translated and selected_status|length > 0 ) %}selected="selected"{% endif %}
value="{{ statuses.not_translated }}">{{ strings.status_not }}</option>
<option {% if( selected_status == statuses.in_progress and selected_status|length > 0 ) %}selected="selected"{% endif %}
value="{{ statuses.in_progress }}">{{ strings.status_in_progress }}</option>
<option {% if( selected_status == statuses.translated ) %}selected="selected"{% endif %}
value="{{ statuses.translated }}">{{ strings.status_translated }}</option>
<option {% if( selected_status == statuses.needs_translation ) %}selected="selected"{% endif %}
value="{{ statuses.needs_translation }}">{{ strings.status_needs_translation }}</option>
</select>
<label class="screen-reader-text" for="media-search-input">{{ strings.search_media }}</label>
<input size="25" type="search" id="media-search-input" placeholder="{{ strings.search_placeholder }}" name="s"
value="{{ search }}">
<input type="submit" class="button action" value="{{ strings.search_button_label }}">
</form>
\ No newline at end of file
<div id="wpml-media-dialog">
<span class="ajax-loader"></span>
<form id="wpml-media-dialog-form" method="post" enctype="multipart/form-data">
{{ nonce|raw }}
<input type="hidden" name="original-attachment-id" value=""/>
<input type="hidden" name="translated-attachment-id" value=""/>
<input type="hidden" name="translated-language" value=""/>
<input type="hidden" name="restore-media" value="0"/>
<input type="hidden" name="update-media-file" value="0"/>
<input type="hidden" name="action" value="wpml_media_save_translation"/>
<header class="wpml-media-translation-header">
<h3 class="wpml-header-original">{{ strings.original }}<span class="wpml-title-flag"><img
src="#"></span><strong>%from_language%</strong>
</h3>
<h3 class="wpml-header-translation">{{ strings.translation }}<span class="wpml-title-flag"><img
src="#"></span><strong>%to_language%</strong>
</h3>
</header>
<div class="wpml-form-row">
<label>{{ strings.file }}</label>
<span class="wpml-media-wrapper">
<span class="wpml-media-original-image">
<img src="#" alt="#">
<span class="wpml-media-original-title"></span>
</span>
</span>
<span class="wpml-media-wrapper wpml-media-upload-handle">
<a class="wpml-media-translation-image drag-drop-area">
<img src="#" alt="#">
<span class="wpml-media-translated-title"></span>
<span class="wpml-media-upload-text hidden">{{ strings.use_different_file }}</span>
</a>
<span class="js-wpml-media-revert wpml-display-block text-center hidden">
<a class="button button-secondary button-small">{{ strings.revert_to_original }}</a>
</span>
</span>
</div>
<div class="wpml-form-row wpml-form-row-title hidden">
<label for="media-title">{{ strings.name }}</label>
<input readonly value="" id="media-title-original" type="text">
<button class="button-copy button-secondary js-button-copy otgs-ico-copy"
title="{{ strings.copy_from_original }}"></button>
<input name="translation[title]" id="media-title-translation" value="" type="text">
</div>
<div class="wpml-form-row wpml-form-row-caption hidden">
<label for="media-caption">{{ strings.caption }}</label>
<textarea readonly id="media-caption-original" cols="22" rows="4"></textarea>
<button class="button-copy button-secondary js-button-copy otgs-ico-copy"
title="{{ strings.copy_from_original }}"></button>
<textarea name="translation[caption]" id="media-caption-translation" cols="22" rows="4"></textarea>
</div>
<div class="wpml-form-row wpml-form-row-alt-text hidden">
<label for="media-alt-text">{{ strings.alt_text }}</label>
<input readonly value="" id="media-alt-text-original" type="text">
<button class="button-copy button-secondary js-button-copy otgs-ico-copy"
title="{{ strings.copy_from_original }}"></button>
<input name="translation[alt-text]" id="media-alt-text-translation" value="" type="text">
</div>
<div class="wpml-form-row wpml-form-row-description hidden">
<label for="media-description">{{ strings.description }}</label>
<textarea readonly id="media-description-original" cols="22" rows="4"></textarea>
<button class="button-copy button-secondary js-button-copy otgs-ico-copy"
title="{{ strings.copy_from_original }}"></button>
<textarea name="translation[description]" id="media-description-translation" cols="22" rows="4"></textarea>
</div>
</form>
{% if( show_text_change_notice) %}
<div class="text-change-notice notice notice-info inline is-dismissible hidden">
<p>{{ strings.texts_change_notice }}</p>
</div>
{% endif %}
<div id="wpml-media-upload-progress-animation">
<div class="upload-progress-bar"></div>
<div class="status">0%</div>
</div>
<span id="wpml-media-upload-error" class="icl_error_text"></span>
</div>
<form id="wpml-media-file-upload-form" enctype="multipart/form-data">
<input type="hidden" name="action" value="wpml_media_upload_file">
<input type="hidden" name="attachment-id" value="">
<input type="hidden" name="original-attachment-id" value="">
<input type="hidden" name="language" value="">
{{ nonce|raw }}
<input style="display:none" type="file" name="image" accept="image/*" />
</form>
<tr class="wpml-media-attachment-row" data-attachment-id="{{ attachment.post.ID }}"
data-language-code="{{ attachment.language }}"
data-language-name="{{ languages[attachment.language].name }}"
data-is-image="{{ attachment.is_image }}"
data-thumb="{{ attachment.thumb.src }}"
data-file-name="{{ attachment.file_name }}"
data-mime-type="{{ attachment.mime_type }}"
data-title="{{ attachment.post.post_title }}"
data-caption="{{ attachment.post.post_excerpt }}"
data-alt_text="{{ attachment.alt }}"
data-description="{{ attachment.post.post_content }}"
data-flag="{{ languages[attachment.language].flag }}">
<td class="wpml-col-media-title">
<span title="{{ languages[attachment.language].name }}" class="wpml-media-original-flag js-otgs-popover-tooltip"
data-tippy-distance="-12">
<img src="{{ languages[attachment.language].flag }}" width="16" height="12" alt="{{ attachment.language }}">
</span>
<span class="wpml-media-wrapper">
<img src="{{ attachment.thumb.src }}"
width="{{ attachment.thumb.width }}"
height="{{ attachment.thumb.height }}"
alt="{{ attachment.language }}"
{% if not attachment.is_image %}
class="is-non-image"
{% else %}
data-tippy-boundary="viewport"
data-tippy-flip="true"
data-tippy-placement="right"
data-tippy-maxWidth= "{{ attachment.preview.width }}px"
data-tippy-content="{{ '<img style=\"max-width:100%;width:auto;max-height:' ~ attachment.preview.height ~ 'px;height:auto;\" src="' ~ attachment.url ~ '" />' }}"
class="js-otgs-popover-tooltip"
{% endif %}
>
</span>
<span class="wpml-col-media-filename">
{{ attachment.file_name }}
</span>
</td>
<td class="wpml-col-media-translations">
{% for code, language in languages %}
{% if target_language is empty or target_language == code %}
{% if attachment.language == code %}
<span class="js-otgs-popover-tooltip" data-tippy-distance="-12"
title="{{ languages[attachment.language].name }}: {{ strings.original_language }}">
<i class="otgs-ico-original"></i>
</span>
{% else %}
<span class="wpml-media-wrapper js-otgs-popover-tooltip"
id="media-attachment-{{ attachment.post.ID }}-{{ code }}"
data-file-name="{{ attachment.translations[code].file_name }}"
title="{{ strings.edit_translation | format(languages[code].name ) }}"
{% if not attachment.translations[code].media_is_translated %}
data-tippy-distance="-12"
{% endif %}
data-attachment-id="{{ attachment.translations[code].id }}"
data-language-code="{{ code }}"
data-language-name="{{ language.name }}"
data-url="{{ attachment.url }}"
data-thumb="{{ attachment.translations[code].thumb.src }}"
data-title="{{ attachment.translations[code].title }}"
data-caption="{{ attachment.translations[code].caption }}"
data-alt_text="{{ attachment.translations[code].alt }}"
data-description="{{ attachment.translations[code].description }}"
data-flag="{{ languages[code].flag }}"
data-media-is-translated="{{ attachment.translations[code].media_is_translated }}">
<a class="js-open-media-translation-dialog {% if attachment.translations[code].media_is_translated %}wpml-media-translation-image{% endif %}">
<img src="{{ attachment.translations[code].thumb.src }}"
width="{{ attachment.thumb.width }}" height="{{ attachment.thumb.height }}"
alt="{{ attachment.language }}"
{% if not attachment.is_image %}class="is-non-image"{% endif %}
{% if not attachment.translations[code].media_is_translated %}style="display:none"{% endif %}>
<i class="{% if attachment.translations[code].id %}otgs-ico-edit{% else %}otgs-ico-add{% endif %}"
{% if attachment.translations[code].media_is_translated %}style="display:none"{% endif %}></i>
</a>
</span>
{% endif %}
{% endif %}
{% endfor %}
</td>
</tr>
<div class="wrap">
<h2>{{ strings.heading }}</h2>
{% include 'batch-translation.twig' with batch_translation %}
<div class="tablenav top wpml-media-tablenav">
{% include 'media-translation-filters.twig' %}
</div>
<table class="widefat striped wpml-media-table js-otgs-table-sticky-header">
<thead>
<tr>
<th class="wpml-col-media-title">{{ strings.original_language }}</th>
<th class="wpml-col-media-translations">
{% for code, language in languages %}
{% if target_language is empty or target_language == code %}
<span class="js-otgs-popover-tooltip" title="{{ language.name }}"><img src="{{ language.flag }}"
width="16" height="12"
alt="{{ language.code }}"></span>
{% endif %}
{% endfor %}
</th>
</tr>
</thead>
<tbody>
{% if attachments %}
{% for attachment in attachments %}
{% include 'media-translation-table-row.twig' with {'attachment' : attachment, 'languages': languages, 'strings': strings, 'target_language': target_language } only %}
{% endfor %}
{% else %}
<tr>
<td colspan="2">{{ strings.no_attachments }}</td>
</tr>
{% endif %}
</tbody>
</table>
<div class="tablenav bottom">
{% include 'pagination.twig' with {'pagination_model' : pagination} only %}
{% include 'media-translation-popup.twig' %}
</div>
</div>
\ No newline at end of file
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf770f44c420bc322254dccc6e9ae55eb::getLoader();
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'WPML\\Media\\Classes\\WPML_Media_Attachment_By_URL_Query' => $baseDir . '/classes/class-wpml-media-attachment-by-url-query.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Audio_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-classic-audio-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Element_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-classic-element-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Video_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-classic-video-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Element_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-element-parser.php',
'WPML\\Media\\Classes\\WPML_Media_File_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-file-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Href_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-href-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Image_Parser' => $baseDir . '/classes/media-translation/class-wpml-media-image-parser.php',
'WPML\\Media\\Classes\\WPML_Non_Embedded_Pdf_Parser' => $baseDir . '/classes/media-translation/class-non-embedded-pdf-parser.php',
'WPML\\Media\\Factories\\WPML_Media_Attachment_By_URL_Query_Factory' => $baseDir . '/classes/class-wpml-media-attachment-by-url-query-factory.php',
'WPML\\Media\\Factories\\WPML_Media_Element_Parser_Factory' => $baseDir . '/classes/media-translation/factories/class-wpml-media-element-parser-factory.php',
'WPML\\Media\\Widgets\\Block\\DisplayTranslation' => $baseDir . '/classes/Widgets/Block/DisplayTranslation.php',
'WPML_Cache_Directory' => $vendorDir . '/wpml-shared/wpml-lib-cache/src/cache/class-wpml-cache-directory.php',
'WPML_Core_Version_Check' => $vendorDir . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php',
'WPML_Dependencies' => $vendorDir . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php',
'WPML_Media' => $baseDir . '/classes/class-wpml-media.php',
'WPML_Media_2_3_0_Migration' => $baseDir . '/classes/upgrade/class-wpml-media-2-3-0-migration.php',
'WPML_Media_Add_To_Basket' => $baseDir . '/classes/media-selector/class-wpml-media-add-to-basket.php',
'WPML_Media_Add_To_Basket_Factory' => $baseDir . '/classes/media-selector/class-wpml-media-add-to-basket-factory.php',
'WPML_Media_Attachment_By_URL' => $baseDir . '/classes/class-wpml-media-attachment-by-url.php',
'WPML_Media_Attachment_By_URL_Factory' => $baseDir . '/classes/class-wpml-media-attachment-by-url-factory.php',
'WPML_Media_Attachment_Image_Update' => $baseDir . '/classes/media-translation/class-wpml-media-attachment-image-update.php',
'WPML_Media_Attachment_Image_Update_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-attachment-image-update-factory.php',
'WPML_Media_Attachments_Query' => $baseDir . '/classes/class-wpml-media-attachments-query.php',
'WPML_Media_Attachments_Query_Factory' => $baseDir . '/classes/class-wpml-media-attachments-query-factory.php',
'WPML_Media_Batch_Url_Translation' => $baseDir . '/classes/batch-media-url-translation/wpml-media-batch-media-url-translation.php',
'WPML_Media_Caption' => $baseDir . '/classes/media-translation/class-wpml-media-caption.php',
'WPML_Media_Caption_Tags_Parse' => $baseDir . '/classes/media-translation/class-wpml-media-caption-tags-parse.php',
'WPML_Media_Custom_Field_Batch_Url_Translation' => $baseDir . '/classes/batch-media-url-translation/wpml-media-custom-field-batch-media-url-translation.php',
'WPML_Media_Custom_Field_Batch_Url_Translation_Factory' => $baseDir . '/classes/batch-media-url-translation/wpml-media-custom-field-batch-media-url-translation-factory.php',
'WPML_Media_Custom_Field_Images_Translation' => $baseDir . '/classes/media-translation/class-wpml-media-custom-field-images-translation.php',
'WPML_Media_Custom_Field_Images_Translation_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-custom-field-images-translation-factory.php',
'WPML_Media_Dependencies' => $baseDir . '/inc/wpml-media-dependencies.class.php',
'WPML_Media_Editor_Notices' => $baseDir . '/classes/menus/wpml-media-translations-editor-notices.php',
'WPML_Media_Editor_Notices_Factory' => $baseDir . '/classes/menus/wpml-media-translations-editor-notices-factory.php',
'WPML_Media_Factory' => $baseDir . '/classes/class-wpml-media-factory.php',
'WPML_Media_File' => $baseDir . '/classes/class-wpml-media-file.php',
'WPML_Media_File_Factory' => $baseDir . '/classes/class-wpml-media-file-factory.php',
'WPML_Media_Help_Tab' => $baseDir . '/classes/menus/wpml-media-help-tab.php',
'WPML_Media_Help_Tab_Factory' => $baseDir . '/classes/menus/wpml-media-help-tab-factory.php',
'WPML_Media_Image_Translate' => $baseDir . '/classes/media-translation/class-wpml-media-image-translate.php',
'WPML_Media_Menus' => $baseDir . '/classes/menus/wpml-media-menus.php',
'WPML_Media_Menus_Factory' => $baseDir . '/classes/menus/wpml-media-menus-factory.php',
'WPML_Media_Populate_Media_Strings_Translations' => $baseDir . '/classes/media-translation/wpml-translation-editor/class-wpml-media-populate-media-strings-translations.php',
'WPML_Media_Populate_Media_Strings_Translations_Factory' => $baseDir . '/classes/media-translation/wpml-translation-editor/class-wpml-media-populate-media-strings-translations-factory.php',
'WPML_Media_Post_Batch_Url_Translation' => $baseDir . '/classes/batch-media-url-translation/wpml-media-post-batch-media-url-translation.php',
'WPML_Media_Post_Batch_Url_Translation_Factory' => $baseDir . '/classes/batch-media-url-translation/wpml-media-post-batch-media-url-translation-factory.php',
'WPML_Media_Post_Images_Translation' => $baseDir . '/classes/media-translation/class-wpml-media-post-images-translation.php',
'WPML_Media_Post_Images_Translation_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-post-images-translation-factory.php',
'WPML_Media_Post_Media_Usage' => $baseDir . '/classes/media-usage/class-wpml-media-post-media-usage.php',
'WPML_Media_Post_Media_Usage_Factory' => $baseDir . '/classes/media-usage/class-wpml-media-post-media-usage-factory.php',
'WPML_Media_Post_With_Media_Files' => $baseDir . '/classes/media-translation/class-wpml-media-post-with-media-files.php',
'WPML_Media_Post_With_Media_Files_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-post-with-media-files-factory.php',
'WPML_Media_Posts_Media_Flag_Notice' => $baseDir . '/classes/menus/wpml-media-posts-media-flag-notice.php',
'WPML_Media_Posts_Media_Flag_Notice_Factory' => $baseDir . '/classes/menus/wpml-media-posts-media-flag-notice-factory.php',
'WPML_Media_Privacy_Content' => $baseDir . '/classes/privacy/class-wpml-media-privacy-content.php',
'WPML_Media_Privacy_Content_Factory' => $baseDir . '/classes/privacy/class-wpml-media-privacy-content-factory.php',
'WPML_Media_Save_Translation' => $baseDir . '/classes/media-translation/class-wpml-media-save-translation.php',
'WPML_Media_Save_Translation_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-save-translation-factory.php',
'WPML_Media_Screen_Options' => $baseDir . '/classes/menus/wpml-media-screen-options.php',
'WPML_Media_Screen_Options_Factory' => $baseDir . '/classes/menus/wpml-media-screen-options-factory.php',
'WPML_Media_Selector' => $baseDir . '/classes/media-selector/class-wpml-media-selector.php',
'WPML_Media_Selector_Factory' => $baseDir . '/classes/media-selector/class-wpml-media-selector-factory.php',
'WPML_Media_Set_Initial_Language' => $baseDir . '/classes/setup/class-wpml-media-set-initial-language.php',
'WPML_Media_Set_Initial_Language_Factory' => $baseDir . '/classes/setup/class-wpml-media-set-initial-language-factory.php',
'WPML_Media_Set_Posts_Media_Flag' => $baseDir . '/classes/media-translation/class-wpml-media-set-posts-media-flag.php',
'WPML_Media_Set_Posts_Media_Flag_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-set-posts-media-flag-factory.php',
'WPML_Media_Sizes' => $baseDir . '/classes/media-translation/class-wpml-media-sizes.php',
'WPML_Media_String_Batch_Url_Translation' => $baseDir . '/classes/batch-media-url-translation/wpml-media-string-batch-media-url-translation.php',
'WPML_Media_String_Batch_Url_Translation_Factory' => $baseDir . '/classes/batch-media-url-translation/wpml-media-string-batch-media-url-translation-factory.php',
'WPML_Media_String_Images_Translation' => $baseDir . '/classes/media-translation/class-wpml-media-string-images-translation.php',
'WPML_Media_String_Images_Translation_Factory' => $baseDir . '/classes/media-translation/class-wpml-media-string-images-translation-factory.php',
'WPML_Media_Submitted_Basket_Notice' => $baseDir . '/classes/media-selector/class-wpml-media-submitted-basket-notice.php',
'WPML_Media_Submitted_Basket_Notice_Factory' => $baseDir . '/classes/media-selector/class-wpml-media-submitted-basket-notice-factory.php',
'WPML_Media_Translated_Images_Update' => $baseDir . '/classes/media-translation/class-wpml-media-translated-images-update.php',
'WPML_Media_Translation_Status' => $baseDir . '/classes/media-translation/class-wpml-media-translation-status.php',
'WPML_Media_Translations_UI' => $baseDir . '/classes/menus/wpml-media-translations-ui.php',
'WPML_Media_Upgrade' => $baseDir . '/inc/wpml-media-upgrade.class.php',
'WPML_Media_Usage' => $baseDir . '/classes/media-usage/class-wpml-media-usage.php',
'WPML_Media_Usage_Factory' => $baseDir . '/classes/media-usage/class-wpml-media-usage-factory.php',
'WPML_PHP_Version_Check' => $vendorDir . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-php-version-check.php',
);
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitf770f44c420bc322254dccc6e9ae55eb
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitf770f44c420bc322254dccc6e9ae55eb', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInitf770f44c420bc322254dccc6e9ae55eb', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf770f44c420bc322254dccc6e9ae55eb::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitf770f44c420bc322254dccc6e9ae55eb
{
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'WPML\\Media\\Classes\\WPML_Media_Attachment_By_URL_Query' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachment-by-url-query.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Audio_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-classic-audio-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Element_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-classic-element-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Classic_Video_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-classic-video-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Element_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-element-parser.php',
'WPML\\Media\\Classes\\WPML_Media_File_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-file-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Href_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-href-parser.php',
'WPML\\Media\\Classes\\WPML_Media_Image_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-image-parser.php',
'WPML\\Media\\Classes\\WPML_Non_Embedded_Pdf_Parser' => __DIR__ . '/../..' . '/classes/media-translation/class-non-embedded-pdf-parser.php',
'WPML\\Media\\Factories\\WPML_Media_Attachment_By_URL_Query_Factory' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachment-by-url-query-factory.php',
'WPML\\Media\\Factories\\WPML_Media_Element_Parser_Factory' => __DIR__ . '/../..' . '/classes/media-translation/factories/class-wpml-media-element-parser-factory.php',
'WPML\\Media\\Widgets\\Block\\DisplayTranslation' => __DIR__ . '/../..' . '/classes/Widgets/Block/DisplayTranslation.php',
'WPML_Cache_Directory' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-cache/src/cache/class-wpml-cache-directory.php',
'WPML_Core_Version_Check' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php',
'WPML_Dependencies' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php',
'WPML_Media' => __DIR__ . '/../..' . '/classes/class-wpml-media.php',
'WPML_Media_2_3_0_Migration' => __DIR__ . '/../..' . '/classes/upgrade/class-wpml-media-2-3-0-migration.php',
'WPML_Media_Add_To_Basket' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-add-to-basket.php',
'WPML_Media_Add_To_Basket_Factory' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-add-to-basket-factory.php',
'WPML_Media_Attachment_By_URL' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachment-by-url.php',
'WPML_Media_Attachment_By_URL_Factory' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachment-by-url-factory.php',
'WPML_Media_Attachment_Image_Update' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-attachment-image-update.php',
'WPML_Media_Attachment_Image_Update_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-attachment-image-update-factory.php',
'WPML_Media_Attachments_Query' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachments-query.php',
'WPML_Media_Attachments_Query_Factory' => __DIR__ . '/../..' . '/classes/class-wpml-media-attachments-query-factory.php',
'WPML_Media_Batch_Url_Translation' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-batch-media-url-translation.php',
'WPML_Media_Caption' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-caption.php',
'WPML_Media_Caption_Tags_Parse' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-caption-tags-parse.php',
'WPML_Media_Custom_Field_Batch_Url_Translation' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-custom-field-batch-media-url-translation.php',
'WPML_Media_Custom_Field_Batch_Url_Translation_Factory' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-custom-field-batch-media-url-translation-factory.php',
'WPML_Media_Custom_Field_Images_Translation' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-custom-field-images-translation.php',
'WPML_Media_Custom_Field_Images_Translation_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-custom-field-images-translation-factory.php',
'WPML_Media_Dependencies' => __DIR__ . '/../..' . '/inc/wpml-media-dependencies.class.php',
'WPML_Media_Editor_Notices' => __DIR__ . '/../..' . '/classes/menus/wpml-media-translations-editor-notices.php',
'WPML_Media_Editor_Notices_Factory' => __DIR__ . '/../..' . '/classes/menus/wpml-media-translations-editor-notices-factory.php',
'WPML_Media_Factory' => __DIR__ . '/../..' . '/classes/class-wpml-media-factory.php',
'WPML_Media_File' => __DIR__ . '/../..' . '/classes/class-wpml-media-file.php',
'WPML_Media_File_Factory' => __DIR__ . '/../..' . '/classes/class-wpml-media-file-factory.php',
'WPML_Media_Help_Tab' => __DIR__ . '/../..' . '/classes/menus/wpml-media-help-tab.php',
'WPML_Media_Help_Tab_Factory' => __DIR__ . '/../..' . '/classes/menus/wpml-media-help-tab-factory.php',
'WPML_Media_Image_Translate' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-image-translate.php',
'WPML_Media_Menus' => __DIR__ . '/../..' . '/classes/menus/wpml-media-menus.php',
'WPML_Media_Menus_Factory' => __DIR__ . '/../..' . '/classes/menus/wpml-media-menus-factory.php',
'WPML_Media_Populate_Media_Strings_Translations' => __DIR__ . '/../..' . '/classes/media-translation/wpml-translation-editor/class-wpml-media-populate-media-strings-translations.php',
'WPML_Media_Populate_Media_Strings_Translations_Factory' => __DIR__ . '/../..' . '/classes/media-translation/wpml-translation-editor/class-wpml-media-populate-media-strings-translations-factory.php',
'WPML_Media_Post_Batch_Url_Translation' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-post-batch-media-url-translation.php',
'WPML_Media_Post_Batch_Url_Translation_Factory' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-post-batch-media-url-translation-factory.php',
'WPML_Media_Post_Images_Translation' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-post-images-translation.php',
'WPML_Media_Post_Images_Translation_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-post-images-translation-factory.php',
'WPML_Media_Post_Media_Usage' => __DIR__ . '/../..' . '/classes/media-usage/class-wpml-media-post-media-usage.php',
'WPML_Media_Post_Media_Usage_Factory' => __DIR__ . '/../..' . '/classes/media-usage/class-wpml-media-post-media-usage-factory.php',
'WPML_Media_Post_With_Media_Files' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-post-with-media-files.php',
'WPML_Media_Post_With_Media_Files_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-post-with-media-files-factory.php',
'WPML_Media_Posts_Media_Flag_Notice' => __DIR__ . '/../..' . '/classes/menus/wpml-media-posts-media-flag-notice.php',
'WPML_Media_Posts_Media_Flag_Notice_Factory' => __DIR__ . '/../..' . '/classes/menus/wpml-media-posts-media-flag-notice-factory.php',
'WPML_Media_Privacy_Content' => __DIR__ . '/../..' . '/classes/privacy/class-wpml-media-privacy-content.php',
'WPML_Media_Privacy_Content_Factory' => __DIR__ . '/../..' . '/classes/privacy/class-wpml-media-privacy-content-factory.php',
'WPML_Media_Save_Translation' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-save-translation.php',
'WPML_Media_Save_Translation_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-save-translation-factory.php',
'WPML_Media_Screen_Options' => __DIR__ . '/../..' . '/classes/menus/wpml-media-screen-options.php',
'WPML_Media_Screen_Options_Factory' => __DIR__ . '/../..' . '/classes/menus/wpml-media-screen-options-factory.php',
'WPML_Media_Selector' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-selector.php',
'WPML_Media_Selector_Factory' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-selector-factory.php',
'WPML_Media_Set_Initial_Language' => __DIR__ . '/../..' . '/classes/setup/class-wpml-media-set-initial-language.php',
'WPML_Media_Set_Initial_Language_Factory' => __DIR__ . '/../..' . '/classes/setup/class-wpml-media-set-initial-language-factory.php',
'WPML_Media_Set_Posts_Media_Flag' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-set-posts-media-flag.php',
'WPML_Media_Set_Posts_Media_Flag_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-set-posts-media-flag-factory.php',
'WPML_Media_Sizes' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-sizes.php',
'WPML_Media_String_Batch_Url_Translation' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-string-batch-media-url-translation.php',
'WPML_Media_String_Batch_Url_Translation_Factory' => __DIR__ . '/../..' . '/classes/batch-media-url-translation/wpml-media-string-batch-media-url-translation-factory.php',
'WPML_Media_String_Images_Translation' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-string-images-translation.php',
'WPML_Media_String_Images_Translation_Factory' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-string-images-translation-factory.php',
'WPML_Media_Submitted_Basket_Notice' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-submitted-basket-notice.php',
'WPML_Media_Submitted_Basket_Notice_Factory' => __DIR__ . '/../..' . '/classes/media-selector/class-wpml-media-submitted-basket-notice-factory.php',
'WPML_Media_Translated_Images_Update' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-translated-images-update.php',
'WPML_Media_Translation_Status' => __DIR__ . '/../..' . '/classes/media-translation/class-wpml-media-translation-status.php',
'WPML_Media_Translations_UI' => __DIR__ . '/../..' . '/classes/menus/wpml-media-translations-ui.php',
'WPML_Media_Upgrade' => __DIR__ . '/../..' . '/inc/wpml-media-upgrade.class.php',
'WPML_Media_Usage' => __DIR__ . '/../..' . '/classes/media-usage/class-wpml-media-usage.php',
'WPML_Media_Usage_Factory' => __DIR__ . '/../..' . '/classes/media-usage/class-wpml-media-usage-factory.php',
'WPML_PHP_Version_Check' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-php-version-check.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->classMap = ComposerStaticInitf770f44c420bc322254dccc6e9ae55eb::$classMap;
}, null, ClassLoader::class);
}
}
<?php return array(
'root' => array(
'pretty_version' => '2.7.3',
'version' => '2.7.3.0',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '8092d6db990d4c9926fffc1c8267cc990d7dfa1d',
'name' => 'wpml/media',
'dev' => false,
),
'versions' => array(
'roave/security-advisories' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'type' => 'metapackage',
'install_path' => NULL,
'aliases' => array(),
'reference' => 'dad1e44d86f958c5be9c5f355c9554ce22f1b1a7',
'dev_requirement' => false,
),
'wpml-shared/wpml-lib-cache' => array(
'pretty_version' => '0.1.0',
'version' => '0.1.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../wpml-shared/wpml-lib-cache',
'aliases' => array(),
'reference' => '4bbcffee0b82285f4037b2b0fbeee72e924e3fe5',
'dev_requirement' => false,
),
'wpml-shared/wpml-lib-dependencies' => array(
'pretty_version' => '0.1.6',
'version' => '0.1.6.0',
'type' => 'library',
'install_path' => __DIR__ . '/../wpml-shared/wpml-lib-dependencies',
'aliases' => array(),
'reference' => '723824a61bfec7dd535afcd7260fad50d8bfe6e8',
'dev_requirement' => false,
),
'wpml/media' => array(
'pretty_version' => '2.7.3',
'version' => '2.7.3.0',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '8092d6db990d4c9926fffc1c8267cc990d7dfa1d',
'dev_requirement' => false,
),
),
);
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 50600)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}
<?php
class WPML_Cache_Directory {
const DIR_PERMISSIONS = 0775;
const MAIN_DIRECTORY_NAME = 'wpml';
const NOTICE_GROUP = 'wpml-cache-directory';
const NOTICE_INVALID_CACHE = 'invalid-cache';
private $cache_disabled = false;
/**
* @var WPML_WP_API
*/
private $wp_api;
/**
* @var WP_Filesystem_Direct
*/
private $filesystem;
/**
* WPML_Cache_Directory constructor.
*
* @param WPML_WP_API $wp_api
*/
public function __construct( WPML_WP_API $wp_api ) {
$this->wp_api = $wp_api;
$this->filesystem = $wp_api->get_wp_filesystem_direct();
}
/**
* @return string
*/
private function get_main_directory_path() {
$main_directory_path = null;
$cache_path_root = $this->wp_api->constant( 'WPML_CACHE_PATH_ROOT' );
if ( $cache_path_root ) {
$main_directory_path = trailingslashit( $cache_path_root ) . self::MAIN_DIRECTORY_NAME;
return trailingslashit( $main_directory_path );
}else {
$upload_dir = wp_upload_dir();
if ( empty( $upload_dir['error'] ) ) {
$base_dir = $upload_dir['basedir'];
$main_directory_path = trailingslashit( $base_dir ) . 'cache/' . self::MAIN_DIRECTORY_NAME;
return trailingslashit( $main_directory_path );
}
}
return null;
}
/**
* The function `wp_mkdir_p` will create directories recursively
*
* @param string $absolute_path
*
* @return string|bool absolute path or false if we can't have a writable and readable directory
*/
private function maybe_create_directory( $absolute_path ) {
$result = true;
if ( ! $this->filesystem->is_dir( $absolute_path ) ) {
$result = wp_mkdir_p( $absolute_path );
}
return $result ? $absolute_path : false;
}
/**
* @param string $relative_path
*
* @return string|bool absolute path or false if we can't have a writable and readable directory
*/
public function get( $relative_path = '' ) {
$absolute_path = false;
$main_directory_path = $this->maybe_create_directory( $this->get_main_directory_path() );
if ( $main_directory_path ) {
$absolute_path = trailingslashit( $main_directory_path . ltrim( $relative_path, '/\\' ) );
$absolute_path = $this->maybe_create_directory( $absolute_path );
}
return $absolute_path;
}
/**
* @param string $relative_path
*/
public function remove( $relative_path = '' ) {
$main_directory_path = $this->get_main_directory_path();
if ( $main_directory_path ) {
$absolute_path = trailingslashit( $main_directory_path . ltrim( $relative_path, '/\\' ) );
$this->filesystem->delete( $absolute_path, true );
}
}
}
<?php
class WPML_Core_Version_Check {
public static function is_ok( $package_file_path ) {
$is_ok = false;
/** @var array $bundle */
$bundle = json_decode( file_get_contents( $package_file_path ), true );
if ( defined( 'ICL_SITEPRESS_VERSION' ) && is_array( $bundle ) ) {
$core_version_stripped = ICL_SITEPRESS_VERSION;
$dev_or_beta_pos = strpos( ICL_SITEPRESS_VERSION, '-' );
if ( $dev_or_beta_pos > 0 ) {
$core_version_stripped = substr( ICL_SITEPRESS_VERSION, 0, $dev_or_beta_pos );
}
if ( version_compare( $core_version_stripped, $bundle['sitepress-multilingual-cms'], '>=' ) ) {
$is_ok = true;
}
}
return $is_ok;
}
}
\ No newline at end of file
<?php
/*
Module Name: WPML Dependency Check Module
Description: This is not a plugin! This module must be included in other plugins (WPML and add-ons) to handle compatibility checks
Author: OnTheGoSystems
Author URI: http://www.onthegosystems.com/
Version: 2.1
*/
/** @noinspection PhpUndefinedClassInspection */
class WPML_Dependencies {
protected static $instance;
private $admin_notice;
private $current_product;
private $current_version = array();
private $expected_versions = array();
private $installed_plugins = array();
private $invalid_plugins = array();
private $valid_plugins = array();
private $validation_results = array();
public $data_key = 'wpml_dependencies:';
public $needs_validation_key = 'wpml_dependencies:needs_validation';
private function __construct() {
if ( null === self::$instance ) {
$this->remove_old_admin_notices();
$this->init_hooks();
}
}
private function collect_data() {
$active_plugins = wp_get_active_and_valid_plugins();
$this->init_bundle( $active_plugins );
foreach ( $active_plugins as $plugin ) {
$this->add_installed_plugin( $plugin );
}
}
protected function remove_old_admin_notices() {
if ( class_exists( 'WPML_Bundle_Check' ) ) {
global $WPML_Bundle_Check;
remove_action( 'admin_notices', array( $WPML_Bundle_Check, 'admin_notices_action' ) );
}
}
private function init_hooks() {
add_action( 'init', array( $this, 'init_plugins_action' ) );
add_action( 'extra_plugin_headers', array( $this, 'extra_plugin_headers_action' ) );
add_action( 'admin_notices', array( $this, 'admin_notices_action' ) );
add_action( 'activated_plugin', array( $this, 'activated_plugin_action' ) );
add_action( 'deactivated_plugin', array( $this, 'deactivated_plugin_action' ) );
add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete_action' ), 10, 2 );
add_action( 'load-plugins.php', array( $this, 'run_validation_on_plugins_page' ) );
}
public function run_validation_on_plugins_page() {
$this->reset_validation();
}
public function activated_plugin_action() {
$this->reset_validation();
}
public function deactivated_plugin_action() {
$this->reset_validation();
}
public function upgrader_process_complete_action( $upgrader_object, $options ) {
if ( 'update' === $options['action'] && 'plugin' === $options['type'] ) {
$this->reset_validation();
}
}
private function reset_validation() {
update_option( $this->needs_validation_key, true );
$this->validate_plugins();
}
private function flag_as_validated() {
update_option( $this->needs_validation_key, false );
}
private function needs_validation() {
return get_option( $this->needs_validation_key );
}
public function admin_notices_action() {
$this->maybe_init_admin_notice();
if ( $this->admin_notice && ( is_admin() && ! $this->is_doing_ajax_cron_or_xmlrpc() ) ) {
echo $this->admin_notice;
}
}
private function is_doing_ajax_cron_or_xmlrpc() {
return ( $this->is_doing_ajax() || $this->is_doing_cron() || $this->is_doing_xmlrpc() );
}
private function is_doing_ajax() {
return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
}
private function is_doing_cron() {
return ( defined( 'DOING_CRON' ) && DOING_CRON );
}
private function is_doing_xmlrpc() {
return ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST );
}
public function extra_plugin_headers_action( array $extra_headers = array() ) {
$new_extra_header = array(
'PluginSlug' => 'Plugin Slug',
);
return array_merge( $new_extra_header, (array) $extra_headers );
}
/**
* @return WPML_Dependencies
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new WPML_Dependencies();
}
return self::$instance;
}
public function get_plugins() {
return $this->installed_plugins;
}
public function init_plugins_action() {
if ( $this->needs_validation() && is_admin() && ! $this->is_doing_ajax_cron_or_xmlrpc() ) {
$this->init_plugins();
$this->validate_plugins();
$this->flag_as_validated();
}
}
private function init_plugins() {
if ( ! $this->installed_plugins ) {
if ( ! function_exists( 'get_plugin_data' ) ) {
/** @noinspection PhpIncludeInspection */
include_once ABSPATH . '/wp-admin/includes/plugin.php';
}
if ( function_exists( 'get_plugin_data' ) ) {
$this->collect_data();
}
}
update_option( $this->data_key . 'installed_plugins', $this->installed_plugins );
}
private function init_bundle( array $active_plugins ) {
foreach ( $active_plugins as $plugin_file ) {
$filename = dirname( $plugin_file ) . '/wpml-dependencies.json';
if ( file_exists( $filename ) ) {
$data = file_get_contents( $filename );
$bundle = json_decode( $data, true );
$this->set_expected_versions( $bundle );
}
}
}
private function add_installed_plugin( $plugin ) {
$data = get_plugin_data( $plugin );
$plugin_dir = realpath( dirname( $plugin ) );
$wp_plugin_dir = realpath( WP_PLUGIN_DIR ) . DIRECTORY_SEPARATOR;
if ( false !== $plugin_dir && $wp_plugin_dir !== $plugin_dir ) {
$plugin_folder = str_replace( $wp_plugin_dir, '', $plugin_dir );
$plugin_slug = $this->guess_plugin_slug( $data, $plugin_folder );
if ( $this->is_valid_plugin( $plugin_slug ) ) {
$this->installed_plugins[ $plugin_slug ] = $data['Version'];
}
}
}
private function set_expected_versions( array $bundle ) {
foreach ( $bundle as $plugin => $version ) {
if ( ! array_key_exists( $plugin, $this->expected_versions ) ) {
$this->expected_versions[ $plugin ] = $version;
} else {
if ( version_compare( $this->expected_versions[ $plugin ], $version, '<' ) ) {
$this->expected_versions[ $plugin ] = $version;
}
}
}
}
private function guess_plugin_slug( $plugin_data, $plugin_folder ) {
$plugin_slug = null;
$plugin_slug = $plugin_folder;
if ( array_key_exists( 'Plugin Slug', $plugin_data ) && $plugin_data['Plugin Slug'] ) {
$plugin_slug = $plugin_data['Plugin Slug'];
}
return $plugin_slug;
}
private function validate_plugins() {
$validation_results = $this->get_plugins_validation();
$this->valid_plugins = array();
$this->invalid_plugins = array();
foreach ( $validation_results as $plugin => $validation_result ) {
if ( true === $validation_result ) {
$this->valid_plugins[] = $plugin;
} else {
$this->invalid_plugins[] = $plugin;
}
}
update_option( $this->data_key . 'valid_plugins', $this->valid_plugins );
update_option( $this->data_key . 'invalid_plugins', $this->invalid_plugins );
update_option( $this->data_key . 'expected_versions', $this->expected_versions );
}
public function get_plugins_validation() {
foreach ( $this->installed_plugins as $plugin => $version ) {
$this->current_product = $plugin;
if ( $this->is_valid_plugin() ) {
$this->current_version = $version;
$validation_result = $this->is_plugin_version_valid();
$this->validation_results[ $plugin ] = $validation_result;
}
}
return $this->validation_results;
}
private function is_valid_plugin( $product = false ) {
$result = false;
if ( ! $product ) {
$product = $this->current_product;
}
if ( $product ) {
$versions = $this->get_expected_versions();
$result = array_key_exists( $product, $versions );
}
return $result;
}
public function is_plugin_version_valid() {
$expected_version = $this->filter_version( $this->get_expected_product_version() );
return $expected_version ? version_compare( $this->filter_version( $this->current_version ), $expected_version, '>=' ) : null;
}
private function filter_version( $version ) {
return preg_replace( '#[^\d.].*#', '', $version );
}
public function get_expected_versions() {
return $this->expected_versions;
}
private function get_expected_product_version( $product = false ) {
$result = null;
if ( ! $product ) {
$product = $this->current_product;
}
if ( $product ) {
$versions = $this->get_expected_versions();
$result = isset( $versions[ $product ] ) ? $versions[ $product ] : null;
}
return $result;
}
private function maybe_init_admin_notice() {
$this->admin_notice = null;
$this->installed_plugins = get_option( $this->data_key . 'installed_plugins', [] );
$this->invalid_plugins = get_option( $this->data_key . 'invalid_plugins', [] );
$this->expected_versions = get_option( $this->data_key . 'expected_versions', [] );
$this->valid_plugins = get_option( $this->data_key . 'valid_plugins', [] );
if ( $this->has_invalid_plugins() ) {
$notice_paragraphs = array();
$notice_paragraphs[] = $this->get_invalid_plugins_report_header();
$notice_paragraphs[] = $this->get_invalid_plugins_report_list();
$notice_paragraphs[] = $this->get_invalid_plugins_report_footer();
$this->admin_notice = '<div class="error wpml-admin-notice">';
$this->admin_notice .= '<h3>' . __( 'WPML Update is Incomplete', 'sitepress' ) . '</h3>';
$this->admin_notice .= '<p>' . implode( '</p><p>', $notice_paragraphs ) . '</p>';
$this->admin_notice .= '</div>';
}
}
public function has_invalid_plugins() {
return count( $this->invalid_plugins );
}
private function get_invalid_plugins_report_header() {
if ( $this->has_valid_plugins() ) {
if ( count( $this->valid_plugins ) === 1 ) {
$paragraph = __( 'You are running updated %s, but the following component is not updated:', 'sitepress' );
$paragraph = sprintf( $paragraph, '<strong>' . $this->valid_plugins[0] . '</strong>' );
} else {
$paragraph = __( 'You are running updated %s and %s, but the following components are not updated:', 'sitepress' );
$first_valid_plugins = implode( ', ', array_slice( $this->valid_plugins, 0, - 1 ) );
$last_valid_plugin = array_slice( $this->valid_plugins, - 1 );
$paragraph = sprintf( $paragraph, '<strong>' . $first_valid_plugins . '</strong>', '<strong>' . $last_valid_plugin[0] . '</strong>' );
}
} else {
$paragraph = __( 'The following components are not updated:', 'sitepress' );
}
return $paragraph;
}
private function get_invalid_plugins_report_list() {
/* translators: %s: Version number */
$required_version = __( 'required version: %s', 'sitepress' );
$invalid_plugins_list = '<ul class="ul-disc">';
foreach ( $this->invalid_plugins as $invalid_plugin ) {
$plugin_name_html = '<li data-installed-version="' . $this->installed_plugins[ $invalid_plugin ] . '">';
$required_version_string = '';
if ( isset( $this->expected_versions[ $invalid_plugin ] ) ) {
$required_version_string = ' (' . sprintf( $required_version, $this->expected_versions[ $invalid_plugin ] ) . ')';
}
$plugin_name_html .= $invalid_plugin . $required_version_string;
$plugin_name_html .= '</li>';
$invalid_plugins_list .= $plugin_name_html;
}
$invalid_plugins_list .= '</ul>';
return $invalid_plugins_list;
}
private function get_invalid_plugins_report_footer() {
$wpml_org_url = '<a href="https://wpml.org/account/" title="WPML.org account">' . __( 'WPML.org account', 'sitepress' ) . '</a>';
$notice_paragraph = __( 'Your site will not work as it should in this configuration', 'sitepress' );
$notice_paragraph .= ' ';
$notice_paragraph .= __( 'Please update all components which you are using.', 'sitepress' );
$notice_paragraph .= ' ';
$notice_paragraph .= sprintf( __( 'For WPML components you can receive updates from your %s or automatically, after you register WPML.', 'sitepress' ), $wpml_org_url );
return $notice_paragraph;
}
private function has_valid_plugins() {
return $this->valid_plugins && count( $this->valid_plugins );
}
}
<?php
/**
* WPML_PHP_Version_Check class file.
*
* @package WPML\LibDependencies
*/
if ( ! class_exists( 'WPML_PHP_Version_Check' ) ) {
/**
* Class WPML_PHP_Version_Check
*/
class WPML_PHP_Version_Check {
/**
* Required php version.
*
* @var string
*/
private $required_php_version;
/**
* Plugin name.
*
* @var string
*/
private $plugin_name;
/**
* Plugin file.
*
* @var string
*/
private $plugin_file;
/**
* Text domain.
*
* @var string
*/
private $text_domain;
/**
* WPML_PHP_Version_Check constructor.
*
* @param string $required_version Required php version.
* @param string $plugin_name Plugin name.
* @param string $plugin_file Plugin file.
* @param string $text_domain Text domain.
*/
public function __construct( $required_version, $plugin_name, $plugin_file, $text_domain ) {
$this->required_php_version = $required_version;
$this->plugin_name = $plugin_name;
$this->plugin_file = $plugin_file;
$this->text_domain = $text_domain;
}
/**
* Check php version.
*
* @return bool
*/
public function is_ok() {
if ( version_compare( $this->required_php_version, phpversion(), '>' ) ) {
add_action( 'admin_notices', array( $this, 'php_requirement_message' ) );
return false;
}
return true;
}
/**
* Show notice with php requirement.
*/
public function php_requirement_message() {
load_plugin_textdomain( $this->text_domain, false, dirname( plugin_basename( $this->plugin_file ) ) . '/locale' );
$errata_page_link = 'https://wpml.org/errata/parse-error-syntax-error-unexpected-t_class-and-other-errors-when-using-php-versions-older-than-5-6/';
// phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralDomain
/* translators: 1: Current PHP version number, 2: Plugin version, 3: Minimum required PHP version number */
$message = sprintf( __( 'Your server is running PHP version %1$s but %2$s requires at least %3$s.', $this->text_domain ), phpversion(), $this->plugin_name, $this->required_php_version );
$message .= '<br>';
/* translators: Link to errata page */
$message .= sprintf( __( 'You can find version of the plugin suitable for your environment <a href="%s">here</a>.', $this->text_domain ), $errata_page_link );
// phpcs:enable WordPress.WP.I18n.NonSingularStringLiteralDomain
?>
<div class="message error">
<p>
<?php echo wp_kses_post( $message ); ?>
</p>
</div>
<?php
}
}
}
<wpml-config>
<custom-fields>
<custom-field action="copy">_wpml_media_duplicate</custom-field>
<custom-field action="copy">_wpml_media_featured</custom-field>
</custom-fields>
</wpml-config>
\ No newline at end of file
{
"sitepress-multilingual-cms": "4.5.0",
"wpml-string-translation": "3.2.0",
"wpml-media-translation": "2.7.0",
"wpml-sticky-links": "1.5.0",
"wpml-cms-nav": "1.5.0",
"gravityforms-multilingual": "1.5.0"
}
\ No newline at end of file
......@@ -87,13 +87,11 @@ $carousel_style = get_field('carousel_style');
);
$new_src = add_query_arg($params, $src);
$iframe = str_replace($src, $new_src, $iframe);
error_log($src);
error_log($iframe);
// Add extra attributes to iframe HTML.
$attributes = 'frameborder="0"';
$iframe = str_replace('></iframe>', ' ' . $attributes . '></iframe>', $iframe);
$iframe = str_replace('<iframe', '<iframe class="yt_player_iframe" ', $iframe);
error_log($iframe); ?>
$iframe = str_replace('<iframe', '<iframe class="yt_player_iframe" ', $iframe);?>
<div class="modal" id="<?php echo $modalId; ?>" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content">
......
......@@ -2,6 +2,6 @@
Theme Name: MSF CA Child
Author: Tenzing Communications
Template: msf-ca
Version: 1.0.510
Version: 1.0.511
*/
......