Ventus
Ventus

Reputation: 2550

TYPO3 8 LTS how to generate frontend page URL in CLI/Scheduler context

I'm trying to figure out how to generate absolute frontend page URLs from CLI/Scheduler context. I've created the following helper class:


class FrontendUrlProvider
{
    /**
     * @var ObjectManagerInterface
     */
    private $objectManager;
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param ObjectManagerInterface $objectManager
     * @param LoggerInterface $logger
     */
    public function __construct(ObjectManagerInterface $objectManager, LoggerInterface $logger)
    {
        $this->objectManager = $objectManager;
        $this->initializeTimeTracker();
        $this->logger = $logger;
    }

    /**
     * @param int $pageId
     * @param int $languageId
     * @return Uri
     */
    public function pageUrl($pageId, $languageId)
    {
        $url = '';
        $this->logger->error('generating preview link');

        try {
            $this->initializeTypoScriptFrontend($pageId);
            $this->setUpPageDomainIfCliContext($pageId);

            $contentRenderer = $this->objectManager->get(ContentObjectRenderer::class);
            $command = $this->linkCommand($pageId, $languageId);

            $url = $contentRenderer->typoLink_URL($command);
            $this->logger->error("preview link is: $url");
        } catch (\Exception $exception) {
            $this->logger->error($exception->getMessage());
            $this->logger->error($exception->getTraceAsString());
        }

        return new Uri($url);
    }

    private function initializeTimeTracker()
    {
        if (!is_object($GLOBALS['TT'])) {
            $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker();
        }
    }

    /**
     * @param int $pageId
     */
    private function initializeTypoScriptFrontend($pageId)
    {
        if (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TFSE'])) {
            return;
        }

        $GLOBALS['TSFE'] = $this->objectManager->get(TypoScriptFrontendController::class, $GLOBALS['TYPO3_CONF_VARS'], $pageId, '');
        $GLOBALS['TSFE']->sys_page = $this->objectManager->get(PageRepository::class);
        $GLOBALS['TSFE']->sys_page->init(false);
        $GLOBALS['TSFE']->tmpl = $this->objectManager->get(TemplateService::class);
        $GLOBALS['TSFE']->tmpl->init();
        $GLOBALS['TSFE']->connectToDB();
        $GLOBALS['TSFE']->initFEuser();
        $GLOBALS['TSFE']->determineId();
        $GLOBALS['TSFE']->initTemplate();
        $GLOBALS['TSFE']->getConfigArray();
    }

    /**
     * @param int $pageId
     */
    private function setUpPageDomainIfCliContext($pageId)
    {
        if (!isset($_SERVER['HTTP_HOST']) || !$_SERVER['HTTP_HOST']) {
            $domainData = $GLOBALS['TSFE']->getDomainDataForPid($pageId);

            if (is_array($domainData) && isset($domainData['domainName']) && !empty($domainData['domainName'])) {
                $_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';
            }
        }
    }

    /**
     * @param int $pageId
     * @param int $languageId
     * @return array
     */
    private function linkCommand($pageId, $languageId)
    {
        $languageQuery = http_build_query(['L' => $languageId], null, '&', PHP_QUERY_RFC3986);

        return array(
            'parameter' => $pageId,
            'useCacheHash' => false,
            'forceAbsoluteUrl' => true,
            'linkAccessRestrictedPages' => true,
            'additionalParams' => '&' . $languageQuery,
        );
    }
}

I'm at the point that it works fine in TYPO3 7 LTS, as long as there's a domain record for the root line.

However this same snippet doesn't work in TYPO3 8 LTS and I need it working for both 7 and 8 at the same time. Obviously, I have set the domain record on the root line in v8, I cleared all the caches, etc. but I can't get an absolute URL in place. I only get the relative URL. At this point I'm not that interested in realUrl or anything like that.

For TYPO3 7 I basically reverse engineered it but with TYPO3 8 it seems a bit more complicated. Do you know what can I do more to get the page frontend URL?

Upvotes: 1

Views: 2079

Answers (2)

DerSchreiner
DerSchreiner

Reputation: 276

https://wissen.netzhaut.de/typo3/extensionentwicklung/typolink-realurl-in-scheduler-tasks/

But really: I'd recommend using a curl call against a custom page which will deliver the link (sort of as a rest API) - because thereby you go around almost all issues - and there are more beyond not having tsfe (e.g. safePath \ images).

Upvotes: 0

Ventus
Ventus

Reputation: 2550

It seems that the issue was an internal cache of the GeneralUtility, which cached a null value for the HTTP_HOST of $_SERVER superglobal.

Therefore the following line from my example above had no effect

$_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';

In order to make it work under the CLI/Scheduler scope I had to clear the internal cache of the GeneralUtility by calling


TYPO3\CMS\Core\Utility\GeneralUtility::flushInternalRuntimeCaches();

before making a call to $contentRenderer->typoLink_URL($command);

Now frontend URL generation works fine on both TYPO3 7 and 8 LTS.

Upvotes: 1

Related Questions