LanguageNegotiationContentEntity.php in Drupal 9
File
core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationContentEntity.php
View source
<?php
namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Url;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\language\LanguageSwitcherInterface;
use Drupal\Core\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
class LanguageNegotiationContentEntity extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface, ContainerFactoryPluginInterface {
const METHOD_ID = 'language-content-entity';
const QUERY_PARAMETER = 'language_content_entity';
protected $contentEntityPaths;
protected $hasLowerLanguageNegotiationWeightResult;
protected $paths;
protected $entityTypeManager;
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
$this->paths = new \SplObjectStorage();
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($container
->get('entity_type.manager'));
}
public function getLangcode(Request $request = NULL) {
$langcode = $request->query
->get(static::QUERY_PARAMETER);
$language_enabled = array_key_exists($langcode, $this->languageManager
->getLanguages());
return $language_enabled ? $langcode : NULL;
}
public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
if (!($request && !empty($options['route']) && $this
->hasLowerLanguageNegotiationWeight() && $this
->meetsContentEntityRoutesCondition($options['route'], $request))) {
return $path;
}
if (isset($options['language']) || ($langcode = $this
->getLangcode($request))) {
if (isset($options['language'])) {
$langcode = $options['language']
->getId();
unset($options['language']);
}
if (!isset($options['query'][static::QUERY_PARAMETER])) {
$options['query'][static::QUERY_PARAMETER] = $langcode;
}
if ($bubbleable_metadata) {
$bubbleable_metadata
->addCacheContexts([
'url.query_args:' . static::QUERY_PARAMETER,
]);
}
}
return $path;
}
public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
$links = [];
$query = [];
parse_str($request
->getQueryString(), $query);
foreach ($this->languageManager
->getNativeLanguages() as $language) {
$langcode = $language
->getId();
$query[static::QUERY_PARAMETER] = $langcode;
$links[$langcode] = [
'url' => $url,
'title' => $language
->getName(),
'attributes' => [
'class' => [
'language-link',
],
],
'query' => $query,
];
}
return $links;
}
protected function hasLowerLanguageNegotiationWeight() {
if (!isset($this->hasLowerLanguageNegotiationWeightResult)) {
$content_method_weights = $this->config
->get('language.types')
->get('negotiation.language_content.enabled') ?: [];
if (isset($content_method_weights[LanguageNegotiationUrl::METHOD_ID]) && $content_method_weights[static::METHOD_ID] > $content_method_weights[LanguageNegotiationUrl::METHOD_ID]) {
$this->hasLowerLanguageNegotiationWeightResult = FALSE;
}
else {
$check_interface_method = FALSE;
if (isset($content_method_weights[LanguageNegotiationUI::METHOD_ID])) {
$interface_method_weights = $this->config
->get('language.types')
->get('negotiation.language_interface.enabled') ?: [];
$check_interface_method = isset($interface_method_weights[LanguageNegotiationUrl::METHOD_ID]);
}
if ($check_interface_method) {
$max_weight = $content_method_weights[LanguageNegotiationUI::METHOD_ID];
$max_weight = isset($content_method_weights[LanguageNegotiationUrl::METHOD_ID]) ? max($max_weight, $content_method_weights[LanguageNegotiationUrl::METHOD_ID]) : $max_weight;
}
else {
$max_weight = isset($content_method_weights[LanguageNegotiationUrl::METHOD_ID]) ? $content_method_weights[LanguageNegotiationUrl::METHOD_ID] : PHP_INT_MAX;
}
$this->hasLowerLanguageNegotiationWeightResult = $content_method_weights[static::METHOD_ID] < $max_weight;
}
}
return $this->hasLowerLanguageNegotiationWeightResult;
}
protected function meetsContentEntityRoutesCondition(Route $outbound_route, Request $request) {
$outbound_path_pattern = $outbound_route
->getPath();
$storage = isset($this->paths[$request]) ? $this->paths[$request] : [];
if (!isset($storage[$outbound_path_pattern])) {
$storage[$outbound_path_pattern] = FALSE;
if ($content_entity_type_id_for_current_route = $this
->getContentEntityTypeIdForCurrentRequest($request)) {
if (!empty($this
->getContentEntityPaths()[$outbound_path_pattern]) && $content_entity_type_id_for_current_route == $this
->getContentEntityPaths()[$outbound_path_pattern]) {
$storage[$outbound_path_pattern] = TRUE;
}
}
$this->paths[$request] = $storage;
}
return $storage[$outbound_path_pattern];
}
protected function getContentEntityTypeIdForCurrentRequest(Request $request) {
$content_entity_type_id_for_current_route = '';
if ($current_route = $request->attributes
->get(RouteObjectInterface::ROUTE_OBJECT)) {
$current_route_path = $current_route
->getPath();
$content_entity_type_id_for_current_route = isset($this
->getContentEntityPaths()[$current_route_path]) ? $this
->getContentEntityPaths()[$current_route_path] : '';
}
return $content_entity_type_id_for_current_route;
}
protected function getContentEntityPaths() {
if (!isset($this->contentEntityPaths)) {
$this->contentEntityPaths = [];
$entity_types = $this->entityTypeManager
->getDefinitions();
foreach ($entity_types as $entity_type_id => $entity_type) {
if ($entity_type
->entityClassImplements(ContentEntityInterface::class)) {
$entity_paths = array_fill_keys($entity_type
->getLinkTemplates(), $entity_type_id);
$this->contentEntityPaths = array_merge($this->contentEntityPaths, $entity_paths);
}
}
}
return $this->contentEntityPaths;
}
}