Bug #87454

Slug/URL segment - /1 is wrongly saved, when trying to set / on rootpage.

Added by Stig Nørgaard Færch 7 months ago. Updated 9 days ago.

Status:
New
Priority:
Must have
Assignee:
-
Category:
Link Handling, Site Handling & Routing
Target version:
-
Start date:
2019-01-16
Due date:
% Done:

0%

TYPO3 Version:
9
PHP Version:
7.2
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

If you create a sysFolder or a standard page for that matter as a container for multiple sites, then it is impossible to make the root page of these sites to have just / as slug. It always adds 1.

The reason seems to be, that when validating the slug, it also considers the slug of the parent container folder, even though the root page of the site is configured in the Sites module.
I conclude this, as if I go and manipulate the DB-record of the container folder and replace / with container in slug, then everything works as expected again.


Related issues

Related to TYPO3 Core - Bug #87884: Root page of page tree suddenly gets slug "/1" Closed 2019-03-11
Related to TYPO3 Core - Bug #86727: Numeric in slugs on multidomain instances. Needs Feedback 2018-10-24

History

#1 Updated by Stig Nørgaard Færch 7 months ago

  • Category changed from DataHandler aka TCEmain to Link Handling, Site Handling & Routing

#2 Updated by Guido Schmechel 5 months ago

  • Related to Bug #87884: Root page of page tree suddenly gets slug "/1" added

#3 Updated by Riccardo De Contardi 4 months ago

  • Related to Bug #86727: Numeric in slugs on multidomain instances. added

#4 Updated by Stefan Neufeind 22 days ago

Still an issue. Manually adjusting the slug in the database works, as expected.

#5 Updated by Stefan Busemann 9 days ago

I can confirm the issue.

Our setup:

  • default lang: de / no language slug
  • overlay: en / en as language slug

If I go the root page (in default language - pid 1) and click "recalculate URL segment", the slug changes from "/" to "/1"

#6 Updated by Stefan Busemann 9 days ago

By changing Web/typo3/sysext/core/Classes/DataHandling/SlugHelper.php

to

    public function isUniqueInSite(string $slug, RecordState $state): bool
    {
        $pageId = $state->resolveNodeAggregateIdentifier();
        $recordId = $state->getSubject()->getIdentifier();
        $languageId = $state->getContext()->getLanguageId();

        if (!MathUtility::canBeInterpretedAsInteger($pageId)) {
            // If this is a new page, we use the parent page to resolve the site
            $pageId = $state->getNode()->getIdentifier();
        }
        $pageId = (int)$pageId;

        if ($pageId < 0) {
            $pageId = $this->resolveLivePageId($recordId);
        }

        $queryBuilder = $this->createPreparedQueryBuilder();
        $this->applySlugConstraint($queryBuilder, $slug);
        $this->applyRecordConstraint($queryBuilder, $recordId);
        $this->applyLanguageConstraint($queryBuilder, $languageId);
        $this->applyWorkspaceConstraint($queryBuilder);
        $statement = $queryBuilder->execute();

        $records = $this->resolveVersionOverlays(
            $statement->fetchAll()
        );
        if (count($records) === 0) {
            return true;
        }

        // The installation contains at least ONE other record with the same slug
        // Now find out if it is the same root page ID
        $siteMatcher = GeneralUtility::makeInstance(SiteMatcher::class);
        $siteMatcher->refresh();
        $siteOfCurrentRecord = $siteMatcher->matchByPageId($pageId);
        foreach ($records as $record) {
            try {
                $recordState = RecordStateFactory::forName($this->tableName)->fromArray($record);
                $siteOfExistingRecord = $siteMatcher->matchByPageId(
                    (int)$recordState->resolveNodeAggregateIdentifier()
                );
            } catch (SiteNotFoundException $exception) {
                // In case not site is found, the record is not
                // organized in any site or pseudo-site
                continue;
            }
            if ($siteOfExistingRecord->getRootPageId() === $siteOfCurrentRecord->getRootPageId()) {
                if ($pageId === (int)$recordState->getNode()->getIdentifier()) {
                    // if we are on the same page, we can skip it and return true
                    return true;
                } else {
                    return false;
                }
            }
        }

        // Otherwise, everything is still fine
        return true;
    }

I added this if statement:

                if ($pageId === (int)$recordState->getNode()->getIdentifier()) {
                    // if we are on the same page, we can skip it and return true
                    return true;
                } else {
                    return false;
                }

Also available in: Atom PDF