Skip to content
Snippets Groups Projects
Verified Commit b279c994 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3134349 by sleitner, yookoala, sharma.amitt16, Akram Khan, sahil.goyal,...

Issue #3134349 by sleitner, yookoala, sharma.amitt16, Akram Khan, sahil.goyal, swatichouhan012, s_leu, penyaskito, smustgrave, joachim, larowlan: \Drupal\language\LanguageNegotiator does not handle PluginNotFoundException and break the site completely
parent d997fd07
Branches
Tags
26 merge requests!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!4100Issue #3249600: Add support for PHP 8.1 Enums as allowed values for list_* data types,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -2,8 +2,10 @@
namespace Drupal\language;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI;
......@@ -13,6 +15,7 @@
* Class responsible for performing language negotiation.
*/
class LanguageNegotiator implements LanguageNegotiatorInterface {
use LoggerChannelTrait;
/**
* The language negotiation method plugin manager.
......@@ -76,7 +79,7 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
* @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Component\Plugin\PluginManagerInterface $negotiator_manager
* The language negotiation methods plugin manager
* The language negotiation methods plugin manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
* @param \Drupal\Core\Site\Settings $settings
......@@ -130,7 +133,13 @@ public function initializeType($type) {
// and return the first valid language found.
foreach ($this->getEnabledNegotiators($type) as $method_id => $info) {
if (!isset($this->negotiatedLanguages[$method_id])) {
$this->negotiatedLanguages[$method_id] = $this->negotiateLanguage($type, $method_id);
try {
$this->negotiatedLanguages[$method_id] = $this->negotiateLanguage($type, $method_id);
}
catch (PluginNotFoundException $e) {
// If a plugin is not found, log the error so user can handle it.
$this->getLogger('language')->error($e->getMessage());
}
}
// Since objects are references, we need to return a clone to prevent
......
<?php
namespace Drupal\Tests\language\Kernel;
use ColinODell\PsrTestLogger\TestLogger;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Logger\LoggerChannelFactory;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests PluginNotFoundException.
*
* @group language
*/
class LanguageNegotiatorPluginTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['language', 'user'];
/**
* Tests for PluginNotFoundException.
*/
public function testLanguageNegotiatorNoPlugin() {
$logger = new TestLogger();
$logger_factory = $this->createMock(LoggerChannelFactory::class);
$logger_factory->expects($this->once())
->method('get')
->with('language')
->willReturn($logger);
$this->container->set('logger.factory', $logger_factory);
$this->installEntitySchema('user');
// Test unavailable plugin.
$config = $this->config('language.types');
$config->set('configurable', [LanguageInterface::TYPE_URL]);
$config->set('negotiation.language_url.enabled', [
self::CLASS => -3,
]);
$config->save();
$languageNegotiator = $this->container->get('language_negotiator');
$languageNegotiator->setCurrentUser($this->prophesize('Drupal\Core\Session\AccountInterface')->reveal());
try {
$languageNegotiator->initializeType(LanguageInterface::TYPE_URL);
}
catch (PluginNotFoundException $exception) {
$this->fail('Plugin not found exception unhandled.');
}
$this->assertTrue($logger->hasErrorThatContains('The "Drupal\Tests\language\Kernel\LanguageNegotiatorPluginTest" plugin does not exist.'));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment