diff --git a/languages/cloudinary.pot b/languages/cloudinary.pot index 2f038de30..b4ef20e80 100644 --- a/languages/cloudinary.pot +++ b/languages/cloudinary.pot @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: Cloudinary STABLETAG\n" "Report-Msgid-Bugs-To: https://github.com/cloudinary/cloudinary_wordpress\n" -"POT-Creation-Date: 2024-03-18 17:39:40+00:00\n" +"POT-Creation-Date: 2024-07-26 09:09:31+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -63,11 +63,11 @@ msgstr[1] "" msgid "No items found." msgstr "" -#: php/cache/class-cache-point.php:962 php/class-assets.php:1131 +#: php/cache/class-cache-point.php:962 php/class-assets.php:1144 msgid "Cloudinary Asset" msgstr "" -#: php/cache/class-cache-point.php:963 php/class-assets.php:1132 +#: php/cache/class-cache-point.php:963 php/class-assets.php:1145 msgid "Post type to represent a non-media library asset." msgstr "" @@ -87,114 +87,114 @@ msgstr "" msgid "Enable Cloudinary status" msgstr "" -#: php/class-assets.php:687 +#: php/class-assets.php:699 msgid "Caching" msgstr "" -#: php/class-assets.php:698 +#: php/class-assets.php:710 msgid "Creating shadow assets" msgstr "" -#: php/class-assets.php:709 +#: php/class-assets.php:721 msgid "Updating asset storage" msgstr "" -#: php/class-assets.php:1193 +#: php/class-assets.php:1206 msgid "Additional Asset Sync Settings" msgstr "" -#: php/class-assets.php:1213 +#: php/class-assets.php:1226 msgid "Additional asset sync settings" msgstr "" -#: php/class-assets.php:1214 +#: php/class-assets.php:1227 msgid "" "Enabling additional asset syncing will sync the toggled assets with " "Cloudinary to make use of advanced optimization and CDN delivery " "functionality." msgstr "" -#: php/class-assets.php:1215 +#: php/class-assets.php:1228 msgid "Enable additional asset syncing" msgstr "" -#: php/class-assets.php:1254 +#: php/class-assets.php:1267 msgid "External Asset Sync Settings" msgstr "" -#: php/class-assets.php:1279 php/class-cache.php:615 +#: php/class-assets.php:1292 php/class-cache.php:615 msgid "Plugin" msgstr "" -#: php/class-assets.php:1315 php/class-cache.php:792 +#: php/class-assets.php:1328 php/class-cache.php:792 msgid "Plugins" msgstr "" -#: php/class-assets.php:1333 php/class-cache.php:809 +#: php/class-assets.php:1346 php/class-cache.php:809 msgid "Deliver assets from all plugin folders" msgstr "" -#: php/class-assets.php:1365 php/class-cache.php:652 +#: php/class-assets.php:1378 php/class-cache.php:652 msgid "Theme" msgstr "" -#: php/class-assets.php:1397 php/class-cache.php:843 +#: php/class-assets.php:1410 php/class-cache.php:843 msgid "Themes" msgstr "" -#: php/class-assets.php:1415 php/class-cache.php:860 +#: php/class-assets.php:1428 php/class-cache.php:860 msgid "Deliver all assets from active theme." msgstr "" -#: php/class-assets.php:1440 php/class-assets.php:1475 php/class-cache.php:684 +#: php/class-assets.php:1453 php/class-assets.php:1488 php/class-cache.php:684 #: php/class-cache.php:895 msgid "WordPress" msgstr "" -#: php/class-assets.php:1449 php/class-cache.php:668 +#: php/class-assets.php:1462 php/class-cache.php:668 msgid "WordPress Admin" msgstr "" -#: php/class-assets.php:1456 php/class-cache.php:675 +#: php/class-assets.php:1469 php/class-cache.php:675 msgid "WordPress Includes" msgstr "" -#: php/class-assets.php:1493 php/class-cache.php:912 +#: php/class-assets.php:1506 php/class-cache.php:912 msgid "Deliver all assets from WordPress core." msgstr "" -#: php/class-assets.php:1519 php/class-assets.php:1545 php/class-cache.php:708 +#: php/class-assets.php:1532 php/class-assets.php:1558 php/class-cache.php:708 #: php/class-cache.php:947 msgid "Content" msgstr "" -#: php/class-assets.php:1526 php/class-cache.php:699 +#: php/class-assets.php:1539 php/class-cache.php:699 msgid "Uploads" msgstr "" -#: php/class-assets.php:1563 php/class-cache.php:964 +#: php/class-assets.php:1576 php/class-cache.php:964 msgid "Deliver all content assets from WordPress Media Library." msgstr "" -#: php/class-assets.php:1587 +#: php/class-assets.php:1600 msgid "Enable external assets" msgstr "" -#: php/class-assets.php:1588 +#: php/class-assets.php:1601 msgid "" "Enabling external assets allows you to sync assets from specific external " "sources with Cloudinary." msgstr "" -#: php/class-assets.php:1598 +#: php/class-assets.php:1611 msgid "Domains for each external source." msgstr "" -#: php/class-assets.php:1601 +#: php/class-assets.php:1614 msgid "Enter a domain" msgstr "" -#: php/class-assets.php:1602 +#: php/class-assets.php:1615 msgid "Press ENTER or SPACE or type comma or tab to continue." msgstr "" @@ -371,7 +371,7 @@ msgstr "" msgid "Share a %s with Cloudinary to help improve the plugin." msgstr "" -#: php/class-deactivation.php:183 php/class-report.php:275 +#: php/class-deactivation.php:183 php/class-report.php:277 #: ui-definitions/settings-pages.php:390 #. translators: The System Report link and label. msgid "System Report" @@ -536,19 +536,19 @@ msgstr "" msgid "Synced" msgstr "" -#: php/class-media.php:3081 +#: php/class-media.php:3082 msgid "No Cloudinary filters" msgstr "" -#: php/class-media.php:3181 +#: php/class-media.php:3182 msgid "Media Settings" msgstr "" -#: php/class-media.php:3184 +#: php/class-media.php:3185 msgid "Media Display" msgstr "" -#: php/class-media.php:3188 php/media/class-global-transformations.php:620 +#: php/class-media.php:3189 php/media/class-global-transformations.php:620 #: php/ui/component/class-asset-preview.php:73 #: php/ui/component/class-plan-details.php:119 #: php/ui/component/class-plan-status.php:128 @@ -556,7 +556,7 @@ msgstr "" msgid "Transformations" msgstr "" -#: php/class-media.php:3189 +#: php/class-media.php:3190 msgid "" "Cloudinary allows you to easily transform your images on-the-fly to any " "required format, style and dimension, and also optimizes images for minimal " @@ -565,12 +565,12 @@ msgid "" "transformation and delivery URLs." msgstr "" -#: php/class-media.php:3194 ui-definitions/settings-image.php:164 +#: php/class-media.php:3195 ui-definitions/settings-image.php:164 #: ui-definitions/settings-video.php:250 msgid "See examples" msgstr "" -#: php/class-plugin.php:762 +#: php/class-plugin.php:741 msgid "Visit plugin site" msgstr "" @@ -586,40 +586,40 @@ msgstr "" msgid "Cloudinary Metadata viewer" msgstr "" -#: php/class-report.php:284 +#: php/class-report.php:286 msgid "System information report" msgstr "" -#: php/class-report.php:287 +#: php/class-report.php:289 msgid "Enable report" msgstr "" -#: php/class-report.php:347 +#: php/class-report.php:349 msgid "" "Enabling system information reporting will allow you to generate and " "download a realtime snapshot report. The report will be in JSON format and " "will include information about:" msgstr "" -#: php/class-report.php:350 +#: php/class-report.php:352 msgid "Current WordPress and Cloudinary configuration." msgstr "" -#: php/class-report.php:351 +#: php/class-report.php:353 msgid "Currently installed plugins." msgstr "" -#: php/class-report.php:352 +#: php/class-report.php:354 msgid "Any themes that are being used." msgstr "" -#: php/class-report.php:353 +#: php/class-report.php:355 msgid "" "Any specifically selected media. These can be added to the report from the " "WordPress Media Library." msgstr "" -#: php/class-report.php:354 +#: php/class-report.php:356 msgid "" "Any specifically selected posts or pages. These can be added to the report " "from the relevant listing pages." @@ -747,60 +747,60 @@ msgid "" "%1$sCloudinary Academy%2$s." msgstr "" -#: php/class-utils.php:440 +#: php/class-utils.php:469 #. translators: The plugin version. msgid "I need help with Cloudinary WordPress plugin version %s" msgstr "" -#: php/class-utils.php:451 +#: php/class-utils.php:480 msgid "" "Please, provide more details on your request, and if possible, attach a " "System Report" msgstr "" -#: php/class-utils.php:743 +#: php/class-utils.php:775 msgid "Debug log is empty" msgstr "" -#: php/class-utils.php:793 +#: php/class-utils.php:825 msgid "Missing SRC attribute." msgstr "" -#: php/class-utils.php:830 +#: php/class-utils.php:862 #. translators: The attachment ID. msgid "Clean up sync metadata for %d" msgstr "" -#: php/class-utils.php:878 +#: php/class-utils.php:910 msgid "Thumbnail" msgstr "" -#: php/class-utils.php:879 +#: php/class-utils.php:911 msgid "Medium" msgstr "" -#: php/class-utils.php:880 +#: php/class-utils.php:912 msgid "Medium Large" msgstr "" -#: php/class-utils.php:881 +#: php/class-utils.php:913 msgid "Large" msgstr "" -#: php/class-utils.php:882 +#: php/class-utils.php:914 msgid "Full Size" msgstr "" -#: php/connect/class-api.php:426 +#: php/connect/class-api.php:427 msgid "No direct access to file system." msgstr "" -#: php/connect/class-api.php:533 +#: php/connect/class-api.php:538 #. translators: variable is thread name and queue size. msgid "Uploading remote url: %1$s." msgstr "" -#: php/connect/class-api.php:664 +#: php/connect/class-api.php:669 msgid "Could not get VIP file content" msgstr "" @@ -1183,18 +1183,29 @@ msgid "Create here a free Cloudinary account" msgstr "" #: php/templates/connection-string.php:31 -msgid "Open your Cloudinary Dashboard" +msgid "Open your Cloudinary Console." msgstr "" -#: php/templates/connection-string.php:32 -msgid "At the top of the dashboard you will find the Account Details section" +#: php/templates/connection-string.php:36 +#. translators: %1$s and %2$s are the opening and close the anchor tag for the +#. API Keys page. +msgid "Copy the API environment variable format from the %1$sAPI Keys page%2$s." msgstr "" -#: php/templates/connection-string.php:33 -msgid "Copy the API Environment variable" +#: php/templates/connection-string.php:37 +msgid "Get your API Keys" msgstr "" -#: php/templates/connection-string.php:37 +#: php/templates/connection-string.php:46 +#. translators: %1$s and %2$s are placeholders for code tags. %3$s is a line +#. break. +msgid "" +"Replace %1$s%2$s and %1$s%2$s with your " +"actual values.%3$sYour cloud name is already correctly included in the " +"format." +msgstr "" + +#: php/templates/connection-string.php:56 msgid "Where the connection string can be found on the cloudinary.com console." msgstr "" diff --git a/php/class-assets.php b/php/class-assets.php index 05f1ba140..20b748bcd 100644 --- a/php/class-assets.php +++ b/php/class-assets.php @@ -433,7 +433,19 @@ public function activate_parent( $url ) { * @return string */ public function clean_path( $path ) { - $home = Utils::clean_url( trailingslashit( home_url() ) ); + /** + * Filter the home url. + * + * @hook cloudinary_home_url + * @since 3.1.9 + * + * @param $home_url {string} The home url. + * + * @return {string} + */ + $home_url = apply_filters( 'cloudinary_home_url', home_url() ); + + $home = Utils::clean_url( trailingslashit( $home_url ) ); $path = str_replace( $home, '', Utils::clean_url( $path ) ); if ( empty( Utils::pathinfo( $path, PATHINFO_EXTENSION ) ) ) { $path = urldecode( trailingslashit( $path ) ); diff --git a/php/class-delivery.php b/php/class-delivery.php index 297fc97ce..4693304a3 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -879,18 +879,29 @@ public function find_attachment_size_urls() { if ( $results ) { foreach ( $results as $result ) { - if ( ! $this->is_deliverable( $result->post_id ) ) { + /** + * Get the contextualized post id. + * + * @hook cloudinary_contextualized_post_id + * @since 3.1.9 + * + * @param $post_id {int} The post ID. + * + * @return {int} + */ + $post_id = apply_filters( 'cloudinary_contextualized_post_id', $result->post_id ); + if ( ! $this->is_deliverable( $post_id ) ) { continue; } // If we are here, it means that an attachment in the media library doesn't have a delivery for the url. // Reset the signature for delivery and add to sync, to update it. - $this->create_delivery( $result->post_id ); + $this->create_delivery( $post_id ); if ( true === $auto_sync ) { - $this->sync->add_to_sync( $result->post_id ); + $this->sync->add_to_sync( $post_id ); } - $size = $this->get_sized( $result->post_id ); - $key = ! empty( $size['sized_url'] ) ? $size['sized_url'] : wp_get_attachment_url( $result->post_id ); - $cached[ $key ] = (int) $result->post_id; + $size = $this->get_sized( $post_id ); + $key = ! empty( $size['sized_url'] ) ? $size['sized_url'] : wp_get_attachment_url( $post_id ); + $cached[ $key ] = (int) $post_id; } } wp_cache_add( $key, $cached ); @@ -1175,8 +1186,20 @@ protected function standardize_tag( $tag_element ) { $this->plugin->get_component( 'storage' )->size_sync( $tag_element['id'] ); } - $base_url = $this->plugin->settings->get_url( 'edit_asset' ); - $tag_element['atts']['data-permalink'] = add_query_arg( 'asset', $tag_element['id'], $base_url ); + $base_url = $this->plugin->settings->get_url( 'edit_asset' ); + + /** + * Filter the permalink for the edit asset link. + * + * @hook cloudinary_edit_asset_permalink + * @since 3.1.9 + * + * @param $permalink {string} The permalink. + * + * @return {string} + */ + $permalink = apply_filters( 'cloudinary_edit_asset_permalink', add_query_arg( 'asset', $tag_element['id'], $base_url ) ); + $tag_element['atts']['data-permalink'] = $permalink; } $tag_element['atts']['data-version'] = $this->media->get_cloudinary_version( $tag_element['id'] ); diff --git a/php/class-media.php b/php/class-media.php index 16dd129a7..346be56e8 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -2764,6 +2764,7 @@ public function get_context_options( $attachment_id ) { ); $context_options = array( 'cld_wp_plugin' => 1, + 'wp_context' => Utils::get_media_context( $attachment_id ), ); if ( $this->is_folder_synced( $attachment_id ) ) { $context_options = wp_parse_args( $media_library_context, $context_options ); diff --git a/php/class-utils.php b/php/class-utils.php index 349041005..c0e9db9be 100644 --- a/php/class-utils.php +++ b/php/class-utils.php @@ -999,21 +999,45 @@ public static function attachment_url_to_postid( $url ) { public static function query_relations( $public_ids, $urls = array() ) { global $wpdb; - $media_context = self::get_media_context(); $wheres = array(); $searched_things = array(); + + /** + * Filter the media context query. + * + * @hook cloudinary_media_context_query + * @since 3.1.9 + * + * @param $media_context_query {string} The default media context query. + * + * @return {string} + */ + $media_context_query = apply_filters( 'cloudinary_media_context_query', 'media_context = %s' ); + + /** + * Filter the media context things. + * + * @hook cloudinary_media_context_things + * @since 3.1.9 + * + * @param $media_context_things {array} The default media context things. + * + * @return {array} + */ + $media_context_things = apply_filters( 'cloudinary_media_context_things', array( 'default' ) ); + if ( ! empty( $urls ) ) { // Do the URLS. $list = implode( ', ', array_fill( 0, count( $urls ), '%s' ) ); - $where = "(url_hash IN( {$list} ) AND media_context = %s)"; - $searched_things = array_merge( $searched_things, array_map( 'md5', $urls ), array( $media_context ) ); + $where = "(url_hash IN( {$list} ) AND {$media_context_query} )"; + $searched_things = array_merge( $searched_things, array_map( 'md5', $urls ), $media_context_things ); $wheres[] = $where; } if ( ! empty( $public_ids ) ) { // Do the public_ids. $list = implode( ', ', array_fill( 0, count( $public_ids ), '%s' ) ); - $where = "(public_hash IN( {$list} ) AND media_context = %s)"; - $searched_things = array_merge( $searched_things, array_map( 'md5', $public_ids ), array( $media_context ) ); + $where = "(public_hash IN( {$list} ) AND {$media_context_query} )"; + $searched_things = array_merge( $searched_things, array_map( 'md5', $public_ids ), $media_context_things ); $wheres[] = $where; } diff --git a/php/integrations/class-wpml.php b/php/integrations/class-wpml.php index 7804f103a..dc0468e90 100644 --- a/php/integrations/class-wpml.php +++ b/php/integrations/class-wpml.php @@ -8,6 +8,8 @@ namespace Cloudinary\Integrations; use Cloudinary\Cron; +use Cloudinary\Relate\Relationship; +use Cloudinary\Utils; use WPML\Auryn\InjectionException; use WPML\FP\Obj; use WPML\Records\Translations as TranslationRecords; @@ -59,6 +61,12 @@ public function register_hooks() { add_filter( 'wp_generate_attachment_metadata', array( $this, 'wp_generate_attachment_metadata' ), 10, 3 ); add_action( 'cloudinary_ready', array( $this, 'setup_cron' ) ); add_filter( 'cloudinary_media_context', array( $this, 'add_wpml_context' ), 10, 2 ); + add_filter( 'cloudinary_media_context_query', array( $this, 'filter_media_context_query' ) ); + add_filter( 'cloudinary_media_context_things', array( $this, 'filter_media_context_things' ) ); + add_filter( 'cloudinary_home_url', array( $this, 'home_url' ) ); + add_action( 'cloudinary_edit_asset_permalink', array( $this, 'add_locale' ) ); + add_filter( 'cloudinary_contextualized_post_id', array( $this, 'contextualized_post_id' ) ); + add_filter( 'wpml_admin_language_switcher_items', array( $this, 'language_switcher_items' ) ); } /** @@ -151,6 +159,101 @@ public function add_wpml_context( $context, $attachment_id ) { return $context; } + /** + * Filter the media context query. + * + * @return string + */ + public function filter_media_context_query() { + return 'media_context IN ( %s, %s )'; + } + + /** + * Filter the media context things to query. + * + * @param array $things The things to query for. + * + * @return array + */ + public function filter_media_context_things( $things ) { + $things[] = Utils::get_media_context(); + + return $things; + } + + /** + * Get the home URL. + * Typically WPML will return the home URL with the current language as subdirectory. + * For dealing with static assets, we need the home URL without the language subdirectory. + * + * @return string + */ + public function home_url() { + return get_option( 'home' ); + } + + /** + * Add the locale to the edit asset link. + * This will ensure that the asset is edited in the correct language. + * + * @param string $permalink The permalink. + * + * @return string + */ + public function add_locale( $permalink ) { + return add_query_arg( 'lang', apply_filters( 'wpml_current_language', null ), $permalink ); + } + + /** + * Get the contextualized post id. + * + * @param int $post_id The attachment id. + * + * @return int + */ + public function contextualized_post_id( $post_id ) { + if ( 'attachment' !== get_post_type( $post_id ) ) { + return $post_id; + } + + return apply_filters( 'wpml_object_id', $post_id, 'attachment' ); + } + + /** + * Update the link for the Cloudinary Assets item on the admin bar language switcher. + * + * @param array $languages_links The language switcher items. + * + * @return array + */ + public function language_switcher_items( $languages_links ) { + foreach ( $languages_links as $language => &$link ) { + $args = array(); + $query_args = wp_parse_url( $link['url'], PHP_URL_QUERY ); + parse_str( $query_args, $args ); + + // Check if we are in the context of editing an asset. + if ( + empty( $args['page'] ) + || 'cloudinary' !== $args['page'] + || empty( $args['section'] ) + || 'edit-asset' !== $args['section'] + || empty( $args['asset'] ) + ) { + break; + } + + $relationship = new Relationship( $args['asset'] ); + $contextual_relationship = $relationship->get_contextualized_relationship( $language ); + + if ( ! empty( $contextual_relationship ) ) { + $link['url'] = add_query_arg( 'asset', $contextual_relationship->post_id, $link['url'] ); + } + } + + return $languages_links; + } + /** * Register the cron action at a late stage to ensure that WPML is loaded. * @@ -223,8 +326,8 @@ protected function get_unynced() { ) LIMIT %d"; - $query = $wpdb->prepare( $sql, self::LIMIT ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - $results = array_map( 'intval', $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared + $query = $wpdb->prepare( $sql, self::LIMIT ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $results = array_map( 'intval', $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return $results; } diff --git a/php/relate/class-relationship.php b/php/relate/class-relationship.php index c7d8d956e..458ba9fd2 100644 --- a/php/relate/class-relationship.php +++ b/php/relate/class-relationship.php @@ -250,4 +250,29 @@ public static function get_ids_by_public_id( $public_id ) { return array_map( 'intval', $ids ); } + + /** + * Get the relationship in a different context. + * + * @param string $context The context. + * + * @return Relationship|null + */ + public function get_contextualized_relationship( $context ) { + $relationship = null; + if ( ! empty( $this->context ) && $this->context !== $context ) { + global $wpdb; + $table_name = Utils::get_relationship_table(); + + $sql = $wpdb->prepare( "SELECT post_id FROM {$table_name} WHERE url_hash = %s AND media_context = %s", $this->url_hash, $context ); // phpcs:ignore WordPress.DB + $post_id = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB + + if ( $post_id ) { + $relationship = self::get_relationship( $post_id ); + $relationship->context = $context; + } + } + + return $relationship; + } }