first commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Hooks implements IWPML_Action {
|
||||
|
||||
/** @var IWPML_PB_Media_Update_Factory $media_update_factory */
|
||||
private $media_update_factory;
|
||||
|
||||
/** @var string $page_builder_slug */
|
||||
private $page_builder_slug;
|
||||
|
||||
/**
|
||||
* WPML_Page_Builders_Media_Hooks constructor.
|
||||
*
|
||||
* @param IWPML_PB_Media_Update_Factory $media_update_factory
|
||||
* @param string $page_builder_slug
|
||||
*/
|
||||
public function __construct( IWPML_PB_Media_Update_Factory $media_update_factory, $page_builder_slug ) {
|
||||
$this->media_update_factory = $media_update_factory;
|
||||
$this->page_builder_slug = $page_builder_slug;
|
||||
}
|
||||
public function add_hooks() {
|
||||
add_filter( 'wpml_pb_get_media_updaters', array( $this, 'add_media_updater' ) );
|
||||
add_filter( 'wpml_media_content_for_media_usage', array( $this, 'add_package_strings_content' ), 10, 2 );
|
||||
}
|
||||
/**
|
||||
* @param IWPML_PB_Media_Update[] $updaters
|
||||
*
|
||||
* @return IWPML_PB_Media_Update[]
|
||||
*/
|
||||
public function add_media_updater( $updaters ) {
|
||||
if ( ! array_key_exists( $this->page_builder_slug, $updaters ) ) {
|
||||
$updaters[ $this->page_builder_slug ] = $this->media_update_factory->create();
|
||||
}
|
||||
return $updaters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param WP_Post $post
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_package_strings_content( $content, $post ) {
|
||||
$packages = apply_filters( 'wpml_st_get_post_string_packages', array(), $post->ID );
|
||||
|
||||
/** @var WPML_Package[] $packages */
|
||||
foreach ( $packages as $package ) {
|
||||
$strings = $package->get_package_strings();
|
||||
|
||||
foreach ( $strings as $string ) {
|
||||
$content .= PHP_EOL . $string->value;
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Translate {
|
||||
|
||||
/** @var WPML_Translation_Element_Factory $element_factory */
|
||||
private $element_factory;
|
||||
|
||||
/** @var WPML_Media_Image_Translate $image_translate */
|
||||
protected $image_translate;
|
||||
|
||||
/** @var array $translated_urls */
|
||||
protected $translated_urls = array();
|
||||
|
||||
/** @var (WP_Post|null)[] $translated_posts */
|
||||
protected $translated_posts = array();
|
||||
|
||||
/** @var array $translated_ids */
|
||||
private $translated_ids = array();
|
||||
|
||||
public function __construct(
|
||||
WPML_Translation_Element_Factory $element_factory,
|
||||
WPML_Media_Image_Translate $image_translate
|
||||
) {
|
||||
$this->element_factory = $element_factory;
|
||||
$this->image_translate = $image_translate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $lang
|
||||
* @param string $source_lang
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function translate_image_url( $url, $lang, $source_lang ) {
|
||||
$key = $url . $lang . $source_lang;
|
||||
|
||||
if ( ! array_key_exists( $key, $this->translated_urls ) ) {
|
||||
$this->translated_urls[ $key ] = $url;
|
||||
|
||||
$attachment_id = $this->image_translate->get_attachment_id_by_url( $url, $source_lang );
|
||||
|
||||
if ( $attachment_id ) {
|
||||
$this->add_translated_id( $attachment_id );
|
||||
$translated_url = $this->image_translate->get_translated_image_by_url( $url, $source_lang, $lang );
|
||||
$this->translated_urls[ $key ] = $url;
|
||||
|
||||
if ( $translated_url ) {
|
||||
$this->translated_urls[ $key ] = $translated_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->translated_urls[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $lang
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function translate_id( $id, $lang ) {
|
||||
if ( (int) $id < 1 ) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
$this->add_translated_id( $id );
|
||||
$translated_attachment = $this->get_translated_attachment( $id, $lang );
|
||||
|
||||
if ( isset( $translated_attachment->ID ) ) {
|
||||
return $translated_attachment->ID;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $lang
|
||||
*
|
||||
* @return WP_Post|null
|
||||
*/
|
||||
private function get_translated_attachment( $id, $lang ) {
|
||||
$key = $id . $lang;
|
||||
|
||||
if ( ! array_key_exists( $key, $this->translated_posts ) ) {
|
||||
$this->translated_posts[ $key ] = null;
|
||||
$element = $this->element_factory->create_post( $id );
|
||||
$translation = $element->get_translation( $lang );
|
||||
|
||||
if ( $translation ) {
|
||||
$this->translated_posts[ $key ] = $translation->get_wp_object();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->translated_posts[ $key ];
|
||||
}
|
||||
|
||||
/** @param int $id */
|
||||
private function add_translated_id( $id ) {
|
||||
if ( ! in_array( $id, $this->translated_ids, true ) ) {
|
||||
$this->translated_ids[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
public function reset_translated_ids() {
|
||||
$this->translated_ids = array();
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function get_translated_ids() {
|
||||
return $this->translated_ids;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Usage {
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Translate $media_translate */
|
||||
private $media_translate;
|
||||
|
||||
/** @var WPML_Media_Usage_Factory $media_usage_factory */
|
||||
private $media_usage_factory;
|
||||
|
||||
public function __construct(
|
||||
WPML_Page_Builders_Media_Translate $media_translate,
|
||||
WPML_Media_Usage_Factory $media_usage_factory
|
||||
) {
|
||||
$this->media_translate = $media_translate;
|
||||
$this->media_usage_factory = $media_usage_factory;
|
||||
}
|
||||
|
||||
/** @param int $post_id */
|
||||
public function update( $post_id ) {
|
||||
$media_ids = $this->media_translate->get_translated_ids();
|
||||
|
||||
foreach ( $media_ids as $media_id ) {
|
||||
$this->media_usage_factory->create( $media_id )->add_post( $post_id );
|
||||
}
|
||||
|
||||
$this->media_translate->reset_translated_ids();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Update_Media implements IWPML_PB_Media_Update {
|
||||
|
||||
/** @var WPML_Page_Builders_Update $pb_update */
|
||||
private $pb_update;
|
||||
|
||||
/** @var WPML_Translation_Element_Factory $element_factory */
|
||||
private $element_factory;
|
||||
|
||||
/** @var IWPML_PB_Media_Nodes_Iterator $node_iterator */
|
||||
protected $node_iterator;
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Usage|null $media_usage */
|
||||
protected $media_usage;
|
||||
|
||||
public function __construct(
|
||||
WPML_Page_Builders_Update $pb_update,
|
||||
WPML_Translation_Element_Factory $element_factory,
|
||||
IWPML_PB_Media_Nodes_Iterator $node_iterator,
|
||||
WPML_Page_Builders_Media_Usage $media_usage = null
|
||||
) {
|
||||
$this->pb_update = $pb_update;
|
||||
$this->element_factory = $element_factory;
|
||||
$this->node_iterator = $node_iterator;
|
||||
$this->media_usage = $media_usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public function translate( $post ) {
|
||||
$element = $this->element_factory->create_post( $post->ID );
|
||||
$source_element = $element->get_source_element();
|
||||
|
||||
if ( ! $source_element ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lang = $element->get_language_code();
|
||||
$source_lang = $source_element->get_language_code();
|
||||
$original_post_id = $source_element->get_id();
|
||||
$converted_data = $this->pb_update->get_converted_data( $post->ID );
|
||||
|
||||
if ( ! $converted_data ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$converted_data = $this->node_iterator->translate( $converted_data, $lang, $source_lang );
|
||||
|
||||
$this->pb_update->save( $post->ID, $original_post_id, $converted_data );
|
||||
|
||||
if ( $this->media_usage ) {
|
||||
$this->media_usage->update( $original_post_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_PB_Media_Nodes_Iterator {
|
||||
|
||||
public function translate( $data, $lang, $source_lang );
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_PB_Media_Update_Factory {
|
||||
|
||||
/** @return IWPML_PB_Media_Update */
|
||||
public function create();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_PB_Media_Update {
|
||||
|
||||
/**
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public function translate( $post );
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Shortcodes_Update_Factory implements IWPML_PB_Media_Update_Factory {
|
||||
|
||||
/** @var WPML_PB_Config_Import_Shortcode WPML_PB_Config_Import_Shortcode */
|
||||
private $page_builder_config_import;
|
||||
|
||||
/** @var WPML_Translation_Element_Factory|null $element_factory */
|
||||
private $element_factory;
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Translate|null $media_translate */
|
||||
private $media_translate;
|
||||
|
||||
public function __construct( WPML_PB_Config_Import_Shortcode $page_builder_config_import ) {
|
||||
$this->page_builder_config_import = $page_builder_config_import;
|
||||
}
|
||||
|
||||
public function create() {
|
||||
$media_shortcodes = new WPML_Page_Builders_Media_Shortcodes(
|
||||
$this->get_media_translate(),
|
||||
$this->page_builder_config_import->get_media_settings()
|
||||
);
|
||||
|
||||
return new WPML_Page_Builders_Media_Shortcodes_Update(
|
||||
$this->get_element_factory(),
|
||||
$media_shortcodes,
|
||||
new WPML_Page_Builders_Media_Usage( $this->get_media_translate(), new WPML_Media_Usage_Factory() )
|
||||
);
|
||||
}
|
||||
|
||||
/** @return WPML_Translation_Element_Factory */
|
||||
private function get_element_factory() {
|
||||
global $sitepress;
|
||||
|
||||
if ( ! $this->element_factory ) {
|
||||
$this->element_factory = new WPML_Translation_Element_Factory( $sitepress );
|
||||
}
|
||||
|
||||
return $this->element_factory;
|
||||
}
|
||||
|
||||
/** @return WPML_Page_Builders_Media_Translate */
|
||||
private function get_media_translate() {
|
||||
global $sitepress;
|
||||
|
||||
if ( ! $this->media_translate ) {
|
||||
$this->media_translate = new WPML_Page_Builders_Media_Translate(
|
||||
$this->get_element_factory(),
|
||||
new WPML_Media_Image_Translate( $sitepress, new WPML_Media_Attachment_By_URL_Factory() )
|
||||
);
|
||||
}
|
||||
|
||||
return $this->media_translate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Shortcodes_Update implements IWPML_PB_Media_Update {
|
||||
|
||||
/** @var WPML_Translation_Element_Factory $element_factory */
|
||||
private $element_factory;
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Shortcodes $media_shortcodes*/
|
||||
private $media_shortcodes;
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Usage $media_usage */
|
||||
private $media_usage;
|
||||
|
||||
public function __construct(
|
||||
WPML_Translation_Element_Factory $element_factory,
|
||||
WPML_Page_Builders_Media_Shortcodes $media_shortcodes,
|
||||
WPML_Page_Builders_Media_Usage $media_usage
|
||||
) {
|
||||
$this->element_factory = $element_factory;
|
||||
$this->media_shortcodes = $media_shortcodes;
|
||||
$this->media_usage = $media_usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public function translate( $post ) {
|
||||
if ( ! $this->media_shortcodes->has_media_shortcode( $post->post_content ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$element = $this->element_factory->create_post( $post->ID );
|
||||
|
||||
if ( ! $element->get_source_language_code() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post->post_content = $this->media_shortcodes->set_target_lang( $element->get_language_code() )
|
||||
->set_source_lang( $element->get_source_language_code() )
|
||||
->translate( $post->post_content );
|
||||
|
||||
$this->media_usage->update( $element->get_source_element()->get_id() );
|
||||
|
||||
/**
|
||||
* The function wp_update_post() can modify post tag.
|
||||
* The code below sends tags by IDs to prevent this.
|
||||
*
|
||||
* @see wpmlcore-5947
|
||||
* @see https://core.trac.wordpress.org/ticket/45121
|
||||
*/
|
||||
$tag_ids = wp_get_post_tags( $post->ID, array( 'fields' => 'ids' ) );
|
||||
$postarr = array(
|
||||
'ID' => $post->ID,
|
||||
'post_content' => $post->post_content,
|
||||
'tags_input' => $tag_ids,
|
||||
);
|
||||
kses_remove_filters();
|
||||
wpml_update_escaped_post( $postarr );
|
||||
kses_init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
class WPML_Page_Builders_Media_Shortcodes {
|
||||
|
||||
const TYPE_URL = 'media-url';
|
||||
const TYPE_IDS = 'media-ids';
|
||||
|
||||
/** @var WPML_Page_Builders_Media_Translate $media_translate */
|
||||
private $media_translate;
|
||||
|
||||
/** @var string $target_lang */
|
||||
private $target_lang;
|
||||
|
||||
/** @var string $source_lang */
|
||||
private $source_lang;
|
||||
|
||||
/** @var array $config */
|
||||
private $config;
|
||||
|
||||
public function __construct( WPML_Page_Builders_Media_Translate $media_translate, array $config ) {
|
||||
$this->media_translate = $media_translate;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function translate( $content ) {
|
||||
foreach ( $this->config as $shortcode ) {
|
||||
$shortcode = $this->sanitize_shortcode( $shortcode );
|
||||
$tag_name = isset( $shortcode['tag']['name'] ) ? $shortcode['tag']['name'] : '';
|
||||
|
||||
if ( ! empty( $shortcode['attributes'] ) ) {
|
||||
$content = $this->translate_attributes( $content, $tag_name, $shortcode['attributes'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $shortcode['content'] ) ) {
|
||||
$content = $this->translate_content( $content, $tag_name, $shortcode['content'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_media_shortcode( $content ) {
|
||||
if ( false === strpos( $content, '[' ) ) {
|
||||
return false;
|
||||
};
|
||||
|
||||
foreach ( $this->config as $shortcode ) {
|
||||
$shortcode = $this->sanitize_shortcode( $shortcode );
|
||||
$tag_name = isset( $shortcode['tag']['name'] ) ? $shortcode['tag']['name'] : '';
|
||||
|
||||
if ( $tag_name && false !== strpos( $content, '[' . $tag_name ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $shortcode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function sanitize_shortcode( array $shortcode ) {
|
||||
$defaults = array(
|
||||
'attributes' => null,
|
||||
);
|
||||
|
||||
return array_merge( $defaults, $shortcode );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param string $tag
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function translate_attributes( $content, $tag, array $attributes ) {
|
||||
foreach ( $attributes as $attribute => $data ) {
|
||||
$pattern = '/(\[' . $tag . '(?: [^\]]* | )' . $attribute . '=(?:"|\'))([^"\']*)/';
|
||||
$type = isset( $data['type'] ) ? $data['type'] : '';
|
||||
$content = preg_replace_callback( $pattern, array( $this, $this->get_callback( $type ) ), $content );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param string $tag
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function translate_content( $content, $tag, array $data ) {
|
||||
$pattern = '/(\[(?:' . $tag . ')[^\]]*\])([^\[]+)/';
|
||||
$type = isset( $data['type'] ) ? $data['type'] : '';
|
||||
return preg_replace_callback( $pattern, array( $this, $this->get_callback( $type ) ), $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_callback( $type ) {
|
||||
if ( self::TYPE_URL === $type ) {
|
||||
return 'replace_url_callback';
|
||||
}
|
||||
|
||||
return 'replace_ids_callback';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $matches
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replace_url_callback( array $matches ) {
|
||||
$translated_url = $this->media_translate->translate_image_url( $matches[2], $this->target_lang, $this->source_lang );
|
||||
|
||||
return $matches[1] . $translated_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $matches
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replace_ids_callback( array $matches ) {
|
||||
$ids = explode( ',', $matches[2] );
|
||||
|
||||
foreach ( $ids as &$id ) {
|
||||
$id = $this->media_translate->translate_id( (int) $id, $this->target_lang );
|
||||
}
|
||||
|
||||
return $matches[1] . implode( ',', $ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $target_lang
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_target_lang( $target_lang ) {
|
||||
$this->target_lang = $target_lang;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_lang
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function set_source_lang( $source_lang ) {
|
||||
$this->source_lang = $source_lang;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user