You are here

StringDatabaseStorageDecorator.php in Language Hierarchy 2.x

File

src/StringDatabaseStorageDecorator.php
View source
<?php

namespace Drupal\language_hierarchy;

use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\locale\StringDatabaseStorage;
use Drupal\locale\StringStorageInterface;

/**
 * Decorates the locale.storage service.
 */
class StringDatabaseStorageDecorator extends StringDatabaseStorage {
  use DependencySerializationTrait;

  /**
   * Core string storage service.
   *
   * @var \Drupal\locale\StringStorageInterface
   */
  protected $stringStorage;

  /**
   * Language manager service.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Constructs a new StringDatabaseStorage class.
   *
   * @param \Drupal\locale\StringStorageInterface $string_storage
   *   Core string storage service.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   Language manager service.
   * @param \Drupal\Core\Database\Connection $connection
   *   A Database connection to use for reading and writing configuration data.
   * @param array $options
   *   (optional) Any additional database connection options to use in queries.
   */
  public function __construct(StringStorageInterface $string_storage, LanguageManagerInterface $language_manager, Connection $connection, array $options = []) {
    $this->stringStorage = $string_storage;
    $this->languageManager = $language_manager;
    parent::__construct($connection, $options);
  }

  /**
   * Performs decorator magic.
   *
   * @param string $method
   *   Name of method in the internal service.
   * @param array $args
   *   Arguments to pass to method.
   *
   * @return mixed
   *   Returns the results of the method in question.
   */
  public function __call($method, array $args) {
    return call_user_func_array([
      $this->stringStorage,
      $method,
    ], $args);
  }

  /**
   * {@inheritdoc}
   */
  protected function dbStringLoad(array $conditions, array $options, $class) {
    $strings = parent::dbStringLoad($conditions, $options, $class);

    // If querying for a single language, remove fallback results that also
    // have corresponding translations in a more specific language.
    if (!empty($conditions['language']) && is_scalar($conditions['language'])) {
      $filtered = [];
      foreach ($strings as $string) {
        $lid = $string
          ->getId();
        if (!isset($filtered[$lid])) {
          $filtered[$lid] = $string;
        }
      }
      $strings = array_values($filtered);
    }
    return $strings;
  }

  /**
   * {@inheritdoc}
   */
  protected function dbStringSelect(array $conditions, array $options = []) {
    $query = $this->stringStorage
      ->dbStringSelect($conditions, $options);

    // The 'translated' meta-condition bypasses fallbacks, since it is used for
    // querying specifically for a given language.
    if (!isset($conditions['translated'])) {
      $tables =& $query
        ->getTables();
      if (isset($tables['t']['arguments'][':langcode'])) {
        $attempted_langcode = $tables['t']['arguments'][':langcode'];

        // Retrieve the language fallback list.
        $candidates = array_values($this->languageManager
          ->getFallbackCandidates([
          'langcode' => $attempted_langcode,
          'operation' => 'locale_lookup',
        ]));
        if ($candidates) {
          $candidates = array_merge([
            $attempted_langcode,
          ], $candidates);

          // Modify langcode to be an array instead of a single value.
          $tables['t']['condition'] = "t.lid = s.lid AND t.language IN (:langcode[])";
          unset($tables['t']['arguments'][':langcode']);
          $tables['t']['arguments'][':langcode[]'] = $candidates;

          // Build custom sort criteria.
          $query
            ->addJoin('LEFT', 'language_hierarchy_priority', 'lhp', 't.language = lhp.langcode');
          $query
            ->orderBy('lhp.priority', 'DESC');
        }
      }
    }
    return $query;
  }

}

Classes

Namesort descending Description
StringDatabaseStorageDecorator Decorates the locale.storage service.