From d0d9de0572a1ea0968f9f56c0a70ca2c093ce2f4 Mon Sep 17 00:00:00 2001 From: Eduardo Morales <eduardo.morales@metadrop.net> Date: Wed, 19 Feb 2025 13:17:40 +0100 Subject: [PATCH 01/10] Issue #3507728 by eduardo morales alberti: Target langcode and source can be different --- entity_mesh.services.yml | 8 +++++- src/EntityRender.php | 55 ++++++++++++++++------------------------ src/Repository.php | 27 +++++++++++++++++--- src/Target.php | 31 +++++++++++++++++++++- src/TargetInterface.php | 4 ++- 5 files changed, 85 insertions(+), 40 deletions(-) diff --git a/entity_mesh.services.yml b/entity_mesh.services.yml index 2b042ef..8b79f02 100644 --- a/entity_mesh.services.yml +++ b/entity_mesh.services.yml @@ -5,7 +5,13 @@ services: arguments: [ 'entity_mesh' ] entity_mesh.repository: class: Drupal\entity_mesh\Repository - arguments: [ '@database', '@entity_mesh.logger', '@request_stack', '@entity_type.manager', '@entity_field.manager' ] + arguments: + - '@database' + - '@entity_mesh.logger' + - '@request_stack' + - '@entity_type.manager' + - '@entity_field.manager' + - '@config.factory' entity_mesh.menu: class: Drupal\entity_mesh\Menu arguments: ['@entity_mesh.repository', '@entity_type.manager', '@language_manager', '@config.factory'] diff --git a/src/EntityRender.php b/src/EntityRender.php index 2b23132..08206f1 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -57,7 +57,7 @@ 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 @@ -194,6 +194,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 +244,7 @@ class EntityRender extends Entity { $target->setCategory('link'); if ($target->getLinkType() == 'internal' && $this->ifProcessInternalTarget()) { - $this->processInternalHref($target, $source->getSourceEntityLangcode() ?? ''); + $this->processInternalHref($target, $target->getEntityLangcode() ?? ''); // Check that the target is not the source to avoid circular references. if ($source->getSourceEntityType() == $target->getEntityType() @@ -263,34 +264,36 @@ 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) { + protected function processInternalHref(TargetInterface $target) { $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; + $prefix = ''; + if ($langcode = $target->getEntityLangcode()) { + $prefix = $this->prefixes[$langcode] ?? $langcode; + } + $alias = str_replace('/' . $prefix, '', $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 +331,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) { @@ -375,7 +377,7 @@ class EntityRender extends Entity { $uri = $possible_alias->path; } - return $this->processInternalPaths($uri, $langcode, $target); + return $this->processInternalPaths($uri, $target); } /** @@ -383,21 +385,20 @@ 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. + $langcode = $target->getEntityLangcode(); $record = $this->getPathFromAliasTables($alias, $langcode); if (!$record) { return FALSE; } - return $this->processInternalPaths($record->path, $langcode, $target); + return $this->processInternalPaths($record->path, $target); } /** @@ -405,15 +406,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 +424,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 +456,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 +469,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 +500,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); } /** diff --git a/src/Repository.php b/src/Repository.php index 6f78a51..677f40b 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -3,6 +3,7 @@ namespace Drupal\entity_mesh; use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityInterface; @@ -14,7 +15,6 @@ use Drupal\redirect\Exception\RedirectLoopException; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RequestStack; - /** * Service to perform database operations. */ @@ -55,6 +55,13 @@ class Repository implements RepositoryInterface { */ protected $entityFieldManager; + /** + * Url language prefixes. + * + * @var array + */ + protected array $prefixes; + /** * Constructs a new Repository object. * @@ -68,13 +75,23 @@ class Repository implements RepositoryInterface { * The entity type manager. * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager * The entity field manager. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * Config factory. */ - public function __construct(Connection $database, LoggerInterface $logger, RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) { + public function __construct( + Connection $database, + LoggerInterface $logger, + RequestStack $request_stack, + EntityTypeManagerInterface $entity_type_manager, + EntityFieldManagerInterface $entity_field_manager, + ConfigFactoryInterface $config_factory, + ) { $this->database = $database; $this->logger = $logger; $this->requestStack = $request_stack; $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; + $this->prefixes = $config_factory->get('language.negotiation')->get('url.prefixes'); } /** @@ -311,7 +328,8 @@ class Repository implements RepositoryInterface { /** @var \Symfony\Component\HttpFoundation\Request $current_request */ $current_request = $this->requestStack->getCurrentRequest(); $domain = $current_request->getHost(); - return Target::create($domain); + $prefixes = $this->prefixes; + return Target::create($domain, $prefixes); } /** @@ -398,7 +416,8 @@ class Repository implements RepositoryInterface { try { /** @var \Drupal\redirect\Entity\Redirect $redirect_object */ $redirect_object = $redirect_repository->findMatchingRedirect($path, [], $langcode); - } catch (RedirectLoopException $e) { + } + catch (RedirectLoopException $e) { $this->logger->error($e->getMessage()); return NULL; } diff --git a/src/Target.php b/src/Target.php index 6208e42..de33931 100644 --- a/src/Target.php +++ b/src/Target.php @@ -102,12 +102,20 @@ class Target implements TargetInterface { */ protected $title; + /** + * Prefixes. + * + * @var array + */ + protected array $prefixes; + /** * {@inheritdoc} */ - public static function create(string $current_domain): Target { + public static function create(string $current_domain, array $prefixes): Target { $target = new self(); $target->currentDomain = $current_domain; + $target->prefixes = $prefixes; return $target; } @@ -172,6 +180,7 @@ class Target implements TargetInterface { $path = $this->sanitizeUrl($path); } $this->setPath($path); + $this->getTargetLangcodeFromPath($path); } } @@ -335,6 +344,26 @@ class Target implements TargetInterface { } } + /** + * Extract langcode from path. + * + * @param mixed $path + * Patch to review. + * + * @return string|null + * Target langcode. + */ + public function getTargetLangcodeFromPath(mixed $path) { + $path = '/' . ltrim($path, '/'); + foreach ($this->prefixes as $langcode => $prefix) { + if ($prefix && str_starts_with($path, '/' . $prefix . '/')) { + $this->setEntityLangcode($langcode); + } + } + + return $this->targetEntityLangcode; + } + /** * {@inheritdoc} */ diff --git a/src/TargetInterface.php b/src/TargetInterface.php index eec26b3..562d8d2 100644 --- a/src/TargetInterface.php +++ b/src/TargetInterface.php @@ -216,10 +216,12 @@ interface TargetInterface { * * @param string $current_domain * The current domain. + * @param array $prefixes + * Prefixes. * * @return \Drupal\entity_mesh\TargetInterface * The target object. */ - public static function create(string $current_domain): TargetInterface; + public static function create(string $current_domain, array $prefixes): TargetInterface; } -- GitLab From 1a8ce35c7e8a0e80f117b39b8239b16a9d78595a Mon Sep 17 00:00:00 2001 From: Eduardo Morales <eduardo.morales@metadrop.net> Date: Wed, 19 Feb 2025 13:26:04 +0100 Subject: [PATCH 02/10] Issue #3507728 by eduardo morales alberti: Target langcode and source can be different --- src/EntityRender.php | 10 +--------- src/Target.php | 16 ++++++++++++++++ src/TargetInterface.php | 8 ++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index 08206f1..b76c9fc 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -266,16 +266,8 @@ class EntityRender extends Entity { * The target. */ protected function processInternalHref(TargetInterface $target) { - $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 = ''; - if ($langcode = $target->getEntityLangcode()) { - $prefix = $this->prefixes[$langcode] ?? $langcode; - } - $alias = str_replace('/' . $prefix, '', $target->getPath() ?? ''); + $alias = $target->getAlias(); $found_data = $this->setDataIfRedirection($alias, $target); diff --git a/src/Target.php b/src/Target.php index de33931..d2ab9f3 100644 --- a/src/Target.php +++ b/src/Target.php @@ -264,6 +264,22 @@ class Target implements TargetInterface { $this->targetEntityLangcode = $entity_langcode; } + /** + * {@inheritdoc} + */ + public function getAlias(): ?string { + // 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 = ''; + if ($langcode = $this->getEntityLangcode()) { + $prefix = $this->prefixes[$langcode] ?? $langcode; + } + + $alias = str_replace('/' . $prefix, '', $this->getPath() ?? ''); + return $alias; + } + /** * {@inheritdoc} */ diff --git a/src/TargetInterface.php b/src/TargetInterface.php index 562d8d2..f0d04d4 100644 --- a/src/TargetInterface.php +++ b/src/TargetInterface.php @@ -65,6 +65,14 @@ interface TargetInterface { */ public function processHrefAndSetComponents(string $href); + /** + * Extract alias from target path. + * + * @return string|null + * Alias from path. + */ + public function getAlias(): ?string; + /** * Get the link type. * -- GitLab From 51f70c1aefcbbb3526fadf793c8ab5a914ca4e65 Mon Sep 17 00:00:00 2001 From: Eduardo Morales <eduardo.morales@metadrop.net> Date: Thu, 20 Feb 2025 11:00:21 +0100 Subject: [PATCH 03/10] Issue #3507728 by eduardo morales alberti: Target langcode and source can be different --- src/EntityRender.php | 9 ++++++--- src/Target.php | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index b76c9fc..9e250a5 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -244,7 +244,7 @@ class EntityRender extends Entity { $target->setCategory('link'); if ($target->getLinkType() == 'internal' && $this->ifProcessInternalTarget()) { - $this->processInternalHref($target, $target->getEntityLangcode() ?? ''); + $this->processInternalHref($target); // Check that the target is not the source to avoid circular references. if ($source->getSourceEntityType() == $target->getEntityType() @@ -511,14 +511,17 @@ class EntityRender extends Entity { * @return mixed|null * Return the path. */ - protected function getPathFromAliasTables(string $alias, string $langcode) { + protected function getPathFromAliasTables(string $alias, string $langcode = NULL) { $query = $this->entityMeshRepository->getDatabaseService()->select('path_alias', 'pa'); $query->fields('pa', ['path']); $or = $query->orConditionGroup() ->condition('alias', $alias) ->condition('path', $alias); $query->condition($or); - $query->condition('langcode', $langcode); + if ($langcode !== NULL) { + $query->condition('langcode', $langcode); + } + $result = $query->execute(); if (!$result instanceof StatementInterface) { return NULL; diff --git a/src/Target.php b/src/Target.php index d2ab9f3..1d94950 100644 --- a/src/Target.php +++ b/src/Target.php @@ -271,12 +271,12 @@ class Target implements TargetInterface { // 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 = ''; + $alias = $this->getPath(); if ($langcode = $this->getEntityLangcode()) { $prefix = $this->prefixes[$langcode] ?? $langcode; + $alias = str_replace('/' . $prefix, '', $this->getPath() ?? ''); } - $alias = str_replace('/' . $prefix, '', $this->getPath() ?? ''); return $alias; } -- GitLab From 59d4417b1ad64a7fa2bdb37d5f3a4cf5d0a40ff3 Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 12:40:07 +0100 Subject: [PATCH 04/10] Issue #3507728: Move logic about lang prefix from Target object to service Repostiroty. It is needed in other contexts --- src/Repository.php | 65 +++++++++++++++++++++++++++++++++++-- src/RepositoryInterface.php | 33 +++++++++++++++++++ src/Target.php | 46 +------------------------- src/TargetInterface.php | 12 +------ 4 files changed, 98 insertions(+), 58 deletions(-) diff --git a/src/Repository.php b/src/Repository.php index 677f40b..8e60105 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -328,8 +328,7 @@ class Repository implements RepositoryInterface { /** @var \Symfony\Component\HttpFoundation\Request $current_request */ $current_request = $this->requestStack->getCurrentRequest(); $domain = $current_request->getHost(); - $prefixes = $this->prefixes; - return Target::create($domain, $prefixes); + return Target::create($domain); } /** @@ -461,4 +460,66 @@ class Repository implements RepositoryInterface { return $uri; } + /** + * {@inheritdoc} + */ + public function getPathWithoutLangPrefix($path) { + $prefix = $this->getLangPrefixFromPath($path); + if (empty($prefix)) { + return $path; + } + $path = ltrim($path, '/'); + return str_replace($prefix, '', $path ?? ''); + } + + /** + * {@inheritdoc} + */ + public function getLangcodeFromPath($path): ?string { + $result = NULL; + if ($langcode_and_prefix = $this->getLangcodeAndPrefixFromPath($path)) { + $result = $langcode_and_prefix['langcode'] ?? NULL; + } + return $result; + } + + /** + * {@inheritdoc} + */ + public function getLangPrefixFromPath($path): ?string { + $result = NULL; + if ($langcode_and_prefix = $this->getLangcodeAndPrefixFromPath($path)) { + $result = $langcode_and_prefix['prefix'] ?? NULL; + } + return $result; + } + + /** + * Get the langcode and prefix from the path. + * + * @param string $path + * The path. + * + * @return array|null + * The langcode and prefix or NULL. + */ + protected function getLangcodeAndPrefixFromPath($path): ?array { + // If the prefixes ares empty, it is not a multilanguage site, so + // there are not langcode to return. + if (empty($this->prefixes)) { + return NULL; + } + $path = '/' . ltrim($path, '/'); + foreach ($this->prefixes as $langcode => $prefix) { + if ($prefix && str_starts_with($path, '/' . $prefix . '/')) { + return [ + 'langcode' => $langcode, + 'prefix' => $prefix, + ]; + } + } + + return NULL; + } + } diff --git a/src/RepositoryInterface.php b/src/RepositoryInterface.php index 5d56a2d..b2d5757 100644 --- a/src/RepositoryInterface.php +++ b/src/RepositoryInterface.php @@ -143,4 +143,37 @@ interface RepositoryInterface { */ public function ifRedirectionForPath(string $path, string $langcode, int $count = 0); + /** + * Get the path without the lang prefix. + * + * @param string $path + * The path. + * + * @return string + * The path without the lang prefix. + */ + public function getPathWithoutLangPrefix($path); + + /** + * Get the langcode from the path. + * + * @param string $path + * The path. + * + * @return string|null + * The langcode or NULL. + */ + public function getLangcodeFromPath($path): ?string; + + /** + * Get the lang prefix from the path. + * + * @param string $path + * The path. + * + * @return string|null + * The langcode or NULL. + */ + public function getLangPrefixFromPath($path): ?string; + } diff --git a/src/Target.php b/src/Target.php index 1d94950..d7082a6 100644 --- a/src/Target.php +++ b/src/Target.php @@ -102,20 +102,12 @@ class Target implements TargetInterface { */ protected $title; - /** - * Prefixes. - * - * @var array - */ - protected array $prefixes; - /** * {@inheritdoc} */ - public static function create(string $current_domain, array $prefixes): Target { + public static function create(string $current_domain): Target { $target = new self(); $target->currentDomain = $current_domain; - $target->prefixes = $prefixes; return $target; } @@ -264,22 +256,6 @@ class Target implements TargetInterface { $this->targetEntityLangcode = $entity_langcode; } - /** - * {@inheritdoc} - */ - public function getAlias(): ?string { - // 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. - $alias = $this->getPath(); - if ($langcode = $this->getEntityLangcode()) { - $prefix = $this->prefixes[$langcode] ?? $langcode; - $alias = str_replace('/' . $prefix, '', $this->getPath() ?? ''); - } - - return $alias; - } - /** * {@inheritdoc} */ @@ -360,26 +336,6 @@ class Target implements TargetInterface { } } - /** - * Extract langcode from path. - * - * @param mixed $path - * Patch to review. - * - * @return string|null - * Target langcode. - */ - public function getTargetLangcodeFromPath(mixed $path) { - $path = '/' . ltrim($path, '/'); - foreach ($this->prefixes as $langcode => $prefix) { - if ($prefix && str_starts_with($path, '/' . $prefix . '/')) { - $this->setEntityLangcode($langcode); - } - } - - return $this->targetEntityLangcode; - } - /** * {@inheritdoc} */ diff --git a/src/TargetInterface.php b/src/TargetInterface.php index f0d04d4..eec26b3 100644 --- a/src/TargetInterface.php +++ b/src/TargetInterface.php @@ -65,14 +65,6 @@ interface TargetInterface { */ public function processHrefAndSetComponents(string $href); - /** - * Extract alias from target path. - * - * @return string|null - * Alias from path. - */ - public function getAlias(): ?string; - /** * Get the link type. * @@ -224,12 +216,10 @@ interface TargetInterface { * * @param string $current_domain * The current domain. - * @param array $prefixes - * Prefixes. * * @return \Drupal\entity_mesh\TargetInterface * The target object. */ - public static function create(string $current_domain, array $prefixes): TargetInterface; + public static function create(string $current_domain): TargetInterface; } -- GitLab From 7f9ac2f9986daf4180db0c6864f0d04a9cdae1da Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 12:56:42 +0100 Subject: [PATCH 05/10] Issue #3507728: Prefix languages are manage by servuce repository, not need in EntityRender service --- src/EntityRender.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index 9e250a5..70f27c1 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -40,13 +40,6 @@ class EntityRender extends Entity { */ protected LanguageNegotiatorSwitcher $languageNegotiatorSwitcher; - /** - * Url language prefixes. - * - * @var array - */ - protected array $prefixes; - /** * Constructs a Menu object. * @@ -79,7 +72,6 @@ class EntityRender extends Entity { $this->accountSwitcher = $account_switcher; $this->type = 'entity_render'; $this->languageNegotiatorSwitcher = $language_negotiator_switcher; - $this->prefixes = $config_factory->get('language.negotiation')->get('url.prefixes'); } /** -- GitLab From 2c5509a54b103aec37aa80b9586afd38a24178d7 Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 12:59:00 +0100 Subject: [PATCH 06/10] Issue #3507728: Remove not needed argument in method --- src/Target.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Target.php b/src/Target.php index d7082a6..6208e42 100644 --- a/src/Target.php +++ b/src/Target.php @@ -172,7 +172,6 @@ class Target implements TargetInterface { $path = $this->sanitizeUrl($path); } $this->setPath($path); - $this->getTargetLangcodeFromPath($path); } } -- GitLab From 8ed8a2810ae5ee685852b4cc66bbc19c8a05fcd5 Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 13:46:21 +0100 Subject: [PATCH 07/10] Issue #3507728: Add possibility to check alias without langcode. --- src/EntityRender.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index 70f27c1..77b17c0 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -259,7 +259,8 @@ class EntityRender extends Entity { */ protected function processInternalHref(TargetInterface $target) { - $alias = $target->getAlias(); + $alias = $this->entityMeshRepository->getPathWithoutLangPrefix($target->getPath()); + $target->setEntityLangcode($this->entityMeshRepository->getLangcodeFromPath($target->getPath())); $found_data = $this->setDataIfRedirection($alias, $target); @@ -347,9 +348,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; @@ -377,7 +376,7 @@ class EntityRender extends Entity { */ protected function setDataTargetFromAliasIfExists(string $alias, TargetInterface $target): bool { // Get the info from alias. - $langcode = $target->getEntityLangcode(); + $langcode = $target->getEntityLangcode() ?? ''; $record = $this->getPathFromAliasTables($alias, $langcode); if (!$record) { return FALSE; @@ -503,17 +502,14 @@ class EntityRender extends Entity { * @return mixed|null * Return the path. */ - protected function getPathFromAliasTables(string $alias, string $langcode = NULL) { + protected function getPathFromAliasTables(string $alias, string $langcode) { $query = $this->entityMeshRepository->getDatabaseService()->select('path_alias', 'pa'); $query->fields('pa', ['path']); $or = $query->orConditionGroup() ->condition('alias', $alias) ->condition('path', $alias); $query->condition($or); - if ($langcode !== NULL) { - $query->condition('langcode', $langcode); - } - + $query->condition('langcode', $langcode); $result = $query->execute(); if (!$result instanceof StatementInterface) { return NULL; -- GitLab From 62bb0323d81fe93411d0d88518a8f81acfa3b458 Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 14:16:18 +0100 Subject: [PATCH 08/10] Issue #3507728: Fix rebase --- src/EntityRender.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index 77b17c0..5c5ca07 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -509,7 +509,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; -- GitLab From c26f3e0b68837c0e8ec1a3397fa2d935b364d191 Mon Sep 17 00:00:00 2001 From: lpeidro <luis.ruiz@metadrop.net> Date: Thu, 20 Feb 2025 15:02:17 +0100 Subject: [PATCH 09/10] Issue #3507728: Ensure that langcode al least is an empty string --- src/EntityRender.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EntityRender.php b/src/EntityRender.php index 5c5ca07..28e9ef5 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -323,7 +323,7 @@ class EntityRender extends Entity { * If is a redirection. */ protected function setDataIfRedirection(string &$alias, TargetInterface $target): bool { - $langcode = $target->getEntityLangcode(); + $langcode = $target->getEntityLangcode() ?? ''; // Check if is a redirected link. $uri = $this->entityMeshRepository->ifRedirectionForPath($alias, $langcode); if ($uri === NULL) { -- GitLab From 98a35428a18bfae19ce7a6193bfd3c8a5a96296c Mon Sep 17 00:00:00 2001 From: Eduardo Morales <eduardo.morales@metadrop.net> Date: Thu, 20 Feb 2025 15:08:40 +0100 Subject: [PATCH 10/10] Issue #3507728 by eduardo morales alberti: Target langcode and source can be different --- entity_mesh.services.yml | 10 +++++++++- src/EntityRender.php | 28 ++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/entity_mesh.services.yml b/entity_mesh.services.yml index 8b79f02..b776574 100644 --- a/entity_mesh.services.yml +++ b/entity_mesh.services.yml @@ -17,7 +17,15 @@ services: arguments: ['@entity_mesh.repository', '@entity_type.manager', '@language_manager', '@config.factory'] entity_mesh.entity_render: class: Drupal\entity_mesh\EntityRender - arguments: ['@entity_mesh.repository', '@entity_type.manager', '@language_manager', '@config.factory', '@renderer', '@account_switcher', '@entity_mesh.language_negotiator_switcher'] + arguments: + - '@entity_mesh.repository' + - '@entity_type.manager' + - '@language_manager' + - '@config.factory' + - '@renderer' + - '@account_switcher' + - '@entity_mesh.language_negotiator_switcher' + - '@module_handler' entity_mesh.language_negotiator_switcher: class: Drupal\entity_mesh\Language\LanguageNegotiatorSwitcher arguments: ['@language_manager', '@module_handler', '@string_translation', '@entity_mesh.static_language_negotiator'] diff --git a/src/EntityRender.php b/src/EntityRender.php index 28e9ef5..8c78439 100644 --- a/src/EntityRender.php +++ b/src/EntityRender.php @@ -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,6 +41,14 @@ class EntityRender extends Entity { */ protected LanguageNegotiatorSwitcher $languageNegotiatorSwitcher; + + /** + * Module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected ModuleHandlerInterface $moduleHandler; + /** * Constructs a Menu object. * @@ -57,6 +66,8 @@ class EntityRender extends Entity { * 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, @@ -66,12 +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->moduleHandler = $module_handler; } /** @@ -376,12 +389,15 @@ class EntityRender extends Entity { */ protected function setDataTargetFromAliasIfExists(string $alias, TargetInterface $target): bool { // Get the info from alias. - $langcode = $target->getEntityLangcode() ?? ''; - $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, $target); + return $this->processInternalPaths($alias, $target); + } /** -- GitLab