first commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\DisplayAsTranslated;
|
||||
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Str;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\LIB\WP\Hooks;
|
||||
use WPML\LIB\WP\Post;
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\spreadArgs;
|
||||
|
||||
class CheckRedirect implements \IWPML_Frontend_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
Hooks::onFilter( 'wpml_is_redirected', 10, 3 )
|
||||
->then( spreadArgs( [ self::class, 'checkForSlugTranslation' ] ) );
|
||||
}
|
||||
|
||||
public static function checkForSlugTranslation( $redirect, $post_id, $q ) {
|
||||
global $sitepress;
|
||||
|
||||
if ( $redirect ) {
|
||||
$postType = Post::getType( $post_id );
|
||||
if (
|
||||
make( \WPML_ST_Post_Slug_Translation_Settings::class )->is_translated( $postType )
|
||||
&& $sitepress->is_display_as_translated_post_type( $postType )
|
||||
) {
|
||||
$adjustLanguageDetails = Obj::set(
|
||||
Obj::lensProp( 'language_code' ), $sitepress->get_current_language()
|
||||
);
|
||||
|
||||
add_filter( 'wpml_st_post_type_link_filter_language_details', $adjustLanguageDetails );
|
||||
|
||||
if ( \WPML_Query_Parser::is_permalink_part_of_request(
|
||||
get_permalink( $post_id ),
|
||||
explode( '?', $_SERVER['REQUEST_URI'] )[0] )
|
||||
) {
|
||||
$redirect = false;
|
||||
}
|
||||
|
||||
remove_filter( 'wpml_st_post_type_link_filter_language_details', $adjustLanguageDetails );
|
||||
}
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\SlugTranslation\Hooks;
|
||||
|
||||
class Hooks {
|
||||
/** @var \WPML_Rewrite_Rule_Filter_Factory */
|
||||
private $factory;
|
||||
|
||||
/** @var \WPML_ST_Slug_Translation_Settings $slug_translation_settings */
|
||||
private $slug_translation_settings;
|
||||
|
||||
/** @var array|null */
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @param \WPML_Rewrite_Rule_Filter_Factory $factory
|
||||
* @param \WPML_ST_Slug_Translation_Settings $slug_translation_settings
|
||||
*/
|
||||
public function __construct(
|
||||
\WPML_Rewrite_Rule_Filter_Factory $factory,
|
||||
\WPML_ST_Slug_Translation_Settings $slug_translation_settings
|
||||
) {
|
||||
$this->factory = $factory;
|
||||
$this->slug_translation_settings = $slug_translation_settings;
|
||||
}
|
||||
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'init', [ $this, 'init' ], \WPML_Slug_Translation_Factory::INIT_PRIORITY );
|
||||
}
|
||||
|
||||
public function init() {
|
||||
if ( $this->slug_translation_settings->is_enabled() ) {
|
||||
add_filter( 'option_rewrite_rules', [ $this, 'filter' ], 1, 1 );
|
||||
add_filter( 'flush_rewrite_rules_hard', [ $this, 'flushRewriteRulesHard' ] );
|
||||
add_action( 'registered_post_type', [ $this, 'clearCache' ] );
|
||||
add_action( 'registered_taxonomy', [ $this, 'clearCache' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $value
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter( $value ) {
|
||||
if ( empty( $value ) || apply_filters( 'wpml_st_disable_rewrite_rules', false ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( ! $this->cache ) {
|
||||
$this->cache = $this->factory->create()->rewrite_rules_filter( $value );
|
||||
}
|
||||
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
public function clearCache() {
|
||||
$this->cache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $hard
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function flushRewriteRulesHard( $hard ) {
|
||||
$this->clearCache();
|
||||
|
||||
return $hard;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\SlugTranslation\Hooks;
|
||||
|
||||
use WPML_Rewrite_Rule_Filter_Factory;
|
||||
use WPML_ST_Slug_Translation_Settings_Factory;
|
||||
|
||||
class HooksFactory {
|
||||
/**
|
||||
* We need a static property because there could be many instances of HooksFactory class but we need to guarantee
|
||||
* there is only a single instance of Hooks
|
||||
*
|
||||
* @var Hooks
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @return Hooks
|
||||
*/
|
||||
public function create() {
|
||||
if ( ! self::$instance ) {
|
||||
$settings_factory = new WPML_ST_Slug_Translation_Settings_Factory();
|
||||
$global_settings = $settings_factory->create();
|
||||
|
||||
self::$instance = new Hooks( new WPML_Rewrite_Rule_Filter_Factory(), $global_settings );
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
class WPML_Rewrite_Rule_Filter implements IWPML_ST_Rewrite_Rule_Filter {
|
||||
/** @var WPML_ST_Slug_Translation_Custom_Types_Repository[] */
|
||||
private $custom_types_repositories;
|
||||
|
||||
/** @var WPML_ST_Slug_New_Match_Finder */
|
||||
private $new_match_finder;
|
||||
|
||||
/**
|
||||
* @param WPML_ST_Slug_Translation_Custom_Types_Repository[] $custom_types_repositories
|
||||
* @param WPML_ST_Slug_New_Match_Finder $new_match_finder
|
||||
*/
|
||||
public function __construct( array $custom_types_repositories, WPML_ST_Slug_New_Match_Finder $new_match_finder ) {
|
||||
$this->custom_types_repositories = $custom_types_repositories;
|
||||
$this->new_match_finder = $new_match_finder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array|false|null $rules
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function rewrite_rules_filter( $rules ) {
|
||||
if ( ! is_array( $rules ) && empty( $rules ) ) {
|
||||
return $rules;
|
||||
}
|
||||
|
||||
$custom_types = $this->get_custom_types();
|
||||
if ( ! $custom_types ) {
|
||||
return $rules;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ( $rules as $match => $query ) {
|
||||
$new_match = $this->new_match_finder->get( $match, $custom_types );
|
||||
$result[ $new_match->get_value() ] = $query;
|
||||
|
||||
if ( $new_match->should_preserve_original() ) {
|
||||
$result[ $match ] = $query;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function get_custom_types() {
|
||||
if ( empty( $this->custom_types_repositories ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$types = array();
|
||||
foreach ( $this->custom_types_repositories as $repository ) {
|
||||
$types[] = $repository->get();
|
||||
}
|
||||
|
||||
return call_user_func_array( 'array_merge', $types );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
<?php
|
||||
|
||||
abstract class WPML_Slug_Translation_Records {
|
||||
|
||||
const CONTEXT_DEFAULT = 'default';
|
||||
const CONTEXT_WORDPRESS = 'WordPress';
|
||||
|
||||
/** @var wpdb $wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/** @var WPML_WP_Cache_Factory $cache_factory*/
|
||||
private $cache_factory;
|
||||
|
||||
public function __construct( wpdb $wpdb, WPML_WP_Cache_Factory $cache_factory ) {
|
||||
$this->wpdb = $wpdb;
|
||||
$this->cache_factory = $cache_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return WPML_ST_Slug
|
||||
*/
|
||||
public function get_slug( $type ) {
|
||||
$cache_item = $this->cache_factory->create_cache_item( $this->get_cache_group(), $type );
|
||||
|
||||
if ( ! $cache_item->exists() ) {
|
||||
$slug = new WPML_ST_Slug();
|
||||
|
||||
/** @var \stdClass $original */
|
||||
$original = $this->wpdb->get_row(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT id, value, language, context, name
|
||||
FROM {$this->wpdb->prefix}icl_strings
|
||||
WHERE name = %s
|
||||
AND (context = %s OR context = %s)",
|
||||
$this->get_string_name( $type ),
|
||||
self::CONTEXT_DEFAULT,
|
||||
self::CONTEXT_WORDPRESS
|
||||
)
|
||||
);
|
||||
|
||||
if ( $original ) {
|
||||
$slug->set_lang_data( $original );
|
||||
|
||||
/** @var array<\stdClass> $translations */
|
||||
$translations = $this->wpdb->get_results(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT value, language, status
|
||||
FROM {$this->wpdb->prefix}icl_string_translations
|
||||
WHERE string_id = %d
|
||||
AND value <> ''
|
||||
AND language <> %s",
|
||||
$original->id,
|
||||
$original->language
|
||||
)
|
||||
);
|
||||
|
||||
if ( $translations ) {
|
||||
foreach ( $translations as $translation ) {
|
||||
$slug->set_lang_data( $translation );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cache_item->set( $slug );
|
||||
|
||||
}
|
||||
|
||||
return $cache_item->get();
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
private function get_cache_group() {
|
||||
return __CLASS__ . '::' . $this->get_element_type();
|
||||
}
|
||||
|
||||
private function flush_cache() {
|
||||
$cache_group = $this->cache_factory->create_cache_group( $this->get_cache_group() );
|
||||
$cache_group->flush_group_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $lang
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function get_translation( $type, $lang ) {
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
if ( $slug->is_translation_complete( $lang ) ) {
|
||||
return $slug->get_value( $lang );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $lang
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function get_original( $type, $lang = '' ) {
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
if ( ! $lang || $slug->get_original_lang() === $lang ) {
|
||||
return $slug->get_original_value();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_slug_id( $type ) {
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
if ( $slug->get_original_id() ) {
|
||||
return $slug->get_original_id();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $slug
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function register_slug( $type, $slug ) {
|
||||
$string_id = icl_register_string(
|
||||
self::CONTEXT_WORDPRESS,
|
||||
$this->get_string_name( $type ),
|
||||
$slug
|
||||
);
|
||||
|
||||
$this->flush_cache();
|
||||
|
||||
return $string_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $slug
|
||||
*/
|
||||
public function update_original_slug( $type, $slug ) {
|
||||
$this->wpdb->update(
|
||||
$this->wpdb->prefix . 'icl_strings',
|
||||
array( 'value' => $slug ),
|
||||
array( 'name' => $this->get_string_name( $type ) )
|
||||
);
|
||||
|
||||
$this->flush_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return null|stdClass
|
||||
*/
|
||||
public function get_original_slug_and_lang( $type ) {
|
||||
$original_slug_and_lang = null;
|
||||
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
if ( $slug->get_original_id() ) {
|
||||
$original_slug_and_lang = (object) array(
|
||||
'value' => $slug->get_original_value(),
|
||||
'language' => $slug->get_original_lang(),
|
||||
);
|
||||
}
|
||||
|
||||
return $original_slug_and_lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
* @param bool $only_status_complete
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_element_slug_translations( $type, $only_status_complete = true ) {
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
$rows = array();
|
||||
|
||||
foreach ( $slug->get_language_codes() as $lang ) {
|
||||
if ( $slug->get_original_lang() === $lang
|
||||
|| ( $only_status_complete && ! $slug->is_translation_complete( $lang ) )
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rows[] = (object) array(
|
||||
'value' => $slug->get_value( $lang ),
|
||||
'language' => $lang,
|
||||
'status' => $slug->get_status( $lang ),
|
||||
);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param array $types
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all_slug_translations( $types ) {
|
||||
$rows = array();
|
||||
|
||||
foreach ( $types as $type ) {
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
foreach ( $slug->get_language_codes() as $lang ) {
|
||||
if ( $slug->get_original_lang() !== $lang ) {
|
||||
$rows[] = (object) array(
|
||||
'value' => $slug->get_value( $lang ),
|
||||
'name' => $slug->get_name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `get_slug` instead.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_slug_translation_languages( $type ) {
|
||||
$languages = array();
|
||||
$slug = $this->get_slug( $type );
|
||||
|
||||
foreach ( $slug->get_language_codes() as $lang ) {
|
||||
if ( $slug->is_translation_complete( $lang ) ) {
|
||||
$languages[] = $lang;
|
||||
}
|
||||
}
|
||||
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use `WPML_ST_String` only for updating the values in the DB
|
||||
* because it does not have any caching feature.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return null|WPML_ST_String
|
||||
*/
|
||||
public function get_slug_string( $type ) {
|
||||
$string_id = $this->get_slug_id( $type );
|
||||
|
||||
if ( $string_id ) {
|
||||
return new WPML_ST_String( $string_id, $this->wpdb );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function get_string_name( $slug );
|
||||
|
||||
/** @return string */
|
||||
abstract protected function get_element_type();
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
<?php
|
||||
|
||||
class WPML_Slug_Translation implements IWPML_Action {
|
||||
|
||||
const STRING_DOMAIN = 'WordPress';
|
||||
|
||||
/** @var array $post_link_cache */
|
||||
private $post_link_cache = array();
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_Slug_Translation_Records_Factory $slug_records_factory */
|
||||
private $slug_records_factory;
|
||||
|
||||
/** @var WPML_ST_Term_Link_Filter $term_link_filter */
|
||||
private $term_link_filter;
|
||||
|
||||
/** @var WPML_Get_LS_Languages_Status $ls_languages_status */
|
||||
private $ls_languages_status;
|
||||
|
||||
/** @var WPML_ST_Slug_Translation_Settings $slug_translation_settings */
|
||||
private $slug_translation_settings;
|
||||
|
||||
private $ignore_post_type_link = false;
|
||||
|
||||
public function __construct(
|
||||
SitePress $sitepress,
|
||||
WPML_Slug_Translation_Records_Factory $slug_records_factory,
|
||||
WPML_Get_LS_Languages_Status $ls_language_status,
|
||||
WPML_ST_Term_Link_Filter $term_link_filter,
|
||||
WPML_ST_Slug_Translation_Settings $slug_translation_settings
|
||||
) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->slug_records_factory = $slug_records_factory;
|
||||
$this->ls_languages_status = $ls_language_status;
|
||||
$this->term_link_filter = $term_link_filter;
|
||||
$this->slug_translation_settings = $slug_translation_settings;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'init', array( $this, 'init' ), WPML_Slug_Translation_Factory::INIT_PRIORITY );
|
||||
}
|
||||
|
||||
public function init() {
|
||||
$this->migrate_global_enabled_setting();
|
||||
|
||||
if ( $this->slug_translation_settings->is_enabled() ) {
|
||||
add_filter( 'post_type_link', array( $this, 'post_type_link_filter' ), apply_filters( 'wpml_post_type_link_priority', 1 ), 4 );
|
||||
add_filter( 'pre_term_link', array( $this->term_link_filter, 'replace_slug_in_termlink' ), 1, 2 ); // high priority
|
||||
add_filter( 'edit_post', array( $this, 'clear_post_link_cache' ), 1, 2 );
|
||||
add_filter( 'query_vars', array( $this, 'add_cpt_names' ), 1, 2 );
|
||||
add_filter( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ), - 1000, 2 );
|
||||
}
|
||||
|
||||
if ( is_admin() ) {
|
||||
add_action( 'icl_ajx_custom_call', array( $this, 'gui_save_options' ), 10, 2 );
|
||||
add_action( 'wp_loaded', array( $this, 'maybe_migrate_string_name' ), 10, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.8.0, use the class `WPML_Post_Slug_Translation_Records` instead.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public static function get_slug_by_type( $type ) {
|
||||
$slug_records_factory = new WPML_Slug_Translation_Records_Factory();
|
||||
$slug_records = $slug_records_factory->create( WPML_Slug_Translation_Factory::POST );
|
||||
|
||||
return $slug_records->get_original( $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only for CPT
|
||||
*
|
||||
* @deprecated use `WPML_ST_Slug::filter_value` directly of the filter hook `wpml_get_translated_slug`
|
||||
*
|
||||
* @param string $slug_value
|
||||
* @param string $post_type
|
||||
* @param string|bool $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_translated_slug( $slug_value, $post_type, $language = false ) {
|
||||
if ( $post_type ) {
|
||||
$language = $language ? $language : $this->sitepress->get_current_language();
|
||||
$slug = $this->slug_records_factory->create( WPML_Slug_Translation_Factory::POST )
|
||||
->get_slug( $post_type );
|
||||
|
||||
return $slug->filter_value( $slug_value, $language );
|
||||
}
|
||||
|
||||
return $slug_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $value
|
||||
*
|
||||
* @return array
|
||||
* @deprecated Use WPML\ST\SlugTranslation\Hooks\Hooks::filter
|
||||
*/
|
||||
public static function rewrite_rules_filter( $value ) {
|
||||
return ( new \WPML\ST\SlugTranslation\Hooks\HooksFactory() )->create()->filter( $value );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $post_link
|
||||
* @param WP_Post $post
|
||||
* @param bool $leavename
|
||||
* @param bool $sample
|
||||
*
|
||||
* @return mixed|string|WP_Error
|
||||
*/
|
||||
public function post_type_link_filter( $post_link, $post, $leavename, $sample ) {
|
||||
|
||||
if ( $this->ignore_post_type_link ) {
|
||||
return $post_link;
|
||||
}
|
||||
|
||||
if ( ! $this->sitepress->is_translated_post_type( $post->post_type )
|
||||
|| ! ( $ld = $this->sitepress->get_element_language_details( $post->ID, 'post_' . $post->post_type ) )
|
||||
) {
|
||||
return $post_link;
|
||||
}
|
||||
|
||||
$ld = apply_filters( 'wpml_st_post_type_link_filter_language_details', $ld );
|
||||
|
||||
$cache_key = $leavename . '#' . $sample;
|
||||
$cache_key .= $this->ls_languages_status->is_getting_ls_languages() ? 'yes' : 'no';
|
||||
$cache_key .= $ld->language_code;
|
||||
$blog_id = get_current_blog_id();
|
||||
if ( isset( $this->post_link_cache[ $blog_id ][ $post->ID ][ $cache_key ] ) ) {
|
||||
$post_link = $this->post_link_cache[ $blog_id ][ $post->ID ][ $cache_key ];
|
||||
} else {
|
||||
$slug_settings = $this->sitepress->get_setting( 'posts_slug_translation' );
|
||||
$slug_settings = ! empty( $slug_settings['types'][ $post->post_type ] ) ? $slug_settings['types'][ $post->post_type ] : null;
|
||||
if ( (bool) $slug_settings === true ) {
|
||||
|
||||
$post_type_obj = get_post_type_object( $post->post_type );
|
||||
$slug_this = isset( $post_type_obj->rewrite['slug'] ) ? trim( $post_type_obj->rewrite['slug'], '/' ) : false;
|
||||
$slug_real = $this->get_translated_slug( $slug_this, $post->post_type, $ld->language_code );
|
||||
|
||||
if ( empty( $slug_real ) || empty( $slug_this ) || $slug_this == $slug_real ) {
|
||||
return $post_link;
|
||||
}
|
||||
|
||||
global $wp_rewrite;
|
||||
|
||||
if ( isset( $wp_rewrite->extra_permastructs[ $post->post_type ] ) ) {
|
||||
$struct_original = $wp_rewrite->extra_permastructs[ $post->post_type ]['struct'];
|
||||
|
||||
/**
|
||||
* This hook allows to filter the slug we want to search and replace
|
||||
* in the permalink structure. This is required for 3rd party
|
||||
* plugins replacing the original slug with a placeholder.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $slug_this The original slug.
|
||||
* @param string $post_link The initial link.
|
||||
* @param WP_Post $post The post.
|
||||
* @param bool $leavename Whether to keep the post name.
|
||||
* @param bool $sample Is it a sample permalink.
|
||||
*/
|
||||
$slug_this = apply_filters( 'wpml_st_post_type_link_filter_original_slug', $slug_this, $post_link, $post, $leavename, $sample );
|
||||
|
||||
$lslash = false !== strpos( $struct_original, '/' . $slug_this ) ? '/' : '';
|
||||
$wp_rewrite->extra_permastructs[ $post->post_type ]['struct'] = preg_replace(
|
||||
'@' . $lslash . $slug_this . '/@',
|
||||
$lslash . $slug_real . '/',
|
||||
$struct_original
|
||||
);
|
||||
$this->ignore_post_type_link = true;
|
||||
$post_link = get_post_permalink( $post->ID, $leavename, $sample );
|
||||
$this->ignore_post_type_link = false;
|
||||
$wp_rewrite->extra_permastructs[ $post->post_type ]['struct'] = $struct_original;
|
||||
} else {
|
||||
$post_link = str_replace( $slug_this . '=', $slug_real . '=', $post_link );
|
||||
}
|
||||
}
|
||||
$this->post_link_cache[ $blog_id ][ $post->ID ][ $cache_key ] = $post_link;
|
||||
}
|
||||
|
||||
return $post_link;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_ID
|
||||
* @param \WP_Post $post
|
||||
*/
|
||||
public function clear_post_link_cache( $post_ID, $post ) {
|
||||
$blog_id = get_current_blog_id();
|
||||
unset( $this->post_link_cache[ $blog_id ][ $post_ID ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function get_all_post_slug_translations() {
|
||||
$slug_translations = array();
|
||||
$post_slug_translation_settings = $this->sitepress->get_setting( 'posts_slug_translation' );
|
||||
|
||||
if ( isset( $post_slug_translation_settings['types'] ) ) {
|
||||
$types = $post_slug_translation_settings['types'];
|
||||
$cache_key = 'WPML_Slug_Translation::get_all_slug_translations' . md5( json_encode( $types ) );
|
||||
|
||||
$slug_translations = wp_cache_get( $cache_key );
|
||||
|
||||
if ( ! is_array( $slug_translations ) ) {
|
||||
$slug_translations = array();
|
||||
$types_to_fetch = array();
|
||||
|
||||
foreach ( $types as $type => $state ) {
|
||||
if ( $state ) {
|
||||
$types_to_fetch[] = str_replace( '%', '%%', $type );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $types_to_fetch ) {
|
||||
$data = $this->slug_records_factory
|
||||
->create( WPML_Slug_Translation_Factory::POST )
|
||||
->get_all_slug_translations( $types_to_fetch );
|
||||
|
||||
foreach ( $data as $row ) {
|
||||
foreach ( $types_to_fetch as $type ) {
|
||||
if ( preg_match( '#\s' . $type . '$#', $row->name ) === 1 ) {
|
||||
$slug_translations[ $row->value ] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wp_cache_set( $cache_key, $slug_translations );
|
||||
}
|
||||
}
|
||||
|
||||
return $slug_translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all translated custom post type slugs as valid query variables in addition to their original values
|
||||
*
|
||||
* @param array $qvars
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_cpt_names( $qvars ) {
|
||||
$all_slugs_translations = array_keys( $this->get_all_post_slug_translations() );
|
||||
$qvars = array_merge( $qvars, $all_slugs_translations );
|
||||
|
||||
return $qvars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_Query $query
|
||||
*
|
||||
* @return WP_Query
|
||||
*/
|
||||
public function filter_pre_get_posts( $query ) {
|
||||
/** Do not alter the query if it has already resolved the post ID */
|
||||
if ( ! empty( $query->query_vars['p'] ) ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$all_slugs_translations = $this->get_all_post_slug_translations();
|
||||
|
||||
foreach ( $query->query as $slug => $post_name ) {
|
||||
if ( isset( $all_slugs_translations[ $slug ] ) ) {
|
||||
$new_slug = isset( $all_slugs_translations[ $slug ] ) ? $all_slugs_translations[ $slug ] : $slug;
|
||||
unset( $query->query[ $slug ] );
|
||||
$query->query[ $new_slug ] = $post_name;
|
||||
$query->query['name'] = $post_name;
|
||||
$query->query['post_type'] = $new_slug;
|
||||
unset( $query->query_vars[ $slug ] );
|
||||
$query->query_vars[ $new_slug ] = $post_name;
|
||||
$query->query_vars['name'] = $post_name;
|
||||
$query->query_vars['post_type'] = $new_slug;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
*/
|
||||
public static function gui_save_options( $action ) {
|
||||
switch ( $action ) {
|
||||
case 'icl_slug_translation':
|
||||
global $sitepress;
|
||||
$is_enabled = intval( ! empty( $_POST['icl_slug_translation_on'] ) );
|
||||
$settings = new WPML_ST_Post_Slug_Translation_Settings( $sitepress );
|
||||
$settings->set_enabled( $is_enabled );
|
||||
echo '1|' . $is_enabled;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitize( $slug ) {
|
||||
// we need to preserve the %
|
||||
$slug = str_replace( '%', '%45', $slug );
|
||||
$slug = sanitize_title_with_dashes( $slug );
|
||||
$slug = str_replace( '%45', '%', $slug );
|
||||
|
||||
/**
|
||||
* Filters the sanitized post type or taxonomy slug translation
|
||||
*
|
||||
* @since 2.10.0
|
||||
*
|
||||
* @param string $slug
|
||||
*/
|
||||
return apply_filters( 'wpml_st_slug_translation_sanitize', $slug );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.8.0, use the class `WPML_Post_Slug_Translation_Records` instead.
|
||||
*/
|
||||
public static function register_string_for_slug( $post_type, $slug ) {
|
||||
return icl_register_string( self::STRING_DOMAIN, 'URL slug: ' . $post_type, $slug );
|
||||
}
|
||||
|
||||
public function maybe_migrate_string_name() {
|
||||
global $wpdb;
|
||||
|
||||
$slug_settings = $this->sitepress->get_setting( 'posts_slug_translation' );
|
||||
|
||||
if ( ! isset( $slug_settings['string_name_migrated'] ) ) {
|
||||
|
||||
$queryable_post_types = get_post_types( array( 'publicly_queryable' => true ) );
|
||||
|
||||
foreach ( $queryable_post_types as $type ) {
|
||||
$post_type_obj = get_post_type_object( $type );
|
||||
if ( null === $post_type_obj || ! isset( $post_type_obj->rewrite['slug'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$slug = trim( $post_type_obj->rewrite['slug'], '/' );
|
||||
if ( $slug ) {
|
||||
// First check if we should migrate from the old format URL slug: slug
|
||||
$string_id = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT id
|
||||
FROM {$wpdb->prefix}icl_strings
|
||||
WHERE name = %s AND value = %s",
|
||||
'URL slug: ' . $slug,
|
||||
$slug
|
||||
)
|
||||
);
|
||||
if ( $string_id ) {
|
||||
// migrate it to URL slug: post_type
|
||||
|
||||
$st_update['name'] = 'URL slug: ' . $type;
|
||||
$wpdb->update( $wpdb->prefix . 'icl_strings', $st_update, array( 'id' => $string_id ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$slug_settings['string_name_migrated'] = true;
|
||||
$this->sitepress->set_setting( 'posts_slug_translation', $slug_settings, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move global on/off setting to its own option WPML_ST_Slug_Translation_Settings::KEY_ENABLED_GLOBALLY
|
||||
*/
|
||||
private function migrate_global_enabled_setting() {
|
||||
$enabled = get_option( WPML_ST_Slug_Translation_Settings::KEY_ENABLED_GLOBALLY );
|
||||
|
||||
if ( false === $enabled ) {
|
||||
$old_setting = $this->sitepress->get_setting( WPML_ST_Post_Slug_Translation_Settings::KEY_IN_SITEPRESS_SETTINGS );
|
||||
|
||||
if ( array_key_exists( 'on', $old_setting ) ) {
|
||||
$enabled = (int) $old_setting['on'];
|
||||
} else {
|
||||
$enabled = 0;
|
||||
}
|
||||
|
||||
update_option( WPML_ST_Slug_Translation_Settings::KEY_ENABLED_GLOBALLY, $enabled );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Custom_Type_Factory {
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_Slug_Translation_Records $slug_records */
|
||||
private $slug_records;
|
||||
|
||||
/** @var WPML_ST_Slug_Translations */
|
||||
private $slug_translations;
|
||||
|
||||
|
||||
public function __construct(
|
||||
SitePress $sitepress,
|
||||
WPML_Slug_Translation_Records $slug_records,
|
||||
WPML_ST_Slug_Translations $slug_translations
|
||||
) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->slug_records = $slug_records;
|
||||
$this->slug_translations = $slug_translations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param bool $display_as_translated
|
||||
*
|
||||
* @return WPML_ST_Slug_Custom_Type
|
||||
*/
|
||||
public function create( $name, $display_as_translated ) {
|
||||
$slug = $this->slug_records->get_slug( $name );
|
||||
|
||||
return new WPML_ST_Slug_Custom_Type(
|
||||
$name,
|
||||
$display_as_translated,
|
||||
$slug->get_original_value(),
|
||||
$this->slug_translations->get( $slug, $display_as_translated )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* It may represent custom posts or custom taxonomies
|
||||
*/
|
||||
class WPML_ST_Slug_Custom_Type {
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/** @var bool */
|
||||
private $display_as_translated;
|
||||
|
||||
/** @var string */
|
||||
private $slug;
|
||||
|
||||
/** @var string */
|
||||
private $slug_translation;
|
||||
|
||||
/**
|
||||
* WPML_ST_Slug_Custom_Type constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $display_as_translated
|
||||
* @param bool $slug
|
||||
* @param bool $slug_translation
|
||||
*/
|
||||
public function __construct( $name, $display_as_translated, $slug, $slug_translation ) {
|
||||
$this->name = $name;
|
||||
$this->display_as_translated = $display_as_translated;
|
||||
$this->slug = $slug;
|
||||
$this->slug_translation = $slug_translation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_display_as_translated() {
|
||||
return $this->display_as_translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_slug() {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_slug_translation() {
|
||||
return $this->slug_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_using_tags() {
|
||||
$pattern = '#%([^/]+)%#';
|
||||
|
||||
return preg_match( $pattern, $this->slug ) || preg_match( $pattern, $this->slug_translation );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
interface WPML_ST_Slug_Translation_Custom_Types_Repository {
|
||||
/**
|
||||
* @return WPML_ST_Slug_Custom_Type[]
|
||||
*/
|
||||
public function get();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_Post_Custom_Types_Repository implements WPML_ST_Slug_Translation_Custom_Types_Repository {
|
||||
/** @var SitePress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_ST_Slug_Custom_Type_Factory */
|
||||
private $custom_type_factory;
|
||||
|
||||
/** @var array */
|
||||
private $post_slug_translation_settings;
|
||||
|
||||
public function __construct( SitePress $sitepress, WPML_ST_Slug_Custom_Type_Factory $custom_type_factory ) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->custom_type_factory = $custom_type_factory;
|
||||
}
|
||||
|
||||
|
||||
public function get() {
|
||||
return array_map(
|
||||
array( $this, 'build_object' ),
|
||||
array_values( array_filter(
|
||||
get_post_types( array( 'publicly_queryable' => true ) ),
|
||||
array( $this, 'filter' )
|
||||
) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function filter( $type ) {
|
||||
$post_slug_translation_settings = $this->get_post_slug_translation_settings();
|
||||
|
||||
return isset( $post_slug_translation_settings['types'][ $type ] )
|
||||
&& $post_slug_translation_settings['types'][ $type ]
|
||||
&& $this->sitepress->is_translated_post_type( $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return WPML_ST_Slug_Custom_Type
|
||||
*/
|
||||
private function build_object( $type ) {
|
||||
return $this->custom_type_factory->create( $type, $this->is_display_as_translated( $type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function get_post_slug_translation_settings() {
|
||||
if ( null === $this->post_slug_translation_settings ) {
|
||||
$this->post_slug_translation_settings = $this->sitepress->get_setting( 'posts_slug_translation', array() );
|
||||
}
|
||||
|
||||
return $this->post_slug_translation_settings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_display_as_translated( $type ) {
|
||||
return $this->sitepress->is_display_as_translated_post_type( $type );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_Taxonomy_Custom_Types_Repository implements WPML_ST_Slug_Translation_Custom_Types_Repository {
|
||||
/** @var SitePress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_ST_Slug_Custom_Type_Factory */
|
||||
private $custom_type_factory;
|
||||
|
||||
/** @var WPML_ST_Tax_Slug_Translation_Settings $settings */
|
||||
private $settings_repository;
|
||||
|
||||
/** @var array */
|
||||
private $settings;
|
||||
|
||||
public function __construct(
|
||||
SitePress $sitepress,
|
||||
WPML_ST_Slug_Custom_Type_Factory $custom_type_factory,
|
||||
WPML_ST_Tax_Slug_Translation_Settings $settings_repository
|
||||
) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->custom_type_factory = $custom_type_factory;
|
||||
$this->settings_repository = $settings_repository;
|
||||
}
|
||||
|
||||
|
||||
public function get() {
|
||||
return array_map(
|
||||
array( $this, 'build_object' ),
|
||||
array_values( array_filter(
|
||||
get_taxonomies( array( 'publicly_queryable' => true ) ),
|
||||
array( $this, 'filter' )
|
||||
) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function filter( $type ) {
|
||||
$settings = $this->get_taxonomy_slug_translation_settings();
|
||||
|
||||
return isset( $settings[ $type ] )
|
||||
&& $settings[ $type ]
|
||||
&& $this->sitepress->is_translated_taxonomy( $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return WPML_ST_Slug_Custom_Type
|
||||
*/
|
||||
private function build_object( $type ) {
|
||||
return $this->custom_type_factory->create( $type, $this->is_display_as_translated( $type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function get_taxonomy_slug_translation_settings() {
|
||||
if ( null === $this->settings ) {
|
||||
$this->settings = $this->settings_repository->get_types();
|
||||
}
|
||||
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_display_as_translated( $type ) {
|
||||
return $this->sitepress->is_display_as_translated_taxonomy( $type );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translations {
|
||||
/** @var SitePress */
|
||||
private $sitepress;
|
||||
|
||||
public function __construct( SitePress $sitepress ) {
|
||||
$this->sitepress = $sitepress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_ST_Slug $slug
|
||||
* @param bool $display_as_translated_mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get( $slug, $display_as_translated_mode ) {
|
||||
$current_language = $this->sitepress->get_current_language();
|
||||
$default_language = $this->sitepress->get_default_language();
|
||||
$slug_translation = $this->get_slug_translation_to_lang( $slug, $current_language );
|
||||
|
||||
if ( ! $slug_translation ) {
|
||||
// check original
|
||||
$slug_translation = $slug->get_original_value();
|
||||
}
|
||||
|
||||
if ( $display_as_translated_mode && ( ! $slug_translation || $slug_translation === $slug->get_original_value() ) && $default_language != 'en' ) {
|
||||
$slug_translation = $this->get_slug_translation_to_lang( $slug, $default_language );
|
||||
}
|
||||
|
||||
return trim( $slug_translation, '/' );
|
||||
}
|
||||
|
||||
private function get_slug_translation_to_lang( WPML_ST_Slug $slug, $lang ) {
|
||||
if ( $slug->is_translation_complete( $lang ) ) {
|
||||
return $slug->get_value( $lang );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_ST_Rewrite_Rule_Filter {
|
||||
|
||||
public function rewrite_rules_filter( $rules );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
use WPML\FP\Fns;
|
||||
use function WPML\FP\partial;
|
||||
|
||||
class WPML_ST_Slug_New_Match_Finder {
|
||||
/**
|
||||
* @param string $match
|
||||
* @param WPML_ST_Slug_Custom_Type[] $custom_types
|
||||
*
|
||||
* @return WPML_ST_Slug_New_Match
|
||||
*/
|
||||
public function get( $match, array $custom_types ) {
|
||||
$best_match = $this->find_the_best_match( $match, $this->map_to_new_matches( $match, $custom_types ) );
|
||||
if ( ! $best_match ) {
|
||||
$best_match = new WPML_ST_Slug_New_Match( $match, false );
|
||||
}
|
||||
|
||||
return $best_match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $match
|
||||
* @param WPML_ST_Slug_Custom_Type[] $custom_types
|
||||
*
|
||||
* @return WPML_ST_Slug_New_Match[]
|
||||
*/
|
||||
private function map_to_new_matches( $match, array $custom_types ) {
|
||||
return Fns::map( partial( [ $this, 'find_match_of_type' ], $match ), $custom_types );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $match
|
||||
* @param WPML_ST_Slug_Custom_Type $custom_type
|
||||
*
|
||||
* @return WPML_ST_Slug_New_Match
|
||||
*/
|
||||
public function find_match_of_type( $match, WPML_ST_Slug_Custom_Type $custom_type ) {
|
||||
if ( $custom_type->is_using_tags() ) {
|
||||
$slug = $this->filter_slug_using_tag( $custom_type->get_slug() );
|
||||
$slug_translation = $this->filter_slug_using_tag( $custom_type->get_slug_translation() );
|
||||
|
||||
$new_match = $this->adjust_match( $match, $slug, $slug_translation );
|
||||
|
||||
$result = new WPML_ST_Slug_New_Match( $new_match, $custom_type->is_display_as_translated() );
|
||||
} else {
|
||||
$new_match = $this->adjust_match( $match, $custom_type->get_slug(), $custom_type->get_slug_translation() );
|
||||
$result = new WPML_ST_Slug_New_Match(
|
||||
$new_match,
|
||||
$match !== $new_match && $custom_type->is_display_as_translated()
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function filter_slug_using_tag( $slug ) {
|
||||
if ( preg_match( '#%([^/]+)%#', $slug ) ) {
|
||||
$slug = preg_replace( '#%[^/]+%#', '.+?', $slug );
|
||||
}
|
||||
|
||||
if ( preg_match( '#\.\+\?#', $slug ) ) {
|
||||
$slug = preg_replace( '#\.\+\?#', '(.+?)', $slug );
|
||||
}
|
||||
|
||||
return $slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $match
|
||||
* @param string $slug
|
||||
* @param string $slug_translation
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function adjust_match( $match, $slug, $slug_translation ) {
|
||||
if (
|
||||
! empty( $slug_translation )
|
||||
&& preg_match( '#^[^/]*/?\(?' . preg_quote( $slug ) . '\)?/#', $match )
|
||||
&& $slug !== $slug_translation
|
||||
) {
|
||||
$replace = function( $match ) use ( $slug, $slug_translation ) {
|
||||
return str_replace( $slug, $slug_translation, $match[0]);
|
||||
};
|
||||
$match = preg_replace_callback( '#^\(?' . preg_quote( addslashes( $slug ) ) . '\)?/#', $replace, $match );
|
||||
}
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* The best is that which differs the most from the original
|
||||
*
|
||||
* @param string $match
|
||||
* @param WPML_ST_Slug_New_Match[] $new_matches
|
||||
*
|
||||
* @return WPML_ST_Slug_New_Match
|
||||
*/
|
||||
private function find_the_best_match( $match, $new_matches ) {
|
||||
$similarities = array();
|
||||
foreach ( $new_matches as $new_match ) {
|
||||
$percent = 0;
|
||||
similar_text( $match, $new_match->get_value(), $percent );
|
||||
// Multiply $percent by 100 because floats as array keys are truncated to integers
|
||||
// This will allow for fractional percentages.
|
||||
$similarities[ intval( $percent * 100 ) ] = $new_match;
|
||||
}
|
||||
|
||||
ksort( $similarities );
|
||||
|
||||
return reset( $similarities );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_New_Match {
|
||||
/** @var string */
|
||||
private $value;
|
||||
|
||||
/** @var bool */
|
||||
private $preserve_original;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param bool $preserve_original
|
||||
*/
|
||||
public function __construct( $value, $preserve_original ) {
|
||||
$this->value = $value;
|
||||
$this->preserve_original = $preserve_original;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_value() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function should_preserve_original() {
|
||||
return $this->preserve_original;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class WPML_Post_Slug_Translation_Records extends WPML_Slug_Translation_Records {
|
||||
|
||||
const STRING_NAME = 'URL slug: %s';
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_string_name( $slug ) {
|
||||
return sprintf( self::STRING_NAME, $slug );
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
protected function get_element_type() {
|
||||
return 'post';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @todo: Move these settings to an independent option
|
||||
* like WPML_ST_Tax_Slug_Translation_Settings::OPTION_NAME
|
||||
*/
|
||||
class WPML_ST_Post_Slug_Translation_Settings extends WPML_ST_Slug_Translation_Settings {
|
||||
|
||||
const KEY_IN_SITEPRESS_SETTINGS = 'posts_slug_translation';
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
private $settings;
|
||||
|
||||
public function __construct( SitePress $sitepress ) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->settings = $sitepress->get_setting( self::KEY_IN_SITEPRESS_SETTINGS, array( ) );
|
||||
}
|
||||
|
||||
/** @param bool $enabled */
|
||||
public function set_enabled( $enabled ) {
|
||||
parent::set_enabled( $enabled );
|
||||
|
||||
/**
|
||||
* Backward compatibility with 3rd part plugins
|
||||
* The `on` key has been replaced by an independent option
|
||||
* WPML_ST_Slug_Translation_Settings::KEY_ENABLED_GLOBALLY
|
||||
*/
|
||||
$this->settings['on'] = (int) $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_translated( $type ) {
|
||||
return ! empty( $this->settings['types'][ $type ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param bool $is_enabled
|
||||
*/
|
||||
public function set_type( $type, $is_enabled ) {
|
||||
if ( $is_enabled ) {
|
||||
$this->settings['types'][ $type ] = 1;
|
||||
} else {
|
||||
unset( $this->settings['types'][ $type ] );
|
||||
}
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$this->sitepress->set_setting( self::KEY_IN_SITEPRESS_SETTINGS, $this->settings, true );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Tax_Slug_Translation_Settings extends WPML_ST_Slug_Translation_Settings {
|
||||
|
||||
const OPTION_NAME = 'wpml_tax_slug_translation_settings';
|
||||
|
||||
/** @var array $types */
|
||||
private $types = array();
|
||||
|
||||
public function __construct() {
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/** @param array $types */
|
||||
public function set_types( array $types ) {
|
||||
$this->types = $types;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function get_types() {
|
||||
return $this->types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy_name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_translated( $taxonomy_name ) {
|
||||
return array_key_exists( $taxonomy_name, $this->types ) && (bool) $this->types[ $taxonomy_name ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy_name
|
||||
* @param bool $is_enabled
|
||||
*/
|
||||
public function set_type( $taxonomy_name, $is_enabled ) {
|
||||
$this->types[ $taxonomy_name ] = (int) $is_enabled;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
private function get_properties() {
|
||||
return get_object_vars( $this );
|
||||
}
|
||||
|
||||
public function init() {
|
||||
$options = get_option( self::OPTION_NAME, array() );
|
||||
|
||||
foreach ( $this->get_properties() as $name => $value ) {
|
||||
if ( array_key_exists( $name, $options ) ) {
|
||||
call_user_func( array( $this, 'set_' . $name ), $options[ $name ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function save() {
|
||||
update_option( self::OPTION_NAME, $this->get_properties() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Term_Link_Filter {
|
||||
|
||||
const CACHE_GROUP = 'WPML_ST_Term_Link_Filter::replace_base_in_permalink_structure';
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_Tax_Slug_Translation_Records $slug_records */
|
||||
private $slug_records;
|
||||
|
||||
/** @var WPML_WP_Cache_Factory $cache_factory */
|
||||
private $cache_factory;
|
||||
|
||||
/** @var WPML_ST_Tax_Slug_Translation_Settings $tax_settings */
|
||||
private $tax_settings;
|
||||
|
||||
public function __construct(
|
||||
WPML_Tax_Slug_Translation_Records $slug_records,
|
||||
SitePress $sitepress,
|
||||
WPML_WP_Cache_Factory $cache_factory,
|
||||
WPML_ST_Tax_Slug_Translation_Settings $tax_settings
|
||||
) {
|
||||
$this->slug_records = $slug_records;
|
||||
$this->sitepress = $sitepress;
|
||||
$this->cache_factory = $cache_factory;
|
||||
$this->tax_settings = $tax_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the permalink structure for a terms before token replacement occurs
|
||||
* with the hook filter `pre_term_link` available since WP 4.9.0
|
||||
*
|
||||
* @see get_term_link
|
||||
*
|
||||
* @param false|string $termlink
|
||||
* @param WP_Term $term
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function replace_slug_in_termlink( $termlink, $term ) {
|
||||
if ( ! $termlink || ! $this->sitepress->is_translated_taxonomy( $term->taxonomy ) ) {
|
||||
return $termlink;
|
||||
}
|
||||
|
||||
$term_lang = $this->sitepress->get_language_for_element( $term->term_taxonomy_id, 'tax_' . $term->taxonomy );
|
||||
$cache_key = $termlink . $term_lang;
|
||||
$cache_item = $this->cache_factory->create_cache_item( self::CACHE_GROUP, $cache_key );
|
||||
|
||||
if ( $cache_item->exists() ) {
|
||||
$termlink = $cache_item->get();
|
||||
} else {
|
||||
if ( $this->tax_settings->is_translated( $term->taxonomy ) ) {
|
||||
$original_slug = $this->slug_records->get_original( $term->taxonomy );
|
||||
$translated_slug = $this->slug_records->get_translation( $term->taxonomy, $term_lang );
|
||||
|
||||
if ( $original_slug && $translated_slug && $original_slug !== $translated_slug ) {
|
||||
$termlink = $this->replace_slug( $termlink, $original_slug, $translated_slug );
|
||||
}
|
||||
}
|
||||
|
||||
$cache_item->set( $termlink );
|
||||
}
|
||||
|
||||
return $termlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $termlink
|
||||
* @param string $original_slug
|
||||
* @param string $translated_slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replace_slug( $termlink, $original_slug, $translated_slug ) {
|
||||
if ( preg_match( '#/?' . preg_quote( $original_slug ) . '/#', $termlink ) ) {
|
||||
$termlink = preg_replace(
|
||||
'#^(/?)(' . addslashes( $original_slug ) . ')/#',
|
||||
"$1$translated_slug/",
|
||||
$termlink
|
||||
);
|
||||
}
|
||||
|
||||
return $termlink;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class WPML_Tax_Slug_Translation_Records extends WPML_Slug_Translation_Records {
|
||||
|
||||
const STRING_NAME = 'URL %s tax slug';
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_string_name( $slug ) {
|
||||
return sprintf( self::STRING_NAME, $slug );
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
protected function get_element_type() {
|
||||
return 'taxonomy';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
class WPML_Rewrite_Rule_Filter_Factory {
|
||||
|
||||
/**
|
||||
* @param SitePress|null $sitepress
|
||||
*
|
||||
* @return WPML_Rewrite_Rule_Filter
|
||||
*/
|
||||
public function create( $sitepress = null ) {
|
||||
if ( ! $sitepress ) {
|
||||
global $sitepress;
|
||||
}
|
||||
|
||||
$slug_records_factory = new WPML_Slug_Translation_Records_Factory();
|
||||
$slug_translations = new WPML_ST_Slug_Translations( $sitepress );
|
||||
|
||||
$custom_types_repositories = array(
|
||||
new WPML_ST_Slug_Translation_Post_Custom_Types_Repository(
|
||||
$sitepress,
|
||||
new WPML_ST_Slug_Custom_Type_Factory(
|
||||
$sitepress,
|
||||
$slug_records_factory->create( WPML_Slug_Translation_Factory::POST ),
|
||||
$slug_translations
|
||||
)
|
||||
),
|
||||
new WPML_ST_Slug_Translation_Taxonomy_Custom_Types_Repository(
|
||||
$sitepress,
|
||||
new WPML_ST_Slug_Custom_Type_Factory(
|
||||
$sitepress,
|
||||
$slug_records_factory->create( WPML_Slug_Translation_Factory::TAX ),
|
||||
$slug_translations
|
||||
),
|
||||
new WPML_ST_Tax_Slug_Translation_Settings()
|
||||
),
|
||||
);
|
||||
|
||||
return new WPML_Rewrite_Rule_Filter( $custom_types_repositories, new WPML_ST_Slug_New_Match_Finder() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
class WPML_Slug_Translation_Factory implements IWPML_Frontend_Action_Loader, IWPML_Backend_Action_Loader, IWPML_AJAX_Action_Loader {
|
||||
|
||||
const POST = 'post';
|
||||
const TAX = 'taxonomy';
|
||||
|
||||
const INIT_PRIORITY = -1000;
|
||||
|
||||
public function create() {
|
||||
global $sitepress;
|
||||
|
||||
$hooks = array();
|
||||
|
||||
$records_factory = new WPML_Slug_Translation_Records_Factory();
|
||||
$settings_factory = new WPML_ST_Slug_Translation_Settings_Factory();
|
||||
|
||||
$post_records = $records_factory->create( self::POST );
|
||||
$tax_records = $records_factory->create( self::TAX );
|
||||
|
||||
$global_settings = $settings_factory->create();
|
||||
$post_settings = $settings_factory->create( self::POST );
|
||||
$tax_settings = $settings_factory->create( self::TAX );
|
||||
|
||||
$term_link_filter = new WPML_ST_Term_Link_Filter( $tax_records, $sitepress, new WPML_WP_Cache_Factory(), $tax_settings );
|
||||
|
||||
$hooks['legacy_class'] = new WPML_Slug_Translation(
|
||||
$sitepress,
|
||||
$records_factory,
|
||||
WPML_Get_LS_Languages_Status::get_instance(),
|
||||
$term_link_filter,
|
||||
$global_settings
|
||||
);
|
||||
|
||||
$hooks['rewrite_rules'] = ( new \WPML\ST\SlugTranslation\Hooks\HooksFactory() )->create();
|
||||
|
||||
if ( is_admin() ) {
|
||||
$hooks['ui_save_post'] = new WPML_ST_Slug_Translation_UI_Save(
|
||||
$post_settings,
|
||||
$post_records,
|
||||
$sitepress,
|
||||
new WPML_WP_Post_Type(),
|
||||
WPML_ST_Slug_Translation_UI_Save::ACTION_HOOK_FOR_POST
|
||||
);
|
||||
$hooks['ui_save_tax'] = new WPML_ST_Slug_Translation_UI_Save(
|
||||
$tax_settings,
|
||||
$tax_records,
|
||||
$sitepress,
|
||||
new WPML_WP_Taxonomy(),
|
||||
WPML_ST_Slug_Translation_UI_Save::ACTION_HOOK_FOR_TAX
|
||||
);
|
||||
|
||||
if ( $global_settings->is_enabled() ) {
|
||||
$hooks['sync_strings'] = new WPML_ST_Slug_Translation_Strings_Sync(
|
||||
$records_factory,
|
||||
$settings_factory
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$hooks['public-api'] = new WPML_ST_Slug_Translation_API(
|
||||
$records_factory,
|
||||
$settings_factory,
|
||||
$sitepress,
|
||||
new WPML_WP_API()
|
||||
);
|
||||
|
||||
return $hooks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
class WPML_Slug_Translation_Records_Factory {
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return WPML_Post_Slug_Translation_Records|WPML_Tax_Slug_Translation_Records
|
||||
*/
|
||||
public function create( $type ) {
|
||||
/** @var wpdb */
|
||||
global $wpdb;
|
||||
|
||||
$cache_factory = new WPML_WP_Cache_Factory();
|
||||
|
||||
if ( WPML_Slug_Translation_Factory::POST === $type ) {
|
||||
return new WPML_Post_Slug_Translation_Records( $wpdb, $cache_factory );
|
||||
} elseif ( WPML_Slug_Translation_Factory::TAX === $type ) {
|
||||
return new WPML_Tax_Slug_Translation_Records( $wpdb, $cache_factory );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Element_Slug_Translation_UI_Model {
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_ST_Slug_Translation_Settings $settings */
|
||||
private $settings;
|
||||
|
||||
/** @var WPML_Slug_Translation_Records $slug_records */
|
||||
private $slug_records;
|
||||
|
||||
/** @var WPML_Element_Sync_Settings $sync_settings */
|
||||
private $sync_settings;
|
||||
|
||||
/** @var WPML_Simple_Language_Selector $lang_selector */
|
||||
private $lang_selector;
|
||||
|
||||
public function __construct(
|
||||
SitePress $sitepress,
|
||||
WPML_ST_Slug_Translation_Settings $settings,
|
||||
WPML_Slug_Translation_Records $slug_records,
|
||||
WPML_Element_Sync_Settings $sync_settings,
|
||||
WPML_Simple_Language_Selector $lang_selector
|
||||
) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->settings = $settings;
|
||||
$this->slug_records = $slug_records;
|
||||
$this->sync_settings = $sync_settings;
|
||||
$this->lang_selector = $lang_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type_name
|
||||
* @param WP_Post_Type|WP_Taxonomy $custom_type
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
public function get( $type_name, $custom_type ) {
|
||||
$has_rewrite_slug = isset( $custom_type->rewrite['slug'] ) && $custom_type->rewrite['slug'];
|
||||
$is_translated_mode = $this->sync_settings->is_sync( $type_name );
|
||||
$is_slug_translated = $this->settings->is_translated( $type_name );
|
||||
|
||||
if ( ! $has_rewrite_slug || ! $this->settings->is_enabled() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$original_slug_and_lang = $this->get_original_slug_and_lang( $type_name, $custom_type );
|
||||
$slug_translations = $this->get_translations( $type_name );
|
||||
|
||||
$model = array(
|
||||
'strings' => array(
|
||||
'toggle_slugs_table' => sprintf( __( 'Set different slugs in different languages for %s.', 'wpml-string-translation' ), $custom_type->labels->name ),
|
||||
'slug_status_incomplete' => __( "Not marked as 'complete'. Press 'Save' to enable.", 'wpml-string-translation' ),
|
||||
'original_label' => __( '(original)', 'wpml-string-translation' ),
|
||||
),
|
||||
'css_class_wrapper' => $is_translated_mode ? '' : 'hidden',
|
||||
'type_name' => $type_name,
|
||||
'slugs' => array(),
|
||||
'has_missing_translations_message' => '',
|
||||
);
|
||||
|
||||
if ( $is_slug_translated && ! $original_slug_and_lang->is_registered ) {
|
||||
$model['has_missing_translations_message'] = sprintf(
|
||||
esc_html__(
|
||||
'%s slugs are set to be translated, but they are missing their translation',
|
||||
'wpml-string-translation'
|
||||
),
|
||||
$custom_type->labels->name
|
||||
);
|
||||
}
|
||||
|
||||
$languages = $this->get_languages( $original_slug_and_lang->language );
|
||||
|
||||
foreach ( $languages as $code => $language ) {
|
||||
$slug = new stdClass();
|
||||
$slug->value = ! empty( $slug_translations[ $code ]['value'] )
|
||||
? $slug_translations[ $code ]['value'] : '';
|
||||
$slug->placeholder = $original_slug_and_lang->value . ' @' . $code;
|
||||
$slug->input_id = sprintf( 'translate_slugs[%s][langs][%s]', $type_name, $code );
|
||||
$slug->language_flag = $this->sitepress->get_flag_img( $code );
|
||||
$slug->language_name = $language['display_name'];
|
||||
$slug->language_code = $code;
|
||||
$slug->is_original = $code == $original_slug_and_lang->language;
|
||||
$slug->status_is_incomplete = isset( $slug_translations[ $code ] )
|
||||
&& ICL_TM_COMPLETE != $slug_translations[ $code ]['status'];
|
||||
|
||||
if ( $slug->is_original ) {
|
||||
$slug->value = $original_slug_and_lang->value;
|
||||
$slug->language_selector = $this->lang_selector->render(
|
||||
array(
|
||||
'name' => 'translate_slugs[' . $type_name . '][original]',
|
||||
'selected' => $code,
|
||||
'show_please_select' => false,
|
||||
'echo' => false,
|
||||
'class' => 'js-translate-slug-original',
|
||||
'data' => array( 'slug' => $slug->value ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$model['slugs'][ $slug->language_code ] = $slug;
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type_name
|
||||
* @param WP_Post_Type|WP_Taxonomy $custom_type
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
private function get_original_slug_and_lang( $type_name, $custom_type ) {
|
||||
$original_slug_and_lang = $this->slug_records->get_original_slug_and_lang( $type_name );
|
||||
|
||||
if ( $original_slug_and_lang ) {
|
||||
$original_slug_and_lang->is_registered = true;
|
||||
} else {
|
||||
$original_slug_and_lang = new stdClass();
|
||||
$original_slug_and_lang->is_registered = false;
|
||||
$original_slug_and_lang->value = isset( $custom_type->slug )
|
||||
? $custom_type->slug : $custom_type->rewrite['slug'];
|
||||
$original_slug_and_lang->language = $this->sitepress->get_default_language();
|
||||
}
|
||||
|
||||
return $original_slug_and_lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_translations( $type_name ) {
|
||||
$translations = array();
|
||||
$rows = $this->slug_records->get_element_slug_translations( $type_name, false );
|
||||
|
||||
foreach( $rows as $row ) {
|
||||
$translations[ $row->language ] = array(
|
||||
'value' => $row->value,
|
||||
'status' => $row->status
|
||||
);
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string_lang
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_languages( $string_lang ) {
|
||||
$languages = $this->sitepress->get_active_languages();
|
||||
|
||||
if ( ! in_array( $string_lang, array_keys( $languages ) ) ) {
|
||||
$all_languages = $this->sitepress->get_languages();
|
||||
$languages[ $string_lang ] = $all_languages[ $string_lang ];
|
||||
}
|
||||
|
||||
return $languages;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Element_Slug_Translation_UI {
|
||||
|
||||
const TEMPLATE_FILE = 'slug-translation-ui.twig';
|
||||
|
||||
/** @var WPML_ST_Element_Slug_Translation_UI_Model $model */
|
||||
private $model;
|
||||
|
||||
/** @var IWPML_Template_Service $template_service */
|
||||
private $template_service;
|
||||
|
||||
public function __construct(
|
||||
WPML_ST_Element_Slug_Translation_UI_Model $model,
|
||||
IWPML_Template_Service $template_service
|
||||
) {
|
||||
$this->model = $model;
|
||||
$this->template_service = $template_service;
|
||||
}
|
||||
|
||||
/** @return WPML_ST_Element_Slug_Translation_UI */
|
||||
public function init() {
|
||||
wp_enqueue_script(
|
||||
'wpml-custom-type-slug-ui',
|
||||
WPML_ST_URL . '/res/js/wpml-custom-type-slug-ui.js',
|
||||
array( 'jquery' ),
|
||||
WPML_ST_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type_name
|
||||
* @param WP_Post_Type|WP_Taxonomy $custom_type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render( $type_name, $custom_type ) {
|
||||
$model = $this->model->get( $type_name, $custom_type );
|
||||
|
||||
if ( ! $model ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( ! empty( $model['has_missing_translations_message'] ) ) {
|
||||
ICL_AdminNotifier::displayInstantMessage(
|
||||
$model['has_missing_translations_message'],
|
||||
'error',
|
||||
'below-h2',
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
return $this->template_service->show( $model, self::TEMPLATE_FILE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_API implements IWPML_Action {
|
||||
|
||||
/**
|
||||
* The section indexes are hardcoded in `sitepress-multilingual-cms/menu/_custom_types_translation.php`
|
||||
*/
|
||||
const SECTION_INDEX_POST = 7;
|
||||
const SECTION_INDEX_TAX = 8;
|
||||
|
||||
/** @var WPML_Slug_Translation_Records_Factory $records_factory */
|
||||
private $records_factory;
|
||||
|
||||
/** @var WPML_ST_Slug_Translation_Settings_Factory $settings_factory */
|
||||
private $settings_factory;
|
||||
|
||||
/** @var IWPML_Current_Language $current_language */
|
||||
private $current_language;
|
||||
|
||||
/** @var WPML_WP_API $wp_api */
|
||||
private $wp_api;
|
||||
|
||||
public function __construct(
|
||||
WPML_Slug_Translation_Records_Factory $records_factory,
|
||||
WPML_ST_Slug_Translation_Settings_Factory $settings_factory,
|
||||
IWPML_Current_Language $current_language,
|
||||
WPML_WP_API $wp_api
|
||||
) {
|
||||
$this->records_factory = $records_factory;
|
||||
$this->settings_factory = $settings_factory;
|
||||
$this->current_language = $current_language;
|
||||
$this->wp_api = $wp_api;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'init', array( $this, 'init' ), WPML_Slug_Translation_Factory::INIT_PRIORITY );
|
||||
}
|
||||
|
||||
public function init() {
|
||||
if ( $this->settings_factory->create()->is_enabled() ) {
|
||||
add_filter( 'wpml_get_translated_slug', array( $this, 'get_translated_slug_filter' ), 1, 4 );
|
||||
add_filter(
|
||||
'wpml_get_slug_translation_languages',
|
||||
array( $this, 'get_slug_translation_languages_filter' ),
|
||||
1,
|
||||
3
|
||||
);
|
||||
add_filter( 'wpml_type_slug_is_translated', array( $this, 'type_slug_is_translated_filter' ), 10, 3 );
|
||||
}
|
||||
|
||||
add_filter( 'wpml_slug_translation_available', '__return_true', 1 );
|
||||
add_action( 'wpml_activate_slug_translation', array( $this, 'activate_slug_translation_action' ), 1, 3 );
|
||||
add_filter( 'wpml_get_slug_translation_url', array( $this, 'get_slug_translation_url_filter' ), 1, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug_value
|
||||
* @param string $type
|
||||
* @param string|bool $language
|
||||
* @param string $element_type WPML_Slug_Translation_Factory::POST|WPML_Slug_Translation_Factory::TAX
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_translated_slug_filter(
|
||||
$slug_value,
|
||||
$type,
|
||||
$language = false,
|
||||
$element_type = WPML_Slug_Translation_Factory::POST
|
||||
) {
|
||||
if ( $type ) {
|
||||
$slug = $this->records_factory->create( $element_type )->get_slug( $type );
|
||||
|
||||
if ( ! $language ) {
|
||||
$language = $this->current_language->get_current_language();
|
||||
}
|
||||
|
||||
return $slug->filter_value( $slug_value, $language );
|
||||
}
|
||||
|
||||
return $slug_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $languages
|
||||
* @param string $type
|
||||
* @param string $element_type WPML_Slug_Translation_Factory::POST|WPML_Slug_Translation_Factory::TAX
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_slug_translation_languages_filter(
|
||||
$languages,
|
||||
$type,
|
||||
$element_type = WPML_Slug_Translation_Factory::POST
|
||||
) {
|
||||
return $this->records_factory->create( $element_type )->get_slug_translation_languages( $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string|null $slug_value
|
||||
* @param string $element_type WPML_Slug_Translation_Factory::POST|WPML_Slug_Translation_Factory::TAX
|
||||
*/
|
||||
public function activate_slug_translation_action(
|
||||
$type,
|
||||
$slug_value = null,
|
||||
$element_type = WPML_Slug_Translation_Factory::POST
|
||||
) {
|
||||
if ( ! $slug_value ) {
|
||||
$slug_value = $type;
|
||||
}
|
||||
|
||||
$records = $this->records_factory->create( $element_type );
|
||||
$settings = $this->settings_factory->create( $element_type );
|
||||
|
||||
$slug = $records->get_slug( $type );
|
||||
|
||||
if ( ! $slug->get_original_id() ) {
|
||||
$records->register_slug( $type, $slug_value );
|
||||
}
|
||||
|
||||
if ( ! $settings->is_enabled() || ! $settings->is_translated( $type ) ) {
|
||||
$settings->set_enabled( true );
|
||||
$settings->set_type( $type, true );
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $element_type WPML_Slug_Translation_Factory::POST or WPML_Slug_Translation_Factory::TAX
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_slug_translation_url_filter( $url, $element_type = WPML_Slug_Translation_Factory::POST ) {
|
||||
$index = self::SECTION_INDEX_POST;
|
||||
|
||||
if ( WPML_Slug_Translation_Factory::TAX === $element_type ) {
|
||||
$index = self::SECTION_INDEX_TAX;
|
||||
}
|
||||
|
||||
$page = $this->wp_api->constant( 'WPML_PLUGIN_FOLDER' )
|
||||
. '/menu/translation-options.php#ml-content-setup-sec-' . $index;
|
||||
|
||||
if ( $this->wp_api->defined( 'WPML_TM_VERSION' ) ) {
|
||||
$page = $this->wp_api->constant( 'WPML_TM_FOLDER' )
|
||||
. '/menu/settings&sm=mcsetup#ml-content-setup-sec-' . $index;
|
||||
}
|
||||
|
||||
return admin_url( 'admin.php?page=' . $page );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $is_translated
|
||||
* @param string $type
|
||||
* @param string $element_type WPML_Slug_Translation_Factory::POST or WPML_Slug_Translation_Factory::TAX
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function type_slug_is_translated_filter(
|
||||
$is_translated,
|
||||
$type,
|
||||
$element_type = WPML_Slug_Translation_Factory::POST
|
||||
) {
|
||||
return $this->settings_factory->create( $element_type )->is_translated( $type );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_Settings_Factory {
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
* @param string $element_type
|
||||
*
|
||||
* @return WPML_ST_Slug_Translation_Settings
|
||||
*/
|
||||
public function create( $element_type = null ) {
|
||||
global $sitepress;
|
||||
|
||||
if ( WPML_Slug_Translation_Factory::POST === $element_type ) {
|
||||
return new WPML_ST_Post_Slug_Translation_Settings( $sitepress );
|
||||
}
|
||||
|
||||
if ( WPML_Slug_Translation_Factory::TAX === $element_type ) {
|
||||
return new WPML_ST_Tax_Slug_Translation_Settings();
|
||||
}
|
||||
|
||||
if ( ! $element_type ) {
|
||||
return new WPML_ST_Slug_Translation_Settings();
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException( 'Invalid element type.' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_Settings {
|
||||
|
||||
const KEY_ENABLED_GLOBALLY = 'wpml_base_slug_translation';
|
||||
|
||||
/** @param bool $enabled */
|
||||
public function set_enabled( $enabled ) {
|
||||
update_option( self::KEY_ENABLED_GLOBALLY, (int) $enabled );
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
public function is_enabled() {
|
||||
return (bool) get_option( self::KEY_ENABLED_GLOBALLY );
|
||||
}
|
||||
|
||||
public function is_translated( $type_name ) {
|
||||
throw new Exception( 'Use a child class with the proper element type: post or taxonomy.' );
|
||||
}
|
||||
|
||||
public function set_type( $type, $is_type_enabled ) {
|
||||
throw new Exception( 'Use a child class with the proper element type: post or taxonomy.' );
|
||||
}
|
||||
|
||||
public function save() {
|
||||
throw new Exception( 'Use a child class with the proper element type: post or taxonomy.' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_Strings_Sync implements IWPML_Action {
|
||||
|
||||
/** @var WPML_Slug_Translation_Records_Factory $slug_records_factory */
|
||||
private $slug_records_factory;
|
||||
|
||||
/** @var WPML_ST_Slug_Translation_Settings_Factory $slug_settings_factory */
|
||||
private $slug_settings_factory;
|
||||
|
||||
public function __construct(
|
||||
WPML_Slug_Translation_Records_Factory $slug_records_factory,
|
||||
WPML_ST_Slug_Translation_Settings_Factory $slug_settings_factory
|
||||
) {
|
||||
$this->slug_records_factory = $slug_records_factory;
|
||||
$this->slug_settings_factory = $slug_settings_factory;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'registered_taxonomy', array( $this, 'run_taxonomy_sync' ), 10, 3 );
|
||||
add_action( 'registered_post_type', array( $this, 'run_post_type_sync' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $taxonomy
|
||||
* @param string|array $object_type
|
||||
* @param array $taxonomy_array
|
||||
*/
|
||||
public function run_taxonomy_sync( $taxonomy, $object_type, $taxonomy_array ) {
|
||||
if ( isset( $taxonomy_array['rewrite']['slug'] ) && $taxonomy_array['rewrite']['slug'] ) {
|
||||
$this->sync_element_slug( $taxonomy_array['rewrite']['slug'], $taxonomy, WPML_Slug_Translation_Factory::TAX );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $post_type
|
||||
* @param WP_Post_Type $post_type_object
|
||||
*/
|
||||
public function run_post_type_sync( $post_type, $post_type_object ) {
|
||||
if ( isset( $post_type_object->rewrite['slug'] ) && $post_type_object->rewrite['slug'] ) {
|
||||
$this->sync_element_slug( trim( $post_type_object->rewrite['slug'], '/' ), $post_type, WPML_Slug_Translation_Factory::POST );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rewrite_slug
|
||||
* @param string $type
|
||||
* @param string $element_type
|
||||
*/
|
||||
public function sync_element_slug( $rewrite_slug, $type, $element_type ) {
|
||||
$settings = $this->slug_settings_factory->create( $element_type );
|
||||
|
||||
if ( ! $settings->is_translated( $type ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$records = $this->slug_records_factory->create( $element_type );
|
||||
$slug = $records->get_slug( $type );
|
||||
|
||||
if ( $slug->get_original_value() !== $rewrite_slug ) {
|
||||
$records->update_original_slug( $type, $rewrite_slug );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug_Translation_UI_Factory {
|
||||
|
||||
const POST = 'post';
|
||||
const TAX = 'taxonomy';
|
||||
const TEMPLATE_PATH = 'templates/slug-translation';
|
||||
|
||||
public function create( $type ) {
|
||||
global $sitepress;
|
||||
|
||||
$sync_settings_factory = new WPML_Element_Sync_Settings_Factory();
|
||||
$records_factory = new WPML_Slug_Translation_Records_Factory();
|
||||
|
||||
if ( WPML_Slug_Translation_Factory::POST === $type ) {
|
||||
$settings = new WPML_ST_Post_Slug_Translation_Settings( $sitepress );
|
||||
} elseif ( WPML_Slug_Translation_Factory::TAX === $type ) {
|
||||
$settings = new WPML_ST_Tax_Slug_Translation_Settings();
|
||||
} else {
|
||||
throw new Exception( 'Unknown element type.' );
|
||||
}
|
||||
|
||||
$records = $records_factory->create( $type );
|
||||
$sync = $sync_settings_factory->create( $type );
|
||||
$template_loader = new WPML_Twig_Template_Loader( array( WPML_ST_PATH . '/' . self::TEMPLATE_PATH ) );
|
||||
$template_service = $template_loader->get_template();
|
||||
$lang_selector = new WPML_Simple_Language_Selector( $sitepress );
|
||||
|
||||
$model = new WPML_ST_Element_Slug_Translation_UI_Model( $sitepress, $settings, $records, $sync, $lang_selector );
|
||||
return new WPML_ST_Element_Slug_Translation_UI( $model, $template_service );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
use WPML\API\Sanitize;
|
||||
|
||||
class WPML_ST_Slug_Translation_UI_Save implements IWPML_Action {
|
||||
|
||||
const ACTION_HOOK_FOR_POST = 'wpml_save_cpt_sync_settings';
|
||||
const ACTION_HOOK_FOR_TAX = 'wpml_save_taxonomy_sync_settings';
|
||||
|
||||
/** @var WPML_ST_Slug_Translation_Settings $settings */
|
||||
private $settings;
|
||||
|
||||
/** @var WPML_Slug_Translation_Records $records */
|
||||
private $records;
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var IWPML_WP_Element_Type $wp_element_type */
|
||||
private $wp_element_type;
|
||||
|
||||
/**
|
||||
* @var string $action_hook either WPML_ST_Slug_Translation_UI_Save::ACTION_HOOK_FOR_POST
|
||||
* or WPML_ST_Slug_Translation_UI_Save::ACTION_HOOK_FOR_TAX
|
||||
*/
|
||||
private $action_hook;
|
||||
|
||||
public function __construct(
|
||||
WPML_ST_Slug_Translation_Settings $settings,
|
||||
WPML_Slug_Translation_Records $records,
|
||||
SitePress $sitepress,
|
||||
IWPML_WP_Element_Type $wp_element_type,
|
||||
$action_hook
|
||||
) {
|
||||
$this->settings = $settings;
|
||||
$this->records = $records;
|
||||
$this->sitepress = $sitepress;
|
||||
$this->wp_element_type = $wp_element_type;
|
||||
$this->action_hook = $action_hook;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( $this->action_hook, array( $this, 'save_element_type_slug_translation_options' ), 1 );
|
||||
}
|
||||
|
||||
public function save_element_type_slug_translation_options() {
|
||||
if ( $this->settings->is_enabled() && ! empty( $_POST['translate_slugs'] ) ) {
|
||||
|
||||
foreach ( $_POST['translate_slugs'] as $type => $data ) {
|
||||
$type = Sanitize::string( $type );
|
||||
$data = $this->sanitize_translate_slug_data( $data );
|
||||
$is_type_enabled = $this->has_translation( $data );
|
||||
$this->settings->set_type( $type, $is_type_enabled );
|
||||
$this->update_slug_translations( $type, $data );
|
||||
}
|
||||
|
||||
$this->settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function sanitize_translate_slug_data( array $data ) {
|
||||
$data['original'] = Sanitize::stringProp( 'original', $data );
|
||||
|
||||
foreach ( $data['langs'] as $lang => $translated_slug ) {
|
||||
$data['langs'][ $lang ] = Sanitize::string( $translated_slug );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function has_translation( array $data ) {
|
||||
$slug_translations = $this->get_slug_translations( $data );
|
||||
|
||||
foreach ( $slug_translations as $slug ) {
|
||||
if ( trim( $slug ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_slug_translations( array $data ) {
|
||||
$slugs = $data['langs'];
|
||||
$original_slug_lang = $data['original'];
|
||||
unset( $slugs[ $original_slug_lang ] );
|
||||
return $slugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param array $data
|
||||
*/
|
||||
private function update_slug_translations( $type, array $data ) {
|
||||
$string = $this->records->get_slug_string( $type );
|
||||
|
||||
if ( ! $string ) {
|
||||
$string = $this->register_string_if_not_exit( $type );
|
||||
}
|
||||
|
||||
if ( $string ) {
|
||||
|
||||
$original_lang = $this->sitepress->get_default_language();
|
||||
|
||||
if ( isset( $data['original'] ) ) {
|
||||
$original_lang = $data['original'];
|
||||
}
|
||||
|
||||
if ( $string->get_language() !== $original_lang ) {
|
||||
$string->set_language( $original_lang );
|
||||
}
|
||||
|
||||
if ( isset( $data['langs'] ) ) {
|
||||
|
||||
foreach ( $this->sitepress->get_active_languages() as $code => $lang ) {
|
||||
|
||||
if ( $code !== $original_lang ) {
|
||||
$translation_value = $this->sanitize_slug( $data['langs'][ $code ] );
|
||||
$translation_value = urldecode( $translation_value );
|
||||
$string->set_translation( $code, $translation_value, ICL_TM_COMPLETE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$string->update_status();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return null|WPML_ST_String
|
||||
*/
|
||||
private function register_string_if_not_exit( $type ) {
|
||||
$slug = $this->get_registered_slug( $type );
|
||||
$this->records->register_slug( $type, $slug );
|
||||
return $this->records->get_slug_string( $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_slug( $slug ) {
|
||||
return implode( '/', array_map( array( 'WPML_Slug_Translation', 'sanitize' ), explode( '/', $slug ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type_name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_registered_slug( $type_name ) {
|
||||
$wp_element = $this->wp_element_type->get_wp_element_type_object( $type_name );
|
||||
return $wp_element ? trim( $wp_element->rewrite['slug'], '/' ) : false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Slug {
|
||||
|
||||
/** @var int $original_id */
|
||||
private $original_id;
|
||||
|
||||
/** @var string $original_lang */
|
||||
private $original_lang;
|
||||
|
||||
/** @var string $original_value */
|
||||
private $original_value;
|
||||
|
||||
/** @var array $langs */
|
||||
private $langs = array();
|
||||
|
||||
/** @param stdClass $data */
|
||||
public function set_lang_data( stdClass $data ) {
|
||||
if ( isset( $data->language ) ) {
|
||||
$this->langs[ $data->language ] = $data;
|
||||
}
|
||||
|
||||
// Case of original string language
|
||||
if ( isset( $data->id ) ) {
|
||||
$this->original_id = $data->id;
|
||||
$this->original_lang = $data->language;
|
||||
$this->original_value = $data->value;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function get_original_lang() {
|
||||
return $this->original_lang;
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function get_original_value() {
|
||||
return $this->original_value;
|
||||
}
|
||||
|
||||
/** @return int */
|
||||
public function get_original_id() {
|
||||
return (int) $this->original_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value( $lang ) {
|
||||
if ( isset( $this->langs[ $lang ]->value ) ) {
|
||||
return $this->langs[ $lang ]->value;
|
||||
}
|
||||
|
||||
return $this->get_original_value();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lang
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_status( $lang ) {
|
||||
if ( isset( $this->langs[ $lang ]->status ) ) {
|
||||
return (int) $this->langs[ $lang ]->status;
|
||||
}
|
||||
|
||||
return ICL_TM_NOT_TRANSLATED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lang
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_translation_complete( $lang ) {
|
||||
return ICL_TM_COMPLETE === $this->get_status( $lang );
|
||||
}
|
||||
|
||||
/** @return string|null */
|
||||
public function get_context() {
|
||||
if ( isset( $this->langs[ $this->original_lang ]->context ) ) {
|
||||
return $this->langs[ $this->original_lang ]->context;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return string|null */
|
||||
public function get_name() {
|
||||
if ( isset( $this->langs[ $this->original_lang ]->name ) ) {
|
||||
return $this->langs[ $this->original_lang ]->name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function get_language_codes() {
|
||||
return array_keys( $this->langs );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used as a filter which returns the initial `$slug_value`
|
||||
* if no better value was found.
|
||||
*
|
||||
* @param string $slug_value
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function filter_value( $slug_value, $lang ) {
|
||||
if ( $this->original_lang === $lang ) {
|
||||
return $this->original_value;
|
||||
} elseif ( in_array( $lang, $this->get_language_codes(), true ) && $this->is_translation_complete( $lang ) ) {
|
||||
return $this->get_value( $lang );
|
||||
}
|
||||
|
||||
return $slug_value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user