File: /var/www/html/wp-content/plugins/jet-engine/includes/compatibility/packages/polylang.php
<?php
use \Jet_Engine\Modules\Data_Stores\Stores\Factory;
/**
* Polylang compatibility package
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'Jet_Engine_Polylang_Package' ) ) {
class Jet_Engine_Polylang_Package {
public function __construct() {
add_filter(
'jet-engine/listings/frontend/rendered-listing-id',
array( $this, 'set_translated_object' )
);
add_filter(
'jet-engine/component/render-id',
array( $this, 'set_translated_object' )
);
add_filter(
'jet-engine/forms/render/form-id',
array( $this, 'set_translated_object' )
);
add_filter(
'jet-engine/listings/components/query-args',
array( $this, 'ensure_all_components_registered' )
);
// Translate Admin Labels
add_filter( 'jet-engine/compatibility/translate-string', array( $this, 'translate_admin_labels' ) );
// Disable `suppress_filters` in the `get_posts` args.
add_filter( 'jet-engine/compatibility/get-posts/args', array( $this, 'disable_suppress_filters' ) );
// Relations
if ( jet_engine()->relations ) {
$this->relations_hooks();
}
//Data Stores
add_filter( 'jet-engine/data-stores/store/data', array( $this, 'set_translated_store' ), 10, 2 );
add_action( 'jet-engine/data-stores/filtered-id', array( $this, 'get_original_data_store_post_id' ), 10, 3 );
add_action( 'jet-engine/data-stores/post-count-increased', array( $this, 'update_translations_count' ), 10, 3 );
add_action( 'jet-engine/data-stores/post-count-decreased', array( $this, 'update_translations_count' ), 10, 3 );
//ensure all translated items share the same count
add_filter( 'jet-engine/data-stores/pre-get-post-count', array( $this, 'get_post_count' ), 10, 3 );
add_filter( 'pll_copy_post_metas', array( $this, 'listing_meta_to_synch' ), 99 );
}
/**
* Ensure all components are registered
*
* @see https://github.com/Crocoblock/issues-tracker/issues/15829
* @param array $args Query args
*
* @return array
*/
public function ensure_all_components_registered( $args ) {
$args['lang'] = '';
return $args;
}
/**
* Add listing meta keys to Polylang copy post metas filter
*
* @param array $keys Array of meta keys
*
* @return array
*/
public function listing_meta_to_synch( $keys ) {
$keys[] = '_entry_type';
$keys[] = '_listing_data';
$keys[] = '_listing_type';
$keys[] = '_jet_engine_listing_css';
$keys[] = '_component_props';
$keys[] = '_component_styles';
return $keys;
}
/**
* @param int $post_id Post ID
* @param string $store Store slug
* @param Factory $factory Factory instance
*/
public function get_original_data_store_post_id( $post_id, $store, $factory ) {
if ( $factory->is_user_store() || $factory->get_arg( 'is_cct' ) ) {
return $post_id;
}
switch ( $factory->get_type()->type_id() ) {
case 'user_ip':
$post_id = $this->get_original_post_id( $post_id );
break;
}
return $post_id;
}
/**
* Get original post ID (translation in default language). Returns translation ID if no original found.
*
* @param int $translation_id Post ID
* @return int Original post ID if found, given post ID otherwise
*/
public function get_original_post_id( $translation_id ) {
$default_language = pll_default_language();
$original_id = pll_get_post( $translation_id, $default_language );
if ( $original_id === $translation_id ) {
return $translation_id;
}
return $original_id;
}
/**
* @param int|false $count Pre-get post count, or false if count should not be pre-get
* @param int $post_id Store slug
* @param Factory $factory Factory instance
* @return int|false Pre-get post count, or false if count should not be pre-get
*/
public function get_post_count( $count, $post_id, $factory ) {
if ( $factory->is_user_store() || ! $factory->get_type() ) {
return $count;
}
$original_id = $this->get_original_post_id( $post_id );
if ( $original_id === $post_id || ! get_post( $original_id ) ) {
return $count;
}
return $factory->get_post_count( $original_id );
}
/**
* Sync data store post count between translations
*
* @param int $post_id Store slug
* @param int $count Post count
* @param Factory $factory Factory instance
*/
public function update_translations_count( $post_id, $count, $factory ) {
if ( $factory->is_user_store() || $factory->get_arg( 'is_cct' ) ) {
return;
}
$original_id = $this->get_original_post_id( $post_id );
if ( ( int ) $original_id !== ( int ) $post_id ) {
update_post_meta( $original_id, $factory->get_count_posts_key() . $factory->get_slug(), $count );
} else {
$translations = pll_get_post_translations( $post_id );
foreach ( $translations as $id ) {
if ( ( int ) $post_id === ( int ) $id ) {
continue;
}
update_post_meta( $id, $factory->get_count_posts_key() . $factory->get_slug(), $count );
}
}
}
/**
* Set translated object ID to show
*
* @param int|string $obj_id Object ID
*
* @return false|int|null
*/
public function set_translated_object( $obj_id ) {
if ( function_exists( 'pll_get_post' ) ) {
$translation_obj_id = pll_get_post( $obj_id );
if ( null === $translation_obj_id ) {
// the current language is not defined yet
return $obj_id;
} elseif ( false === $translation_obj_id ) {
//no translation yet
return $obj_id;
} elseif ( $translation_obj_id > 0 ) {
// return translated post id
return $translation_obj_id;
}
}
return $obj_id;
}
/**
* Set translated data store item IDs to show
*
* @param array $store Array of store items
* @param string $store_id Store ID
*
* @return array Array of store items
*/
public function set_translated_store( $store, $store_id ) {
if ( empty( $store ) ) {
return $store;
}
$store_instance = \Jet_Engine\Modules\Data_Stores\Module::instance()->stores->get_store( $store_id );
if ( $store_instance->is_user_store() || $store_instance->get_arg( 'is_cct' ) ) {
return $store;
}
$store = array_map( function( $item ) {
if ( ! is_array( $item ) ) {
$item = $this->set_translated_object( $item );
}
return $item;
}, $store );
return $store;
}
/**
* Translate Admin Labels
*
* @param string $label
* @return string
*/
public function translate_admin_labels( $label ) {
pll_register_string( 'jet-engine', $label, 'JetEngine', true );
return pll__( $label );
}
public function disable_suppress_filters( $args = array() ) {
$args['suppress_filters'] = false;
return $args;
}
public function relations_hooks() {
add_filter( 'jet-engine/relations/types/posts/get-items', array( $this, 'filtered_relations_posts_items' ), 10, 2 );
add_action( 'jet-engine/relations/types/posts/on-create', array( $this, 'set_lang_to_new_object' ), 10, 3 );
add_action( 'jet-engine/relations/types/terms/on-create', array( $this, 'set_lang_to_new_object' ), 10, 3 );
$auto_sync_relations = apply_filters( 'jet-engine/compatibility/polylang/auto-sync-relations', true );
if ( $auto_sync_relations && is_admin() ) {
add_filter( 'wp_insert_post', array( $this, 'sync_relations_on_add_translation_post' ) );
add_action( 'jet-engine/relation/update/after', array( $this, 'sync_relations_on_update' ), 10, 4 );
add_action( 'jet-engine/relation/delete/after', array( $this, 'sync_relations_on_delete' ), 10, 4 );
}
}
public function filtered_relations_posts_items( $items, $post_type ) {
if ( ! pll_is_translated_post_type( $post_type ) ) {
return $items;
}
$current_lang = pll_current_language();
$items = array_filter( $items, function ( $item ) use ( $current_lang ) {
$lang = pll_get_post_language( $item['value'] );
return $current_lang === $lang;
} );
return $items;
}
public function set_lang_to_new_object( $object_id, $data, $object_type ) {
if ( is_wp_error( $object_id ) ) {
return;
}
// phpcs:disable WordPress.Security.NonceVerification
if ( empty( $_REQUEST['relatedObjectType'] ) ) {
return;
}
// phpcs:enable WordPress.Security.NonceVerification
$refer_lang = false;
// phpcs:disable
if ( ! empty( $_REQUEST['pll_post_id'] ) ) {
$refer_lang = pll_get_post_language( absint( $_REQUEST['pll_post_id'] ) );
} elseif ( ! empty( $_REQUEST['pll_term_id'] ) ) {
$refer_lang = pll_get_term_language( absint( $_REQUEST['pll_term_id'] ) );
}
// phpcs:enable
if ( empty( $refer_lang ) ) {
return;
}
// phpcs:disable WordPress.Security.NonceVerification
switch ( $_REQUEST['relatedObjectType'] ) {
case 'posts':
if ( ! pll_is_translated_post_type( $object_type ) ) {
return;
}
$obj_lang = pll_get_post_language( $object_id );
if ( $obj_lang !== $refer_lang ) {
pll_set_post_language( $object_id, $refer_lang );
}
break;
case 'terms':
if ( ! pll_is_translated_taxonomy( $object_type ) ) {
return;
}
$obj_lang = pll_get_term_language( $object_id );
if ( $obj_lang !== $refer_lang ) {
pll_set_term_language( $object_id, $refer_lang );
}
break;
}
// php:enable WordPress.Security.NonceVerification
}
public function sync_relations_on_add_translation_post( $post_id ) {
// phpcs:disable WordPress.Security.NonceVerification
if ( ! isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) ) {
return;
}
if ( 'post-new.php' !== $GLOBALS['pagenow'] ) {
return;
}
if ( ! pll_is_translated_post_type( get_post_type( $post_id ) ) ) {
return;
}
$from_post_id = absint( wp_unslash( $_GET['from_post'] ) );
$lang = PLL()->model->get_language( sanitize_key( wp_unslash( $_GET['new_lang'] ) ) );
$this->sync_relations_items( $from_post_id, $post_id, $lang->slug );
// phpcs:enable WordPress.Security.NonceVerification
}
public function sync_relations_items( $original_id, $translated_id, $lang ) {
$post_type = get_post_type( $original_id );
$rel_type = jet_engine()->relations->types_helper->type_name_by_parts( 'posts', $post_type );
$active_relations = jet_engine()->relations->get_active_relations();
$relations = array_filter( $active_relations, function( $relation ) use ( $rel_type ) {
if ( $rel_type === $relation->get_args( 'parent_object' ) ) {
return true;
}
if ( $rel_type === $relation->get_args( 'child_object' ) ) {
return true;
}
return false;
} );
if ( empty( $relations ) ) {
return;
}
foreach ( $relations as $rel_id => $relation ) {
$is_parent = $rel_type === $relation->get_args( 'parent_object' );
$meta_fields = $relation->get_args( 'meta_fields' );
if ( $is_parent ) {
$rel_items = $relation->get_children( $original_id, 'ids' );
$obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'child_object' ) );
$is_single = $relation->is_single_child();
} else {
$rel_items = $relation->get_parents( $original_id, 'ids' );
$obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'parent_object' ) );
$is_single = $relation->is_single_parent();
}
$rel_items = array_reverse( $rel_items );
$obj_type = $obj_data[0];
$obj_sub_type = $obj_data[1];
foreach ( $rel_items as $rel_item ) {
switch ( $obj_type ) {
case 'posts':
$new_rel_item = pll_get_post( $rel_item, $lang );
$new_rel_item = ! empty( $new_rel_item ) ? $new_rel_item : $rel_item;
break;
case 'terms':
$new_rel_item = pll_get_term( $rel_item, $lang );
$new_rel_item = ! empty( $new_rel_item ) ? $new_rel_item : $rel_item;
break;
default:
$new_rel_item = $rel_item;
}
if ( $is_single && $new_rel_item == $rel_item ) {
continue;
}
if ( $is_parent ) {
$relation->update( $translated_id, $new_rel_item );
if ( empty( $meta_fields ) ) {
continue;
}
$meta = $relation->get_all_meta( $original_id, $rel_item );
$new_meta = $relation->get_all_meta( $translated_id, $new_rel_item );
$new_meta = array_merge( $meta, $new_meta );
if ( ! empty( $new_meta ) ) {
$relation->update_all_meta( $new_meta, $translated_id, $new_rel_item );
}
} else {
$relation->update( $new_rel_item, $translated_id );
if ( empty( $meta_fields ) ) {
continue;
}
$meta = $relation->get_all_meta( $rel_item, $original_id );
$new_meta = $relation->get_all_meta( $new_rel_item, $translated_id );
$new_meta = array_merge( $meta, $new_meta );
if ( ! empty( $new_meta ) ) {
$relation->update_all_meta( $meta, $new_rel_item, $translated_id );
}
}
}
}
}
public function sync_relations_on_update( $parent_id, $child_id, $item_id, $relation ) {
if ( empty( $item_id ) ) {
return;
}
$parent_obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'parent_object' ) );
$child_obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'child_object' ) );
$support_types = array( 'posts', 'terms' );
if ( ! in_array( $parent_obj_data[0], $support_types ) || ! in_array( $child_obj_data[0], $support_types ) ) {
return;
}
if ( ! $this->is_item_translated( $parent_obj_data[1], $parent_obj_data[0] ) ||
! $this->is_item_translated( $child_obj_data[1], $child_obj_data[0] )
) {
return;
}
$parent_translations = $this->get_item_translations( $parent_id, $parent_obj_data[0] );
$child_translations = $this->get_item_translations( $child_id, $child_obj_data[0] );
remove_action( 'jet-engine/relation/update/after', array( $this, 'sync_relations_on_update' ) );
foreach ( $parent_translations as $lang => $translation_id ) {
if ( $translation_id == $parent_id ) {
continue;
}
if ( ! isset( $child_translations[ $lang ] ) ) {
continue;
}
$child_trans_id = $child_translations[ $lang ];
$relation->update( $translation_id, $child_trans_id );
}
add_action( 'jet-engine/relation/update/after', array( $this, 'sync_relations_on_update' ), 10, 4 );
}
public function sync_relations_on_delete( $parent_id, $child_id, $clear_meta, $relation ) {
$parent_obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'parent_object' ) );
$child_obj_data = jet_engine()->relations->types_helper->type_parts_by_name( $relation->get_args( 'child_object' ) );
$support_types = array( 'posts', 'terms' );
if ( ! in_array( $parent_obj_data[0], $support_types ) || ! in_array( $child_obj_data[0], $support_types ) ) {
return;
}
if ( ! $this->is_item_translated( $parent_obj_data[1], $parent_obj_data[0] ) ||
! $this->is_item_translated( $child_obj_data[1], $child_obj_data[0] )
) {
return;
}
$parent_translations = $this->get_item_translations( $parent_id, $parent_obj_data[0] );
$child_translations = $this->get_item_translations( $child_id, $child_obj_data[0] );
remove_action( 'jet-engine/relation/delete/after', array( $this, 'sync_relations_on_delete' ) );
foreach ( $parent_translations as $lang => $translation_id ) {
if ( $translation_id == $parent_id ) {
continue;
}
if ( ! isset( $child_translations[ $lang ] ) ) {
continue;
}
$rel_items = $relation->get_children( $translation_id, 'ids' );
$child_trans_id = $child_translations[ $lang ];
if ( ! in_array( $child_trans_id, $rel_items ) ) {
continue;
}
$relation->delete_rows( $translation_id, $child_trans_id );
}
add_action( 'jet-engine/relation/delete/after', array( $this, 'sync_relations_on_delete' ), 10, 4 );
}
public function is_item_translated( $type = null, $obj_type = null ) {
switch ( $obj_type ) {
case 'posts':
$is_translated = pll_is_translated_post_type( $type );
break;
case 'terms':
$is_translated = pll_is_translated_taxonomy( $type );
break;
default:
$is_translated = false;
}
return $is_translated;
}
public function get_item_translations( $id, $obj_type = null ) {
switch ( $obj_type ) {
case 'posts':
$translations = pll_get_post_translations( $id );
break;
case 'terms':
$translations = pll_get_term_translations( $id );
break;
default:
$translations = array();
}
return $translations;
}
}
}
new Jet_Engine_Polylang_Package();