Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Classes/Backend/ToolbarItems/NewsItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
use Xima\XimaTypo3InternalNews\Domain\Model\News;
use Xima\XimaTypo3InternalNews\Domain\Repository\NewsRepository;
use Xima\XimaTypo3InternalNews\Service\NewsService;
use Xima\XimaTypo3InternalNews\Utilities\ViewFactoryHelper;

class NewsItem implements ToolbarItemInterface
{
protected array $configuration;
public function __construct(
private readonly NewsRepository $newsRepository
private readonly NewsRepository $newsRepository,
private readonly NewsService $newsService
) {}

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

return ViewFactoryHelper::renderView(
'Backend/ToolbarItems/NewsItem.html',
Expand Down
5 changes: 3 additions & 2 deletions Classes/Controller/DateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,16 @@ final class DateController extends ActionController
protected array $configuration;
public function __construct(
private readonly NewsRepository $newsRepository,
private readonly ExtensionConfiguration $extensionConfiguration
private readonly ExtensionConfiguration $extensionConfiguration,
private readonly DateService $dateService
) {
$this->configuration = $this->extensionConfiguration->get(Configuration::EXT_KEY);
}

public function notifiesAction(): ResponseInterface
{
$newsList = $this->newsRepository->findAllByCurrentUser();
$notifies = DateService::getNotifyDatesByNewsList($newsList);
$notifies = $this->dateService->getNotifyDatesByNewsList($newsList);

return new JsonResponse([
'notifies' => $notifies,
Expand Down
25 changes: 0 additions & 25 deletions Classes/Domain/Model/News.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use Xima\XimaTypo3InternalNews\Service\DateService;
use Xima\XimaTypo3InternalNews\Utilities\BackendUserHelper;

class News extends AbstractEntity
{
Expand Down Expand Up @@ -92,16 +90,6 @@ public function setDates(ObjectStorage $dates): void
$this->dates = $dates;
}

public function getNextDate(): ?array
{
return DateService::getNextDate($this);
}

public function getNextDates(): array
{
return DateService::getNextDates($this);
}

public function isTop(): bool
{
return $this->top;
Expand All @@ -112,19 +100,6 @@ public function setTop(bool $top): void
$this->top = $top;
}

public function isTopAndNew(): bool
{
if (!$this->top) {
return false;
}
return BackendUserHelper::checkAndSetModuleDate('internal_news/top', $this->getUid());
}

public function isNew(): bool
{
return BackendUserHelper::checkAndSetModuleDate('internal_news/read', $this->getUid());
}

public function getTstamp(): ?int
{
return $this->tstamp;
Expand Down
34 changes: 18 additions & 16 deletions Classes/Service/DateService.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@
use Recurr\Rule;
use Recurr\Transformer\ArrayTransformer;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Xima\XimaTypo3InternalNews\Configuration;
use Xima\XimaTypo3InternalNews\Domain\Model\Date;
use Xima\XimaTypo3InternalNews\Domain\Model\News;

class DateService
{
public static function getNextDate(News $news): ?array
public function __construct(
private readonly ExtensionConfiguration $extensionConfiguration
) {}
public function getNextDate(News $news): ?array
{
$nextDate = null;
foreach ($news->getDates() as $date) {
$nextDateArray = self::getDates($news, $date, true, true);
$nextDateArray = $this->getDates($news, $date, true, true);
if (isset($nextDateArray[0])) {
$nextDate = $nextDateArray[0];
}
Expand All @@ -46,25 +48,25 @@ public static function getNextDate(News $news): ?array
return $nextDate;
}

public static function getNextDates(News $news): array
public function getNextDates(News $news): array
{
$nextDates = [];
foreach ($news->getDates() as $date) {
// merge arrays
$nextDates = array_merge($nextDates, self::getDates($news, $date, true));
$nextDates = array_merge($nextDates, $this->getDates($news, $date, true));
}
usort($nextDates, function (array $a, array $b) {
return $a['date'] <=> $b['date'];
});
return $nextDates;
}

public static function getNotifyDatesByNewsList(array $newsList): array
public function getNotifyDatesByNewsList(array $newsList): array
{
$notifyDates = [];
foreach ($newsList as $news) {
foreach ($news->getDates() as $date) {
$notifyDates = array_merge($notifyDates, self::getDates($news, $date, true, true));
$notifyDates = array_merge($notifyDates, $this->getDates($news, $date, true, true));
}
}
usort($notifyDates, function (array $a, array $b) {
Expand All @@ -73,13 +75,13 @@ public static function getNotifyDatesByNewsList(array $newsList): array
return $notifyDates;
}

public static function getDates(News $news, Date $date, bool $respectNotify = false, bool $forceNotify = false, bool $onlyNextDate = false): array
public function getDates(News $news, Date $date, bool $respectNotify = false, bool $forceNotify = false, bool $onlyNextDate = false): array
{
$dates = [];
switch ($date->getType()) {
case 'single_date':
if ($date->getSingleDate() > new \DateTime() && (!$forceNotify || self::checkNotifyIsReached($date->getSingleDate()))) {
$dates[] = self::createDateEntry($news, $date, $date->getSingleDate(), $respectNotify);
if ($date->getSingleDate() > new \DateTime() && (!$forceNotify || $this->checkNotifyIsReached($date->getSingleDate()))) {
$dates[] = $this->createDateEntry($news, $date, $date->getSingleDate(), $respectNotify);
if ($onlyNextDate) {
break;
}
Expand All @@ -89,8 +91,8 @@ public static function getDates(News $news, Date $date, bool $respectNotify = fa
$transformer = new ArrayTransformer();
$rule = new Rule($date->getRecurrence(), $date->getSingleDate(), null, (new \DateTimeZone('Europe/Berlin'))->getName());
foreach ($transformer->transform($rule) as $recurrence) {
if ($recurrence->getStart() > new \DateTime() && (!$forceNotify || self::checkNotifyIsReached($recurrence->getStart()))) {
$dates[] = self::createDateEntry($news, $date, $recurrence->getStart(), $respectNotify);
if ($recurrence->getStart() > new \DateTime() && (!$forceNotify || $this->checkNotifyIsReached($recurrence->getStart()))) {
$dates[] = $this->createDateEntry($news, $date, $recurrence->getStart(), $respectNotify);
if ($onlyNextDate) {
break 2;
}
Expand All @@ -101,7 +103,7 @@ public static function getDates(News $news, Date $date, bool $respectNotify = fa
return $dates;
}

private static function createDateEntry(News $news, Date $date, \DateTimeInterface $startDate, bool $respectNotify): array
private function createDateEntry(News $news, Date $date, \DateTimeInterface $startDate, bool $respectNotify): array
{
$newDate = [
'id' => $date->getUid(),
Expand All @@ -110,17 +112,17 @@ private static function createDateEntry(News $news, Date $date, \DateTimeInterfa
'type' => $date->getType(),
'newsId' => $news->getUid(),
];
if ($respectNotify && $date->isNotify() && self::checkNotifyIsReached($startDate)) {
if ($respectNotify && $date->isNotify() && $this->checkNotifyIsReached($startDate)) {
$newDate['notify'] = true;
$newDate['notifyType'] = ($date->getNotifyType() !== '') ? $date->getNotifyType() : 'info';
$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') . ')';
}
return $newDate;
}

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

$thresholdDate = clone $date;
Expand Down
58 changes: 58 additions & 0 deletions Classes/Service/NewsService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
*
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Xima\XimaTypo3InternalNews\Service;

use Xima\XimaTypo3InternalNews\Domain\Model\News;
use Xima\XimaTypo3InternalNews\Utilities\BackendUserHelper;

class NewsService
{
public function __construct(
private readonly DateService $dateService,
private readonly BackendUserHelper $backendUserHelper
) {}

public function getNextDate(News $news): ?array
{
return $this->dateService->getNextDate($news);
}

public function getNextDates(News $news): array
{
return $this->dateService->getNextDates($news);
}

public function isTopAndNew(News $news): bool
{
if (!$news->isTop()) {
return false;
}
return $this->backendUserHelper->checkAndSetModuleDate('internal_news/top', $news->getUid());
}

public function isNew(News $news): bool
{
return $this->backendUserHelper->checkAndSetModuleDate('internal_news/read', $news->getUid());
}
}
12 changes: 9 additions & 3 deletions Classes/Utilities/BackendUserHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,22 @@

class BackendUserHelper
{
public static function checkAndSetModuleDate(string $moduleName, mixed $value): bool
public function checkAndSetModuleDate(string $moduleName, mixed $value): bool
{
// Validate backend user exists and is authenticated
if (!isset($GLOBALS['BE_USER']) || !is_object($GLOBALS['BE_USER'])) {
return false;
}

$backendUser = $GLOBALS['BE_USER'];
$return = true;

$array = $GLOBALS['BE_USER']->getModuleData($moduleName) ?? [];
$array = $backendUser->getModuleData($moduleName) ?? [];
if (is_array($array) && in_array($value, $array, true)) {
$return = false;
}
$array[] = $value;
$GLOBALS['BE_USER']->pushModuleData($moduleName, $array);
$backendUser->pushModuleData($moduleName, $array);
return $return;
}
}
3 changes: 2 additions & 1 deletion Classes/Utilities/UserFunc.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public function dateLabel(array &$parameters): void
return;
}

$dates = DateService::getDates(GeneralUtility::makeInstance(News::class), $record);
$dateService = GeneralUtility::makeInstance(DateService::class);
$dates = $dateService->getDates(GeneralUtility::makeInstance(News::class), $record);
if ($dates === []) {
return;
}
Expand Down
48 changes: 48 additions & 0 deletions Classes/ViewHelpers/IsNewViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
*
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Xima\XimaTypo3InternalNews\ViewHelpers;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use Xima\XimaTypo3InternalNews\Domain\Model\News;
use Xima\XimaTypo3InternalNews\Service\NewsService;

class IsNewViewHelper extends AbstractViewHelper
{
public function initializeArguments(): void
{
$this->registerArgument('news', News::class, 'The news object', true);
}

public function render(): bool
{
$news = $this->arguments['news'];
if (!$news instanceof News) {
return false;
}

$newsService = GeneralUtility::makeInstance(NewsService::class);
return $newsService->isNew($news);
}
}
48 changes: 48 additions & 0 deletions Classes/ViewHelpers/IsTopAndNewViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "xima_typo3_internal_news".
*
* Copyright (C) 2025 Konrad Michalik <hej@konradmichalik.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Xima\XimaTypo3InternalNews\ViewHelpers;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use Xima\XimaTypo3InternalNews\Domain\Model\News;
use Xima\XimaTypo3InternalNews\Service\NewsService;

class IsTopAndNewViewHelper extends AbstractViewHelper
{
public function initializeArguments(): void
{
$this->registerArgument('news', News::class, 'The news object', true);
}

public function render(): bool
{
$news = $this->arguments['news'];
if (!$news instanceof News) {
return false;
}

$newsService = GeneralUtility::makeInstance(NewsService::class);
return $newsService->isTopAndNew($news);
}
}
Loading