TYPO3 API  SVNRelease
class.tx_recycler_model_deletedRecords.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2009-2011 Julian Kleinhans <typo3@kj187.de>
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *
00017 *  This script is distributed in the hope that it will be useful,
00018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *  GNU General Public License for more details.
00021 *
00022 *  This copyright notice MUST APPEAR in all copies of the script!
00023 ***************************************************************/
00024 
00025 require_once(t3lib_extMgm::extPath('recycler', 'classes/helper/class.tx_recycler_helper.php'));
00026 
00027 /**
00028  * Model class for the 'recycler' extension.
00029  *
00030  * @author  Julian Kleinhans <typo3@kj187.de>
00031  * @package TYPO3
00032  * @subpackage  tx_recycler
00033  * @version $Id: class.tx_recycler_model_deletedRecords.php 10120 2011-01-18 20:03:36Z ohader $
00034  */
00035 class tx_recycler_model_deletedRecords {
00036     /**
00037      * Array with all deleted rows
00038      * @var array
00039      */
00040     protected $deletedRows = array();
00041 
00042     /**
00043      * String with the global limit
00044      * @var string
00045      */
00046     protected $limit = '';
00047 
00048     /**
00049      * Array with all avaiable FE tables
00050      * @var array
00051      */
00052     protected $table = array();
00053 
00054     /**
00055      * Object from helper class
00056      * @var tx_recycler_helper
00057      */
00058     protected $recyclerHelper;
00059 
00060     /**
00061      * Array with all label fields drom different tables
00062      * @var array
00063      */
00064     public $label;
00065 
00066     /**
00067      * Array with all title fields drom different tables
00068      * @var array
00069      */
00070     public $title;
00071 
00072 
00073     /************************************************************
00074      * GET DATA FUNCTIONS
00075      *
00076      *
00077      ************************************************************/
00078 
00079     /**
00080      * Load all deleted rows from $table
00081      * If table is not set, it iterates the TCA tables
00082      *
00083      * @param   integer     $id: UID from selected page
00084      * @param   string      $table: Tablename
00085      * @param   integer     $depth: How many levels recursive
00086      * @param   integer     $limit: MySQL LIMIT
00087      * @param   string      $filter: Filter text
00088      * @return  recycler_model_delRecords
00089      */
00090     public function loadData($id, $table, $depth, $limit='', $filter = '') {
00091         // set the limit
00092         $this->limit = trim($limit);
00093 
00094         if ($table) {
00095             if (array_key_exists($table, $GLOBALS['TCA'])) {
00096                 $this->table[] = $table;
00097                 $this->setData($id, $table, $depth, $GLOBALS['TCA'][$table]['ctrl'], $filter);
00098             }
00099         } else {
00100             foreach ($GLOBALS['TCA'] as $tableKey => $tableValue) {
00101                 // only go into this table if the limit allows it
00102                 if ($this->limit != '') {
00103                     $parts = t3lib_div::trimExplode(',', $this->limit);
00104 
00105                     // abort loop if LIMIT 0,0
00106                     if ($parts[0] == 0 && $parts[1] == 0) {
00107                         break;
00108                     }
00109                 }
00110 
00111                 $this->table[] = $tableKey;
00112                 $this->setData($id, $tableKey, $depth, $tableValue['ctrl'], $filter);
00113             }
00114         }
00115 
00116         return $this;
00117     }
00118 
00119     /**
00120      * Find the total count of deleted records
00121      *
00122      * @param   integer     $id: UID from record
00123      * @param   string      $table: Tablename from record
00124      * @param   integer     $depth: How many levels recursive
00125      * @param   string      $filter: Filter text
00126      * @return  void
00127      */
00128     public function getTotalCount($id, $table, $depth, $filter) {
00129         $deletedRecords = $this->loadData($id, $table, $depth, '', $filter)->getDeletedRows();
00130         $countTotal = 0;
00131 
00132         foreach($this->table as $tableName) {
00133             $countTotal += count($deletedRecords[$tableName]);
00134         }
00135 
00136         return $countTotal;
00137     }
00138 
00139     /**
00140      * Set all deleted rows
00141      *
00142      * @param   integer     $id: UID from record
00143      * @param   string      $table: Tablename from record
00144      * @param   integer     $depth: How many levels recursive
00145      * @param   array       $ctrl: TCA CTRL Array
00146      * @param   string      $filter: Filter text
00147      * @return  void
00148      */
00149     protected function setData($id = 0, $table, $depth, $tcaCtrl, $filter) {
00150         $id = intval($id);
00151 
00152         if (array_key_exists('delete', $tcaCtrl)) {
00153                 // find the 'deleted' field for this table
00154             $deletedField = tx_recycler_helper::getDeletedField($table);
00155 
00156                 // create the filter WHERE-clause
00157             if (trim($filter) != '') {
00158                 $filterWhere = ' AND (' .
00159                     (t3lib_div::testInt($filter) ? 'uid = ' . $filter . ' OR pid = ' . $filter . ' OR ' : '') .
00160                     $tcaCtrl['label'] . ' LIKE "%' . $this->escapeValueForLike($filter, $table) . '%"' .
00161                 ')';
00162             }
00163 
00164                 // get the limit
00165             if ($this->limit != '') {
00166                     // count the number of deleted records for this pid
00167                 $deletedCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
00168                     'uid',
00169                     $table,
00170                     $deletedField . '!=0 AND pid = ' . $id . $filterWhere
00171                 );
00172 
00173                     // split the limit
00174                 $parts = t3lib_div::trimExplode(',', $this->limit);
00175                 $offset = $parts[0];
00176                 $rowCount = $parts[1];
00177 
00178                     // subtract the number of deleted records from the limit's offset
00179                 $result = $offset - $deletedCount;
00180 
00181                     // if the result is >= 0
00182                 if ($result >= 0) {
00183                         // store the new offset in the limit and go into the next depth
00184                     $offset = $result;
00185                     $this->limit = implode(',', array($offset, $rowCount));
00186 
00187                         // do NOT query this depth; limit also does not need to be set, we set it anyways
00188                     $allowQuery = false;
00189                     $allowDepth = true;
00190                     $limit = ''; // won't be queried anyways
00191                     // if the result is < 0
00192                 } else {
00193                         // the offset for the temporary limit has to remain like the original offset
00194                         // in case the original offset was just crossed by the amount of deleted records
00195                     if ($offset != 0) {
00196                         $tempOffset = $offset;
00197                     } else {
00198                         $tempOffset = 0;
00199                     }
00200 
00201                         // set the offset in the limit to 0
00202                     $newOffset = 0;
00203 
00204                         // convert to negative result to the positive equivalent
00205                     $absResult = abs($result);
00206 
00207                         // if the result now is > limit's row count
00208                     if ($absResult > $rowCount) {
00209                             // use the limit's row count as the temporary limit
00210                         $limit = implode(',', array($tempOffset, $rowCount));
00211 
00212                             // set the limit's row count to 0
00213                         $this->limit = implode(',', array($newOffset, 0));
00214 
00215                             // do not go into new depth
00216                         $allowDepth = false;
00217                     } else {
00218                             // if the result now is <= limit's row count
00219                             // use the result as the temporary limit
00220                         $limit = implode(',', array($tempOffset, $absResult));
00221 
00222                             // subtract the result from the row count
00223                         $newCount = $rowCount - $absResult;
00224 
00225                             // store the new result in the limit's row count
00226                         $this->limit = implode(',', array($newOffset, $newCount));
00227 
00228                             // if the new row count is > 0
00229                         if ($newCount > 0) {
00230                             // go into new depth
00231                             $allowDepth = true;
00232                         } else {
00233                                 // if the new row count is <= 0 (only =0 makes sense though)
00234                                 // do not go into new depth
00235                             $allowDepth = false;
00236                         }
00237                     }
00238 
00239                         // allow query for this depth
00240                     $allowQuery = true;
00241                 }
00242             } else {
00243                 $limit = '';
00244                 $allowDepth = true;
00245                 $allowQuery = true;
00246             }
00247 
00248                 // query for actual deleted records
00249             if ($allowQuery) {
00250                 $recordsToCheck = t3lib_BEfunc::getRecordsByField(
00251                     $table,
00252                     $deletedField,
00253                     '1',
00254                     ' AND pid = ' . $id . $filterWhere ,
00255                     '',
00256                     '',
00257                     $limit,
00258                     false
00259                 );
00260                 if ($recordsToCheck) {
00261                     $this->checkRecordAccess($table, $recordsToCheck);
00262                 }
00263             }
00264 
00265                 // go into depth
00266             if ($allowDepth && $depth >= 1) {
00267                     // check recursively for elements beneath this page
00268                 $resPages = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . $id, '', 'sorting');
00269                 if (is_resource($resPages)) {
00270                     while ($rowPages = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resPages)) {
00271                         $this->setData($rowPages['uid'], $table, $depth - 1, $tcaCtrl, $filter);
00272 
00273                             // some records might have been added, check if we still have the limit for further queries
00274                         if ('' != $this->limit) {
00275                             $parts = t3lib_div::trimExplode(',', $this->limit);
00276 
00277                                 // abort loop if LIMIT 0,0
00278                             if ($parts[0] == 0 && $parts[1] == 0) {
00279                                 break;
00280                             }
00281                         }
00282                     }
00283                     $GLOBALS['TYPO3_DB']->sql_free_result($resPages);
00284                 }
00285             }
00286 
00287             $this->label[$table] = $tcaCtrl['label'];
00288             $this->title[$table] = $tcaCtrl['title'];
00289         }
00290     }
00291 
00292     /**
00293      * Checks whether the current backend user has access to the given records.
00294      *
00295      * @param   string      $table: Name of the table
00296      * @param   array       $rows: Record row
00297      * @return  void
00298      */
00299     protected function checkRecordAccess($table, array $rows) {
00300         foreach ($rows as $key => $row) {
00301             if (tx_recycler_helper::checkAccess($table, $row)) {
00302                 $this->setDeletedRows($table, $row);
00303             }
00304         }
00305     }
00306 
00307     /**
00308      * Escapes a value to be used for like in a database query.
00309      * There is a special handling for the characters '%' and '_'.
00310      *
00311      * @param   string      $value: The value to be escaped for like conditions
00312      * @paran   string      $tableName: The name of the table the query should be used for
00313      * @return  string      The escaped value to be used for like conditions
00314      */
00315     protected function escapeValueForLike($value, $tableName) {
00316         return $GLOBALS['TYPO3_DB']->escapeStrForLike(
00317             $GLOBALS['TYPO3_DB']->quoteStr($value, $tableName),
00318             $tableName
00319         );
00320     }
00321 
00322 
00323     /************************************************************
00324      * DELETE FUNCTIONS
00325      ************************************************************/
00326 
00327     /**
00328      * Delete element from any table
00329      *
00330      * @param   string      $recordArray: Representation of the records
00331      * @return  void
00332      */
00333     public function deleteData($recordsArray) {
00334         $recordsArray = json_decode($recordsArray);
00335         if (is_array($recordsArray)) {
00336             $tce = t3lib_div::makeInstance('t3lib_TCEmain');
00337             $tce->start('', '');
00338             $tce->disableDeleteClause();
00339             foreach ($recordsArray as $key => $record) {
00340                 $tce->deleteEl($record[0], $record[1], true, true);
00341             }
00342             return true;
00343         }
00344         return false;
00345     }
00346 
00347 
00348     /************************************************************
00349      * UNDELETE FUNCTIONS
00350      ************************************************************/
00351 
00352     /**
00353      * Undelete records
00354      * If $recursive is true all records below the page uid would be undelete too
00355      *
00356      * @param   string      $recordArray: Representation of the records
00357      * @param   boolean     $recursive: true/false
00358      * @return  boolean
00359      */
00360     public function undeleteData($recordsArray, $recursive = false) {
00361         require_once PATH_t3lib . 'class.t3lib_tcemain.php';
00362         $result = false;
00363         $depth = 999;
00364 
00365         $recordsArray = json_decode($recordsArray);
00366 
00367         if (is_array($recordsArray)) {
00368             $this->deletedRows = array();
00369             $cmd = array();
00370 
00371             foreach ($recordsArray as $key => $row) {
00372                 $cmd[$row[0]][$row[1]]['undelete'] = 1;
00373                 if ($row[0] == 'pages' && $recursive == true) {
00374                     $this->loadData($row[1], '', $depth, '');
00375                     $childRecords = $this->getDeletedRows();
00376                     if (count($childRecords)>0) {
00377                         foreach ($childRecords as $table => $childRows) {
00378                             foreach ($childRows as $childKey => $childRow) {
00379                                 $cmd[$table][$childRow['uid']]['undelete'] = 1;
00380                             }
00381                         }
00382                     }
00383                 }
00384             }
00385 
00386             if ($cmd) {
00387                 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
00388                 $tce->start(array(), $cmd);
00389                 $tce->process_cmdmap();
00390                 $result = true;
00391             }
00392         }
00393 
00394         return $result;
00395     }
00396 
00397 
00398     /************************************************************
00399      * SETTER FUNCTIONS
00400      ************************************************************/
00401 
00402     /**
00403      * Set deleted rows
00404      *
00405      * @param   string      $table: Tablename
00406      * @param   array       $row: Deleted record row
00407      * @return  void
00408      */
00409     public function setDeletedRows($table, array $row) {
00410         $this->deletedRows[$table][] = $row;
00411     }
00412 
00413 
00414     /************************************************************
00415      * GETTER FUNCTIONS
00416      ************************************************************/
00417 
00418     /**
00419      * Get deleted Rows
00420      *
00421      * @return  array       $this->deletedRows: Array with all deleted rows from TCA
00422      */
00423     public function getDeletedRows() {
00424         return $this->deletedRows;
00425     }
00426 
00427     /**
00428      * Get table
00429      *
00430      * @return  array       $this->table: Array with table from TCA
00431      */
00432     public function getTable() {
00433         return $this->table;
00434     }
00435 }
00436 
00437 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/recycler/classes/model/class.tx_recycler_model_deletedRecords.php'])) {
00438     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/recycler/classes/model/class.tx_recycler_model_deletedRecords.php']);
00439 }
00440 
00441 ?>