EventCacheService   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 66
dl 0
loc 139
rs 10
c 2
b 0
f 0
wmc 18

4 Methods

Rating   Name   Duplication   Size   Complexity  
A addPageCacheTagsByEventDemandObject() 0 14 4
A flushEventCache() 0 14 4
B getCacheTagLifetimeForStoragePage() 0 67 7
A addCacheTagsByEventRecords() 0 15 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Service;
13
14
use DateTime;
15
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
16
use DERHANSEN\SfEventMgt\Domain\Model\Event;
17
use TYPO3\CMS\Core\Cache\CacheDataCollectorInterface;
18
use TYPO3\CMS\Core\Cache\CacheManager;
19
use TYPO3\CMS\Core\Cache\CacheTag;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Cache\CacheTag was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use TYPO3\CMS\Core\Database\Connection;
21
use TYPO3\CMS\Core\Database\ConnectionPool;
22
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
23
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
24
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26
class EventCacheService
27
{
28
    /**
29
     * Adds cache tags to page cache by event records.
30
     *
31
     * Following cache tags will be added to CacheDataCollector
32
     * "tx_sfeventmgt_uid_[event:uid]"
33
     */
34
    public function addCacheTagsByEventRecords(
35
        CacheDataCollectorInterface $cacheDataCollector,
36
        array $eventRecords
37
    ): void {
38
        $cacheTags = [];
39
40
        $now = new DateTime();
41
42
        /** @var Event $event */
43
        foreach ($eventRecords as $event) {
44
            // cache tag for each event record
45
            $cacheTags[] = new CacheTag('tx_sfeventmgt_uid_' . $event->getUid(), $event->getCacheTagLifetime($now));
46
        }
47
        if (count($cacheTags) > 0) {
48
            $cacheDataCollector->addCacheTags(...$cacheTags);
49
        }
50
    }
51
52
    /**
53
     * Adds page cache tags by used storagePages.
54
     *
55
     * This adds tags with the scheme tx_sfeventmgt_pid_[event:pid]
56
     */
57
    public function addPageCacheTagsByEventDemandObject(
58
        CacheDataCollectorInterface $cacheDataCollector,
59
        EventDemand $demand
60
    ): void {
61
        $cacheTags = [];
62
        if ($demand->getStoragePage()) {
63
            // Add cache tags for each storage page
64
            foreach (GeneralUtility::trimExplode(',', $demand->getStoragePage()) as $pageUid) {
65
                $lifetime = $this->getCacheTagLifetimeForStoragePage((int)$pageUid);
66
                $cacheTags[] = new CacheTag('tx_sfeventmgt_pid_' . $pageUid, $lifetime);
67
            }
68
        }
69
        if (count($cacheTags) > 0) {
70
            $cacheDataCollector->addCacheTags(...$cacheTags);
71
        }
72
    }
73
74
    /**
75
     * Flushes the page cache by event tags for the given event uid and pid
76
     */
77
    public function flushEventCache(int $eventUid = 0, int $eventPid = 0): void
78
    {
79
        $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
80
        $cacheTagsToFlush = [];
81
82
        if ($eventUid > 0) {
83
            $cacheTagsToFlush[] = 'tx_sfeventmgt_uid_' . $eventUid;
84
        }
85
        if ($eventPid > 0) {
86
            $cacheTagsToFlush[] = 'tx_sfeventmgt_pid_' . $eventPid;
87
        }
88
89
        foreach ($cacheTagsToFlush as $cacheTagToFlush) {
90
            $cacheManager->flushCachesInGroupByTag('pages', $cacheTagToFlush);
91
        }
92
    }
93
94
    /**
95
     * Calculates the cache tag liftime for all events in the given Page UID by considering the event several
96
     * event fields.
97
     */
98
    protected function getCacheTagLifetimeForStoragePage(int $pid): int
99
    {
100
        $result = PHP_INT_MAX;
101
102
        $currentTimestamp = (new DateTime())->getTimestamp();
103
104
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
105
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_event');
106
        $queryBuilder->getRestrictions()
107
            ->removeByType(StartTimeRestriction::class)
108
            ->removeByType(EndTimeRestriction::class);
109
        $timeFields = ['registration_startdate', 'registration_deadline', 'startdate', 'starttime', 'endtime'];
110
        $timeConditions = $queryBuilder->expr()->or();
111
        foreach ($timeFields as $field) {
112
            $queryBuilder->addSelectLiteral(
113
                'MIN('
114
                . 'CASE WHEN '
115
                . $queryBuilder->expr()->lte(
116
                    $field,
117
                    $queryBuilder->createNamedParameter($currentTimestamp, Connection::PARAM_INT)
118
                )
119
                . ' THEN NULL ELSE ' . $queryBuilder->quoteIdentifier($field) . ' END'
120
                . ') AS ' . $queryBuilder->quoteIdentifier($field)
121
            );
122
            $timeConditions->with(
123
                $queryBuilder->expr()->gt(
124
                    $field,
125
                    $queryBuilder->createNamedParameter($currentTimestamp, Connection::PARAM_INT)
126
                )
127
            );
128
        }
129
130
        // Only consider events where registration is enabled and that have not started yet.
131
        // Also include PID and timeConditions
132
        $row = $queryBuilder
133
            ->from('tx_sfeventmgt_domain_model_event')
134
            ->where(
135
                $queryBuilder->expr()->eq(
136
                    'pid',
137
                    $queryBuilder->createNamedParameter($pid, Connection::PARAM_INT)
138
                ),
139
                $queryBuilder->expr()->eq(
140
                    'enable_registration',
141
                    $queryBuilder->createNamedParameter(1, Connection::PARAM_INT)
142
                ),
143
                $queryBuilder->expr()->gt(
144
                    'startdate',
145
                    $queryBuilder->createNamedParameter($currentTimestamp, Connection::PARAM_INT)
146
                ),
147
                $timeConditions
148
            )
149
            ->executeQuery()
150
            ->fetchAssociative();
151
152
        if ($row) {
153
            foreach ($timeFields as $timeField) {
154
                if ($row[$timeField] !== null && (int)$row[$timeField] > $currentTimestamp) {
155
                    $result = min($result, (int)$row[$timeField]);
156
                }
157
            }
158
        }
159
160
        if ($result !== PHP_INT_MAX) {
161
            $result = $result - $currentTimestamp + 1;
162
        }
163
164
        return $result;
165
    }
166
}
167