[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Plugin 5 * @subpackage System.languagefilter 6 * 7 * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 10 * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace 11 */ 12 13 use Joomla\CMS\Application\ApplicationHelper; 14 use Joomla\CMS\Application\CMSApplication; 15 use Joomla\CMS\Application\CMSApplicationInterface; 16 use Joomla\CMS\Association\AssociationServiceInterface; 17 use Joomla\CMS\Component\ComponentHelper; 18 use Joomla\CMS\Factory; 19 use Joomla\CMS\Filesystem\Folder; 20 use Joomla\CMS\Language\Associations; 21 use Joomla\CMS\Language\Language; 22 use Joomla\CMS\Language\LanguageHelper; 23 use Joomla\CMS\Language\Multilanguage; 24 use Joomla\CMS\Language\Text; 25 use Joomla\CMS\Plugin\CMSPlugin; 26 use Joomla\CMS\Router\Route; 27 use Joomla\CMS\Router\Router; 28 use Joomla\CMS\Router\SiteRouter; 29 use Joomla\CMS\Uri\Uri; 30 use Joomla\Component\Menus\Administrator\Helper\MenusHelper; 31 use Joomla\Registry\Registry; 32 use Joomla\String\StringHelper; 33 34 // phpcs:disable PSR1.Files.SideEffects 35 \defined('_JEXEC') or die; 36 // phpcs:enable PSR1.Files.SideEffects 37 38 /** 39 * Joomla! Language Filter Plugin. 40 * 41 * @since 1.6 42 */ 43 class PlgSystemLanguageFilter extends CMSPlugin 44 { 45 /** 46 * The routing mode. 47 * 48 * @var boolean 49 * @since 2.5 50 */ 51 protected $mode_sef; 52 53 /** 54 * Available languages by sef. 55 * 56 * @var array 57 * @since 1.6 58 */ 59 protected $sefs; 60 61 /** 62 * Available languages by language codes. 63 * 64 * @var array 65 * @since 2.5 66 */ 67 protected $lang_codes; 68 69 /** 70 * The current language code. 71 * 72 * @var string 73 * @since 3.4.2 74 */ 75 protected $current_lang; 76 77 /** 78 * The default language code. 79 * 80 * @var string 81 * @since 2.5 82 */ 83 protected $default_lang; 84 85 /** 86 * The logged user language code. 87 * 88 * @var string 89 * @since 3.3.1 90 */ 91 private $user_lang_code; 92 93 /** 94 * Application object. 95 * 96 * @var CMSApplicationInterface 97 * @since 3.3 98 */ 99 protected $app; 100 101 /** 102 * Constructor. 103 * 104 * @param object &$subject The object to observe 105 * @param array $config An optional associative array of configuration settings. 106 * 107 * @since 1.6 108 */ 109 public function __construct(&$subject, $config) 110 { 111 parent::__construct($subject, $config); 112 113 // Setup language data. 114 $this->mode_sef = $this->app->get('sef', 0); 115 $this->sefs = LanguageHelper::getLanguages('sef'); 116 $this->lang_codes = LanguageHelper::getLanguages('lang_code'); 117 $this->default_lang = ComponentHelper::getParams('com_languages')->get('site', 'en-GB'); 118 119 // If language filter plugin is executed in a site page. 120 if ($this->app->isClient('site')) { 121 $levels = $this->app->getIdentity()->getAuthorisedViewLevels(); 122 123 foreach ($this->sefs as $sef => $language) { 124 // @todo: In Joomla 2.5.4 and earlier access wasn't set. Non modified Content Languages got 0 as access value 125 // we also check if frontend language exists and is enabled 126 if ( 127 ($language->access && !in_array($language->access, $levels)) 128 || (!array_key_exists($language->lang_code, LanguageHelper::getInstalledLanguages(0))) 129 ) { 130 unset($this->lang_codes[$language->lang_code], $this->sefs[$language->sef]); 131 } 132 } 133 } else { 134 // If language filter plugin is executed in an admin page (ex: Route site). 135 // Set current language to default site language, fallback to en-GB if there is no content language for the default site language. 136 $this->current_lang = isset($this->lang_codes[$this->default_lang]) ? $this->default_lang : 'en-GB'; 137 138 foreach ($this->sefs as $sef => $language) { 139 if (!array_key_exists($language->lang_code, LanguageHelper::getInstalledLanguages(0))) { 140 unset($this->lang_codes[$language->lang_code]); 141 unset($this->sefs[$language->sef]); 142 } 143 } 144 } 145 } 146 147 /** 148 * After initialise. 149 * 150 * @return void 151 * 152 * @since 1.6 153 */ 154 public function onAfterInitialise() 155 { 156 $this->app->item_associations = $this->params->get('item_associations', 0); 157 158 // We need to make sure we are always using the site router, even if the language plugin is executed in admin app. 159 // Router can be injected when turned into a DI built plugin 160 $router = Factory::getContainer()->get(SiteRouter::class); 161 162 // Attach build rules for language SEF. 163 $router->attachBuildRule(array($this, 'preprocessBuildRule'), Router::PROCESS_BEFORE); 164 165 if ($this->mode_sef) { 166 $router->attachBuildRule(array($this, 'buildRule'), Router::PROCESS_BEFORE); 167 $router->attachBuildRule(array($this, 'postprocessSEFBuildRule'), Router::PROCESS_AFTER); 168 } else { 169 $router->attachBuildRule(array($this, 'postprocessNonSEFBuildRule'), Router::PROCESS_AFTER); 170 } 171 172 // Attach parse rule. 173 $router->attachParseRule(array($this, 'parseRule'), Router::PROCESS_BEFORE); 174 } 175 176 /** 177 * After route. 178 * 179 * @return void 180 * 181 * @since 3.4 182 */ 183 public function onAfterRoute() 184 { 185 // Add custom site name. 186 if ($this->app->isClient('site') && isset($this->lang_codes[$this->current_lang]) && $this->lang_codes[$this->current_lang]->sitename) { 187 $this->app->set('sitename', $this->lang_codes[$this->current_lang]->sitename); 188 } 189 } 190 191 /** 192 * Add build preprocess rule to router. 193 * 194 * @param Router &$router Router object. 195 * @param Uri &$uri Uri object. 196 * 197 * @return void 198 * 199 * @since 3.4 200 */ 201 public function preprocessBuildRule(&$router, &$uri) 202 { 203 $lang = $uri->getVar('lang', $this->current_lang); 204 205 if (isset($this->sefs[$lang])) { 206 $lang = $this->sefs[$lang]->lang_code; 207 } 208 209 $uri->setVar('lang', $lang); 210 } 211 212 /** 213 * Add build rule to router. 214 * 215 * @param Router &$router Router object. 216 * @param Uri &$uri Uri object. 217 * 218 * @return void 219 * 220 * @since 1.6 221 */ 222 public function buildRule(&$router, &$uri) 223 { 224 $lang = $uri->getVar('lang'); 225 226 if (isset($this->lang_codes[$lang])) { 227 $sef = $this->lang_codes[$lang]->sef; 228 } else { 229 $sef = $this->lang_codes[$this->current_lang]->sef; 230 } 231 232 if ( 233 !$this->params->get('remove_default_prefix', 0) 234 || $lang !== $this->default_lang 235 || $lang !== $this->current_lang 236 ) { 237 $uri->setPath($uri->getPath() . '/' . $sef . '/'); 238 } 239 } 240 241 /** 242 * postprocess build rule for SEF URLs 243 * 244 * @param Router &$router Router object. 245 * @param Uri &$uri Uri object. 246 * 247 * @return void 248 * 249 * @since 3.4 250 */ 251 public function postprocessSEFBuildRule(&$router, &$uri) 252 { 253 $uri->delVar('lang'); 254 } 255 256 /** 257 * postprocess build rule for non-SEF URLs 258 * 259 * @param Router &$router Router object. 260 * @param Uri &$uri Uri object. 261 * 262 * @return void 263 * 264 * @since 3.4 265 */ 266 public function postprocessNonSEFBuildRule(&$router, &$uri) 267 { 268 $lang = $uri->getVar('lang'); 269 270 if (isset($this->lang_codes[$lang])) { 271 $uri->setVar('lang', $this->lang_codes[$lang]->sef); 272 } 273 } 274 275 /** 276 * Add parse rule to router. 277 * 278 * @param Router &$router Router object. 279 * @param Uri &$uri Uri object. 280 * 281 * @return void 282 * 283 * @since 1.6 284 */ 285 public function parseRule(&$router, &$uri) 286 { 287 // Did we find the current and existing language yet? 288 $found = false; 289 290 // Are we in SEF mode or not? 291 if ($this->mode_sef) { 292 $path = $uri->getPath(); 293 $parts = explode('/', $path); 294 295 $sef = StringHelper::strtolower($parts[0]); 296 297 // Do we have a URL Language Code ? 298 if (!isset($this->sefs[$sef])) { 299 // Check if remove default URL language code is set 300 if ($this->params->get('remove_default_prefix', 0)) { 301 if ($parts[0]) { 302 // We load a default site language page 303 $lang_code = $this->default_lang; 304 } else { 305 // We check for an existing language cookie 306 $lang_code = $this->getLanguageCookie(); 307 } 308 } else { 309 $lang_code = $this->getLanguageCookie(); 310 } 311 312 // No language code. Try using browser settings or default site language 313 if (!$lang_code && $this->params->get('detect_browser', 0) == 1) { 314 $lang_code = LanguageHelper::detectLanguage(); 315 } 316 317 if (!$lang_code) { 318 $lang_code = $this->default_lang; 319 } 320 321 if ($lang_code === $this->default_lang && $this->params->get('remove_default_prefix', 0)) { 322 $found = true; 323 } 324 } else { 325 // We found our language 326 $found = true; 327 $lang_code = $this->sefs[$sef]->lang_code; 328 329 // If we found our language, but it's the default language and we don't want a prefix for that, we are on a wrong URL. 330 // Or we try to change the language back to the default language. We need a redirect to the proper URL for the default language. 331 if ($lang_code === $this->default_lang && $this->params->get('remove_default_prefix', 0)) { 332 // Create a cookie. 333 $this->setLanguageCookie($lang_code); 334 335 $found = false; 336 array_shift($parts); 337 $path = implode('/', $parts); 338 } 339 340 // We have found our language and the first part of our URL is the language prefix 341 if ($found) { 342 array_shift($parts); 343 344 // Empty parts array when "index.php" is the only part left. 345 if (count($parts) === 1 && $parts[0] === 'index.php') { 346 $parts = array(); 347 } 348 349 $uri->setPath(implode('/', $parts)); 350 } 351 } 352 } else { 353 // We are not in SEF mode 354 $lang_code = $this->getLanguageCookie(); 355 356 if (!$lang_code && $this->params->get('detect_browser', 1)) { 357 $lang_code = LanguageHelper::detectLanguage(); 358 } 359 360 if (!isset($this->lang_codes[$lang_code])) { 361 $lang_code = $this->default_lang; 362 } 363 } 364 365 $lang = $uri->getVar('lang', $lang_code); 366 367 if (isset($this->sefs[$lang])) { 368 // We found our language 369 $found = true; 370 $lang_code = $this->sefs[$lang]->lang_code; 371 } 372 373 // We are called via POST or the nolangfilter url parameter was set. We don't care about the language 374 // and simply set the default language as our current language. 375 if ( 376 $this->app->input->getMethod() === 'POST' 377 || $this->app->input->get('nolangfilter', 0) == 1 378 || count($this->app->input->post) > 0 379 || count($this->app->input->files) > 0 380 ) { 381 $found = true; 382 383 if (!isset($lang_code)) { 384 $lang_code = $this->getLanguageCookie(); 385 } 386 387 if (!$lang_code && $this->params->get('detect_browser', 1)) { 388 $lang_code = LanguageHelper::detectLanguage(); 389 } 390 391 if (!isset($this->lang_codes[$lang_code])) { 392 $lang_code = $this->default_lang; 393 } 394 } 395 396 // We have not found the language and thus need to redirect 397 if (!$found) { 398 // Lets find the default language for this user 399 if (!isset($lang_code) || !isset($this->lang_codes[$lang_code])) { 400 $lang_code = false; 401 402 if ($this->params->get('detect_browser', 1)) { 403 $lang_code = LanguageHelper::detectLanguage(); 404 405 if (!isset($this->lang_codes[$lang_code])) { 406 $lang_code = false; 407 } 408 } 409 410 if (!$lang_code) { 411 $lang_code = $this->default_lang; 412 } 413 } 414 415 if ($this->mode_sef) { 416 // Use the current language sef or the default one. 417 if ( 418 $lang_code !== $this->default_lang 419 || !$this->params->get('remove_default_prefix', 0) 420 ) { 421 $path = $this->lang_codes[$lang_code]->sef . '/' . $path; 422 } 423 424 $uri->setPath($path); 425 426 if (!$this->app->get('sef_rewrite')) { 427 $uri->setPath('index.php/' . $uri->getPath()); 428 } 429 430 $redirectUri = $uri->base() . $uri->toString(array('path', 'query', 'fragment')); 431 } else { 432 $uri->setVar('lang', $this->lang_codes[$lang_code]->sef); 433 $redirectUri = $uri->base() . 'index.php?' . $uri->getQuery(); 434 } 435 436 // Set redirect HTTP code to "302 Found". 437 $redirectHttpCode = 302; 438 439 // If selected language is the default language redirect code is "301 Moved Permanently". 440 if ($lang_code === $this->default_lang) { 441 $redirectHttpCode = 301; 442 443 // We cannot cache this redirect in browser. 301 is cacheable by default so we need to force to not cache it in browsers. 444 $this->app->setHeader('Expires', 'Wed, 17 Aug 2005 00:00:00 GMT', true); 445 $this->app->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true); 446 $this->app->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate', false); 447 $this->app->sendHeaders(); 448 } 449 450 // Redirect to language. 451 $this->app->redirect($redirectUri, $redirectHttpCode); 452 } 453 454 // We have found our language and now need to set the cookie and the language value in our system 455 $array = array('lang' => $lang_code); 456 $this->current_lang = $lang_code; 457 458 // Set the request var. 459 $this->app->input->set('language', $lang_code); 460 $this->app->set('language', $lang_code); 461 $language = $this->app->getLanguage(); 462 463 if ($language->getTag() !== $lang_code) { 464 $language_new = Language::getInstance($lang_code, (bool) $this->app->get('debug_lang')); 465 466 foreach ($language->getPaths() as $extension => $files) { 467 if (strpos($extension, 'plg_system') !== false) { 468 $extension_name = substr($extension, 11); 469 470 $language_new->load($extension, JPATH_ADMINISTRATOR) 471 || $language_new->load($extension, JPATH_PLUGINS . '/system/' . $extension_name); 472 473 continue; 474 } 475 476 $language_new->load($extension); 477 } 478 479 Factory::$language = $language_new; 480 $this->app->loadLanguage($language_new); 481 } 482 483 // Create a cookie. 484 if ($this->getLanguageCookie() !== $lang_code) { 485 $this->setLanguageCookie($lang_code); 486 } 487 488 return $array; 489 } 490 491 /** 492 * Reports the privacy related capabilities for this plugin to site administrators. 493 * 494 * @return array 495 * 496 * @since 3.9.0 497 */ 498 public function onPrivacyCollectAdminCapabilities() 499 { 500 $this->loadLanguage(); 501 502 return array( 503 Text::_('PLG_SYSTEM_LANGUAGEFILTER') => array( 504 Text::_('PLG_SYSTEM_LANGUAGEFILTER_PRIVACY_CAPABILITY_LANGUAGE_COOKIE'), 505 ), 506 ); 507 } 508 509 /** 510 * Before store user method. 511 * 512 * Method is called before user data is stored in the database. 513 * 514 * @param array $user Holds the old user data. 515 * @param boolean $isnew True if a new user is stored. 516 * @param array $new Holds the new user data. 517 * 518 * @return void 519 * 520 * @since 1.6 521 */ 522 public function onUserBeforeSave($user, $isnew, $new) 523 { 524 if (array_key_exists('params', $user) && $this->params->get('automatic_change', 1) == 1) { 525 $registry = new Registry($user['params']); 526 $this->user_lang_code = $registry->get('language'); 527 528 if (empty($this->user_lang_code)) { 529 $this->user_lang_code = $this->current_lang; 530 } 531 } 532 } 533 534 /** 535 * After store user method. 536 * 537 * Method is called after user data is stored in the database. 538 * 539 * @param array $user Holds the new user data. 540 * @param boolean $isnew True if a new user is stored. 541 * @param boolean $success True if user was successfully stored in the database. 542 * @param string $msg Message. 543 * 544 * @return void 545 * 546 * @since 1.6 547 */ 548 public function onUserAfterSave($user, $isnew, $success, $msg): void 549 { 550 if ($success && array_key_exists('params', $user) && $this->params->get('automatic_change', 1) == 1) { 551 $registry = new Registry($user['params']); 552 $lang_code = $registry->get('language'); 553 554 if (empty($lang_code)) { 555 $lang_code = $this->current_lang; 556 } 557 558 if ($lang_code === $this->user_lang_code || !isset($this->lang_codes[$lang_code])) { 559 if ($this->app->isClient('site')) { 560 $this->app->setUserState('com_users.edit.profile.redirect', null); 561 } 562 } else { 563 if ($this->app->isClient('site')) { 564 $this->app->setUserState('com_users.edit.profile.redirect', 'index.php?Itemid=' 565 . $this->app->getMenu()->getDefault($lang_code)->id . '&lang=' . $this->lang_codes[$lang_code]->sef); 566 567 // Create a cookie. 568 $this->setLanguageCookie($lang_code); 569 } 570 } 571 } 572 } 573 574 /** 575 * Method to handle any login logic and report back to the subject. 576 * 577 * @param array $user Holds the user data. 578 * @param array $options Array holding options (remember, autoregister, group). 579 * 580 * @return boolean True on success. 581 * 582 * @since 1.5 583 */ 584 public function onUserLogin($user, $options = array()) 585 { 586 if ($this->app->isClient('site')) { 587 $menu = $this->app->getMenu(); 588 589 if ($this->params->get('automatic_change', 1)) { 590 $assoc = Associations::isEnabled(); 591 $lang_code = $user['language']; 592 593 // If no language is specified for this user, we set it to the site default language 594 if (empty($lang_code)) { 595 $lang_code = $this->default_lang; 596 } 597 598 // The language has been deleted/disabled or the related content language does not exist/has been unpublished 599 // or the related home page does not exist/has been unpublished 600 if ( 601 !array_key_exists($lang_code, $this->lang_codes) 602 || !array_key_exists($lang_code, Multilanguage::getSiteHomePages()) 603 || !Folder::exists(JPATH_SITE . '/language/' . $lang_code) 604 ) { 605 $lang_code = $this->current_lang; 606 } 607 608 // Try to get association from the current active menu item 609 $active = $menu->getActive(); 610 611 $foundAssociation = false; 612 613 /** 614 * Looking for associations. 615 * If the login menu item form contains an internal URL redirection, 616 * This will override the automatic change to the user preferred site language. 617 * In that case we use the redirect as defined in the menu item. 618 * Otherwise we redirect, when available, to the user preferred site language. 619 */ 620 if ($active && !$active->getParams()->get('login_redirect_url')) { 621 if ($assoc) { 622 $associations = MenusHelper::getAssociations($active->id); 623 } 624 625 // Retrieves the Itemid from a login form. 626 $uri = new Uri($this->app->getUserState('users.login.form.return')); 627 628 if ($uri->getVar('Itemid')) { 629 // The login form contains a menu item redirection. Try to get associations from that menu item. 630 // If any association set to the user preferred site language, redirect to that page. 631 if ($assoc) { 632 $associations = MenusHelper::getAssociations($uri->getVar('Itemid')); 633 } 634 635 if (isset($associations[$lang_code]) && $menu->getItem($associations[$lang_code])) { 636 $associationItemid = $associations[$lang_code]; 637 $this->app->setUserState('users.login.form.return', 'index.php?Itemid=' . $associationItemid); 638 $foundAssociation = true; 639 } 640 } elseif (isset($associations[$lang_code]) && $menu->getItem($associations[$lang_code])) { 641 /** 642 * The login form does not contain a menu item redirection. 643 * The active menu item has associations. 644 * We redirect to the user preferred site language associated page. 645 */ 646 $associationItemid = $associations[$lang_code]; 647 $this->app->setUserState('users.login.form.return', 'index.php?Itemid=' . $associationItemid); 648 $foundAssociation = true; 649 } elseif ($active->home) { 650 // We are on a Home page, we redirect to the user preferred site language Home page. 651 $item = $menu->getDefault($lang_code); 652 653 if ($item && $item->language !== $active->language && $item->language !== '*') { 654 $this->app->setUserState('users.login.form.return', 'index.php?Itemid=' . $item->id); 655 $foundAssociation = true; 656 } 657 } 658 } 659 660 if ($foundAssociation && $lang_code !== $this->current_lang) { 661 // Change language. 662 $this->current_lang = $lang_code; 663 664 // Create a cookie. 665 $this->setLanguageCookie($lang_code); 666 667 // Change the language code. 668 Factory::getContainer()->get(\Joomla\CMS\Language\LanguageFactoryInterface::class)->createLanguage($lang_code); 669 } 670 } else { 671 if ($this->app->getUserState('users.login.form.return')) { 672 $this->app->setUserState('users.login.form.return', Route::_($this->app->getUserState('users.login.form.return'), false)); 673 } 674 } 675 } 676 } 677 678 /** 679 * Method to add alternative meta tags for associated menu items. 680 * 681 * @return void 682 * 683 * @since 1.7 684 */ 685 public function onAfterDispatch() 686 { 687 $doc = $this->app->getDocument(); 688 689 if ($this->app->isClient('site') && $this->params->get('alternate_meta', 1) && $doc->getType() === 'html') { 690 $languages = $this->lang_codes; 691 $homes = Multilanguage::getSiteHomePages(); 692 $menu = $this->app->getMenu(); 693 $active = $menu->getActive(); 694 $levels = $this->app->getIdentity()->getAuthorisedViewLevels(); 695 $remove_default_prefix = $this->params->get('remove_default_prefix', 0); 696 $server = Uri::getInstance()->toString(array('scheme', 'host', 'port')); 697 $is_home = false; 698 699 // Router can be injected when turned into a DI built plugin 700 $currentInternalUrl = 'index.php?' . http_build_query(Factory::getContainer()->get(SiteRouter::class)->getVars()); 701 702 if ($active) { 703 $active_link = Route::_($active->link . '&Itemid=' . $active->id); 704 $current_link = Route::_($currentInternalUrl); 705 706 // Load menu associations 707 if ($active_link === $current_link) { 708 $associations = MenusHelper::getAssociations($active->id); 709 } 710 711 // Check if we are on the home page 712 $is_home = ($active->home 713 && ($active_link === $current_link || $active_link === $current_link . 'index.php' || $active_link . '/' === $current_link)); 714 } 715 716 // Load component associations. 717 $option = $this->app->input->get('option'); 718 719 $component = $this->app->bootComponent($option); 720 721 if ($component instanceof AssociationServiceInterface) { 722 $cassociations = $component->getAssociationsExtension()->getAssociationsForItem(); 723 } else { 724 $cName = ucfirst(substr($option, 4)) . 'HelperAssociation'; 725 JLoader::register($cName, \Joomla\CMS\Filesystem\Path::clean(JPATH_SITE . '/components/' . $option . '/helpers/association.php')); 726 727 if (class_exists($cName) && is_callable(array($cName, 'getAssociations'))) { 728 $cassociations = call_user_func(array($cName, 'getAssociations')); 729 } 730 } 731 732 // For each language... 733 foreach ($languages as $i => $language) { 734 switch (true) { 735 // Language without frontend UI || Language without specific home menu || Language without authorized access level 736 case !array_key_exists($i, LanguageHelper::getInstalledLanguages(0)): 737 case !isset($homes[$i]): 738 case isset($language->access) && $language->access && !in_array($language->access, $levels): 739 unset($languages[$i]); 740 break; 741 742 // Home page 743 case $is_home: 744 $language->link = Route::_('index.php?lang=' . $language->sef . '&Itemid=' . $homes[$i]->id); 745 break; 746 747 // Current language link 748 case $i === $this->current_lang: 749 $language->link = Route::_($currentInternalUrl); 750 break; 751 752 // Component association 753 case isset($cassociations[$i]): 754 $language->link = Route::_($cassociations[$i]); 755 break; 756 757 // Menu items association 758 // Heads up! "$item = $menu" here below is an assignment, *NOT* comparison 759 case isset($associations[$i]) && ($item = $menu->getItem($associations[$i])): 760 $language->link = Route::_('index.php?Itemid=' . $item->id . '&lang=' . $language->sef); 761 break; 762 763 // Too bad... 764 default: 765 unset($languages[$i]); 766 } 767 } 768 769 // If there are at least 2 of them, add the rel="alternate" links to the <head> 770 if (count($languages) > 1) { 771 // Remove the sef from the default language if "Remove URL Language Code" is on 772 if ($remove_default_prefix && isset($languages[$this->default_lang])) { 773 $languages[$this->default_lang]->link 774 = preg_replace('|/' . $languages[$this->default_lang]->sef . '/|', '/', $languages[$this->default_lang]->link, 1); 775 } 776 777 foreach ($languages as $i => $language) { 778 $doc->addHeadLink($server . $language->link, 'alternate', 'rel', array('hreflang' => $i)); 779 } 780 781 // Add x-default language tag 782 if ($this->params->get('xdefault', 1)) { 783 $xdefault_language = $this->params->get('xdefault_language', $this->default_lang); 784 $xdefault_language = ($xdefault_language === 'default') ? $this->default_lang : $xdefault_language; 785 786 if (isset($languages[$xdefault_language])) { 787 // Use a custom tag because addHeadLink is limited to one URI per tag 788 $doc->addCustomTag('<link href="' . $server . $languages[$xdefault_language]->link . '" rel="alternate" hreflang="x-default">'); 789 } 790 } 791 } 792 } 793 } 794 795 /** 796 * Set the language cookie 797 * 798 * @param string $languageCode The language code for which we want to set the cookie 799 * 800 * @return void 801 * 802 * @since 3.4.2 803 */ 804 private function setLanguageCookie($languageCode) 805 { 806 // If is set to use language cookie for a year in plugin params, save the user language in a new cookie. 807 if ((int) $this->params->get('lang_cookie', 0) === 1) { 808 // Create a cookie with one year lifetime. 809 $this->app->input->cookie->set( 810 ApplicationHelper::getHash('language'), 811 $languageCode, 812 time() + 365 * 86400, 813 $this->app->get('cookie_path', '/'), 814 $this->app->get('cookie_domain', ''), 815 $this->app->isHttpsForced(), 816 true 817 ); 818 } else { 819 // If not, set the user language in the session (that is already saved in a cookie). 820 $this->app->getSession()->set('plg_system_languagefilter.language', $languageCode); 821 } 822 } 823 824 /** 825 * Get the language cookie 826 * 827 * @return string 828 * 829 * @since 3.4.2 830 */ 831 private function getLanguageCookie() 832 { 833 // Is is set to use a year language cookie in plugin params, get the user language from the cookie. 834 if ((int) $this->params->get('lang_cookie', 0) === 1) { 835 $languageCode = $this->app->input->cookie->get(ApplicationHelper::getHash('language')); 836 } else { 837 // Else get the user language from the session. 838 $languageCode = $this->app->getSession()->get('plg_system_languagefilter.language'); 839 } 840 841 // Let's be sure we got a valid language code. Fallback to null. 842 if (!array_key_exists($languageCode, $this->lang_codes)) { 843 $languageCode = null; 844 } 845 846 return $languageCode; 847 } 848 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |