51b200435c6c14e0284d4c7c0b0915110d4c1027
[Packages/TYPO3.CMS.git] / typo3 / sysext / recycler / Classes / Task / CleanerTask.php
1 <?php
2 namespace TYPO3\CMS\Recycler\Task;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Core\Database\ConnectionPool;
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Scheduler\Task\AbstractTask;
19
20 /**
21 * A task that should be run regularly that deletes deleted
22 * datasets from the DB.
23 */
24 class CleanerTask extends AbstractTask
25 {
26 /**
27 * @var int The time period, after which the rows are deleted
28 */
29 protected $period = 0;
30
31 /**
32 * @var array The tables to clean
33 */
34 protected $tcaTables = [];
35
36 /**
37 * The main method of the task. Iterates through
38 * the tables and calls the cleaning function
39 *
40 * @return bool Returns TRUE on successful execution, FALSE on error
41 */
42 public function execute()
43 {
44 $success = true;
45 $tables = $this->getTcaTables();
46 foreach ($tables as $table) {
47 if (!$this->cleanTable($table)) {
48 $success = false;
49 }
50 }
51
52 return $success;
53 }
54
55 /**
56 * Executes the delete-query for the given table
57 *
58 * @param string $tableName
59 * @return bool
60 */
61 protected function cleanTable($tableName)
62 {
63 if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
64 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
65 $queryBuilder->getRestrictions()->removeAll();
66
67 $constraints = [
68 $queryBuilder->expr()->eq(
69 $GLOBALS['TCA'][$tableName]['ctrl']['delete'],
70 $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)
71 )
72 ,
73 ];
74
75 if ($GLOBALS['TCA'][$tableName]['ctrl']['tstamp']) {
76 $dateBefore = $this->getPeriodAsTimestamp();
77 $constraints[] = $queryBuilder->expr()->lt(
78 $GLOBALS['TCA'][$tableName]['ctrl']['tstamp'],
79 $queryBuilder->createNamedParameter($dateBefore, \PDO::PARAM_INT)
80 );
81 }
82 $this->checkFileResourceFieldsBeforeDeletion($tableName);
83 try {
84 $queryBuilder->delete($tableName)
85 ->where(...$constraints)
86 ->execute();
87 } catch (\Doctrine\DBAL\DBALException $e) {
88 return false;
89 }
90 }
91 return true;
92 }
93
94 /**
95 * Returns the information shown in the task-list
96 *
97 * @return string Information-text fot the scheduler task-list
98 */
99 public function getAdditionalInformation()
100 {
101 $message = '';
102
103 $message .= sprintf(
104 $this->getLanguageService()->sL('LLL:EXT:recycler/Resources/Private/Language/locallang_tasks.xlf:cleanerTaskDescriptionTables'),
105 implode(', ', $this->getTcaTables())
106 );
107
108 $message .= '; ';
109
110 $message .= sprintf(
111 $this->getLanguageService()->sL('LLL:EXT:recycler/Resources/Private/Language/locallang_tasks.xlf:cleanerTaskDescriptionDays'),
112 $this->getPeriod()
113 );
114
115 return $message;
116 }
117
118 /**
119 * Sets the period after which a row is deleted
120 *
121 * @param int $period
122 */
123 public function setPeriod($period)
124 {
125 $this->period = (int)$period;
126 }
127
128 /**
129 * Returns the period after which a row is deleted
130 *
131 * @return int
132 */
133 public function getPeriod()
134 {
135 return $this->period;
136 }
137
138 /**
139 * @return int
140 */
141 public function getPeriodAsTimestamp()
142 {
143 return strtotime('-' . $this->getPeriod() . ' days');
144 }
145
146 /**
147 * Sets the TCA-tables which are cleaned
148 *
149 * @param array $tcaTables
150 */
151 public function setTcaTables($tcaTables = [])
152 {
153 $this->tcaTables = $tcaTables;
154 }
155
156 /**
157 * Returns the TCA-tables which are cleaned
158 *
159 * @return array
160 */
161 public function getTcaTables()
162 {
163 return $this->tcaTables;
164 }
165
166 /**
167 * Checks if the table has fields for uploaded files and removes those files.
168 *
169 * @param string $table
170 */
171 protected function checkFileResourceFieldsBeforeDeletion($table)
172 {
173 $fieldList = $this->getFileResourceFields($table);
174 if (!empty($fieldList)) {
175 $this->deleteFilesForTable($table, $fieldList);
176 }
177 }
178
179 /**
180 * Removes all files from the given field list in the table.
181 *
182 * @param string $table
183 * @param array $fieldList
184 */
185 protected function deleteFilesForTable($table, array $fieldList)
186 {
187 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
188 $queryBuilder->getRestrictions()->removeAll();
189
190 $constraints = [
191 $queryBuilder->expr()->eq(
192 $GLOBALS['TCA'][$table]['ctrl']['delete'],
193 $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)
194 )
195 ];
196
197 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
198 $dateBefore = $this->getPeriodAsTimestamp();
199 $constraints[] = $queryBuilder->expr()->lt(
200 $GLOBALS['TCA'][$table]['ctrl']['tstamp'],
201 $queryBuilder->createNamedParameter($dateBefore, \PDO::PARAM_INT)
202 );
203 }
204
205 $result = $queryBuilder
206 ->select(...$fieldList)
207 ->from($table)
208 ->where(...$constraints)
209 ->execute();
210
211 while ($row = $result->fetch()) {
212 foreach ($fieldList as $fieldName) {
213 $uploadDir = PATH_site . $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['uploadfolder'] . '/';
214 $fileList = GeneralUtility::trimExplode(',', $row[$fieldName]);
215 foreach ($fileList as $fileName) {
216 @unlink($uploadDir . $fileName);
217 }
218 }
219 }
220 }
221
222 /**
223 * Checks the $TCA for fields that can list file resources.
224 *
225 * @param string $table
226 * @return array
227 */
228 protected function getFileResourceFields($table)
229 {
230 $result = [];
231 if (isset($GLOBALS['TCA'][$table]['columns'])) {
232 foreach ($GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldConfiguration) {
233 if ($fieldConfiguration['config']['type'] === 'group'
234 && $fieldConfiguration['config']['internal_type'] === 'file'
235 ) {
236 $result[] = $fieldName;
237 break;
238 }
239 }
240 }
241 return $result;
242 }
243
244 /**
245 * @return \TYPO3\CMS\Core\Localization\LanguageService
246 */
247 protected function getLanguageService()
248 {
249 return $GLOBALS['LANG'];
250 }
251 }