Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/media-translation.tar
Назад
class-wpml-media-custom-field-images-translation.php 0000644 00000007102 14721521357 0016613 0 ustar 00 <?php use WPML\Media\Classes\WPML_Media_Element_Translation_Factory; /** * 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 = WPML_Media_Element_Translation_Factory::create( $object_id ); $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; } } class-wpml-media-classic-audio-parser.php 0000644 00000001675 14721521357 0014444 0 ustar 00 <?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 ); } } class-wpml-media-set-posts-media-flag.php 0000644 00000010726 14721521357 0014354 0 ustar 00 <?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(); } } class-wpml-media-post-images-translation-factory.php 0000644 00000002125 14721521357 0016652 0 ustar 00 <?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; } } class-wpml-media-attachment-image-update.php 0000644 00000010506 14721521357 0015113 0 ustar 00 <?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' ); } } class-wpml-media-element-parser.php 0000644 00000001611 14721521357 0013343 0 ustar 00 <?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; } } class-wpml-media-image-parser.php 0000644 00000006505 14721521357 0013003 0 ustar 00 <?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; } } class-wpml-media-set-posts-media-flag-factory.php 0000644 00000000617 14721521357 0016017 0 ustar 00 <?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() ); } } factories/class-wpml-media-element-parser-factory.php 0000644 00000003011 14721521357 0016763 0 ustar 00 <?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; } } class-wpml-media-image-translate.php 0000644 00000014513 14721521357 0013502 0 ustar 00 <?php use WPML\LIB\WP\Cache; use WPML\Media\Classes\WPML_Media_Element_Translation_Factory; /** * Class WPML_Media_Image_Translate * Allows getting translated images in a give language from an attachment */ class WPML_Media_Image_Translate { const URLS_TO_IDS_CACHE_KEY = 'urls-to-ids-cache-key'; /** * @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(); wp_cache_add_non_persistent_groups( self::URLS_TO_IDS_CACHE_KEY ); } /** * @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|null $language * @param string|null $size * * @return string */ public function get_translated_image( $attachment_id, $language = null, $size = null ) { if ( ! $language ) { $language = $this->sitepress->get_current_language(); } $image_url = ''; $attachment = WPML_Media_Element_Translation_Factory::create( $attachment_id ); $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|null $source_language * @param string|null $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|null $source_language * * @return int */ public function get_attachment_id_by_url( $img_src, $source_language = null ) { if ( ! $source_language ) { $source_language = $this->getLanguageByUrl( $img_src ) ?: $this->sitepress->get_current_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 * * @return null|string */ private function getLanguageByUrl( $url ) { $imageUrl = WPML_Media_Attachment_By_URL::getUrl( $url ); $imageId = Cache::get( self::URLS_TO_IDS_CACHE_KEY, $imageUrl )->getOrElse( null ); if ( ! $imageId ) { $imageId = attachment_url_to_postid( $imageUrl ); Cache::set( self::URLS_TO_IDS_CACHE_KEY, $imageUrl, HOUR_IN_SECONDS, $imageId ); } return $this->sitepress->get_language_for_element( $imageId, 'post_attachment' ); } /** * @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; } } class-wpml-media-file-parser.php 0000644 00000001475 14721521357 0012641 0 ustar 00 <?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' ); } } class-wpml-media-save-translation.php 0000644 00000025602 14721521357 0013720 0 ustar 00 <?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 ); } } } class-wpml-media-string-images-translation.php 0000644 00000002734 14721521357 0015534 0 ustar 00 <?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; } } class-wpml-media-classic-element-parser.php 0000644 00000003005 14721521357 0014761 0 ustar 00 <?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; } } class-wpml-media-post-images-translation.php 0000644 00000024654 14721521357 0015220 0 ustar 00 <?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; } } class-wpml-media-classic-video-parser.php 0000644 00000001675 14721521357 0014451 0 ustar 00 <?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 ); } } class-wpml-media-translation-status.php 0000644 00000000472 14721521357 0014303 0 ustar 00 <?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_'; } class-wpml-media-caption-tags-parse.php 0000644 00000000753 14721521357 0014127 0 ustar 00 <?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; } } class-wpml-media-href-parser.php 0000644 00000003366 14721521357 0012647 0 ustar 00 <?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(); } } class-wpml-media-sizes.php 0000644 00000006045 14721521357 0011563 0 ustar 00 <?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; } } class-wpml-media-post-with-media-files-factory.php 0000644 00000001065 14721521357 0016203 0 ustar 00 <?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() ); } } class-non-embedded-pdf-parser.php 0000644 00000001733 14721521357 0012755 0 ustar 00 <?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 ); } } class-wpml-media-custom-field-images-translation-factory.php 0000644 00000001723 14721521357 0020263 0 ustar 00 <?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; } } class-wpml-media-save-translation-factory.php 0000644 00000000541 14721521357 0015360 0 ustar 00 <?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 ) ); } } wpml-translation-editor/class-wpml-media-populate-media-strings-translations.php 0000644 00000005502 14721521357 0024336 0 ustar 00 <?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; } } wpml-translation-editor/class-wpml-media-populate-media-strings-translations-factory.php 0000644 00000000614 14721521357 0026002 0 ustar 00 <?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() ); } } } class-wpml-media-string-images-translation-factory.php 0000644 00000001611 14721521357 0017172 0 ustar 00 <?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; } } class-wpml-media-caption.php 0000644 00000005450 14721521357 0012062 0 ustar 00 <?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; } } class-wpml-media-attachment-image-update-factory.php 0000644 00000000412 14721521357 0016553 0 ustar 00 <?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 ); } } class-wpml-media-translated-images-update.php 0000644 00000024426 14721521357 0015315 0 ustar 00 <?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; } } class-wpml-media-element-translation-factory.php 0000644 00000000542 14721521357 0016054 0 ustar 00 <?php namespace WPML\Media\Classes; class WPML_Media_Element_Translation_Factory { /** * @param int $mediaId * * @return \WPML_Post_Element */ public static function create( $mediaId ) { /** @var \SitePress $sitepress */ global $sitepress; return ( new \WPML_Translation_Element_Factory( $sitepress ) )->create_post( $mediaId ); } } class-wpml-media-post-with-media-files.php 0000644 00000020404 14721521357 0014534 0 ustar 00 <?php use WPML\FP\Fns; use WPML\LIB\WP\Post; use WPML\Media\Classes\WPML_Media_Element_Translation_Factory; 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 = WPML_Media_Element_Translation_Factory::create( $attachment_id ); 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 ); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0.01 |
proxy
|
phpinfo
|
Настройка