TYPO3 API  SVNRelease
class.lost_files.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
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 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Cleaner module: Lost files
00029  * User function called from tx_lowlevel_cleaner_core configured in ext_localconf.php
00030  *
00031  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00032  */
00033 /**
00034  * [CLASS/FUNCTION INDEX of SCRIPT]
00035  *
00036  *
00037  *
00038  *   56: class tx_lowlevel_lost_files extends tx_lowlevel_cleaner_core
00039  *   65:     function tx_lowlevel_lost_files()
00040  *  103:     function main()
00041  *  181:     function main_autoFix($resultArray)
00042  *
00043  * TOTAL FUNCTIONS: 3
00044  * (This index is automatically created/updated by the extension "extdeveval")
00045  *
00046  */
00047 
00048 
00049 /**
00050  * Looking for Lost files
00051  *
00052  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00053  * @package TYPO3
00054  * @subpackage tx_lowlevel
00055  */
00056 class tx_lowlevel_lost_files extends tx_lowlevel_cleaner_core {
00057 
00058     var $checkRefIndex = TRUE;
00059 
00060     /**
00061      * Constructor
00062      *
00063      * @return  void
00064      */
00065     function tx_lowlevel_lost_files()   {
00066         parent::tx_lowlevel_cleaner_core();
00067 
00068         $this->cli_options[] = array('--excludePath [path-list]', 'Comma separated list of paths to exclude. Example: "uploads/[path1],uploads/[path2],..."');
00069 
00070             // Setting up help:
00071         $this->cli_help['name'] = 'lost_files -- Looking for files in the uploads/ folder which does not have a reference in TYPO3 managed records.';
00072         $this->cli_help['description'] = trim('
00073 Assumptions:
00074 - a perfect integrity of the reference index table (always update the reference index table before using this tool!)
00075 - that all contents in the uploads folder are files attached to TCA records and exclusively managed by TCEmain through "group" type fields
00076 - exceptions are: index.html and .htaccess files (ignored)
00077 - exceptions are: RTEmagic* image files (ignored)
00078 - files found in deleted records are included (otherwise you would see a false list of lost files)
00079 
00080 The assumptions are not requirements by the TYPO3 API but reflects the de facto implementation of most TYPO3 installations and therefore a practical approach to cleaning up the uploads/ folder.
00081 Therefore, if all "group" type fields in TCA and flexforms are positioned inside the uploads/ folder and if no files inside are managed manually it should be safe to clean out files with no relations found in the system.
00082 Under such circumstances there should theoretically be no lost files in the uploads/ folder since TCEmain should have managed relations automatically including adding and deleting files.
00083 However, there is at least one reason known to why files might be found lost and that is when FlexForms are used. In such a case a change of/in the Data Structure XML (or the ability of the system to find the Data Structure definition!) used for the flexform could leave lost files behind. This is not unlikely to happen when records are deleted. More details can be found in a note to the function t3lib_BEfunc::getFlexFormDS()
00084 Another scenario could of course be de-installation of extensions which managed files in the uploads/ folders.
00085 
00086 Automatic Repair of Errors:
00087 - Simply delete lost files (Warning: First, make sure those files are not used somewhere TYPO3 does not know about! See the assumptions above).
00088 ');
00089 
00090         $this->cli_help['examples'] = '/.../cli_dispatch.phpsh lowlevel_cleaner lost_files -s -r
00091 Will report lost files.';
00092     }
00093 
00094 
00095     /**
00096      * Find lost files in uploads/ folder
00097      * FIX METHOD: Simply delete the file...
00098      *
00099      * TODO: Add parameter to exclude filepath
00100      * TODO: Add parameter to list more file names/patterns to ignore
00101      * TODO: Add parameter to include RTEmagic images
00102      *
00103      * @return  array
00104      */
00105     function main() {
00106         global $TYPO3_DB;
00107 
00108             // Initialize result array:
00109         $resultArray = array(
00110             'message' => $this->cli_help['name'].LF.LF.$this->cli_help['description'],
00111             'headers' => array(
00112                 'managedFiles' => array('Files related to TYPO3 records and managed by TCEmain','These files you definitely want to keep.',0),
00113                 'ignoredFiles' => array('Ignored files (index.html, .htaccess etc.)','These files are allowed in uploads/ folder',0),
00114                 'RTEmagicFiles' => array('RTE magic images - those found (and ignored)','These files are also allowed in some uploads/ folders as RTEmagic images.',0),
00115                 'lostFiles' => array('Lost files - those you can delete','You can delete these files!',3),
00116                 'warnings' => array('Warnings picked up','',2)
00117             ),
00118             'managedFiles' => array(),
00119             'ignoredFiles' => array(),
00120             'RTEmagicFiles' => array(),
00121             'lostFiles' => array(),
00122             'warnings' => array()
00123         );
00124 
00125             // Get all files:
00126         $fileArr = array();
00127         $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,PATH_site.'uploads/');
00128         $fileArr = t3lib_div::removePrefixPathFromList($fileArr,PATH_site);
00129 
00130         $excludePaths = t3lib_div::trimExplode(',',$this->cli_argValue('--excludePath',0),1);
00131 
00132             // Traverse files and for each, look up if its found in the reference index.
00133         foreach($fileArr as $key => $value) {
00134 
00135             $include = TRUE;
00136             foreach($excludePaths as $exclPath) {
00137                 if (t3lib_div::isFirstPartOfStr($value,$exclPath))  {
00138                     $include = FALSE;
00139                 }
00140             }
00141 
00142             $shortKey = t3lib_div::shortmd5($value);
00143 
00144             if ($include)   {
00145                     // First, allow "index.html", ".htaccess" files since they are often used for good reasons
00146                 if (substr($value,-11) == '/index.html' || substr($value,-10) == '/.htaccess')  {
00147                     unset($fileArr[$key])   ;
00148                     $resultArray['ignoredFiles'][$shortKey] = $value;
00149                 } else {
00150                         // Looking for a reference from a field which is NOT a soft reference (thus, only fields with a proper TCA/Flexform configuration)
00151                     $recs = $TYPO3_DB->exec_SELECTgetRows(
00152                         '*',
00153                         'sys_refindex',
00154                         'ref_table='.$TYPO3_DB->fullQuoteStr('_FILE', 'sys_refindex').
00155                             ' AND ref_string='.$TYPO3_DB->fullQuoteStr($value, 'sys_refindex').
00156                             ' AND softref_key='.$TYPO3_DB->fullQuoteStr('', 'sys_refindex'),
00157                         '',
00158                         'sorting DESC'
00159                     );
00160 
00161                         // If found, unset entry:
00162                     if (count($recs))       {
00163                         unset($fileArr[$key])   ;
00164                         $resultArray['managedFiles'][$shortKey] = $value;
00165                         if (count($recs)>1) {
00166                             $resultArray['warnings'][$shortKey] = 'Warning: File "'.$value.'" had '.count($recs).' references from group-fields, should have only one!';
00167                         }
00168                     } else {
00169                             // When here it means the file was not found. So we test if it has a RTEmagic-image name and if so, we allow it:
00170                         if (preg_match('/^RTEmagic[P|C]_/',basename($value)))   {
00171                             unset($fileArr[$key])   ;
00172                             $resultArray['RTEmagicFiles'][$shortKey] = $value;
00173                         } else {
00174                                 // We conclude that the file is lost...:
00175                             unset($fileArr[$key])   ;
00176                             $resultArray['lostFiles'][$shortKey] = $value;
00177                         }
00178                     }
00179                 }
00180             }
00181         }
00182 
00183         asort($resultArray['ignoredFiles']);
00184         asort($resultArray['managedFiles']);
00185         asort($resultArray['RTEmagicFiles']);
00186         asort($resultArray['lostFiles']);
00187         asort($resultArray['warnings']);
00188 
00189         // $fileArr variable should now be empty with all contents transferred to the result array keys.
00190 
00191 
00192         return $resultArray;
00193     }
00194 
00195     /**
00196      * Mandatory autofix function
00197      * Will run auto-fix on the result array. Echos status during processing.
00198      *
00199      * @param   array       Result array from main() function
00200      * @return  void
00201      */
00202     function main_autoFix($resultArray) {
00203         foreach($resultArray['lostFiles'] as $key => $value)    {
00204             $absFileName = t3lib_div::getFileAbsFileName($value);
00205             echo 'Deleting file: "'.$absFileName.'": ';
00206             if ($bypass = $this->cli_noExecutionCheck($absFileName))    {
00207                 echo $bypass;
00208             } else {
00209                 if ($absFileName && @is_file($absFileName)) {
00210                     unlink($absFileName);
00211                     echo 'DONE';
00212                 } else {
00213                     echo '  ERROR: File "'.$absFileName.'" was not found!';
00214                 }
00215             }
00216             echo LF;
00217         }
00218     }
00219 }
00220 
00221 ?>