Passed
Push — master ( 90c78c...318ab6 )
by Tomas Norre
07:41
created

ProcessRepository::countActive()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AOE\Crawler\Domain\Repository;
6
7
/***************************************************************
8
 *  Copyright notice
9
 *
10
 *  (c) 2019 AOE GmbH <[email protected]>
11
 *
12
 *  All rights reserved
13
 *
14
 *  This script is part of the TYPO3 project. The TYPO3 project is
15
 *  free software; you can redistribute it and/or modify
16
 *  it under the terms of the GNU General Public License as published by
17
 *  the Free Software Foundation; either version 3 of the License, or
18
 *  (at your option) any later version.
19
 *
20
 *  The GNU General Public License can be found at
21
 *  http://www.gnu.org/copyleft/gpl.html.
22
 *
23
 *  This script is distributed in the hope that it will be useful,
24
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
 *  GNU General Public License for more details.
27
 *
28
 *  This copyright notice MUST APPEAR in all copies of the script!
29
 ***************************************************************/
30
31
use AOE\Crawler\Configuration\ExtensionConfigurationProvider;
32
use AOE\Crawler\Domain\Model\Process;
33
use AOE\Crawler\Domain\Model\ProcessCollection;
34
use TYPO3\CMS\Core\Database\Connection;
35
use TYPO3\CMS\Core\Database\ConnectionPool;
36
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
use TYPO3\CMS\Extbase\Object\ObjectManager;
39
use TYPO3\CMS\Extbase\Persistence\Repository;
40
41
/**
42
 * Class ProcessRepository
43
 *
44
 * @package AOE\Crawler\Domain\Repository
45
 */
46
class ProcessRepository extends Repository
47
{
48
    /**
49
     * @var string
50
     */
51
    protected $tableName = 'tx_crawler_process';
52
53
    /**
54
     * @var QueryBuilder
55
     */
56
    protected $queryBuilder;
57
58
    /**
59
     * @var array
60
     */
61
    protected $extensionSettings = [];
62
63
    /**
64
     * QueueRepository constructor.
65
     */
66 66
    public function __construct()
67
    {
68 66
        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
69
70 66
        parent::__construct($objectManager);
71
72 66
        $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
73
74
        /** @var ExtensionConfigurationProvider $configurationProvider */
75 66
        $configurationProvider = GeneralUtility::makeInstance(ExtensionConfigurationProvider::class);
76 66
        $this->extensionSettings = $configurationProvider->getExtensionConfiguration();
77 66
    }
78
79
    /**
80
     * This method is used to find all cli processes within a limit.
81
     */
82 7
    public function findAll(): ProcessCollection
83
    {
84
        /** @var ProcessCollection $collection */
85 7
        $collection = GeneralUtility::makeInstance(ProcessCollection::class);
86 7
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
87
88
        $statement = $queryBuilder
89 7
            ->select('*')
90 7
            ->from($this->tableName)
91 7
            ->orderBy('ttl', 'DESC')
92 7
            ->execute();
93
94 7
        while ($row = $statement->fetch()) {
95 7
            $process = GeneralUtility::makeInstance(Process::class);
96 7
            $process->setProcessId($row['process_id']);
97 7
            $process->setActive($row['active']);
98 7
            $process->setTtl($row['ttl']);
99 7
            $process->setAssignedItemsCount($row['assigned_items_count']);
100 7
            $process->setDeleted($row['deleted']);
101 7
            $process->setSystemProcessId($row['system_process_id']);
102 7
            $collection->append($process);
103
        }
104
105 7
        return $collection;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $collection returns the type AOE\Crawler\Domain\Model\ProcessCollection which is incompatible with the return type mandated by TYPO3\CMS\Extbase\Persis...oryInterface::findAll() of TYPO3\CMS\Extbase\Persis...ryResultInterface|array.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
106
    }
107
108
    /**
109
     * @param string $processId
110
     */
111 1
    public function findByProcessId($processId)
112
    {
113 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
114
115
        return $queryBuilder
116 1
            ->select('*')
117 1
            ->from($this->tableName)
118 1
            ->where(
119 1
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId, \PDO::PARAM_STR))
120 1
            )->execute()->fetch(0);
121
    }
122
123 3
    public function findAllActive(): ProcessCollection
124
    {
125
        /** @var ProcessCollection $collection */
126 3
        $collection = GeneralUtility::makeInstance(ProcessCollection::class);
127 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
128
129
        $statement = $queryBuilder
130 3
            ->select('*')
131 3
            ->from($this->tableName)
132 3
            ->where(
133 3
                $queryBuilder->expr()->eq('active', 1),
134 3
                $queryBuilder->expr()->eq('deleted', 0)
135
            )
136 3
            ->orderBy('ttl', 'DESC')
137 3
            ->execute();
138
139 3
        while ($row = $statement->fetch()) {
140 3
            $process = new Process();
141 3
            $process->setProcessId($row['process_id']);
142 3
            $process->setActive($row['active']);
143 3
            $process->setTtl($row['ttl']);
144 3
            $process->setAssignedItemsCount($row['assigned_items_count']);
145 3
            $process->setDeleted($row['deleted']);
146 3
            $process->setSystemProcessId($row['system_process_id']);
147 3
            $collection->append($process);
148
        }
149
150 3
        return $collection;
151
    }
152
153
    /**
154
     * @param string $processId
155
     */
156 4
    public function removeByProcessId($processId): void
157
    {
158 4
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
159
160
        $queryBuilder
161 4
            ->delete($this->tableName)
162 4
            ->where(
163 4
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId, \PDO::PARAM_STR))
164 4
            )->execute();
165 4
    }
166
167
    /**
168
     * Returns the number of active processes.
169
     *
170
     * @return int
171
     * @deprecated Using ProcessRepository->countActive() is deprecated since 9.1.1 and will be removed in v11.x, please use ProcessRepository->findAllActive->count() instead
172
     * @codeCoverageIgnore
173
     */
174
    public function countActive()
175
    {
176
        return $this->findAllActive()->count();
177
    }
178
179
    /**
180
     * @return array|null
181
     *
182
     * Function is moved from ProcessCleanUpHook
183
     * TODO: Check why we need both getActiveProcessesOlderThanOneHour and getActiveOrphanProcesses, the get getActiveOrphanProcesses does not really check for Orphan in this implementation.
184
     */
185 1
    public function getActiveProcessesOlderThanOneHour()
186
    {
187 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
188 1
        $activeProcesses = [];
189
        $statement = $queryBuilder
190 1
            ->select('process_id', 'system_process_id')
191 1
            ->from($this->tableName)
192 1
            ->where(
193 1
                $queryBuilder->expr()->lte('ttl', intval(time() - $this->extensionSettings['processMaxRunTime'] - 3600)),
194 1
                $queryBuilder->expr()->eq('active', 1)
195
            )
196 1
            ->execute();
197
198 1
        while ($row = $statement->fetch()) {
199 1
            $activeProcesses[] = $row;
200
        }
201
202 1
        return $activeProcesses;
203
    }
204
205
    /**
206
     * Function is moved from ProcessCleanUpHook
207
     *
208
     * @return array
209
     * @see getActiveProcessesOlderThanOneHour
210
     */
211 1
    public function getActiveOrphanProcesses()
212
    {
213 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
214
215
        return $queryBuilder
216 1
            ->select('process_id', 'system_process_id')
217 1
            ->from($this->tableName)
218 1
            ->where(
219 1
                $queryBuilder->expr()->lte('ttl', intval(time() - $this->extensionSettings['processMaxRunTime'])),
220 1
                $queryBuilder->expr()->eq('active', 1)
221
            )
222 1
            ->execute()->fetchAll();
223
    }
224
225
    /**
226
     * Returns the number of processes that live longer than the given timestamp.
227
     */
228 1
    public function countNotTimeouted(int $ttl): int
229
    {
230 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
231
232
        return $queryBuilder
233 1
            ->count('*')
234 1
            ->from($this->tableName)
235 1
            ->where(
236 1
                $queryBuilder->expr()->eq('deleted', 0),
237 1
                $queryBuilder->expr()->gt('ttl', intval($ttl))
238
            )
239 1
            ->execute()
240 1
            ->fetchColumn(0);
241
    }
242
243
    /**
244
     * Get limit clause
245
     * @deprecated Using ProcessRepository::getLimitFromItemCountAndOffset() is deprecated since 9.1.1 and will be removed in v11.x, was not used, so will be removed
246
     */
247 4
    public static function getLimitFromItemCountAndOffset(int $itemCount, int $offset): string
248
    {
249 4
        $itemCount = filter_var($itemCount, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'default' => 20]]);
250 4
        $offset = filter_var($offset, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0, 'default' => 0]]);
251
252 4
        return $offset . ', ' . $itemCount;
253
    }
254
255 1
    public function deleteProcessesWithoutItemsAssigned(): void
256
    {
257 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
258
        $queryBuilder
259 1
            ->delete($this->tableName)
260 1
            ->where(
261 1
                $queryBuilder->expr()->eq('assigned_items_count', 0)
262
            )
263 1
            ->execute();
264 1
    }
265
266 1
    public function deleteProcessesMarkedAsDeleted(): void
267
    {
268 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
269
        $queryBuilder
270 1
            ->delete($this->tableName)
271 1
            ->where(
272 1
                $queryBuilder->expr()->eq('deleted', 1)
273
            )
274 1
            ->execute();
275 1
    }
276
277
    public function isProcessActive(string $processId): bool
278
    {
279
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
280
        $isActive = $queryBuilder
281
            ->select('active')
282
            ->from($this->tableName)
283
            ->where(
284
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId))
285
            )
286
            ->orderBy('ttl')
287
            ->execute()
288
            ->fetchColumn(0);
289
290
        return (bool) $isActive;
291
    }
292
293
    /**
294
     * @param $numberOfAffectedRows
295
     */
296 1
    public function updateProcessAssignItemsCount($numberOfAffectedRows, string $processId): void
297
    {
298 1
        GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->tableName)
299 1
            ->update(
300 1
                'tx_crawler_process',
301 1
                ['assigned_items_count' => (int) $numberOfAffectedRows],
302 1
                ['process_id' => $processId]
303
            );
304 1
    }
305
306 1
    public function markRequestedProcessesAsNotActive(array $processIds): void
307
    {
308 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
309 1
        $queryBuilder->update('tx_crawler_process')
310 1
            ->where(
311 1
                'NOT EXISTS (
312
                SELECT * FROM tx_crawler_queue
313
                    WHERE tx_crawler_queue.process_id = tx_crawler_process.process_id
314
                    AND tx_crawler_queue.exec_time = 0
315
                )',
316 1
                $queryBuilder->expr()->in('process_id', $queryBuilder->createNamedParameter($processIds, Connection::PARAM_STR_ARRAY)),
317 1
                $queryBuilder->expr()->eq('deleted', 0)
318
            )
319 1
            ->set('active', 0)
320 1
            ->execute();
321 1
    }
322
}
323