Skip to content

Commit e75f46b

Browse files
authored
Merge commit from fork
1 parent 3f05c60 commit e75f46b

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

news-bundle/config/services.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ services:
6767
- '%kernel.project_dir%'
6868
- '@contao.cache.entity_tags'
6969
- '%kernel.charset%'
70+
- '@security.helper'
7071

7172
contao_news.listener.preview_url_convert:
7273
class: Contao\NewsBundle\EventListener\PreviewUrlConvertListener

news-bundle/src/EventListener/NewsFeedListener.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
use Contao\CoreBundle\Image\ImageFactoryInterface;
2020
use Contao\CoreBundle\InsertTag\InsertTagParser;
2121
use Contao\CoreBundle\Routing\ContentUrlGenerator;
22+
use Contao\CoreBundle\Security\ContaoCorePermissions;
2223
use Contao\Environment;
2324
use Contao\File;
2425
use Contao\FilesModel;
26+
use Contao\NewsArchiveModel;
2527
use Contao\NewsBundle\Event\FetchArticlesForFeedEvent;
2628
use Contao\NewsBundle\Event\TransformArticleForFeedEvent;
2729
use Contao\NewsModel;
@@ -35,6 +37,7 @@
3537
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
3638
use Symfony\Component\Filesystem\Path;
3739
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
40+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
3841

3942
/**
4043
* @internal
@@ -49,14 +52,15 @@ public function __construct(
4952
private readonly string $projectDir,
5053
private readonly EntityCacheTags $cacheTags,
5154
private readonly string $charset,
55+
private readonly AuthorizationCheckerInterface $authorizationChecker,
5256
) {
5357
}
5458

5559
#[AsEventListener(FetchArticlesForFeedEvent::class)]
5660
public function onFetchArticlesForFeed(FetchArticlesForFeedEvent $event): void
5761
{
5862
$pageModel = $event->getPageModel();
59-
$archives = StringUtil::deserialize($pageModel->newsArchives, true);
63+
$archives = $this->sortOutProtected(StringUtil::deserialize($pageModel->newsArchives, true));
6064

6165
$featured = match ($pageModel->feedFeatured) {
6266
'featured' => true,
@@ -197,4 +201,25 @@ private function getEnclosures(NewsModel $article, TransformArticleForFeedEvent
197201

198202
return $enclosures;
199203
}
204+
205+
/**
206+
* @param list<int> $archiveIds
207+
*
208+
* @return list<int>
209+
*/
210+
private function sortOutProtected(array $archiveIds): array
211+
{
212+
$newsArchiveModel = $this->framework->getAdapter(NewsArchiveModel::class);
213+
$allowedIds = [];
214+
215+
foreach ($newsArchiveModel->findMultipleByIds($archiveIds) ?? [] as $archive) {
216+
if ($archive->protected && !$this->authorizationChecker->isGranted(ContaoCorePermissions::MEMBER_IN_GROUPS, $archive->groups)) {
217+
continue;
218+
}
219+
220+
$allowedIds[] = (int) $archive->id;
221+
}
222+
223+
return $allowedIds;
224+
}
200225
}

news-bundle/tests/EventListener/NewsFeedListenerTest.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Contao\FilesModel;
2424
use Contao\Image\ImageInterface;
2525
use Contao\Model\Collection;
26+
use Contao\NewsArchiveModel;
2627
use Contao\NewsBundle\Event\FetchArticlesForFeedEvent;
2728
use Contao\NewsBundle\Event\TransformArticleForFeedEvent;
2829
use Contao\NewsBundle\EventListener\NewsFeedListener;
@@ -38,6 +39,7 @@
3839
use Symfony\Component\Filesystem\Path;
3940
use Symfony\Component\HttpFoundation\Request;
4041
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
42+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
4143

4244
class NewsFeedListenerTest extends ContaoTestCase
4345
{
@@ -57,6 +59,8 @@ public function testFetchesArticlesFromArchives(string $feedFeatured, bool|null
5759
$imageFactory = $this->createMock(ImageFactoryInterface::class);
5860
$cacheTags = $this->createMock(EntityCacheTags::class);
5961
$newsModel = $this->createMock(NewsModel::class);
62+
$normalArchive = $this->mockClassWithProperties(NewsArchiveModel::class, ['id' => 1, 'protected' => 0]);
63+
$protectedArchive = $this->mockClassWithProperties(NewsArchiveModel::class, ['id' => 2, 'protected' => 1]);
6064

6165
$collection = $this->createMock(Collection::class);
6266
$collection
@@ -73,20 +77,35 @@ public function testFetchesArticlesFromArchives(string $feedFeatured, bool|null
7377
->willReturn($collection)
7478
;
7579

76-
$framework = $this->mockContaoFramework([NewsModel::class => $newsAdapter]);
80+
$newsArchiveAdapter = $this->mockAdapter(['findMultipleByIds']);
81+
$newsArchiveAdapter
82+
->expects($this->once())
83+
->method('findMultipleByIds')
84+
->with([1, 2])
85+
->willReturn(new Collection([$normalArchive, $protectedArchive], 'tl_news_archive'))
86+
;
87+
88+
$framework = $this->mockContaoFramework([NewsModel::class => $newsAdapter, NewsArchiveModel::class => $newsArchiveAdapter]);
7789
$feed = $this->createMock(Feed::class);
7890
$request = $this->createMock(Request::class);
7991
$urlGenerator = $this->createMock(ContentUrlGenerator::class);
8092

93+
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
94+
$authorizationChecker
95+
->expects($this->once())
96+
->method('isGranted')
97+
->willReturn(false)
98+
;
99+
81100
$pageModel = $this->mockClassWithProperties(PageModel::class, [
82-
'newsArchives' => serialize([1]),
101+
'newsArchives' => serialize([1, 2]),
83102
'feedFeatured' => $feedFeatured,
84103
'maxFeedItems' => 0,
85104
]);
86105

87106
$event = new FetchArticlesForFeedEvent($feed, $request, $pageModel);
88107

89-
$listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8');
108+
$listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8', $authorizationChecker);
90109
$listener->onFetchArticlesForFeed($event);
91110

92111
$this->assertSame([$newsModel], $event->getArticles());
@@ -211,6 +230,7 @@ public function testTransformsArticlesToFeedItems(string $feedSource, array $hea
211230

212231
$feed = $this->createMock(Feed::class);
213232
$cacheTags = $this->createMock(EntityCacheTags::class);
233+
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
214234

215235
$urlGenerator = $this->createMock(ContentUrlGenerator::class);
216236
$urlGenerator
@@ -229,7 +249,7 @@ public function testTransformsArticlesToFeedItems(string $feedSource, array $hea
229249
$baseUrl = 'example.org';
230250
$event = new TransformArticleForFeedEvent($article, $feed, $pageModel, $request, $baseUrl);
231251

232-
$listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8');
252+
$listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8', $authorizationChecker);
233253
$listener->onTransformArticleForFeed($event);
234254

235255
$item = $event->getItem();

0 commit comments

Comments
 (0)