1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Aoe\AoeDbSequenzer; |
4
|
|
|
|
5
|
|
|
use Doctrine\DBAL\Types\Type; |
6
|
|
|
use TYPO3\CMS\Core\Database\Connection; |
7
|
|
|
use TYPO3\CMS\Core\Database\ConnectionPool; |
8
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
9
|
|
|
|
10
|
|
|
/*************************************************************** |
11
|
|
|
* Copyright notice |
12
|
|
|
* |
13
|
|
|
* (c) 2017 AOE GmbH ([email protected]) |
14
|
|
|
* All rights reserved |
15
|
|
|
* |
16
|
|
|
* This script is part of the TYPO3 project. The TYPO3 project is |
17
|
|
|
* free software; you can redistribute it and/or modify |
18
|
|
|
* it under the terms of the GNU General Public License as published by |
19
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
20
|
|
|
* (at your option) any later version. |
21
|
|
|
* |
22
|
|
|
* The GNU General Public License can be found at |
23
|
|
|
* http://www.gnu.org/copyleft/gpl.html. |
24
|
|
|
* |
25
|
|
|
* This script is distributed in the hope that it will be useful, |
26
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
27
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
28
|
|
|
* GNU General Public License for more details. |
29
|
|
|
* |
30
|
|
|
* This copyright notice MUST APPEAR in all copies of the script! |
31
|
|
|
***************************************************************/ |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Sequenzer is used to generate system wide independent IDs |
35
|
|
|
* |
36
|
|
|
* @package Aoe\AoeDbSequenzer |
37
|
|
|
*/ |
38
|
|
|
class Sequenzer |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* @var string |
42
|
|
|
*/ |
43
|
|
|
const SEQUENZER_TABLE = 'tx_aoedbsequenzer_sequenz'; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var integer |
47
|
|
|
*/ |
48
|
|
|
private $defaultStart = 0; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var integer |
52
|
|
|
*/ |
53
|
|
|
private $defaultOffset = 1; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @var integer in seconds |
57
|
|
|
*/ |
58
|
|
|
private $checkInterval = 120; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @param integer $defaultStart to set |
62
|
|
|
*/ |
63
|
1 |
|
public function setDefaultStart($defaultStart) |
64
|
|
|
{ |
65
|
1 |
|
$this->defaultStart = $defaultStart; |
66
|
1 |
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @param integer $defaultOffset to set |
70
|
|
|
*/ |
71
|
1 |
|
public function setDefaultOffset($defaultOffset) |
72
|
|
|
{ |
73
|
1 |
|
$this->defaultOffset = $defaultOffset; |
74
|
1 |
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* returns next free id in the sequenz of the table |
78
|
|
|
* |
79
|
|
|
* @param $table |
80
|
|
|
* @param int $depth |
81
|
|
|
* |
82
|
|
|
* @return int |
83
|
|
|
* @throws \Exception |
84
|
|
|
*/ |
85
|
|
|
public function getNextIdForTable($table, $depth = 0) |
86
|
|
|
{ |
87
|
|
|
if ($depth > 99) { |
88
|
|
|
throw new \Exception( |
89
|
|
|
'The sequenzer cannot return IDs for this table -' . $table . ' Too many recursions - maybe to much load?', |
90
|
|
|
1512378158 |
91
|
|
|
); |
92
|
|
|
} |
93
|
|
|
/** @var Connection $databaseConnection */ |
94
|
|
|
$databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::SEQUENZER_TABLE); |
95
|
|
|
$row = $databaseConnection->select(['*'], self::SEQUENZER_TABLE, ['tablename' => $table])->fetch(); |
|
|
|
|
96
|
|
|
|
97
|
|
|
if (!isset($row['current'])) { |
98
|
|
|
$this->initSequenzerForTable($table); |
99
|
|
|
return $this->getNextIdForTable($table, ++$depth); |
100
|
|
|
} elseif ($row['timestamp'] + $this->checkInterval < $GLOBALS['EXEC_TIME']) { |
101
|
|
|
$defaultStartValue = $this->getDefaultStartValue($table); |
102
|
|
|
$isValueOutdated = ($row['current'] < $defaultStartValue); |
103
|
|
|
$isOffsetChanged = ($row['offset'] != $this->defaultOffset); |
104
|
|
|
$isStartChanged = ($row['current'] % $this->defaultOffset != $this->defaultStart); |
105
|
|
|
if ($isValueOutdated || $isOffsetChanged || $isStartChanged) { |
106
|
|
|
$row['current'] = $defaultStartValue; |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$new = $row['current'] + $row['offset']; |
111
|
|
|
$updateTimeStamp = $GLOBALS['EXEC_TIME']; |
112
|
|
|
$updateResult = $databaseConnection->update( |
113
|
|
|
self::SEQUENZER_TABLE, |
114
|
|
|
['current' => $new, 'timestamp' => $updateTimeStamp], |
115
|
|
|
['timestamp' => $row['timestamp'], 'tablename' => $table] |
116
|
|
|
); |
117
|
|
|
|
118
|
|
|
if ($updateResult > 0) { |
119
|
|
|
return $new; |
120
|
|
|
} else { |
121
|
|
|
return $this->getNextIdForTable($table, ++$depth); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Gets the default start value for a given table. |
127
|
|
|
* |
128
|
|
|
* @param $table |
129
|
|
|
* |
130
|
|
|
* @return int |
131
|
|
|
* @throws \Exception |
132
|
|
|
*/ |
133
|
|
|
private function getDefaultStartValue($table) |
134
|
|
|
{ |
135
|
|
|
/** @var Connection $databaseConnection */ |
136
|
|
|
$databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::SEQUENZER_TABLE); |
137
|
|
|
$row = $databaseConnection->select(['uid'], $table, [], [], ['uid' => 'DESC'], 1)->fetch(); |
|
|
|
|
138
|
|
|
$currentMax = $row['uid'] + 1; |
139
|
|
|
$start = $this->defaultStart + ($this->defaultOffset * ceil($currentMax / $this->defaultOffset)); |
140
|
|
|
|
141
|
|
|
return (int)$start; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* if no scheduler entry for the table yet exists, this method initialises the sequenzer to fit offest and start and current max value |
146
|
|
|
* in the table |
147
|
|
|
* |
148
|
|
|
* @param string $table |
149
|
|
|
* |
150
|
|
|
* @throws \Exception |
151
|
|
|
*/ |
152
|
|
|
private function initSequenzerForTable($table) |
153
|
|
|
{ |
154
|
|
|
$start = $this->getDefaultStartValue($table); |
155
|
|
|
|
156
|
|
|
/** @var Connection $databaseConnection */ |
157
|
|
|
$databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::SEQUENZER_TABLE); |
158
|
|
|
$databaseConnection->insert( |
159
|
|
|
self::SEQUENZER_TABLE, |
160
|
|
|
['tablename' => $table, 'current' => $start, 'offset' => $this->defaultOffset, 'timestamp' => $GLOBALS['EXEC_TIME']], |
161
|
|
|
[Type::STRING, Type::INTEGER, Type::INTEGER, Type::STRING] |
|
|
|
|
162
|
|
|
); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.