first commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TaxonomyTermTranslation;
|
||||
|
||||
use WPML\Element\API\Languages;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Maybe;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Relation;
|
||||
use WPML\FP\Str;
|
||||
use WPML\LIB\WP\Hooks;
|
||||
use WPML\Settings\PostType\Automatic;
|
||||
use WPML\Setup\Option;
|
||||
use function WPML\FP\pipe;
|
||||
use function WPML\FP\spreadArgs;
|
||||
|
||||
class AutoSync implements \IWPML_Backend_Action, \IWPML_REST_Action, \IWPML_AJAX_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
if ( Option::shouldTranslateEverything() ) {
|
||||
Hooks::onAction( 'wpml_pro_translation_completed', 10, 3 )
|
||||
->then( spreadArgs( self::syncTaxonomyHierarchy() ) );
|
||||
|
||||
remove_action( 'save_post', 'display_tax_sync_message' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure (int, array, object) -> void
|
||||
*/
|
||||
private static function syncTaxonomyHierarchy() {
|
||||
return function( $newPostId, $fields, $job ) {
|
||||
// $isPostJob :: object -> bool
|
||||
$isPostJob = Relation::propEq( 'element_type_prefix', 'post' );
|
||||
|
||||
// $getPostType :: object -> string
|
||||
$getPostType = pipe(
|
||||
Obj::prop( 'original_post_type' ),
|
||||
Str::replace( 'post_', '' )
|
||||
);
|
||||
|
||||
// $isAutomaticPostType :: string -> bool
|
||||
$isAutomaticPostType = [ Automatic::class, 'isAutomatic' ];
|
||||
|
||||
// $isTranslatableTax :: string -> bool
|
||||
$isTranslatableTax = function( $taxonomy ) {
|
||||
return \WPML_Element_Sync_Settings_Factory::createTax()->is_sync( $taxonomy );
|
||||
};
|
||||
|
||||
// $syncTaxonomyHierarchies :: array -> void
|
||||
$syncTaxonomyHierarchies = function( $taxonomies ) {
|
||||
wpml_get_hierarchy_sync_helper( 'term' )->sync_element_hierarchy( $taxonomies, Languages::getDefaultCode() );
|
||||
};
|
||||
|
||||
Maybe::of( $job )
|
||||
->filter( $isPostJob )
|
||||
->map( $getPostType )
|
||||
->filter( $isAutomaticPostType )
|
||||
->map( 'get_object_taxonomies' )
|
||||
->map( Fns::filter( $isTranslatableTax ) )
|
||||
->map( $syncTaxonomyHierarchies );
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TaxonomyTermTranslation;
|
||||
|
||||
use WPML\FP\Relation;
|
||||
use WPML\LIB\WP\Hooks as WpHooks;
|
||||
use function WPML\FP\spreadArgs;
|
||||
|
||||
class Hooks implements \IWPML_Backend_Action, \IWPML_Frontend_Action {
|
||||
|
||||
const KEY_SKIP_FILTERS = 'wpml_skip_filters';
|
||||
|
||||
public function add_hooks() {
|
||||
WpHooks::onFilter( 'term_exists_default_query_args' )
|
||||
->then( spreadArgs( function( $args ) {
|
||||
return array_merge(
|
||||
$args,
|
||||
[
|
||||
'cache_domain' => microtime(), // Prevent caching of the query
|
||||
self::KEY_SKIP_FILTERS => true,
|
||||
]
|
||||
);
|
||||
} ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function shouldSkip( $args ) {
|
||||
return (bool) Relation::propEq( self::KEY_SKIP_FILTERS, true, (array) $args );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
class WPML_Sync_Term_Meta_Action {
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var int $term_taxonomy_id */
|
||||
private $term_taxonomy_id;
|
||||
|
||||
/** @var bool $is_new_term */
|
||||
private $is_new_term;
|
||||
|
||||
/**
|
||||
* WPML_Sync_Term_Meta_Action constructor.
|
||||
*
|
||||
* @param SitePress $sitepress
|
||||
* @param int $term_taxonomy_id just saved term's term_taxonomy_id
|
||||
* @param bool $is_new_term
|
||||
*/
|
||||
public function __construct( $sitepress, $term_taxonomy_id, $is_new_term = false ) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->term_taxonomy_id = $term_taxonomy_id;
|
||||
$this->is_new_term = $is_new_term;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies to be synchronized term meta data to the translations of the term.
|
||||
*/
|
||||
public function run() {
|
||||
$term_taxonomy_id_from = $this->sitepress->term_translations()->get_original_element( $this->term_taxonomy_id );
|
||||
|
||||
if ( ! $term_taxonomy_id_from ) {
|
||||
$term_taxonomy_id_from = $this->term_taxonomy_id;
|
||||
}
|
||||
|
||||
$translations = $this->sitepress
|
||||
->term_translations()
|
||||
->get_element_translations( $term_taxonomy_id_from, false, true );
|
||||
|
||||
if ( ! empty( $translations ) ) {
|
||||
foreach ( $translations as $term_taxonomy_id_to ) {
|
||||
$this->copy_custom_fields( (int) $term_taxonomy_id_to, $term_taxonomy_id_from );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_taxonomy_id_to
|
||||
* @param int $term_taxonomy_id_from
|
||||
*/
|
||||
private function copy_custom_fields( $term_taxonomy_id_to, $term_taxonomy_id_from ) {
|
||||
$cf_copy = array();
|
||||
|
||||
$setting_factory = $this->sitepress->core_tm()->settings_factory();
|
||||
$meta_keys = $setting_factory->get_term_meta_keys();
|
||||
|
||||
foreach ( $meta_keys as $meta_key ) {
|
||||
$meta_key_status = $setting_factory->term_meta_setting( $meta_key )->status();
|
||||
|
||||
if ( WPML_COPY_CUSTOM_FIELD === $meta_key_status
|
||||
|| $this->should_copy_once( $meta_key_status, $term_taxonomy_id_to )
|
||||
) {
|
||||
$cf_copy[] = $meta_key;
|
||||
}
|
||||
}
|
||||
|
||||
$term_id_to = $this->sitepress->term_translations()->adjust_term_id_for_ttid( $term_taxonomy_id_to );
|
||||
$term_id_from = $this->sitepress->term_translations()->adjust_term_id_for_ttid( $term_taxonomy_id_from );
|
||||
|
||||
foreach ( $cf_copy as $meta_key ) {
|
||||
$meta_from = $this->sitepress->get_wp_api()->get_term_meta( $term_id_from, $meta_key );
|
||||
$meta_to = $this->sitepress->get_wp_api()->get_term_meta( $term_id_to, $meta_key );
|
||||
if ( $meta_from || $meta_to ) {
|
||||
$this->sync_custom_field( $term_id_from, $term_id_to, $meta_key );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sync_custom_field(
|
||||
$term_id_from,
|
||||
$term_id_to,
|
||||
$meta_key
|
||||
) {
|
||||
$wpdb = $this->sitepress->wpdb();
|
||||
$sql = "SELECT meta_value FROM {$wpdb->termmeta} WHERE term_id=%d AND meta_key=%s";
|
||||
$values_from = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
$sql,
|
||||
array( $term_id_from, $meta_key )
|
||||
)
|
||||
);
|
||||
$values_to = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
$sql,
|
||||
array( $term_id_to, $meta_key )
|
||||
)
|
||||
);
|
||||
|
||||
$removed = array_diff( $values_to, $values_from );
|
||||
foreach ( $removed as $v ) {
|
||||
$delete_prepared = $wpdb->prepare(
|
||||
"DELETE FROM {$wpdb->termmeta}
|
||||
WHERE term_id=%d
|
||||
AND meta_key=%s
|
||||
AND meta_value=%s",
|
||||
array( $term_id_to, $meta_key, $v )
|
||||
);
|
||||
$wpdb->query( $delete_prepared );
|
||||
}
|
||||
|
||||
$added = array_diff( $values_from, $values_to );
|
||||
foreach ( $added as $v ) {
|
||||
$insert_prepared = $wpdb->prepare(
|
||||
"INSERT INTO {$wpdb->termmeta}(term_id, meta_key, meta_value)
|
||||
VALUES(%d, %s, %s)",
|
||||
array( $term_id_to, $meta_key, $v )
|
||||
);
|
||||
$wpdb->query( $insert_prepared );
|
||||
}
|
||||
wp_cache_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta_key_status
|
||||
* @param int $term_taxonomy_id_to
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function should_copy_once( $meta_key_status, $term_taxonomy_id_to ) {
|
||||
return $this->is_new_term
|
||||
&& WPML_COPY_ONCE_CUSTOM_FIELD === $meta_key_status
|
||||
&& $term_taxonomy_id_to === $this->term_taxonomy_id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPML_Taxonomy_Translation_Help_Notice
|
||||
*/
|
||||
class WPML_Taxonomy_Translation_Help_Notice {
|
||||
|
||||
const NOTICE_GROUP = 'taxonomy-term-help-notices';
|
||||
|
||||
/**
|
||||
* @var WPML_Notices
|
||||
*/
|
||||
private $wpml_admin_notices;
|
||||
|
||||
/**
|
||||
* @var WPML_Notice
|
||||
*/
|
||||
private $notice = false;
|
||||
|
||||
/**
|
||||
* @var SitePress
|
||||
*/
|
||||
private $sitepress;
|
||||
|
||||
/**
|
||||
* WPML_Taxonomy_Translation_Help_Notice constructor.
|
||||
*
|
||||
* @param WPML_Notices $wpml_admin_notices
|
||||
* @param SitePress $sitepress
|
||||
*/
|
||||
public function __construct( WPML_Notices $wpml_admin_notices, SitePress $sitepress ) {
|
||||
$this->wpml_admin_notices = $wpml_admin_notices;
|
||||
$this->sitepress = $sitepress;
|
||||
}
|
||||
|
||||
public function __sleep() {
|
||||
return array( 'wpml_admin_notices', 'notice' );
|
||||
}
|
||||
|
||||
public function __wakeup() {
|
||||
global $sitepress;
|
||||
$this->sitepress = $sitepress;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'admin_init', array( $this, 'add_help_notice' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function should_display_help_notice() {
|
||||
$display_notice = false;
|
||||
$taxonomy = $this->get_current_translatable_taxonomy();
|
||||
$notice = $this->get_notice();
|
||||
if ( $notice && $taxonomy && $taxonomy->name === $notice->get_id() && $this->taxonomy_term_screen() ) {
|
||||
$display_notice = true;
|
||||
}
|
||||
|
||||
return $display_notice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add notice.
|
||||
*/
|
||||
public function add_help_notice() {
|
||||
$notice = $this->create_and_set_term_translation_help_notice();
|
||||
if ( false !== $notice ) {
|
||||
$this->add_term_help_notice_to_admin_notices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|WP_Taxonomy
|
||||
*/
|
||||
private function get_current_translatable_taxonomy() {
|
||||
$taxonomy = false;
|
||||
if ( array_key_exists( 'taxonomy', $_GET )
|
||||
&& ! empty( $_GET['taxonomy'] )
|
||||
&& $this->is_translatable_taxonomy( $_GET['taxonomy'] )
|
||||
) {
|
||||
$taxonomy = get_taxonomy( $_GET['taxonomy'] );
|
||||
}
|
||||
|
||||
return $taxonomy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_Notice
|
||||
*/
|
||||
private function create_and_set_term_translation_help_notice() {
|
||||
$taxonomy = $this->get_current_translatable_taxonomy();
|
||||
if ( false !== $taxonomy ) {
|
||||
$link_to_taxonomy_translation_screen = $this->build_tag_to_taxonomy_translation( $taxonomy );
|
||||
$text = sprintf( esc_html__( 'Translating %1$s? Use the %2$s table for easier translation.', 'sitepress' ), $taxonomy->labels->name, $link_to_taxonomy_translation_screen );
|
||||
$this->set_notice( new WPML_Notice( $taxonomy->name, $text, self::NOTICE_GROUP ) );
|
||||
}
|
||||
|
||||
return $this->get_notice();
|
||||
}
|
||||
|
||||
private function add_term_help_notice_to_admin_notices() {
|
||||
$notice = $this->get_notice();
|
||||
$notice->set_css_class_types( 'info' );
|
||||
$notice->add_display_callback( array( $this, 'should_display_help_notice' ) );
|
||||
$action = $this->wpml_admin_notices->get_new_notice_action( esc_html__( 'Dismiss', 'sitepress' ), '#', false, false, false );
|
||||
$action->set_js_callback( 'wpml_dismiss_taxonomy_translation_notice' );
|
||||
$action->set_group_to_dismiss( $notice->get_group() );
|
||||
$notice->add_action( $action );
|
||||
$this->wpml_admin_notices->add_notice( $notice );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Taxonomy $taxonomy
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function build_tag_to_taxonomy_translation( $taxonomy ) {
|
||||
|
||||
$url = add_query_arg(
|
||||
array(
|
||||
'page' => WPML_PLUGIN_FOLDER . '/menu/taxonomy-translation.php',
|
||||
'taxonomy' => $taxonomy->name,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
);
|
||||
$url = apply_filters( 'wpml_taxonomy_term_translation_url', $url, $taxonomy->name );
|
||||
|
||||
return '<a href="' . esc_url( $url ) . '">' .
|
||||
sprintf( esc_html__( ' %s translation', 'sitepress' ), $taxonomy->labels->singular_name ) . '</a>';
|
||||
}
|
||||
|
||||
private function taxonomy_term_screen() {
|
||||
$screen = get_current_screen();
|
||||
$is_taxonomy_term_screen = false;
|
||||
if ( 'edit-tags' === $screen->base || 'term' === $screen->base ) {
|
||||
$is_taxonomy_term_screen = true;
|
||||
}
|
||||
|
||||
return $is_taxonomy_term_screen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Notice $notice
|
||||
*/
|
||||
public function set_notice( WPML_Notice $notice ) {
|
||||
$this->notice = $notice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_Notice
|
||||
*/
|
||||
public function get_notice() {
|
||||
return $this->notice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue JS callback script.
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
$notice = $this->get_notice();
|
||||
if ( $notice ) {
|
||||
wp_register_script( 'wpml-dismiss-taxonomy-help-notice', ICL_PLUGIN_URL . '/res/js/dismiss-taxonomy-help-notice.js', array( 'jquery' ) );
|
||||
wp_localize_script(
|
||||
'wpml-dismiss-taxonomy-help-notice',
|
||||
'wpml_notice_information',
|
||||
array(
|
||||
'notice_id' => $notice->get_id(),
|
||||
'notice_group' => $notice->get_group(),
|
||||
)
|
||||
);
|
||||
wp_enqueue_script( 'wpml-dismiss-taxonomy-help-notice' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_translatable_taxonomy( $taxonomy ) {
|
||||
$is_translatable = false;
|
||||
|
||||
$taxonomy_object = get_taxonomy( $taxonomy );
|
||||
if ( $taxonomy_object ) {
|
||||
$post_type = isset( $taxonomy_object->object_type[0] ) ? $taxonomy_object->object_type[0] : 'post';
|
||||
$translatable_taxonomies = $this->sitepress->get_translatable_taxonomies( true, $post_type );
|
||||
$is_translatable = in_array( $taxonomy, $translatable_taxonomies );
|
||||
}
|
||||
|
||||
return $is_translatable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* WPML_Term_Actions Class
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Term_Actions extends WPML_Full_Translation_API {
|
||||
|
||||
/** @var bool $delete_recursion_flag */
|
||||
private $delete_recursion_flag = false;
|
||||
|
||||
/**
|
||||
* Handle AJAX request to generate unique slug.
|
||||
*/
|
||||
public function generate_unique_term_slug_ajax_handler() {
|
||||
if ( $this->sitepress->get_wp_api()->is_ajax() && wp_verify_nonce( $_POST['nonce'], 'wpml_generate_unique_slug_nonce' ) ) {
|
||||
$term = array_key_exists( 'term', $_POST ) ? sanitize_text_field( $_POST['term'] ) : '';
|
||||
$taxonomy = array_key_exists( 'taxonomy', $_POST ) ? sanitize_text_field( $_POST['taxonomy'] ) : '';
|
||||
$language_code = array_key_exists( 'language_code', $_POST ) ? sanitize_text_field( $_POST['language_code'] ) : '';
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'slug' => urldecode( $this->term_translations->generate_unique_term_slug( $term, '', $taxonomy, $language_code ) ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tt_id Taxonomy Term ID of the saved Term
|
||||
* @param string $taxonomy Taxonomy of the saved Term
|
||||
*/
|
||||
function save_term_actions( $tt_id, $taxonomy ) {
|
||||
if ( ! $this->sitepress->is_translated_taxonomy( $taxonomy ) ) {
|
||||
return;
|
||||
};
|
||||
$post_action = filter_input( INPUT_POST, 'action' );
|
||||
$term_lang = $this->get_term_lang( $tt_id, $post_action, $taxonomy );
|
||||
$trid = $this->get_saved_term_trid( $tt_id, $post_action );
|
||||
$src_language = $this->term_translations->get_source_lang_code( $tt_id );
|
||||
$this->sitepress->set_element_language_details(
|
||||
$tt_id,
|
||||
'tax_' . $taxonomy,
|
||||
$trid,
|
||||
$term_lang,
|
||||
$src_language
|
||||
);
|
||||
|
||||
add_action( 'created_term', array( $this, 'sync_term_meta' ), 10, 2 );
|
||||
add_action( 'edited_term', array( $this, 'sync_term_meta' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_id
|
||||
* @param int $tt_id
|
||||
*/
|
||||
public function sync_term_meta( $term_id, $tt_id ) {
|
||||
$is_new_term = 'created_term' === current_filter();
|
||||
$sync_meta_action = new WPML_Sync_Term_Meta_Action( $this->sitepress, $tt_id, $is_new_term );
|
||||
$sync_meta_action->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_taxonomy_id term taxonomy id of the deleted term
|
||||
* @param string $taxonomy_name taxonomy of the deleted term
|
||||
*/
|
||||
function delete_term_actions( $term_taxonomy_id, $taxonomy_name ) {
|
||||
$element_type = 'tax_' . $taxonomy_name;
|
||||
|
||||
$lang_details = $this->sitepress->get_element_language_details( $term_taxonomy_id, $element_type );
|
||||
if ( ! $lang_details ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$trid = $lang_details->trid;
|
||||
|
||||
if ( empty( $lang_details->source_language_code ) ) {
|
||||
if ( ! $this->delete_recursion_flag && $this->sitepress->get_setting( 'sync_delete_tax' ) ) {
|
||||
$this->delete_recursion_flag = true;
|
||||
$translations = $this->sitepress->get_element_translations( $trid, $element_type );
|
||||
$this->delete_translations( $term_taxonomy_id, $taxonomy_name, $translations );
|
||||
$this->delete_recursion_flag = false;
|
||||
} else {
|
||||
$this->set_new_original_term( $trid, $lang_details->language_code );
|
||||
}
|
||||
}
|
||||
|
||||
$update_args = array(
|
||||
'element_id' => $term_taxonomy_id,
|
||||
'element_type' => $element_type,
|
||||
'context' => 'tax',
|
||||
);
|
||||
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'before_delete' ) ) );
|
||||
$this->wpdb->delete(
|
||||
$this->wpdb->prefix . 'icl_translations',
|
||||
array(
|
||||
'element_type' => $element_type,
|
||||
'element_id' => $term_taxonomy_id,
|
||||
)
|
||||
);
|
||||
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'after_delete' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $trid
|
||||
* @param string $deleted_language_code
|
||||
*/
|
||||
public function set_new_original_term( $trid, $deleted_language_code ) {
|
||||
if ( $trid && $deleted_language_code ) {
|
||||
$order_languages = $this->sitepress->get_setting( 'languages_order' );
|
||||
$this->term_translations->reload();
|
||||
$translations = $this->term_translations->get_element_translations( false, $trid );
|
||||
$new_source_lang_code = false;
|
||||
foreach ( $order_languages as $lang_code ) {
|
||||
if ( isset( $translations[ $lang_code ] ) ) {
|
||||
$new_source_lang_code = $lang_code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( $new_source_lang_code ) {
|
||||
$rows_updated = $this->wpdb->update(
|
||||
$this->wpdb->prefix . 'icl_translations',
|
||||
array( 'source_language_code' => $new_source_lang_code ),
|
||||
array(
|
||||
'trid' => $trid,
|
||||
'source_language_code' => $deleted_language_code,
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 < $rows_updated ) {
|
||||
do_action( 'wpml_translation_update', array( 'trid' => $trid ) );
|
||||
}
|
||||
|
||||
$this->wpdb->query(
|
||||
"UPDATE {$this->wpdb->prefix}icl_translations
|
||||
SET source_language_code = NULL
|
||||
WHERE language_code = source_language_code"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This action is hooked to the 'deleted_term_relationships' hook.
|
||||
* It removes terms from translated posts as soon as they are removed from the original post.
|
||||
* It only fires, if the setting 'sync_post_taxonomies' is activated.
|
||||
*
|
||||
* @param int $post_id ID of the post the deleted terms were attached to
|
||||
* @param array $delete_terms Array of term taxonomy id's for those terms that were deleted from the post.
|
||||
*/
|
||||
public function deleted_term_relationships( $post_id, $delete_terms ) {
|
||||
$post = get_post( $post_id );
|
||||
$trid = $this->sitepress->get_element_trid( $post_id, 'post_' . $post->post_type );
|
||||
if ( $trid ) {
|
||||
$translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type );
|
||||
foreach ( $translations as $translation ) {
|
||||
if ( $translation->original == 1 && $translation->element_id == $post_id ) {
|
||||
$taxonomies = get_object_taxonomies( $post->post_type );
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
foreach ( $delete_terms as $delete_term ) {
|
||||
$trid = $this->sitepress->get_element_trid( $delete_term, 'tax_' . $taxonomy );
|
||||
if ( $trid ) {
|
||||
$tags = $this->sitepress->get_element_translations( $trid, 'tax_' . $taxonomy );
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( ! $tag->original && isset( $translations[ $tag->language_code ] ) ) {
|
||||
$translated_post = $translations[ $tag->language_code ];
|
||||
$this->wpdb->delete(
|
||||
$this->wpdb->term_relationships,
|
||||
array(
|
||||
'object_id' => $translated_post->element_id,
|
||||
'term_taxonomy_id' => $tag->element_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies taxonomy terms from original posts to their translation, if the translations of these terms exist
|
||||
* and the option 'sync_post_taxonomies' is set.
|
||||
*
|
||||
* @param int $object_id ID of the object, that terms have just been added to.
|
||||
*/
|
||||
public function added_term_relationships( $object_id ) {
|
||||
$i = $this->wpdb->prefix . 'icl_translations';
|
||||
$current_ttids_sql =
|
||||
$this->wpdb->prepare(
|
||||
"SELECT
|
||||
ctt.taxonomy,
|
||||
ctt.term_id,
|
||||
p.ID
|
||||
FROM {$this->wpdb->posts} p
|
||||
JOIN {$i} i
|
||||
ON p.ID = i.element_id
|
||||
AND i.element_type = CONCAT('post_', p.post_type)
|
||||
JOIN {$i} ip
|
||||
ON ip.trid = i.trid
|
||||
AND i.source_language_code = ip.language_code
|
||||
JOIN {$i} it
|
||||
JOIN {$this->wpdb->term_taxonomy} tt
|
||||
ON tt.term_taxonomy_id = it.element_id
|
||||
AND CONCAT('tax_', tt.taxonomy) = it.element_type
|
||||
JOIN {$this->wpdb->term_relationships} objrel
|
||||
ON objrel.object_id = ip.element_id
|
||||
AND objrel.term_taxonomy_id = tt.term_taxonomy_id
|
||||
JOIN {$i} itt
|
||||
ON itt.trid = it.trid
|
||||
AND itt.language_code = i.language_code
|
||||
JOIN {$this->wpdb->term_taxonomy} ctt
|
||||
ON ctt.term_taxonomy_id = itt.element_id
|
||||
LEFT JOIN {$this->wpdb->term_relationships} trans_rel
|
||||
ON trans_rel.object_id = p.ID
|
||||
AND trans_rel.term_taxonomy_id = ctt.term_taxonomy_id
|
||||
WHERE ip.element_id = %d
|
||||
AND trans_rel.object_id IS NULL",
|
||||
$object_id
|
||||
);
|
||||
|
||||
$this->apply_added_term_changes( $this->wpdb->get_results( $current_ttids_sql ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $corrections
|
||||
*
|
||||
* @uses \WPML_WP_API::wp_set_object_terms to add terms to posts, always appending terms
|
||||
*/
|
||||
private function apply_added_term_changes( $corrections ) {
|
||||
$changes = array();
|
||||
|
||||
foreach ( $corrections as $correction ) {
|
||||
if ( ! $this->sitepress->is_translated_taxonomy( $correction->taxonomy ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( ! isset( $changes[ $correction->taxonomy ] ) ) {
|
||||
$changes[ $correction->ID ][ $correction->taxonomy ] = array();
|
||||
}
|
||||
$changes[ $correction->ID ][ $correction->taxonomy ][] = (int) $correction->term_id;
|
||||
}
|
||||
foreach ( $changes as $post_id => $tax_changes ) {
|
||||
foreach ( $tax_changes as $taxonomy => $term_ids ) {
|
||||
remove_action(
|
||||
'set_object_terms',
|
||||
array( 'WPML_Terms_Translations', 'set_object_terms_action' ),
|
||||
10
|
||||
);
|
||||
$this->sitepress->get_wp_api()->wp_set_object_terms( $post_id, $term_ids, $taxonomy, true );
|
||||
add_action(
|
||||
'set_object_terms',
|
||||
array( 'WPML_Terms_Translations', 'set_object_terms_action' ),
|
||||
10,
|
||||
6
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language under which a term is to be saved from the HTTP request and falls back on existing data in
|
||||
* case the HTTP request does not contain the necessary data.
|
||||
* If no language can be determined for the term to be saved under the default language is used as a fallback.
|
||||
*
|
||||
* @param int $tt_id Taxonomy Term ID of the saved term
|
||||
* @param string $post_action
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private function get_term_lang( $tt_id, $post_action, $taxonomy ) {
|
||||
$term_lang = filter_input(
|
||||
INPUT_POST,
|
||||
'icl_tax_' . $taxonomy . '_language',
|
||||
FILTER_SANITIZE_FULL_SPECIAL_CHARS
|
||||
);
|
||||
$term_lang = $term_lang ? $term_lang : $this->get_term_lang_ajax( $taxonomy, $post_action );
|
||||
$term_lang = $term_lang ? $term_lang : $this->get_lang_from_post( $post_action, $tt_id );
|
||||
|
||||
$term_lang = $term_lang ? $term_lang : $this->sitepress->get_current_language();
|
||||
$term_lang = apply_filters( 'wpml_create_term_lang', $term_lang );
|
||||
$term_lang = $this->sitepress->is_active_language( $term_lang ) ? $term_lang
|
||||
: $this->sitepress->get_default_language();
|
||||
|
||||
return $term_lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no language could be set from the WPML $_POST variables as well as from the HTTP Referrer, then this function
|
||||
* uses fallbacks to determine the language from the post the the term might be associated to.
|
||||
* A post language determined from $_POST['icl_post_language'] will be used as term language.
|
||||
* Also a check for whether the publishing of the term happens via quickpress is performed in which case the term
|
||||
* is always associated with the default language.
|
||||
* Next a check for the 'inline-save-tax' and the 'editedtag' action is performed. In case the check returns true
|
||||
* the language of the term is not changed from what is saved for it in the database.
|
||||
* If no term language can be determined from the above the $_POST['post_ID'] is checked as a last resort and in
|
||||
* case it contains a valid post_ID the posts language is associated with the term.
|
||||
*
|
||||
* @param string $post_action
|
||||
* @param int $tt_id
|
||||
*
|
||||
* @return string|null Language code of the term
|
||||
*/
|
||||
private function get_lang_from_post( $post_action, $tt_id ) {
|
||||
$icl_post_lang = filter_input( INPUT_POST, 'icl_post_language' );
|
||||
$term_lang = $post_action === 'editpost' && $icl_post_lang ? $icl_post_lang : null;
|
||||
$term_lang = $post_action === 'post-quickpress-publish' ? $this->sitepress->get_default_language()
|
||||
: $term_lang;
|
||||
$term_lang = ! $term_lang && $post_action === 'inline-save-tax' || $post_action === 'editedtag'
|
||||
? $this->term_translations->get_element_lang_code( $tt_id ) : $term_lang;
|
||||
$term_lang = ! $term_lang && $post_action === 'inline-save'
|
||||
? $this->post_translations->get_element_lang_code(
|
||||
filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_NUMBER_INT )
|
||||
) : $term_lang;
|
||||
|
||||
return $term_lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to determine the terms language from the HTTP Referer. This is used in case of ajax actions
|
||||
* that save the term.
|
||||
*
|
||||
* @param string $taxonomy
|
||||
* @param string $post_action
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function get_term_lang_ajax( $taxonomy, $post_action ) {
|
||||
if ( isset( $_POST['_ajax_nonce'] ) && filter_var( $_POST['_ajax_nonce'] ) !== false
|
||||
&& $post_action === 'add-' . $taxonomy
|
||||
) {
|
||||
$referrer = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
|
||||
parse_str( (string) wpml_parse_url( $referrer, PHP_URL_QUERY ), $qvars );
|
||||
$term_lang = ! empty( $qvars['post'] ) && $this->sitepress->is_translated_post_type(
|
||||
get_post_type( $qvars['post'] )
|
||||
)
|
||||
? $this->post_translations->get_element_lang_code( $qvars['post'] )
|
||||
: ( isset( $qvars['lang'] ) ? $qvars['lang'] : null );
|
||||
}
|
||||
|
||||
return isset( $term_lang ) ? $term_lang : null;
|
||||
}
|
||||
|
||||
private function get_saved_term_trid( $tt_id, $post_action ) {
|
||||
if ( $post_action === 'editpost' ) {
|
||||
$trid = $this->term_translations->get_element_trid( $tt_id );
|
||||
} elseif ( $post_action === 'editedtag' ) {
|
||||
$translation_of = filter_input( INPUT_POST, 'icl_translation_of', FILTER_VALIDATE_INT );
|
||||
$translation_of = $translation_of ? $translation_of : filter_input( INPUT_POST, 'icl_translation_of' );
|
||||
|
||||
$trid = $translation_of === 'none' ? false
|
||||
: ( $translation_of
|
||||
? $this->term_translations->get_element_trid( $translation_of )
|
||||
: $trid = filter_input( INPUT_POST, 'icl_trid', FILTER_SANITIZE_NUMBER_INT )
|
||||
);
|
||||
} else {
|
||||
$trid = filter_input( INPUT_POST, 'icl_trid', FILTER_SANITIZE_NUMBER_INT );
|
||||
$trid = $trid
|
||||
? $trid
|
||||
: $this->term_translations->get_element_trid(
|
||||
filter_input( INPUT_POST, 'icl_translation_of', FILTER_VALIDATE_INT )
|
||||
);
|
||||
$trid = $trid ? $trid : $this->term_translations->get_element_trid( $tt_id );
|
||||
}
|
||||
|
||||
return $trid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $term_taxonomy_id
|
||||
* @param string $taxonomy
|
||||
* @param array $translations
|
||||
*/
|
||||
private function delete_translations( $term_taxonomy_id, $taxonomy, array $translations ) {
|
||||
$has_filter = remove_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1 );
|
||||
foreach ( $translations as $translation ) {
|
||||
if ( (int) $translation->element_id !== (int) $term_taxonomy_id ) {
|
||||
wp_delete_term( $translation->term_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
if ( $has_filter ) {
|
||||
add_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @since 3.1.8.4
|
||||
*
|
||||
* Class WPML_Term_Language_Synchronization
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage taxonomy-term-translation
|
||||
*/
|
||||
class WPML_Term_Language_Synchronization extends WPML_WPDB_And_SP_User {
|
||||
|
||||
/** @var string $taxonomy */
|
||||
private $taxonomy;
|
||||
/** @var array $data */
|
||||
private $data;
|
||||
/** @var array $missing_terms */
|
||||
private $missing_terms = array();
|
||||
/** @var WPML_Terms_Translations $term_utils */
|
||||
private $term_utils;
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
* @param WPML_Terms_Translations $term_utils
|
||||
* @param string $taxonomy
|
||||
*/
|
||||
public function __construct( &$sitepress, &$term_utils, $taxonomy ) {
|
||||
$wpdb = $sitepress->wpdb();
|
||||
parent::__construct( $wpdb, $sitepress );
|
||||
$this->term_utils = $term_utils;
|
||||
$this->taxonomy = $taxonomy;
|
||||
$this->data = $this->set_affected_ids();
|
||||
$this->prepare_missing_terms_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for the two database actions performed by this object.
|
||||
* First those terms are created that lack translations and then following that,
|
||||
* the assignment of posts and languages is corrected, taking advantage of the newly created terms
|
||||
* and resulting in a state of no conflicts in the form of a post language being different from
|
||||
* an assigned terms language, remaining.
|
||||
*/
|
||||
public function set_translated() {
|
||||
$this->prepare_missing_originals();
|
||||
$this->reassign_terms();
|
||||
$this->set_initial_term_language();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for the installation process,
|
||||
* finds all terms missing an entry in icl_translations and then
|
||||
* assigns them the default language.
|
||||
*/
|
||||
public function set_initial_term_language() {
|
||||
$element_ids = $this->wpdb->get_col(
|
||||
$this->wpdb->prepare(
|
||||
"
|
||||
SELECT tt.term_taxonomy_id
|
||||
FROM {$this->wpdb->term_taxonomy} AS tt
|
||||
LEFT JOIN {$this->wpdb->prefix}icl_translations AS i
|
||||
ON tt.term_taxonomy_id = i.element_id
|
||||
AND CONCAT('tax_', tt.taxonomy) = i.element_type
|
||||
WHERE taxonomy = %s
|
||||
AND i.element_id IS NULL",
|
||||
$this->taxonomy
|
||||
)
|
||||
);
|
||||
$default_language = $this->sitepress->get_default_language();
|
||||
foreach ( $element_ids as $id ) {
|
||||
$this->sitepress->set_element_language_details( $id, 'tax_' . $this->taxonomy, false, $default_language );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an SQL query assigning all terms to their correct language equivalent if it exists.
|
||||
* This should only be run after the previous functionality in here has finished.
|
||||
* Afterwards the term counts are recalculated globally, since term assignments bypassing the WordPress Core,
|
||||
* will not trigger any sort of update on those.
|
||||
*/
|
||||
private function reassign_terms() {
|
||||
$update_query = $this->wpdb->prepare(
|
||||
"UPDATE {$this->wpdb->term_relationships} AS o,
|
||||
{$this->wpdb->prefix}icl_translations AS ic,
|
||||
{$this->wpdb->prefix}icl_translations AS iw,
|
||||
{$this->wpdb->prefix}icl_translations AS ip,
|
||||
{$this->wpdb->posts} AS p
|
||||
SET o.term_taxonomy_id = ic.element_id
|
||||
WHERE ic.trid = iw.trid
|
||||
AND ic.element_type = iw.element_type
|
||||
AND iw.element_id = o.term_taxonomy_id
|
||||
AND ic.language_code = ip.language_code
|
||||
AND ip.element_type = CONCAT('post_', p.post_type)
|
||||
AND ip.element_id = p.ID
|
||||
AND o.object_id = p.ID
|
||||
AND o.term_taxonomy_id != ic.element_id
|
||||
AND iw.element_type = %s",
|
||||
'tax_' . $this->taxonomy
|
||||
);
|
||||
|
||||
$rows_affected = $this->wpdb->query( $update_query );
|
||||
if ( $rows_affected ) {
|
||||
$term_ids = $this->wpdb->get_col(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT term_taxonomy_id FROM {$this->wpdb->term_taxonomy} WHERE taxonomy = %s",
|
||||
$this->taxonomy
|
||||
)
|
||||
);
|
||||
// Do not run the count update on taxonomies that are not actually registered as proper taxonomy objects, e.g. WooCommerce Product Attributes.
|
||||
$taxonomy_object = $this->sitepress->get_wp_api()->get_taxonomy( $this->taxonomy );
|
||||
if ( $taxonomy_object && isset( $taxonomy_object->object_type ) ) {
|
||||
$this->sitepress->get_wp_api()->wp_update_term_count( $term_ids, $this->taxonomy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $sql_result holding the information retrieved in \self::set_affected_ids
|
||||
*
|
||||
* @return array The associative array to be returned by \self::set_affected_ids
|
||||
*/
|
||||
private function format_data( $sql_result ) {
|
||||
$res = array();
|
||||
foreach ( $sql_result as $pair ) {
|
||||
$res[ $pair->ttid ] = isset( $res[ $pair->ttid ] )
|
||||
? $res[ $pair->ttid ]
|
||||
: array(
|
||||
'tlang' => array(),
|
||||
'plangs' => array(),
|
||||
);
|
||||
|
||||
if ( $pair->term_lang && $pair->trid ) {
|
||||
$res[ $pair->ttid ]['tlang'] = array(
|
||||
'lang' => $pair->term_lang,
|
||||
'trid' => $pair->trid,
|
||||
);
|
||||
}
|
||||
if ( $pair->post_lang ) {
|
||||
$res[ $pair->ttid ]['plangs'][ $pair->post_id ] = $pair->post_lang;
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the API provided in \WPML_Terms_Translations to create missing term translations.
|
||||
* These arise when a term, previously having been untranslated, is set to be translated
|
||||
* and assigned to posts in more than one language.
|
||||
*
|
||||
* @param int $trid The trid value for which term translations are missing.
|
||||
* @param string $source_lang The source language of this trid.
|
||||
* @param array $langs The languages' codes for which term translations are missing.
|
||||
*/
|
||||
private function prepare_missing_translations(
|
||||
$trid,
|
||||
$source_lang,
|
||||
$langs
|
||||
) {
|
||||
$existing_translations = $this->sitepress->term_translations()->get_element_translations(
|
||||
false,
|
||||
$trid
|
||||
);
|
||||
foreach ( $langs as $lang ) {
|
||||
if ( ! isset( $existing_translations[ $lang ] ) ) {
|
||||
$this->term_utils->create_automatic_translation(
|
||||
array(
|
||||
'lang_code' => $lang,
|
||||
'source_language' => $source_lang,
|
||||
'trid' => $trid,
|
||||
'taxonomy' => $this->taxonomy,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all term_ids, and if applicable, their language and assigned to posts,
|
||||
* in an associative array,
|
||||
* which are in the situation of not being assigned to any language or in which a term
|
||||
* is assigned to a post in a language different from its own.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function set_affected_ids() {
|
||||
$query_for_post_ids = $this->wpdb->prepare(
|
||||
"
|
||||
SELECT tl.trid AS trid, tl.ttid AS ttid, tl.tlang AS term_lang, tl.pid AS post_id, pl.plang AS post_lang
|
||||
FROM (
|
||||
SELECT
|
||||
o.object_id AS pid,
|
||||
tt.term_taxonomy_id AS ttid,
|
||||
i.language_code AS tlang,
|
||||
i.trid AS trid
|
||||
FROM {$this->wpdb->term_relationships} AS o
|
||||
JOIN {$this->wpdb->term_taxonomy} AS tt
|
||||
ON o.term_taxonomy_id = tt.term_taxonomy_id
|
||||
LEFT JOIN {$this->wpdb->prefix}icl_translations AS i
|
||||
ON i.element_id = tt.term_taxonomy_id
|
||||
AND i.element_type = CONCAT('tax_', tt.taxonomy)
|
||||
WHERE tt.taxonomy = %s) AS tl
|
||||
LEFT JOIN
|
||||
( SELECT p.ID AS pid, i.language_code AS plang
|
||||
FROM {$this->wpdb->posts} AS p
|
||||
JOIN {$this->wpdb->prefix}icl_translations AS i
|
||||
ON i.element_id = p.ID
|
||||
AND i.element_type = CONCAT('post_', p.post_type)
|
||||
) AS pl
|
||||
ON tl.pid = pl.pid
|
||||
",
|
||||
$this->taxonomy
|
||||
);
|
||||
$ttid_pid_pairs = $this->wpdb->get_results( $query_for_post_ids );
|
||||
|
||||
return $this->format_data( $ttid_pid_pairs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns language information to terms that are to be treated as originals at the time of
|
||||
* their taxonomy being set to translated instead of 'do nothing'.
|
||||
*/
|
||||
private function prepare_missing_originals() {
|
||||
foreach ( $this->missing_terms as $ttid => $missing_lang_data ) {
|
||||
if ( ! isset( $this->data[ $ttid ]['tlang']['trid'] ) ) {
|
||||
foreach ( $missing_lang_data as $lang => $post_ids ) {
|
||||
$this->sitepress->set_element_language_details(
|
||||
$ttid,
|
||||
'tax_' . $this->taxonomy,
|
||||
null,
|
||||
$lang
|
||||
);
|
||||
$trid = $this->sitepress->term_translations()->get_element_trid( $ttid );
|
||||
if ( $trid ) {
|
||||
$this->data[ $ttid ]['tlang']['trid'] = $trid;
|
||||
$this->data[ $ttid ]['tlang']['lang'] = $lang;
|
||||
unset( $this->missing_terms[ $ttid ][ $lang ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( isset( $this->data[ $ttid ]['tlang']['trid'] ) ) {
|
||||
$this->prepare_missing_translations(
|
||||
$this->data[ $ttid ]['tlang']['trid'],
|
||||
$this->data[ $ttid ]['tlang']['lang'],
|
||||
array_keys( $this->missing_terms[ $ttid ] )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the data retrieved from the database and saves information about,
|
||||
* in need of fixing terms to this object.
|
||||
*/
|
||||
private function prepare_missing_terms_data() {
|
||||
$default_lang = $this->sitepress->get_default_language();
|
||||
$data = $this->data;
|
||||
$missing = array();
|
||||
foreach ( $data as $ttid => $data_item ) {
|
||||
if ( empty( $data_item['plangs'] ) && empty( $data_item['tlang'] ) ) {
|
||||
$missing[ $ttid ][ $default_lang ] = - 1;
|
||||
} else {
|
||||
$affected_languages = array_diff( $data_item['plangs'], $data_item['tlang'] );
|
||||
if ( ! empty( $affected_languages ) ) {
|
||||
foreach ( $data_item['plangs'] as $post_id => $lang ) {
|
||||
if ( ! isset( $missing[ $ttid ][ $lang ] ) ) {
|
||||
$missing[ $ttid ][ $lang ] = array( $post_id );
|
||||
} else {
|
||||
$missing[ $ttid ][ $lang ][] = $post_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->missing_terms = $missing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
class WPML_Update_Term_Count {
|
||||
|
||||
const CACHE_GROUP = __CLASS__;
|
||||
|
||||
/** @var WPML_WP_API $wp_api */
|
||||
private $wp_api;
|
||||
|
||||
/**
|
||||
* WPML_Update_Term_Count constructor.
|
||||
*
|
||||
* @param WPML_WP_API $wp_api
|
||||
*/
|
||||
public function __construct( $wp_api ) {
|
||||
$this->wp_api = $wp_api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers an update to the term count of all terms associated with the
|
||||
* input post_id
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public function update_for_post( $post_id ) {
|
||||
static $taxonomies;
|
||||
|
||||
if ( ! $taxonomies ) {
|
||||
$taxonomies = $this->wp_api->get_taxonomies();
|
||||
}
|
||||
|
||||
if ( is_wp_error( $taxonomies ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$found = false;
|
||||
$terms = WPML_Non_Persistent_Cache::get( $post_id, self::CACHE_GROUP, $found );
|
||||
if ( ! $found ) {
|
||||
$terms = $this->wp_api->wp_get_post_terms( $post_id, $taxonomies );
|
||||
|
||||
WPML_Non_Persistent_Cache::set( $post_id, $terms, self::CACHE_GROUP );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $terms ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
foreach ( $terms as $term ) {
|
||||
if ( $term->taxonomy === $taxonomy ) {
|
||||
$this->wp_api->wp_update_term_count( $term->term_taxonomy_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user