first commit
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPML_Nav_Menu_Actions
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Nav_Menu_Actions extends WPML_Full_Translation_API {
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
* @param wpdb $wpdb
|
||||
* @param WPML_Post_Translation $post_translations
|
||||
* @param WPML_Term_Translation $term_translations
|
||||
*/
|
||||
public function __construct( &$sitepress, &$wpdb, &$post_translations, &$term_translations ) {
|
||||
parent::__construct( $sitepress, $wpdb, $post_translations, $term_translations );
|
||||
add_action( 'wp_delete_nav_menu', array( $this, 'wp_delete_nav_menu' ) );
|
||||
add_action( 'wp_create_nav_menu', array( $this, 'wp_update_nav_menu' ), 10, 2 );
|
||||
add_action( 'wp_update_nav_menu', array( $this, 'wp_update_nav_menu' ), 10, 2 );
|
||||
add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 3 );
|
||||
add_action( 'delete_post', array( $this, 'wp_delete_nav_menu_item' ) );
|
||||
add_filter( 'pre_update_option_theme_mods_' . get_option( 'stylesheet' ), array( $this, 'pre_update_theme_mods_theme' ) );
|
||||
if ( is_admin() ) {
|
||||
add_filter( 'theme_mod_nav_menu_locations', array( $this, 'theme_mod_nav_menu_locations' ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function wp_delete_nav_menu( $id ) {
|
||||
$menu_id_tt = $this->wpdb->get_var(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT term_taxonomy_id FROM {$this->wpdb->term_taxonomy} WHERE term_id=%d AND taxonomy='nav_menu'",
|
||||
$id
|
||||
)
|
||||
);
|
||||
|
||||
$update_args = array(
|
||||
'element_id' => $menu_id_tt,
|
||||
'element_type' => 'tax_nav_menu',
|
||||
'context' => 'tax',
|
||||
);
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'before_delete' ) ) );
|
||||
|
||||
$q = "DELETE FROM {$this->wpdb->prefix}icl_translations WHERE element_id=%d AND element_type='tax_nav_menu' LIMIT 1";
|
||||
$q_prepared = $this->wpdb->prepare( $q, $menu_id_tt );
|
||||
$this->wpdb->query( $q_prepared );
|
||||
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'after_delete' ) ) );
|
||||
}
|
||||
|
||||
function wp_update_nav_menu( $menu_id, $menu_data = null ) {
|
||||
if ( $menu_data ) {
|
||||
$trid = $this->get_trid_from_post_data();
|
||||
$language_code = $this->get_save_lang( $menu_id );
|
||||
$menu_id_tt = $this->wpdb->get_var(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT term_taxonomy_id FROM {$this->wpdb->term_taxonomy} WHERE term_id=%d AND taxonomy='nav_menu' LIMIT 1",
|
||||
$menu_id
|
||||
)
|
||||
);
|
||||
$this->term_translations->reload();
|
||||
$this->sitepress->set_element_language_details( $menu_id_tt, 'tax_nav_menu', $trid, $language_code );
|
||||
}
|
||||
}
|
||||
|
||||
function wp_update_nav_menu_item( $menu_id, $menu_item_db_id, $args ) {
|
||||
$menu_lang = $this->term_translations->lang_code_by_termid( $menu_id );
|
||||
$trid = $this->post_translations->get_element_trid( $menu_item_db_id );
|
||||
if ( array_key_exists( 'menu-item-type', $args )
|
||||
&& ( $args['menu-item-type'] === 'post_type' || $args['menu-item-type'] === 'taxonomy' )
|
||||
&& array_key_exists( 'menu-item-object-id', $args )
|
||||
&& $menu_id > 0
|
||||
) {
|
||||
$language_code_item = $args['menu-item-type'] === 'post_type'
|
||||
? $this->post_translations->get_element_lang_code( $args['menu-item-object-id'] )
|
||||
: $this->term_translations->lang_code_by_termid( $args['menu-item-object-id'] );
|
||||
$language_code_item = $language_code_item ? $language_code_item : $this->sitepress->get_current_language();
|
||||
if ( $language_code_item !== $menu_lang ) {
|
||||
wp_remove_object_terms( (int) $menu_item_db_id, (int) $menu_id, 'nav_menu' );
|
||||
}
|
||||
}
|
||||
|
||||
$language_code = isset( $language_code_item ) && $language_code_item
|
||||
? $language_code_item : ( $menu_lang ? $menu_lang : $this->sitepress->get_current_language() );
|
||||
$this->sitepress->set_element_language_details( $menu_item_db_id, 'post_nav_menu_item', $trid, $language_code );
|
||||
}
|
||||
|
||||
public function wp_delete_nav_menu_item( $menu_item_id ) {
|
||||
$post = get_post( $menu_item_id );
|
||||
if ( ! empty( $post->post_type ) && $post->post_type == 'nav_menu_item' ) {
|
||||
|
||||
$update_args = array(
|
||||
'element_id' => $menu_item_id,
|
||||
'element_type' => 'post_nav_menu_item',
|
||||
'context' => 'post',
|
||||
);
|
||||
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'before_delete' ) ) );
|
||||
|
||||
$q = "DELETE FROM {$this->wpdb->prefix}icl_translations WHERE element_id=%d AND element_type='post_nav_menu_item' LIMIT 1";
|
||||
$q_prepared = $this->wpdb->prepare( $q, $menu_item_id );
|
||||
$this->wpdb->query( $q_prepared );
|
||||
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'after_delete' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function pre_update_theme_mods_theme( $val ) {
|
||||
$default_language = $this->sitepress->get_default_language();
|
||||
$current_language = $this->sitepress->get_current_language();
|
||||
|
||||
if ( isset( $val['nav_menu_locations'] )
|
||||
&& filter_input( INPUT_GET, 'action' ) === 'delete'
|
||||
&& $current_language !== $default_language
|
||||
) {
|
||||
$val['nav_menu_locations'] = get_theme_mod( 'nav_menu_locations' );
|
||||
}
|
||||
|
||||
if ( isset( $val['nav_menu_locations'] ) ) {
|
||||
foreach ( (array) $val['nav_menu_locations'] as $k => $v ) {
|
||||
if ( ! $v && $current_language !== $default_language ) {
|
||||
$tl = get_theme_mod( 'nav_menu_locations' );
|
||||
if ( isset( $tl[ $k ] ) ) {
|
||||
$val['nav_menu_locations'][ $k ] = $tl[ $k ];
|
||||
}
|
||||
} else {
|
||||
$val['nav_menu_locations'][ $k ] = icl_object_id(
|
||||
$val['nav_menu_locations'][ $k ],
|
||||
'nav_menu',
|
||||
true,
|
||||
$default_language
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
public function theme_mod_nav_menu_locations( $theme_locations ) {
|
||||
if ( is_admin() && (bool) $theme_locations === true ) {
|
||||
$current_lang = $this->sitepress->get_current_language();
|
||||
foreach ( (array) $theme_locations as $location => $menu_id ) {
|
||||
$translated_menu_id = $this->term_translations->term_id_in( $menu_id, $current_lang );
|
||||
if ( $translated_menu_id ) {
|
||||
$theme_locations[ $location ] = $translated_menu_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $theme_locations;
|
||||
}
|
||||
|
||||
private function get_save_lang( $menu_id ) {
|
||||
$language_code = isset( $_POST['icl_nav_menu_language'] )
|
||||
? $_POST['icl_nav_menu_language'] : $this->term_translations->lang_code_by_termid( $menu_id );
|
||||
$language_code = $language_code ? $language_code : $this->sitepress->get_current_language();
|
||||
|
||||
return $language_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int|mixed|null|string
|
||||
*/
|
||||
private function get_trid_from_post_data() {
|
||||
$trid = null;
|
||||
if ( ! empty( $_POST['icl_translation_of'] ) && $_POST['icl_translation_of'] !== 'none' ) {
|
||||
$trid = $this->sitepress->get_element_trid( $_POST['icl_translation_of'], 'tax_nav_menu' );
|
||||
|
||||
return $trid;
|
||||
} elseif ( isset( $_POST['icl_nav_menu_trid'] ) ) {
|
||||
$trid = ( (int) $_POST['icl_nav_menu_trid'] );
|
||||
|
||||
return $trid;
|
||||
}
|
||||
|
||||
return $trid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
class WPML_Frontend_Tax_Filters {
|
||||
|
||||
public function __construct() {
|
||||
add_filter( 'taxonomy_template', array( $this, 'slug_template' ) );
|
||||
add_filter( 'category_template', array( $this, 'slug_template' ) );
|
||||
add_filter( 'tag_template', array( $this, 'slug_template' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust template (taxonomy-)$taxonomy-$term.php for translated term slugs and IDs
|
||||
*
|
||||
* @since 3.1
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @return string The template filename if found.
|
||||
*/
|
||||
function slug_template( $template ) {
|
||||
global $sitepress;
|
||||
|
||||
$term = $this->get_queried_tax_term();
|
||||
|
||||
if ( $term === false || ! is_taxonomy_translated( $term->taxonomy ) ) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
$templates = array();
|
||||
|
||||
$has_filter = remove_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1 );
|
||||
|
||||
$current_language = $sitepress->get_current_language();
|
||||
$default_language = $sitepress->get_default_language();
|
||||
|
||||
$templates = $this->add_term_templates( $term, $current_language, $templates );
|
||||
$templates = $this->add_original_term_templates( $term, $default_language, $current_language, $templates );
|
||||
|
||||
if ( ! in_array( $term->taxonomy, array( 'category', 'post_tag' ), true ) ) {
|
||||
$templates[] = 'taxonomy-' . $current_language . '.php';
|
||||
$templates[] = 'taxonomy.php';
|
||||
}
|
||||
|
||||
if ( $has_filter ) {
|
||||
add_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1, 1 );
|
||||
}
|
||||
|
||||
$new_template = locate_template( array_unique( $templates ) );
|
||||
$template = $new_template ? $new_template : $template;
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
private function get_template_prefix( $taxonomy ) {
|
||||
|
||||
$prefix = in_array( $taxonomy, array( 'category', 'post_tag' ), true ) ? '' : 'taxonomy-';
|
||||
$prefix .= $taxonomy == 'post_tag' ? 'tag' : $taxonomy;
|
||||
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
private function add_term_templates( $term, $current_language, $templates ) {
|
||||
$prefix = $this->get_template_prefix( $term->taxonomy );
|
||||
$templates[] = "$prefix-{$current_language}-{$term->slug}.php";
|
||||
$templates[] = "$prefix-{$current_language}-{$term->term_id}.php";
|
||||
$templates[] = "$prefix-{$current_language}.php";
|
||||
$templates[] = "$prefix-{$term->slug}.php";
|
||||
$templates[] = "$prefix-{$term->term_id}.php";
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
private function add_original_term_templates( $term, $default_language, $current_language, $templates ) {
|
||||
$taxonomy = $term->taxonomy;
|
||||
$prefix = $this->get_template_prefix( $taxonomy );
|
||||
$original_term_id = icl_object_id( $term->term_id, $taxonomy, true, $default_language );
|
||||
$original_term = get_term_by( 'id', $original_term_id, $taxonomy );
|
||||
if ( $original_term ) {
|
||||
$templates[] = "$prefix-{$current_language}-{$original_term->slug}.php";
|
||||
$templates[] = "$prefix-{$current_language}-{$original_term_id}.php";
|
||||
$templates[] = "$prefix-{$original_term->slug}.php";
|
||||
$templates[] = "$prefix-{$original_term_id}.php";
|
||||
$templates[] = "$prefix-{$current_language}.php";
|
||||
$templates[] = "$prefix.php";
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
private function get_queried_tax_term() {
|
||||
global $wp_query;
|
||||
/** @var WP_Query $wp_query */
|
||||
$term = $wp_query->get_queried_object();
|
||||
$res = false;
|
||||
|
||||
if ( (bool) $term === true && isset( $term->taxonomy ) && $term->taxonomy ) {
|
||||
$res = $term;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* WPML_Term_Filters class file.
|
||||
*
|
||||
* @package WPML\Core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPML_Term_Filters
|
||||
*/
|
||||
class WPML_Term_Filters extends WPML_WPDB_And_SP_User {
|
||||
|
||||
/**
|
||||
* Init class.
|
||||
*/
|
||||
public function init() {
|
||||
$taxonomies = get_taxonomies();
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
$this->add_hooks_to_translated_taxonomy( $taxonomy );
|
||||
}
|
||||
|
||||
add_action( 'registered_taxonomy', [ $this, 'registered_taxonomy' ], 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param array|string $object_type Object type or array of object types.
|
||||
* @param array $taxonomy_object Array of taxonomy registration arguments.
|
||||
*/
|
||||
public function registered_taxonomy( $taxonomy, $object_type, $taxonomy_object ) {
|
||||
$this->add_hooks_to_translated_taxonomy( $taxonomy );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
*/
|
||||
private function add_hooks_to_translated_taxonomy( $taxonomy ) {
|
||||
if ( is_taxonomy_translated( $taxonomy ) ) {
|
||||
add_filter( "pre_option_{$taxonomy}_children", [ $this, 'pre_option_tax_children' ], 10, 0 );
|
||||
add_action( "create_{$taxonomy}", [ $this, 'update_tax_children_option' ], 10, 0 );
|
||||
add_action( "edit_{$taxonomy}", [ $this, 'update_tax_children_option' ], 10, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
public function update_tax_children_option( $taxonomy_input = false ) {
|
||||
global $wpml_language_resolution, $wp_taxonomies;
|
||||
|
||||
$language_codes = $wpml_language_resolution->get_active_language_codes();
|
||||
$language_codes[] = 'all';
|
||||
$taxonomy = str_replace( array( 'create_', 'edit_' ), '', current_action() );
|
||||
$taxonomy = isset( $wp_taxonomies[ $taxonomy ] ) ? $taxonomy : $taxonomy_input;
|
||||
foreach ( $language_codes as $lang ) {
|
||||
$tax_children = $this->get_tax_hier_array( $taxonomy, $lang );
|
||||
$option_key = "{$taxonomy}_children_{$lang}";
|
||||
update_option( $option_key, $tax_children );
|
||||
}
|
||||
}
|
||||
|
||||
public function pre_option_tax_children() {
|
||||
$taxonomy = str_replace( array( 'pre_option_', '_children' ), '', current_filter() );
|
||||
$lang = $this->sitepress->get_current_language();
|
||||
$option_key = "{$taxonomy}_children_{$lang}";
|
||||
$tax_children = get_option( $option_key, false );
|
||||
if ( $tax_children === false ) {
|
||||
$tax_children = $this->get_tax_hier_array( $taxonomy, $lang );
|
||||
update_option( $option_key, $tax_children );
|
||||
}
|
||||
|
||||
return ! empty( $tax_children ) ? $tax_children : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy
|
||||
* @param string $lang_code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tax_hier_array( $taxonomy, $lang_code ) {
|
||||
$hierarchy = array();
|
||||
|
||||
if ( $lang_code != 'all' ) {
|
||||
$terms = $this->wpdb->get_results(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT term_id, parent
|
||||
FROM {$this->wpdb->term_taxonomy} tt
|
||||
JOIN {$this->wpdb->prefix}icl_translations iclt
|
||||
ON tt.term_taxonomy_id = iclt.element_id
|
||||
WHERE tt.parent > 0
|
||||
AND tt.taxonomy = %s
|
||||
AND iclt.language_code = %s
|
||||
AND iclt.element_type = %s
|
||||
ORDER BY term_id",
|
||||
$taxonomy,
|
||||
$lang_code,
|
||||
'tax_' . $taxonomy
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$terms = $this->wpdb->get_results(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT term_id, parent
|
||||
FROM {$this->wpdb->term_taxonomy} tt
|
||||
WHERE tt.parent > 0
|
||||
AND tt.taxonomy = %s
|
||||
ORDER BY term_id",
|
||||
$taxonomy
|
||||
)
|
||||
);
|
||||
}
|
||||
foreach ( $terms as $term ) {
|
||||
if ( $term->parent > 0 ) {
|
||||
$hierarchy[ $term->parent ] = isset( $hierarchy[ $term->parent ] )
|
||||
? $hierarchy[ $term->parent ] : array();
|
||||
$hierarchy[ $term->parent ][] = $term->term_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $hierarchy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPML_Term_Hierarchy_Duplication
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Term_Hierarchy_Duplication extends WPML_WPDB_And_SP_User {
|
||||
|
||||
public function duplicates_require_sync( $post_ids, $duplicates_only = true ) {
|
||||
$taxonomies = $this->sitepress->get_translatable_taxonomies( true );
|
||||
foreach ( $taxonomies as $key => $tax ) {
|
||||
if ( ! is_taxonomy_hierarchical( $tax ) ) {
|
||||
unset( $taxonomies[ $key ] );
|
||||
}
|
||||
}
|
||||
if ( (bool) $post_ids === true ) {
|
||||
$need_sync_taxonomies = $duplicates_only === true
|
||||
? $this->get_need_sync_new_dupl( $post_ids, $taxonomies )
|
||||
: $this->get_need_sync_all_terms( $taxonomies, $post_ids );
|
||||
} else {
|
||||
$need_sync_taxonomies = array();
|
||||
}
|
||||
|
||||
return array_values( array_unique( $need_sync_taxonomies ) );
|
||||
}
|
||||
|
||||
private function get_need_sync_new_dupl( $duplicated_ids, $taxonomies ) {
|
||||
$new_terms = $this->get_new_terms_just_duplicated( $duplicated_ids, $taxonomies );
|
||||
$affected_taxonomies = array();
|
||||
foreach ( $new_terms as $term ) {
|
||||
$affected_taxonomies[] = $term->taxonomy;
|
||||
}
|
||||
$affected_taxonomies = array_unique( $affected_taxonomies );
|
||||
$hierarchy_sync_helper = wpml_get_hierarchy_sync_helper( 'term' );
|
||||
|
||||
$unsynced_terms = $hierarchy_sync_helper->get_unsynced_elements(
|
||||
$affected_taxonomies,
|
||||
$this->sitepress->get_default_language()
|
||||
);
|
||||
|
||||
foreach ( $new_terms as $key => $new_term ) {
|
||||
$sync = true;
|
||||
foreach ( $unsynced_terms as $term_unsynced ) {
|
||||
if ( $term_unsynced->translated_id == $new_term->term_taxonomy_id ) {
|
||||
$sync = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( $sync === true ) {
|
||||
unset( $new_terms[ $key ] );
|
||||
}
|
||||
}
|
||||
$need_sync_taxonomies = array();
|
||||
foreach ( $new_terms as $term ) {
|
||||
$need_sync_taxonomies[] = $term->taxonomy;
|
||||
}
|
||||
|
||||
return $need_sync_taxonomies;
|
||||
}
|
||||
|
||||
private function get_need_sync_all_terms( $translated_taxonomies, $post_ids ) {
|
||||
$hierarchy_sync_helper = wpml_get_hierarchy_sync_helper( 'term' );
|
||||
$post_ids_in = wpml_prepare_in( (array) $post_ids, '%d' );
|
||||
$taxonomies_in = wpml_prepare_in( $translated_taxonomies );
|
||||
|
||||
$this->wpdb->get_col(
|
||||
"SELECT DISTINCT tt.taxonomy
|
||||
FROM {$this->wpdb->term_taxonomy} tt
|
||||
JOIN {$this->wpdb->term_relationships} tr
|
||||
ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
||||
WHERE tr.object_id IN ({$post_ids_in}) AND tt.taxonomy IN ({$taxonomies_in})"
|
||||
);
|
||||
|
||||
foreach ( $translated_taxonomies as $key => $tax ) {
|
||||
$unsynced_terms = $hierarchy_sync_helper->get_unsynced_elements(
|
||||
$tax,
|
||||
$this->sitepress->get_default_language()
|
||||
);
|
||||
if ( (bool) $unsynced_terms === false ) {
|
||||
unset( $translated_taxonomies[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $translated_taxonomies;
|
||||
}
|
||||
|
||||
private function get_new_terms_just_duplicated( $duplicate_ids, $taxonomies ) {
|
||||
if ( (bool) $duplicate_ids === false || (bool) $taxonomies === false ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$duplicate_ids_in = wpml_prepare_in( $duplicate_ids, '%d' );
|
||||
$taxonomies_in = wpml_prepare_in( $taxonomies );
|
||||
$terms = $this->wpdb->get_results(
|
||||
"SELECT tt.term_taxonomy_id, tt.taxonomy
|
||||
FROM {$this->wpdb->term_taxonomy} tt
|
||||
JOIN {$this->wpdb->term_relationships} tr
|
||||
ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
||||
JOIN {$this->wpdb->postmeta} pm
|
||||
ON pm.post_id = tr.object_id
|
||||
JOIN {$this->wpdb->terms} t_duplicate
|
||||
ON t_duplicate.term_id = tt.term_id
|
||||
JOIN {$this->wpdb->terms} t_original
|
||||
ON t_original.name = t_duplicate.name
|
||||
JOIN {$this->wpdb->term_taxonomy} tt_master
|
||||
ON tt_master.term_id = t_original.term_id
|
||||
JOIN {$this->wpdb->term_relationships} tr_master
|
||||
ON tt_master.term_taxonomy_id = tr_master.term_taxonomy_id
|
||||
LEFT JOIN {$this->wpdb->term_relationships} tr_other
|
||||
ON tt.term_taxonomy_id = tr_other.term_taxonomy_id
|
||||
AND tr_other.object_id != tr.object_id
|
||||
AND tr_other.object_id NOT IN ({$duplicate_ids_in})
|
||||
LEFT JOIN {$this->wpdb->postmeta} pm_other
|
||||
ON pm_other.post_id = tr_other.object_id
|
||||
AND NOT (pm_other.meta_key = '_icl_lang_duplicate_of'
|
||||
AND pm_other.meta_value IN ({$duplicate_ids_in}))
|
||||
WHERE pm.meta_key = '_icl_lang_duplicate_of'
|
||||
AND tr_other.object_id IS NULL
|
||||
AND pm_other.post_id IS NULL
|
||||
AND pm.meta_value IN ({$duplicate_ids_in})
|
||||
AND tr_master.object_id IN ({$duplicate_ids_in})
|
||||
AND tt.taxonomy IN ({$taxonomies_in})"
|
||||
);
|
||||
|
||||
return $terms;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
class WPML_Term_Hierarchy_Sync extends WPML_Hierarchy_Sync {
|
||||
|
||||
protected $element_id_column = 'term_taxonomy_id';
|
||||
protected $parent_id_column = 'parent';
|
||||
protected $parent_element_id_column = 'term_id';
|
||||
protected $element_type_column = 'taxonomy';
|
||||
protected $element_type_prefix = 'tax_';
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb
|
||||
*/
|
||||
public function __construct( &$wpdb ) {
|
||||
parent::__construct( $wpdb );
|
||||
|
||||
$this->elements_table = $wpdb->term_taxonomy;
|
||||
}
|
||||
|
||||
public function is_need_sync( $taxonomy, $ref_lang = false ) {
|
||||
|
||||
return (bool) $this->get_unsynced_elements( $taxonomy, $ref_lang );
|
||||
}
|
||||
|
||||
public function sync_element_hierarchy( $element_types, $ref_lang = false ) {
|
||||
/** @var WPML_Term_Filters $wpml_term_filters_general */
|
||||
global $wpml_term_filters_general;
|
||||
|
||||
parent::sync_element_hierarchy( $element_types, $ref_lang );
|
||||
do_action( 'wpml_sync_term_hierarchy_done' );
|
||||
|
||||
$element_types = (array) $element_types;
|
||||
|
||||
foreach ( $element_types as $taxonomy ) {
|
||||
$wpml_term_filters_general->update_tax_children_option( $taxonomy );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $element_type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_hierarchical( $element_type ) {
|
||||
return is_taxonomy_hierarchical( $element_type );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
use WPML\FP\Fns;
|
||||
|
||||
class WPML_Term_Translation_Utils extends WPML_SP_User {
|
||||
|
||||
/**
|
||||
* Duplicates all terms, that exist in the given target language,
|
||||
* from the original post to the translation in that language.
|
||||
*
|
||||
* @param int $original_post_id
|
||||
* @param string $lang
|
||||
*/
|
||||
function sync_terms( $original_post_id, $lang ) {
|
||||
$this->synchronize_terms( $original_post_id, $lang, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates all terms on the original post to its translation in the given target language.
|
||||
* Missing terms are created with the same name as their originals.
|
||||
*
|
||||
* @param int $original_post_id
|
||||
* @param string $lang
|
||||
*/
|
||||
function duplicate_terms( $original_post_id, $lang ) {
|
||||
$this->synchronize_terms( $original_post_id, $lang, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $original_post_id
|
||||
* @param string $lang
|
||||
* @param bool $duplicate sets whether missing terms should be created by duplicating the original term
|
||||
*/
|
||||
private function synchronize_terms( $original_post_id, $lang, $duplicate ) {
|
||||
global $wpml_post_translations;
|
||||
|
||||
$returnTrue = Fns::always( true );
|
||||
add_filter( 'wpml_disable_term_adjust_id', $returnTrue );
|
||||
|
||||
$wpml_post_translations->reload();
|
||||
$translated_post_id = $wpml_post_translations->element_id_in( $original_post_id, $lang );
|
||||
if ( (bool) $translated_post_id === true ) {
|
||||
$taxonomies = get_post_taxonomies( $original_post_id );
|
||||
|
||||
foreach ( $taxonomies as $tax ) {
|
||||
$terms_on_original = wp_get_object_terms( $original_post_id, $tax );
|
||||
|
||||
if ( ! $this->sitepress->is_translated_taxonomy( $tax ) ) {
|
||||
if ( $this->sitepress->get_setting( 'sync_post_taxonomies' ) ) {
|
||||
// Taxonomy is not translated so we can just copy from the original
|
||||
foreach ( $terms_on_original as $key => $term ) {
|
||||
$terms_on_original[ $key ] = $term->term_id;
|
||||
}
|
||||
wp_set_object_terms( $translated_post_id, $terms_on_original, $tax );
|
||||
}
|
||||
} else {
|
||||
|
||||
/** @var int[] $translated_terms translated term_ids */
|
||||
$translated_terms = $this->get_translated_term_ids( $terms_on_original, $lang, $tax, $duplicate );
|
||||
wp_set_object_terms( $translated_post_id, $translated_terms, $tax );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove_filter( 'wpml_disable_term_adjust_id', $returnTrue );
|
||||
clean_object_term_cache( $original_post_id, get_post_type( $original_post_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $terms
|
||||
* @param string $lang
|
||||
* @param string $taxonomy
|
||||
* @param bool $duplicate sets whether missing terms should be created by duplicating the original term
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_translated_term_ids( $terms, $lang, $taxonomy, $duplicate ) {
|
||||
/** @var WPML_Term_Translation $wpml_term_translations */
|
||||
global $wpml_term_translations;
|
||||
|
||||
$term_utils = new WPML_Terms_Translations();
|
||||
$wpml_term_translations->reload();
|
||||
$translated_terms = array();
|
||||
foreach ( $terms as $orig_term ) {
|
||||
$translated_id = (int) $wpml_term_translations->term_id_in( $orig_term->term_id, $lang );
|
||||
if ( ! $translated_id && $duplicate ) {
|
||||
$translation = $term_utils->create_automatic_translation(
|
||||
array(
|
||||
'lang_code' => $lang,
|
||||
'taxonomy' => $taxonomy,
|
||||
'trid' => $wpml_term_translations->get_element_trid( $orig_term->term_taxonomy_id ),
|
||||
'source_language' => $wpml_term_translations->get_element_lang_code(
|
||||
$orig_term->term_taxonomy_id
|
||||
),
|
||||
)
|
||||
);
|
||||
$translated_id = isset( $translation['term_id'] ) ? $translation['term_id'] : false;
|
||||
}
|
||||
if ( $translated_id ) {
|
||||
$translated_terms[] = $translated_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $translated_terms;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @since 3.2
|
||||
*
|
||||
* Class WPML_Term_Translation
|
||||
*
|
||||
* Provides APIs for translating taxonomy terms
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Term_Translation extends WPML_Element_Translation {
|
||||
|
||||
/** @var array|null */
|
||||
protected $ttids;
|
||||
|
||||
/** @var array|null */
|
||||
protected $term_ids;
|
||||
|
||||
public function reload() {
|
||||
parent::reload();
|
||||
$this->term_ids = null;
|
||||
$this->ttids = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_id
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function lang_code_by_termid( $term_id ) {
|
||||
|
||||
return $this->get_element_lang_code( $this->adjust_ttid_for_term_id( $term_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts term_id into term_taxonomy_id
|
||||
*
|
||||
* @param int $term_id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function adjust_ttid_for_term_id( $term_id ) {
|
||||
$this->maybe_warm_term_id_cache();
|
||||
|
||||
return $term_id && isset( $this->ttids[ $term_id ] ) ? end( $this->ttids[ $term_id ] ) : $term_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts term_taxonomy_id into term_id
|
||||
*
|
||||
* @param int $ttid term_taxonomy_id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function adjust_term_id_for_ttid( $ttid ) {
|
||||
$this->maybe_warm_term_id_cache();
|
||||
|
||||
return $ttid && isset( $this->term_ids[ $ttid ] ) ? $this->term_ids[ $ttid ] : $ttid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_id
|
||||
* @param string $lang_code
|
||||
* @param bool|false $original_fallback if true will return the the input term_id in case no translation is found
|
||||
*
|
||||
* @return null|int
|
||||
*/
|
||||
public function term_id_in( $term_id, $lang_code, $original_fallback = false ) {
|
||||
|
||||
return $this->adjust_term_id_for_ttid(
|
||||
$this->element_id_in( $this->adjust_ttid_for_term_id( $term_id ), $lang_code, $original_fallback )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the trid for a given term_id and taxonomy or null on failure
|
||||
*
|
||||
* @param int $term_id term_id of a term
|
||||
* @param string $taxonomy taxonomy of the term
|
||||
*
|
||||
* @return null|int
|
||||
*/
|
||||
public function trid_from_tax_and_id( $term_id, $taxonomy ) {
|
||||
$this->maybe_warm_term_id_cache();
|
||||
$ttid = $term_id && isset( $this->ttids[ $term_id ][ $taxonomy ] )
|
||||
? $this->ttids[ $term_id ][ $taxonomy ] : $term_id;
|
||||
|
||||
return $this->get_element_trid( $ttid );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all post types to which a taxonomy is linked.
|
||||
*
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.2.3
|
||||
*/
|
||||
public function get_taxonomy_post_types( $taxonomy ) {
|
||||
return WPML_WP_Taxonomy::get_linked_post_types( $taxonomy );
|
||||
}
|
||||
|
||||
protected function get_element_join() {
|
||||
|
||||
return "FROM {$this->wpdb->prefix}icl_translations wpml_translations
|
||||
JOIN {$this->wpdb->term_taxonomy} tax
|
||||
ON wpml_translations.element_id = tax.term_taxonomy_id
|
||||
AND wpml_translations.element_type = CONCAT('tax_', tax.taxonomy)";
|
||||
}
|
||||
|
||||
protected function get_type_prefix() {
|
||||
return 'tax_';
|
||||
}
|
||||
|
||||
private function maybe_warm_term_id_cache() {
|
||||
|
||||
if ( ! isset( $this->ttids ) || ! isset( $this->term_ids ) ) {
|
||||
|
||||
$data = $this->wpdb->get_results(
|
||||
' SELECT wpml_translations.element_id, tax.term_id, tax.taxonomy
|
||||
' . $this->get_element_join() . "
|
||||
JOIN {$this->wpdb->terms} terms
|
||||
ON terms.term_id = tax.term_id
|
||||
WHERE tax.term_id != tax.term_taxonomy_id",
|
||||
ARRAY_A
|
||||
);
|
||||
$this->term_ids = array();
|
||||
$this->ttids = array();
|
||||
foreach ( $data as $row ) {
|
||||
$this->ttids[ $row['term_id'] ] = isset( $this->ttids[ $row['term_id'] ] )
|
||||
? $this->ttids[ $row['term_id'] ] : array();
|
||||
$this->ttids[ $row['term_id'] ][ $row['taxonomy'] ] = $row['element_id'];
|
||||
$this->term_ids[ $row['element_id'] ] = $row['term_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $term
|
||||
* @param string $slug
|
||||
* @param string $taxonomy
|
||||
* @param string $lang_code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_unique_term_slug( $term, $slug, $taxonomy, $lang_code ) {
|
||||
if ( '' === trim( $slug ) ) {
|
||||
$slug = sanitize_title( $term );
|
||||
}
|
||||
return WPML_Terms_Translations::term_unique_slug( $slug, $taxonomy, $lang_code );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public static function getGlobalInstance() {
|
||||
global $wpml_term_translations, $wpdb;
|
||||
|
||||
if ( ! isset( $wpml_term_translations ) ) {
|
||||
$wpml_term_translations = new WPML_Term_Translation( $wpdb );
|
||||
}
|
||||
|
||||
return $wpml_term_translations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,719 @@
|
||||
<?php
|
||||
require_once dirname( __FILE__ ) . '/wpml-update-term-action.class.php';
|
||||
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Logic;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
/**
|
||||
* @since 3.1.8
|
||||
*
|
||||
* Class WPML_Terms_Translations
|
||||
*
|
||||
* This class holds some basic functionality for translating taxonomy terms.
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Terms_Translations {
|
||||
|
||||
/**
|
||||
* @param array<string|\WP_Term> $terms
|
||||
* @param string[]|string $taxonomies This is only used by the WP core AJAX call that fetches the preview
|
||||
* auto-complete for flat taxonomy term adding
|
||||
*
|
||||
* @return array<\WP_Term>
|
||||
* @deprecated since Version 3.1.8.3
|
||||
*/
|
||||
public static function get_terms_filter( $terms, $taxonomies ) {
|
||||
global $wpdb, $sitepress;
|
||||
|
||||
$lang = $sitepress->get_current_language();
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
|
||||
if ( $sitepress->is_translated_taxonomy( $taxonomy ) ) {
|
||||
|
||||
$element_type = 'tax_' . $taxonomy;
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT wptt.term_id
|
||||
FROM {$wpdb->prefix}icl_translations AS iclt
|
||||
JOIN {$wpdb->prefix}term_taxonomy AS wptt
|
||||
ON iclt.element_id = wptt.term_taxonomy_id
|
||||
WHERE language_code=%s AND element_type = %s",
|
||||
$lang,
|
||||
$element_type
|
||||
);
|
||||
|
||||
$element_ids_array = $wpdb->get_col( $query );
|
||||
|
||||
foreach ( $terms as $key => $term ) {
|
||||
if ( ! is_object( $term ) ) {
|
||||
$term = get_term_by( 'name', $term, $taxonomy );
|
||||
}
|
||||
if ( $term && isset( $term->taxonomy )
|
||||
&& $term->taxonomy === $taxonomy
|
||||
&& ! in_array( $term->term_id, $element_ids_array ) ) {
|
||||
unset( $terms[ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
* @param string $taxonomy
|
||||
* @param string $lang
|
||||
* Creates a unique slug for a given term, using a scheme
|
||||
* encoding the language code in the slug.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function term_unique_slug( $slug, $taxonomy, $lang ) {
|
||||
global $sitepress;
|
||||
|
||||
$default_language = $sitepress->get_default_language();
|
||||
|
||||
if ( $lang !== $default_language && self::term_slug_exists( $slug, $taxonomy ) ) {
|
||||
$slug .= '-' . $lang;
|
||||
}
|
||||
|
||||
$i = 2;
|
||||
$suffix = '-' . $i;
|
||||
|
||||
if ( self::term_slug_exists( $slug, $taxonomy ) ) {
|
||||
while ( self::term_slug_exists( $slug . $suffix, $taxonomy ) ) {
|
||||
$i ++;
|
||||
$suffix = '-' . $i;
|
||||
}
|
||||
$slug .= $suffix;
|
||||
}
|
||||
|
||||
return $slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
* @param bool $taxonomy
|
||||
* If $taxonomy is given, then slug existence is checked only for the specific taxonomy.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function term_slug_exists( $slug, $taxonomy = false ) {
|
||||
global $wpdb;
|
||||
|
||||
$existing_term_prepared_query = $wpdb->prepare(
|
||||
"SELECT t.term_id
|
||||
FROM {$wpdb->terms} t
|
||||
JOIN {$wpdb->term_taxonomy} tt
|
||||
ON t.term_id = tt.term_id
|
||||
WHERE t.slug = %s
|
||||
AND tt.taxonomy = %s
|
||||
LIMIT 1",
|
||||
$slug,
|
||||
$taxonomy
|
||||
);
|
||||
$term_id = $wpdb->get_var( $existing_term_prepared_query );
|
||||
|
||||
return (bool) $term_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function provides an action hook only used by WCML.
|
||||
* It will be removed in the future and should not be implemented in new spots.
|
||||
*
|
||||
* @deprecated deprecated since version 3.1.8.3
|
||||
*
|
||||
* @param string $taxonomy The identifier of the taxonomy the translation was just saved to.
|
||||
* @param array $translated_term The associative array holding term taxonomy id and term id,
|
||||
* as returned by wp_insert_term or wp_update_term.
|
||||
*/
|
||||
public static function icl_save_term_translation_action( $taxonomy, $translated_term ) {
|
||||
global $wpdb, $sitepress;
|
||||
|
||||
if ( is_taxonomy_hierarchical( $taxonomy ) ) {
|
||||
$term_taxonomy_id = $translated_term['term_taxonomy_id'];
|
||||
|
||||
$original_ttid = $sitepress->get_original_element_id( $term_taxonomy_id, 'tax_' . $taxonomy );
|
||||
|
||||
$original_tax_sql = "SELECT * FROM {$wpdb->term_taxonomy} WHERE taxonomy=%s AND term_taxonomy_id = %d";
|
||||
$original_tax_prepared = $wpdb->prepare( $original_tax_sql, array( $taxonomy, $original_ttid ) );
|
||||
$original_tax = $wpdb->get_row( $original_tax_prepared );
|
||||
|
||||
do_action( 'icl_save_term_translation', $original_tax, $translated_term );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a hidden div, containing the list of allowed terms for a post type in each language.
|
||||
* This is used to only display the correct categories and tags in the quick-edit fields of the post table.
|
||||
*
|
||||
* @param string $column_name
|
||||
* @param string|string[]|\WP_Post $post_type
|
||||
*/
|
||||
public static function quick_edit_terms_removal( $column_name, $post_type ) {
|
||||
global $sitepress, $wpdb;
|
||||
if ( $column_name == 'icl_translations' ) {
|
||||
$taxonomies = array_filter(
|
||||
get_object_taxonomies( $post_type ),
|
||||
array(
|
||||
$sitepress,
|
||||
'is_translated_taxonomy',
|
||||
)
|
||||
);
|
||||
$terms_by_language_and_taxonomy = array();
|
||||
|
||||
if ( ! empty( $taxonomies ) ) {
|
||||
$res = $wpdb->get_results(
|
||||
" SELECT language_code, taxonomy, term_id FROM {$wpdb->term_taxonomy} tt
|
||||
JOIN {$wpdb->prefix}icl_translations wpml_translations
|
||||
ON wpml_translations.element_id = tt.term_taxonomy_id
|
||||
AND wpml_translations.element_type = CONCAT('tax_', tt.taxonomy)
|
||||
WHERE tt.taxonomy IN (" . wpml_prepare_in( $taxonomies ) . ' )'
|
||||
);
|
||||
} else {
|
||||
$res = array();
|
||||
}
|
||||
|
||||
foreach ( $res as $term ) {
|
||||
$lang = $term->language_code;
|
||||
$tax = $term->taxonomy;
|
||||
$terms_by_language_and_taxonomy[ $lang ] = isset( $terms_by_language_and_taxonomy[ $lang ] ) ? $terms_by_language_and_taxonomy[ $lang ] : array();
|
||||
$terms_by_language_and_taxonomy[ $lang ][ $tax ] = isset( $terms_by_language_and_taxonomy[ $lang ][ $tax ] ) ? $terms_by_language_and_taxonomy[ $lang ][ $tax ] : array();
|
||||
$terms_by_language_and_taxonomy[ $lang ][ $tax ][] = $term->term_id;
|
||||
}
|
||||
$terms_json = wp_json_encode( $terms_by_language_and_taxonomy );
|
||||
$output = '<div id="icl-terms-by-lang" style="display: none;">' . wp_kses_post( $terms_json ) . '</div>';
|
||||
echo $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new term from an argument array.
|
||||
*
|
||||
* @param array $args
|
||||
* @return array|bool
|
||||
* Returns either an array containing the term_id and term_taxonomy_id of the term resulting from this database
|
||||
* write or false on error.
|
||||
*/
|
||||
public static function create_new_term( $args ) {
|
||||
global $wpdb, $sitepress;
|
||||
|
||||
/** @var string $taxonomy */
|
||||
$taxonomy = false;
|
||||
/** @var string $lang_code */
|
||||
$lang_code = false;
|
||||
/**
|
||||
* Sets whether translations of posts are to be updated by the newly created term,
|
||||
* should they be missing a translation still.
|
||||
* During debug actions designed to synchronise post and term languages this should not be set to true,
|
||||
* doing so introduces the possibility of removing terms from posts before switching
|
||||
* them with their translation in the correct language.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
$sync = false;
|
||||
|
||||
extract( $args, EXTR_OVERWRITE );
|
||||
|
||||
require_once dirname( __FILE__ ) . '/wpml-update-term-action.class.php';
|
||||
|
||||
$new_term_action = new WPML_Update_Term_Action( $wpdb, $sitepress, $args );
|
||||
$new_term = $new_term_action->execute();
|
||||
|
||||
if ( $sync && $new_term && $taxonomy && $lang_code ) {
|
||||
self::sync_taxonomy_terms_language( $taxonomy );
|
||||
}
|
||||
|
||||
return $new_term;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $args
|
||||
* Creates an automatic translation of a term, the name of which is set as "original" . @ "lang_code" and the slug of which is set as "original_slug" . - . "lang_code".
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function create_automatic_translation( $args ) {
|
||||
global $sitepress;
|
||||
|
||||
$term = false;
|
||||
$lang_code = false;
|
||||
$taxonomy = false;
|
||||
$original_id = false;
|
||||
$original_tax_id = false;
|
||||
$trid = false;
|
||||
$original_term = false;
|
||||
$update_translations = false;
|
||||
$source_language = null;
|
||||
|
||||
extract( $args, EXTR_OVERWRITE );
|
||||
|
||||
if ( $trid && ! $original_id ) {
|
||||
$original_tax_id = $sitepress->get_original_element_id_by_trid( $trid );
|
||||
$original_term = get_term_by( 'term_taxonomy_id', $original_tax_id, $taxonomy, OBJECT, 'no' );
|
||||
}
|
||||
|
||||
if ( $original_id && ! $original_tax_id ) {
|
||||
$original_term = get_term( $original_id, $taxonomy, OBJECT, 'no' );
|
||||
if ( isset( $original_term['term_taxonomy_id'] ) ) {
|
||||
$original_tax_id = $original_term['term_taxonomy_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $trid ) {
|
||||
$trid = $sitepress->get_element_trid( $original_tax_id, 'tax_' . $taxonomy );
|
||||
}
|
||||
|
||||
if ( ! $source_language ) {
|
||||
$source_language = $sitepress->get_source_language_by_trid( $trid );
|
||||
}
|
||||
|
||||
$existing_translations = $sitepress->get_element_translations( $trid, 'tax_' . $taxonomy );
|
||||
if ( $lang_code && isset( $existing_translations[ $lang_code ] ) ) {
|
||||
$new_translated_term = false;
|
||||
} else {
|
||||
|
||||
if ( ! $original_term ) {
|
||||
if ( $original_id ) {
|
||||
$original_term = get_term( $original_id, $taxonomy, OBJECT, 'no' );
|
||||
} elseif ( $original_tax_id ) {
|
||||
$original_term = get_term_by( 'term_taxonomy_id', $original_tax_id, $taxonomy, OBJECT, 'no' );
|
||||
}
|
||||
}
|
||||
$translated_slug = false;
|
||||
|
||||
if ( ! $term && isset( $original_term->name ) ) {
|
||||
$term = $original_term->name;
|
||||
|
||||
/**
|
||||
* @deprecated use 'wpml_duplicate_generic_string' instead, with the same arguments
|
||||
*/
|
||||
$term = apply_filters(
|
||||
'icl_duplicate_generic_string',
|
||||
$term,
|
||||
$lang_code,
|
||||
array(
|
||||
'context' => 'taxonomy',
|
||||
'attribute' => $taxonomy,
|
||||
'key' => $original_term->term_id,
|
||||
)
|
||||
);
|
||||
|
||||
$term = apply_filters(
|
||||
'wpml_duplicate_generic_string',
|
||||
$term,
|
||||
$lang_code,
|
||||
array(
|
||||
'context' => 'taxonomy',
|
||||
'attribute' => $taxonomy,
|
||||
'key' => $original_term->term_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
if ( isset( $original_term->slug ) ) {
|
||||
$translated_slug = $original_term->slug;
|
||||
|
||||
/**
|
||||
* @deprecated use 'wpml_duplicate_generic_string' instead, with the same arguments
|
||||
*/
|
||||
$translated_slug = apply_filters(
|
||||
'icl_duplicate_generic_string',
|
||||
$translated_slug,
|
||||
$lang_code,
|
||||
array(
|
||||
'context' => 'taxonomy_slug',
|
||||
'attribute' => $taxonomy,
|
||||
'key' => $original_term->term_id,
|
||||
)
|
||||
);
|
||||
|
||||
$translated_slug = apply_filters(
|
||||
'wpml_duplicate_generic_string',
|
||||
$translated_slug,
|
||||
$lang_code,
|
||||
array(
|
||||
'context' => 'taxonomy_slug',
|
||||
'attribute' => $taxonomy,
|
||||
'key' => $original_term->term_id,
|
||||
)
|
||||
);
|
||||
|
||||
$translated_slug = self::term_unique_slug( $translated_slug, $taxonomy, $lang_code );
|
||||
}
|
||||
$new_translated_term = false;
|
||||
if ( $term ) {
|
||||
$new_term_args = array(
|
||||
'term' => $term,
|
||||
'slug' => $translated_slug,
|
||||
'taxonomy' => $taxonomy,
|
||||
'lang_code' => $lang_code,
|
||||
'original_tax_id' => $original_tax_id,
|
||||
'update_translations' => $update_translations,
|
||||
'trid' => $trid,
|
||||
'source_language' => $source_language,
|
||||
);
|
||||
|
||||
$new_translated_term = self::create_new_term( $new_term_args );
|
||||
}
|
||||
}
|
||||
|
||||
return $new_translated_term;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* Sets all taxonomy terms to the correct language on each post, having at least one term from the taxonomy.
|
||||
*/
|
||||
public static function sync_taxonomy_terms_language( $taxonomy ) {
|
||||
$all_posts_in_taxonomy = get_posts( array( 'tax_query' => array( 'taxonomy' => $taxonomy ) ) );
|
||||
|
||||
foreach ( $all_posts_in_taxonomy as $post_in_taxonomy ) {
|
||||
self::sync_post_and_taxonomy_terms_language( $post_in_taxonomy->ID, $taxonomy );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id
|
||||
*
|
||||
* Sets all taxonomy terms ot the correct language for a given post.
|
||||
*/
|
||||
public static function sync_post_terms_language( $post_id ) {
|
||||
|
||||
$taxonomies = get_taxonomies();
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
self::sync_post_and_taxonomy_terms_language( $post_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id
|
||||
* @param string $taxonomy
|
||||
* Synchronizes a posts taxonomy term's languages with the posts language for all translations of the post.
|
||||
*/
|
||||
public static function sync_post_and_taxonomy_terms_language( $post_id, $taxonomy ) {
|
||||
global $sitepress;
|
||||
|
||||
$post = get_post( $post_id );
|
||||
$post_type = $post->post_type;
|
||||
$post_trid = $sitepress->get_element_trid( $post_id, 'post_' . $post_type );
|
||||
$post_translations = $sitepress->get_element_translations( $post_trid, 'post_' . $post_type );
|
||||
$terms_from_original_post = wp_get_post_terms( $post_id, $taxonomy );
|
||||
|
||||
$is_original = true;
|
||||
|
||||
if ( $sitepress->get_original_element_id( $post_id, 'post_' . $post_type ) != $post_id ) {
|
||||
$is_original = false;
|
||||
}
|
||||
|
||||
foreach ( $post_translations as $post_language => $translated_post ) {
|
||||
|
||||
$translated_post_id = $translated_post->element_id;
|
||||
if ( ! $translated_post_id ) {
|
||||
continue;
|
||||
}
|
||||
$terms_from_translated_post = wp_get_post_terms( $translated_post_id, $taxonomy );
|
||||
if ( $is_original ) {
|
||||
$duplicates = $sitepress->get_duplicates( $post_id );
|
||||
if ( in_array( $translated_post_id, $duplicates ) ) {
|
||||
$terms = array_merge( $terms_from_original_post, $terms_from_translated_post );
|
||||
} else {
|
||||
$terms = $terms_from_translated_post;
|
||||
}
|
||||
} else {
|
||||
$terms = $terms_from_translated_post;
|
||||
}
|
||||
foreach ( (array) $terms as $term ) {
|
||||
$term_original_tax_id = $term->term_taxonomy_id;
|
||||
$original_term_language_object = $sitepress->get_element_language_details( $term_original_tax_id, 'tax_' . $term->taxonomy );
|
||||
if ( $original_term_language_object && isset( $original_term_language_object->language_code ) ) {
|
||||
$original_term_language = $original_term_language_object->language_code;
|
||||
} else {
|
||||
$original_term_language = $post_language;
|
||||
}
|
||||
if ( $original_term_language != $post_language ) {
|
||||
$term_trid = $sitepress->get_element_trid( $term_original_tax_id, 'tax_' . $term->taxonomy );
|
||||
$translated_terms = $sitepress->get_element_translations( $term_trid, 'tax_' . $term->taxonomy, false, false, true );
|
||||
|
||||
$term_id = $term->term_id;
|
||||
wp_remove_object_terms( $translated_post_id, (int) $term_id, $taxonomy );
|
||||
|
||||
if ( isset( $translated_terms[ $post_language ] ) ) {
|
||||
$term_in_correct_language = $translated_terms[ $post_language ];
|
||||
wp_set_post_terms( $translated_post_id, array( (int) $term_in_correct_language->term_id ), $taxonomy, true );
|
||||
}
|
||||
|
||||
if ( isset( $term->term_taxonomy_id ) ) {
|
||||
wp_update_term_count( $term->term_taxonomy_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
wp_update_term_count( $term_original_tax_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id Object ID.
|
||||
* @param array $terms An array of object terms.
|
||||
* @param array $tt_ids An array of term taxonomy IDs.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param bool $append Whether to append new terms to the old terms.
|
||||
* @param array $old_tt_ids Old array of term taxonomy IDs.
|
||||
*/
|
||||
public static function set_object_terms_action( $post_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
|
||||
global $sitepress;
|
||||
|
||||
// TODO: [WPML 3.2] We have a better way to check if the post is an external type (e.g. Package).
|
||||
if ( get_post( $post_id ) ) {
|
||||
self::set_tags_in_proper_language( $post_id, $tt_ids, $taxonomy, $old_tt_ids );
|
||||
|
||||
if ( $sitepress->get_setting( 'sync_post_taxonomies' ) ) {
|
||||
$term_actions_helper = $sitepress->get_term_actions_helper();
|
||||
$term_actions_helper->added_term_relationships( $post_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id Object ID.
|
||||
* @param array $tt_ids An array of term taxonomy IDs.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param array $old_tt_ids Old array of term taxonomy IDs.
|
||||
* @param bool $isBulkEdit
|
||||
*/
|
||||
private static function set_tags_in_proper_language( $post_id, $tt_ids, $taxonomy, $old_tt_ids ) {
|
||||
$isEditAction = isset( $_POST['action'] ) && ( 'editpost' === $_POST['action'] || 'inline-save' === $_POST['action'] );
|
||||
$isBulkEdit = isset( $_REQUEST['bulk_edit'] );
|
||||
if ( $isEditAction || $isBulkEdit ) {
|
||||
$tt_ids = array_map( 'intval', $tt_ids );
|
||||
$tt_ids = array_diff( $tt_ids, $old_tt_ids );
|
||||
self::quick_edited_post_terms( $post_id, $taxonomy, $tt_ids );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id
|
||||
* @param string $taxonomy
|
||||
* @param array $changed_ttids
|
||||
*
|
||||
* Running this function will remove certain issues arising out of bulk adding of terms to posts of various languages.
|
||||
* This case can result in situations in which the WP Core functionality adds a term to a post, before the language assignment
|
||||
* operations of WPML are triggered. This leads to states in which terms can be assigned to a post even though their language
|
||||
* differs from that of the post.
|
||||
* This function behaves between hierarchical and flat taxonomies. Hierarchical terms from the wrong taxonomy are simply removed
|
||||
* from the post. Flat terms are added with the same name but in the correct language.
|
||||
* For flat terms this implies either the use of the existing term or the creation of a new one.
|
||||
* This function uses wpdb queries instead of the WordPress API, it is therefore save to be run out of
|
||||
* any language setting.
|
||||
*/
|
||||
public static function quick_edited_post_terms( $post_id, $taxonomy, $newlyAddedTermIds ) {
|
||||
global $wpdb, $sitepress, $wpml_post_translations;
|
||||
|
||||
$postLang = $wpml_post_translations->get_element_lang_code( $post_id ) ?: Obj::prop( 'icl_post_language', $_POST );
|
||||
if ( ! $sitepress->is_translated_taxonomy( $taxonomy ) || ! ( $postLang ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = "SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE language_code = %s AND element_type = %s";
|
||||
$termIdsInPostLang = $wpdb->get_col( $wpdb->prepare( $sql, $postLang, 'tax_' . $taxonomy ) );
|
||||
$termIdsInPostLang = Fns::map( \WPML\FP\Cast::toInt(), $termIdsInPostLang );
|
||||
|
||||
$newlyCreatedTermIds = [];
|
||||
|
||||
$isInPostLang = Lst::includes( Fns::__, $termIdsInPostLang );
|
||||
|
||||
if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
|
||||
$getTermInPostLang = Obj::prop( 'idInPostLang' );
|
||||
|
||||
$createTermIfNotExists = Logic::ifElse( $getTermInPostLang, Fns::identity(), self::createTerm( $taxonomy, $postLang ) );
|
||||
|
||||
$updateOrDeleteTermInPost = Logic::ifElse(
|
||||
$getTermInPostLang,
|
||||
self::updatePostTaxonomy( $post_id ),
|
||||
pipe( Obj::prop( 'id' ), self::deletePostTaxonomy( $post_id ) )
|
||||
);
|
||||
|
||||
$newlyCreatedTermIds = \wpml_collect( $newlyAddedTermIds )
|
||||
->reject( $isInPostLang )
|
||||
->map( self::appendTermName() )
|
||||
->map( self::appendTermIdCounterpartInPostLang( $termIdsInPostLang, $taxonomy ) )
|
||||
->map( $createTermIfNotExists )
|
||||
->map( $updateOrDeleteTermInPost )
|
||||
->all();
|
||||
} else {
|
||||
\wpml_collect( $newlyAddedTermIds )->reject( $isInPostLang )->each( self::deletePostTaxonomy( $post_id ) );
|
||||
}
|
||||
|
||||
// Update term counts manually here, since using sql, will not trigger the updating of term counts automatically.
|
||||
wp_update_term_count( array_merge( $newlyAddedTermIds, $newlyCreatedTermIds ), $taxonomy );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $postId
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
private static function deletePostTaxonomy( $postId ) {
|
||||
return function ( $termId ) use ( $postId ) {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->delete(
|
||||
$wpdb->term_relationships,
|
||||
[
|
||||
'object_id' => $postId,
|
||||
'term_taxonomy_id' => $termId,
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Closure
|
||||
*/
|
||||
private static function appendTermName() {
|
||||
return function ( $termId ) {
|
||||
global $wpdb;
|
||||
|
||||
$sql = "SELECT t.name FROM {$wpdb->terms} AS t JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.term_taxonomy_id=%d";
|
||||
$termName = $wpdb->get_var( $wpdb->prepare( $sql, $termId ) );
|
||||
|
||||
return [ 'id' => $termId, 'name' => $termName ];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $termIdsInPostLang
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
private static function appendTermIdCounterpartInPostLang( $termIdsInPostLang, $taxonomy ) {
|
||||
return function ( $termData ) use ( $termIdsInPostLang, $taxonomy ) {
|
||||
global $wpdb;
|
||||
$idInPostLang = false;
|
||||
|
||||
if ( count( $termIdsInPostLang ) ) {
|
||||
$in = wpml_prepare_in( $termIdsInPostLang, '%d' );
|
||||
|
||||
$sql = "
|
||||
SELECT tt.term_taxonomy_id FROM {$wpdb->terms} AS t
|
||||
JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
|
||||
WHERE t.name=%s AND tt.taxonomy=%s AND tt.term_taxonomy_id IN ({$in})
|
||||
";
|
||||
|
||||
$idInPostLang = $wpdb->get_var( $wpdb->prepare( $sql, $termData['name'], $taxonomy ) );
|
||||
}
|
||||
|
||||
return Obj::assoc( 'idInPostLang', $idInPostLang, $termData );
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy
|
||||
* @param string $postLang
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
private static function createTerm( $taxonomy, $postLang ) {
|
||||
return function ( $termData ) use ( $taxonomy, $postLang ) {
|
||||
global $sitepress;
|
||||
|
||||
$idInCorrectId = false;
|
||||
$newTerm = wp_insert_term( $termData['name'], $taxonomy, [ 'slug' => self::term_unique_slug( sanitize_title( $termData['name'] ), $taxonomy, $postLang ) ] );
|
||||
if ( isset( $newTerm['term_taxonomy_id'] ) ) {
|
||||
$idInCorrectId = $newTerm['term_taxonomy_id'];
|
||||
$trid = $sitepress->get_element_trid( $termData['id'], 'tax_' . $taxonomy );
|
||||
$sitepress->set_element_language_details( $idInCorrectId, 'tax_' . $taxonomy, $trid, $postLang );
|
||||
}
|
||||
|
||||
return Obj::assoc( 'idInPostLang', $idInCorrectId, $termData );
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $postId
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
private static function updatePostTaxonomy( $postId ) {
|
||||
return function ( $termData ) use ( $postId ) {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->term_relationships,
|
||||
[ 'term_taxonomy_id' => $termData['idInPostLang'] ],
|
||||
[
|
||||
'object_id' => $postId,
|
||||
'term_taxonomy_id' => $termData['id'],
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all terms, that have a language suffix on them.
|
||||
* This is used by troubleshooting functionality.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all_terms_with_language_suffix() {
|
||||
global $wpdb;
|
||||
|
||||
$lang_codes = $wpdb->get_col( "SELECT code FROM {$wpdb->prefix}icl_languages" );
|
||||
|
||||
/*
|
||||
Build the expression to find all potential candidates for renaming.
|
||||
* These must have the part "<space>@lang_code<space>" in them.
|
||||
*/
|
||||
|
||||
$where_parts = array();
|
||||
|
||||
foreach ( $lang_codes as $key => $code ) {
|
||||
$where_parts[ $key ] = "t.name LIKE '" . '% @' . esc_sql( $code ) . "%'";
|
||||
}
|
||||
|
||||
$where = '(' . join( ' OR ', $where_parts ) . ')';
|
||||
|
||||
$terms_with_suffix = $wpdb->get_results( "SELECT t.name, t.term_id, tt.taxonomy FROM {$wpdb->terms} AS t JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE {$where}" );
|
||||
|
||||
$terms = array();
|
||||
|
||||
foreach ( $terms_with_suffix as $term ) {
|
||||
|
||||
if ( $term->name == WPML_Troubleshooting_Terms_Menu::strip_language_suffix( $term->name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$term_id = $term->term_id;
|
||||
|
||||
$term_taxonomy_label = $term->taxonomy;
|
||||
|
||||
$taxonomy = get_taxonomy( $term->taxonomy );
|
||||
|
||||
if ( $taxonomy && isset( $taxonomy->labels ) && isset( $taxonomy->labels->name ) ) {
|
||||
$term_taxonomy_label = $taxonomy->labels->name;
|
||||
}
|
||||
|
||||
if ( isset( $terms[ $term_id ] ) && isset( $terms[ $term_id ]['taxonomies'] ) ) {
|
||||
if ( ! in_array( $term_taxonomy_label, $terms[ $term_id ]['taxonomies'] ) ) {
|
||||
$terms[ $term_id ]['taxonomies'][] = $term_taxonomy_label;
|
||||
}
|
||||
} else {
|
||||
$terms[ $term_id ] = array(
|
||||
'name' => $term->name,
|
||||
'taxonomies' => array( $term_taxonomy_label ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $terms;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPML_Update_Term_Action
|
||||
*
|
||||
* This class holds the functionality for creating or editing a taxonomy term.
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Update_Term_Action extends WPML_WPDB_And_SP_User {
|
||||
|
||||
/**
|
||||
* TRUE if this object represents valid data for the update or creation of a term, false otherwise.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_valid = true;
|
||||
/**
|
||||
* TRUE if this object represents term update action, false if it represents a term creation action.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_update;
|
||||
/**
|
||||
* Argument array containing arguments in a format that can and is used as input to \wp_update_term or
|
||||
* \wp_insert_term
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $wp_new_term_args = array();
|
||||
/**
|
||||
* The taxonomy in which this action takes place.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $taxonomy;
|
||||
/**
|
||||
* Trid value in the icl_translations table to which this action is to be written.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $trid;
|
||||
/**
|
||||
* Language of the term that is to result from this action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $lang_code;
|
||||
/**
|
||||
* Source language of the term that is to result from this action.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $source_lang_code = null;
|
||||
/**
|
||||
* Array holding translations of the term created by this object prior to it's creation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $existing_translations = array();
|
||||
/**
|
||||
* The term id of the term to be updated or resulting from this action.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $term_id;
|
||||
/**
|
||||
* This only gets set for update actions. In this case the new slug has to be compared with the old slug,
|
||||
* to decide whether any slug name sanitation has to happen.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $old_slug;
|
||||
|
||||
/**
|
||||
* @param wpdb $wpdb
|
||||
* @param SitePress $sitepress
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct( &$wpdb, &$sitepress, $args ) {
|
||||
parent::__construct( $wpdb, $sitepress );
|
||||
/**
|
||||
* Actual name of the term. Same as the name input argument to \wp_update_term or \wp_insert_term
|
||||
*
|
||||
* @var string|bool
|
||||
*/
|
||||
$term = false;
|
||||
$slug = '';
|
||||
$taxonomy = '';
|
||||
/** @var string $lang_code */
|
||||
$lang_code = '';
|
||||
$trid = null;
|
||||
/** @var int|bool $original_tax_id */
|
||||
$original_tax_id = false;
|
||||
/**
|
||||
* Taxonomy_term_id of the parent element
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
$parent = 0;
|
||||
$description = false;
|
||||
$term_group = false;
|
||||
$source_language = null;
|
||||
|
||||
extract( $args, EXTR_OVERWRITE );
|
||||
|
||||
// We cannot create a term unless we at least know its name
|
||||
if ( (string) $term !== '' && $taxonomy ) {
|
||||
$this->wp_new_term_args['name'] = $term;
|
||||
$this->taxonomy = $taxonomy;
|
||||
} else {
|
||||
$this->is_valid = false;
|
||||
|
||||
return;
|
||||
}
|
||||
if ( $parent ) {
|
||||
$this->wp_new_term_args['parent'] = $parent;
|
||||
}
|
||||
if ( $description ) {
|
||||
$this->wp_new_term_args['description'] = $description;
|
||||
}
|
||||
if ( $term_group ) {
|
||||
$this->wp_new_term_args['term_group'] = $term_group;
|
||||
}
|
||||
$this->wp_new_term_args['term_group'] = $term_group;
|
||||
$this->is_valid = $this->set_language_information( $trid, $original_tax_id, $lang_code, $source_language );
|
||||
$this->set_action_type();
|
||||
if ( ! $this->is_update || ( $this->is_update && $slug != $this->old_slug && ! empty( $slug ) ) ) {
|
||||
if ( trim( $slug ) == '' ) {
|
||||
$slug = sanitize_title( $term );
|
||||
}
|
||||
$slug = WPML_Terms_Translations::term_unique_slug( $slug, $taxonomy, $lang_code );
|
||||
$this->wp_new_term_args['slug'] = $slug;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the term update or creation action saved in this object to the database.
|
||||
*
|
||||
* @return array|false
|
||||
* Returns either an array containing the term_id and term_taxonomy_id of the term resulting from this database
|
||||
* write or false on error.
|
||||
*/
|
||||
public function execute() {
|
||||
global $sitepress;
|
||||
|
||||
$switch_lang = new WPML_Temporary_Switch_Language( $sitepress, $this->lang_code );
|
||||
|
||||
remove_action( 'create_term', array( $sitepress, 'create_term' ), 1 );
|
||||
remove_action( 'edit_term', array( $sitepress, 'create_term' ), 1 );
|
||||
add_action( 'create_term', array( $this, 'add_term_language_action' ), 1, 3 );
|
||||
$new_term = false;
|
||||
|
||||
if ( $this->is_valid ) {
|
||||
if ( $this->is_update && $this->term_id ) {
|
||||
$new_term = wp_update_term( $this->term_id, $this->taxonomy, $this->wp_new_term_args );
|
||||
} else {
|
||||
$new_term = wp_insert_term( $this->wp_new_term_args['name'], $this->taxonomy, $this->wp_new_term_args );
|
||||
}
|
||||
}
|
||||
add_action( 'create_term', array( $sitepress, 'create_term' ), 1, 3 );
|
||||
add_action( 'edit_term', array( $sitepress, 'create_term' ), 1, 3 );
|
||||
remove_action( 'create_term', array( $this, 'add_term_language_action' ), 1 );
|
||||
|
||||
if ( ! is_array( $new_term ) ) {
|
||||
$new_term = false;
|
||||
}
|
||||
|
||||
unset( $switch_lang );
|
||||
return $new_term;
|
||||
}
|
||||
|
||||
/**
|
||||
* This action is to be hooked to the WP create_term and edit_term hooks.
|
||||
* It sets the correct language information after a term is saved.
|
||||
*
|
||||
* @param int|string $term_id
|
||||
* @param int|string $term_taxonomy_id
|
||||
* @param string $taxonomy
|
||||
*/
|
||||
public function add_term_language_action( $term_id, $term_taxonomy_id, $taxonomy ) {
|
||||
if ( $this->is_valid && ! $this->is_update && $this->taxonomy == $taxonomy ) {
|
||||
$this->sitepress->set_element_language_details(
|
||||
$term_taxonomy_id,
|
||||
'tax_' . $taxonomy,
|
||||
$this->trid,
|
||||
$this->lang_code,
|
||||
$this->source_lang_code
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the language variables for this object.
|
||||
*
|
||||
* @param bool|int $trid
|
||||
* @param bool|int $original_tax_id
|
||||
* @param string $lang_code
|
||||
* @param bool|string $source_language
|
||||
* @return bool True if the given language parameters allowed for determining valid language information, false
|
||||
* otherwise.
|
||||
*/
|
||||
private function set_language_information( $trid, $original_tax_id, $lang_code, $source_language ) {
|
||||
if ( ! $lang_code || ! $this->sitepress->is_active_language( $lang_code ) ) {
|
||||
return false;
|
||||
} else {
|
||||
$this->lang_code = $lang_code;
|
||||
}
|
||||
if ( ! $trid && $original_tax_id ) {
|
||||
$trid = $this->sitepress->get_element_trid( $original_tax_id, 'tax_' . $this->taxonomy );
|
||||
}
|
||||
if ( $trid ) {
|
||||
$this->trid = $trid;
|
||||
$this->existing_translations = $this->sitepress->get_element_translations( $trid, 'tax_' . $this->taxonomy );
|
||||
|
||||
foreach ( $this->existing_translations as $lang => $translation ) {
|
||||
if ( $original_tax_id && isset( $translation->element_id ) && $translation->element_id == $original_tax_id && isset( $translation->language_code ) && $translation->language_code ) {
|
||||
$this->source_lang_code = $translation->language_code;
|
||||
break;
|
||||
} elseif ( isset( $translation->language_code ) && $translation->language_code && ! $translation->source_language_code ) {
|
||||
$this->source_lang_code = $translation->language_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action type of this object.
|
||||
* In case of this action being an update the is_update flag is set true.
|
||||
* Also the term_id of the existing term is saved in $this->term_id.
|
||||
*/
|
||||
private function set_action_type() {
|
||||
if ( ! $this->trid ) {
|
||||
$this->is_update = false;
|
||||
} elseif ( isset( $this->existing_translations[ $this->lang_code ] ) ) {
|
||||
$existing_db_entry = $this->existing_translations[ $this->lang_code ];
|
||||
if ( isset( $existing_db_entry->element_id ) && $existing_db_entry->element_id ) {
|
||||
// Term update actions need information about the term_id, not the term_taxonomy_id saved in the element_id column of icl_translations.
|
||||
/** @var \stdClass $term */
|
||||
$term = $this->wpdb->get_row(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT t.term_id, t.slug FROM {$this->wpdb->terms} AS t
|
||||
JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id=tt.term_id
|
||||
WHERE term_taxonomy_id=%d",
|
||||
$existing_db_entry->element_id
|
||||
)
|
||||
);
|
||||
if ( $term->term_id && $term->slug ) {
|
||||
$this->is_update = true;
|
||||
$this->term_id = $term->term_id;
|
||||
$this->old_slug = $term->slug;
|
||||
} else {
|
||||
$this->is_update = false;
|
||||
}
|
||||
} else {
|
||||
$this->sitepress->delete_element_translation( $this->trid, 'tax_' . $this->taxonomy, $this->lang_code );
|
||||
$this->is_update = false;
|
||||
}
|
||||
} else {
|
||||
$this->is_update = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user