Cleanup: Updated copyright comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / lowlevel / clmods / class.lost_files.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
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 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Cleaner module: Lost files
29 * User function called from tx_lowlevel_cleaner_core configured in ext_localconf.php
30 *
31 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
32 */
33 /**
34 * [CLASS/FUNCTION INDEX of SCRIPT]
35 *
36 *
37 *
38 * 56: class tx_lowlevel_lost_files extends tx_lowlevel_cleaner_core
39 * 65: function tx_lowlevel_lost_files()
40 * 103: function main()
41 * 181: function main_autoFix($resultArray)
42 *
43 * TOTAL FUNCTIONS: 3
44 * (This index is automatically created/updated by the extension "extdeveval")
45 *
46 */
47
48
49 /**
50 * Looking for Lost files
51 *
52 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
53 * @package TYPO3
54 * @subpackage tx_lowlevel
55 */
56 class tx_lowlevel_lost_files extends tx_lowlevel_cleaner_core {
57
58 var $checkRefIndex = TRUE;
59
60 /**
61 * Constructor
62 *
63 * @return void
64 */
65 function tx_lowlevel_lost_files() {
66 parent::tx_lowlevel_cleaner_core();
67
68 $this->cli_options[] = array('--excludePath [path-list]', 'Comma separated list of paths to exclude. Example: "uploads/[path1],uploads/[path2],..."');
69
70 // Setting up help:
71 $this->cli_help['name'] = 'lost_files -- Looking for files in the uploads/ folder which does not have a reference in TYPO3 managed records.';
72 $this->cli_help['description'] = trim('
73 Assumptions:
74 - a perfect integrity of the reference index table (always update the reference index table before using this tool!)
75 - that all contents in the uploads folder are files attached to TCA records and exclusively managed by TCEmain through "group" type fields
76 - exceptions are: index.html and .htaccess files (ignored)
77 - exceptions are: RTEmagic* image files (ignored)
78 - files found in deleted records are included (otherwise you would see a false list of lost files)
79
80 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.
81 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.
82 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.
83 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()
84 Another scenario could of course be de-installation of extensions which managed files in the uploads/ folders.
85
86 Automatic Repair of Errors:
87 - Simply delete lost files (Warning: First, make sure those files are not used somewhere TYPO3 does not know about! See the assumptions above).
88 ');
89
90 $this->cli_help['examples'] = '/.../cli_dispatch.phpsh lowlevel_cleaner lost_files -s -r
91 Will report lost files.';
92 }
93
94
95 /**
96 * Find lost files in uploads/ folder
97 * FIX METHOD: Simply delete the file...
98 *
99 * TODO: Add parameter to exclude filepath
100 * TODO: Add parameter to list more file names/patterns to ignore
101 * TODO: Add parameter to include RTEmagic images
102 *
103 * @return array
104 */
105 function main() {
106 global $TYPO3_DB;
107
108 // Initialize result array:
109 $resultArray = array(
110 'message' => $this->cli_help['name'].LF.LF.$this->cli_help['description'],
111 'headers' => array(
112 'managedFiles' => array('Files related to TYPO3 records and managed by TCEmain','These files you definitely want to keep.',0),
113 'ignoredFiles' => array('Ignored files (index.html, .htaccess etc.)','These files are allowed in uploads/ folder',0),
114 'RTEmagicFiles' => array('RTE magic images - those found (and ignored)','These files are also allowed in some uploads/ folders as RTEmagic images.',0),
115 'lostFiles' => array('Lost files - those you can delete','You can delete these files!',3),
116 'warnings' => array('Warnings picked up','',2)
117 ),
118 'managedFiles' => array(),
119 'ignoredFiles' => array(),
120 'RTEmagicFiles' => array(),
121 'lostFiles' => array(),
122 'warnings' => array()
123 );
124
125 // Get all files:
126 $fileArr = array();
127 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,PATH_site.'uploads/');
128 $fileArr = t3lib_div::removePrefixPathFromList($fileArr,PATH_site);
129
130 $excludePaths = t3lib_div::trimExplode(',',$this->cli_argValue('--excludePath',0),1);
131
132 // Traverse files and for each, look up if its found in the reference index.
133 foreach($fileArr as $key => $value) {
134
135 $include = TRUE;
136 foreach($excludePaths as $exclPath) {
137 if (t3lib_div::isFirstPartOfStr($value,$exclPath)) {
138 $include = FALSE;
139 }
140 }
141
142 $shortKey = t3lib_div::shortmd5($value);
143
144 if ($include) {
145 // First, allow "index.html", ".htaccess" files since they are often used for good reasons
146 if (substr($value,-11) == '/index.html' || substr($value,-10) == '/.htaccess') {
147 unset($fileArr[$key]) ;
148 $resultArray['ignoredFiles'][$shortKey] = $value;
149 } else {
150 // Looking for a reference from a field which is NOT a soft reference (thus, only fields with a proper TCA/Flexform configuration)
151 $recs = $TYPO3_DB->exec_SELECTgetRows(
152 '*',
153 'sys_refindex',
154 'ref_table='.$TYPO3_DB->fullQuoteStr('_FILE', 'sys_refindex').
155 ' AND ref_string='.$TYPO3_DB->fullQuoteStr($value, 'sys_refindex').
156 ' AND softref_key='.$TYPO3_DB->fullQuoteStr('', 'sys_refindex'),
157 '',
158 'sorting DESC'
159 );
160
161 // If found, unset entry:
162 if (count($recs)) {
163 unset($fileArr[$key]) ;
164 $resultArray['managedFiles'][$shortKey] = $value;
165 if (count($recs)>1) {
166 $resultArray['warnings'][$shortKey] = 'Warning: File "'.$value.'" had '.count($recs).' references from group-fields, should have only one!';
167 }
168 } else {
169 // 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:
170 if (preg_match('/^RTEmagic[P|C]_/',basename($value))) {
171 unset($fileArr[$key]) ;
172 $resultArray['RTEmagicFiles'][$shortKey] = $value;
173 } else {
174 // We conclude that the file is lost...:
175 unset($fileArr[$key]) ;
176 $resultArray['lostFiles'][$shortKey] = $value;
177 }
178 }
179 }
180 }
181 }
182
183 asort($resultArray['ignoredFiles']);
184 asort($resultArray['managedFiles']);
185 asort($resultArray['RTEmagicFiles']);
186 asort($resultArray['lostFiles']);
187 asort($resultArray['warnings']);
188
189 // $fileArr variable should now be empty with all contents transferred to the result array keys.
190
191
192 return $resultArray;
193 }
194
195 /**
196 * Mandatory autofix function
197 * Will run auto-fix on the result array. Echos status during processing.
198 *
199 * @param array Result array from main() function
200 * @return void
201 */
202 function main_autoFix($resultArray) {
203 foreach($resultArray['lostFiles'] as $key => $value) {
204 $absFileName = t3lib_div::getFileAbsFileName($value);
205 echo 'Deleting file: "'.$absFileName.'": ';
206 if ($bypass = $this->cli_noExecutionCheck($absFileName)) {
207 echo $bypass;
208 } else {
209 if ($absFileName && @is_file($absFileName)) {
210 unlink($absFileName);
211 echo 'DONE';
212 } else {
213 echo ' ERROR: File "'.$absFileName.'" was not found!';
214 }
215 }
216 echo LF;
217 }
218 }
219 }
220
221 ?>