The annual foobar event.
'; - $events = $this->mockAdapter(['generateEventUrl']); - $events - ->method('generateEventUrl') - ->willReturnCallback( - static function (CalendarEventsModel $model, bool $absolute): string { - if ($absolute) { - return 'http://domain.tld/events/the-foobar-event.html'; - } - - return 'events/the-foobar-event.html'; - } - ) + $eventModel + ->method('getFrontendUrl') + ->willReturn('events/the-foobar-event.html') + ; + + $eventModel + ->method('getAbsoluteUrl') + ->willReturn('http://domain.tld/events/the-foobar-event.html') ; $adapters = [ CalendarEventsModel::class => $this->mockConfiguredAdapter(['findByIdOrAlias' => $eventModel]), - Events::class => $events, ]; $listener = new InsertTagsListener($this->mockContaoFramework($adapters)); diff --git a/calendar-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php b/calendar-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php index 224e9a42e7f..6c5bae5c97e 100644 --- a/calendar-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php +++ b/calendar-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php @@ -16,7 +16,6 @@ use Contao\CalendarEventsModel; use Contao\CoreBundle\Event\PreviewUrlConvertEvent; use Contao\CoreBundle\Framework\ContaoFramework; -use Contao\Events; use Contao\TestCase\ContaoTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -34,10 +33,14 @@ public function testConvertsThePreviewUrl(): void $requestStack->push($request); $eventModel = $this->createMock(CalendarEventsModel::class); + $eventModel + ->expects($this->once()) + ->method('getFrontendUrl') + ->willReturn('events/winter-holidays.html') + ; $adapters = [ CalendarEventsModel::class => $this->mockConfiguredAdapter(['findByPk' => $eventModel]), - Events::class => $this->mockConfiguredAdapter(['generateEventUrl' => 'events/winter-holidays.html']), ]; $framework = $this->mockContaoFramework($adapters); diff --git a/core-bundle/src/Resources/contao/config/config.php b/core-bundle/src/Resources/contao/config/config.php index 1f7cd9932ac..b922ce881eb 100644 --- a/core-bundle/src/Resources/contao/config/config.php +++ b/core-bundle/src/Resources/contao/config/config.php @@ -233,7 +233,8 @@ 'imageSize' => 'Contao\ImageSize', 'timePeriod' => 'Contao\TimePeriod', 'metaWizard' => 'Contao\MetaWizard', - 'sectionWizard' => 'Contao\SectionWizard' + 'sectionWizard' => 'Contao\SectionWizard', + 'serpPreview' => 'Contao\SerpPreview' ); // Front end form fields diff --git a/core-bundle/src/Resources/contao/dca/tl_page.php b/core-bundle/src/Resources/contao/dca/tl_page.php index f43a6645df1..ea8e2d5591a 100644 --- a/core-bundle/src/Resources/contao/dca/tl_page.php +++ b/core-bundle/src/Resources/contao/dca/tl_page.php @@ -153,7 +153,7 @@ ( '__selector__' => array('type', 'fallback', 'autoforward', 'protected', 'createSitemap', 'includeLayout', 'includeCache', 'includeChmod', 'enforceTwoFactor'), 'default' => '{title_legend},title,alias,type', - 'regular' => '{title_legend},title,alias,type;{meta_legend},pageTitle,robots,description,serp_preview;{protected_legend:hide},protected;{layout_legend:hide},includeLayout;{cache_legend:hide},includeCache;{chmod_legend:hide},includeChmod;{expert_legend:hide},cssClass,sitemap,hide,noSearch,guests,requireItem;{tabnav_legend:hide},tabindex,accesskey;{publish_legend},published,start,stop', + 'regular' => '{title_legend},title,alias,type;{meta_legend},pageTitle,robots,description,serpPreview;{protected_legend:hide},protected;{layout_legend:hide},includeLayout;{cache_legend:hide},includeCache;{chmod_legend:hide},includeChmod;{expert_legend:hide},cssClass,sitemap,hide,noSearch,guests,requireItem;{tabnav_legend:hide},tabindex,accesskey;{publish_legend},published,start,stop', 'forward' => '{title_legend},title,alias,type;{meta_legend},pageTitle;{redirect_legend},jumpTo,redirect;{protected_legend:hide},protected;{layout_legend:hide},includeLayout;{cache_legend:hide},includeCache;{chmod_legend:hide},includeChmod;{expert_legend:hide},cssClass,sitemap,hide,guests;{tabnav_legend:hide},tabindex,accesskey;{publish_legend},published,start,stop', 'redirect' => '{title_legend},title,alias,type;{meta_legend},pageTitle;{redirect_legend},redirect,url,target;{protected_legend:hide},protected;{layout_legend:hide},includeLayout;{cache_legend:hide},includeCache;{chmod_legend:hide},includeChmod;{expert_legend:hide},cssClass,sitemap,hide,guests;{tabnav_legend:hide},tabindex,accesskey;{publish_legend},published,start,stop', 'root' => '{title_legend},title,alias,type;{meta_legend},pageTitle;{dns_legend},dns,useSSL,language,fallback;{global_legend:hide},dateFormat,timeFormat,datimFormat,adminEmail,staticFiles,staticPlugins;{alias_legend:hide},validAliasCharacters,useFolderUrl;{sitemap_legend:hide},createSitemap;{protected_legend:hide},protected;{layout_legend},includeLayout;{twoFactor_legend:hide},enforceTwoFactor;{cache_legend:hide},includeCache;{chmod_legend:hide},includeChmod;{publish_legend},published,start,stop', @@ -264,11 +264,12 @@ 'eval' => array('style'=>'height:60px', 'decodeEntities'=>true, 'tl_class'=>'clr'), 'sql' => "text NULL" ), - 'serp_preview' => array + 'serpPreview' => array ( - 'label' => &$GLOBALS['TL_LANG']['MSC']['serp_preview'], + 'label' => &$GLOBALS['TL_LANG']['MSC']['serpPreview'], 'exclude' => true, - 'input_field_callback' => array('tl_page', 'showSerpPreview') + 'inputType' => 'serpPreview', + 'eval' => array('serpPreview'=>array('title'=>array('pageTitle', 'title'))) ), 'redirect' => array ( @@ -1287,35 +1288,6 @@ public function checkJumpTo($varValue, Contao\DataContainer $dc) return $varValue; } - /** - * Show the SERP preview - * - * @param Contao\DataContainer $dc - * - * @return string - */ - public function showSerpPreview(Contao\DataContainer $dc) - { - $page = Contao\PageModel::findByPk($dc->activeRecord->id); - $url = $page->getAbsoluteUrl(); - $suffix = substr($dc->inputName, strlen($dc->field)); - - list($baseUrl) = explode($page->alias ?: $page->id, $url); - - $template = new Contao\FrontendTemplate('be_serp'); - $template->id = $page->id; - $template->title = $page->pageTitle ?: $page->title; - $template->url = $url; - $template->description = $page->description; - $template->baseUrl = $baseUrl; - $template->titleField = 'ctrl_pageTitle' . $suffix; - $template->titleFallbackField = 'ctrl_title' . $suffix; - $template->aliasField = 'ctrl_alias' . $suffix; - $template->descriptionField = 'ctrl_description' . $suffix; - - return $template->parse(); - } - /** * Check the DNS settings * diff --git a/core-bundle/src/Resources/contao/languages/en/default.xlf b/core-bundle/src/Resources/contao/languages/en/default.xlf index 559e45732dd..eb3494b1eea 100644 --- a/core-bundle/src/Resources/contao/languages/en/default.xlf +++ b/core-bundle/src/Resources/contao/languages/en/default.xlf @@ -1847,10 +1847,10 @@$title
+$url
+$description
+ + +EOT; + } + + private function getTitle(Model $model) + { + if (!isset($this->serpPreview['title'])) + { + return $model->title; + } + + if (\is_array($this->serpPreview['title'])) + { + return $model->{$this->serpPreview['title'][0]} ?: $model->{$this->serpPreview['title'][1]}; + } + + return $model->{$this->serpPreview['title']}; + } + + private function getDescription(Model $model) + { + if (!isset($this->serpPreview['description'])) + { + return $model->description; + } + + if (\is_array($this->serpPreview['description'])) + { + return $model->{$this->serpPreview['description'][0]} ?: $model->{$this->serpPreview['description'][1]}; + } + + return $model->{$this->serpPreview['description']}; + } + + private function getTitleField() + { + if (!isset($this->serpPreview['title'])) + { + return 'ctrl_title'; + } + + if (\is_array($this->serpPreview['title'])) + { + return 'ctrl_' . $this->serpPreview['title'][0]; + } + + return 'ctrl_' . $this->serpPreview['title']; + } + + private function getTitleFallbackField() + { + if (!isset($this->serpPreview['title']) || !\is_array($this->serpPreview['title'])) + { + return ''; + } + + return 'ctrl_' . $this->serpPreview['title'][1]; + } + + private function getAliasField() + { + if (!isset($this->serpPreview['alias'])) + { + return 'ctrl_alias'; + } + + return 'ctrl_' . $this->serpPreview['alias']; + } + + private function getDescriptionField() + { + if (!isset($this->serpPreview['description'])) + { + return 'ctrl_description'; + } + + if (\is_array($this->serpPreview['description'])) + { + return 'ctrl_' . $this->serpPreview['description'][0]; + } + + return 'ctrl_' . $this->serpPreview['description']; + } + + private function getDescriptionFallbackField() + { + if (!isset($this->serpPreview['description']) || !\is_array($this->serpPreview['description'])) + { + return ''; + } + + return 'ctrl_' . $this->serpPreview['description'][1]; + } +} diff --git a/news-bundle/src/EventListener/InsertTagsListener.php b/news-bundle/src/EventListener/InsertTagsListener.php index dc81138252b..e83c1b42885 100644 --- a/news-bundle/src/EventListener/InsertTagsListener.php +++ b/news-bundle/src/EventListener/InsertTagsListener.php @@ -13,7 +13,6 @@ namespace Contao\NewsBundle\EventListener; use Contao\CoreBundle\Framework\ContaoFramework; -use Contao\News; use Contao\NewsFeedModel; use Contao\NewsModel; use Contao\StringUtil; @@ -82,14 +81,11 @@ private function replaceNewsInsertTags(string $insertTag, string $idOrAlias, arr return ''; } - /** @var News $news */ - $news = $this->framework->getAdapter(News::class); - switch ($insertTag) { case 'news': return sprintf( '%s', - $news->generateNewsUrl($model, false, \in_array('absolute', $flags, true)), + \in_array('absolute', $flags, true) ? $model->getAbsoluteUrl() : $model->getFrontendUrl(), StringUtil::specialchars($model->headline), $model->headline ); @@ -97,12 +93,12 @@ private function replaceNewsInsertTags(string $insertTag, string $idOrAlias, arr case 'news_open': return sprintf( '', - $news->generateNewsUrl($model, false, \in_array('absolute', $flags, true)), + \in_array('absolute', $flags, true) ? $model->getAbsoluteUrl() : $model->getFrontendUrl(), StringUtil::specialchars($model->headline) ); case 'news_url': - return $news->generateNewsUrl($model, false, \in_array('absolute', $flags, true)); + return \in_array('absolute', $flags, true) ? $model->getAbsoluteUrl() : $model->getFrontendUrl(); case 'news_title': return StringUtil::specialchars($model->headline); diff --git a/news-bundle/src/EventListener/PreviewUrlConvertListener.php b/news-bundle/src/EventListener/PreviewUrlConvertListener.php index 69418a89d16..558435ee410 100644 --- a/news-bundle/src/EventListener/PreviewUrlConvertListener.php +++ b/news-bundle/src/EventListener/PreviewUrlConvertListener.php @@ -14,7 +14,6 @@ use Contao\CoreBundle\Event\PreviewUrlConvertEvent; use Contao\CoreBundle\Framework\ContaoFramework; -use Contao\News; use Contao\NewsModel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -52,10 +51,7 @@ public function onPreviewUrlConvert(PreviewUrlConvertEvent $event): void return; } - /** @var News $newsAdapter */ - $newsAdapter = $this->framework->getAdapter(News::class); - - $event->setUrl($request->getSchemeAndHttpHost().'/'.$newsAdapter->generateNewsUrl($news)); + $event->setUrl($request->getSchemeAndHttpHost().'/'.$news->getFrontendUrl()); } private function getNewsModel(Request $request): ?NewsModel diff --git a/news-bundle/src/Resources/contao/classes/News.php b/news-bundle/src/Resources/contao/classes/News.php index b76a57b93d2..1fc0c306621 100644 --- a/news-bundle/src/Resources/contao/classes/News.php +++ b/news-bundle/src/Resources/contao/classes/News.php @@ -351,9 +351,14 @@ public function getSearchablePages($arrPages, $intRoot=0, $blnIsSitemap=false) * @param boolean $blnAbsolute * * @return string + * + * @deprecated Deprecated since Contao 4.9, to be removed in Contao 5.0; + * use NewsModel::getFrontendUrl() instead */ public static function generateNewsUrl($objItem, $blnAddArchive=false, $blnAbsolute=false) { + @trigger_error('Using News::generateNewsUrl() has been deprecated and will no longer work in Contao 5.0. Use NewsModel::getFrontendUrl() instead.', E_USER_DEPRECATED); + $strCacheKey = 'id_' . $objItem->id . ($blnAbsolute ? '_absolute' : ''); // Load the URL from cache diff --git a/news-bundle/src/Resources/contao/dca/tl_news.php b/news-bundle/src/Resources/contao/dca/tl_news.php index 8b76ec7b2c8..b6f198c2584 100644 --- a/news-bundle/src/Resources/contao/dca/tl_news.php +++ b/news-bundle/src/Resources/contao/dca/tl_news.php @@ -124,7 +124,7 @@ 'palettes' => array ( '__selector__' => array('addImage', 'addEnclosure', 'source', 'overwriteMeta'), - 'default' => '{title_legend},headline,alias,author;{date_legend},date,time;{meta_legend},pageTitle,description,serp_preview;{teaser_legend},subheadline,teaser;{image_legend},addImage;{enclosure_legend:hide},addEnclosure;{source_legend:hide},source;{expert_legend:hide},cssClass,noComments,featured;{publish_legend},published,start,stop' + 'default' => '{title_legend},headline,alias,author;{date_legend},date,time;{meta_legend},pageTitle,description,serpPreview;{teaser_legend},subheadline,teaser;{image_legend},addImage;{enclosure_legend:hide},addEnclosure;{source_legend:hide},source;{expert_legend:hide},cssClass,noComments,featured;{publish_legend},published,start,stop' ), // Subpalettes @@ -234,11 +234,12 @@ 'eval' => array('style'=>'height:60px', 'decodeEntities'=>true, 'tl_class'=>'clr'), 'sql' => "text NULL" ), - 'serp_preview' => array + 'serpPreview' => array ( - 'label' => &$GLOBALS['TL_LANG']['MSC']['serp_preview'], + 'label' => &$GLOBALS['TL_LANG']['MSC']['serpPreview'], 'exclude' => true, - 'input_field_callback' => array('tl_news', 'showSerpPreview') + 'inputType' => 'serpPreview', + 'eval' => array('serpPreview'=>array('title'=>array('pageTitle', 'headline'), 'description'=>array('description', 'teaser'))), ), 'subheadline' => array ( @@ -736,36 +737,6 @@ public function getArticleAlias(Contao\DataContainer $dc) return $arrAlias; } - /** - * Show the SERP preview - * - * @param Contao\DataContainer $dc - * - * @return string - */ - public function showSerpPreview(Contao\DataContainer $dc) - { - $news = Contao\NewsModel::findByPk($dc->activeRecord->id); - $url = Contao\News::generateNewsUrl($news, false, true); - $suffix = substr($dc->inputName, strlen($dc->field)); - - list($baseUrl) = explode($news->alias ?: $news->id, $url); - - $template = new Contao\FrontendTemplate('be_serp'); - $template->id = $news->id; - $template->title = $news->pageTitle ?: $news->headline; - $template->url = $url; - $template->description = $news->description ?: strip_tags($news->teaser); - $template->baseUrl = $baseUrl; - $template->titleField = 'ctrl_pageTitle' . $suffix; - $template->titleFallbackField = 'ctrl_headline' . $suffix; - $template->aliasField = 'ctrl_alias' . $suffix; - $template->descriptionField = 'ctrl_description' . $suffix; - $template->descriptionFallbackField = 'ctrl_teaser' . $suffix; - - return $template->parse(); - } - /** * Add the source options depending on the allowed fields (see #5498) * diff --git a/news-bundle/src/Resources/contao/models/NewsModel.php b/news-bundle/src/Resources/contao/models/NewsModel.php index b0d141e2ecf..9b6260e3cda 100644 --- a/news-bundle/src/Resources/contao/models/NewsModel.php +++ b/news-bundle/src/Resources/contao/models/NewsModel.php @@ -11,6 +11,7 @@ namespace Contao; use Contao\Model\Collection; +use Contao\Model\Routable; /** * Reads and writes news @@ -162,7 +163,7 @@ * * @author Leo FeyerFoo does not equal bar.
'; - $news = $this->mockAdapter(['generateNewsUrl']); - $news - ->method('generateNewsUrl') - ->willReturnCallback( - static function (NewsModel $model, bool $addArchive, bool $absolute): string { - if ($absolute) { - return 'http://domain.tld/news/foo-is-not-bar.html'; - } - - return 'news/foo-is-not-bar.html'; - } - ) + $newsModel + ->method('getFrontendUrl') + ->willReturn('news/foo-is-not-bar.html') + ; + + $newsModel + ->method('getAbsoluteUrl') + ->willReturn('http://domain.tld/news/foo-is-not-bar.html') ; $adapters = [ NewsModel::class => $this->mockConfiguredAdapter(['findByIdOrAlias' => $newsModel]), - News::class => $news, ]; $listener = new InsertTagsListener($this->mockContaoFramework($adapters)); diff --git a/news-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php b/news-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php index 1c874983783..d63c8256dd5 100644 --- a/news-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php +++ b/news-bundle/tests/EventListener/PreviewUrlConverterListenerTest.php @@ -14,7 +14,6 @@ use Contao\CoreBundle\Event\PreviewUrlConvertEvent; use Contao\CoreBundle\Framework\ContaoFramework; -use Contao\News; use Contao\NewsBundle\EventListener\PreviewUrlConvertListener; use Contao\NewsModel; use Contao\TestCase\ContaoTestCase; @@ -34,10 +33,14 @@ public function testConvertsThePreviewUrl(): void $requestStack->push($request); $newsModel = $this->createMock(NewsModel::class); + $newsModel + ->expects($this->once()) + ->method('getFrontendUrl') + ->willReturn('news/james-wilson-returns.html') + ; $adapters = [ NewsModel::class => $this->mockConfiguredAdapter(['findByPk' => $newsModel]), - News::class => $this->mockConfiguredAdapter(['generateNewsUrl' => 'news/james-wilson-returns.html']), ]; $framework = $this->mockContaoFramework($adapters);