368 lines
11 KiB
PHP
368 lines
11 KiB
PHP
<?php
|
|
|
|
use WPML\Element\API\Languages;
|
|
use WPML\FP\Maybe;
|
|
use WPML\FP\Relation;
|
|
use WPML\Language\Detection\CookieLanguage;
|
|
use WPML\LIB\WP\Hooks;
|
|
use WPML\LIB\WP\User;
|
|
use WPML\LIB\WP\Option;
|
|
use WPML\UIPage;
|
|
use WPML\UrlHandling\WPLoginUrlConverter;
|
|
use function WPML\Container\make;
|
|
use function WPML\FP\spreadArgs;
|
|
|
|
/**
|
|
* @package wpml-core
|
|
* @subpackage wpml-user-language
|
|
*/
|
|
class WPML_User_Language {
|
|
/** @var SitePress $sitepress */
|
|
protected $sitepress;
|
|
|
|
private $language_changes_history = array();
|
|
private $admin_language_changes_history = array();
|
|
|
|
/**
|
|
* @var \wpdb|null
|
|
*/
|
|
private $wpdb;
|
|
|
|
/**
|
|
* WPML_User_Language constructor.
|
|
*
|
|
* @param SitePress $sitepress
|
|
* @param wpdb|null $wpdb
|
|
*/
|
|
public function __construct( SitePress $sitepress, wpdb $wpdb = null ) {
|
|
$this->sitepress = $sitepress;
|
|
|
|
if ( ! $wpdb ) {
|
|
global $wpdb;
|
|
}
|
|
$this->wpdb = $wpdb;
|
|
|
|
$this->register_hooks();
|
|
}
|
|
|
|
public function register_hooks() {
|
|
Hooks::onAction( 'wp_login', 10, 2 )
|
|
->then( spreadArgs( [ $this, 'update_user_lang_from_login' ] ) );
|
|
|
|
Hooks::onAction( 'init' )
|
|
->then( [ $this, 'add_how_to_set_notice' ] );
|
|
|
|
Hooks::onAction( 'wpml_user_profile_options' )
|
|
->then( [ $this, 'show_ui_to_enable_login_translation' ] );
|
|
|
|
add_action( 'wpml_switch_language_for_email', array( $this, 'switch_language_for_email_action' ), 10, 1 );
|
|
add_action( 'wpml_restore_language_from_email', array( $this, 'restore_language_from_email_action' ), 10, 0 );
|
|
add_action( 'profile_update', array( $this, 'sync_admin_user_language_action' ), 10, 2 );
|
|
add_action( 'wpml_language_cookie_added', array( $this, 'update_user_lang_on_cookie_update' ) );
|
|
|
|
if ( $this->is_editing_current_profile() || $this->is_editing_other_profile() ) {
|
|
add_filter( 'get_available_languages', array( $this, 'intersect_wpml_wp_languages' ) );
|
|
}
|
|
|
|
register_activation_hook(
|
|
WPML_PLUGIN_PATH . '/' . WPML_PLUGIN_FILE,
|
|
[ $this, 'update_user_lang_on_site_setup' ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array $wp_languages
|
|
*
|
|
* @return array
|
|
*/
|
|
public function intersect_wpml_wp_languages( $wp_languages ) {
|
|
$active_wpml_languages = wp_list_pluck( $this->sitepress->get_active_languages(), 'default_locale' );
|
|
$active_wpml_codes = array_flip( $active_wpml_languages );
|
|
$intersect_languages_by_locale = array_intersect( $active_wpml_languages, $wp_languages );
|
|
$intersect_languages_by_code = array_intersect( $active_wpml_codes, $wp_languages );
|
|
|
|
return array_merge( $intersect_languages_by_code, $intersect_languages_by_locale );
|
|
}
|
|
|
|
/**
|
|
* @param string $email
|
|
*/
|
|
public function switch_language_for_email_action( $email ) {
|
|
$this->switch_language_for_email( $email );
|
|
}
|
|
|
|
/**
|
|
* @param string $email
|
|
*/
|
|
private function switch_language_for_email( $email ) {
|
|
$language = apply_filters( 'wpml_user_language', null, $email );
|
|
|
|
if ( $language ) {
|
|
$user_language = $this->sitepress->get_current_language();
|
|
$admin_language = $this->sitepress->get_admin_language();
|
|
|
|
if ( $language !== $user_language || $language !== $admin_language ) {
|
|
$this->language_changes_history[] = $user_language;
|
|
$this->admin_language_changes_history[] = $admin_language;
|
|
|
|
$this->sitepress->switch_lang( $language, true );
|
|
|
|
$this->sitepress->set_admin_language( $language );
|
|
}
|
|
}
|
|
}
|
|
|
|
public function restore_language_from_email_action() {
|
|
$this->wpml_restore_language_from_email();
|
|
}
|
|
|
|
private function wpml_restore_language_from_email() {
|
|
if ( count( $this->language_changes_history ) > 0 ) {
|
|
$this->sitepress->switch_lang( array_pop( $this->language_changes_history ), true );
|
|
}
|
|
if ( count( $this->admin_language_changes_history ) > 0 ) {
|
|
$this->sitepress->set_admin_language( array_pop( $this->admin_language_changes_history ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $user_id
|
|
*/
|
|
public function sync_admin_user_language_action( $user_id ) {
|
|
if ( $this->user_needs_sync_admin_lang() ) {
|
|
$this->sync_admin_user_language( $user_id );
|
|
}
|
|
}
|
|
|
|
public function sync_default_admin_user_languages() {
|
|
$sql_users = 'SELECT user_id FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = %s AND meta_value = %s';
|
|
$query_users = $this->wpdb->prepare( $sql_users, array( 'locale', '' ) );
|
|
$user_ids = $this->wpdb->get_col( $query_users );
|
|
|
|
if ( $user_ids ) {
|
|
$language = $this->sitepress->get_default_language();
|
|
|
|
$sql = 'UPDATE ' . $this->wpdb->usermeta . ' SET meta_value = %s WHERE meta_key = %s and user_id IN (' . wpml_prepare_in( $user_ids ) . ')';
|
|
$query = $this->wpdb->prepare( $sql, array( $language, 'icl_admin_language' ) );
|
|
|
|
$this->wpdb->query( $query );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $user_id
|
|
*/
|
|
private function sync_admin_user_language( $user_id ) {
|
|
$wp_language = get_user_meta( $user_id, 'locale', true );
|
|
|
|
if ( $wp_language ) {
|
|
$user_language = $this->select_language_code_from_locale( $wp_language );
|
|
} else {
|
|
$user_language = $this->sitepress->get_default_language();
|
|
}
|
|
update_user_meta( $user_id, 'icl_admin_language', $user_language );
|
|
|
|
if ( $this->user_admin_language_for_edit( $user_id ) && $this->is_editing_current_profile() ) {
|
|
$this->set_language_cookie( $user_language );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $wp_locale
|
|
*
|
|
* @return null|string
|
|
*/
|
|
private function select_language_code_from_locale( $wp_locale ) {
|
|
$code = $this->sitepress->get_language_code_from_locale( $wp_locale );
|
|
|
|
if ( ! $code ) {
|
|
$guess_code = strtolower( substr( $wp_locale, 0, 2 ) );
|
|
$guess_locale = $this->sitepress->get_locale_from_language_code( $guess_code );
|
|
|
|
if ( $guess_locale ) {
|
|
$code = $guess_code;
|
|
}
|
|
}
|
|
|
|
return $code;
|
|
}
|
|
|
|
private function user_needs_sync_admin_lang() {
|
|
$wp_api = $this->sitepress->get_wp_api();
|
|
|
|
return $wp_api->version_compare_naked( get_bloginfo( 'version' ), '4.7', '>=' );
|
|
}
|
|
|
|
private function set_language_cookie( $user_language ) {
|
|
global $wpml_request_handler;
|
|
|
|
if ( is_object( $wpml_request_handler ) ) {
|
|
$wpml_request_handler->set_language_cookie( $user_language );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $user_id
|
|
*
|
|
* @return mixed
|
|
*/
|
|
private function user_admin_language_for_edit( $user_id ) {
|
|
return get_user_meta( $user_id, 'icl_admin_language_for_edit', true );
|
|
}
|
|
|
|
/**
|
|
* @param string $lang
|
|
*/
|
|
public function update_user_lang_on_cookie_update( $lang ) {
|
|
$user_id = get_current_user_id();
|
|
|
|
if ( $this->user_needs_sync_admin_lang() && $user_id && $this->user_admin_language_for_edit( $user_id ) ) {
|
|
update_user_meta( $user_id, 'icl_admin_language', $lang );
|
|
|
|
$wpLang = Maybe::of( $lang )
|
|
->map( Languages::getLanguageDetails() )
|
|
->map( Languages::getWPLocale() )
|
|
->getOrElse( null );
|
|
|
|
update_user_meta( $user_id, 'locale', $wpLang );
|
|
}
|
|
}
|
|
|
|
private function is_editing_current_profile() {
|
|
global $pagenow;
|
|
|
|
return isset( $pagenow ) && 'profile.php' === $pagenow;
|
|
}
|
|
|
|
private function is_editing_other_profile() {
|
|
global $pagenow;
|
|
|
|
return isset( $pagenow ) && 'user-edit.php' === $pagenow;
|
|
}
|
|
|
|
public function update_user_lang_on_site_setup() {
|
|
$current_user_id = get_current_user_id();
|
|
$wp_user_lang = get_user_meta( $current_user_id, 'locale', true );
|
|
|
|
if ( ! $wp_user_lang ) {
|
|
return;
|
|
}
|
|
|
|
$lang_code_from_locale = $this->select_language_code_from_locale( $wp_user_lang );
|
|
$wpml_user_lang = get_user_meta( $current_user_id, 'icl_admin_language', true );
|
|
|
|
if ( $current_user_id && $lang_code_from_locale && ! $wpml_user_lang ) {
|
|
update_user_meta( $current_user_id, 'icl_admin_language', $lang_code_from_locale );
|
|
}
|
|
}
|
|
|
|
public function update_user_lang_from_login( $username, WP_User $user ) {
|
|
$cookieName = 'wp-wpml_login_lang';
|
|
Maybe::fromNullable( make( CookieLanguage::class, [ ':defaultLanguage' => '' ] )->get( $cookieName ) )
|
|
->map( [ $this->sitepress, 'get_locale_from_language_code' ] )
|
|
->reject( Relation::equals( User::getMetaSingle( $user->ID, 'locale' ) ) )
|
|
->map( User::updateMeta( $user->ID, 'locale' ) );
|
|
|
|
$secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) );
|
|
setcookie( $cookieName, '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, $secure );
|
|
}
|
|
|
|
public function add_how_to_set_notice() {
|
|
global $pagenow;
|
|
$adminNotices = wpml_get_admin_notices();
|
|
|
|
$noticeId = self::class . 'how_to_set_notice';
|
|
$noticeGroup = self::class;
|
|
|
|
if (
|
|
$pagenow !== 'profile.php'
|
|
&& ! Option::getOr( WPLoginUrlConverter::SETTINGS_KEY, false )
|
|
) {
|
|
$notice = new WPML_Notice(
|
|
$noticeId,
|
|
self::getNotice(),
|
|
$noticeGroup
|
|
);
|
|
$notice->set_css_class_types( [ 'info' ] );
|
|
$notice->add_capability_check( [ 'manage_options' ] );
|
|
$notice->set_dismissible( true );
|
|
$notice->add_user_restriction( User::getCurrentId() );
|
|
$adminNotices->add_notice( $notice );
|
|
} else {
|
|
$adminNotices->remove_notice( $noticeGroup, $noticeId );
|
|
}
|
|
|
|
}
|
|
|
|
public static function getNotice() {
|
|
ob_start();
|
|
?>
|
|
<h2><?php esc_html_e( 'Do you want the WordPress admin to be in a different language?', 'sitepress' ); ?></h2>
|
|
<p>
|
|
<?php esc_html_e( 'WPML lets each user choose the admin language, unrelated of the language in which visitors will see the front-end of the site.', 'sitepress' ); ?>
|
|
<br/>
|
|
<br/>
|
|
<?php
|
|
/* translators: %s is replaced with the word 'profile' wrapped in a link */
|
|
echo sprintf(
|
|
__( 'Go to your %s to choose your admin language.', 'sitepress' ),
|
|
'<a href="' . admin_url( 'profile.php' ) . '">' . __( 'profile', 'sitepress' ) . '</a>'
|
|
);
|
|
?>
|
|
</p>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
public function show_ui_to_enable_login_translation() {
|
|
if ( current_user_can( 'manage_options' ) && ! WPLoginUrlConverter::isEnabled() ) {
|
|
|
|
$settingsPage = UIPage::getSettings() . '#ml-content-setup-sec-wp-login';
|
|
$settingsPageLink = '<a href="' . $settingsPage . '">' . __( 'WPML->Settings', 'sitepress' ) . '</a>';
|
|
// translators: %s link to WPML Settings page
|
|
$message = esc_html__( 'WPML will include a language switcher on the WordPress login page. To change this, go to %s.', 'sitepress' );
|
|
?>
|
|
<tr class="user-language-wrap">
|
|
<th><?php esc_html_e( 'Login Page:', 'sitepress' ); ?></th>
|
|
<td>
|
|
<?php wp_nonce_field( 'icl_login_page_translation_nonce', 'icl_login_page_translation_nonce' ); ?>
|
|
<div id="wpml-login-translation">
|
|
<p>
|
|
<?php esc_html_e( 'Your site currently has language switching for the login page disabled.', 'sitepress' ); ?>
|
|
<button type="button" class="button wpml-login-activate">
|
|
<?php esc_html_e( 'Activate', 'sitepress' ); ?>
|
|
</button>
|
|
<span class="spinner" style="float: none"></span>
|
|
</p>
|
|
</div>
|
|
<div id="wpml-login-translation-updated" style="display:none">
|
|
<?php echo sprintf( $message, $settingsPageLink ); ?>
|
|
</div>
|
|
<script type="text/javascript">
|
|
jQuery(function ($) {
|
|
$('.wpml-login-activate').click(function () {
|
|
$(this).prop('disabled', true);
|
|
$(this).parent().find('.spinner').css('visibility', 'visible');
|
|
$.ajax({
|
|
url: ajaxurl,
|
|
type: "POST",
|
|
data: {
|
|
icl_ajx_action: 'icl_login_page_translation',
|
|
_icl_nonce: $('#icl_login_page_translation_nonce').val(),
|
|
login_page_translation: 1
|
|
},
|
|
success: function (response) {
|
|
$('#wpml-login-translation').hide();
|
|
$('#wpml-login-translation-updated').css('display', 'block');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
}
|
|
}
|