Files
doitinpoland.com/wp-content/plugins/wpml-media-translation/classes/media-translation/class-wpml-media-post-images-translation.php
2023-09-12 21:41:04 +02:00

336 lines
10 KiB
PHP

<?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 {
/**
* @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() ) {
$this->translate_images_in_post_content( get_post( $translation->get_id() ), $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( WPML_Media_Add_To_Translation_Package::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="' . WPML_Media_Add_To_Translation_Package::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;
}
}