first commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
class WPML_Rewrite_Rules_Filter {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $active_languages;
|
||||
|
||||
/**
|
||||
* @var WPML_URL_Filters
|
||||
*/
|
||||
private $wpml_url_filters;
|
||||
|
||||
/**
|
||||
* @param array $active_languages
|
||||
* @param WPML_URL_Filters $wpml_url_filters
|
||||
*/
|
||||
public function __construct( $active_languages, $wpml_url_filters = null ) {
|
||||
$this->active_languages = $active_languages;
|
||||
|
||||
if ( ! $wpml_url_filters ) {
|
||||
global $wpml_url_filters;
|
||||
}
|
||||
$this->wpml_url_filters = $wpml_url_filters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $htaccess_string Content of the .htaccess file
|
||||
*
|
||||
* @return string .htaccess file contents with adjusted RewriteBase
|
||||
*/
|
||||
public function rid_of_language_param( $htaccess_string ) {
|
||||
if ( $this->wpml_url_filters->frontend_uses_root() || $this->is_permalink_page() || $this->is_shop_page() ) {
|
||||
foreach ( $this->active_languages as $lang_code ) {
|
||||
foreach ( array( '', 'index.php' ) as $base ) {
|
||||
$htaccess_string = str_replace(
|
||||
'/' . $lang_code . '/' . $base,
|
||||
'/' . $base,
|
||||
$htaccess_string
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $htaccess_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is permalink page in admin.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_permalink_page() {
|
||||
return $this->is_admin_screen( 'options-permalink' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is WooCommerce shop page in admin.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_shop_page() {
|
||||
return $this->is_admin_screen( 'page' ) && get_option( 'woocommerce_shop_page_id' ) === intval( $_GET['post'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it as a certain screen on admin page.
|
||||
*
|
||||
* @param string $screen_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_admin_screen( $screen_id ) {
|
||||
return is_admin() && function_exists( 'get_current_screen' ) && get_current_screen() && get_current_screen()->id === $screen_id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Cached_Converter extends WPML_URL_Converter {
|
||||
|
||||
/** @var string[] $cache */
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string|bool $lang_code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_url( $url, $lang_code = false ) {
|
||||
global $sitepress;
|
||||
|
||||
if ( ! $lang_code ) {
|
||||
$lang_code = $sitepress->get_current_language();
|
||||
}
|
||||
|
||||
$negotiation_type = $sitepress->get_setting( 'language_negotiation_type' );
|
||||
|
||||
$skip_convert_url_string = $this->get_strategy()->skip_convert_url_string( $url, $lang_code );
|
||||
|
||||
$cache_key_args = array( $url, $lang_code, $negotiation_type, $skip_convert_url_string );
|
||||
$cache_key = md5( wp_json_encode( $cache_key_args ) );
|
||||
$cache_group = 'convert_url';
|
||||
$cache_found = false;
|
||||
$cache = new WPML_WP_Cache( $cache_group );
|
||||
$new_url = $cache->get( $cache_key, $cache_found );
|
||||
|
||||
if ( ! $cache_found ) {
|
||||
$new_url = parent::convert_url( $url, $lang_code );
|
||||
$cache->set( $cache_key, $new_url );
|
||||
}
|
||||
|
||||
return $new_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_language_from_url( $url ) {
|
||||
if ( isset( $this->cache[ $url ] ) ) {
|
||||
return $this->cache[ $url ];
|
||||
}
|
||||
|
||||
$lang = parent::get_language_from_url( $url );
|
||||
|
||||
$this->cache[ $url ] = $lang;
|
||||
|
||||
return $lang;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_CPT {
|
||||
/**
|
||||
* @var WPML_Slash_Management
|
||||
*/
|
||||
private $slash_helper;
|
||||
|
||||
/**
|
||||
* @param WPML_Slash_Management $slash_helper
|
||||
*/
|
||||
public function __construct( WPML_Slash_Management $slash_helper = null ) {
|
||||
if ( ! $slash_helper ) {
|
||||
$slash_helper = new WPML_Slash_Management();
|
||||
}
|
||||
$this->slash_helper = $slash_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the CPT archive slug for possible slug translations from ST.
|
||||
*
|
||||
* @param string $link
|
||||
* @param string $post_type
|
||||
* @param null|string $language_code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function adjust_cpt_slug_in_url( $link, $post_type, $language_code = null ) {
|
||||
|
||||
$post_type_object = get_post_type_object( $post_type );
|
||||
|
||||
if ( isset( $post_type_object->rewrite ) ) {
|
||||
$slug = trim( $post_type_object->rewrite['slug'], '/' );
|
||||
} else {
|
||||
$slug = $post_type_object->name;
|
||||
}
|
||||
|
||||
$translated_slug = apply_filters( 'wpml_get_translated_slug', $slug, $post_type, $language_code );
|
||||
|
||||
if ( is_string( $translated_slug ) ) {
|
||||
$link_parts = explode( '?', $link, 2 );
|
||||
|
||||
$pattern = '#\/' . preg_quote( $slug, '#' ) . '\/#';
|
||||
$link_new = trailingslashit( preg_replace( $pattern, '/' . $translated_slug . '/', trailingslashit( $link_parts[0] ), 1 ) );
|
||||
$link = $this->slash_helper->match_trailing_slash_to_reference( $link_new, $link_parts[0] );
|
||||
$link = isset( $link_parts[1] ) ? $link . '?' . $link_parts[1] : $link;
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_Factory {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $default_lang_code;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $active_language_codes;
|
||||
|
||||
/**
|
||||
* @var WPML_Resolve_Object_Url_Helper_Factory
|
||||
*/
|
||||
private $object_url_helper_factory;
|
||||
|
||||
/** @var WPML_URL_Converter */
|
||||
private static $previous_url_converter;
|
||||
|
||||
const SUBDIR = 1;
|
||||
const DOMAIN = 2;
|
||||
|
||||
/**
|
||||
* @param array $settings
|
||||
* @param string $default_lang_code
|
||||
* @param array $active_language_codes
|
||||
*/
|
||||
public function __construct( $settings, $default_lang_code, $active_language_codes ) {
|
||||
$this->settings = $settings;
|
||||
$this->default_lang_code = $default_lang_code;
|
||||
$this->active_language_codes = $active_language_codes;
|
||||
}
|
||||
|
||||
public static function remove_previous_hooks() {
|
||||
if ( self::$previous_url_converter ) {
|
||||
self::$previous_url_converter->get_strategy()->remove_hooks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_Resolve_Object_Url_Helper_Factory
|
||||
*/
|
||||
public function get_object_url_helper_factory() {
|
||||
if ( ! $this->object_url_helper_factory ) {
|
||||
$this->object_url_helper_factory = new WPML_Resolve_Object_Url_Helper_Factory();
|
||||
}
|
||||
|
||||
return $this->object_url_helper_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Resolve_Object_Url_Helper_Factory $factory
|
||||
*/
|
||||
public function set_object_url_helper_factory( WPML_Resolve_Object_Url_Helper_Factory $factory ) {
|
||||
$this->object_url_helper_factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $url_type
|
||||
*
|
||||
* @return WPML_URL_Converter
|
||||
*/
|
||||
public function create( $url_type ) {
|
||||
switch ( $url_type ) {
|
||||
case self::SUBDIR:
|
||||
$wpml_url_converter = $this->create_subdir_converter();
|
||||
break;
|
||||
case self::DOMAIN:
|
||||
$wpml_url_converter = $this->create_domain_converter();
|
||||
break;
|
||||
default:
|
||||
$wpml_url_converter = $this->create_parameter_converter();
|
||||
}
|
||||
|
||||
$home_url = new WPML_URL_Converter_Url_Helper();
|
||||
$wpml_url_converter->set_url_helper( $home_url );
|
||||
$wpml_url_converter->get_strategy()->add_hooks();
|
||||
|
||||
self::$previous_url_converter = $wpml_url_converter;
|
||||
|
||||
return $wpml_url_converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_URL_Cached_Converter
|
||||
*/
|
||||
private function create_subdir_converter() {
|
||||
$dir_default = false;
|
||||
if ( ! isset( $this->settings['urls'] ) ) {
|
||||
$this->settings['urls'] = array();
|
||||
} else {
|
||||
if ( isset( $this->settings['urls']['directory_for_default_language'] ) ) {
|
||||
$dir_default = $this->settings['urls']['directory_for_default_language'];
|
||||
}
|
||||
}
|
||||
|
||||
$strategy = new WPML_URL_Converter_Subdir_Strategy( $dir_default, $this->default_lang_code, $this->active_language_codes, $this->settings['urls'] );
|
||||
|
||||
return new WPML_URL_Cached_Converter(
|
||||
$strategy,
|
||||
$this->get_object_url_helper_factory()->create(),
|
||||
$this->default_lang_code,
|
||||
$this->active_language_codes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_URL_Cached_Converter
|
||||
*/
|
||||
private function create_domain_converter() {
|
||||
$domains = isset( $this->settings['language_domains'] ) ? $this->settings['language_domains'] : array();
|
||||
$wpml_wp_api = new WPML_WP_API();
|
||||
$strategy = new WPML_URL_Converter_Domain_Strategy( $domains, $this->default_lang_code, $this->active_language_codes );
|
||||
$wpml_url_converter = new WPML_URL_Cached_Converter(
|
||||
$strategy,
|
||||
$this->get_object_url_helper_factory()->create(),
|
||||
$this->default_lang_code,
|
||||
$this->active_language_codes
|
||||
);
|
||||
|
||||
$wpml_fix_url_domain = new WPML_Lang_Domain_Filters(
|
||||
$wpml_url_converter,
|
||||
$wpml_wp_api,
|
||||
new WPML_Debug_BackTrace( null, 10 )
|
||||
);
|
||||
$wpml_fix_url_domain->add_hooks();
|
||||
|
||||
$xdomain_data_parser = new WPML_XDomain_Data_Parser( $this->settings, new WPML_Data_Encryptor() );
|
||||
$xdomain_data_parser->init_hooks();
|
||||
|
||||
return $wpml_url_converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_URL_Cached_Converter
|
||||
*/
|
||||
private function create_parameter_converter() {
|
||||
$strategy = new WPML_URL_Converter_Parameter_Strategy( $this->default_lang_code, $this->active_language_codes );
|
||||
$wpml_url_converter = new WPML_URL_Cached_Converter(
|
||||
$strategy,
|
||||
$this->get_object_url_helper_factory()->create(),
|
||||
$this->default_lang_code,
|
||||
$this->active_language_codes
|
||||
);
|
||||
|
||||
$filters = new WPML_Lang_Parameter_Filters();
|
||||
$filters->add_hooks();
|
||||
|
||||
return $wpml_url_converter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WPML_URL_Converter
|
||||
*
|
||||
* @package wpml-core
|
||||
* @subpackage url-handling
|
||||
*/
|
||||
|
||||
use WPML\SuperGlobals\Server;
|
||||
use WPML\UrlHandling\WPLoginUrlConverter;
|
||||
|
||||
class WPML_URL_Converter {
|
||||
/**
|
||||
* @var IWPML_URL_Converter_Strategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $default_language;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $active_languages;
|
||||
|
||||
/**
|
||||
* @var WPML_URL_Converter_Url_Helper
|
||||
*/
|
||||
protected $home_url_helper;
|
||||
|
||||
/**
|
||||
* @var WPML_URL_Converter_Lang_Param_Helper
|
||||
*/
|
||||
protected $lang_param;
|
||||
|
||||
/**
|
||||
* @var WPML_Slash_Management
|
||||
*/
|
||||
protected $slash_helper;
|
||||
|
||||
/**
|
||||
* @var WPML_Resolve_Object_Url_Helper
|
||||
*/
|
||||
protected $object_url_helper;
|
||||
|
||||
/**
|
||||
* @param IWPML_URL_Converter_Strategy $strategy
|
||||
* @param WPML_Resolve_Object_Url_Helper $object_url_helper
|
||||
* @param string $default_language
|
||||
* @param array<string> $active_languages
|
||||
*/
|
||||
public function __construct(
|
||||
IWPML_URL_Converter_Strategy $strategy,
|
||||
WPML_Resolve_Object_Url_Helper $object_url_helper,
|
||||
$default_language,
|
||||
$active_languages
|
||||
) {
|
||||
$this->strategy = $strategy;
|
||||
$this->object_url_helper = $object_url_helper;
|
||||
$this->default_language = $default_language;
|
||||
$this->active_languages = $active_languages;
|
||||
|
||||
$this->lang_param = new WPML_URL_Converter_Lang_Param_Helper( $active_languages );
|
||||
$this->slash_helper = new WPML_Slash_Management();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IWPML_URL_Converter_Strategy
|
||||
*/
|
||||
public function get_strategy() {
|
||||
return $this->strategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_URL_Converter_Url_Helper $url_helper
|
||||
*/
|
||||
public function set_url_helper( WPML_URL_Converter_Url_Helper $url_helper ) {
|
||||
$this->home_url_helper = $url_helper;
|
||||
|
||||
if ( $this->strategy instanceof WPML_URL_Converter_Abstract_Strategy ) {
|
||||
$this->strategy->set_url_helper( $url_helper );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_URL_Converter_Url_Helper
|
||||
*/
|
||||
public function get_url_helper() {
|
||||
if ( ! $this->home_url_helper ) {
|
||||
$this->home_url_helper = new WPML_URL_Converter_Url_Helper();
|
||||
}
|
||||
|
||||
return $this->home_url_helper;
|
||||
}
|
||||
|
||||
public function get_abs_home() {
|
||||
return $this->get_url_helper()->get_abs_home();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_URL_Converter_Lang_Param_Helper $lang_param_helper
|
||||
*/
|
||||
public function set_lang_param_helper( WPML_URL_Converter_Lang_Param_Helper $lang_param_helper ) {
|
||||
$this->lang_param = $lang_param_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Slash_Management $slash_helper
|
||||
*/
|
||||
public function set_slash_helper( WPML_Slash_Management $slash_helper ) {
|
||||
$this->slash_helper = $slash_helper;
|
||||
}
|
||||
|
||||
public function get_default_site_url() {
|
||||
return $this->get_url_helper()->get_unfiltered_home_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope of this function:
|
||||
* 1. Convert the home URL in the specified language depending on language negotiation:
|
||||
* 1. Add a language directory
|
||||
* 2. Change the domain
|
||||
* 3. Add a language parameter
|
||||
* 2. If the requested URL is equal to the current URL, the URI will be adapted
|
||||
* with potential slug translations for:
|
||||
* - single post slugs
|
||||
* - taxonomy term slug
|
||||
*
|
||||
* WARNING: The URI slugs won't be translated for arbitrary URL (not the current one)
|
||||
*
|
||||
* @param string $url
|
||||
* @param bool $lang_code
|
||||
*
|
||||
* @return bool|mixed|string
|
||||
*/
|
||||
public function convert_url( $url, $lang_code = false ) {
|
||||
if ( ! $url ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
global $sitepress;
|
||||
|
||||
$new_url = false;
|
||||
if ( ! $lang_code ) {
|
||||
$lang_code = $sitepress->get_current_language();
|
||||
}
|
||||
$language_from_url = $this->get_language_from_url( $url );
|
||||
|
||||
if ( $language_from_url === $lang_code || 'all' === $lang_code ) {
|
||||
$new_url = $url;
|
||||
} else {
|
||||
if ( $this->can_resolve_object_url( $url ) ) {
|
||||
$new_url = $this->object_url_helper->resolve_object_url( $url, $lang_code );
|
||||
}
|
||||
|
||||
if ( false === $new_url ) {
|
||||
$new_url = $this->strategy->convert_url_string( $url, $lang_code );
|
||||
}
|
||||
}
|
||||
|
||||
return $new_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a URL and returns the language of the document it points at
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public function get_language_from_url( $url ) {
|
||||
$http_referer_factory = new WPML_URL_HTTP_Referer_Factory();
|
||||
$http_referer = $http_referer_factory->create();
|
||||
$url = $http_referer->get_url( $url );
|
||||
$language = $this->lang_param->lang_by_param( $url ) ?: $this->get_strategy()->get_lang_from_url_string( $url );
|
||||
|
||||
/**
|
||||
* Filters language code fetched from the current URL and allows to rewrite
|
||||
* the language to set on front-end
|
||||
*
|
||||
* @param string $language language fetched from the current URL
|
||||
* @param string $url current URL.
|
||||
*/
|
||||
$language = apply_filters( 'wpml_get_language_from_url', $language, $url );
|
||||
|
||||
return $this->get_strategy()->validate_language( $language, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_home_url_relative( $url, $language ) {
|
||||
return $this->get_strategy()->get_home_url_relative( $url, $language );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
*
|
||||
* @return WPLoginUrlConverter|null
|
||||
*/
|
||||
public function get_wp_login_url_converter( $sitepress ) {
|
||||
return $this->strategy->use_wp_login_url_converter()
|
||||
? new WPLoginUrlConverter( $sitepress, $this )
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_resolve_object_url( $url ) {
|
||||
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
|
||||
$server_name = strpos( $request_uri, '/' ) === 0
|
||||
? untrailingslashit( Server::getServerName() ) : trailingslashit( Server::getServerName() );
|
||||
$request_url = stripos( get_option( 'siteurl' ), 'https://' ) === 0
|
||||
? 'https://' . $server_name . $request_uri : 'http://' . $server_name . $request_uri;
|
||||
|
||||
$is_request_url = trailingslashit( $request_url ) === trailingslashit( $url );
|
||||
$is_home_url = trailingslashit( $this->get_url_helper()->get_abs_home() ) === trailingslashit( $url );
|
||||
$is_home_url_filter = current_filter() === 'home_url';
|
||||
|
||||
return $is_request_url && ! $is_home_url && ! $is_home_url_filter;
|
||||
}
|
||||
|
||||
/** @return WPML_URL_Converter */
|
||||
public static function getGlobalInstance() {
|
||||
global $wpml_url_converter;
|
||||
return $wpml_url_converter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
class WPML_Lang_Domain_Filters {
|
||||
|
||||
private $wpml_url_converter;
|
||||
private $wpml_wp_api;
|
||||
private $debug_backtrace;
|
||||
private $domains = array();
|
||||
|
||||
/**
|
||||
* WPML_Lang_Domain_Filters constructor.
|
||||
*
|
||||
* @param \WPML_URL_Converter $wpml_url_converter
|
||||
* @param \WPML_WP_API $wpml_wp_api
|
||||
*/
|
||||
public function __construct(
|
||||
WPML_URL_Converter $wpml_url_converter,
|
||||
WPML_WP_API $wpml_wp_api,
|
||||
WPML_Debug_BackTrace $debug_backtrace
|
||||
) {
|
||||
|
||||
$this->wpml_url_converter = $wpml_url_converter;
|
||||
$this->wpml_wp_api = $wpml_wp_api;
|
||||
$this->debug_backtrace = $debug_backtrace;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'upload_dir', array( $this, 'upload_dir_filter_callback' ) );
|
||||
add_filter( 'stylesheet_uri', array( $this, 'convert_url' ) );
|
||||
add_filter( 'option_siteurl', array( $this, 'siteurl_callback' ) );
|
||||
add_filter( 'content_url', array( $this, 'siteurl_callback' ) );
|
||||
add_filter( 'plugins_url', array( $this, 'siteurl_callback' ) );
|
||||
add_filter( 'login_url', array( $this, 'convert_url' ) );
|
||||
add_filter( 'logout_url', array( $this, 'convert_logout_url' ) );
|
||||
add_filter( 'admin_url', array( $this, 'admin_url_filter' ), 10, 2 );
|
||||
add_filter( 'login_redirect', array( $this, 'convert_url' ), 1, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_url( $url ) {
|
||||
return $this->wpml_url_converter->convert_url( $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $upload_dir
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function upload_dir_filter_callback( $upload_dir ) {
|
||||
$convertWithMatchingTrailingSlash = function ( $url ) {
|
||||
$hasTrailingSlash = '/' === substr( $url, -1 );
|
||||
$newUrl = $this->wpml_url_converter->convert_url( $url );
|
||||
|
||||
return $hasTrailingSlash ? trailingslashit( $newUrl ) : untrailingslashit( $newUrl );
|
||||
};
|
||||
|
||||
$upload_dir['url'] = $convertWithMatchingTrailingSlash( $upload_dir['url'] );
|
||||
$upload_dir['baseurl'] = $convertWithMatchingTrailingSlash( $upload_dir['baseurl'] );
|
||||
|
||||
return $upload_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function siteurl_callback( $url ) {
|
||||
$getting_network_site_url = $this->debug_backtrace->is_function_in_call_stack( 'get_admin_url' ) && is_multisite();
|
||||
|
||||
if ( ! $this->debug_backtrace->is_function_in_call_stack( 'get_home_path', false ) && ! $getting_network_site_url ) {
|
||||
$parsed_url = wpml_parse_url( $url );
|
||||
$host = is_array( $parsed_url ) && isset( $parsed_url['host'] );
|
||||
if ( $host && isset( $_SERVER['HTTP_HOST'] ) && $_SERVER['HTTP_HOST'] ) {
|
||||
$domain_from_global = $this->get_host_from_HTTP_HOST();
|
||||
if ( $domain_from_global ) {
|
||||
$url = str_replace( $parsed_url['host'], $domain_from_global, $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function get_host_from_HTTP_HOST() {
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
if ( false !== strpos( $_SERVER['HTTP_HOST'], ':' ) ) {
|
||||
$host = explode( ':', $_SERVER['HTTP_HOST'] );
|
||||
$host = $host[0];
|
||||
}
|
||||
|
||||
return $this->is_host_valid( $host ) ? $host : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_host_valid( $host ) {
|
||||
$valid = false;
|
||||
|
||||
foreach ( $this->get_domains() as $domain ) {
|
||||
if ( $domain === $host ) {
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function get_domains() {
|
||||
if ( ! $this->domains ) {
|
||||
$this->domains = wpml_get_setting( 'language_domains' );
|
||||
$home_parsed = wp_parse_url( $this->wpml_url_converter->get_abs_home() );
|
||||
$this->domains[] = $home_parsed['host'];
|
||||
}
|
||||
|
||||
return $this->domains;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function admin_url_filter( $url, $path ) {
|
||||
if ( ( strpos( $url, 'http://' ) === 0
|
||||
|| strpos( $url, 'https://' ) === 0 )
|
||||
&& 'admin-ajax.php' === $path && $this->wpml_wp_api->is_front_end()
|
||||
) {
|
||||
global $sitepress;
|
||||
|
||||
$url = $this->wpml_url_converter->convert_url( $url, $sitepress->get_current_language() );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert logout url only for front-end.
|
||||
*
|
||||
* @param string $logout_url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_logout_url( $logout_url ) {
|
||||
if ( $this->wpml_wp_api->is_front_end() ) {
|
||||
$logout_url = $this->wpml_url_converter->convert_url( $logout_url );
|
||||
}
|
||||
|
||||
return $logout_url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
class WPML_Lang_Parameter_Filters {
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'request', array( $this, 'request_filter' ) );
|
||||
add_filter( 'get_pagenum_link', array( $this, 'paginated_url_filter' ) );
|
||||
add_filter( 'wp_link_pages_link', array( $this, 'paginated_link_filter' ) );
|
||||
}
|
||||
|
||||
public function request_filter( $request ) {
|
||||
// This is required so that home page detection works for other languages.
|
||||
if ( ! defined( 'WP_ADMIN' ) && isset( $request['lang'] ) ) {
|
||||
unset( $request['lang'] );
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the pagination links on taxonomy archives to properly have the language parameter after the URI.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function paginated_url_filter( $url ) {
|
||||
$url = urldecode( $url );
|
||||
$parts = explode( '?', $url );
|
||||
$last_part = count( $parts ) > 2 ? array_pop( $parts ) : '';
|
||||
$url = join( '?', $parts );
|
||||
$url = preg_replace( '#(.+?)(/\?|\?)(.*?)(/.+?$)$#', '$1$4$5?$3', $url );
|
||||
$url = preg_replace( '#(\?.+)(%2F|\/)$#', '$1', $url );
|
||||
|
||||
if ( '' !== $last_part && strpos( $url, '?' . $last_part ) === false ) {
|
||||
$url .= '&' . $last_part;
|
||||
}
|
||||
$parts = explode( '?', $url );
|
||||
|
||||
if ( isset( $parts[1] ) ) {
|
||||
// Maybe remove duplicated lang param
|
||||
$params = array();
|
||||
parse_str( $parts[1], $params );
|
||||
$url = $parts[0] . '?' . build_query( $params );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the pagination links on paginated posts and pages, acting on the links html
|
||||
* output containing the anchor tag the link is a property of.
|
||||
*
|
||||
* @param string $link_html
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @hook wp_link_pages_link
|
||||
*/
|
||||
public function paginated_link_filter( $link_html ) {
|
||||
return preg_replace( '#"([^"].+?)(/\?|\?)([^/]+)(/[^"]+)"#', '"$1$4?$3"', $link_html );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
class WPML_Tax_Permalink_Filters_Factory implements IWPML_Frontend_Action_Loader, IWPML_Backend_Action_Loader {
|
||||
|
||||
public function create() {
|
||||
global $wpml_url_converter, $sitepress;
|
||||
|
||||
return new WPML_Tax_Permalink_Filters(
|
||||
$wpml_url_converter,
|
||||
new WPML_WP_Cache_Factory(),
|
||||
new WPML_Translation_Element_Factory( $sitepress ),
|
||||
WPML_Get_LS_Languages_Status::get_instance()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
class WPML_Tax_Permalink_Filters implements IWPML_Action {
|
||||
|
||||
/** @var WPML_Translation_Element_Factory */
|
||||
private $term_element_factory;
|
||||
|
||||
/** @var WPML_URL_Converter */
|
||||
private $url_converter;
|
||||
|
||||
/** @var WPML_WP_Cache_Factory $cache_factory */
|
||||
private $cache_factory;
|
||||
|
||||
/** @var WPML_Get_LS_Languages_Status */
|
||||
private $ls_languages_status;
|
||||
|
||||
public function __construct(
|
||||
WPML_URL_Converter $url_converter,
|
||||
WPML_WP_Cache_Factory $cache_factory,
|
||||
WPML_Translation_Element_Factory $term_element_factory,
|
||||
WPML_Get_LS_Languages_Status $ls_language_status
|
||||
) {
|
||||
$this->term_element_factory = $term_element_factory;
|
||||
$this->url_converter = $url_converter;
|
||||
$this->cache_factory = $cache_factory;
|
||||
$this->ls_languages_status = $ls_language_status;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'term_link', array( $this, 'cached_filter_tax_permalink' ), 1, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $permalink
|
||||
* @param int|\WP_Term|\stdClass $tag
|
||||
* @param string $taxonomy
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function cached_filter_tax_permalink( $permalink, $tag, $taxonomy ) {
|
||||
$tag = is_object( $tag ) ? $tag : get_term( $tag, $taxonomy );
|
||||
$tag_id = $tag ? $tag->term_id : 0;
|
||||
|
||||
$cache = $this->cache_factory->create_cache_item( 'icl_tax_permalink_filter', array(
|
||||
$tag_id,
|
||||
$taxonomy,
|
||||
$this->is_link_for_language_switcher()
|
||||
) );
|
||||
if ( $cache->exists() ) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$permalink = $this->filter_tax_permalink( $permalink, $tag_id );
|
||||
|
||||
$cache->set( $permalink );
|
||||
|
||||
return $permalink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the permalink pointing at a taxonomy archive to correctly reflect the language of its underlying term
|
||||
*
|
||||
* @param string $permalink url pointing at a term's archive
|
||||
* @param int $tag_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function filter_tax_permalink( $permalink, $tag_id ) {
|
||||
if ( $tag_id ) {
|
||||
$term_element = $this->term_element_factory->create( $tag_id, 'term' );
|
||||
|
||||
if ( ! $this->is_display_as_translated_and_in_default_lang( $term_element )
|
||||
|| $this->is_link_for_language_switcher()
|
||||
) {
|
||||
$term_language = $term_element->get_language_code();
|
||||
|
||||
if ( (bool) $term_language ) {
|
||||
$permalink = $this->url_converter->convert_url( $permalink, $term_language );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $permalink;
|
||||
}
|
||||
|
||||
private function is_display_as_translated_and_in_default_lang( WPML_Translation_Element $element ) {
|
||||
return $element->is_display_as_translated()
|
||||
&& $element->is_in_default_language();
|
||||
}
|
||||
|
||||
private function is_link_for_language_switcher() {
|
||||
return $this->ls_languages_status->is_getting_ls_languages();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_Lang_Param_Helper {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $cache = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $active_languages;
|
||||
|
||||
/**
|
||||
* @param array $active_languages
|
||||
*/
|
||||
public function __construct( array $active_languages ) {
|
||||
$this->active_languages = $active_languages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $url
|
||||
* @param bool $only_admin If set to true only language parameters on Admin Screen URLs will be recognized. The
|
||||
* function will return null for non-Admin Screens.
|
||||
*
|
||||
* @return null|string Language code
|
||||
*/
|
||||
public function lang_by_param( $url, $only_admin = true ) {
|
||||
if ( isset( self::$cache[ $url ] ) ) {
|
||||
return self::$cache[ $url ];
|
||||
}
|
||||
|
||||
$lang = $this->extract_lang_param_from_url( $url, $only_admin );
|
||||
|
||||
self::$cache[ $url ] = $lang;
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param bool $only_admin
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function extract_lang_param_from_url( $url, $only_admin ) {
|
||||
$url = wpml_strip_subdir_from_url( $url );
|
||||
$url_query_parts = wpml_parse_url( $url );
|
||||
$url_query = $this->has_query_part( $only_admin, $url_query_parts ) ? untrailingslashit( $url_query_parts['query'] ) : null;
|
||||
|
||||
if ( null !== $url_query ) {
|
||||
parse_str( $url_query, $vars );
|
||||
if ( $this->can_retrieve_lang_from_query( $only_admin, $vars ) ) {
|
||||
return $vars['lang'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $only_admin
|
||||
* @param array $url_query_parts
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function has_query_part( $only_admin, $url_query_parts ) {
|
||||
if ( ! isset( $url_query_parts['query'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( false === $only_admin ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! isset( $url_query_parts['path'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( false === strpos( $url_query_parts['path'], '/wp-admin' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $only_admin
|
||||
* @param array $vars
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_retrieve_lang_from_query( $only_admin, $vars ) {
|
||||
if ( ! isset( $vars['lang'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $only_admin && 'all' === $vars['lang'] ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( in_array( $vars['lang'], $this->active_languages, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_Url_Helper {
|
||||
/**
|
||||
* @var wpdb
|
||||
*/
|
||||
private $wpdb;
|
||||
|
||||
/**
|
||||
* @var WPML_Include_Url
|
||||
*/
|
||||
private $wpml_include_url_filter;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $absolute_home;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param wpdb $wpdb
|
||||
* @param WPML_Include_Url $wpml_include_url_filter
|
||||
*/
|
||||
public function __construct( wpdb $wpdb = null, WPML_Include_Url $wpml_include_url_filter = null ) {
|
||||
if ( ! $wpdb ) {
|
||||
global $wpdb;
|
||||
}
|
||||
|
||||
if ( ! $wpml_include_url_filter ) {
|
||||
global $wpml_include_url_filter;
|
||||
}
|
||||
|
||||
$this->wpdb = $wpdb;
|
||||
$this->wpml_include_url_filter = $wpml_include_url_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unfiltered home_url by directly retrieving it from wp_options.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_abs_home() {
|
||||
if ( ! $this->absolute_home ) {
|
||||
$is_multisite = is_multisite();
|
||||
if ( ! $is_multisite && defined( 'WP_HOME' ) ) {
|
||||
$this->absolute_home = WP_HOME;
|
||||
} elseif ( $is_multisite && ! is_main_site() ) {
|
||||
$protocol = preg_match( '/^(https)/', get_option( 'home' ) ) === 1 ? 'https://' : 'http://';
|
||||
$sql = "
|
||||
SELECT CONCAT(b.domain, b.path)
|
||||
FROM {$this->wpdb->blogs} b
|
||||
WHERE blog_id = {$this->wpdb->blogid}
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
$this->absolute_home = $protocol . $this->wpdb->get_var( $sql );
|
||||
} else {
|
||||
$this->absolute_home = $this->get_unfiltered_home_option();
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'wpml_url_converter_get_abs_home', $this->absolute_home );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a $url points to a WP Admin screen.
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool True if the input $url points to an admin screen.
|
||||
*/
|
||||
public function is_url_admin( $url ) {
|
||||
$url_query_parts = wpml_parse_url( strpos( $url, 'http' ) === false ? 'http://' . $url : $url );
|
||||
|
||||
return isset( $url_query_parts['path'] )
|
||||
&& strpos( wpml_strip_subdir_from_url( $url_query_parts['path'] ), '/wp-admin' ) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unfiltered home option from the database.
|
||||
*
|
||||
* @uses \WPML_Include_Url::get_unfiltered_home in case the $wpml_include_url_filter global is loaded
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_unfiltered_home_option() {
|
||||
if ( $this->wpml_include_url_filter ) {
|
||||
return $this->wpml_include_url_filter->get_unfiltered_home();
|
||||
} else {
|
||||
$sql = "
|
||||
SELECT option_value
|
||||
FROM {$this->wpdb->options}
|
||||
WHERE option_name = 'home'
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
return $this->wpdb->get_var( $sql );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
abstract class WPML_URL_Converter_Abstract_Strategy implements IWPML_URL_Converter_Strategy {
|
||||
protected $absolute_home;
|
||||
|
||||
protected $default_language;
|
||||
protected $active_languages;
|
||||
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var WPML_URL_Converter_Url_Helper
|
||||
*/
|
||||
protected $url_helper;
|
||||
|
||||
/**
|
||||
* @var WPML_URL_Converter_Lang_Param_Helper
|
||||
*/
|
||||
protected $lang_param;
|
||||
|
||||
/**
|
||||
* @var WPML_Slash_Management
|
||||
*/
|
||||
protected $slash_helper;
|
||||
|
||||
/**
|
||||
* @var WP_Rewrite
|
||||
*/
|
||||
protected $wp_rewrite;
|
||||
|
||||
/**
|
||||
* @param string $default_language
|
||||
* @param array<string> $active_languages
|
||||
* @param WP_Rewrite|null $wp_rewrite
|
||||
* @param WPML_Slash_Management|null $splash_helper
|
||||
*/
|
||||
public function __construct( $default_language, $active_languages, $wp_rewrite = null, $splash_helper = null ) {
|
||||
$this->default_language = $default_language;
|
||||
$this->active_languages = $active_languages;
|
||||
|
||||
$this->lang_param = new WPML_URL_Converter_Lang_Param_Helper( $active_languages );
|
||||
$this->slash_helper = $splash_helper ?: new WPML_Slash_Management();
|
||||
|
||||
if ( ! $wp_rewrite ) {
|
||||
global $wp_rewrite;
|
||||
}
|
||||
$this->wp_rewrite = $wp_rewrite;
|
||||
}
|
||||
|
||||
public function validate_language( $language, $url ) {
|
||||
return in_array( $language, $this->active_languages, true )
|
||||
|| 'all' === $language && $this->get_url_helper()->is_url_admin( $url ) ? $language : $this->get_default_language();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_URL_Converter_Url_Helper $url_helper
|
||||
*/
|
||||
public function set_url_helper( WPML_URL_Converter_Url_Helper $url_helper ) {
|
||||
$this->url_helper = $url_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WPML_URL_Converter_Url_Helper
|
||||
*/
|
||||
public function get_url_helper() {
|
||||
if ( ! $this->url_helper ) {
|
||||
$this->url_helper = new WPML_URL_Converter_Url_Helper();
|
||||
}
|
||||
|
||||
return $this->url_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_URL_Converter_Lang_Param_Helper $lang_param
|
||||
*/
|
||||
public function set_lang_param( WPML_URL_Converter_Lang_Param_Helper $lang_param ) {
|
||||
$this->lang_param = $lang_param;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Slash_Management $slash_helper
|
||||
*/
|
||||
public function set_slash_helper( WPML_Slash_Management $slash_helper ) {
|
||||
$this->slash_helper = $slash_helper;
|
||||
}
|
||||
|
||||
private function get_default_language() {
|
||||
if ( $this->default_language ) {
|
||||
return $this->default_language;
|
||||
} else {
|
||||
return icl_get_setting( 'default_language' );
|
||||
}
|
||||
}
|
||||
|
||||
public function fix_trailingslashit( $source_url ) {
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
public function skip_convert_url_string( $source_url, $lang_code ) {
|
||||
/**
|
||||
* Allows plugins to skip url conversion.
|
||||
*
|
||||
* @since 4.3
|
||||
*
|
||||
* @param bool
|
||||
* @param string $source_url
|
||||
* @param string $lang_code
|
||||
* @return bool
|
||||
*/
|
||||
return apply_filters( 'wpml_skip_convert_url_string', false, $source_url, $lang_code );
|
||||
}
|
||||
|
||||
public function use_wp_login_url_converter() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
use \WPML\SuperGlobals\Server;
|
||||
|
||||
class WPML_URL_Converter_Domain_Strategy extends WPML_URL_Converter_Abstract_Strategy {
|
||||
|
||||
/** @var string[] $domains */
|
||||
private $domains = array();
|
||||
|
||||
/**
|
||||
* @param array $domains
|
||||
* @param string $default_language
|
||||
* @param array $active_languages
|
||||
*/
|
||||
public function __construct(
|
||||
$domains,
|
||||
$default_language,
|
||||
$active_languages
|
||||
) {
|
||||
parent::__construct( $default_language, $active_languages );
|
||||
|
||||
$domains = array_map( 'untrailingslashit', $domains );
|
||||
$this->domains = array_map( array( $this, 'strip_protocol' ), $domains );
|
||||
|
||||
if ( isset( $this->domains[ $default_language ] ) ) {
|
||||
unset( $this->domains[ $default_language ] );
|
||||
}
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'rest_url', [ $this, 'convertRestUrlToCurrentDomain' ], 10, 4 );
|
||||
}
|
||||
|
||||
public function remove_hooks() {
|
||||
remove_filter( 'rest_url', [ $this, 'convertRestUrlToCurrentDomain' ] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter REST url to avoid CORS error in Gutenberg.
|
||||
* https://onthegosystems.myjetbrains.com/youtrack/issue/wpmlcore-7022
|
||||
*
|
||||
* @param string $url REST URL.
|
||||
* @param string $path REST route.
|
||||
* @param int $blog_id Blog ID.
|
||||
* @param string $scheme Sanitization scheme.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertRestUrlToCurrentDomain( $url, $path, $blog_id, $scheme ) {
|
||||
$url_parts = $this->parse_domain_and_subdir( $url );
|
||||
$url_parts['host'] = Server::getServerName();
|
||||
$url = http_build_url( $url_parts );
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function get_lang_from_url_string( $url ) {
|
||||
$url = $this->strip_protocol( $url );
|
||||
|
||||
if ( strpos( $url, '?' ) ) {
|
||||
$parts = explode( '?', $url );
|
||||
$url = $parts[0];
|
||||
}
|
||||
|
||||
foreach ( $this->domains as $code => $domain ) {
|
||||
if ( $domain && strpos( trailingslashit( $url ), trailingslashit( $domain ) ) === 0 ) {
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function convert_url_string( $source_url, $lang ) {
|
||||
$original_source_url = untrailingslashit( $source_url );
|
||||
if ( is_admin() && $this->get_url_helper()->is_url_admin( $original_source_url ) ) {
|
||||
return $original_source_url;
|
||||
}
|
||||
|
||||
return $this->convert_url( $source_url, $lang );
|
||||
}
|
||||
|
||||
public function convert_admin_url_string( $source_url, $lang ) {
|
||||
return $this->convert_url( $source_url, $lang );
|
||||
}
|
||||
|
||||
private function convert_url( $source_url, $lang ) {
|
||||
if ( $this->skip_convert_url_string( $source_url, $lang ) ) {
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
$base_url = isset( $this->domains[ $lang ] ) ? $this->domains[ $lang ] : $this->get_url_helper()->get_abs_home();
|
||||
|
||||
$base_url_parts = $this->parse_domain_and_subdir( $base_url );
|
||||
$url_parts = $this->parse_domain_and_subdir( $source_url );
|
||||
|
||||
if ( isset( $base_url_parts['host'] ) ) {
|
||||
$url_parts['host'] = $base_url_parts['host'];
|
||||
}
|
||||
|
||||
$converted_url = http_build_url( $url_parts );
|
||||
|
||||
return $this->slash_helper->maybe_user_trailingslashit( $converted_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $base_url
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parse_domain_and_subdir( $base_url ) {
|
||||
$url_parts = wpml_parse_url( $base_url );
|
||||
|
||||
return is_array( $url_parts ) ?
|
||||
$this->slash_helper->parse_missing_host_from_path( $url_parts ) :
|
||||
[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_home_url_relative( $url, $language ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function strip_protocol( $url ) {
|
||||
$url_parts = wpml_parse_url( $url );
|
||||
if ( is_array( $url_parts ) ) {
|
||||
$url_parts = $this->slash_helper->parse_missing_host_from_path( $url_parts );
|
||||
unset( $url_parts['scheme'] );
|
||||
|
||||
return http_build_url( $url_parts );
|
||||
} else {
|
||||
return preg_replace( '/^https?:\/\//', '', $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_Parameter_Strategy extends WPML_URL_Converter_Abstract_Strategy {
|
||||
|
||||
public function add_hooks() {
|
||||
|
||||
}
|
||||
|
||||
public function remove_hooks() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function get_lang_from_url_string( $url ) {
|
||||
return $this->lang_param->lang_by_param( $url, false );
|
||||
}
|
||||
|
||||
public function convert_url_string( $source_url, $lang_code ) {
|
||||
if ( $this->skip_convert_url_string( $source_url, $lang_code ) ) {
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
if ( ! $lang_code || $lang_code === $this->default_language ) {
|
||||
$lang_code = '';
|
||||
}
|
||||
|
||||
$url_parts = wpml_parse_url( $source_url );
|
||||
if ( ! is_array( $url_parts ) ) {
|
||||
$url_parts = [];
|
||||
}
|
||||
|
||||
// This is required for logout url, the parameter comes urlencoded in the URI generated by WordPress.
|
||||
// If we don't decode it first, it will be misinterpreted by browsers when combined with regular parameters.
|
||||
if ( isset( $url_parts['query'] ) ) {
|
||||
$url_parts['query'] = str_replace( '&_wpnonce', '&_wpnonce', $url_parts['query'] );
|
||||
}
|
||||
|
||||
$query_args = $this->get_query_args( $url_parts );
|
||||
|
||||
if ( $lang_code ) {
|
||||
$query_args['lang'] = $lang_code;
|
||||
} else {
|
||||
unset( $query_args['lang'] );
|
||||
}
|
||||
|
||||
$url_parts['query'] = http_build_query( $query_args );
|
||||
$converted_url = http_build_url( $url_parts );
|
||||
|
||||
return $this->slash_helper->maybe_user_trailingslashit( $converted_url );
|
||||
}
|
||||
|
||||
public function convert_admin_url_string( $source_url, $lang ) {
|
||||
return $this->convert_url_string( $source_url, $lang );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $url_parts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_query_args( array $url_parts ) {
|
||||
$query = isset( $url_parts['query'] ) ? $url_parts['query'] : '';
|
||||
$query = str_replace( '?', '&', $query );
|
||||
parse_str( $query, $query_args );
|
||||
return $query_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_home_url_relative( $url, $language ) {
|
||||
if ( $language === $this->default_language ) {
|
||||
$language = '';
|
||||
}
|
||||
|
||||
if ( $language ) {
|
||||
return add_query_arg( 'lang', $language, $url );
|
||||
} else {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fix_trailingslashit( $source_url ) {
|
||||
$query = wpml_parse_url( $source_url, PHP_URL_QUERY );
|
||||
if ( ! empty( $query ) ) {
|
||||
$source_url = str_replace( '?' . $query, '', $source_url );
|
||||
}
|
||||
|
||||
$source_url = $this->slash_helper->maybe_user_trailingslashit( $source_url );
|
||||
|
||||
if ( ! empty( $query ) ) {
|
||||
$source_url .= '?' . untrailingslashit( $query );
|
||||
}
|
||||
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
public function use_wp_login_url_converter() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
class WPML_URL_Converter_Subdir_Strategy extends WPML_URL_Converter_Abstract_Strategy {
|
||||
/** @var bool */
|
||||
private $use_directory_for_default_lang;
|
||||
|
||||
/** @var array copy of $sitepress->get_settings( 'urls' ) */
|
||||
private $urls_settings;
|
||||
|
||||
/** @var string|bool */
|
||||
private $root_url;
|
||||
|
||||
/** @var array map of wpml codes to custom codes*/
|
||||
private $language_codes_map;
|
||||
private $language_codes_reverse_map;
|
||||
|
||||
/** @var bool */
|
||||
private $is_rest_request;
|
||||
|
||||
/**
|
||||
* @param bool $use_directory_for_default_lang
|
||||
* @param string $default_language
|
||||
* @param array $active_languages
|
||||
* @param array $urls_settings
|
||||
*/
|
||||
public function __construct(
|
||||
$use_directory_for_default_lang,
|
||||
$default_language,
|
||||
$active_languages,
|
||||
$urls_settings
|
||||
) {
|
||||
parent::__construct( $default_language, $active_languages );
|
||||
$this->use_directory_for_default_lang = (bool) $use_directory_for_default_lang;
|
||||
$this->urls_settings = $urls_settings;
|
||||
|
||||
$this->language_codes_map = array_combine( $active_languages, $active_languages );
|
||||
$this->language_codes_map = apply_filters( 'wpml_language_codes_map', $this->language_codes_map );
|
||||
|
||||
$this->language_codes_reverse_map = array_flip( $this->language_codes_map );
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'rest_url', [ $this, 'convertRestUrl' ] );
|
||||
}
|
||||
|
||||
public function remove_hooks() {
|
||||
remove_filter( 'rest_url', [ $this, 'convertRestUrl' ] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertRestUrl( $url ) {
|
||||
/** @var SitePress */
|
||||
global $sitepress;
|
||||
|
||||
$matchTrailingSlash = $url[ strlen( $url ) - 1 ] === '/' ? 'trailingslashit' : 'untrailingslashit';
|
||||
|
||||
return $matchTrailingSlash( $this->convert_url_string( $url, $sitepress->get_current_language() ) );
|
||||
}
|
||||
|
||||
public function get_lang_from_url_string( $url ) {
|
||||
$url_path = $this->get_url_path( wpml_strip_subdir_from_url( $url ) );
|
||||
$lang = $this->extract_lang_from_url_path( $url_path );
|
||||
|
||||
if ( $lang && in_array( $lang, $this->active_languages, true ) ) {
|
||||
return $lang;
|
||||
}
|
||||
|
||||
return $this->use_directory_for_default_lang ? null : $this->default_language;
|
||||
}
|
||||
|
||||
public function validate_language( $language, $url ) {
|
||||
if ( ! ( null === $language && $this->use_directory_for_default_lang && ! $this->get_url_helper()->is_url_admin( $url ) ) ) {
|
||||
$language = parent::validate_language( $language, $url );
|
||||
}
|
||||
|
||||
return $language;
|
||||
}
|
||||
|
||||
public function convert_url_string( $source_url, $code ) {
|
||||
if ( $this->is_root_url( $source_url ) || $this->skip_convert_url_string( $source_url, $code ) ) {
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
$source_url = $this->filter_source_url( $source_url );
|
||||
|
||||
$absolute_home_url = trailingslashit( preg_replace( '#^(http|https)://#', '', $this->get_url_helper()->get_abs_home() ) );
|
||||
$absolute_home_url = strpos( $source_url, $absolute_home_url ) === false ? trailingslashit( get_option( 'home' ) ) : $absolute_home_url;
|
||||
|
||||
$current_language = $this->get_lang_from_url_string( $source_url );
|
||||
$code = $this->get_language_of_current_dir( $code, '' );
|
||||
$current_language = $this->get_language_of_current_dir( $current_language, '' );
|
||||
|
||||
$code = isset( $this->language_codes_map[ $code ] ) ? $this->language_codes_map[ $code ] : $code;
|
||||
$current_language = isset( $this->language_codes_map[ $current_language ] ) ? $this->language_codes_map[ $current_language ] : $current_language;
|
||||
|
||||
$source_url = str_replace(
|
||||
[
|
||||
trailingslashit( $absolute_home_url . $current_language ),
|
||||
'/' . $code . '//',
|
||||
],
|
||||
[
|
||||
$code ? ( $absolute_home_url . $code . '/' ) : trailingslashit( $absolute_home_url ),
|
||||
'/' . $code . '/',
|
||||
],
|
||||
$source_url
|
||||
);
|
||||
|
||||
return $this->slash_helper->maybe_user_trailingslashit( $source_url );
|
||||
}
|
||||
|
||||
public function convert_admin_url_string( $source_url, $lang ) {
|
||||
return $source_url; // Admin strings should not be converted with language in directories
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_home_url_relative( $url, $language ) {
|
||||
$language = $this->get_language_of_current_dir( $language, '' );
|
||||
$language = isset( $this->language_codes_map[ $language ] ) ? $this->language_codes_map[ $language ] : $language;
|
||||
|
||||
if ( $language ) {
|
||||
$parts = parse_url( get_option( 'home' ) );
|
||||
$path = isset( $parts['path'] ) ? $parts['path'] : '';
|
||||
$url = preg_replace( '@^' . $path . '@', '', $url );
|
||||
|
||||
return rtrim( $path, '/' ) . '/' . $language . $url;
|
||||
} else {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
public function use_wp_login_url_converter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return true if root URL or child of root URL
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_root_url( $url ) {
|
||||
$result = false;
|
||||
|
||||
if ( isset( $this->urls_settings['root_page'], $this->urls_settings['show_on_root'] ) &&
|
||||
'page' === $this->urls_settings['show_on_root'] &&
|
||||
! empty( $this->urls_settings['directory_for_default_language'] )
|
||||
) {
|
||||
|
||||
$root_url = $this->get_root_url();
|
||||
if ( $root_url ) {
|
||||
$result = strpos( trailingslashit( $url ), $root_url ) === 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|bool
|
||||
*/
|
||||
private function get_root_url() {
|
||||
if ( null === $this->root_url ) {
|
||||
$root_post = get_post( $this->urls_settings['root_page'] );
|
||||
|
||||
if ( $root_post ) {
|
||||
$this->root_url = trailingslashit( $this->get_url_helper()->get_abs_home() ) . $root_post->post_name;
|
||||
$this->root_url = trailingslashit( $this->root_url );
|
||||
} else {
|
||||
$this->root_url = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->root_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function filter_source_url( $source_url ) {
|
||||
if ( false === strpos( $source_url, '?' ) ) {
|
||||
$source_url = trailingslashit( $source_url );
|
||||
} elseif ( false !== strpos( $source_url, '?' ) && false === strpos( $source_url, '/?' ) ) {
|
||||
$source_url = str_replace( '?', '/?', $source_url );
|
||||
}
|
||||
|
||||
return $source_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_url_path( $url ) {
|
||||
if ( strpos( $url, 'http://' ) === 0 || strpos( $url, 'https://' ) === 0 ) {
|
||||
$url_path = wpml_parse_url( $url, PHP_URL_PATH );
|
||||
} else {
|
||||
$pathparts = array_filter( explode( '/', $url ) );
|
||||
if ( count( $pathparts ) > 1 ) {
|
||||
unset( $pathparts[0] );
|
||||
$url_path = implode( '/', $pathparts );
|
||||
} else {
|
||||
$url_path = $url;
|
||||
}
|
||||
}
|
||||
|
||||
return $url_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url_path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function extract_lang_from_url_path( $url_path ) {
|
||||
$fragments = ! empty( $url_path ) ? array_filter( explode( '/', $url_path ) ) : [''];
|
||||
$lang = array_shift( $fragments );
|
||||
|
||||
$lang_get_parts = ! empty( $lang ) ? explode( '?', $lang ) : [''];
|
||||
$lang = $lang_get_parts[0];
|
||||
|
||||
return isset( $this->language_codes_reverse_map[ $lang ] ) ? $this->language_codes_reverse_map[ $lang ] : $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language_code
|
||||
* @param null|string $value_if_default_language
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function get_language_of_current_dir( $language_code, $value_if_default_language = null ) {
|
||||
if ( ! $this->use_directory_for_default_lang && $language_code === $this->default_language ) {
|
||||
return $value_if_default_language;
|
||||
}
|
||||
|
||||
return $language_code;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_URL_Converter_Strategy {
|
||||
|
||||
public function add_hooks();
|
||||
|
||||
public function remove_hooks();
|
||||
|
||||
public function convert_url_string( $source_url, $lang );
|
||||
|
||||
public function convert_admin_url_string( $source_url, $lang );
|
||||
|
||||
public function validate_language( $language, $url );
|
||||
|
||||
public function get_lang_from_url_string( $url );
|
||||
|
||||
public function get_home_url_relative( $url, $lang );
|
||||
|
||||
public function fix_trailingslashit( $source_url );
|
||||
|
||||
public function skip_convert_url_string( $url, $lang_code );
|
||||
|
||||
public function use_wp_login_url_converter();
|
||||
}
|
||||
Reference in New Issue
Block a user