Project

General

Profile

Actions

Task #91663

open

PersistedAliasMapper can only resolve with fixed field "uid"

Added by Sven Erens almost 4 years ago. Updated 9 months ago.

Status:
New
Priority:
Should have
Assignee:
-
Category:
Link Handling, Site Handling & Routing
Target version:
-
Start date:
2020-06-17
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
9
PHP Version:
Tags:
Complexity:
Sprint Focus:

Description

I recently had an issue while migrating from RealURL to the new TYPO3 url handling. As RealURL has an option to resolve using any fieldname (setting "id_field"), the PersistedAliasMapper only supports the field "uid". In most cases this should be enough. In my case I had to create a new AliasMapper:

<?php
namespace VENDOR\Project\Routing\Aspect;

/**
 * Class PersistedAliasMapper.
 */
class PersistedAliasMapper extends \TYPO3\CMS\Core\Routing\Aspect\PersistedAliasMapper
{
    /**
     * @var string
     */
    protected $idFieldName;

    public function __construct(array $settings)
    {
        $idFieldName = $settings['idFieldName'] ?? 'uid';

        if (!is_string($idFieldName)) {
            throw new \InvalidArgumentException(
                'idFieldName must be string',
                1592311617
            );
        }

        $this->idFieldName = $idFieldName;

        parent::__construct($settings);
    }

    public function resolve(string $value): ?string
    {
        $value = $this->routeValuePrefix . $this->purgeRouteValuePrefix($value);
        $result = $this->findByRouteFieldValue($value);
        if ($result[$this->languageParentFieldName] ?? null > 0) {
            return (string)$result[$this->languageParentFieldName];
        }
        if (isset($result[$this->idFieldName])) {
            return (string)$result[$this->idFieldName];
        }
        return null;
    }

    protected function buildPersistenceFieldNames(): array
    {
        return array_filter([
            $this->idFieldName,
            'pid',
            $this->routeFieldName,
            $this->languageFieldName,
            $this->languageParentFieldName,
        ]);
    }

    protected function findByIdentifier(string $value): ?array
    {
        $queryBuilder = $this->createQueryBuilder();
        $result = $queryBuilder
            ->select(...$this->persistenceFieldNames)
            ->where($queryBuilder->expr()->eq(
                $this->idFieldName,
                $queryBuilder->createNamedParameter($value, \PDO::PARAM_INT)
            ))
            ->execute()
            ->fetch();

        return $result !== false ? $result : null;
    }
}

As you can see I only changed the hard coded "uid"-field to a setting, which defaults to "uid". Maybe you want to apply this to the core.

Actions #1

Updated by Sven Erens almost 4 years ago

  • Description updated (diff)
Actions #2

Updated by Stefan P over 3 years ago

I'll join this request. We have the same issue. We have a routing-enabled table that is not in TCA (its rows are fully autogenerated by custom PHP and not used in Extbase or whatever) and has neither the uid nor pid field.

I also extended the core aspect and overwrote all methods to fetch from the correct fields.

In our case the primary (id) field is also no int, but a varchar.

Actions #3

Updated by Oliver Hader over 1 year ago

  • Sprint Focus set to On Location Sprint
Actions #4

Updated by Benni Mack 9 months ago

  • Sprint Focus deleted (On Location Sprint)
Actions

Also available in: Atom PDF