Verified Commit faeae2b8 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

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

Issue #3134349 by sleitner, yookoala, sharma.amitt16, Akram Khan, penyaskito, sahil.goyal, swatichouhan012, s_leu, larowlan, smustgrave, joachim: \Drupal\language\LanguageNegotiator does not handle PluginNotFoundException and break the site completely

(cherry picked from commit 67fc8fbf)
parent 892cecb5
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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,8 +133,14 @@ 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])) {
          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
        // the language negotiation method cache from being unintentionally
+56 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\language\Kernel;

use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Logger\LoggerChannelFactory;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\ErrorHandler\BufferingLogger;

/**
 * Tests PluginNotFoundException.
 *
 * @group language
 */
class LanguageNegotiatorPluginTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['language', 'user'];

  /**
   * Tests for PluginNotFoundException.
   */
  public function testLanguageNegotiatorNoPlugin() {
    $logger = new BufferingLogger();
    $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.');
    }
    $log_message = $logger->cleanLogs()[0];
    $this->assertEquals('error', $log_message[0]);
    $this->assertStringContainsString('The "Drupal\Tests\language\Kernel\LanguageNegotiatorPluginTest" plugin does not exist.', $log_message[1]);
  }

}