ProcessRepository::addProcess()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 1
rs 10
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 PDO;
35
use TYPO3\CMS\Core\Database\Connection;
36
use TYPO3\CMS\Core\Database\ConnectionPool;
37
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
use TYPO3\CMS\Extbase\Object\ObjectManager;
40
use TYPO3\CMS\Extbase\Persistence\Repository;
41
42
/**
43
 * @internal since v9.2.5
44
 */
45
class ProcessRepository extends Repository
46
{
47
    public const TABLE_NAME = 'tx_crawler_process';
48
49
    /**
50
     * @var QueryBuilder
51
     */
52
    protected $queryBuilder;
53
54
    /**
55
     * @var array
56
     */
57
    protected $extensionSettings = [];
58
59 67
    public function __construct()
60
    {
61 67
        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
62
63 67
        parent::__construct($objectManager);
64
65 67
        $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
66
67
        /** @var ExtensionConfigurationProvider $configurationProvider */
68 67
        $configurationProvider = GeneralUtility::makeInstance(ExtensionConfigurationProvider::class);
69 67
        $this->extensionSettings = $configurationProvider->getExtensionConfiguration();
70 67
    }
71
72
    /**
73
     * This method is used to find all cli processes within a limit.
74
     */
75 7
    public function findAll(): ProcessCollection
76
    {
77
        /** @var ProcessCollection $collection */
78 7
        $collection = GeneralUtility::makeInstance(ProcessCollection::class);
79 7
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
80
81
        $statement = $queryBuilder
82 7
            ->select('*')
83 7
            ->from(self::TABLE_NAME)
84 7
            ->orderBy('ttl', 'DESC')
85 7
            ->execute();
86
87 7
        while ($row = $statement->fetch()) {
88 7
            $process = GeneralUtility::makeInstance(Process::class);
89 7
            $process->setProcessId($row['process_id']);
90 7
            $process->setActive($row['active']);
91 7
            $process->setTtl($row['ttl']);
92 7
            $process->setAssignedItemsCount($row['assigned_items_count']);
93 7
            $process->setDeleted($row['deleted']);
94 7
            $process->setSystemProcessId($row['system_process_id']);
95 7
            $collection->append($process);
96
        }
97
98 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...
99
    }
100
101
    /**
102
     * @param string $processId
103
     */
104 2
    public function findByProcessId($processId)
105
    {
106 2
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
107
108
        return $queryBuilder
109 2
            ->select('*')
110 2
            ->from(self::TABLE_NAME)
111 2
            ->where(
112 2
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId, PDO::PARAM_STR))
113 2
            )->execute()->fetch(0);
114
    }
115
116 5
    public function findAllActive(): ProcessCollection
117
    {
118
        /** @var ProcessCollection $collection */
119 5
        $collection = GeneralUtility::makeInstance(ProcessCollection::class);
120 5
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
121
122
        $statement = $queryBuilder
123 5
            ->select('*')
124 5
            ->from(self::TABLE_NAME)
125 5
            ->where(
126 5
                $queryBuilder->expr()->eq('active', 1),
127 5
                $queryBuilder->expr()->eq('deleted', 0)
128
            )
129 5
            ->orderBy('ttl', 'DESC')
130 5
            ->execute();
131
132 5
        while ($row = $statement->fetch()) {
133 3
            $process = new Process();
134 3
            $process->setProcessId($row['process_id']);
135 3
            $process->setActive($row['active']);
136 3
            $process->setTtl($row['ttl']);
137 3
            $process->setAssignedItemsCount($row['assigned_items_count']);
138 3
            $process->setDeleted($row['deleted']);
139 3
            $process->setSystemProcessId($row['system_process_id']);
140 3
            $collection->append($process);
141
        }
142
143 5
        return $collection;
144
    }
145
146
    /**
147
     * @param string $processId
148
     */
149 4
    public function removeByProcessId($processId): void
150
    {
151 4
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
152
153
        $queryBuilder
154 4
            ->delete(self::TABLE_NAME)
155 4
            ->where(
156 4
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId, PDO::PARAM_STR))
157 4
            )->execute();
158 4
    }
159
160
    /**
161
     * Returns the number of active processes.
162
     *
163
     * @return int
164
     * @deprecated Using ProcessRepository->countActive() is deprecated since 9.1.1 and will be removed in v11.x, please use ProcessRepository->findAllActive->count() instead
165
     * @codeCoverageIgnore
166
     */
167
    public function countActive()
168
    {
169
        return $this->findAllActive()->count();
170
    }
171
172
    /**
173
     * @return array|null
174
     *
175
     * Function is moved from ProcessCleanUpHook
176
     * TODO: Check why we need both getActiveProcessesOlderThanOneHour and getActiveOrphanProcesses, the get getActiveOrphanProcesses does not really check for Orphan in this implementation.
177
     */
178 3
    public function getActiveProcessesOlderThanOneHour()
179
    {
180 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
181 3
        $activeProcesses = [];
182
        $statement = $queryBuilder
183 3
            ->select('process_id', 'system_process_id')
184 3
            ->from(self::TABLE_NAME)
185 3
            ->where(
186 3
                $queryBuilder->expr()->lte('ttl', intval(time() - $this->extensionSettings['processMaxRunTime'] - 3600)),
187 3
                $queryBuilder->expr()->eq('active', 1)
188
            )
189 3
            ->execute();
190
191 3
        while ($row = $statement->fetch()) {
192 1
            $activeProcesses[] = $row;
193
        }
194
195 3
        return $activeProcesses;
196
    }
197
198
    /**
199
     * Function is moved from ProcessCleanUpHook
200
     *
201
     * @return array
202
     * @see getActiveProcessesOlderThanOneHour
203
     */
204 3
    public function getActiveOrphanProcesses()
205
    {
206 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
207
208
        return $queryBuilder
209 3
            ->select('process_id', 'system_process_id')
210 3
            ->from(self::TABLE_NAME)
211 3
            ->where(
212 3
                $queryBuilder->expr()->lte('ttl', intval(time() - $this->extensionSettings['processMaxRunTime'])),
213 3
                $queryBuilder->expr()->eq('active', 1)
214
            )
215 3
            ->execute()->fetchAll();
216
    }
217
218
    /**
219
     * Returns the number of processes that live longer than the given timestamp.
220
     */
221 1
    public function countNotTimeouted(int $ttl): int
222
    {
223 1
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
224
225
        return $queryBuilder
226 1
            ->count('*')
227 1
            ->from(self::TABLE_NAME)
228 1
            ->where(
229 1
                $queryBuilder->expr()->eq('deleted', 0),
230 1
                $queryBuilder->expr()->gt('ttl', intval($ttl))
231
            )
232 1
            ->execute()
233 1
            ->fetchColumn(0);
234
    }
235
236
    /**
237
     * Get limit clause
238
     * @deprecated Using ProcessRepository::getLimitFromItemCountAndOffset() is deprecated since 9.1.1 and will be removed in v11.x, was not used, so will be removed
239
     */
240 6
    public static function getLimitFromItemCountAndOffset(int $itemCount, int $offset): string
241
    {
242 6
        $itemCount = filter_var($itemCount, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'default' => 20]]);
243 6
        $offset = filter_var($offset, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0, 'default' => 0]]);
244
245 6
        return $offset . ', ' . $itemCount;
246
    }
247
248 3
    public function deleteProcessesWithoutItemsAssigned(): void
249
    {
250 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
251
        $queryBuilder
252 3
            ->delete(self::TABLE_NAME)
253 3
            ->where(
254 3
                $queryBuilder->expr()->eq('assigned_items_count', 0)
255
            )
256 3
            ->execute();
257 3
    }
258
259 3
    public function deleteProcessesMarkedAsDeleted(): void
260
    {
261 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
262
        $queryBuilder
263 3
            ->delete(self::TABLE_NAME)
264 3
            ->where(
265 3
                $queryBuilder->expr()->eq('deleted', 1)
266
            )
267 3
            ->execute();
268 3
    }
269
270 2
    public function isProcessActive(string $processId): bool
271
    {
272 2
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
273
        $isActive = $queryBuilder
274 2
            ->select('active')
275 2
            ->from(self::TABLE_NAME)
276 2
            ->where(
277 2
                $queryBuilder->expr()->eq('process_id', $queryBuilder->createNamedParameter($processId))
278
            )
279 2
            ->orderBy('ttl')
280 2
            ->execute()
281 2
            ->fetchColumn(0);
282
283 2
        return (bool) $isActive;
284
    }
285
286
    /**
287
     * @param $numberOfAffectedRows
288
     */
289 3
    public function updateProcessAssignItemsCount($numberOfAffectedRows, string $processId): void
290
    {
291 3
        GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::TABLE_NAME)
292 3
            ->update(
293 3
                self::TABLE_NAME,
294 3
                ['assigned_items_count' => (int) $numberOfAffectedRows],
295 3
                ['process_id' => $processId]
296
            );
297 3
    }
298
299 3
    public function markRequestedProcessesAsNotActive(array $processIds): void
300
    {
301 3
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
302 3
        $queryBuilder->update(self::TABLE_NAME)
303 3
            ->where(
304 3
                'NOT EXISTS (
305
                SELECT * FROM tx_crawler_queue
306
                    WHERE tx_crawler_queue.process_id = tx_crawler_process.process_id
307
                    AND tx_crawler_queue.exec_time = 0
308
                )',
309 3
                $queryBuilder->expr()->in('process_id', $queryBuilder->createNamedParameter($processIds, Connection::PARAM_STR_ARRAY)),
310 3
                $queryBuilder->expr()->eq('deleted', 0)
311
            )
312 3
            ->set('active', 0)
313 3
            ->execute();
314 3
    }
315
316 3
    public function addProcess(string $processId, int $systemProcessId): void
317
    {
318 3
        GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::TABLE_NAME)->insert(
319 3
            self::TABLE_NAME,
320
            [
321 3
                'process_id' => $processId,
322 3
                'active' => 1,
323 3
                'ttl' => time() + (int) $this->extensionSettings['processMaxRunTime'],
324 3
                'system_process_id' => $systemProcessId,
325
            ]
326
        );
327 3
    }
328
}
329