Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/media.tar
Назад
duplication/Hooks.php 0000644 00000001742 14721660154 0010665 0 ustar 00 <?php namespace WPML\Media\Duplication; use WPML\Element\API\IfOriginalPost; use WPML\FP\Fns; use WPML\FP\Relation; use WPML\LIB\WP\Post; use WPML\LIB\WP\Hooks as WPHooks; use function WPML\FP\pipe; use function WPML\FP\spreadArgs; class Hooks { public static function add() { WPHooks::onAction( 'update_postmeta', 10, 4 ) ->then( spreadArgs( Fns::withoutRecursion( Fns::noop(), [ self::class, 'syncAttachedFile' ] ) ) ); } public static function syncAttachedFile( $meta_id, $object_id, $meta_key, $meta_value ) { if ( $meta_key === '_wp_attached_file' ) { $prevValue = Post::getMetaSingle( $object_id, $meta_key ); // $isMetaSameAsPrevious :: id → bool $isMetaSameAsPrevious = pipe( Post::getMetaSingle( Fns::__, $meta_key ), Relation::equals( $prevValue ) ); IfOriginalPost::getTranslationIds( $object_id ) ->filter( Fns::unary( $isMetaSameAsPrevious ) ) ->each( Fns::unary( Post::updateMeta( Fns::__, $meta_key, $meta_value ) ) ); } } } duplication/class-wpml-media-attachments-duplication-factory.php 0000644 00000000424 14721660154 0021224 0 ustar 00 <?php class WPML_Media_Attachments_Duplication_Factory extends \WPML\Media\Duplication\AbstractFactory { public function create() { if ( self::shouldActivateHooks() ) { return \WPML\Container\make( WPML_Media_Attachments_Duplication::class ); } return null; } } duplication/AbstractFactory.php 0000644 00000000473 14721660154 0012675 0 ustar 00 <?php namespace WPML\Media\Duplication; abstract class AbstractFactory implements \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader { /** * @return bool */ protected static function shouldActivateHooks() { return \WPML_Element_Sync_Settings_Factory::createPost()->is_sync( 'attachment' ); } } duplication/class-wpml-media-attachments-duplication.php 0000644 00000151447 14721660154 0017573 0 ustar 00 <?php use WPML\FP\Obj; use WPML\LIB\WP\Nonce; use WPML\LIB\WP\User; use WPML\Media\Option; class WPML_Media_Attachments_Duplication { const WPML_MEDIA_PROCESSED_META_KEY = 'wpml_media_processed'; /** @var WPML_Model_Attachments */ private $attachments_model; /** @var SitePress */ private $sitepress; private $wpdb; private $language_resolution; private $original_thumbnail_ids = array(); /** * WPML_Media_Attachments_Duplication constructor. * * @param SitePress $sitepress * @param WPML_Model_Attachments $attachments_model * * @internal param WPML_WP_API $wpml_wp_api */ public function __construct( SitePress $sitepress, WPML_Model_Attachments $attachments_model, wpdb $wpdb, WPML_Language_Resolution $language_resolution ) { $this->sitepress = $sitepress; $this->attachments_model = $attachments_model; $this->wpdb = $wpdb; $this->language_resolution = $language_resolution; } public function add_hooks() { // do not run this when user is importing posts in Tools > Import if ( ! isset( $_GET['import'] ) || $_GET['import'] !== 'wordpress' ) { add_action( 'add_attachment', array( $this, 'save_attachment_actions' ) ); add_action( 'add_attachment', array( $this, 'save_translated_attachments' ) ); add_filter( 'wp_generate_attachment_metadata', array( $this, 'wp_generate_attachment_metadata' ), 10, 2 ); } $active_languages = $this->language_resolution->get_active_language_codes(); if ( $this->is_admin_or_xmlrpc() && ! $this->is_uploading_plugin_or_theme() && 1 < count( $active_languages ) ) { add_action( 'edit_attachment', array( $this, 'save_attachment_actions' ) ); add_action( 'icl_make_duplicate', array( $this, 'make_duplicate' ), 10, 4 ); } $this->add_postmeta_hooks(); add_action( 'save_post', array( $this, 'save_post_actions' ), 100, 2 ); add_action( 'wpml_pro_translation_completed', array( $this, 'sync_on_translation_complete' ), 10, 3 ); add_action( 'wp_ajax_wpml_media_set_initial_language', array( $this, 'batch_set_initial_language' ) ); add_action( 'wp_ajax_wpml_media_translate_media', array( $this, 'ajax_batch_translate_media' ), 10, 0 ); add_action( 'wp_ajax_wpml_media_duplicate_media', array( $this, 'ajax_batch_duplicate_media' ), 10, 0 ); add_action( 'wp_ajax_wpml_media_duplicate_featured_images', array( $this, 'ajax_batch_duplicate_featured_images' ), 10, 0 ); add_action( 'wp_ajax_wpml_media_mark_processed', array( $this, 'ajax_batch_mark_processed' ), 10, 0 ); add_action( 'wp_ajax_wpml_media_scan_prepare', array( $this, 'ajax_batch_scan_prepare' ), 10, 0 ); add_action( 'wp_ajax_wpml_media_set_content_prepare', array( $this, 'set_content_defaults_prepare' ) ); add_action( 'wpml_loaded', array( $this, 'add_settings_hooks' ) ); } public function add_settings_hooks() { if ( User::getCurrent() && ( User::canManageTranslations() || User::hasCap( 'wpml_manage_media_translation' ) ) ) { add_action('wp_ajax_wpml_media_set_content_defaults', array($this, 'wpml_media_set_content_defaults') ); } } private function add_postmeta_hooks() { add_action( 'update_postmeta', [ $this, 'record_original_thumbnail_ids_and_sync' ], 10, 4 ); add_action( 'delete_post_meta', [ $this, 'record_original_thumbnail_ids_and_sync' ], 10, 4 ); } private function withPostMetaFiltersDisabled( callable $callback ) { $filter = [ $this, 'record_original_thumbnail_ids_and_sync' ]; $shouldRestoreFilters = remove_action( 'update_postmeta', $filter, 10 ) && remove_action( 'delete_post_meta', $filter, 10 ); $callback(); if ( $shouldRestoreFilters ) { $this->add_postmeta_hooks(); } } private function is_admin_or_xmlrpc() { $is_admin = is_admin(); $is_xmlrpc = defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST; return $is_admin || $is_xmlrpc; } public function save_attachment_actions( $post_id ) { if ( $this->is_uploading_media_on_wpml_media_screen() ) { return; } if ( $this->is_uploading_plugin_or_theme() && get_post_type( $post_id ) == 'attachment' ) { return; } $media_language = $this->sitepress->get_language_for_element( $post_id, 'post_attachment' ); $trid = false; if ( ! empty( $media_language ) ) { $trid = $this->sitepress->get_element_trid( $post_id, 'post_attachment' ); } if ( empty( $media_language ) ) { $parent_post_sql = "SELECT p2.ID, p2.post_type FROM {$this->wpdb->posts} p1 JOIN {$this->wpdb->posts} p2 ON p1.post_parent = p2.ID WHERE p1.ID=%d"; $parent_post_prepared = $this->wpdb->prepare( $parent_post_sql, array( $post_id ) ); /** @var \stdClass $parent_post */ $parent_post = $this->wpdb->get_row( $parent_post_prepared ); if ( $parent_post ) { $media_language = $this->sitepress->get_language_for_element( $parent_post->ID, 'post_' . $parent_post->post_type ); } if ( empty( $media_language ) ) { $media_language = $this->sitepress->get_admin_language_cookie(); } if ( empty( $media_language ) ) { $media_language = $this->sitepress->get_default_language(); } } if ( ! empty( $media_language ) ) { $this->sitepress->set_element_language_details( $post_id, 'post_attachment', $trid, $media_language ); $this->save_translated_attachments( $post_id ); $this->update_attachment_metadata( $post_id ); } } private function is_uploading_media_on_wpml_media_screen() { return isset( $_POST['action'] ) && 'wpml_media_save_translation' === $_POST['action']; } public function wp_generate_attachment_metadata( $metadata, $attachment_id ) { if ( $this->is_uploading_media_on_wpml_media_screen() ) { return $metadata; } $this->synchronize_attachment_metadata( $metadata, $attachment_id ); return $metadata; } private function update_attachment_metadata( $source_attachment_id ) { $original_element_id = $this->sitepress->get_original_element_id( $source_attachment_id, 'post_attachment', false, false, true ); if ( $original_element_id ) { $metadata = wp_get_attachment_metadata( $original_element_id ); $this->synchronize_attachment_metadata( $metadata, $original_element_id ); } } private function synchronize_attachment_metadata( $metadata, $attachment_id ) { // Update _wp_attachment_metadata to all translations (excluding the current one) $trid = $this->sitepress->get_element_trid( $attachment_id, 'post_attachment' ); if ( $trid ) { $translations = $this->sitepress->get_element_translations( $trid, 'post_attachment', true, true, true ); foreach ( $translations as $translation ) { if ( $translation->element_id != $attachment_id ) { $this->update_attachment_texts( $translation ); /** * Action to allow synchronise additional attachment data with translation. * * @param int $attachment_id The ID of original attachment. * @param object $translation The translated attachment. */ do_action( 'wpml_after_update_attachment_texts', $attachment_id, $translation ); $attachment_meta_data = get_post_meta( $translation->element_id, '_wp_attachment_metadata' ); if ( isset( $attachment_meta_data[0]['file'] ) ) { continue; } update_post_meta( $translation->element_id, '_wp_attachment_metadata', $metadata ); $mime_type = get_post_mime_type( $attachment_id ); if ( $mime_type ) { $this->wpdb->update( $this->wpdb->posts, array( 'post_mime_type' => $mime_type ), array( 'ID' => $translation->element_id ) ); } } } } } private function update_attachment_texts( $translation ) { if ( ! isset( $_POST['changes'] ) ) { return; } $changes = array( 'ID' => $translation->element_id ); foreach ( $_POST['changes'] as $key => $value ) { switch ( $key ) { case 'caption': $post = get_post( $translation->element_id ); if ( ! $post->post_excerpt ) { $changes['post_excerpt'] = $value; } break; case 'description': $translated_attachment = get_post( $translation->element_id ); if ( ! $translated_attachment->post_content ) { $changes['post_content'] = $value; } break; case 'alt': if ( ! get_post_meta( $translation->element_id, '_wp_attachment_image_alt', true ) ) { update_post_meta( $translation->element_id, '_wp_attachment_image_alt', $value ); } break; } } remove_action( 'edit_attachment', array( $this, 'save_attachment_actions' ) ); wp_update_post( $changes ); add_action( 'edit_attachment', array( $this, 'save_attachment_actions' ) ); } public function save_translated_attachments( $post_id ) { if ( $this->is_uploading_plugin_or_theme() && get_post_type( $post_id ) == 'attachment' ) { return; } $language_details = $this->sitepress->get_element_language_details( $post_id, 'post_attachment' ); if ( isset( $language_details->language_code ) ) { $this->translate_attachments( $post_id, $language_details->language_code ); } } private function translate_attachments( $attachment_id, $source_language, $override_always_translate_media = false ) { if ( ! $source_language ) { return; } if ( $override_always_translate_media || Obj::prop( 'always_translate_media', Option::getNewContentSettings() ) ) { /** @var SitePress $sitepress */ global $sitepress; $original_attachment_id = false; $trid = $sitepress->get_element_trid( $attachment_id, 'post_attachment' ); if ( $trid ) { $translations = $sitepress->get_element_translations( $trid, 'post_attachment', true, true ); $translated_languages = []; $default_language = $sitepress->get_default_language(); $default_language_attachment_id = false; foreach ( $translations as $translation ) { // Get the default language attachment ID if ( $translation->original ) { $original_attachment_id = $translation->element_id; } if ( $translation->language_code == $default_language ) { $default_language_attachment_id = $translation->element_id; } // Store already translated versions $translated_languages[] = $translation->language_code; } // Original attachment is missing if ( ! $original_attachment_id ) { $attachment = get_post( $attachment_id ); if ( ! $default_language_attachment_id ) { $this->create_duplicate_attachment( $attachment_id, $attachment->post_parent, $default_language ); } else { $sitepress->set_element_language_details( $default_language_attachment_id, 'post_attachment', $trid, $default_language, null ); } // Start over $this->translate_attachments( $attachment->ID, $source_language ); } else { // Original attachment is present $original = get_post( $original_attachment_id ); $codes = array_keys( $sitepress->get_active_languages() ); foreach ( $codes as $code ) { // If translation is not present, create it if ( ! in_array( $code, $translated_languages ) ) { $this->create_duplicate_attachment( $attachment_id, $original->post_parent, $code ); } } } } } } private function is_uploading_plugin_or_theme() { global $action; return isset( $action ) && ( $action == 'upload-plugin' || $action == 'upload-theme' ); } public function make_duplicate( $master_post_id, $target_lang, $post_array, $target_post_id ) { $translated_attachment_id = false; // Get Master Post attachments $master_post_attachment_ids_prepared = $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_parent = %d AND post_type = %s", array( $master_post_id, 'attachment', ) ); $master_post_attachment_ids = $this->wpdb->get_col( $master_post_attachment_ids_prepared ); if ( $master_post_attachment_ids ) { foreach ( $master_post_attachment_ids as $master_post_attachment_id ) { $attachment_trid = $this->sitepress->get_element_trid( $master_post_attachment_id, 'post_attachment' ); if ( $attachment_trid ) { // Get attachment translation $attachment_translations = $this->sitepress->get_element_translations( $attachment_trid, 'post_attachment' ); foreach ( $attachment_translations as $attachment_translation ) { if ( $attachment_translation->language_code == $target_lang ) { $translated_attachment_id = $attachment_translation->element_id; break; } } if ( ! $translated_attachment_id ) { $translated_attachment_id = $this->create_duplicate_attachment( $master_post_attachment_id, wp_get_post_parent_id( $master_post_id ), $target_lang ); } if ( $translated_attachment_id ) { // Set the parent post, if not already set $translated_attachment = get_post( $translated_attachment_id ); if ( $translated_attachment && ! $translated_attachment->post_parent ) { $prepared_query = $this->wpdb->prepare( "UPDATE {$this->wpdb->posts} SET post_parent=%d WHERE ID=%d", array( $target_post_id, $translated_attachment_id, ) ); $this->wpdb->query( $prepared_query ); } } } } } // Duplicate the featured image. $thumbnail_id = get_post_meta( $master_post_id, '_thumbnail_id', true ); if ( $thumbnail_id ) { $thumbnail_trid = $this->sitepress->get_element_trid( $thumbnail_id, 'post_attachment' ); if ( $thumbnail_trid ) { // translation doesn't have a featured image $t_thumbnail_id = icl_object_id( $thumbnail_id, 'attachment', false, $target_lang ); if ( $t_thumbnail_id == null ) { $dup_att_id = $this->create_duplicate_attachment( $thumbnail_id, $target_post_id, $target_lang ); $t_thumbnail_id = $dup_att_id; } if ( $t_thumbnail_id != null ) { update_post_meta( $target_post_id, '_thumbnail_id', $t_thumbnail_id ); } } } return $translated_attachment_id; } /** * @param int $attachment_id * @param int|false|null $parent_id * @param string $target_language * * @return int|null */ public function create_duplicate_attachment( $attachment_id, $parent_id, $target_language ) { try { $attachment_post = get_post( $attachment_id ); if ( ! $attachment_post ) { throw new WPML_Media_Exception( sprintf( 'Post with id %d does not exist', $attachment_id ) ); } $trid = $this->sitepress->get_element_trid( $attachment_id, WPML_Model_Attachments::ATTACHMENT_TYPE ); if ( ! $trid ) { throw new WPML_Media_Exception( sprintf( 'Attachment with id %s does not contain language information', $attachment_id ) ); } $duplicated_attachment = $this->attachments_model->find_duplicated_attachment( $trid, $target_language ); $duplicated_attachment_id = null; if ( null !== $duplicated_attachment ) { $duplicated_attachment_id = $duplicated_attachment->ID; } $translated_parent_id = $this->attachments_model->fetch_translated_parent_id( $duplicated_attachment, $parent_id, $target_language ); if ( null !== $duplicated_attachment ) { if ( (int) $duplicated_attachment->post_parent !== (int) $translated_parent_id ) { $this->attachments_model->update_parent_id_in_existing_attachment( $translated_parent_id, $duplicated_attachment ); } } else { $duplicated_attachment_id = $this->attachments_model->duplicate_attachment( $attachment_id, $target_language, $translated_parent_id, $trid ); } $this->attachments_model->duplicate_post_meta_data( $attachment_id, $duplicated_attachment_id ); /** * Fires when attachment is duplicated * * @since 4.1.0 * * @param int $attachment_id The ID of the source/original attachment. * @param int $duplicated_attachment_id The ID of the duplicated attachment. */ do_action( 'wpml_after_duplicate_attachment', $attachment_id, $duplicated_attachment_id ); return $duplicated_attachment_id; } catch ( WPML_Media_Exception $e ) { return null; } } public function sync_on_translation_complete( $new_post_id, $fields, $job ) { $new_post = get_post( $new_post_id ); $this->save_post_actions( $new_post_id, $new_post ); } public function record_original_thumbnail_ids_and_sync( $meta_id, $object_id, $meta_key, $meta_value ) { if ( '_thumbnail_id' === $meta_key ) { $original_thumbnail_id = get_post_meta( $object_id, $meta_key, true ); if ( $original_thumbnail_id !== $meta_value ) { $this->original_thumbnail_ids[ $object_id ] = $original_thumbnail_id; $this->sync_post_thumbnail( $object_id, $meta_value ? $meta_value : false ); } } } /** * @param int $pidd * @param WP_Post $post */ function save_post_actions( $pidd, $post ) { if ( ! $post ) { return; } if ( $post->post_type !== 'attachment' && $post->post_status !== 'auto-draft' ) { $this->sync_attachments( $pidd, $post ); } if ( $post->post_type === 'attachment' ) { $metadata = wp_get_attachment_metadata( $post->ID ); $attachment_id = $pidd; if ( $metadata ) { $this->synchronize_attachment_metadata( $metadata, $attachment_id ); } } } /** * @param int $pidd * @param WP_Post $post */ function sync_attachments( $pidd, $post ) { if ( $post->post_type == 'attachment' || $post->post_status == 'auto-draft' ) { return; } $posts_prepared = $this->wpdb->prepare( "SELECT post_type, post_status FROM {$this->wpdb->posts} WHERE ID = %d", array( $pidd ) ); list( $post_type, $post_status ) = $this->wpdb->get_row( $posts_prepared, ARRAY_N ); // checking - if translation and not saved before if ( isset( $_GET['trid'] ) && ! empty( $_GET['trid'] ) && $post_status == 'auto-draft' ) { // get source language if ( isset( $_GET['source_lang'] ) && ! empty( $_GET['source_lang'] ) ) { $src_lang = $_GET['source_lang']; } else { $src_lang = $this->sitepress->get_default_language(); } // get source id $src_id_prepared = $this->wpdb->prepare( "SELECT element_id FROM {$this->wpdb->prefix}icl_translations WHERE trid=%d AND language_code=%s", array( $_GET['trid'], $src_lang ) ); $src_id = $this->wpdb->get_var( $src_id_prepared ); // delete exist auto-draft post media $results_prepared = $this->wpdb->prepare( "SELECT p.id FROM {$this->wpdb->posts} AS p LEFT JOIN {$this->wpdb->posts} AS p1 ON p.post_parent = p1.id WHERE p1.post_status = %s", array( 'auto-draft' ) ); $results = $this->wpdb->get_results( $results_prepared, ARRAY_A ); $attachments = array(); if ( ! empty( $results ) ) { foreach ( $results as $result ) { $attachments[] = $result['id']; } if ( ! empty( $attachments ) ) { $in_attachments = wpml_prepare_in( $attachments, '%d' ); $delete_prepared = "DELETE FROM {$this->wpdb->posts} WHERE id IN (" . $in_attachments . ')'; $this->wpdb->query( $delete_prepared ); $delete_prepared = "DELETE FROM {$this->wpdb->postmeta} WHERE post_id IN (" . $in_attachments . ')'; $this->wpdb->query( $delete_prepared ); } } // checking - if set duplicate media if ( $src_id && Option::shouldDuplicateMedia( (int) $src_id ) ) { // duplicate media before first save $this->duplicate_post_attachments( $pidd, $_GET['trid'], $src_lang, $this->sitepress->get_language_for_element( $pidd, 'post_' . $post_type ) ); } } // exceptions if ( ! $this->sitepress->is_translated_post_type( $post_type ) || isset( $_POST['autosave'] ) || ( isset( $_POST['post_ID'] ) && $_POST['post_ID'] != $pidd ) || ( isset( $_POST['post_type'] ) && $_POST['post_type'] === 'revision' ) || $post_type === 'revision' || get_post_meta( $pidd, '_wp_trash_meta_status', true ) || ( isset( $_GET['action'] ) && $_GET['action'] === 'restore' ) || $post_status === 'auto-draft' ) { return; } if ( isset( $_POST['icl_trid'] ) ) { $icl_trid = $_POST['icl_trid']; } else { // get trid from database. $icl_trid_prepared = $this->wpdb->prepare( "SELECT trid FROM {$this->wpdb->prefix}icl_translations WHERE element_id=%d AND element_type = %s", array( $pidd, 'post_' . $post_type ) ); $icl_trid = $this->wpdb->get_var( $icl_trid_prepared ); } if ( $icl_trid ) { $language_details = $this->sitepress->get_element_language_details( $pidd, 'post_' . $post_type ); // In some cases the sitepress cache doesn't get updated (e.g. when posts are created with wp_insert_post() // Only in this case, the sitepress cache will be cleared so we can read the element language details if ( ! $language_details ) { $this->sitepress->get_translations_cache()->clear(); $language_details = $this->sitepress->get_element_language_details( $pidd, 'post_' . $post_type ); } if ( $language_details ) { $this->duplicate_post_attachments( $pidd, $icl_trid, $language_details->source_language_code, $language_details->language_code ); } } } /** * @param int $post_id * @param int|null $request_post_thumbnail_id */ public function sync_post_thumbnail( $post_id, $request_post_thumbnail_id = null ) { if ( $post_id && Option::shouldDuplicateFeatured( $post_id ) ) { if ( null === $request_post_thumbnail_id ) { $request_post_thumbnail_id = filter_input( INPUT_POST, 'thumbnail_id', FILTER_SANITIZE_NUMBER_INT, FILTER_NULL_ON_FAILURE ); $thumbnail_id = $request_post_thumbnail_id ? $request_post_thumbnail_id : get_post_meta( $post_id, '_thumbnail_id', true ); } else { $thumbnail_id = $request_post_thumbnail_id; } $trid = $this->sitepress->get_element_trid( $post_id, 'post_' . get_post_type( $post_id ) ); $translations = $this->sitepress->get_element_translations( $trid, 'post_' . get_post_type( $post_id ) ); // Check if it is original. $is_original = false; foreach ( $translations as $translation ) { if ( 1 === (int) $translation->original && (int) $translation->element_id === $post_id ) { $is_original = true; } } if ( $is_original ) { foreach ( $translations as $translation ) { if ( ! $translation->original && $translation->element_id ) { if ( $this->are_post_thumbnails_still_in_sync( $post_id, $thumbnail_id, $translation ) ) { if ( ! $thumbnail_id || - 1 === (int) $thumbnail_id ) { $this->withPostMetaFiltersDisabled( function () use ( $translation ) { delete_post_meta( $translation->element_id, '_thumbnail_id' ); } ); } else { $translated_thumbnail_id = wpml_object_id_filter( $thumbnail_id, 'attachment', false, $translation->language_code ); $id = get_post_meta( $translation->element_id, '_thumbnail_id', true ); if ( (int) $id !== $translated_thumbnail_id ) { $this->withPostMetaFiltersDisabled( function () use ( $translation, $translated_thumbnail_id ) { update_post_meta( $translation->element_id, '_thumbnail_id', $translated_thumbnail_id ); } ); } } } } } } } } protected function are_post_thumbnails_still_in_sync( $source_id, $source_thumbnail_id, $translation ) { $translation_thumbnail_id = get_post_meta( $translation->element_id, '_thumbnail_id', true ); if ( isset( $this->original_thumbnail_ids[ $source_id ] ) ) { if ( $this->original_thumbnail_ids[ $source_id ] === $translation_thumbnail_id ) { return true; } return $this->are_translations_of_each_other( $this->original_thumbnail_ids[ $source_id ], $translation_thumbnail_id ); } else { return $this->are_translations_of_each_other( $source_thumbnail_id, $translation_thumbnail_id ); } } private function are_translations_of_each_other( $post_id_1, $post_id_2 ) { return $this->sitepress->get_element_trid( $post_id_1, 'post_' . get_post_type( $post_id_1 ) ) === $this->sitepress->get_element_trid( $post_id_2, 'post_' . get_post_type( $post_id_2 ) ); } function duplicate_post_attachments( $pidd, $icl_trid, $source_lang = null, $lang = null ) { $wpdb = $this->wpdb; $pidd = ( is_numeric( $pidd ) ) ? (int) $pidd : null; $request_post_icl_ajx_action = filter_input( INPUT_POST, 'icl_ajx_action', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE ); $request_post_icl_post_language = filter_input( INPUT_POST, 'icl_post_language', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE ); $request_post_post_id = filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT, FILTER_NULL_ON_FAILURE ); if ( $icl_trid == '' ) { return; } if ( ! $source_lang ) { $source_lang_prepared = $this->wpdb->prepare( "SELECT source_language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND trid=%d", array( $pidd, $icl_trid ) ); $source_lang = $this->wpdb->get_var( $source_lang_prepared ); } // exception for making duplicates. language info not set when this runs and creating the duplicated posts 1/3 if ( $request_post_icl_ajx_action == 'make_duplicates' && $request_post_icl_post_language ) { $source_lang_prepared = $this->wpdb->prepare( "SELECT language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND trid = %d", array( $request_post_post_id, $icl_trid ) ); $source_lang = $this->wpdb->get_var( $source_lang_prepared ); $lang = $request_post_icl_post_language; } if ( $source_lang == null || $source_lang == '' ) { // This is the original see if we should copy to translations if ( Option::shouldDuplicateMedia( $pidd ) || Option::shouldDuplicateFeatured( $pidd ) ) { $translations = $wpdb->get_col( $wpdb->prepare( 'SELECT element_id FROM ' . $wpdb->prefix . 'icl_translations WHERE trid = %d', array( $icl_trid ) ) ); $translations = array_map( 'intval', $translations ); $source_attachments = $wpdb->get_col( $wpdb->prepare( 'SELECT ID FROM ' . $wpdb->posts . ' WHERE post_parent = %d AND post_type = %s', array( $pidd, 'attachment' ) ) ); $source_attachments = array_map( 'intval', $source_attachments ); $all_element_ids = []; $attachments_by_element_id = []; foreach ( $translations as $element_id ) { if ( $element_id && $element_id !== $pidd ) { $all_element_ids[] = $element_id; $attachments_by_element_id[ $element_id ] = []; } } $all_attachments = []; if ( count( $all_element_ids ) > 0 ) { $all_attachments = $wpdb->get_results( $wpdb->prepare( // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared 'SELECT ID, post_parent AS element_id FROM ' . $wpdb->posts . ' WHERE post_parent IN (' . wpml_prepare_in( $all_element_ids ) . ') AND post_type = %s', array( 'attachment' ) ), ARRAY_A ); } foreach ( $all_attachments as $attachment ) { $attachments_by_element_id[ (int) $attachment['element_id'] ][] = (int) $attachment['ID']; } foreach ( $translations as $element_id ) { if ( $element_id && $element_id !== $pidd ) { $lang_prepared = $this->wpdb->prepare( "SELECT language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND trid = %d", array( $element_id, $icl_trid ) ); $lang = $this->wpdb->get_var( $lang_prepared ); if ( Option::shouldDuplicateFeatured( $element_id ) ) { $attachments = $attachments_by_element_id[ $element_id ]; $has_missing_translation_attachment_id = false; foreach ( $attachments as $attachment_id ) { if ( ! icl_object_id( $attachment_id, 'attachment', false, $lang ) ) { $has_missing_translation_attachment_id = true; break; } } $source_attachment_ids = $has_missing_translation_attachment_id ? $source_attachments : []; foreach ( $source_attachment_ids as $source_attachment_id ) { $this->create_duplicate_attachment_not_static( $source_attachment_id, $element_id, $lang ); } } $translation_thumbnail_id = get_post_meta( $element_id, '_thumbnail_id', true ); if ( Option::shouldDuplicateFeatured( $element_id ) && empty( $translation_thumbnail_id ) ) { $thumbnail_id = get_post_meta( $pidd, '_thumbnail_id', true ); if ( $thumbnail_id ) { $t_thumbnail_id = icl_object_id( $thumbnail_id, 'attachment', false, $lang ); if ( $t_thumbnail_id == null ) { $dup_att_id = $this->create_duplicate_attachment_not_static( $thumbnail_id, $element_id, $lang ); $t_thumbnail_id = $dup_att_id; } if ( $t_thumbnail_id != null ) { update_post_meta( $element_id, '_thumbnail_id', $t_thumbnail_id ); } } } } } } } else { // This is a translation. // exception for making duplicates. language info not set when this runs and creating the duplicated posts 2/3 if ( $request_post_icl_ajx_action === 'make_duplicates' ) { $source_id = $request_post_post_id; } else { $source_id_prepared = $this->wpdb->prepare( "SELECT element_id FROM {$this->wpdb->prefix}icl_translations WHERE language_code = %s AND trid = %d", array( $source_lang, $icl_trid ) ); $source_id = $this->wpdb->get_var( $source_id_prepared ); } if ( ! $lang ) { $lang_prepared = $this->wpdb->prepare( "SELECT language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND trid = %d", array( $pidd, $icl_trid ) ); $lang = $this->wpdb->get_var( $lang_prepared ); } // exception for making duplicates. language info not set when this runs and creating the duplicated posts 3/3 if ( $request_post_icl_ajx_action === 'make_duplicates' ) { $duplicate = Option::shouldDuplicateMedia( $source_id ); } else { $duplicate = Option::shouldDuplicateMedia( $pidd, false ); if ( $duplicate === null ) { // check the original state $duplicate = Option::shouldDuplicateMedia( $source_id ); } } if ( $duplicate ) { $source_attachments_prepared = $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_parent = %d AND post_type = %s", array( $source_id, 'attachment' ) ); $source_attachments = $this->wpdb->get_col( $source_attachments_prepared ); foreach ( $source_attachments as $source_attachment_id ) { $translation_attachment_id = icl_object_id( $source_attachment_id, 'attachment', false, $lang ); if ( ! $translation_attachment_id ) { self::create_duplicate_attachment( $source_attachment_id, $pidd, $lang ); } else { $translated_attachment = get_post( $translation_attachment_id ); if ( $translated_attachment && ! $translated_attachment->post_parent ) { $translated_attachment->post_parent = $pidd; /** @phpstan-ignore-next-line (WP doc issue) */ wp_update_post( $translated_attachment ); } } } } $featured = Option::shouldDuplicateFeatured( $pidd, false ); if ( $featured === null ) { // check the original state $featured = Option::shouldDuplicateFeatured( $source_id ); } $translation_thumbnail_id = get_post_meta( $pidd, '_thumbnail_id', true ); if ( $featured && empty( $translation_thumbnail_id ) ) { $thumbnail_id = get_post_meta( $source_id, '_thumbnail_id', true ); if ( $thumbnail_id ) { $t_thumbnail_id = icl_object_id( $thumbnail_id, 'attachment', false, $lang ); if ( $t_thumbnail_id == null ) { $dup_att_id = self::create_duplicate_attachment( $thumbnail_id, $pidd, $lang ); $t_thumbnail_id = $dup_att_id; } if ( $t_thumbnail_id != null ) { update_post_meta( $pidd, '_thumbnail_id', $t_thumbnail_id ); } } } } } /** * @param int $source_attachment_id * @param int $pidd * @param string $lang * * @return int|null|WP_Error */ public function create_duplicate_attachment_not_static( $source_attachment_id, $pidd, $lang ) { return self::create_duplicate_attachment( $source_attachment_id, $pidd, $lang ); } private function duplicate_featured_images( $limit = 0, $offset = 0 ) { global $wpdb; list( $thumbnails, $processed ) = $this->get_post_thumbnail_map( $limit, $offset ); if ( sizeof( $thumbnails ) ) { // Posts IDs with found featured images $post_ids = wpml_prepare_in( array_keys( $thumbnails ), '%d' ); $posts_prepared = "SELECT ID, post_type FROM {$wpdb->posts} WHERE ID IN ({$post_ids})"; $posts = $wpdb->get_results( $posts_prepared ); foreach ( $posts as $post ) { $this->duplicate_featured_image_in_post( $post, $thumbnails ); } } return $processed; } /** * @param int $limit * @param int $offset Offset to use for getting thumbnails. Default: 0. * * @return array */ public function get_post_thumbnail_map( $limit = 0, $offset = 0 ) { global $wpdb; $featured_images_sql = "SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id' ORDER BY `meta_id`"; if ( $limit > 0 ) { $featured_images_sql .= $wpdb->prepare( ' LIMIT %d, %d', $offset, $limit ); } $featured_images = $wpdb->get_results( $featured_images_sql ); $processed = count( $featured_images ); $thumbnails = array(); foreach ( $featured_images as $featured ) { $thumbnails[ $featured->post_id ] = $featured->meta_value; } return array( $thumbnails, $processed ); } /** * @param \stdClass $post contains properties `ID` and `post_type` * @param array $thumbnails a map of post ID => thumbnail ID */ public function duplicate_featured_image_in_post( $post, $thumbnails = array() ) { global $wpdb, $sitepress; $row_prepared = $wpdb->prepare( "SELECT trid, source_language_code FROM {$wpdb->prefix}icl_translations WHERE element_id=%d AND element_type = %s", array( $post->ID, 'post_' . $post->post_type ) ); $row = $wpdb->get_row( $row_prepared ); if ( $row && $row->trid && ( $row->source_language_code == null || $row->source_language_code == '' ) ) { $translations = $sitepress->get_element_translations( $row->trid, 'post_' . $post->post_type ); foreach ( $translations as $translation ) { if ( $translation->element_id != $post->ID ) { $translation_thumbnail_id = get_post_meta( $translation->element_id, '_thumbnail_id', true ); if ( empty( $translation_thumbnail_id ) ) { if ( ! in_array( $translation->element_id, array_keys( $thumbnails ) ) ) { // translation doesn't have a featured image $t_thumbnail_id = icl_object_id( $thumbnails[ $post->ID ], 'attachment', false, $translation->language_code ); if ( $t_thumbnail_id == null ) { $dup_att_id = self::create_duplicate_attachment( $thumbnails[ $post->ID ], $translation->element_id, $translation->language_code ); $t_thumbnail_id = $dup_att_id; } if ( $t_thumbnail_id != null ) { update_post_meta( $translation->element_id, '_thumbnail_id', $t_thumbnail_id ); } } elseif ( $thumbnails[ $post->ID ] ) { update_post_meta( $translation->element_id, '_thumbnail_id', $thumbnails[ $post->ID ] ); } } } } } } public function ajax_batch_duplicate_featured_images() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_duplicate_featured_images' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $featured_images_left = array_key_exists( 'featured_images_left', $_POST ) && is_numeric( $_POST['featured_images_left'] ) ? (int) $_POST['featured_images_left'] : null; return $this->batch_duplicate_featured_images( true, $featured_images_left ); } public function batch_duplicate_featured_images( $outputResult = true, $featured_images_left = null ) { // Use $featured_images_left if it's a number otherwise proceed with null. $featured_images_left = is_numeric( $featured_images_left ) ? (int) $featured_images_left : null; if ( null === $featured_images_left ) { $featured_images_left = $this->get_featured_images_total_number(); } // Use 10 as limit or what's left if there are less than 10 images left to proceed. $limit = $featured_images_left < 10 ? $featured_images_left : 10; // Duplicate batch of feature images. $processed = $this->duplicate_featured_images( $limit, $featured_images_left - $limit ); // Response result. $response = array( 'left' => max( $featured_images_left - $processed, 0 ) ); if ( $response['left'] ) { $response['message'] = sprintf( __( 'Duplicating featured images. %d left', 'sitepress' ), $response['left'] ); } else { $response['message'] = sprintf( __( 'Duplicating featured images: done!', 'sitepress' ), $response['left'] ); } if ( $outputResult ) { wp_send_json( $response ); } return $response['left']; } /** * Returns the total number of Featured Images. * * @return int */ private function get_featured_images_total_number() { $wpdb = $this->wpdb; // Makes Codesniffer interpret the following correctly. return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id'" ); } public function ajax_batch_duplicate_media() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_duplicate_media' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } return $this->batch_duplicate_media(); } public function batch_duplicate_media( $outputResult = true ) { $limit = 10; $response = array(); $attachments_prepared = $this->wpdb->prepare( " SELECT SQL_CALC_FOUND_ROWS p1.ID, p1.post_parent FROM {$this->wpdb->posts} p1 WHERE post_type = %s AND ID NOT IN (SELECT post_id FROM {$this->wpdb->postmeta} WHERE meta_key = %s) ORDER BY p1.ID ASC LIMIT %d", array( 'attachment', 'wpml_media_processed', $limit ) ); $attachments = $this->wpdb->get_results( $attachments_prepared ); $found = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' ); if ( $attachments ) { foreach ( $attachments as $attachment ) { $this->create_duplicated_media( $attachment ); } } $response['left'] = max( $found - $limit, 0 ); if ( $response['left'] ) { $response['message'] = sprintf( __( 'Duplicating media. %d left', 'sitepress' ), $response['left'] ); } else { $response['message'] = sprintf( __( 'Duplicating media: done!', 'sitepress' ), $response['left'] ); } if ( $outputResult ) { wp_send_json( $response ); } return $response['left']; } private function get_batch_translate_limit( $activeLanguagesCount ) { global $sitepress; $limit = $sitepress->get_wp_api()->constant( 'WPML_MEDIA_BATCH_LIMIT' ); $limit = $limit ?: ceil( 100 / max( $activeLanguagesCount - 1, 1 ) ); return max( $limit, 1 ); } public function ajax_batch_translate_media() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_translate_media' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } return $this->batch_translate_media(); } public function batch_translate_media( $outputResult = true ) { $response = []; $activeLanguagesCount = count( $this->sitepress->get_active_languages() ); $limit = $this->get_batch_translate_limit( $activeLanguagesCount ); $sql = " SELECT SQL_CALC_FOUND_ROWS p1.ID, p1.post_parent FROM {$this->wpdb->prefix}icl_translations t INNER JOIN {$this->wpdb->posts} p1 ON t.element_id = p1.ID LEFT JOIN {$this->wpdb->prefix}icl_translations tt ON t.trid = tt.trid WHERE t.element_type = 'post_attachment' AND t.source_language_code IS null GROUP BY p1.ID, p1.post_parent HAVING count(tt.language_code) < %d LIMIT %d "; $sql_prepared = $this->wpdb->prepare( $sql, [ $activeLanguagesCount, $limit ] ); $attachments = $this->wpdb->get_results( $sql_prepared ); $found = $this->wpdb->get_var( 'SELECT FOUND_ROWS()' ); if ( $attachments ) { foreach ( $attachments as $attachment ) { $lang = $this->sitepress->get_element_language_details( $attachment->ID, 'post_attachment' ); $this->translate_attachments( $attachment->ID, ( is_object( $lang ) && property_exists( $lang, 'language_code' ) ) ? $lang->language_code : null, true ); } } $response['left'] = max( $found - $limit, 0 ); if ( $response['left'] ) { $response['message'] = sprintf( esc_html__( 'Translating media. %d left', 'sitepress' ), $response['left'] ); } else { $response['message'] = __( 'Translating media: done!', 'sitepress' ); } if ( $outputResult ) { wp_send_json( $response ); } return $response['left']; } public function batch_set_initial_language() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_set_initial_language' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $default_language = $this->sitepress->get_default_language(); $limit = 10; $response = array(); $attachments_prepared = $this->wpdb->prepare( " SELECT SQL_CALC_FOUND_ROWS ID FROM {$this->wpdb->posts} WHERE post_type = %s AND ID NOT IN (SELECT element_id FROM {$this->wpdb->prefix}icl_translations WHERE element_type=%s) LIMIT %d", array( 'attachment', 'post_attachment', $limit, ) ); $attachments = $this->wpdb->get_col( $attachments_prepared ); $found = (int) $this->wpdb->get_var( 'SELECT FOUND_ROWS()' ); foreach ( $attachments as $attachment_id ) { $this->sitepress->set_element_language_details( $attachment_id, 'post_attachment', false, $default_language ); } $response['left'] = max( $found - $limit, 0 ); if ( $response['left'] ) { $response['message'] = sprintf( __( 'Setting language to media. %d left', 'sitepress' ), $response['left'] ); } else { $response['message'] = sprintf( __( 'Setting language to media: done!', 'sitepress' ), $response['left'] ); } echo wp_json_encode( $response ); exit; } public function ajax_batch_scan_prepare() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_scan_prepare' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $this->batch_scan_prepare(); } public function batch_scan_prepare( $outputResult = true ) { $response = array(); $this->wpdb->delete( $this->wpdb->postmeta, array( 'meta_key' => 'wpml_media_processed' ) ); $response['message'] = __( 'Started...', 'sitepress' ); if ( $outputResult ) { wp_send_json( $response ); } } public function ajax_batch_mark_processed() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_mark_processed' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $this->batch_mark_processed(); } public function batch_mark_processed( $outputResult = true ) { $response = []; $wpmlMediaProcessedMetaValue = 1; $limit = 300; /** * Query to get count of attachments from wp_posts table to decide how many rounds we should loop according to $limit */ $attachmentsCountQuery = "SELECT COUNT(ID) from {$this->wpdb->posts} where post_type = %s"; $attachmentsCountQueryPrepared = $this->wpdb->prepare( $attachmentsCountQuery, 'attachment' ); /** * Retrieving count of attachments */ $attachmentsCount = $this->wpdb->get_var( $attachmentsCountQueryPrepared ); /** * Query to get limited number of attachments with metadata up to $limit * * We join with the wp_postmeta table to also retrieve any related data of attachments in this table, * we only need the related data when the wp_postmeta.metavalue is null or != 1 because if it equals 1 then it doesn't need to be processed again */ $limitedAttachmentsWithMetaDataQuery = "SELECT posts.ID, post_meta.post_id, post_meta.meta_key, post_meta.meta_value FROM {$this->wpdb->posts} AS posts LEFT JOIN {$this->wpdb->postmeta} AS post_meta ON posts.ID = post_meta.post_id AND post_meta.meta_key = %s WHERE posts.post_type = %s AND (post_meta.meta_value IS NULL OR post_meta.meta_value != %d) LIMIT %d"; $limitedAttachmentsWithMetaDataQueryPrepared = $this->wpdb->prepare( $limitedAttachmentsWithMetaDataQuery, [ self::WPML_MEDIA_PROCESSED_META_KEY, 'attachment', 1, $limit, ] ); /** * Calculating loop rounds for processing attachments */ $attachmentsProcessingLoopRounds = $attachmentsCount ? ceil( $attachmentsCount / $limit ) : 0; /** * Callback function used to decide if attachment already has metadata or not * * @param $attachmentWithMetaData * * @return bool */ $attachmentHasNoMetaData = function ( $attachmentWithMetaData ) { return Obj::prop( 'post_id', $attachmentWithMetaData ) === null && Obj::prop( 'meta_key', $attachmentWithMetaData ) === null && Obj::prop( 'meta_value', $attachmentWithMetaData ) === null; }; /** * Callback function that prepares values to be inserted in the wp_postmeta table * * @param $attachmentId * * @return array */ $prepareInsertAttachmentsMetaValues = function ( $attachmentId ) use ( $wpmlMediaProcessedMetaValue ) { // The order of returned items is important, it represents (meta_value, meta_key, post_id) when insert into wp_postmeta table is done return [ $wpmlMediaProcessedMetaValue, self::WPML_MEDIA_PROCESSED_META_KEY, $attachmentId ]; }; /** * Looping through the retrieved limited number of attachments with metadata */ for ( $i = 0; $i < $attachmentsProcessingLoopRounds; $i ++ ) { /** * Retrieving limited number of attachments with metadata */ $attachmentsWithMetaData = $this->wpdb->get_results( $limitedAttachmentsWithMetaDataQueryPrepared ); if ( is_array( $attachmentsWithMetaData ) && count( $attachmentsWithMetaData ) ) { /** * Filtering data to separate existing and non-existing attachments with metdata */ list( $notExistingMetaAttachmentIds, $existingAttachmentsWithMetaData ) = \WPML\FP\Lst::partition( $attachmentHasNoMetaData, $attachmentsWithMetaData ); if ( is_array( $notExistingMetaAttachmentIds ) && count( $notExistingMetaAttachmentIds ) ) { /** * If we have attachments with no related data in wp_postmeta table, we start inserting values for it in wp_postmeta */ // Getting only attachments Ids $notExistingAttachmentsIds = \WPML\FP\Lst::pluck( 'ID', $notExistingMetaAttachmentIds ); // Preparing placeholders to be used in INSERT query /** @phpstan-ignore-next-line */ $attachmentMetaValuesPlaceholders = implode( ',', \WPML\FP\Lst::repeat( '(%d, %s, %d)', count( $notExistingAttachmentsIds ) ) ); // Preparing INSERT query $insertAttachmentsMetaQuery = "INSERT INTO {$this->wpdb->postmeta} (meta_value, meta_key, post_id) VALUES "; $insertAttachmentsMetaQuery .= $attachmentMetaValuesPlaceholders; // Preparing values to be inserted, at his point they're in separate arrays /** @phpstan-ignore-next-line */ $insertAttachmentsMetaValues = array_map( $prepareInsertAttachmentsMetaValues, $notExistingAttachmentsIds ); // Merging all values together in one array to be used wpdb->prepare function so each value is placed in a placeholder $insertAttachmentsMetaValues = array_merge( ...$insertAttachmentsMetaValues ); // Start replacing placeholders with values and run query $insertAttachmentsMetaQuery = $this->wpdb->prepare( $insertAttachmentsMetaQuery, $insertAttachmentsMetaValues ); $this->wpdb->query( $insertAttachmentsMetaQuery ); } if ( count( $existingAttachmentsWithMetaData ) ) { /** * If we have attachments with related data in wp_postmeta table, we start updating meta_value in wp_postmeta */ $existingAttachmentsIds = \WPML\FP\Lst::pluck( 'ID', $existingAttachmentsWithMetaData ); $attachmentsIn = wpml_prepare_in( $existingAttachmentsIds, '%d' ); $updateAttachmentsMetaQuery = $this->wpdb->prepare( "UPDATE {$this->wpdb->postmeta} SET meta_value = %d WHERE post_id IN ({$attachmentsIn})", [ $wpmlMediaProcessedMetaValue, ] ); $this->wpdb->query( $updateAttachmentsMetaQuery ); } } else { /** * When there are no more attachments with metadata found we get out of the loop */ break; } } Option::setSetupFinished(); $response['message'] = __( 'Done!', 'sitepress' ); if ( $outputResult ) { wp_send_json( $response ); } } public function create_duplicated_media( $attachment ) { static $parents_processed = array(); if ( $attachment->post_parent && ! in_array( $attachment->post_parent, $parents_processed ) ) { // see if we have translations. $post_type_prepared = $this->wpdb->prepare( "SELECT post_type FROM {$this->wpdb->posts} WHERE ID = %d", array( $attachment->post_parent ) ); $post_type = $this->wpdb->get_var( $post_type_prepared ); $trid_prepared = $this->wpdb->prepare( "SELECT trid FROM {$this->wpdb->prefix}icl_translations WHERE element_id=%d AND element_type = %s", array( $attachment->post_parent, 'post_' . $post_type, ) ); $trid = $this->wpdb->get_var( $trid_prepared ); if ( $trid ) { $attachments_prepared = $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_type = %s AND post_parent = %d", array( 'attachment', $attachment->post_parent, ) ); $attachments = $this->wpdb->get_col( $attachments_prepared ); $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post_type ); foreach ( $translations as $translation ) { if ( $translation->element_id && $translation->element_id != $attachment->post_parent ) { $attachments_in_translation_prepared = $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_type = %s AND post_parent = %d", array( 'attachment', $translation->element_id, ) ); $attachments_in_translation = $this->wpdb->get_col( $attachments_in_translation_prepared ); if ( sizeof( $attachments_in_translation ) == 0 ) { // only duplicate attachments if there a none already. foreach ( $attachments as $attachment_id ) { // duplicate the attachment self::create_duplicate_attachment( $attachment_id, $translation->element_id, $translation->language_code ); } } } } } $parents_processed[] = $attachment->post_parent; } else { // no parent - set to default language $target_language = $this->sitepress->get_default_language(); // Getting the trid and language, just in case image translation already exists $trid = $this->sitepress->get_element_trid( $attachment->ID, 'post_attachment' ); if ( $trid ) { $target_language = $this->sitepress->get_language_for_element( $attachment->ID, 'post_attachment' ); } $this->sitepress->set_element_language_details( $attachment->ID, 'post_attachment', $trid, $target_language ); } // Duplicate the post meta of the source element the translation $source_element_id = SitePress::get_original_element_id_by_trid( $trid ); if ( $source_element_id ) { $this->update_attachment_metadata( $source_element_id ); } update_post_meta( $attachment->ID, 'wpml_media_processed', 1 ); } function set_content_defaults_prepare() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_set_content_prepare' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $response = array( 'message' => __( 'Started...', 'sitepress' ) ); echo wp_json_encode( $response ); exit; } public function wpml_media_set_content_defaults() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'wpml_media_set_content_defaults' ) ) { wp_send_json_error( esc_html__( 'Invalid request!', 'sitepress' ) ); } $this->set_content_defaults(); } private function set_content_defaults() { $always_translate_media = $_POST['always_translate_media']; $duplicate_media = $_POST['duplicate_media']; $duplicate_featured = $_POST['duplicate_featured']; $translateMediaLibraryTexts = \WPML\API\Sanitize::stringProp('translate_media_library_texts', $_POST); $content_defaults_option = [ 'always_translate_media' => $always_translate_media == 'true', 'duplicate_media' => $duplicate_media == 'true', 'duplicate_featured' => $duplicate_featured == 'true', ]; Option::setNewContentSettings( $content_defaults_option ); $settings = get_option( '_wpml_media' ); $settings['new_content_settings'] = $content_defaults_option; $settings['translate_media_library_texts'] = $translateMediaLibraryTexts === 'true'; update_option( '_wpml_media', $settings ); $response = [ 'result' => true, 'message' => __( 'Settings saved', 'sitepress' ), ]; wp_send_json_success( $response ); } } duplication/HooksFactory.php 0000644 00000000326 14721660154 0012212 0 ustar 00 <?php namespace WPML\Media\Duplication; class HooksFactory extends AbstractFactory { public function create() { if ( self::shouldActivateHooks() ) { return [ Hooks::class, 'add' ]; } return null; } } class-wpml-attachment-action-factory.php 0000644 00000001131 14721660154 0014407 0 ustar 00 <?php /** * WPML_Attachment_Action_Factory * * @package WPML */ /** * Class WPML_Attachment_Action_Factory */ class WPML_Attachment_Action_Factory implements IWPML_Backend_Action_Loader, IWPML_Frontend_Action_Loader, IWPML_AJAX_Action_Loader, IWPML_Deferred_Action_Loader { /** * Get load action. * * @return string */ public function get_load_action() { return 'wpml_loaded'; } /** * Create attachment action. * * @return WPML_Attachment_Action */ public function create() { global $sitepress, $wpdb; return new WPML_Attachment_Action( $sitepress, $wpdb ); } } class-wpml-attachment-action.php 0000644 00000013253 14721660154 0012752 0 ustar 00 <?php use WPML\FP\Str; /** * WPML_Attachment_Action class file. * * @package WPML */ /** * Class WPML_Attachment_Action */ class WPML_Attachment_Action implements IWPML_Action { /** * SitePress instance. * * @var SitePress */ private $sitepress; /** * Wpdb instance. * * @var wpdb */ private $wpdb; /** * WPML_Attachment_Action constructor. * * @param SitePress $sitepress SitePress instance. * @param wpdb $wpdb wpdb instance. */ public function __construct( SitePress $sitepress, wpdb $wpdb ) { $this->sitepress = $sitepress; $this->wpdb = $wpdb; } /** * Add hooks. */ public function add_hooks() { if ( $this->is_admin_or_xmlrpc() && ! $this->is_uploading_plugin_or_theme() ) { $active_languages = $this->sitepress->get_active_languages(); if ( count( $active_languages ) > 1 ) { add_filter( 'views_upload', array( $this, 'views_upload_actions' ) ); } } add_filter( 'attachment_link', array( $this->sitepress, 'convert_url' ), 10, 1 ); add_filter( 'wp_delete_file', array( $this, 'delete_file_filter' ) ); } /** * Check if we are in site console or xmlrpc request is active. * * @return bool */ private function is_admin_or_xmlrpc() { $is_admin = is_admin(); $is_xmlrpc = ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ); return $is_admin || $is_xmlrpc; } /** * Check if we are uploading plugin or theme. * * @return bool */ private function is_uploading_plugin_or_theme() { global $action; return ( isset( $action ) && ( 'upload-plugin' === $action || 'upload-theme' === $action ) ); } /** * Filter views. * * @param array $views Views. * * @return array */ public function views_upload_actions( $views ) { global $pagenow; if ( 'upload.php' === $pagenow ) { // Get current language. $lang = $this->sitepress->get_current_language(); foreach ( $views as $key => $view ) { // Extract the base URL and query parameters. $href_count = preg_match( '/(href=["\'])([\s\S]+?)\?([\s\S]+?)(["\'])/', $view, $href_matches ); if ( $href_count && isset( $href_args ) ) { $href_base = $href_matches[2]; wp_parse_str( $href_matches[3], $href_args ); } else { $href_base = 'upload.php'; $href_args = array(); } if ( 'all' !== $lang ) { $sql = $this->wpdb->prepare( " SELECT COUNT(p.id) FROM {$this->wpdb->posts} AS p INNER JOIN {$this->wpdb->prefix}icl_translations AS t ON p.id = t.element_id WHERE p.post_type = 'attachment' AND t.element_type='post_attachment' AND t.language_code = %s ", $lang ); switch ( $key ) { case 'all': $and = " AND p.post_status != 'trash' "; break; case 'detached': $and = " AND p.post_status != 'trash' AND p.post_parent = 0 "; break; case 'trash': $and = " AND p.post_status = 'trash' "; break; default: if ( isset( $href_args['post_mime_type'] ) ) { $and = " AND p.post_status != 'trash' " . wp_post_mime_type_where( $href_args['post_mime_type'], 'p' ); } else { $and = $this->wpdb->prepare( " AND p.post_status != 'trash' AND p.post_mime_type LIKE %s", $key . '%' ); } } // phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores $and = apply_filters( 'wpml-media_view-upload-sql_and', $and, $key, $view, $lang ); $sql_and = $sql . $and; $sql = apply_filters( 'wpml-media_view-upload-sql', $sql_and, $key, $view, $lang ); $res = apply_filters( 'wpml-media_view-upload-count', null, $key, $view, $lang ); // phpcs:enable if ( null === $res ) { $res = $this->wpdb->get_col( $sql ); } // Replace count. $view = preg_replace( '/\((\d+)\)/', '(' . $res[0] . ')', $view ); } // Replace href link, adding the 'lang' argument and the revised count. $href_args['lang'] = $lang; $href_args = array_map( 'urlencode', $href_args ); $new_href = add_query_arg( $href_args, $href_base ); $views[ $key ] = preg_replace( '/(href=["\'])([\s\S]+?)(["\'])/', '$1' . $new_href . '$3', $view ); } } return $views; } /** * Check if the image is not duplicated to another post before deleting it physically. * * @param string $file Full file name. * * @return string|null */ public function delete_file_filter( $file ) { if ( $file ) { $file_name = $this->get_file_name( $file ); $sql = "SELECT pm.meta_id, pm.post_id FROM {$this->wpdb->postmeta} AS pm WHERE pm.meta_value = %s AND pm.meta_key='_wp_attached_file'"; $attachment_prepared = $this->wpdb->prepare( $sql, [ $file_name ] ); $attachment = $this->wpdb->get_row( $attachment_prepared ); if ( ! empty( $attachment ) ) { $file = null; } } return $file; } private function get_file_name( $file ) { $file_name = $this->get_file_name_without_size_from_full_name( $file ); $upload_dir = wp_upload_dir(); /** @phpstan-ignore-next-line */ $path_parts = $file ? explode( "/", Str::replace( $upload_dir['basedir'], '', $file ) ) : []; if ( $path_parts ) { $path_parts[ count( $path_parts ) - 1 ] = $file_name; } return ltrim( implode( '/', $path_parts ), '/' ); } /** * Get file name without a size, i.e. 'a-600x400.png' -> 'a.png'. * * @param string $file Full file name. * * @return mixed|string|string[]|null */ private function get_file_name_without_size_from_full_name( $file ) { $file_name = preg_replace( '/^(.+)\-\d+x\d+(\.\w+)$/', '$1$2', $file ); $file_name = preg_replace( '/^[\s\S]+(\/.+)$/', '$1', $file_name ); $file_name = str_replace( '/', '', $file_name ); return $file_name; } } setup/endpoints/PerformSetup.php 0000644 00000001272 14721660154 0013063 0 ustar 00 <?php namespace WPML\Media\Setup\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use WPML\FP\Right; use WPML\FP\Left; use function WPML\Container\make; class PerformSetup implements IHandler { public function run( Collection $data ) { if ( ! defined( 'WPML_MEDIA_VERSION' ) || ! class_exists( 'WPML_Media_Set_Posts_Media_Flag_Factory' ) ) { return Left::of( [ 'key' => false ] ); } $offset = $data->get( 'offset' ); $mediaFlag = make( \WPML_Media_Set_Posts_Media_Flag_Factory::class )->create(); list ( , $newOffset, $continue ) = $mediaFlag->process_batch( $offset ); return Right::of( [ 'continue' => $continue, 'offset' => $newOffset, ] ); } } setup/endpoints/PrepareSetup.php 0000644 00000001563 14721660154 0013052 0 ustar 00 <?php namespace WPML\Media\Setup\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use WPML\Utilities\KeyedLock; use WPML\FP\Left; use WPML\FP\Right; use function WPML\Container\make; class PrepareSetup implements IHandler { const LOCK_RELEASE_TIMEOUT = 2 * MINUTE_IN_SECONDS; public function run( Collection $data ) { if ( !defined( 'WPML_MEDIA_VERSION' ) || !class_exists( 'WPML_Media_Set_Posts_Media_Flag_Factory' ) ) { return Left::of( [ 'key' => false ] ); } $lock = make( KeyedLock::class, [ ':name' => self::class ] ); $key = $lock->create( $data->get( 'key' ), self::LOCK_RELEASE_TIMEOUT ); if ( $key ) { $mediaFlag = make( \WPML_Media_Set_Posts_Media_Flag_Factory::class)->create(); $mediaFlag->clear_flags(); return Right::of( [ 'key' => $key, ] ); } else { return Left::of( [ 'key' => 'in-use', ] ); } } } translate/endpoints/PrepareForTranslation.php 0000644 00000001461 14721660154 0015551 0 ustar 00 <?php namespace WPML\Media\Translate\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use function WPML\Container\make; use WPML\FP\Left; use WPML\FP\Right; use WPML\Media\Option; use WPML\Utilities\KeyedLock; class PrepareForTranslation implements IHandler { const LOCK_RELEASE_TIMEOUT = 2 * MINUTE_IN_SECONDS; public function run( Collection $data ) { if ( Option::isSetupFinished() ) { return Left::of( [ 'key' => false ] ); } $lock = make( KeyedLock::class, [ ':name' => self::class ] ); $key = $lock->create( $data->get( 'key' ), self::LOCK_RELEASE_TIMEOUT ); if ( $key ) { make( \WPML_Media_Attachments_Duplication::class )->batch_scan_prepare( false ); return Right::of( [ 'key' => $key, ] ); } else { return Left::of( [ 'key' => 'in-use', ] ); } } } translate/endpoints/FinishMediaTranslation.php 0000644 00000000570 14721660154 0015664 0 ustar 00 <?php namespace WPML\Media\Translate\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use function WPML\Container\make; use WPML\FP\Right; class FinishMediaTranslation implements IHandler { public function run( Collection $data ) { make( \WPML_Media_Attachments_Duplication::class )->batch_mark_processed( false ); return Right::of( true ); } } translate/endpoints/DuplicateFeaturedImages.php 0000644 00000001342 14721660154 0016003 0 ustar 00 <?php namespace WPML\Media\Translate\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use WPML\FP\Obj; use WPML\Media\Option; use function WPML\Container\make; use WPML\FP\Right; class DuplicateFeaturedImages implements IHandler { public function run( Collection $data ) { if ( ! $this->shouldDuplicateFeaturedImages() ) { return Right::of( 0 ); } $numberLeft = $data->get( 'remaining', null ); return Right::of( make( \WPML_Media_Attachments_Duplication::class )->batch_duplicate_featured_images( false, $numberLeft ) ); } /** * @return bool */ private function shouldDuplicateFeaturedImages() { return (bool) Obj::prop( 'duplicate_featured', Option::getNewContentSettings() ); } } translate/endpoints/TranslateExistingMedia.php 0000644 00000000566 14721660154 0015702 0 ustar 00 <?php namespace WPML\Media\Translate\Endpoint; use WPML\Ajax\IHandler; use WPML\Collect\Support\Collection; use function WPML\Container\make; use WPML\FP\Right; class TranslateExistingMedia implements IHandler { public function run( Collection $data ) { return Right::of( make( \WPML_Media_Attachments_Duplication::class )->batch_translate_media( false ) ); } } FrontendHooks.php 0000644 00000002012 14721660154 0010041 0 ustar 00 <?php namespace WPML\Media; use WPML\Element\API\PostTranslations; use WPML\FP\Cast; use WPML\FP\Fns; use WPML\FP\Maybe; use WPML\FP\Obj; use WPML\FP\Relation; use WPML\LIB\WP\Hooks; use function WPML\FP\pipe; use function WPML\FP\spreadArgs; class FrontendHooks implements \IWPML_Frontend_Action { public function add_hooks() { Hooks::onFilter( 'wp_get_attachment_caption', 10, 2 ) ->then( spreadArgs( Fns::withoutRecursion( Fns::identity(), [ __CLASS__, 'translateCaption' ] ) ) ); } /** * @param string $caption * @param int $postId * * @return string */ public static function translateCaption( $caption, $postId ) { // $convertId :: int -> string|int|null $convertId = pipe( PostTranslations::getInCurrentLanguage(), Obj::prop( 'element_id' ) ); return Maybe::of( $postId ) ->map( $convertId ) ->map( Cast::toInt() ) ->reject( Relation::equals( $postId ) ) ->map( 'wp_get_attachment_caption' ) ->getOrElse( $caption ); } } class-wpml-model-attachments.php 0000644 00000012544 14721660154 0012762 0 ustar 00 <?php class WPML_Model_Attachments { const ATTACHMENT_TYPE = 'post_attachment'; /** @var SitePress */ private $sitepress; /** * @var WPML_Post_Status */ private $status_helper; /** * @param SitePress $sitepress * @param WPML_Post_Status $status_helper */ public function __construct( SitePress $sitepress, WPML_Post_Status $status_helper ) { $this->sitepress = $sitepress; $this->status_helper = $status_helper; } /** * @param int $attachment_id * @param int $duplicated_attachment_id */ public function duplicate_post_meta_data( $attachment_id, $duplicated_attachment_id ) { foreach ( array( '_wp_attachment_metadata', '_wp_attached_file' ) as $meta_key ) { $duplicated_meta_value = get_post_meta( $duplicated_attachment_id, $meta_key, true ); if ( ! $duplicated_meta_value ) { $source_meta_value = get_post_meta( $attachment_id, $meta_key, true ); update_post_meta( $duplicated_attachment_id, $meta_key, $source_meta_value ); } } update_post_meta( $duplicated_attachment_id, 'wpml_media_processed', 1 ); do_action( 'wpml_media_create_duplicate_attachment', $attachment_id, $duplicated_attachment_id ); } /** * @param int $trid * @param string $target_language * * @return null|WP_Post */ public function find_duplicated_attachment( $trid, $target_language ) { $attachment_translations = $this->sitepress->get_element_translations( $trid, self::ATTACHMENT_TYPE, true, true ); if ( is_array( $attachment_translations ) ) { foreach ( $attachment_translations as $attachment_translation ) { if ( $attachment_translation->language_code === $target_language ) { return get_post( $attachment_translation->element_id ); } } } return null; } /** * @param WP_Post|null $attachment * @param int|false|null $parent_id_of_attachement * @param string $target_language * * @return int|null */ public function fetch_translated_parent_id( $attachment, $parent_id_of_attachement, $target_language ) { $translated_parent_id = null; if ( null !== $attachment && $attachment->post_parent ) { $translated_parent_id = $attachment->post_parent; } if ( $parent_id_of_attachement ) { $parent_post = get_post( $parent_id_of_attachement ); if ( $parent_post ) { $translated_parent_id = $parent_id_of_attachement; $parent_id_language_code = $this->sitepress->get_language_for_element( $parent_post->ID, 'post_' . $parent_post->post_type ); if ( $parent_id_language_code !== $target_language ) { $translated_parent_id = $this->sitepress->get_object_id( $parent_post->ID, $parent_post->post_type, false, $target_language ); } } } return $translated_parent_id; } /** * @param int $new_parent_id * @param WP_Post $attachment */ public function update_parent_id_in_existing_attachment( $new_parent_id, $attachment ) { if ( $this->is_valid_post_type( $attachment->post_type ) ) { wp_update_post( array( 'ID' => $attachment->ID, 'post_parent' => $new_parent_id ) ); } } /** * @param string $post_type * * @return bool */ private function is_valid_post_type( $post_type ) { $post_types = array_keys( get_post_types( ) ); return in_array( $post_type, $post_types, true ); } /** * @param int $attachment_id * @param string $target_language * @param int $parent_id_in_target_language * @param int $trid * * @return int * @throws WPML_Media_Exception */ public function duplicate_attachment( $attachment_id, $target_language, $parent_id_in_target_language, $trid ) { $post = get_post( $attachment_id ); $post->post_parent = $parent_id_in_target_language; $post->ID = null; $duplicated_attachment_id = $this->insert_attachment( $post ); if ( ! $duplicated_attachment_id ) { throw new WPML_Media_Exception( 'Error occured during inserting duplicated attachment to db' ); } $this->add_language_information_to_attachment( $attachment_id, $duplicated_attachment_id, $target_language, $trid ); return $duplicated_attachment_id; } /** * @param WP_Post $post * * @return int */ private function insert_attachment( $post ) { $add_attachment_filters_temp = null; if ( array_key_exists( 'add_attachment', $GLOBALS['wp_filter'] ) ) { $add_attachment_filters_temp = $GLOBALS['wp_filter']['add_attachment']; unset( $GLOBALS['wp_filter']['add_attachment'] ); } /** @phpstan-ignore-next-line (WP doc issue) */ $duplicated_attachment_id = wp_insert_post( $post ); if ( ! is_int( $duplicated_attachment_id ) ) { $duplicated_attachment_id = 0; } if ( null !== $add_attachment_filters_temp ) { $GLOBALS['wp_filter']['add_attachment'] = $add_attachment_filters_temp; unset( $add_attachment_filters_temp ); } return $duplicated_attachment_id; } /** * @param int $attachment_id * @param int $duplicated_attachment_id * @param string $target_language * @param int $trid */ private function add_language_information_to_attachment( $attachment_id, $duplicated_attachment_id, $target_language, $trid ) { $source_language = $this->sitepress->get_language_for_element( $attachment_id, self::ATTACHMENT_TYPE ); $this->sitepress->set_element_language_details( $duplicated_attachment_id, self::ATTACHMENT_TYPE, $trid, $target_language, $source_language ); $this->status_helper->set_status( $duplicated_attachment_id, ICL_TM_DUPLICATE ); $this->status_helper->set_update_status( $duplicated_attachment_id, false ); } } class-wpml-media-exception.php 0000644 00000000070 14721660154 0012413 0 ustar 00 <?php class WPML_Media_Exception extends Exception { } Loader.php 0000644 00000002253 14721660154 0006473 0 ustar 00 <?php namespace WPML\Media; use WPML\Core\WP\App\Resources; use WPML\LIB\WP\Hooks; use WPML\Media\Option; use WPML\Media\Setup\Endpoint\PerformSetup; use WPML\Media\Setup\Endpoint\PrepareSetup; use WPML\Media\Translate\Endpoint\DuplicateFeaturedImages; use WPML\Media\Translate\Endpoint\FinishMediaTranslation; use WPML\Media\Translate\Endpoint\PrepareForTranslation; use WPML\Media\Translate\Endpoint\TranslateExistingMedia; class Loader implements \IWPML_Backend_Action { public function add_hooks() { if ( ! Option::isSetupFinished() ) { Hooks::onAction( 'wp_loaded' ) ->then( [ self::class, 'getData' ] ) ->then( Resources::enqueueApp( 'media-setup' ) ); } } public static function getData() { return [ 'name' => 'media_setup', 'data' => [ 'endpoints' => [ 'prepareForTranslation' => PrepareForTranslation::class, 'translateExistingMedia' => TranslateExistingMedia::class, 'duplicateFeaturedImages' => DuplicateFeaturedImages::class, 'finishMediaTranslation' => FinishMediaTranslation::class, 'prepareForSetup' => PrepareSetup::class, 'performSetup' => PerformSetup::class, ] ] ]; } } settings/class-wpml-media-settings.php 0000644 00000020273 14721660154 0014124 0 ustar 00 <?php use WPML\LIB\WP\Nonce; class WPML_Media_Settings { const ID = 'ml-content-setup-sec-media'; private $wpdb; public function __construct( $wpdb ) { $this->wpdb = $wpdb; } public function add_hooks() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_script' ) ); add_action( 'icl_tm_menu_mcsetup', array( $this, 'render' ) ); add_filter( 'wpml_mcsetup_navigation_links', array( $this, 'mcsetup_navigation_links' ) ); } public function enqueue_script() { $handle = 'wpml-media-settings'; wp_register_script( $handle, ICL_PLUGIN_URL . '/res/js/media/settings.js', [], ICL_SITEPRESS_VERSION, true ); wp_localize_script( $handle, 'wpml_media_settings_data', [ 'nonce_wpml_media_scan_prepare' => wp_create_nonce( 'wpml_media_scan_prepare' ), 'nonce_wpml_media_set_initial_language' => wp_create_nonce( 'wpml_media_set_initial_language' ), 'nonce_wpml_media_translate_media' => wp_create_nonce( 'wpml_media_translate_media' ), 'nonce_wpml_media_duplicate_featured_images' => wp_create_nonce( 'wpml_media_duplicate_featured_images' ), 'nonce_wpml_media_set_content_prepare' => wp_create_nonce( 'wpml_media_set_content_prepare' ), 'nonce_wpml_media_set_content_defaults' => wp_create_nonce( 'wpml_media_set_content_defaults' ), 'nonce_wpml_media_duplicate_media' => wp_create_nonce( 'wpml_media_duplicate_media' ), 'nonce_wpml_media_mark_processed' => wp_create_nonce( 'wpml_media_mark_processed' ), ] ); wp_enqueue_script( $handle ); } public function render() { // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared $has_orphan_attachments = $this->wpdb->get_var( "SELECT ID FROM {$this->wpdb->posts} as posts LEFT JOIN {$this->wpdb->prefix}icl_translations as translations ON posts.ID = translations.element_id WHERE posts.post_type = 'attachment' AND translations.element_id IS NULL LIMIT 0, 1" ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared $has_orphan_attachments = $has_orphan_attachments ? 1 : 0; ?> <div class="wpml-section" id="<?php echo esc_attr( self::ID ); ?>"> <div class="wpml-section-header"> <h3><?php esc_html_e( 'Media Translation', 'sitepress' ); ?></h3> </div> <div class="wpml-section-content"> <?php if ( $has_orphan_attachments ) : ?> <p><?php esc_html_e( "The Media Translation plugin needs to add languages to your site's media. Without this language information, existing media files will not be displayed in the WordPress admin.", 'sitepress' ); ?></p> <?php else : ?> <p><?php esc_html_e( 'You can check if some attachments can be duplicated to translated content:', 'sitepress' ); ?></p> <?php endif ?> <form id="wpml_media_options_form"> <input type="hidden" name="no_lang_attachments" value="<?php echo (int) $has_orphan_attachments; ?>"/> <input type="hidden" id="wpml_media_options_action"/> <table class="wpml-media-existing-content"> <tr> <td colspan="2"> <ul class="wpml_media_options_language"> <li> <label> <input type="checkbox" id="set_language_info" name="set_language_info" value="1" <?php echo $has_orphan_attachments ? ' checked="checked"' : ' disabled="disabled"'; ?> /> <?php esc_html_e( 'Set language information for existing media', 'sitepress' ); ?> </label></li> <li><label><input type="checkbox" id="translate_media" name="translate_media" value="1" checked="checked"/> <?php esc_html_e( 'Translate existing media in all languages', 'sitepress' ); ?></label></li> <li><label><input type="checkbox" id="duplicate_media" name="duplicate_media" value="1" checked="checked"/> <?php esc_html_e( 'Duplicate existing media for translated content', 'sitepress' ); ?></label></li> <li><label><input type="checkbox" id="duplicate_featured" name="duplicate_featured" value="1" checked="checked"/> <?php esc_html_e( 'Duplicate the featured images for translated content', 'sitepress' ); ?></label></li> </ul> </td> </tr> <tr> <td><a href="https://wpml.org/documentation/getting-started-guide/media-translation/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore" target="_blank"><?php esc_html_e( 'Media Translation Documentation', 'sitepress' ); ?></a></td> <td align="right"> <input class="button-primary" name="start" type="submit" value="<?php esc_attr_e( 'Start', 'sitepress' ); ?> »"/> </td> </tr> <tr> <td colspan="2"> <img class="progress" src="<?php echo ICL_PLUGIN_URL; ?>/res/img/ajax-loader.gif" width="16" height="16" alt="loading" style="display: none;"/> <span class="status"> </span> </td> </tr> </table> <table class="wpml-media-new-content-settings"> <tr> <td colspan="2"> <h4><?php esc_html_e( 'How to handle media for new content:', 'sitepress' ); ?></h4> </td> </tr> <tr> <td colspan="2"> <ul class="wpml_media_options_language"> <?php $content_defaults = \WPML\Media\Option::getNewContentSettings(); $always_translate_media_html_checked = $content_defaults['always_translate_media'] ? 'checked="checked"' : ''; $duplicate_media_html_checked = $content_defaults['duplicate_media'] ? 'checked="checked"' : ''; $duplicate_featured_html_checked = $content_defaults['duplicate_featured'] ? 'checked="checked"' : ''; ?> <li> <label><input type="checkbox" name="content_default_always_translate_media" value="1" <?php echo $always_translate_media_html_checked; ?> /> <?php esc_html_e( 'When uploading media to the Media library, make it available in all languages', 'sitepress' ); ?></label> </li> <li> <label><input type="checkbox" name="content_default_duplicate_media" value="1" <?php echo $duplicate_media_html_checked; ?> /> <?php esc_html_e( 'Duplicate media attachments for translations', 'sitepress' ); ?></label> </li> <li> <label><input type="checkbox" name="content_default_duplicate_featured" value="1" <?php echo $duplicate_featured_html_checked; ?> /> <?php esc_html_e( 'Duplicate featured images for translations', 'sitepress' ); ?></label> </li> </ul> </td> </tr> <tr> <td colspan="2"> <h4><?php esc_html_e( 'How to handle media library texts:', 'sitepress' ); ?></h4> </td> </tr> <tr> <td colspan="2"> <ul class="wpml_media_options_media_library_texts"> <?php $translateMediaLibraryTexts = \WPML\Media\Option::getTranslateMediaLibraryTexts() ? 'checked="checked"' : ''; ?> <li> <label><input type="checkbox" name="translate_media_library_texts" value="1" <?php echo $translateMediaLibraryTexts; ?> /> <?php esc_html_e( 'Translate media library texts with posts', 'sitepress' ); ?></label> </li> </ul> </td> </tr> <tr> <td colspan="2" align="right"> <input class="button-secondary" name="set_defaults" type="submit" value="<?php esc_attr_e( 'Apply', 'sitepress' ); ?>"/> </td> </tr> <tr> <td colspan="2"> <img class="content_default_progress" src="<?php echo ICL_PLUGIN_URL; ?>/res/img/ajax-loader.gif" width="16" height="16" alt="loading" style="display: none;"/> <span class="content_default_status"> </span> </td> </tr> </table> <div id="wpml_media_all_done" class="hidden updated"> <p><?php esc_html_e( "You're all done. From now on, all new media files that you upload to content will receive a language. You can automatically duplicate them to translations from the post-edit screen.", 'sitepress' ); ?></p> </div> </form> </div> </div> <?php } public function mcsetup_navigation_links( array $mcsetup_sections ) { $mcsetup_sections[ self::ID ] = esc_html__( 'Media Translation', 'sitepress' ); return $mcsetup_sections; } } settings/class-wpml-media-settings-factory.php 0000644 00000000673 14721660154 0015573 0 ustar 00 <?php class WPML_Media_Settings_Factory extends WPML_Current_Screen_Loader_Factory { public function create_hooks() { global $wpdb; return new WPML_Media_Settings( $wpdb ); } public function get_screen_regex() { return defined( 'WPML_TM_FOLDER' ) ? '/(' . WPML_PLUGIN_FOLDER . '\/menu\/translation-options|wpml_page_' . WPML_TM_FOLDER . '\/menu\/settings)/' : '/' . WPML_PLUGIN_FOLDER . '\/menu\/translation-options/'; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0.03 |
proxy
|
phpinfo
|
Настройка