first commit
This commit is contained in:
@@ -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