Skip to content

Commit bd8a81f

Browse files
author
Konrad Michalik
authored
Merge pull request #13 from xima-media/architecture-improvements
feat: architecture improvements
2 parents eb2ae2c + 75590a4 commit bd8a81f

20 files changed

Lines changed: 367 additions & 81 deletions

File tree

Classes/Backend/ToolbarItems/NewsItem.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
2727
use Xima\XimaTypo3InternalNews\Domain\Model\News;
2828
use Xima\XimaTypo3InternalNews\Domain\Repository\NewsRepository;
29+
use Xima\XimaTypo3InternalNews\Service\NewsService;
2930
use Xima\XimaTypo3InternalNews\Utilities\ViewFactoryHelper;
3031

3132
class NewsItem implements ToolbarItemInterface
3233
{
3334
protected array $configuration;
3435
public function __construct(
35-
private readonly NewsRepository $newsRepository
36+
private readonly NewsRepository $newsRepository,
37+
private readonly NewsService $newsService
3638
) {}
3739

3840
/**
@@ -53,7 +55,7 @@ public function checkAccess(): bool
5355
public function getItem(): string
5456
{
5557
$items = $this->newsRepository->findAllByCurrentUser();
56-
$newItemsCount = count(array_filter($items, static fn(News $item) => $item->isNew()));
58+
$newItemsCount = count(array_filter($items, fn(News $item) => $this->newsService->isNew($item)));
5759

5860
return ViewFactoryHelper::renderView(
5961
'Backend/ToolbarItems/NewsItem.html',

Classes/Controller/DateController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ final class DateController extends ActionController
3939
protected array $configuration;
4040
public function __construct(
4141
private readonly NewsRepository $newsRepository,
42-
private readonly ExtensionConfiguration $extensionConfiguration
42+
private readonly ExtensionConfiguration $extensionConfiguration,
43+
private readonly DateService $dateService
4344
) {
4445
$this->configuration = $this->extensionConfiguration->get(Configuration::EXT_KEY);
4546
}
4647

4748
public function notifiesAction(): ResponseInterface
4849
{
4950
$newsList = $this->newsRepository->findAllByCurrentUser();
50-
$notifies = DateService::getNotifyDatesByNewsList($newsList);
51+
$notifies = $this->dateService->getNotifyDatesByNewsList($newsList);
5152

5253
return new JsonResponse([
5354
'notifies' => $notifies,

Classes/Domain/Model/News.php

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
2828
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
2929
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
30-
use Xima\XimaTypo3InternalNews\Service\DateService;
31-
use Xima\XimaTypo3InternalNews\Utilities\BackendUserHelper;
3230

3331
class News extends AbstractEntity
3432
{
@@ -92,16 +90,6 @@ public function setDates(ObjectStorage $dates): void
9290
$this->dates = $dates;
9391
}
9492

95-
public function getNextDate(): ?array
96-
{
97-
return DateService::getNextDate($this);
98-
}
99-
100-
public function getNextDates(): array
101-
{
102-
return DateService::getNextDates($this);
103-
}
104-
10593
public function isTop(): bool
10694
{
10795
return $this->top;
@@ -112,19 +100,6 @@ public function setTop(bool $top): void
112100
$this->top = $top;
113101
}
114102

115-
public function isTopAndNew(): bool
116-
{
117-
if (!$this->top) {
118-
return false;
119-
}
120-
return BackendUserHelper::checkAndSetModuleDate('internal_news/top', $this->getUid());
121-
}
122-
123-
public function isNew(): bool
124-
{
125-
return BackendUserHelper::checkAndSetModuleDate('internal_news/read', $this->getUid());
126-
}
127-
128103
public function getTstamp(): ?int
129104
{
130105
return $this->tstamp;

Classes/Service/DateService.php

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,20 @@
2626
use Recurr\Rule;
2727
use Recurr\Transformer\ArrayTransformer;
2828
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
29-
use TYPO3\CMS\Core\Utility\GeneralUtility;
3029
use Xima\XimaTypo3InternalNews\Configuration;
3130
use Xima\XimaTypo3InternalNews\Domain\Model\Date;
3231
use Xima\XimaTypo3InternalNews\Domain\Model\News;
3332

3433
class DateService
3534
{
36-
public static function getNextDate(News $news): ?array
35+
public function __construct(
36+
private readonly ExtensionConfiguration $extensionConfiguration
37+
) {}
38+
public function getNextDate(News $news): ?array
3739
{
3840
$nextDate = null;
3941
foreach ($news->getDates() as $date) {
40-
$nextDateArray = self::getDates($news, $date, true, true);
42+
$nextDateArray = $this->getDates($news, $date, true, true);
4143
if (isset($nextDateArray[0])) {
4244
$nextDate = $nextDateArray[0];
4345
}
@@ -46,25 +48,25 @@ public static function getNextDate(News $news): ?array
4648
return $nextDate;
4749
}
4850

49-
public static function getNextDates(News $news): array
51+
public function getNextDates(News $news): array
5052
{
5153
$nextDates = [];
5254
foreach ($news->getDates() as $date) {
5355
// merge arrays
54-
$nextDates = array_merge($nextDates, self::getDates($news, $date, true));
56+
$nextDates = array_merge($nextDates, $this->getDates($news, $date, true));
5557
}
5658
usort($nextDates, function (array $a, array $b) {
5759
return $a['date'] <=> $b['date'];
5860
});
5961
return $nextDates;
6062
}
6163

62-
public static function getNotifyDatesByNewsList(array $newsList): array
64+
public function getNotifyDatesByNewsList(array $newsList): array
6365
{
6466
$notifyDates = [];
6567
foreach ($newsList as $news) {
6668
foreach ($news->getDates() as $date) {
67-
$notifyDates = array_merge($notifyDates, self::getDates($news, $date, true, true));
69+
$notifyDates = array_merge($notifyDates, $this->getDates($news, $date, true, true));
6870
}
6971
}
7072
usort($notifyDates, function (array $a, array $b) {
@@ -73,13 +75,13 @@ public static function getNotifyDatesByNewsList(array $newsList): array
7375
return $notifyDates;
7476
}
7577

76-
public static function getDates(News $news, Date $date, bool $respectNotify = false, bool $forceNotify = false, bool $onlyNextDate = false): array
78+
public function getDates(News $news, Date $date, bool $respectNotify = false, bool $forceNotify = false, bool $onlyNextDate = false): array
7779
{
7880
$dates = [];
7981
switch ($date->getType()) {
8082
case 'single_date':
81-
if ($date->getSingleDate() > new \DateTime() && (!$forceNotify || self::checkNotifyIsReached($date->getSingleDate()))) {
82-
$dates[] = self::createDateEntry($news, $date, $date->getSingleDate(), $respectNotify);
83+
if ($date->getSingleDate() > new \DateTime() && (!$forceNotify || $this->checkNotifyIsReached($date->getSingleDate()))) {
84+
$dates[] = $this->createDateEntry($news, $date, $date->getSingleDate(), $respectNotify);
8385
if ($onlyNextDate) {
8486
break;
8587
}
@@ -89,8 +91,8 @@ public static function getDates(News $news, Date $date, bool $respectNotify = fa
8991
$transformer = new ArrayTransformer();
9092
$rule = new Rule($date->getRecurrence(), $date->getSingleDate(), null, (new \DateTimeZone('Europe/Berlin'))->getName());
9193
foreach ($transformer->transform($rule) as $recurrence) {
92-
if ($recurrence->getStart() > new \DateTime() && (!$forceNotify || self::checkNotifyIsReached($recurrence->getStart()))) {
93-
$dates[] = self::createDateEntry($news, $date, $recurrence->getStart(), $respectNotify);
94+
if ($recurrence->getStart() > new \DateTime() && (!$forceNotify || $this->checkNotifyIsReached($recurrence->getStart()))) {
95+
$dates[] = $this->createDateEntry($news, $date, $recurrence->getStart(), $respectNotify);
9496
if ($onlyNextDate) {
9597
break 2;
9698
}
@@ -101,7 +103,7 @@ public static function getDates(News $news, Date $date, bool $respectNotify = fa
101103
return $dates;
102104
}
103105

104-
private static function createDateEntry(News $news, Date $date, \DateTimeInterface $startDate, bool $respectNotify): array
106+
private function createDateEntry(News $news, Date $date, \DateTimeInterface $startDate, bool $respectNotify): array
105107
{
106108
$newDate = [
107109
'id' => $date->getUid(),
@@ -110,17 +112,17 @@ private static function createDateEntry(News $news, Date $date, \DateTimeInterfa
110112
'type' => $date->getType(),
111113
'newsId' => $news->getUid(),
112114
];
113-
if ($respectNotify && $date->isNotify() && self::checkNotifyIsReached($startDate)) {
115+
if ($respectNotify && $date->isNotify() && $this->checkNotifyIsReached($startDate)) {
114116
$newDate['notify'] = true;
115117
$newDate['notifyType'] = ($date->getNotifyType() !== '') ? $date->getNotifyType() : 'info';
116118
$newDate['notifyMessage'] = (($date->getNotifyMessage() !== '') ? $date->getNotifyMessage() : $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_internal_news/Resources/Private/Language/locallang.xlf:internal_news_notify_note')) . ' (' . $startDate->format('d.m.Y H:i') . ')';
117119
}
118120
return $newDate;
119121
}
120122

121-
private static function checkNotifyIsReached(\DateTimeInterface $date): bool
123+
private function checkNotifyIsReached(\DateTimeInterface $date): bool
122124
{
123-
$extensionConfiguration = (GeneralUtility::makeInstance(ExtensionConfiguration::class))->get(Configuration::EXT_KEY);
125+
$extensionConfiguration = $this->extensionConfiguration->get(Configuration::EXT_KEY);
124126
$threshold = $extensionConfiguration['notifyTimeThreshold'];
125127

126128
$thresholdDate = clone $date;

Classes/Service/NewsService.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
7+
*
8+
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation, either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
24+
namespace Xima\XimaTypo3InternalNews\Service;
25+
26+
use Xima\XimaTypo3InternalNews\Domain\Model\News;
27+
use Xima\XimaTypo3InternalNews\Utilities\BackendUserHelper;
28+
29+
class NewsService
30+
{
31+
public function __construct(
32+
private readonly DateService $dateService,
33+
private readonly BackendUserHelper $backendUserHelper
34+
) {}
35+
36+
public function getNextDate(News $news): ?array
37+
{
38+
return $this->dateService->getNextDate($news);
39+
}
40+
41+
public function getNextDates(News $news): array
42+
{
43+
return $this->dateService->getNextDates($news);
44+
}
45+
46+
public function isTopAndNew(News $news): bool
47+
{
48+
if (!$news->isTop()) {
49+
return false;
50+
}
51+
return $this->backendUserHelper->checkAndSetModuleDate('internal_news/top', $news->getUid());
52+
}
53+
54+
public function isNew(News $news): bool
55+
{
56+
return $this->backendUserHelper->checkAndSetModuleDate('internal_news/read', $news->getUid());
57+
}
58+
}

Classes/Utilities/BackendUserHelper.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,22 @@
2525

2626
class BackendUserHelper
2727
{
28-
public static function checkAndSetModuleDate(string $moduleName, mixed $value): bool
28+
public function checkAndSetModuleDate(string $moduleName, mixed $value): bool
2929
{
30+
// Validate backend user exists and is authenticated
31+
if (!isset($GLOBALS['BE_USER']) || !is_object($GLOBALS['BE_USER'])) {
32+
return false;
33+
}
34+
35+
$backendUser = $GLOBALS['BE_USER'];
3036
$return = true;
3137

32-
$array = $GLOBALS['BE_USER']->getModuleData($moduleName) ?? [];
38+
$array = $backendUser->getModuleData($moduleName) ?? [];
3339
if (is_array($array) && in_array($value, $array, true)) {
3440
$return = false;
3541
}
3642
$array[] = $value;
37-
$GLOBALS['BE_USER']->pushModuleData($moduleName, $array);
43+
$backendUser->pushModuleData($moduleName, $array);
3844
return $return;
3945
}
4046
}

Classes/Utilities/UserFunc.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public function dateLabel(array &$parameters): void
3838
return;
3939
}
4040

41-
$dates = DateService::getDates(GeneralUtility::makeInstance(News::class), $record);
41+
$dateService = GeneralUtility::makeInstance(DateService::class);
42+
$dates = $dateService->getDates(GeneralUtility::makeInstance(News::class), $record);
4243
if ($dates === []) {
4344
return;
4445
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
7+
*
8+
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation, either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
24+
namespace Xima\XimaTypo3InternalNews\ViewHelpers;
25+
26+
use TYPO3\CMS\Core\Utility\GeneralUtility;
27+
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
28+
use Xima\XimaTypo3InternalNews\Domain\Model\News;
29+
use Xima\XimaTypo3InternalNews\Service\NewsService;
30+
31+
class IsNewViewHelper extends AbstractViewHelper
32+
{
33+
public function initializeArguments(): void
34+
{
35+
$this->registerArgument('news', News::class, 'The news object', true);
36+
}
37+
38+
public function render(): bool
39+
{
40+
$news = $this->arguments['news'];
41+
if (!$news instanceof News) {
42+
return false;
43+
}
44+
45+
$newsService = GeneralUtility::makeInstance(NewsService::class);
46+
return $newsService->isNew($news);
47+
}
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
7+
*
8+
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation, either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
24+
namespace Xima\XimaTypo3InternalNews\ViewHelpers;
25+
26+
use TYPO3\CMS\Core\Utility\GeneralUtility;
27+
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
28+
use Xima\XimaTypo3InternalNews\Domain\Model\News;
29+
use Xima\XimaTypo3InternalNews\Service\NewsService;
30+
31+
class IsTopAndNewViewHelper extends AbstractViewHelper
32+
{
33+
public function initializeArguments(): void
34+
{
35+
$this->registerArgument('news', News::class, 'The news object', true);
36+
}
37+
38+
public function render(): bool
39+
{
40+
$news = $this->arguments['news'];
41+
if (!$news instanceof News) {
42+
return false;
43+
}
44+
45+
$newsService = GeneralUtility::makeInstance(NewsService::class);
46+
return $newsService->isTopAndNew($news);
47+
}
48+
}

0 commit comments

Comments
 (0)