Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate news URLs using the content URL generator #6604

Merged
merged 13 commits into from
Jan 17, 2024
10 changes: 10 additions & 0 deletions news-bundle/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ services:
class: Contao\NewsBundle\EventListener\GeneratePageListener
arguments:
- '@contao.framework'
- '@contao.routing.content_url_generator'
tags:
- { name: contao.hook, hook: generatePage }

contao_news.listener.insert_tags:
class: Contao\NewsBundle\EventListener\InsertTagsListener
arguments:
- '@contao.framework'
- '@contao.routing.content_url_generator'
- '@logger'
tags:
- { name: contao.hook, hook: replaceInsertTags }
Expand All @@ -58,6 +60,7 @@ services:
arguments:
- '@contao.framework'
- '@contao.image.factory'
- '@contao.routing.content_url_generator'
- '@contao.insert_tag.parser'
- '%kernel.project_dir%'
- '@contao.cache.entity_tags'
Expand All @@ -67,6 +70,7 @@ services:
class: Contao\NewsBundle\EventListener\PreviewUrlConvertListener
arguments:
- '@contao.framework'
- '@contao.routing.content_url_generator'
tags:
- kernel.event_listener

Expand All @@ -83,6 +87,7 @@ services:
arguments:
- '@contao.framework'
- '@security.helper'
- '@contao.routing.content_url_generator'
tags:
- kernel.event_listener

Expand All @@ -104,6 +109,11 @@ services:
tags:
- { name: contao.picker_provider, priority: 128 }

contao_news.routing.news_resolver:
class: Contao\NewsBundle\Routing\NewsResolver
arguments:
- '@contao.framework'

contao_news.security.news_access_voter:
class: Contao\NewsBundle\Security\Voter\NewsAccessVoter
arguments:
Expand Down
93 changes: 17 additions & 76 deletions news-bundle/contao/classes/News.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@

namespace Contao;

use Symfony\Component\Routing\Exception\ExceptionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
* Provide methods regarding news archives.
*/
class News extends Frontend
{
/**
* URL cache array
* @var array
*/
private static $arrUrlCache = array();

/**
* Generate a URL and return it as string
*
Expand All @@ -30,85 +27,28 @@ class News extends Frontend
*
* @return string
*/
public static function generateNewsUrl($objItem, $blnAddArchive=false, $blnAbsolute=false)
public static function generateNewsUrl($objItem, $blnAddArchive=false, $blnAbsolute=true)
leofeyer marked this conversation as resolved.
Show resolved Hide resolved
{
$strCacheKey = 'id_' . $objItem->id . ($blnAbsolute ? '_absolute' : '') . (($blnAddArchive && Input::get('month')) ? '_' . Input::get('month') : '');
trigger_deprecation('contao/core-bundle', '5.3', 'Using "%s" is deprecated, use the content URL generator instead.', __METHOD__);

// Load the URL from cache
if (isset(self::$arrUrlCache[$strCacheKey]))
try
{
return self::$arrUrlCache[$strCacheKey];
}

// Initialize the cache
self::$arrUrlCache[$strCacheKey] = null;

switch ($objItem->source)
{
// Link to an external page
case 'external':
if (str_starts_with($objItem->url, 'mailto:'))
{
self::$arrUrlCache[$strCacheKey] = StringUtil::encodeEmail($objItem->url);
}
else
{
$url = $objItem->url;

if (Validator::isRelativeUrl($url))
{
$url = Environment::get('path') . '/' . $url;
}

self::$arrUrlCache[$strCacheKey] = StringUtil::ampersand($url);
}
break;

// Link to an internal page
case 'internal':
if (($objTarget = $objItem->getRelated('jumpTo')) instanceof PageModel)
{
/** @var PageModel $objTarget */
self::$arrUrlCache[$strCacheKey] = StringUtil::ampersand($blnAbsolute ? $objTarget->getAbsoluteUrl() : $objTarget->getFrontendUrl());
}
break;

// Link to an article
case 'article':
if (($objArticle = ArticleModel::findByPk($objItem->articleId)) instanceof ArticleModel && ($objPid = $objArticle->getRelated('pid')) instanceof PageModel)
{
$params = '/articles/' . ($objArticle->alias ?: $objArticle->id);

/** @var PageModel $objPid */
self::$arrUrlCache[$strCacheKey] = StringUtil::ampersand($blnAbsolute ? $objPid->getAbsoluteUrl($params) : $objPid->getFrontendUrl($params));
}
break;
}

// Link to the default page
if (self::$arrUrlCache[$strCacheKey] === null)
{
$objPage = PageModel::findByPk($objItem->getRelated('pid')->jumpTo);

if (!$objPage instanceof PageModel)
{
self::$arrUrlCache[$strCacheKey] = StringUtil::ampersand(Environment::get('requestUri'));
}
else
{
$params = '/' . ($objItem->alias ?: $objItem->id);

self::$arrUrlCache[$strCacheKey] = StringUtil::ampersand($blnAbsolute ? $objPage->getAbsoluteUrl($params) : $objPage->getFrontendUrl($params));
}
$parameters = array();

// Add the current archive parameter (news archive)
if ($blnAddArchive && Input::get('month'))
{
self::$arrUrlCache[$strCacheKey] .= '?month=' . Input::get('month');
$parameters['month'] = Input::get('month');
}

$url = System::getContainer()->get('contao.routing.content_url_generator')->generate($objItem, $parameters, $blnAbsolute ? UrlGeneratorInterface::ABSOLUTE_URL : UrlGeneratorInterface::ABSOLUTE_PATH);
}
catch (ExceptionInterface)
{
return StringUtil::ampersand(Environment::get('requestUri'));
}

return self::$arrUrlCache[$strCacheKey];
return $url;
}

/**
Expand All @@ -121,11 +61,12 @@ public static function generateNewsUrl($objItem, $blnAddArchive=false, $blnAbsol
public static function getSchemaOrgData(NewsModel $objArticle): array
{
$htmlDecoder = System::getContainer()->get('contao.string.html_decoder');
$urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

$jsonLd = array(
'@type' => 'NewsArticle',
'identifier' => '#/schema/news/' . $objArticle->id,
'url' => self::generateNewsUrl($objArticle),
'url' => $urlGenerator->generate($objArticle),
'headline' => $htmlDecoder->inputEncodedToPlainText($objArticle->headline),
'datePublished' => date('Y-m-d\TH:i:sP', $objArticle->date),
);
Expand Down
14 changes: 1 addition & 13 deletions news-bundle/contao/dca/tl_news.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
(
'label' => &$GLOBALS['TL_LANG']['MSC']['serpPreview'],
'inputType' => 'serpPreview',
'eval' => array('url_callback'=>array('tl_news', 'getSerpUrl'), 'title_tag_callback'=>array('tl_news', 'getTitleTag'), 'titleFields'=>array('pageTitle', 'headline'), 'descriptionFields'=>array('description', 'teaser')),
'eval' => array('title_tag_callback'=>array('tl_news', 'getTitleTag'), 'titleFields'=>array('pageTitle', 'headline'), 'descriptionFields'=>array('description', 'teaser')),
'sql' => null
),
'canonicalLink' => array
Expand Down Expand Up @@ -481,18 +481,6 @@ public function loadTime($value)
return strtotime('1970-01-01 ' . date('H:i:s', $value));
}

/**
* Return the SERP URL
*
* @param NewsModel $model
*
* @return string
*/
public function getSerpUrl(NewsModel $model)
{
return News::generateNewsUrl($model, false, true);
}

/**
* Return the title tag from the associated page layout
*
Expand Down
17 changes: 15 additions & 2 deletions news-bundle/contao/modules/ModuleNews.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ protected function parseArticle($objArticle, $blnAddArchive=false, $strClass='',
$objTemplate->hasSubHeadline = $objArticle->subheadline ? true : false;
$objTemplate->linkHeadline = $this->generateLink($objArticle->headline, $objArticle, $blnAddArchive);
$objTemplate->more = $this->generateLink($objArticle->linkText ?: $GLOBALS['TL_LANG']['MSC']['more'], $objArticle, $blnAddArchive, true);
$objTemplate->link = News::generateNewsUrl($objArticle, $blnAddArchive);
$objTemplate->link = $this->generateContentUrl($objArticle, $blnAddArchive);
$objTemplate->archive = $objArticle->getRelated('pid');
$objTemplate->count = $intCount; // see #5708
$objTemplate->text = '';
Expand Down Expand Up @@ -302,7 +302,7 @@ protected function generateLink($strLink, $objArticle, $blnAddArchive=false, $bl
{
$blnIsInternal = $objArticle->source != 'external';
$strReadMore = $blnIsInternal ? $GLOBALS['TL_LANG']['MSC']['readMore'] : $GLOBALS['TL_LANG']['MSC']['open'];
$strArticleUrl = News::generateNewsUrl($objArticle, $blnAddArchive);
$strArticleUrl = $this->generateContentUrl($objArticle, $blnAddArchive);

return sprintf(
'<a href="%s" title="%s"%s>%s%s</a>',
Expand All @@ -313,4 +313,17 @@ protected function generateLink($strLink, $objArticle, $blnAddArchive=false, $bl
$blnIsReadMore && $blnIsInternal ? '<span class="invisible"> ' . $objArticle->headline . '</span>' : ''
);
}

private function generateContentUrl(NewsModel $content, bool $addArchive): string
{
$parameters = array();

// Add the current archive parameter (news archive)
if ($addArchive && Input::get('month'))
{
$parameters['month'] = Input::get('month');
}

return System::getContainer()->get('contao.routing.content_url_generator')->generate($content, $parameters);
}
}
12 changes: 10 additions & 2 deletions news-bundle/contao/modules/ModuleNewsMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace Contao;

use Contao\CoreBundle\Exception\PageNotFoundException;
use Symfony\Component\Routing\Exception\ExceptionInterface;

/**
* Front end module "news archive".
Expand Down Expand Up @@ -74,8 +75,15 @@ public function generate()

if (($objTarget = $this->objModel->getRelated('jumpTo')) instanceof PageModel)
{
/** @var PageModel $objTarget */
$this->strUrl = $objTarget->getFrontendUrl();
try
{
$urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

$this->strUrl = $urlGenerator->generate($objTarget);
}
catch (ExceptionInterface)
{
}
}

return parent::generate();
Expand Down
33 changes: 7 additions & 26 deletions news-bundle/contao/modules/ModuleNewsReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Contao\CoreBundle\Exception\RedirectResponseException;
use Contao\CoreBundle\Routing\ResponseContext\HtmlHeadBag\HtmlHeadBag;
use Contao\CoreBundle\Util\UrlUtil;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
* Front end module "newsreader".
Expand Down Expand Up @@ -75,11 +76,13 @@ public function generate()
*/
protected function compile()
{
$urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

$this->Template->articles = '';

if ($this->overviewPage)
if ($this->overviewPage && ($overviewPage = PageModel::findById($this->overviewPage)))
{
$this->Template->referer = PageModel::findById($this->overviewPage)->getFrontendUrl();
$this->Template->referer = $urlGenerator->generate($overviewPage);
$this->Template->back = $this->customLabel ?: $GLOBALS['TL_LANG']['MSC']['newsOverview'];
}

Expand All @@ -96,31 +99,9 @@ protected function compile()
switch ($objArticle->source)
{
case 'internal':
if ($page = PageModel::findPublishedById($objArticle->jumpTo))
{
throw new RedirectResponseException($page->getAbsoluteUrl(), 301);
}

throw new InternalServerErrorException('Invalid "jumpTo" value or target page not public');

case 'article':
if (($article = ArticleModel::findByPk($objArticle->articleId)) && ($page = PageModel::findPublishedById($article->pid)))
{
throw new RedirectResponseException($page->getAbsoluteUrl('/articles/' . ($article->alias ?: $article->id)), 301);
}

throw new InternalServerErrorException('Invalid "articleId" value or target page not public');

case 'external':
if ($objArticle->url)
{
$url = System::getContainer()->get('contao.insert_tag.parser')->replaceInline($objArticle->url);
$url = UrlUtil::makeAbsolute($url, Environment::get('base'));

throw new RedirectResponseException($url, 301);
}

throw new InternalServerErrorException('Empty target URL');
throw new RedirectResponseException(System::getContainer()->get('contao.routing.content_url_generator')->generate($objArticle, array(), UrlGeneratorInterface::ABSOLUTE_URL), 301);
}

// Set the default template
Expand Down Expand Up @@ -183,7 +164,7 @@ protected function compile()
}
elseif (!$this->news_keepCanonical)
{
$htmlHeadBag->setCanonicalUri(News::generateNewsUrl($objArticle, false, true));
$htmlHeadBag->setCanonicalUri($urlGenerator->generate($objArticle, array(), UrlGeneratorInterface::ABSOLUTE_URL));
}
}

Expand Down
14 changes: 11 additions & 3 deletions news-bundle/src/EventListener/GeneratePageListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@
namespace Contao\NewsBundle\EventListener;

use Contao\CoreBundle\Framework\ContaoFramework;
use Contao\CoreBundle\Routing\ContentUrlGenerator;
use Contao\LayoutModel;
use Contao\NewsBundle\Controller\Page\NewsFeedController;
use Contao\PageModel;
use Contao\StringUtil;
use Symfony\Component\Routing\Exception\ExceptionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
* @internal
*/
class GeneratePageListener
{
public function __construct(private readonly ContaoFramework $framework)
{
public function __construct(
private readonly ContaoFramework $framework,
private readonly ContentUrlGenerator $urlGenerator,
) {
}

/**
Expand Down Expand Up @@ -52,7 +57,10 @@ public function __invoke(PageModel $pageModel, LayoutModel $layoutModel): void
}

// TODO: Use ResponseContext, once it supports appending to <head>
$GLOBALS['TL_HEAD'][] = $this->generateFeedTag($feed->getAbsoluteUrl(), $feed->feedFormat, $feed->title);
try {
$GLOBALS['TL_HEAD'][] = $this->generateFeedTag($this->urlGenerator->generate($feed, [], UrlGeneratorInterface::ABSOLUTE_URL), $feed->feedFormat, $feed->title);
} catch (ExceptionInterface) {
}
}
}

Expand Down