Cleanup: Updated copyright comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / recycler / classes / model / class.tx_recycler_model_deletedRecords.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009-2011 Julian Kleinhans <typo3@kj187.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 require_once(t3lib_extMgm::extPath('recycler', 'classes/helper/class.tx_recycler_helper.php'));
26
27 /**
28 * Model class for the 'recycler' extension.
29 *
30 * @author Julian Kleinhans <typo3@kj187.de>
31 * @package TYPO3
32 * @subpackage tx_recycler
33 * @version $Id$
34 */
35 class tx_recycler_model_deletedRecords {
36 /**
37 * Array with all deleted rows
38 * @var array
39 */
40 protected $deletedRows = array();
41
42 /**
43 * String with the global limit
44 * @var string
45 */
46 protected $limit = '';
47
48 /**
49 * Array with all avaiable FE tables
50 * @var array
51 */
52 protected $table = array();
53
54 /**
55 * Object from helper class
56 * @var tx_recycler_helper
57 */
58 protected $recyclerHelper;
59
60 /**
61 * Array with all label fields drom different tables
62 * @var array
63 */
64 public $label;
65
66 /**
67 * Array with all title fields drom different tables
68 * @var array
69 */
70 public $title;
71
72
73 /************************************************************
74 * GET DATA FUNCTIONS
75 *
76 *
77 ************************************************************/
78
79 /**
80 * Load all deleted rows from $table
81 * If table is not set, it iterates the TCA tables
82 *
83 * @param integer $id: UID from selected page
84 * @param string $table: Tablename
85 * @param integer $depth: How many levels recursive
86 * @param integer $limit: MySQL LIMIT
87 * @param string $filter: Filter text
88 * @return recycler_model_delRecords
89 */
90 public function loadData($id, $table, $depth, $limit='', $filter = '') {
91 // set the limit
92 $this->limit = trim($limit);
93
94 if ($table) {
95 if (array_key_exists($table, $GLOBALS['TCA'])) {
96 $this->table[] = $table;
97 $this->setData($id, $table, $depth, $GLOBALS['TCA'][$table]['ctrl'], $filter);
98 }
99 } else {
100 foreach ($GLOBALS['TCA'] as $tableKey => $tableValue) {
101 // only go into this table if the limit allows it
102 if ($this->limit != '') {
103 $parts = t3lib_div::trimExplode(',', $this->limit);
104
105 // abort loop if LIMIT 0,0
106 if ($parts[0] == 0 && $parts[1] == 0) {
107 break;
108 }
109 }
110
111 $this->table[] = $tableKey;
112 $this->setData($id, $tableKey, $depth, $tableValue['ctrl'], $filter);
113 }
114 }
115
116 return $this;
117 }
118
119 /**
120 * Find the total count of deleted records
121 *
122 * @param integer $id: UID from record
123 * @param string $table: Tablename from record
124 * @param integer $depth: How many levels recursive
125 * @param string $filter: Filter text
126 * @return void
127 */
128 public function getTotalCount($id, $table, $depth, $filter) {
129 $deletedRecords = $this->loadData($id, $table, $depth, '', $filter)->getDeletedRows();
130 $countTotal = 0;
131
132 foreach($this->table as $tableName) {
133 $countTotal += count($deletedRecords[$tableName]);
134 }
135
136 return $countTotal;
137 }
138
139 /**
140 * Set all deleted rows
141 *
142 * @param integer $id: UID from record
143 * @param string $table: Tablename from record
144 * @param integer $depth: How many levels recursive
145 * @param array $ctrl: TCA CTRL Array
146 * @param string $filter: Filter text
147 * @return void
148 */
149 protected function setData($id = 0, $table, $depth, $tcaCtrl, $filter) {
150 $id = intval($id);
151
152 if (array_key_exists('delete', $tcaCtrl)) {
153 // find the 'deleted' field for this table
154 $deletedField = tx_recycler_helper::getDeletedField($table);
155
156 // create the filter WHERE-clause
157 if (trim($filter) != '') {
158 $filterWhere = ' AND (' .
159 (t3lib_div::testInt($filter) ? 'uid = ' . $filter . ' OR pid = ' . $filter . ' OR ' : '') .
160 $tcaCtrl['label'] . ' LIKE "%' . $this->escapeValueForLike($filter, $table) . '%"' .
161 ')';
162 }
163
164 // get the limit
165 if ($this->limit != '') {
166 // count the number of deleted records for this pid
167 $deletedCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
168 'uid',
169 $table,
170 $deletedField . '!=0 AND pid = ' . $id . $filterWhere
171 );
172
173 // split the limit
174 $parts = t3lib_div::trimExplode(',', $this->limit);
175 $offset = $parts[0];
176 $rowCount = $parts[1];
177
178 // subtract the number of deleted records from the limit's offset
179 $result = $offset - $deletedCount;
180
181 // if the result is >= 0
182 if ($result >= 0) {
183 // store the new offset in the limit and go into the next depth
184 $offset = $result;
185 $this->limit = implode(',', array($offset, $rowCount));
186
187 // do NOT query this depth; limit also does not need to be set, we set it anyways
188 $allowQuery = false;
189 $allowDepth = true;
190 $limit = ''; // won't be queried anyways
191 // if the result is < 0
192 } else {
193 // the offset for the temporary limit has to remain like the original offset
194 // in case the original offset was just crossed by the amount of deleted records
195 if ($offset != 0) {
196 $tempOffset = $offset;
197 } else {
198 $tempOffset = 0;
199 }
200
201 // set the offset in the limit to 0
202 $newOffset = 0;
203
204 // convert to negative result to the positive equivalent
205 $absResult = abs($result);
206
207 // if the result now is > limit's row count
208 if ($absResult > $rowCount) {
209 // use the limit's row count as the temporary limit
210 $limit = implode(',', array($tempOffset, $rowCount));
211
212 // set the limit's row count to 0
213 $this->limit = implode(',', array($newOffset, 0));
214
215 // do not go into new depth
216 $allowDepth = false;
217 } else {
218 // if the result now is <= limit's row count
219 // use the result as the temporary limit
220 $limit = implode(',', array($tempOffset, $absResult));
221
222 // subtract the result from the row count
223 $newCount = $rowCount - $absResult;
224
225 // store the new result in the limit's row count
226 $this->limit = implode(',', array($newOffset, $newCount));
227
228 // if the new row count is > 0
229 if ($newCount > 0) {
230 // go into new depth
231 $allowDepth = true;
232 } else {
233 // if the new row count is <= 0 (only =0 makes sense though)
234 // do not go into new depth
235 $allowDepth = false;
236 }
237 }
238
239 // allow query for this depth
240 $allowQuery = true;
241 }
242 } else {
243 $limit = '';
244 $allowDepth = true;
245 $allowQuery = true;
246 }
247
248 // query for actual deleted records
249 if ($allowQuery) {
250 $recordsToCheck = t3lib_BEfunc::getRecordsByField(
251 $table,
252 $deletedField,
253 '1',
254 ' AND pid = ' . $id . $filterWhere ,
255 '',
256 '',
257 $limit,
258 false
259 );
260 if ($recordsToCheck) {
261 $this->checkRecordAccess($table, $recordsToCheck);
262 }
263 }
264
265 // go into depth
266 if ($allowDepth && $depth >= 1) {
267 // check recursively for elements beneath this page
268 $resPages = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . $id, '', 'sorting');
269 if (is_resource($resPages)) {
270 while ($rowPages = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resPages)) {
271 $this->setData($rowPages['uid'], $table, $depth - 1, $tcaCtrl, $filter);
272
273 // some records might have been added, check if we still have the limit for further queries
274 if ('' != $this->limit) {
275 $parts = t3lib_div::trimExplode(',', $this->limit);
276
277 // abort loop if LIMIT 0,0
278 if ($parts[0] == 0 && $parts[1] == 0) {
279 break;
280 }
281 }
282 }
283 $GLOBALS['TYPO3_DB']->sql_free_result($resPages);
284 }
285 }
286
287 $this->label[$table] = $tcaCtrl['label'];
288 $this->title[$table] = $tcaCtrl['title'];
289 }
290 }
291
292 /**
293 * Checks whether the current backend user has access to the given records.
294 *
295 * @param string $table: Name of the table
296 * @param array $rows: Record row
297 * @return void
298 */
299 protected function checkRecordAccess($table, array $rows) {
300 foreach ($rows as $key => $row) {
301 if (tx_recycler_helper::checkAccess($table, $row)) {
302 $this->setDeletedRows($table, $row);
303 }
304 }
305 }
306
307 /**
308 * Escapes a value to be used for like in a database query.
309 * There is a special handling for the characters '%' and '_'.
310 *
311 * @param string $value: The value to be escaped for like conditions
312 * @paran string $tableName: The name of the table the query should be used for
313 * @return string The escaped value to be used for like conditions
314 */
315 protected function escapeValueForLike($value, $tableName) {
316 return $GLOBALS['TYPO3_DB']->escapeStrForLike(
317 $GLOBALS['TYPO3_DB']->quoteStr($value, $tableName),
318 $tableName
319 );
320 }
321
322
323 /************************************************************
324 * DELETE FUNCTIONS
325 ************************************************************/
326
327 /**
328 * Delete element from any table
329 *
330 * @param string $recordArray: Representation of the records
331 * @return void
332 */
333 public function deleteData($recordsArray) {
334 $recordsArray = json_decode($recordsArray);
335 if (is_array($recordsArray)) {
336 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
337 $tce->start('', '');
338 $tce->disableDeleteClause();
339 foreach ($recordsArray as $key => $record) {
340 $tce->deleteEl($record[0], $record[1], true, true);
341 }
342 return true;
343 }
344 return false;
345 }
346
347
348 /************************************************************
349 * UNDELETE FUNCTIONS
350 ************************************************************/
351
352 /**
353 * Undelete records
354 * If $recursive is true all records below the page uid would be undelete too
355 *
356 * @param string $recordArray: Representation of the records
357 * @param boolean $recursive: true/false
358 * @return boolean
359 */
360 public function undeleteData($recordsArray, $recursive = false) {
361 require_once PATH_t3lib . 'class.t3lib_tcemain.php';
362 $result = false;
363 $depth = 999;
364
365 $recordsArray = json_decode($recordsArray);
366
367 if (is_array($recordsArray)) {
368 $this->deletedRows = array();
369 $cmd = array();
370
371 foreach ($recordsArray as $key => $row) {
372 $cmd[$row[0]][$row[1]]['undelete'] = 1;
373 if ($row[0] == 'pages' && $recursive == true) {
374 $this->loadData($row[1], '', $depth, '');
375 $childRecords = $this->getDeletedRows();
376 if (count($childRecords)>0) {
377 foreach ($childRecords as $table => $childRows) {
378 foreach ($childRows as $childKey => $childRow) {
379 $cmd[$table][$childRow['uid']]['undelete'] = 1;
380 }
381 }
382 }
383 }
384 }
385
386 if ($cmd) {
387 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
388 $tce->start(array(), $cmd);
389 $tce->process_cmdmap();
390 $result = true;
391 }
392 }
393
394 return $result;
395 }
396
397
398 /************************************************************
399 * SETTER FUNCTIONS
400 ************************************************************/
401
402 /**
403 * Set deleted rows
404 *
405 * @param string $table: Tablename
406 * @param array $row: Deleted record row
407 * @return void
408 */
409 public function setDeletedRows($table, array $row) {
410 $this->deletedRows[$table][] = $row;
411 }
412
413
414 /************************************************************
415 * GETTER FUNCTIONS
416 ************************************************************/
417
418 /**
419 * Get deleted Rows
420 *
421 * @return array $this->deletedRows: Array with all deleted rows from TCA
422 */
423 public function getDeletedRows() {
424 return $this->deletedRows;
425 }
426
427 /**
428 * Get table
429 *
430 * @return array $this->table: Array with table from TCA
431 */
432 public function getTable() {
433 return $this->table;
434 }
435 }
436
437 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/recycler/classes/model/class.tx_recycler_model_deletedRecords.php'])) {
438 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/recycler/classes/model/class.tx_recycler_model_deletedRecords.php']);
439 }
440
441 ?>