Skip to content

Commit

Permalink
Implement the content URL generator (see #6596)
Browse files Browse the repository at this point in the history
Description
-----------

Finally! This is a first step towards the _Content URL Generator_. I was able to get this wrapped up so that **generating the URL** is separated from **matching a URL (with parameters)**. This is only the part about generating URLs for any content, since the other part is way more complex and not finished yet.

Be aware that this deprecates the `PageModel::getFrontendUrl`/`getAbsoluteUrl` methods, but it does not replace it in all places. Probably not everywhere in core-bundle, and currently in non of the add-on bundles.

This does not yet implement content URL generator for any of our add-on bundles (like news and events), because that alone are dozens of file to adjust and will be easier to review in separate PRs (I do have some of that code available locally though, so I can quickly add them once this is merged).


- [x] Replaces #6547
- [x] (Probably) requires #6595 and #6594
- [x] Needs tests on the new services

Commits
-------

ba2bd8e Implement the content URL generator
83d3f27 Various improvements, CS and tests
9636820 Use the ContentUrlGenerator in the SERP widget
ad1e137 Correctly mark URL result as redirect
cc27676 Cache exceptions thrown when generating a content URL
279308a Merge remote-tracking branch 'upstream/5.x' into feature/content-url-…
71c1abd Remove unnecessary optional parameters
53f4cda Re-add the reference type
bbbb67a Fix existing code for absolute URLs
b8177b8 Fixed tests
873e033 Skip cache if content or parameters are not serializable (e.g. contai…
1903333 Tests for ContentUrlGenerator
8fd38de Fixes from code review
ba10d11 Tests for resolvers
74267e8 Fixed argument of AuthenticationSuccessHandler
9a13b4e Fixed phpstan error
419360d Fixed phpstan error
5487c57 Drop the obsolete SerpPreview url_callback for tl_page
03b5b56 Replace PageModel::getFrontendUrl and getAbsoluteUrl
2ea63d7 Added review comments
23b8f7b Fix CI
223644d Replace PageModel::getFrontendUrl and getAbsoluteUrl
4303856 Correctly make URLs absolute
34cf962 Fixed tests
a941ccd Rename the ContentUrlResult
ba24a4a Revert "Rename the ContentUrlResult"
9b529db Use NULL instead of ContentUrlResult::abstain()
f5fe023 Remove the null option
  • Loading branch information
aschempp committed Jan 17, 2024
1 parent c3d5726 commit 3f26369
Show file tree
Hide file tree
Showing 56 changed files with 1,685 additions and 503 deletions.
1 change: 1 addition & 0 deletions core-bundle/config/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -221,5 +221,6 @@ services:
arguments:
- '@contao.routing.page_registry'
- '@contao.routing.page_finder'
- '@contao.routing.content_url_generator'
tags:
- controller.service_arguments
2 changes: 2 additions & 0 deletions core-bundle/config/listener.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ services:
arguments:
- '@contao.framework'
- '@contao.routing.page_registry'
- '@contao.routing.content_url_generator'
- '@uri_signer'
- '%fragment.path%'
tags:
Expand Down Expand Up @@ -585,6 +586,7 @@ services:
arguments:
- '@contao.framework'
- '@contao.routing.scope_matcher'
- '@contao.routing.content_url_generator'
- '@security.token_storage'
- '%scheb_two_factor.security_tokens%'
tags:
Expand Down
29 changes: 29 additions & 0 deletions core-bundle/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ services:
arguments:
- '@database_connection'
- '@contao.framework'
- '@contao.routing.content_url_generator'

contao.crawl.escargot.search_index_subscriber:
class: Contao\CoreBundle\Crawl\Escargot\Subscriber\SearchIndexSubscriber
Expand Down Expand Up @@ -467,6 +468,7 @@ services:
arguments:
- '@contao.framework'
- '@contao.security.token_checker'
- '@contao.routing.content_url_generator'

contao.insert_tag.string_util_flag:
class: Contao\CoreBundle\InsertTag\Flag\StringUtilFlag
Expand Down Expand Up @@ -651,6 +653,31 @@ services:
contao.routing.backend_matcher:
class: Contao\CoreBundle\Routing\Matcher\BackendMatcher

contao.routing.content.article_resolver:
class: Contao\CoreBundle\Routing\Content\ArticleResolver
arguments:
- '@contao.framework'

contao.routing.content.page_resolver:
class: Contao\CoreBundle\Routing\Content\PageResolver
arguments:
- '@contao.framework'

contao.routing.content.string_resolver:
class: Contao\CoreBundle\Routing\Content\StringResolver
arguments:
- '@contao.insert_tag.parser'
- '@url_helper'

contao.routing.content_url_generator:
class: Contao\CoreBundle\Routing\ContentUrlGenerator
arguments:
- '@router'
- '@contao.routing.page_registry'
- '@doctrine.orm.entity_manager'
- !tagged_iterator contao.content_url_resolver
public: true

contao.routing.frontend_matcher:
class: Contao\CoreBundle\Routing\Matcher\FrontendMatcher

Expand Down Expand Up @@ -839,6 +866,7 @@ services:
- '@contao.framework'
- '@contao.security.two_factor.trusted_device_manager'
- '@security.firewall.map'
- '@contao.routing.content_url_generator'
- '@uri_signer'
- '@security.token_storage'
- '@?logger'
Expand Down Expand Up @@ -1236,6 +1264,7 @@ services:
Contao\CoreBundle\Mailer\AvailableTransports: '@contao.mailer.available_transports'
Contao\CoreBundle\OptIn\OptIn: '@contao.opt_in'
Contao\CoreBundle\Picker\PickerBuilderInterface: '@contao.picker.builder'
Contao\CoreBundle\Routing\ContentUrlGenerator: '@contao.routing.content_url_generator'
Contao\CoreBundle\Routing\PageFinder: '@contao.routing.page_finder'
Contao\CoreBundle\Routing\Page\PageRegistry: '@contao.routing.page_registry'
Contao\CoreBundle\Routing\ResponseContext\ResponseContextAccessor: '@contao.routing.response_context_accessor'
Expand Down
5 changes: 4 additions & 1 deletion core-bundle/contao/classes/Frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Contao\CoreBundle\Util\LocaleUtil;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
* Provide methods to manage front end controllers.
Expand Down Expand Up @@ -163,7 +164,9 @@ protected function jumpToOrReload($intId, $strParams=null)

if ($intId > 0 && ($intId != $objPage->id || $blnForceRedirect) && ($objNextPage = PageModel::findPublishedById($intId)) !== null)
{
$this->redirect($objNextPage->getAbsoluteUrl($strParams));
$urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

$this->redirect($urlGenerator->generate($objNextPage, $strParams ? array('parameters' => $strParams) : array(), UrlGeneratorInterface::ABSOLUTE_URL));
}

$this->reload();
Expand Down
14 changes: 1 addition & 13 deletions core-bundle/contao/dca/tl_page.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ static function ($value) {
(
'label' => &$GLOBALS['TL_LANG']['MSC']['serpPreview'],
'inputType' => 'serpPreview',
'eval' => array('url_callback'=>array('tl_page', 'getSerpUrl'), 'title_tag_callback'=>array('tl_page', 'getTitleTag'), 'titleFields'=>array('pageTitle', 'title'), 'tl_class'=>'clr'),
'eval' => array('title_tag_callback'=>array('tl_page', 'getTitleTag'), 'titleFields'=>array('pageTitle', 'title'), 'tl_class'=>'clr'),
'sql' => null
),
'redirect' => array
Expand Down Expand Up @@ -748,18 +748,6 @@ public function setRootType(DataContainer $dc)
}
}

/**
* Return the SERP URL
*
* @param PageModel $page
*
* @return string
*/
public function getSerpUrl(PageModel $page)
{
return $page->getAbsoluteUrl();
}

/**
* Return the title tag from the associated page layout
*
Expand Down
3 changes: 2 additions & 1 deletion core-bundle/contao/elements/ContentTeaser.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ public function generate()
protected function compile()
{
$objArticle = $this->objArticle;
$urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

$this->Template->href = $this->objParent->getFrontendUrl('/articles/' . ($objArticle->alias ?: $objArticle->id));
$this->Template->href = $urlGenerator->generate($objArticle);
$this->Template->text = $objArticle->teaser;
$this->Template->headline = $objArticle->title;
$this->Template->readMore = StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['readMore'], $objArticle->title));
Expand Down
10 changes: 7 additions & 3 deletions core-bundle/contao/forms/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,14 @@ protected function compile()
$this->Template->ajax = $this->isAjaxEnabled();

// Get the target URL
if ($this->method == 'GET' && ($objTarget = $this->objModel->getRelated('jumpTo')) instanceof PageModel)
if ($this->method == 'GET')
{
/** @var PageModel $objTarget */
$this->Template->action = $objTarget->getFrontendUrl();
$objTarget = $this->objModel->getRelated('jumpTo');

if ($objTarget instanceof PageModel)
{
$this->Template->action = System::getContainer()->get('contao.routing.content_url_generator')->generate($objTarget);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions core-bundle/contao/library/Contao/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -1223,11 +1223,11 @@ public static function resetControllerCache()
* @return string The URL of the target page
*
* @deprecated Deprecated since Contao 5.3, to be removed in Contao 6.0.
* Use "PageModel::getAbsoluteUrl()" and the contao_backend_preview route instead.
* Use the contao_backend_preview route instead.
*/
protected function redirectToFrontendPage($intPage, $strArticle=null, $blnReturn=false)
{
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use "PageModel::getAbsoluteUrl()" and the contao_backend_preview route instead.', __METHOD__);
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use the contao_backend_preview route instead.', __METHOD__);

if (($intPage = (int) $intPage) <= 0)
{
Expand Down
51 changes: 29 additions & 22 deletions core-bundle/contao/models/PageModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@
namespace Contao;

use Contao\CoreBundle\Exception\NoRootPageFoundException;
use Contao\CoreBundle\Routing\Page\PageRoute;
use Contao\CoreBundle\Util\LocaleUtil;
use Contao\Model\Collection;
use Contao\Model\Registry;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
Expand Down Expand Up @@ -1104,27 +1102,30 @@ public function loadDetails()
* @throws ResourceNotFoundException
*
* @return string A URL that can be used in the front end
*
* @deprecated Deprecated since Contao 5.3, to be removed in Contao 6;
* use the content URL generator instead.
*/
public function getFrontendUrl($strParams=null)
{
$page = $this;
$page->loadDetails();
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use the content URL generator instead.', __METHOD__);

$objRouter = System::getContainer()->get('router');
$referenceType = $this->domain && $objRouter->getContext()->getHost() !== $this->domain ? UrlGeneratorInterface::ABSOLUTE_URL : UrlGeneratorInterface::ABSOLUTE_PATH;
$this->loadDetails();

if (\is_array($strParams))
{
$parameters = array_merge($strParams, array(RouteObjectInterface::CONTENT_OBJECT => $page));
$parameters = $strParams;
}
else
{
$parameters = array(RouteObjectInterface::CONTENT_OBJECT => $page, 'parameters' => $strParams);
$parameters = array('parameters' => $strParams);
}

$objRouter = System::getContainer()->get('contao.routing.content_url_generator');

try
{
$strUrl = $objRouter->generate(PageRoute::PAGE_BASED_ROUTE_NAME, $parameters, $referenceType);
$strUrl = $objRouter->generate($this, $parameters);
}
catch (RouteNotFoundException $e)
{
Expand All @@ -1150,25 +1151,30 @@ public function getFrontendUrl($strParams=null)
* @throws ResourceNotFoundException
*
* @return string An absolute URL that can be used in the front end
*
* @deprecated Deprecated since Contao 5.3, to be removed in Contao 6;
* use the content URL generator instead.
*/
public function getAbsoluteUrl($strParams=null)
{
$this->loadDetails();
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use the content URL generator instead.', __METHOD__);

$objRouter = System::getContainer()->get('router');
$this->loadDetails();

if (\is_array($strParams))
{
$parameters = array_merge($strParams, array(RouteObjectInterface::CONTENT_OBJECT => $this));
$parameters = $strParams;
}
else
{
$parameters = array(RouteObjectInterface::CONTENT_OBJECT => $this, 'parameters' => $strParams);
$parameters = array('parameters' => $strParams);
}

$objRouter = System::getContainer()->get('contao.routing.content_url_generator');

try
{
$strUrl = $objRouter->generate(PageRoute::PAGE_BASED_ROUTE_NAME, $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
$strUrl = $objRouter->generate($this, $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
}
catch (RouteNotFoundException $e)
{
Expand All @@ -1194,10 +1200,13 @@ public function getAbsoluteUrl($strParams=null)
* @throws ResourceNotFoundException
*
* @return string The front end preview URL
*
* @deprecated Deprecated since Contao 5.3, to be removed in Contao 6;
* use the content URL generator instead
*/
public function getPreviewUrl($strParams=null)
{
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use "PageModel::getAbsoluteUrl()" and the contao_backend_preview route instead.', __METHOD__);
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s()" has been deprecated and will no longer work in Contao 6. Use the contao_backend_preview route instead.', __METHOD__);

$container = System::getContainer();

Expand All @@ -1206,28 +1215,26 @@ public function getPreviewUrl($strParams=null)
return $this->getAbsoluteUrl($strParams);
}

$this->loadDetails();
$objRouter = System::getContainer()->get('contao.routing.content_url_generator');

$context = $container->get('router')->getContext();
$context = $objRouter->getContext();
$baseUrl = $context->getBaseUrl();

// Add the preview script
$context->setBaseUrl(preg_replace('(/[^/]*$)', '', $baseUrl) . $previewScript);

$objRouter = System::getContainer()->get('router');

if (\is_array($strParams))
{
$parameters = array_merge($strParams, array(RouteObjectInterface::CONTENT_OBJECT => $this));
$parameters = $strParams;
}
else
{
$parameters = array(RouteObjectInterface::CONTENT_OBJECT => $this, 'parameters' => $strParams);
$parameters = array('parameters' => $strParams);
}

try
{
$strUrl = $objRouter->generate(PageRoute::PAGE_BASED_ROUTE_NAME, $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
$strUrl = $objRouter->generate($this, $parameters);
}
catch (RouteNotFoundException $e)
{
Expand Down

0 comments on commit 3f26369

Please sign in to comment.