Skip to content
Snippets Groups Projects

Issue #3507728 by eduardo morales alberti: Target langcode and source can be different

Files
4
+ 40
50
@@ -7,6 +7,7 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\StatementInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountSwitcherInterface;
@@ -40,12 +41,13 @@ class EntityRender extends Entity {
*/
protected LanguageNegotiatorSwitcher $languageNegotiatorSwitcher;
/**
* Url language prefixes.
* Module handler.
*
* @var array
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected array $prefixes;
protected ModuleHandlerInterface $moduleHandler;
/**
* Constructs a Menu object.
@@ -57,13 +59,15 @@ class EntityRender extends Entity {
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The language manager.
* The config factory.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer manager.
* @param \Drupal\Core\Session\AccountSwitcherInterface $account_switcher
* The AccountSwitcher manager.
* @param \Drupal\entity_mesh\Language\LanguageNegotiatorSwitcher $language_negotiator_switcher
* The language negotiator switcher service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* Module handler.
*/
public function __construct(
RepositoryInterface $entity_mesh_repository,
@@ -73,13 +77,14 @@ class EntityRender extends Entity {
RendererInterface $renderer,
AccountSwitcherInterface $account_switcher,
LanguageNegotiatorSwitcher $language_negotiator_switcher,
ModuleHandlerInterface $module_handler,
) {
parent::__construct($entity_mesh_repository, $entity_type_manager, $language_manager, $config_factory);
parent::__construct($entity_mesh_repository, $entity_type_manager, $language_manager, $config_factory, $module_handler);
$this->renderer = $renderer;
$this->accountSwitcher = $account_switcher;
$this->type = 'entity_render';
$this->languageNegotiatorSwitcher = $language_negotiator_switcher;
$this->prefixes = $config_factory->get('language.negotiation')->get('url.prefixes');
$this->moduleHandler = $module_handler;
}
/**
@@ -194,6 +199,7 @@ class EntityRender extends Entity {
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$pre_render = $view_builder->view($entity, $view_mode, $langcode);
// @todo Review render plain is deprecated.
$render_output = $this->renderer->renderPlain($pre_render);
// Switches back to the current language:
@@ -243,7 +249,7 @@ class EntityRender extends Entity {
$target->setCategory('link');
if ($target->getLinkType() == 'internal' && $this->ifProcessInternalTarget()) {
$this->processInternalHref($target, $source->getSourceEntityLangcode() ?? '');
$this->processInternalHref($target);
// Check that the target is not the source to avoid circular references.
if ($source->getSourceEntityType() == $target->getEntityType()
@@ -263,34 +269,29 @@ class EntityRender extends Entity {
*
* @param \Drupal\entity_mesh\TargetInterface $target
* The target.
* @param string $langcode
* The language code.
*/
protected function processInternalHref(TargetInterface $target, string $langcode) {
$found_data = FALSE;
// Remove the langcode to find the alias.
// @todo take into account other languages also to support cross-language paths.
// @todo this is the default URL creation, change with the real one.
$prefix = $this->prefixes[$langcode] ?? $langcode;
$alias = str_replace('/' . $prefix, '', $target->getPath() ?? '');
protected function processInternalHref(TargetInterface $target) {
$alias = $this->entityMeshRepository->getPathWithoutLangPrefix($target->getPath());
$target->setEntityLangcode($this->entityMeshRepository->getLangcodeFromPath($target->getPath()));
$found_data = $this->setDataIfRedirection($alias, $langcode, $target);
$found_data = $this->setDataIfRedirection($alias, $target);
// Get the info from alias.
// This method is quicker than using the router service,
// so firstly apply this system.
if (!$found_data) {
$found_data = $this->setDataTargetFromAliasIfExists($alias, $langcode, $target);
$found_data = $this->setDataTargetFromAliasIfExists($alias, $target);
}
// If this method not found the data, use the router service.
if (!$found_data) {
$this->setDataTargetFromRoute($langcode, $target);
$this->setDataTargetFromRoute($target);
}
// If the target is set as link broken maybe is because is a file url.
if ($target->getSubcategory() === 'broken-link') {
$this->setDataTargetIfFileUrl($langcode, $target);
$this->setDataTargetIfFileUrl($target);
}
$this->setBundleInTarget($target);
@@ -328,15 +329,14 @@ class EntityRender extends Entity {
*
* @param string $alias
* The alias.
* @param string $langcode
* The language code.
* @param TargetInterface $target
* The target.
*
* @return bool
* If is a redirection.
*/
protected function setDataIfRedirection(string &$alias, string $langcode, TargetInterface $target): bool {
protected function setDataIfRedirection(string &$alias, TargetInterface $target): bool {
$langcode = $target->getEntityLangcode() ?? '';
// Check if is a redirected link.
$uri = $this->entityMeshRepository->ifRedirectionForPath($alias, $langcode);
if ($uri === NULL) {
@@ -361,9 +361,7 @@ class EntityRender extends Entity {
return TRUE;
}
if (str_starts_with($uri, "/$langcode")) {
$uri = substr($uri, strlen("/$langcode"));
}
$uri = $this->entityMeshRepository->getPathWithoutLangPrefix($uri);
if ($type === '') {
$alias = $uri;
@@ -375,7 +373,7 @@ class EntityRender extends Entity {
$uri = $possible_alias->path;
}
return $this->processInternalPaths($uri, $langcode, $target);
return $this->processInternalPaths($uri, $target);
}
/**
@@ -383,21 +381,23 @@ class EntityRender extends Entity {
*
* @param string $alias
* Alias.
* @param string $langcode
* Langcode.
* @param TargetInterface $target
* Target.
*
* @return bool
* If this method found the data.
*/
protected function setDataTargetFromAliasIfExists(string $alias, string $langcode, TargetInterface $target): bool {
protected function setDataTargetFromAliasIfExists(string $alias, TargetInterface $target): bool {
// Get the info from alias.
$record = $this->getPathFromAliasTables($alias, $langcode);
if (!$record) {
return FALSE;
$langcode = $target->getEntityLangcode();
if ($this->moduleHandler->moduleExists('path_alias')) {
$record = $this->getPathFromAliasTables($alias, $langcode);
if ($record) {
return $this->processInternalPaths($record->path, $target);
}
}
return $this->processInternalPaths($record->path, $langcode, $target);
return $this->processInternalPaths($alias, $target);
}
/**
@@ -405,15 +405,13 @@ class EntityRender extends Entity {
*
* @param string $path
* The path.
* @param string $langcode
* The language code.
* @param TargetInterface $target
* The target.
*
* @return bool
* If the path is processed.
*/
protected function processInternalPaths(string $path, string $langcode, TargetInterface $target) {
protected function processInternalPaths(string $path, TargetInterface $target) {
$path = explode('/', ltrim($path, '/'));
if (count($path) < 2) {
return FALSE;
@@ -425,25 +423,21 @@ class EntityRender extends Entity {
if (isset($path[2]) && is_numeric($path[2])) {
$target->setEntityType($path[0]);
$target->setEntityId((string) $path[2]);
$target->setEntityLangcode($langcode);
return TRUE;
}
$target->setEntityType($path[0]);
$target->setEntityId((string) ($path[1] ?? ''));
$target->setEntityLangcode($langcode);
return TRUE;
}
/**
* Set data about the target from route.
*
* @param string $langcode
* The language code.
* @param TargetInterface $target
* The target.
*/
protected function setDataTargetFromRoute($langcode, $target) {
protected function setDataTargetFromRoute($target) {
if (empty($target->getPath())) {
return;
}
@@ -461,7 +455,6 @@ class EntityRender extends Entity {
if (isset($route_match['view_id'])) {
$target->setEntityType('view');
$target->setEntityId($route_match['view_id'] . '.' . $route_match['display_id']);
$target->setEntityLangcode($langcode);
return;
}
@@ -475,19 +468,16 @@ class EntityRender extends Entity {
}
$target->setEntityType($entity);
$target->setEntityId((string) $entity_id);
$target->setEntityLangcode($langcode);
}
}
/**
* Set data target if file url.
*
* @param string $langcode
* The language code.
* @param TargetInterface $target
* The target.
*/
protected function setDataTargetIfFileUrl($langcode, $target) {
protected function setDataTargetIfFileUrl($target) {
// Check if the path is a file.
$path = $this->entityMeshRepository->getPathFromFileUrl($target->getPath() ?? '');
if (!$path) {
@@ -509,14 +499,12 @@ class EntityRender extends Entity {
if (!$media) {
$target->setEntityType($file->getEntityTypeId());
$target->setEntityId((string) $file->id());
$target->setEntityLangcode($langcode);
return;
}
$target->setEntityType($media->getEntityTypeId());
$target->setEntityBundle($media->bundle());
$target->setEntityId((string) $media->id());
$target->setEntityLangcode($langcode);
}
/**
@@ -537,7 +525,9 @@ class EntityRender extends Entity {
->condition('alias', $alias)
->condition('path', $alias);
$query->condition($or);
$query->condition('langcode', $langcode);
if (!empty($langcode)) {
$query->condition('langcode', $langcode);
}
$result = $query->execute();
if (!$result instanceof StatementInterface) {
return NULL;
Loading