Files
doitinpoland.com/wp-content/plugins/sitepress-multilingual-cms/classes/url-handling/wpml-wp-login-url-converter.php
2023-09-12 21:41:04 +02:00

280 lines
7.7 KiB
PHP

<?php
namespace WPML\UrlHandling;
use WPML\API\Sanitize;
use WPML\Element\API\Languages;
use WPML\FP\Obj;
use WPML\FP\Relation;
use WPML\FP\Str;
use WPML\LIB\WP\Option;
use WPML\LIB\WP\User;
class WPLoginUrlConverter implements \IWPML_Action {
const PRIORITY_AFTER_URL_FILTERS = 100;
const SETTINGS_KEY = 'wpml_login_page_translation';
private $rewrite_rule_not_found;
/** @var \WPML_URL_Converter $url_converter */
private $url_converter;
/** @var \SitePress $sitepress */
private $sitepress;
/**
* @param \WPML_URL_Converter $url_converter
* @param \SitePress $sitepress
*/
public function __construct( $sitepress, $url_converter ) {
$this->rewrite_rule_not_found = false;
$this->url_converter = $url_converter;
$this->sitepress = $sitepress;
}
public function add_hooks() {
add_filter( 'site_url', [ $this, 'site_url' ], self::PRIORITY_AFTER_URL_FILTERS, 3 );
add_filter( 'login_url', [ $this, 'convert_url' ] );
add_filter( 'register_url', [ $this, 'convert_url' ] );
add_filter( 'lostpassword_url', [ $this, 'convert_url' ] );
add_filter( 'request', [ $this, 'on_request' ] );
add_filter(
'wpml_get_language_from_url',
[
$this,
'wpml_login_page_language_from_url',
],
self::PRIORITY_AFTER_URL_FILTERS,
2
);
add_filter( 'registration_redirect', [ $this, 'filter_redirect_with_lang' ] );
add_filter( 'lostpassword_redirect', [ $this, 'filter_redirect_with_lang' ] );
if ( self::isEnabled() ) {
add_filter( 'logout_url', [ $this, 'convert_user_logout_url' ] );
add_filter( 'logout_redirect', [ $this, 'convert_default_redirect_url' ], 2, 10 );
}
add_action( 'generate_rewrite_rules', [ $this, 'generate_rewrite_rules' ] );
add_action( 'login_init', [ $this, 'redirect_to_login_url_with_lang' ] );
if ( is_multisite() ) {
add_filter( 'network_site_url', [ $this, 'site_url' ], self::PRIORITY_AFTER_URL_FILTERS, 3 );
add_filter( 'wp_signup_location', [ $this, 'convert_url' ] );
add_action( 'signup_hidden_fields', [ $this, 'add_signup_language_field' ] );
}
}
/**
* Converts the logout URL to be translated.
*
* @param string $url
* @return string
*/
public function convert_user_logout_url( $url ) {
$current_user_id = User::getCurrentId();
if ( $current_user_id ) {
$user_locale = User::getMetaSingle( $current_user_id, 'locale' );
if ( ! empty( $user_locale ) ) {
$language_code = $this->sitepress->get_language_code_from_locale( $user_locale );
return $this->url_converter->convert_url( $url, $language_code );
}
}
return $url;
}
public function add_signup_language_field() {
echo "<input type='hidden' name='lang' value='" . $this->sitepress->get_current_language() . "' />";
}
public function redirect_to_login_url_with_lang() {
$sitePath = Obj::propOr( '', 'path', parse_url( site_url() ) );
$requestUriWithoutPath = Str::trimPrefix( $sitePath, $_SERVER['REQUEST_URI'] );
$converted_url = site_url( $requestUriWithoutPath, 'login' );
if (
! is_multisite()
&& $converted_url != site_url( $requestUriWithoutPath )
&& wp_redirect( $converted_url, 302, 'WPML' )
) {
exit;
}
}
public function generate_rewrite_rules() {
global $wp_rewrite;
$language_rules = wpml_collect( Languages::getActive() )->mapWithKeys(
function ( $lang ) {
return [ $lang['code'] . '/wp-login.php' => 'wp-login.php' ];
}
);
$wp_rewrite->non_wp_rules = array_merge( $language_rules->toArray(), $wp_rewrite->non_wp_rules );
}
/**
* Converts the redirected string if it's the default one.
*
* @param string $redirect_to
* @param string $requested_redirect_to
* @return string
*/
public function convert_default_redirect_url( $redirect_to, $requested_redirect_to ) {
if ( '' === $requested_redirect_to ) {
return $this->convert_url( $redirect_to );
}
return $redirect_to;
}
public function filter_redirect_with_lang( $redirect_to ) {
if ( ! $redirect_to && Obj::prop( 'lang', $_GET ) ) {
$redirect_to = site_url( 'wp-login.php?checkemail=confirm', 'login' );
}
return $redirect_to;
}
public function wpml_login_page_language_from_url( $language, $url ) {
if ( $this->is_wp_login_url( $url ) ) {
if ( isset( $_GET['lang'] ) && $_GET['lang'] != $language ) {
return Sanitize::stringProp( 'lang', $_GET );
}
if ( is_multisite() && isset( $_POST['lang'] ) && $_POST['lang'] != $language ) {
return Sanitize::stringProp( 'lang', $_POST );
}
}
return $language;
}
public function site_url( $url, $path, $scheme ) {
if ( $scheme === 'login_post' || $scheme === 'login' || $this->should_convert_url_for_multisite( $url ) ) {
$url = $this->convert_url( $url );
}
return $url;
}
public function convert_url( $url ) {
$lang_param = $this->get_language_param_for_convert_url();
if ( $lang_param ) {
return add_query_arg( 'lang', $lang_param, $url );
}
return $this->url_converter->convert_url( $url );
}
public function on_request( $query_vars ) {
if ( Relation::propEq( 'name', 'wp-login.php', $query_vars ) ) {
$this->rewrite_rule_not_found = true;
} else {
$this->rewrite_rule_not_found = false;
}
if ( $this->rewrite_rule_not_found && $this->is_wp_login_action() ) {
$current_url = site_url( $_SERVER['REQUEST_URI'], 'login' );
$redirect_to = $this->remove_language_directory_from_url( $current_url );
if (
$redirect_to !== $current_url
&& wp_redirect( $redirect_to, 302, 'WPML' )
) {
exit;
}
}
return $query_vars;
}
/**
* @param bool $validateOrRollback - If true, it will be validated that the translated Login URL is accessible or rollback.
* @return void
*/
public static function enable( $validateOrRollback = false ) {
self::saveState( true, $validateOrRollback );
}
public static function disable() {
self::saveState( false );
}
/**
* @return bool
*/
public static function isEnabled() {
return Option::getOr( self::SETTINGS_KEY, false );
}
/**
* @param bool $state
* @param bool $validate - if true, will validate the change or undo it.
*
*/
public static function saveState( $state, $validate = false ) {
Option::update( self::SETTINGS_KEY, $state );
WPLoginUrlConverterRules::markRulesForUpdating( $validate );
}
private function should_convert_url_for_multisite( $url ) {
return is_multisite() && Str::includes( 'wp-activate.php', $url );
}
private function is_wp_login_url( $url ) {
return Str::includes( 'wp-login.php', $url )
|| Str::includes( 'wp-signup.php', $url )
|| Str::includes( 'wp-activate.php', $url );
}
private function is_wp_login_action() {
$actions = wpml_collect(
[
'confirm_admin_email',
'postpass',
'logout',
'lostpassword',
'retrievepassword',
'resetpass',
'rp',
'register',
'login',
'confirmaction',
]
);
return $actions->contains( Obj::prop( 'action', $_GET ) );
}
private function get_language_param_for_convert_url() {
if ( isset( $_GET['lang'] ) ) {
return Sanitize::stringProp( 'lang', $_GET );
}
if ( is_multisite() && isset( $_POST['lang'] ) ) {
return Sanitize::stringProp( 'lang', $_POST );
}
if ( $this->rewrite_rule_not_found || $this->is_subdomain_multisite() ) {
return $this->sitepress->get_current_language();
}
return null;
}
private function is_subdomain_multisite() {
return is_multisite() && defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL;
}
private function remove_language_directory_from_url( $url ) {
$lang = $this->get_language_param_for_convert_url();
$url_parts = wpml_parse_url( $url );
if ( $lang && Str::includes( '/' . $lang . '/', $url_parts['path'] ) ) {
$url = Str::replace( '/' . $lang . '/', '/', $url );
}
return $url;
}
}