first commit
This commit is contained in:
233
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/admin-sync.php
vendored
Normal file
233
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/admin-sync.php
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manages copy and synchronization of terms and post metas
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
class PLL_Admin_Sync extends PLL_Sync {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 1.2
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
parent::__construct( $polylang );
|
||||
|
||||
add_filter( 'wp_insert_post_parent', array( $this, 'wp_insert_post_parent' ), 10, 3 );
|
||||
add_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ) );
|
||||
add_filter( 'use_block_editor_for_post', array( $this, 'new_post_translation' ), 5000 ); // After content duplication.
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate post parent if exists when using "Add new" ( translation )
|
||||
*
|
||||
* @since 0.6
|
||||
*
|
||||
* @param int $post_parent Post parent ID
|
||||
* @param int $post_id Post ID, unused
|
||||
* @param array $postarr Array of parsed post data
|
||||
* @return int
|
||||
*/
|
||||
public function wp_insert_post_parent( $post_parent, $post_id, $postarr ) {
|
||||
if ( isset( $_GET['from_post'], $_GET['new_lang'], $_GET['post_type'] ) ) {
|
||||
check_admin_referer( 'new-post-translation' );
|
||||
// Make sure not to impact media translations created at the same time
|
||||
if ( $_GET['post_type'] === $postarr['post_type'] && ( $id = wp_get_post_parent_id( (int) $_GET['from_post'] ) ) && $parent = $this->model->post->get_translation( $id, sanitize_key( $_GET['new_lang'] ) ) ) {
|
||||
$post_parent = $parent;
|
||||
}
|
||||
}
|
||||
return $post_parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy menu order, comment, ping status and optionally the date when creating a new translation
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @param array $data An array of slashed post data.
|
||||
* @return array
|
||||
*/
|
||||
public function wp_insert_post_data( $data ) {
|
||||
if ( isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) && 'post-new.php' === $GLOBALS['pagenow'] && $this->model->is_translated_post_type( $data['post_type'] ) ) {
|
||||
check_admin_referer( 'new-post-translation' );
|
||||
|
||||
$from_post_id = (int) $_GET['from_post'];
|
||||
$from_post = get_post( $from_post_id );
|
||||
|
||||
if ( $from_post instanceof WP_Post ) {
|
||||
foreach ( array( 'menu_order', 'comment_status', 'ping_status' ) as $property ) {
|
||||
$data[ $property ] = $from_post->$property;
|
||||
}
|
||||
|
||||
// Copy the date only if the synchronization is activated
|
||||
if ( in_array( 'post_date', $this->options['sync'] ) ) {
|
||||
$data['post_date'] = $from_post->post_date;
|
||||
$data['post_date_gmt'] = $from_post->post_date_gmt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy post metas, and taxonomies when using "Add new" ( translation )
|
||||
*
|
||||
* @since 2.5
|
||||
* @since 3.1 Use of use_block_editor_for_post filter instead of rest_api_init which is triggered too early in WP 5.8.
|
||||
*
|
||||
* @param bool $is_block_editor Whether the post can be edited or not.
|
||||
* @return bool
|
||||
*/
|
||||
public function new_post_translation( $is_block_editor ) {
|
||||
global $post;
|
||||
static $done = array();
|
||||
|
||||
if ( ! empty( $post ) && isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) && 'post-new.php' === $GLOBALS['pagenow'] && $this->model->is_translated_post_type( $post->post_type ) ) {
|
||||
check_admin_referer( 'new-post-translation' );
|
||||
|
||||
// Capability check already done in post-new.php
|
||||
$from_post_id = (int) $_GET['from_post'];
|
||||
$lang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) );
|
||||
|
||||
if ( ! $from_post_id || ! $lang || ! empty( $done[ $from_post_id ] ) ) {
|
||||
return $is_block_editor;
|
||||
}
|
||||
|
||||
$done[ $from_post_id ] = true; // Avoid a second duplication in the block editor. Using an array only to allow multiple phpunit tests.
|
||||
|
||||
$this->taxonomies->copy( $from_post_id, $post->ID, $lang->slug );
|
||||
$this->post_metas->copy( $from_post_id, $post->ID, $lang->slug );
|
||||
|
||||
if ( is_sticky( $from_post_id ) ) {
|
||||
stick_post( $post->ID );
|
||||
}
|
||||
}
|
||||
|
||||
return $is_block_editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post fields to synchronize.
|
||||
*
|
||||
* @since 2.4
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @return array Fields to synchronize.
|
||||
*/
|
||||
protected function get_fields_to_sync( $post ) {
|
||||
global $wpdb;
|
||||
|
||||
$postarr = parent::get_fields_to_sync( $post );
|
||||
|
||||
// For new drafts, save the date now otherwise it is overridden by WP. Thanks to JoryHogeveen. See #32.
|
||||
if ( in_array( 'post_date', $this->options['sync'] ) && isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) && 'post-new.php' === $GLOBALS['pagenow'] ) {
|
||||
check_admin_referer( 'new-post-translation' );
|
||||
|
||||
unset( $postarr['post_date'] );
|
||||
unset( $postarr['post_date_gmt'] );
|
||||
|
||||
$original = get_post( (int) $_GET['from_post'] );
|
||||
|
||||
if ( $original instanceof WP_Post ) {
|
||||
$wpdb->update(
|
||||
$wpdb->posts,
|
||||
array(
|
||||
'post_date' => $original->post_date,
|
||||
'post_date_gmt' => $original->post_date_gmt,
|
||||
),
|
||||
array( 'ID' => $post->ID )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $GLOBALS['post_type'] ) ) {
|
||||
$post_type = $GLOBALS['post_type'];
|
||||
} elseif ( isset( $_REQUEST['post_type'] ) ) {
|
||||
$post_type = sanitize_key( $_REQUEST['post_type'] ); // 2nd case for quick edit
|
||||
}
|
||||
|
||||
// Make sure not to impact media translations when creating them at the same time as post
|
||||
if ( in_array( 'post_parent', $this->options['sync'] ) && ( ! isset( $post_type ) || $post_type !== $post->post_type ) ) {
|
||||
unset( $postarr['post_parent'] );
|
||||
}
|
||||
|
||||
return $postarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes post fields in translations.
|
||||
*
|
||||
* @since 1.2
|
||||
*
|
||||
* @param int $post_id Post id.
|
||||
* @param WP_Post $post Post object.
|
||||
* @param int[] $translations Post translations.
|
||||
*/
|
||||
public function pll_save_post( $post_id, $post, $translations ) {
|
||||
parent::pll_save_post( $post_id, $post, $translations );
|
||||
|
||||
// Sticky posts
|
||||
if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
|
||||
$stickies = get_option( 'sticky_posts' );
|
||||
if ( isset( $_REQUEST['sticky'] ) && 'sticky' === $_REQUEST['sticky'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$stickies = array_merge( $stickies, array_values( $translations ) );
|
||||
} else {
|
||||
$stickies = array_diff( $stickies, array_values( $translations ) );
|
||||
}
|
||||
update_option( 'sticky_posts', array_unique( $stickies ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some backward compatibility with Polylang < 2.3
|
||||
* allows to call PLL()->sync->copy_post_metas() and PLL()->sync->copy_taxonomies()
|
||||
* used for example in Polylang for WooCommerce
|
||||
* the compatibility is however only partial as the 4th argument $sync is lost
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param string $func Function name
|
||||
* @param array $args Function arguments
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function __call( $func, $args ) {
|
||||
$obj = substr( $func, 5 );
|
||||
|
||||
if ( is_object( $this->$obj ) && method_exists( $this->$obj, 'copy' ) ) {
|
||||
if ( WP_DEBUG ) {
|
||||
$debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
||||
$i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
|
||||
|
||||
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
||||
sprintf(
|
||||
'%1$s was called incorrectly in %3$s on line %4$s: the call to PLL()->sync->%1$s() has been deprecated in Polylang 2.3, use PLL()->sync->%2$s->copy() instead.' . "\nError handler",
|
||||
esc_html( $func ),
|
||||
esc_html( $obj ),
|
||||
esc_html( $debug[ $i ]['file'] ),
|
||||
absint( $debug[ $i ]['line'] )
|
||||
)
|
||||
);
|
||||
}
|
||||
return call_user_func_array( array( $this->$obj, 'copy' ), $args );
|
||||
}
|
||||
|
||||
$debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
||||
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
||||
sprintf(
|
||||
'Call to undefined function PLL()->sync->%1$s() in %2$s on line %3$s' . "\nError handler",
|
||||
esc_html( $func ),
|
||||
esc_html( $debug[0]['file'] ),
|
||||
absint( $debug[0]['line'] )
|
||||
),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
26
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/load.php
vendored
Normal file
26
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/load.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Loads the module for general synchronization such as metas and taxonomies.
|
||||
*
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Don't access directly
|
||||
}
|
||||
|
||||
if ( $polylang->model->has_languages() ) {
|
||||
if ( $polylang instanceof PLL_Admin_Base ) {
|
||||
$polylang->sync = new PLL_Admin_Sync( $polylang );
|
||||
} else {
|
||||
$polylang->sync = new PLL_Sync( $polylang );
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'pll_settings_modules',
|
||||
function ( $modules ) {
|
||||
$modules[] = 'PLL_Settings_Sync';
|
||||
return $modules;
|
||||
}
|
||||
);
|
||||
}
|
||||
115
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/settings-sync.php
vendored
Normal file
115
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/settings-sync.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* Settings class for synchronization settings management
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
class PLL_Settings_Sync extends PLL_Settings_Module {
|
||||
/**
|
||||
* Stores the display order priority.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $priority = 50;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 1.8
|
||||
*
|
||||
* @param object $polylang The polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
parent::__construct(
|
||||
$polylang,
|
||||
array(
|
||||
'module' => 'sync',
|
||||
'title' => __( 'Synchronization', 'polylang' ),
|
||||
'description' => __( 'The synchronization options allow to maintain exact same values (or translations in the case of taxonomies and page parent) of meta content between the translations of a post or page.', 'polylang' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the module
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public function deactivate() {
|
||||
$this->options['sync'] = array();
|
||||
update_option( 'polylang', $this->options );
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the settings form
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
protected function form() {
|
||||
?>
|
||||
<ul class="pll-inline-block-list">
|
||||
<?php
|
||||
foreach ( self::list_metas_to_sync() as $key => $str ) {
|
||||
printf(
|
||||
'<li><label><input name="sync[%s]" type="checkbox" value="1" %s /> %s</label></li>',
|
||||
esc_attr( $key ),
|
||||
checked( in_array( $key, $this->options['sync'] ), true, false ),
|
||||
esc_html( $str )
|
||||
);
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the settings before saving.
|
||||
*
|
||||
* @since 1.8
|
||||
*
|
||||
* @param array $options Unsanitized options to save.
|
||||
* @return array
|
||||
*/
|
||||
protected function update( $options ) {
|
||||
$newoptions = array( 'sync' => empty( $options['sync'] ) ? array() : array_keys( $options['sync'], 1 ) );
|
||||
return $newoptions; // Take care to return only validated options.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the row actions.
|
||||
*
|
||||
* @since 1.8
|
||||
*
|
||||
* @return string[] Row actions.
|
||||
*/
|
||||
protected function get_actions() {
|
||||
return empty( $this->options['sync'] ) ? array( 'configure' ) : array( 'configure', 'deactivate' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of synchronization settings.
|
||||
*
|
||||
* @since 1.0
|
||||
*
|
||||
* @return string[] Array synchronization options.
|
||||
*/
|
||||
public static function list_metas_to_sync() {
|
||||
return array(
|
||||
'taxonomies' => __( 'Taxonomies', 'polylang' ),
|
||||
'post_meta' => __( 'Custom fields', 'polylang' ),
|
||||
'comment_status' => __( 'Comment status', 'polylang' ),
|
||||
'ping_status' => __( 'Ping status', 'polylang' ),
|
||||
'sticky_posts' => __( 'Sticky posts', 'polylang' ),
|
||||
'post_date' => __( 'Published date', 'polylang' ),
|
||||
'post_format' => __( 'Post format', 'polylang' ),
|
||||
'post_parent' => __( 'Page parent', 'polylang' ),
|
||||
'_wp_page_template' => __( 'Page template', 'polylang' ),
|
||||
'menu_order' => __( 'Page order', 'polylang' ),
|
||||
'_thumbnail_id' => __( 'Featured image', 'polylang' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
406
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-metas.php
vendored
Normal file
406
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-metas.php
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class to manage the copy and synchronization of metas
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
abstract class PLL_Sync_Metas {
|
||||
/**
|
||||
* @var PLL_Model
|
||||
*/
|
||||
public $model;
|
||||
|
||||
/**
|
||||
* Meta type. Typically 'post' or 'term'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $meta_type;
|
||||
|
||||
/**
|
||||
* Stores the previous values when updating a meta.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $prev_value = array();
|
||||
|
||||
/**
|
||||
* Stores the metas to synchronize before deleting them.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $to_copy = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
$this->model = &$polylang->model;
|
||||
|
||||
add_filter( "add_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
||||
add_filter( "update_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
||||
add_filter( "delete_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
||||
|
||||
$this->add_all_meta_actions();
|
||||
|
||||
add_action( "pll_save_{$this->meta_type}", array( $this, 'save_object' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes "added_{$this->meta_type}_meta" action
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function remove_add_meta_action() {
|
||||
remove_action( "added_{$this->meta_type}_meta", array( $this, 'add_meta' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all meta synchronization actions and filters
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove_all_meta_actions() {
|
||||
$this->remove_add_meta_action();
|
||||
|
||||
remove_filter( "update_{$this->meta_type}_metadata", array( $this, 'update_metadata' ), 999 );
|
||||
remove_action( "update_{$this->meta_type}_meta", array( $this, 'update_meta' ) );
|
||||
|
||||
remove_action( "delete_{$this->meta_type}_meta", array( $this, 'store_metas_to_sync' ) );
|
||||
remove_action( "deleted_{$this->meta_type}_meta", array( $this, 'delete_meta' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds "added_{$this->meta_type}_meta" action
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restore_add_meta_action() {
|
||||
add_action( "added_{$this->meta_type}_meta", array( $this, 'add_meta' ), 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds meta synchronization actions and filters
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_all_meta_actions() {
|
||||
$this->restore_add_meta_action();
|
||||
|
||||
add_filter( "update_{$this->meta_type}_metadata", array( $this, 'update_metadata' ), 999, 5 ); // Very late in case a filter prevents the meta to be updated
|
||||
add_action( "update_{$this->meta_type}_meta", array( $this, 'update_meta' ), 10, 4 );
|
||||
|
||||
add_action( "delete_{$this->meta_type}_meta", array( $this, 'store_metas_to_sync' ), 10, 2 );
|
||||
add_action( "deleted_{$this->meta_type}_meta", array( $this, 'delete_meta' ), 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe modify ("translate") a meta value when it is copied or synchronized
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param mixed $value Meta value
|
||||
* @param string $key Meta key
|
||||
* @param int $from Id of the source
|
||||
* @param int $to Id of the target
|
||||
* @param string $lang Language of target
|
||||
* @return mixed
|
||||
*/
|
||||
protected function maybe_translate_value( $value, $key, $from, $to, $lang ) {
|
||||
/**
|
||||
* Filter a meta value before is copied or synchronized
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param mixed $value Meta value
|
||||
* @param string $key Meta key
|
||||
* @param string $lang Language of target
|
||||
* @param int $from Id of the source
|
||||
* @param int $to Id of the target
|
||||
*/
|
||||
return apply_filters( "pll_translate_{$this->meta_type}_meta", maybe_unserialize( $value ), $key, $lang, $from, $to );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom fields to copy or synchronize.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $from Id of the post from which we copy information.
|
||||
* @param int $to Id of the post to which we paste information.
|
||||
* @param string $lang Language slug.
|
||||
* @param bool $sync True if it is synchronization, false if it is a copy.
|
||||
* @return string[] List of meta keys.
|
||||
*/
|
||||
protected function get_metas_to_copy( $from, $to, $lang, $sync = false ) {
|
||||
/**
|
||||
* Filters the custom fields to copy or synchronize.
|
||||
*
|
||||
* @since 0.6
|
||||
* @since 1.9.2 The `$from`, `$to`, `$lang` parameters were added.
|
||||
*
|
||||
* @param string[] $keys List of custom fields names.
|
||||
* @param bool $sync True if it is synchronization, false if it is a copy.
|
||||
* @param int $from Id of the post from which we copy information.
|
||||
* @param int $to Id of the post to which we paste information.
|
||||
* @param string $lang Language slug.
|
||||
*/
|
||||
return array_unique( apply_filters( "pll_copy_{$this->meta_type}_metas", array(), $sync, $from, $to, $lang ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disallow modifying synchronized meta if the current user can not modify translations
|
||||
*
|
||||
* @since 2.6
|
||||
*
|
||||
* @param null|bool $check Whether to allow adding/updating/deleting metadata.
|
||||
* @param int $id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @return null|bool
|
||||
*/
|
||||
public function can_synchronize_metadata( $check, $id, $meta_key ) {
|
||||
if ( ! $this->model->{$this->meta_type}->current_user_can_synchronize( $id ) ) {
|
||||
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
if ( $tr_id != $id ) {
|
||||
$to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
||||
if ( in_array( $meta_key, $to_copy ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $check;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize added metas across translations
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $mid Meta id.
|
||||
* @param int $id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value. Must be serializable if non-scalar.
|
||||
* @return void
|
||||
*/
|
||||
public function add_meta( $mid, $id, $meta_key, $meta_value ) {
|
||||
static $avoid_recursion = false;
|
||||
|
||||
if ( ! $avoid_recursion ) {
|
||||
$avoid_recursion = true;
|
||||
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
if ( $tr_id != $id ) {
|
||||
$to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
||||
if ( in_array( $meta_key, $to_copy ) ) {
|
||||
$meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang );
|
||||
add_metadata( $this->meta_type, $tr_id, wp_slash( $meta_key ), is_object( $meta_value ) ? $meta_value : wp_slash( $meta_value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$avoid_recursion = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the previous value when updating metas
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param null|bool $r Not used
|
||||
* @param int $id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value. Must be serializable if non-scalar.
|
||||
* @param mixed $prev_value If specified, only update existing metadata entries with the specified value.
|
||||
* @return null|bool Unchanged
|
||||
*/
|
||||
public function update_metadata( $r, $id, $meta_key, $meta_value, $prev_value ) {
|
||||
if ( null === $r ) {
|
||||
$hash = md5( "$id|$meta_key|" . maybe_serialize( $meta_value ) );
|
||||
$this->prev_value[ $hash ] = $prev_value;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize updated metas across translations
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $mid Meta id.
|
||||
* @param int $id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value. Must be serializable if non-scalar.
|
||||
* @return void
|
||||
*/
|
||||
public function update_meta( $mid, $id, $meta_key, $meta_value ) {
|
||||
static $avoid_recursion = false;
|
||||
$id = (int) $id;
|
||||
|
||||
if ( ! $avoid_recursion ) {
|
||||
$avoid_recursion = true;
|
||||
$hash = md5( "$id|$meta_key|" . maybe_serialize( $meta_value ) );
|
||||
|
||||
$prev_meta = get_metadata_by_mid( $this->meta_type, $mid );
|
||||
|
||||
if ( $prev_meta ) {
|
||||
$this->remove_add_meta_action(); // We don't want to sync back the new metas
|
||||
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
if ( $tr_id != $id && in_array( $meta_key, $this->get_metas_to_copy( $id, $tr_id, $lang, true ) ) ) {
|
||||
if ( empty( $this->prev_value[ $hash ] ) || $this->prev_value[ $hash ] === $prev_meta->meta_value ) {
|
||||
$prev_value = $this->maybe_translate_value( $prev_meta->meta_value, $meta_key, $id, $tr_id, $lang );
|
||||
$meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang );
|
||||
update_metadata( $this->meta_type, $tr_id, wp_slash( $meta_key ), is_object( $meta_value ) ? $meta_value : wp_slash( $meta_value ), $prev_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->restore_add_meta_action();
|
||||
}
|
||||
|
||||
unset( $this->prev_value[ $hash ] );
|
||||
$avoid_recursion = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store metas to synchronize before deleting them.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int[] $mids Not used.
|
||||
* @param int $id Object ID.
|
||||
* @return void
|
||||
*/
|
||||
public function store_metas_to_sync( $mids, $id ) {
|
||||
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
$this->to_copy[ $id ][ $tr_id ] = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes deleted meta across translations.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int[] $mids Not used.
|
||||
* @param int $id Object ID.
|
||||
* @param string $key Meta key.
|
||||
* @param mixed $value Meta value.
|
||||
* @return void
|
||||
*/
|
||||
public function delete_meta( $mids, $id, $key, $value ) {
|
||||
static $avoid_recursion = false;
|
||||
|
||||
if ( ! $avoid_recursion ) {
|
||||
$avoid_recursion = true;
|
||||
|
||||
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
if ( $tr_id != $id ) {
|
||||
if ( in_array( $key, $this->to_copy[ $id ][ $tr_id ] ) ) {
|
||||
if ( '' !== $value && null !== $value && false !== $value ) { // Same test as WP
|
||||
$value = $this->maybe_translate_value( $value, $key, $id, $tr_id, $lang );
|
||||
}
|
||||
delete_metadata( $this->meta_type, $tr_id, wp_slash( $key ), is_object( $value ) ? $value : wp_slash( $value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$avoid_recursion = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy or synchronize metas
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $from Id of the source object
|
||||
* @param int $to Id of the target object
|
||||
* @param string $lang Language code of the target object
|
||||
* @param bool $sync Optional, defaults to true. True if it is synchronization, false if it is a copy
|
||||
* @return void
|
||||
*/
|
||||
public function copy( $from, $to, $lang, $sync = false ) {
|
||||
$this->remove_all_meta_actions();
|
||||
|
||||
$to_copy = $this->get_metas_to_copy( $from, $to, $lang, $sync );
|
||||
$metas = get_metadata( $this->meta_type, $from );
|
||||
$metas = is_array( $metas ) ? $metas : array();
|
||||
$tr_metas = get_metadata( $this->meta_type, $to );
|
||||
$tr_metas = is_array( $tr_metas ) ? $tr_metas : array();
|
||||
|
||||
foreach ( $to_copy as $key ) {
|
||||
if ( empty( $metas[ $key ] ) ) {
|
||||
if ( ! empty( $tr_metas[ $key ] ) ) {
|
||||
// If the meta key is not present in the source object, delete all values
|
||||
delete_metadata( $this->meta_type, $to, wp_slash( $key ) );
|
||||
}
|
||||
} elseif ( ! empty( $tr_metas[ $key ] ) && 1 === count( $metas[ $key ] ) && 1 === count( $tr_metas[ $key ] ) ) {
|
||||
// One custom field to update
|
||||
$value = reset( $metas[ $key ] );
|
||||
$value = maybe_unserialize( $value );
|
||||
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
||||
update_metadata( $this->meta_type, $to, wp_slash( $key ), is_object( $to_value ) ? $to_value : wp_slash( $to_value ) );
|
||||
} else {
|
||||
// Multiple custom fields, either in the source or the target
|
||||
if ( ! empty( $tr_metas[ $key ] ) ) {
|
||||
// The synchronization of multiple values custom fields is easier if we delete all metas first
|
||||
delete_metadata( $this->meta_type, $to, wp_slash( $key ) );
|
||||
}
|
||||
|
||||
foreach ( $metas[ $key ] as $value ) {
|
||||
$value = maybe_unserialize( $value );
|
||||
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
||||
add_metadata( $this->meta_type, $to, wp_slash( $key ), is_object( $to_value ) ? $to_value : wp_slash( $to_value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->add_all_meta_actions();
|
||||
}
|
||||
|
||||
/**
|
||||
* If synchronized custom fields were previously not synchronized, it is expected
|
||||
* that saving a post (or term) will synchronize them.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $object_id Id of the object being saved.
|
||||
* @param object $obj Not used.
|
||||
* @param int[] $translations The list of translations object ids.
|
||||
* @return void
|
||||
*/
|
||||
public function save_object( $object_id, $obj, $translations ) {
|
||||
foreach ( $translations as $tr_lang => $tr_id ) {
|
||||
if ( $tr_id != $object_id ) {
|
||||
$this->copy( $object_id, $tr_id, $tr_lang, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-post-metas.php
vendored
Normal file
94
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-post-metas.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* A class to manage copy and synchronization of post metas.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
class PLL_Sync_Post_Metas extends PLL_Sync_Metas {
|
||||
/**
|
||||
* Stores the plugin options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
$this->meta_type = 'post';
|
||||
|
||||
parent::__construct( $polylang );
|
||||
|
||||
$this->options = &$polylang->options;
|
||||
|
||||
add_filter( 'pll_translate_post_meta', array( $this, 'translate_thumbnail_id' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom fields to copy or synchronize.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $from Id of the post from which we copy information.
|
||||
* @param int $to Id of the post to which we paste information.
|
||||
* @param string $lang Language slug.
|
||||
* @param bool $sync True if it is synchronization, false if it is a copy.
|
||||
* @return string[] List of meta keys.
|
||||
*/
|
||||
protected function get_metas_to_copy( $from, $to, $lang, $sync = false ) {
|
||||
$keys = array();
|
||||
|
||||
// Get public meta keys ( including from translated post in case we just deleted a custom field ).
|
||||
if ( ! $sync || in_array( 'post_meta', $this->options['sync'] ) ) {
|
||||
$from_keys = (array) get_post_custom_keys( $from );
|
||||
$to_keys = (array) get_post_custom_keys( $to );
|
||||
|
||||
$keys = array_unique( array_merge( $from_keys, $to_keys ) );
|
||||
foreach ( $keys as $k => $meta_key ) {
|
||||
if ( is_protected_meta( $meta_key ) ) {
|
||||
unset( $keys[ $k ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add page template and featured image.
|
||||
foreach ( array( '_wp_page_template', '_thumbnail_id' ) as $meta ) {
|
||||
if ( ! $sync || in_array( $meta, $this->options['sync'] ) ) {
|
||||
$keys[] = $meta;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->options['media_support'] ) {
|
||||
$keys[] = '_wp_attached_file';
|
||||
$keys[] = '_wp_attachment_metadata';
|
||||
$keys[] = '_wp_attachment_backup_sizes';
|
||||
$keys[] = '_wp_attachment_is_custom_header'; // Random header image.
|
||||
}
|
||||
|
||||
/** This filter is documented in modules/sync/sync-metas.php */
|
||||
return array_unique( apply_filters( 'pll_copy_post_metas', $keys, $sync, $from, $to, $lang ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the thumbnail id.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $value Thumbnail id.
|
||||
* @param string $key Meta key.
|
||||
* @param string $lang Language code.
|
||||
* @return int
|
||||
*/
|
||||
public function translate_thumbnail_id( $value, $key, $lang ) {
|
||||
return ( $this->options['media_support'] && '_thumbnail_id' === $key && $to_value = $this->model->post->get_translation( $value, $lang ) ) ? $to_value : $value;
|
||||
}
|
||||
}
|
||||
310
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-tax.php
vendored
Normal file
310
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-tax.php
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* A class to manage the synchronization of taxonomy terms across posts translations
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
class PLL_Sync_Tax {
|
||||
|
||||
/**
|
||||
* Stores the plugin options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var PLL_Model
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
$this->model = &$polylang->model;
|
||||
$this->options = &$polylang->options;
|
||||
|
||||
add_action( 'set_object_terms', array( $this, 'set_object_terms' ), 10, 5 );
|
||||
add_action( 'pll_save_term', array( $this, 'create_term' ), 10, 3 );
|
||||
add_action( 'pre_delete_term', array( $this, 'pre_delete_term' ) );
|
||||
add_action( 'delete_term', array( $this, 'delete_term' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of taxonomies to copy or to synchronize.
|
||||
*
|
||||
* @since 1.7
|
||||
* @since 2.1 The `$from`, `$to`, `$lang` parameters were added.
|
||||
* @since 3.2 Changed visibility from protected to public.
|
||||
*
|
||||
* @param bool $sync True if it is synchronization, false if it is a copy.
|
||||
* @param int $from Id of the post from which we copy information, optional, defaults to null.
|
||||
* @param int $to Id of the post to which we paste information, optional, defaults to null.
|
||||
* @param string $lang Language slug, optional, defaults to null.
|
||||
* @return string[] List of taxonomy names.
|
||||
*/
|
||||
public function get_taxonomies_to_copy( $sync, $from = null, $to = null, $lang = null ) {
|
||||
$taxonomies = ! $sync || in_array( 'taxonomies', $this->options['sync'] ) ? $this->model->get_translated_taxonomies() : array();
|
||||
if ( ! $sync || in_array( 'post_format', $this->options['sync'] ) ) {
|
||||
$taxonomies[] = 'post_format';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the taxonomies to copy or synchronize.
|
||||
*
|
||||
* @since 1.7
|
||||
* @since 2.1 The `$from`, `$to`, `$lang` parameters were added.
|
||||
*
|
||||
* @param string[] $taxonomies List of taxonomy names.
|
||||
* @param bool $sync True if it is synchronization, false if it is a copy.
|
||||
* @param int $from Id of the post from which we copy information.
|
||||
* @param int $to Id of the post to which we paste information.
|
||||
* @param string $lang Language slug.
|
||||
*/
|
||||
return array_unique( apply_filters( 'pll_copy_taxonomies', $taxonomies, $sync, $from, $to, $lang ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* When copying or synchronizing terms, translate terms in translatable taxonomies
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $object_id Object ID.
|
||||
* @param int[] $terms List of terms ids assigned to the source post.
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
* @param string $lang Language slug.
|
||||
* @return int[] List of terms ids to assign to the target post.
|
||||
*/
|
||||
protected function maybe_translate_terms( $object_id, $terms, $taxonomy, $lang ) {
|
||||
if ( is_array( $terms ) && $this->model->is_translated_taxonomy( $taxonomy ) ) {
|
||||
$newterms = array();
|
||||
|
||||
// Convert to term ids if we got tag names
|
||||
$strings = array_map( 'is_string', $terms );
|
||||
if ( in_array( true, $strings, true ) ) {
|
||||
$terms = get_the_terms( $object_id, $taxonomy );
|
||||
$terms = wp_list_pluck( $terms, 'term_id' );
|
||||
}
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
/**
|
||||
* Filter the translated term when a post translation is created or synchronized
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $tr_term Translated term id
|
||||
* @param int $term Source term id
|
||||
* @param string $lang Language slug
|
||||
*/
|
||||
if ( $term_id = apply_filters( 'pll_maybe_translate_term', (int) $this->model->term->get_translation( $term, $lang ), $term, $lang ) ) {
|
||||
$newterms[] = (int) $term_id; // Cast is important otherwise we get 'numeric' tags
|
||||
}
|
||||
}
|
||||
|
||||
return $newterms;
|
||||
}
|
||||
|
||||
return $terms; // Empty $terms or untranslated taxonomy
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe copy taxonomy terms from one post to the other.
|
||||
*
|
||||
* @since 2.6
|
||||
*
|
||||
* @param int $object_id Source object ID.
|
||||
* @param int $tr_id Target object ID.
|
||||
* @param string $lang Target language.
|
||||
* @param array $terms An array of object terms.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param bool $append Whether to append new terms to the old terms.
|
||||
* @return void
|
||||
*/
|
||||
protected function copy_object_terms( $object_id, $tr_id, $lang, $terms, $taxonomy, $append ) {
|
||||
$to_copy = $this->get_taxonomies_to_copy( true, $object_id, $tr_id, $lang );
|
||||
|
||||
if ( in_array( $taxonomy, $to_copy ) ) {
|
||||
$newterms = $this->maybe_translate_terms( $object_id, $terms, $taxonomy, $lang );
|
||||
|
||||
// For some reasons, the user may have untranslated terms in the translation. Don't forget them.
|
||||
if ( $this->model->is_translated_taxonomy( $taxonomy ) ) {
|
||||
$tr_terms = get_the_terms( $tr_id, $taxonomy );
|
||||
if ( is_array( $tr_terms ) ) {
|
||||
foreach ( $tr_terms as $term ) {
|
||||
if ( ! $this->model->term->get_translation( $term->term_id, $this->model->post->get_language( $object_id ) ) ) {
|
||||
$newterms[] = (int) $term->term_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wp_set_object_terms( $tr_id, $newterms, $taxonomy, $append );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When assigning terms to a post, assign translated terms to the translated posts (synchronisation).
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $object_id Object ID.
|
||||
* @param array $terms An array of object terms.
|
||||
* @param int[] $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.
|
||||
* @return void
|
||||
*/
|
||||
public function set_object_terms( $object_id, $terms, $tt_ids, $taxonomy, $append ) {
|
||||
static $avoid_recursion = false;
|
||||
$taxonomy_object = get_taxonomy( $taxonomy );
|
||||
|
||||
// Make sure that the taxonomy is registered for a post type
|
||||
if ( ! $avoid_recursion && ! empty( $taxonomy_object ) && array_filter( $taxonomy_object->object_type, 'post_type_exists' ) ) {
|
||||
$avoid_recursion = true;
|
||||
|
||||
$tr_ids = $this->model->post->get_translations( $object_id );
|
||||
|
||||
foreach ( $tr_ids as $lang => $tr_id ) {
|
||||
if ( $tr_id !== $object_id ) {
|
||||
if ( $this->model->post->current_user_can_synchronize( $object_id ) ) {
|
||||
$this->copy_object_terms( $object_id, $tr_id, $lang, $terms, $taxonomy, $append );
|
||||
} else {
|
||||
// No permission to synchronize, so let's synchronize in reverse order
|
||||
$orig_lang = array_search( $object_id, $tr_ids );
|
||||
$tr_terms = get_the_terms( $tr_id, $taxonomy );
|
||||
|
||||
if ( false === $tr_terms ) {
|
||||
$tr_terms = array();
|
||||
}
|
||||
|
||||
if ( is_string( $orig_lang ) && is_array( $tr_terms ) ) {
|
||||
$tr_terms = wp_list_pluck( $tr_terms, 'term_id' );
|
||||
$this->copy_object_terms( $tr_id, $object_id, $orig_lang, $tr_terms, $taxonomy, $append );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$avoid_recursion = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy terms from one post to a translation, does not sync
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $from Id of the source post
|
||||
* @param int $to Id of the target post
|
||||
* @param string $lang Language slug
|
||||
* @return void
|
||||
*/
|
||||
public function copy( $from, $to, $lang ) {
|
||||
remove_action( 'set_object_terms', array( $this, 'set_object_terms' ) );
|
||||
|
||||
// Get taxonomies to sync for this post type
|
||||
$taxonomies = array_intersect( get_post_taxonomies( $from ), $this->get_taxonomies_to_copy( false, $from, $to, $lang ) );
|
||||
|
||||
// Update the term cache to reduce the number of queries in the loop
|
||||
update_object_term_cache( array( $from ), get_post_type( $from ) );
|
||||
|
||||
// Copy
|
||||
foreach ( $taxonomies as $tax ) {
|
||||
if ( $terms = get_the_terms( $from, $tax ) ) {
|
||||
$terms = array_map( 'intval', wp_list_pluck( $terms, 'term_id' ) );
|
||||
$newterms = $this->maybe_translate_terms( $from, $terms, $tax, $lang );
|
||||
|
||||
if ( ! empty( $newterms ) ) {
|
||||
wp_set_object_terms( $to, $newterms, $tax );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'set_object_terms', array( $this, 'set_object_terms' ), 10, 5 );
|
||||
}
|
||||
|
||||
/**
|
||||
* When creating a new term, associate it to posts having translations associated to the translated terms.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $term_id Id of the created term.
|
||||
* @param string $taxonomy Taxonomy.
|
||||
* @param int[] $translations Ids of the translations of the created term.
|
||||
* @return void
|
||||
*/
|
||||
public function create_term( $term_id, $taxonomy, $translations ) {
|
||||
if ( doing_action( 'create_term' ) && in_array( $taxonomy, $this->get_taxonomies_to_copy( true ) ) ) {
|
||||
// Get all posts associated to the translated terms
|
||||
$tr_posts = get_posts(
|
||||
array(
|
||||
'numberposts' => -1,
|
||||
'nopaging' => true,
|
||||
'post_type' => 'any',
|
||||
'post_status' => 'any',
|
||||
'fields' => 'ids',
|
||||
'tax_query' => array(
|
||||
array(
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'id',
|
||||
'terms' => array_merge( array( $term_id ), array_values( $translations ) ),
|
||||
'include_children' => false,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$lang = $this->model->term->get_language( $term_id ); // Language of the created term
|
||||
$posts = array();
|
||||
|
||||
foreach ( $tr_posts as $post_id ) {
|
||||
$post = $this->model->post->get_translation( $post_id, $lang );
|
||||
|
||||
if ( $post ) {
|
||||
$posts[] = $post;
|
||||
}
|
||||
}
|
||||
|
||||
$posts = array_unique( $posts );
|
||||
|
||||
foreach ( $posts as $post_id ) {
|
||||
if ( current_user_can( 'assign_term', $term_id ) ) {
|
||||
wp_set_object_terms( $post_id, $term_id, $taxonomy, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate the synchronization of terms before deleting a term
|
||||
* to avoid translated terms to be removed from translated posts
|
||||
*
|
||||
* @since 2.3.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function pre_delete_term() {
|
||||
remove_action( 'set_object_terms', array( $this, 'set_object_terms' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-activate the synchronization of terms after a term is deleted
|
||||
*
|
||||
* @since 2.3.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_term() {
|
||||
add_action( 'set_object_terms', array( $this, 'set_object_terms' ), 10, 5 );
|
||||
}
|
||||
}
|
||||
25
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-term-metas.php
vendored
Normal file
25
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync-term-metas.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* A class to manage the copy and synchronization of term metas.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
class PLL_Sync_Term_Metas extends PLL_Sync_Metas {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
$this->meta_type = 'term';
|
||||
|
||||
parent::__construct( $polylang );
|
||||
}
|
||||
}
|
||||
268
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync.php
vendored
Normal file
268
wp-content/plugins/polylang-pro/vendor/wpsyntex/polylang/modules/sync/sync.php
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Polylang
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manages copy and synchronization of terms and post metas on front
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
class PLL_Sync {
|
||||
/**
|
||||
* @var PLL_Sync_Tax
|
||||
*/
|
||||
public $taxonomies;
|
||||
|
||||
/**
|
||||
* @var PLL_Sync_Post_Metas
|
||||
*/
|
||||
public $post_metas;
|
||||
|
||||
/**
|
||||
* @var PLL_Sync_Term_Metas
|
||||
*/
|
||||
public $term_metas;
|
||||
|
||||
/**
|
||||
* Stores the plugin options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var PLL_Model
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 1.2
|
||||
*
|
||||
* @param object $polylang The Polylang object.
|
||||
*/
|
||||
public function __construct( &$polylang ) {
|
||||
$this->model = &$polylang->model;
|
||||
$this->options = &$polylang->options;
|
||||
|
||||
$this->taxonomies = new PLL_Sync_Tax( $polylang );
|
||||
$this->post_metas = new PLL_Sync_Post_Metas( $polylang );
|
||||
$this->term_metas = new PLL_Sync_Term_Metas( $polylang );
|
||||
|
||||
add_filter( 'wp_insert_post_parent', array( $this, 'can_sync_post_parent' ), 10, 3 );
|
||||
add_filter( 'wp_insert_post_data', array( $this, 'can_sync_post_data' ), 10, 2 );
|
||||
|
||||
add_action( 'pll_save_post', array( $this, 'pll_save_post' ), 10, 3 );
|
||||
add_action( 'created_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
||||
add_action( 'edited_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
||||
|
||||
add_action( 'pll_duplicate_term', array( $this->term_metas, 'copy' ), 10, 3 );
|
||||
|
||||
if ( $this->options['media_support'] ) {
|
||||
add_action( 'pll_translate_media', array( $this->taxonomies, 'copy' ), 10, 3 );
|
||||
add_action( 'pll_translate_media', array( $this->post_metas, 'copy' ), 10, 3 );
|
||||
add_action( 'edit_attachment', array( $this, 'edit_attachment' ) );
|
||||
}
|
||||
|
||||
add_filter( 'pre_update_option_sticky_posts', array( $this, 'sync_sticky_posts' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post fields to synchronize.
|
||||
*
|
||||
* @since 2.4
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_fields_to_sync( $post ) {
|
||||
$postarr = array();
|
||||
|
||||
foreach ( array( 'comment_status', 'ping_status', 'menu_order' ) as $property ) {
|
||||
if ( in_array( $property, $this->options['sync'] ) ) {
|
||||
$postarr[ $property ] = $post->$property;
|
||||
}
|
||||
}
|
||||
|
||||
if ( in_array( 'post_date', $this->options['sync'] ) ) {
|
||||
$postarr['post_date'] = $post->post_date;
|
||||
$postarr['post_date_gmt'] = $post->post_date_gmt;
|
||||
}
|
||||
|
||||
if ( in_array( 'post_parent', $this->options['sync'] ) ) {
|
||||
$postarr['post_parent'] = wp_get_post_parent_id( $post->ID );
|
||||
}
|
||||
|
||||
return $postarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents synchronized post parent modification if the current user hasn't enough rights
|
||||
*
|
||||
* @since 2.6
|
||||
*
|
||||
* @param int $post_parent Post parent ID
|
||||
* @param int $post_id Post ID, unused
|
||||
* @param array $postarr Array of parsed post data
|
||||
* @return int
|
||||
*/
|
||||
public function can_sync_post_parent( $post_parent, $post_id, $postarr ) {
|
||||
if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
|
||||
$tr_ids = $this->model->post->get_translations( $postarr['ID'] );
|
||||
foreach ( $tr_ids as $tr_id ) {
|
||||
if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
|
||||
$post_parent = $post->post_parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $post_parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents synchronized post data modification if the current user hasn't enough rights
|
||||
*
|
||||
* @since 2.6
|
||||
*
|
||||
* @param array $data An array of slashed post data.
|
||||
* @param array $postarr An array of sanitized, but otherwise unmodified post data.
|
||||
* @return array
|
||||
*/
|
||||
public function can_sync_post_data( $data, $postarr ) {
|
||||
if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
|
||||
foreach ( $this->model->post->get_translations( $postarr['ID'] ) as $tr_id ) {
|
||||
if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
|
||||
$to_sync = $this->get_fields_to_sync( $post );
|
||||
$data = array_merge( $data, $to_sync );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes post fields in translations.
|
||||
*
|
||||
* @since 2.4
|
||||
*
|
||||
* @param int $post_id Post id.
|
||||
* @param WP_Post $post Post object.
|
||||
* @param int[] $translations Post translations.
|
||||
* @return void
|
||||
*/
|
||||
public function pll_save_post( $post_id, $post, $translations ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $this->model->post->current_user_can_synchronize( $post_id ) ) {
|
||||
$postarr = $this->get_fields_to_sync( $post );
|
||||
|
||||
if ( ! empty( $postarr ) ) {
|
||||
foreach ( $translations as $lang => $tr_id ) {
|
||||
if ( ! $tr_id || $tr_id === $post_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tr_arr = $postarr;
|
||||
unset( $tr_arr['post_parent'] );
|
||||
|
||||
// Do not update the translation parent if the user set a parent with no translation.
|
||||
if ( isset( $postarr['post_parent'] ) ) {
|
||||
$post_parent = $postarr['post_parent'] ? $this->model->post->get_translation( $postarr['post_parent'], $lang ) : 0;
|
||||
if ( ! ( $postarr['post_parent'] && ! $post_parent ) ) {
|
||||
$tr_arr['post_parent'] = $post_parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Update all the rows at once.
|
||||
if ( ! empty( $tr_arr ) ) {
|
||||
// Don't use wp_update_post to avoid infinite loop.
|
||||
$wpdb->update( $wpdb->posts, $tr_arr, array( 'ID' => $tr_id ) );
|
||||
clean_post_cache( $tr_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize term parent in translations
|
||||
* Calling clean_term_cache *after* this is mandatory otherwise the $taxonomy_children option is not correctly updated
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int $term_id Term id.
|
||||
* @param int $tt_id Term taxonomy id, not used.
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
* @return void
|
||||
*/
|
||||
public function sync_term_parent( $term_id, $tt_id, $taxonomy ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_taxonomy_hierarchical( $taxonomy ) && $this->model->is_translated_taxonomy( $taxonomy ) ) {
|
||||
$term = get_term( $term_id );
|
||||
|
||||
if ( $term instanceof WP_Term ) {
|
||||
$translations = $this->model->term->get_translations( $term_id );
|
||||
|
||||
foreach ( $translations as $lang => $tr_id ) {
|
||||
if ( $tr_id !== $term_id ) {
|
||||
$tr_parent = $this->model->term->get_translation( $term->parent, $lang );
|
||||
$tr_term = get_term( (int) $tr_id, $taxonomy );
|
||||
|
||||
if ( $tr_term instanceof WP_Term && ! ( $term->parent && empty( $tr_parent ) ) ) {
|
||||
$wpdb->update(
|
||||
$wpdb->term_taxonomy,
|
||||
array( 'parent' => $tr_parent ? $tr_parent : 0 ),
|
||||
array( 'term_taxonomy_id' => $tr_term->term_taxonomy_id )
|
||||
);
|
||||
|
||||
clean_term_cache( $tr_id, $taxonomy ); // OK since WP 3.9.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes terms and metas in translations for media
|
||||
*
|
||||
* @since 1.8
|
||||
*
|
||||
* @param int $post_id post id
|
||||
* @return void
|
||||
*/
|
||||
public function edit_attachment( $post_id ) {
|
||||
$this->pll_save_post( $post_id, get_post( $post_id ), $this->model->post->get_translations( $post_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize sticky posts.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param int[] $value New option value.
|
||||
* @param int[] $old_value Old option value.
|
||||
* @return int[]
|
||||
*/
|
||||
public function sync_sticky_posts( $value, $old_value ) {
|
||||
if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
|
||||
// Stick post
|
||||
if ( $sticked = array_diff( $value, $old_value ) ) {
|
||||
$translations = $this->model->post->get_translations( reset( $sticked ) );
|
||||
$value = array_unique( array_merge( $value, array_values( $translations ) ) );
|
||||
}
|
||||
|
||||
// Unstick post
|
||||
if ( $unsticked = array_diff( $old_value, $value ) ) {
|
||||
$translations = $this->model->post->get_translations( reset( $unsticked ) );
|
||||
$value = array_unique( array_diff( $value, array_values( $translations ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user