Files
doitinpoland.com/wp-content/plugins/sitepress-multilingual-cms/classes/language-switcher/class-wpml-ls-model-build.php
2023-09-12 21:41:04 +02:00

491 lines
14 KiB
PHP

<?php
class WPML_LS_Model_Build extends WPML_SP_User {
const LINK_CSS_CLASS = 'wpml-ls-link';
/* @var WPML_LS_Settings $settings */
private $settings;
/* @var WPML_Mobile_Detect $mobile_detect */
private $mobile_detect;
/* @var bool $is_touch_screen */
private $is_touch_screen = false;
/* @var string $css_prefix */
private $css_prefix;
private $allowed_vars = [
'languages' => 'array',
'current_language_code' => 'string',
'css_classes' => 'string',
'css_classes_link' => 'string',
'backward_compatibility' => 'array',
];
private $allowed_language_vars = [
'code' => 'string',
'url' => 'string',
'flag_url' => 'string',
'flag_title' => 'string',
'flag_alt' => 'string',
'native_name' => 'string',
'display_name' => 'string',
'is_current' => 'bool',
'css_classes' => 'string',
'db_id' => 'string',
'menu_item_parent' => 'mixed',
'is_parent' => 'bool',
'backward_compatibility' => 'array',
'flag_width' => 'int',
'flag_height' => 'int',
];
/**
* WPML_Language_Switcher_Render_Model constructor.
*
* @param WPML_LS_Settings $settings
* @param SitePress $sitepress
* @param string $css_prefix
*/
public function __construct( $settings, $sitepress, $css_prefix ) {
$this->settings = $settings;
$this->css_prefix = $css_prefix;
parent::__construct( $sitepress );
}
/**
* @param WPML_LS_Slot $slot
* @param array $template_data
*
* @return array
*/
public function get( $slot, $template_data = [] ) {
$vars = [];
$vars['current_language_code'] = $this->sitepress->get_current_language();
$vars['languages'] = $this->get_language_items( $slot, $template_data );
$vars['css_classes'] = $this->get_slot_css_classes( $slot );
$vars['css_classes_link'] = self::LINK_CSS_CLASS;
$vars = $this->add_backward_compatibility_to_wrapper( $vars, $slot );
return $this->sanitize_vars( $vars, $this->allowed_vars );
}
/**
* @param WPML_LS_Slot $slot
*
* @return string
*/
public function get_slot_css_classes( $slot ) {
$classes = [ $this->get_slot_css_main_class( $slot->group(), $slot->slug() ) ];
$classes[] = trim( $this->css_prefix, '-' );
if ( $this->sitepress->is_rtl( $this->sitepress->get_current_language() ) ) {
$classes[] = $this->css_prefix . 'rtl';
}
$classes = $this->add_user_agent_touch_device_classes( $classes );
/**
* Filter the css classes for the language switcher wrapper
* The wrapper is not available for menus
*
* @param array $classes
*/
$classes = apply_filters( 'wpml_ls_model_css_classes', $classes );
return implode( ' ', $classes );
}
/**
* @param string $group
* @param string $slug
*
* @return string
*/
public function get_slot_css_main_class( $group, $slug ) {
return $this->css_prefix . $group . '-' . $slug;
}
/**
* @return string
*/
public function get_css_prefix() {
return $this->css_prefix;
}
/**
* @param WPML_LS_Slot $slot
* @param array $template_data
*
* @return array
*/
private function get_language_items( $slot, $template_data ) {
$ret = [];
$get_ls_args = [
'skip_missing' => ! $this->settings->get_setting( 'link_empty' ),
];
if ( $slot->is_post_translations() ) {
$get_ls_args['skip_missing'] = true;
} elseif ( ( WPML_Root_Page::uses_html_root() || WPML_Root_Page::get_root_id() ) && WPML_Root_Page::is_current_request_root() ) {
$get_ls_args['skip_missing'] = false;
}
$flag_width = $slot->get( 'include_flag_width' );
$flag_height = $slot->get( 'include_flag_height' );
$languages = $this->sitepress->get_ls_languages( $get_ls_args );
$languages = is_array( $languages ) ? $languages : [];
$languages = $this->order_languages( $languages, $this->sitepress->get_current_language() );
if ( $languages ) {
foreach ( $languages as $code => $data ) {
$is_current_language = $code === $this->sitepress->get_current_language();
if ( ! $slot->get( 'display_link_for_current_lang' ) && $is_current_language ) {
continue;
}
$ret[ $code ] = [
'code' => $code,
'url' => $data['url'],
];
if ( $flag_width ) {
$ret[ $code ]['flag_width'] = $flag_width;
}
if ( $flag_height ) {
$ret[ $code ]['flag_height'] = $flag_height;
}
/* @deprecated Use 'wpml_ls_language_url' instead */
$ret[ $code ]['url'] = apply_filters( 'WPML_filter_link', $ret[ $code ]['url'], $data );
/**
* This filter allows to change the URL for each languages links in the switcher
*
* @param string $ret [ $code ]['url'] The language URL to be filtered
* @param array $data The language information
*/
$ret[ $code ]['url'] = apply_filters( 'wpml_ls_language_url', $ret[ $code ]['url'], $data );
$ret[ $code ]['url'] = $this->sitepress->get_wp_api()->is_admin() ? '#' : $ret[ $code ]['url'];
$css_classes = $this->get_language_css_classes( $slot, $code );
$display_native = $slot->get( 'display_names_in_native_lang' );
$display_name = $slot->get( 'display_names_in_current_lang' );
if ( $slot->get( 'display_flags' ) ) {
$ret[ $code ]['flag_url'] = $this->filter_flag_url( $data['country_flag_url'], $template_data );
$ret[ $code ]['flag_title'] = $data['native_name'];
$ret[ $code ]['flag_alt'] = ( $display_name || $display_native ) ? '' : $data['translated_name'];
}
if ( $display_native ) {
$ret[ $code ]['native_name'] = $data['native_name'];
}
if ( $display_name ) {
$ret[ $code ]['display_name'] = $data['translated_name'];
}
if ( $is_current_language ) {
$ret[ $code ]['is_current'] = true;
array_push( $css_classes, $this->css_prefix . 'current-language' );
}
if ( $slot->is_menu() ) {
$ret[ $code ]['db_id'] = $this->get_menu_item_id( $code, $slot );
$ret[ $code ]['menu_item_parent'] = $slot->get( 'is_hierarchical' ) && ! $is_current_language && $slot->get( 'display_link_for_current_lang' )
? $this->get_menu_item_id( $this->sitepress->get_current_language(), $slot ) : 0;
$ret[ $code ]['is_parent'] = $slot->get( 'is_hierarchical' ) && $is_current_language;
array_unshift( $css_classes, 'menu-item' );
array_push( $css_classes, $this->css_prefix . 'menu-item' );
}
$ret[ $code ]['css_classes'] = $css_classes;
}
$i = 1;
foreach ( $ret as &$lang ) {
if ( $i === 1 ) {
array_push( $lang['css_classes'], $this->css_prefix . 'first-item' );
}
if ( $i === count( $ret ) ) {
array_push( $lang['css_classes'], $this->css_prefix . 'last-item' );
}
$lang = $this->add_backward_compatibility_to_languages( $lang, $slot );
/**
* Filter the css classes for each language item
*
* @param array $lang ['css_classes']
*/
$lang['css_classes'] = apply_filters( 'wpml_ls_model_language_css_classes', $lang['css_classes'] );
$lang['css_classes'] = implode( ' ', $lang['css_classes'] );
$lang = $this->sanitize_vars( $lang, $this->allowed_language_vars );
$i++;
}
}
return $ret;
}
/**
* @param array $languages
*
* @return array
*/
private function order_languages( $languages, $current_language ) {
if ( isset( $languages[$current_language] ) ) {
$current_language_value = $languages[$current_language];
unset($languages[$current_language]);
return array_merge([$current_language => $current_language_value], $languages);
} else {
return $languages;
}
}
/**
* @param string $url
* @param array $template_data
*
* @return string
*/
private function filter_flag_url( $url, $template_data = [] ) {
$wp_upload_dir = wp_upload_dir();
$has_custom_flag = strpos( $url, $wp_upload_dir['baseurl'] . '/flags/' ) === 0 ? true : false;
if ( ! $has_custom_flag && ! empty( $template_data['flags_base_uri'] ) ) {
$url = trailingslashit( $template_data['flags_base_uri'] ) . basename( $url );
if ( isset( $template_data['flag_extension'] ) ) {
$old_ext = pathinfo( $url, PATHINFO_EXTENSION );
$url = preg_replace( '#' . $old_ext . '$#', $template_data['flag_extension'], $url, 1 );
}
}
return $url;
}
/**
* @param WPML_LS_Slot $slot
* @param string $code
*
* @return array
*/
private function get_language_css_classes( $slot, $code ) {
return [
$this->css_prefix . 'slot-' . $slot->slug(),
$this->css_prefix . 'item',
$this->css_prefix . 'item-' . $code,
];
}
/**
* @param array $classes
*
* @return array
*/
private function add_user_agent_touch_device_classes( $classes ) {
if ( is_null( $this->mobile_detect ) ) {
require_once WPML_PLUGIN_PATH . '/lib/mobile-detect.php';
$this->mobile_detect = new WPML_Mobile_Detect();
$this->is_touch_screen = $this->mobile_detect->isMobile() || $this->mobile_detect->isTablet();
}
if ( $this->is_touch_screen ) {
$classes[] = $this->css_prefix . 'touch-device';
}
return $classes;
}
/**
* @return bool
*/
private function needs_backward_compatibility() {
return (bool) $this->settings->get_setting( 'migrated' );
}
/**
* @param string $code
* @param WPML_LS_Slot $slot
*
* @return string
*/
private function get_menu_item_id( $code, $slot ) {
return $this->css_prefix . $slot->slug() . '-' . $code;
}
/**
* @param array $vars
* @param array $allowed_vars
*
* @return array
*/
private function sanitize_vars( $vars, $allowed_vars ) {
$sanitized = [];
foreach ( $allowed_vars as $allowed_var => $type ) {
if ( isset( $vars[ $allowed_var ] ) ) {
switch ( $type ) {
case 'array':
$sanitized[ $allowed_var ] = (array) $vars[ $allowed_var ];
break;
case 'string':
$sanitized[ $allowed_var ] = (string) $vars[ $allowed_var ];
break;
case 'int':
$sanitized[ $allowed_var ] = (int) $vars[ $allowed_var ];
break;
case 'bool':
$sanitized[ $allowed_var ] = (bool) $vars[ $allowed_var ];
break;
case 'mixed':
$sanitized[ $allowed_var ] = $vars[ $allowed_var ];
break;
}
}
}
return $sanitized;
}
/**
* @param array $lang
* @param WPML_LS_Slot $slot
*
* @return array
*/
private function add_backward_compatibility_to_languages( $lang, $slot ) {
if ( $this->needs_backward_compatibility() ) {
$is_current_language = isset( $lang['is_current'] ) && $lang['is_current'];
if ( $slot->is_menu() ) {
if ( $is_current_language ) {
array_unshift( $lang['css_classes'], 'menu-item-language-current' );
}
array_unshift( $lang['css_classes'], 'menu-item-language' );
}
if ( $slot->is_sidebar() || $slot->is_shortcode_actions() ) {
if ( $this->is_legacy_template( $slot->template(), 'list-vertical' )
|| $this->is_legacy_template( $slot->template(), 'list-horizontal' )
) {
array_unshift( $lang['css_classes'], 'icl-' . $lang['code'] );
$lang['backward_compatibility']['css_classes_a'] = $is_current_language ?
'lang_sel_sel' : 'lang_sel_other';
}
if ( $this->is_legacy_template( $slot->template(), 'dropdown' )
|| $this->is_legacy_template( $slot->template(), 'dropdown-click' )
) {
if ( $is_current_language ) {
$lang['backward_compatibility']['css_classes_a'] = 'lang_sel_sel icl-' . $lang['code'];
} else {
array_unshift( $lang['css_classes'], 'icl-' . $lang['code'] );
}
}
}
}
return $lang;
}
/**
* @param array $vars
* @param WPML_LS_Slot $slot
*
* @return mixed
*/
private function add_backward_compatibility_to_wrapper( $vars, $slot ) {
if ( $this->needs_backward_compatibility() ) {
if ( $slot->is_sidebar() || $slot->is_shortcode_actions() ) {
if ( $this->is_legacy_template( $slot->template(), 'list-vertical' )
|| $this->is_legacy_template( $slot->template(), 'list-horizontal' )
) {
$vars['backward_compatibility']['css_id'] = 'lang_sel_list';
if ( $this->is_legacy_template( $slot->template(), 'list-horizontal' ) ) {
$vars['css_classes'] = 'lang_sel_list_horizontal ' . $vars['css_classes'];
} else {
$vars['css_classes'] = 'lang_sel_list_vertical ' . $vars['css_classes'];
}
}
if ( $this->is_legacy_template( $slot->template(), 'dropdown' ) ) {
$vars['backward_compatibility']['css_id'] = 'lang_sel';
}
if ( $this->is_legacy_template( $slot->template(), 'dropdown-click' ) ) {
$vars['backward_compatibility']['css_id'] = 'lang_sel_click';
}
}
if ( $slot->is_post_translations() ) {
$vars['css_classes'] = 'icl_post_in_other_langs ' . $vars['css_classes'];
}
if ( $slot->is_footer() ) {
$vars['backward_compatibility']['css_id'] = 'lang_sel_footer';
}
$vars['backward_compatibility']['css_classes_flag'] = 'iclflag';
$vars['backward_compatibility']['css_classes_native'] = 'icl_lang_sel_native';
$vars['backward_compatibility']['css_classes_display'] = 'icl_lang_sel_translated';
$vars['backward_compatibility']['css_classes_bracket'] = 'icl_lang_sel_bracket';
}
return $vars;
}
/**
* @param string $template_slug
* @param string|null $type
*
* @return bool
*/
private function is_legacy_template( $template_slug, $type = null ) {
$templates = $this->settings->get_core_templates();
$ret = in_array( $template_slug, $templates, true );
if ( $ret && array_key_exists( $type, $templates ) ) {
$ret = $templates[ $type ] === $template_slug;
}
return $ret;
}
}