[BUGFIX] Remove XCLASS inclusion blocks from t3lib
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_admin.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 * Contains a class for evaluation of database integrity according to $GLOBALS['TCA']
29 * Most of these functions are considered obsolete!
30 *
31 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
32 * XHTML compliant
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 */
36
37
38 /**
39 * This class holds functions used by the TYPO3 backend to check the integrity of the database (The DBint module, 'lowlevel' extension)
40 *
41 * Depends on: Depends on loaddbgroup from t3lib/
42 *
43 * @todo Need to really extend this class when the tcemain library has been updated and the whole API is better defined. There are some known bugs in this library. Further it would be nice with a facility to not only analyze but also clean up!
44 * @see SC_mod_tools_dbint_index::func_relations(), SC_mod_tools_dbint_index::func_records()
45 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
46 * @package TYPO3
47 * @subpackage t3lib
48 */
49 class t3lib_admin {
50 /** @var bool If set, genTree() includes deleted pages. This is default.*/
51 var $genTree_includeDeleted = TRUE;
52
53 /** @var bool If set, genTree() includes versionized pages/records. This is default.*/
54 var $genTree_includeVersions = TRUE;
55
56 /** @var bool If set, genTree() includes records from pages. */
57 var $genTree_includeRecords = FALSE;
58
59 /** @var string Extra where-clauses for the tree-selection */
60 var $perms_clause = '';
61
62 /** @var int If set, genTree() generates HTML, that visualizes the tree. */
63 var $genTree_makeHTML = 0;
64
65 // internal
66 /** @var array Will hold id/rec pairs from genTree() */
67 var $page_idArray = array();
68
69 /** @var array */
70 var $rec_idArray = array();
71
72 /** @var string Will hold the HTML-code visualising the tree. genTree() */
73 var $genTree_HTML = '';
74
75 /** @var string */
76 var $backPath = '';
77
78 // internal
79 /** @var array */
80 var $checkFileRefs = array();
81
82 /** @var array From the select-fields */
83 var $checkSelectDBRefs = array();
84
85 /** @var array From the group-fields */
86 var $checkGroupDBRefs = array();
87
88 /** @var array Statistics */
89 var $recStats = array(
90 'allValid' => array(),
91 'published_versions' => array(),
92 'deleted' => array(),
93 );
94
95 /** @var array */
96 var $lRecords = array();
97
98 /** @var string */
99 var $lostPagesList = '';
100
101
102 /**
103 * Generates a list of Page-uid's that corresponds to the tables in the tree. This list should ideally include all records in the pages-table.
104 *
105 * @param integer a pid (page-record id) from which to start making the tree
106 * @param string HTML-code (image-tags) used when this function calls itself recursively.
107 * @param boolean Internal variable, don't set from outside!
108 * @return void
109 */
110 function genTree($theID, $depthData, $versions = FALSE) {
111
112 if ($versions) {
113 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
114 'uid,title,doktype,deleted,t3ver_wsid,t3ver_id,t3ver_count,t3ver_swapmode' . (t3lib_extMgm::isLoaded('cms') ? ',hidden' : ''),
115 'pages',
116 'pid=-1 AND t3ver_oid=' . intval($theID) . ' ' . ((!$this->genTree_includeDeleted) ? 'AND deleted=0' : '') . $this->perms_clause,
117 '',
118 'sorting'
119 );
120 } else {
121 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
122 'uid,title,doktype,deleted' . (t3lib_extMgm::isLoaded('cms') ? ',hidden' : ''),
123 'pages',
124 'pid=' . intval($theID) . ' ' . ((!$this->genTree_includeDeleted) ? 'AND deleted=0' : '') . $this->perms_clause,
125 '',
126 'sorting'
127 );
128 }
129
130 // Traverse the records selected:
131 $a = 0;
132 $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
133 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
134
135 // Prepare the additional label used in the HTML output in case of versions:
136 if ($versions) {
137 $versionLabel = '[v1.' . $row['t3ver_id'] . '; WS#' . $row['t3ver_wsid'] . ']';
138 } else {
139 $versionLabel = '';
140 }
141
142 $a++;
143 $newID = $row['uid'];
144
145 // Build HTML output:
146 if ($this->genTree_makeHTML) {
147 $this->genTree_HTML .= LF . '<div><span class="nobr">';
148 $PM = 'join';
149 $LN = ($a == $c) ? 'blank' : 'line';
150 $BTM = ($a == $c) ? 'bottom' : '';
151 $this->genTree_HTML .= $depthData .
152 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $PM . $BTM . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' .
153 $versionLabel .
154 t3lib_iconWorks::getSpriteIconForRecord('pages', $row) .
155 htmlspecialchars($row['uid'] . ': ' . t3lib_div::fixed_lgd_cs(strip_tags($row['title']), 50)) . '</span></div>';
156 }
157
158 // Register various data for this item:
159 $this->page_idArray[$newID] = $row;
160
161 $this->recStats['all_valid']['pages'][$newID] = $newID;
162 # if ($versions) $this->recStats['versions']['pages'][$newID] = $newID;
163 if ($row['deleted']) {
164 $this->recStats['deleted']['pages'][$newID] = $newID;
165 }
166 if ($versions && $row['t3ver_count'] >= 1) {
167 $this->recStats['published_versions']['pages'][$newID] = $newID;
168 }
169
170 if ($row['deleted']) {
171 $this->recStats['deleted']++;
172 }
173 if ($row['hidden']) {
174 $this->recStats['hidden']++;
175 }
176 $this->recStats['doktype'][$row['doktype']]++;
177
178 // Create the HTML code prefix for recursive call:
179 $genHTML = $depthData . '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $LN . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' . $versionLabel;
180
181 // If all records should be shown, do so:
182 if ($this->genTree_includeRecords) {
183 foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
184 if ($tableName != 'pages') {
185 $this->genTree_records($newID, $this->genTree_HTML ? $genHTML : '', $tableName);
186 }
187 }
188 }
189
190 // Add sub pages:
191 $this->genTree($newID, $this->genTree_HTML ? $genHTML : '');
192
193 // If versions are included in the tree, add those now:
194 if ($this->genTree_includeVersions) {
195 $this->genTree($newID, $this->genTree_HTML ? $genHTML : '', TRUE);
196 }
197 }
198 }
199
200 /**
201 * @param integer a pid (page-record id) from which to start making the tree
202 * @param string HTML-code used when this function calls itself recursively.
203 * @param string Table to get the records from
204 * @param bool Internal variable, don't set from outside!
205 * @return void
206 */
207 function genTree_records($theID, $depthData, $table = '', $versions = FALSE) {
208 if ($versions) {
209 // Select all records from table pointing to this page:
210 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
211 t3lib_BEfunc::getCommonSelectFields($table),
212 $table,
213 'pid=-1 AND t3ver_oid=' . intval($theID) .
214 (!$this->genTree_includeDeleted ? t3lib_BEfunc::deleteClause($table) : '')
215 );
216 } else {
217 // Select all records from table pointing to this page:
218 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
219 t3lib_BEfunc::getCommonSelectFields($table),
220 $table,
221 'pid=' . intval($theID) .
222 (!$this->genTree_includeDeleted ? t3lib_BEfunc::deleteClause($table) : '')
223 );
224 }
225
226 // Traverse selected:
227 $a = 0;
228 $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
229 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
230
231 // Prepare the additional label used in the HTML output in case of versions:
232 if ($versions) {
233 $versionLabel = '[v1.' . $row['t3ver_id'] . '; WS#' . $row['t3ver_wsid'] . ']';
234 } else {
235 $versionLabel = '';
236 }
237
238 $a++;
239 $newID = $row['uid'];
240
241 // Build HTML output:
242 if ($this->genTree_makeHTML) {
243 $this->genTree_HTML .= LF . '<div><span class="nobr">';
244 $PM = 'join';
245 $LN = ($a == $c) ? 'blank' : 'line';
246 $BTM = ($a == $c) ? 'bottom' : '';
247 $this->genTree_HTML .= $depthData .
248 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $PM . $BTM . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' .
249 $versionLabel .
250 t3lib_iconWorks::getSpriteIconForRecord($table, $row, array('title' => $table)) . htmlspecialchars($row['uid'] . ': ' . t3lib_BEfunc::getRecordTitle($table, $row)) . '</span></div>';
251 }
252
253 // Register various data for this item:
254 $this->rec_idArray[$table][$newID] = $row;
255
256 $this->recStats['all_valid'][$table][$newID] = $newID;
257 # $this->recStats[$versions?'versions':'live'][$table][$newID] = $newID;
258 if ($row['deleted']) {
259 $this->recStats['deleted'][$table][$newID] = $newID;
260 }
261 if ($versions && $row['t3ver_count'] >= 1 && $row['t3ver_wsid'] == 0) {
262 $this->recStats['published_versions'][$table][$newID] = $newID;
263 }
264
265 # if ($row['deleted']) {$this->recStat['deleted']++;}
266 # if ($row['hidden']) {$this->recStat['hidden']++;}
267
268
269 // Select all versions of this record:
270 if ($this->genTree_includeVersions && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
271 $genHTML = $depthData . '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $LN . '.gif', 'width="18" height="16"') . ' align="top" alt="" />';
272
273 $this->genTree_records($newID, $genHTML, $table, TRUE);
274 }
275 }
276 }
277
278 /**
279 * Generates tree and returns statistics
280 *
281 * @return array Record statistics
282 */
283 function genTreeStatus($root = 0) {
284 $this->genTree_includeDeleted = TRUE; // if set, genTree() includes deleted pages. This is default.
285 $this->genTree_includeVersions = TRUE; // if set, genTree() includes verisonized pages/records. This is default.
286 $this->genTree_includeRecords = TRUE; // if set, genTree() includes records from pages.
287 $this->perms_clause = ''; // extra where-clauses for the tree-selection
288 $this->genTree_makeHTML = 0; // if set, genTree() generates HTML, that visualizes the tree.
289
290 $this->genTree($root, '');
291
292 return $this->recStats;
293 }
294
295
296 /**
297 * Fills $this->lRecords with the records from all tc-tables that are not attached to a PID in the pid-list.
298 *
299 * @param string list of pid's (page-record uid's). This list is probably made by genTree()
300 * @return void
301 */
302 function lostRecords($pid_list) {
303 $this->lostPagesList = '';
304 if ($pid_list) {
305 foreach ($GLOBALS['TCA'] as $table => $tableConf) {
306 t3lib_div::loadTCA($table);
307
308 $pid_list_tmp = $pid_list;
309 if (!isset($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) || !$GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
310 // Remove preceding "-1," for non-versioned tables
311 $pid_list_tmp = preg_replace('/^\-1,/', '', $pid_list_tmp);
312 }
313
314 $garbage = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
315 'uid,pid,' . $GLOBALS['TCA'][$table]['ctrl']['label'],
316 $table,
317 'pid NOT IN (' . $pid_list_tmp . ')'
318 );
319 $lostIdList = array();
320 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($garbage)) {
321 $this->lRecords[$table][$row['uid']] = array(
322 'uid' => $row['uid'],
323 'pid' => $row['pid'],
324 'title' => strip_tags(t3lib_BEfunc::getRecordTitle($table, $row)),
325 );
326 $lostIdList[] = $row['uid'];
327 }
328 if ($table == 'pages') {
329 $this->lostPagesList = implode(',', $lostIdList);
330 }
331 }
332 }
333 }
334
335 /**
336 * Fixes lost record from $table with uid $uid by setting the PID to zero. If there is a disabled column for the record that will be set as well.
337 *
338 * @param string Database tablename
339 * @param integer The uid of the record which will have the PID value set to 0 (zero)
340 * @return boolean TRUE if done.
341 */
342 function fixLostRecord($table, $uid) {
343 if ($table && $GLOBALS['TCA'][$table] && $uid && is_array($this->lRecords[$table][$uid]) && $GLOBALS['BE_USER']->user['admin']) {
344
345 $updateFields = array();
346 $updateFields['pid'] = 0;
347 if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']) { // If possible a lost record restored is hidden as default
348 $updateFields[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']] = 1;
349 }
350
351 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), $updateFields);
352
353 return TRUE;
354 } else {
355 return FALSE;
356 }
357 }
358
359 /**
360 * Counts records from $GLOBALS['TCA']-tables that ARE attached to an existing page.
361 *
362 * @param string list of pid's (page-record uid's). This list is probably made by genTree()
363 * @return array an array with the number of records from all $GLOBALS['TCA']-tables that are attached to a PID in the pid-list.
364 */
365 function countRecords($pid_list) {
366 $list = array();
367 $list_n = array();
368 if ($pid_list) {
369 foreach ($GLOBALS['TCA'] as $table => $tableConf) {
370 t3lib_div::loadTCA($table);
371
372 $pid_list_tmp = $pid_list;
373 if (!isset($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) || !$GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
374 // Remove preceding "-1," for non-versioned tables
375 $pid_list_tmp = preg_replace('/^\-1,/', '', $pid_list_tmp);
376 }
377
378 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', $table, 'pid IN (' . $pid_list_tmp . ')');
379 if ($count) {
380 $list[$table] = $count;
381 }
382
383 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', $table, 'pid IN (' . $pid_list_tmp . ')' . t3lib_BEfunc::deleteClause($table));
384 if ($count) {
385 $list_n[$table] = $count;
386 }
387 }
388 }
389 return array('all' => $list, 'non_deleted' => $list_n);
390 }
391
392 /**
393 * Finding relations in database based on type 'group' (files or database-uid's in a list)
394 *
395 * @param string $mode = file, $mode = db, $mode = '' (all...)
396 * @return array An array with all fields listed that somehow are references to other records (foreign-keys) or files
397 */
398 function getGroupFields($mode) {
399 $result = array();
400 foreach ($GLOBALS['TCA'] as $table => $tableConf) {
401 t3lib_div::loadTCA($table);
402 $cols = $GLOBALS['TCA'][$table]['columns'];
403 foreach ($cols as $field => $config) {
404 if ($config['config']['type'] == 'group') {
405 if (
406 ((!$mode || $mode == 'file') && $config['config']['internal_type'] == 'file') ||
407 ((!$mode || $mode == 'db') && $config['config']['internal_type'] == 'db')
408 ) {
409 $result[$table][] = $field;
410 }
411 }
412 if ((!$mode || $mode == 'db') && $config['config']['type'] == 'select' && $config['config']['foreign_table']) {
413 $result[$table][] = $field;
414 }
415 }
416 if ($result[$table]) {
417 $result[$table] = implode(',', $result[$table]);
418 }
419 }
420 return $result;
421 }
422
423 /**
424 * Finds all fields that hold filenames from uploadfolder
425 *
426 * @param string Path to uploadfolder
427 * @return array An array with all fields listed that have references to files in the $uploadfolder
428 */
429 function getFileFields($uploadfolder) {
430 $result = array();
431 foreach ($GLOBALS['TCA'] as $table => $tableConf) {
432 t3lib_div::loadTCA($table);
433 $cols = $GLOBALS['TCA'][$table]['columns'];
434 foreach ($cols as $field => $config) {
435 if ($config['config']['type'] == 'group' && $config['config']['internal_type'] == 'file' && $config['config']['uploadfolder'] == $uploadfolder) {
436 $result[] = array($table, $field);
437 }
438 }
439 }
440 return $result;
441 }
442
443 /**
444 * Returns an array with arrays of table/field pairs which are allowed to hold references to the input table name - according to $GLOBALS['TCA']
445 *
446 * @param string Table name
447 * @return array
448 */
449 function getDBFields($theSearchTable) {
450 $result = array();
451 foreach ($GLOBALS['TCA'] as $table => $tableConf) {
452 t3lib_div::loadTCA($table);
453 $cols = $GLOBALS['TCA'][$table]['columns'];
454 foreach ($cols as $field => $config) {
455 if ($config['config']['type'] == 'group' && $config['config']['internal_type'] == 'db') {
456 if (trim($config['config']['allowed']) == '*' || strstr($config['config']['allowed'], $theSearchTable)) {
457 $result[] = array($table, $field);
458 }
459 } elseif ($config['config']['type'] == 'select' && $config['config']['foreign_table'] == $theSearchTable) {
460 $result[] = array($table, $field);
461 }
462 }
463 }
464 return $result;
465 }
466
467 /**
468 * This selects non-empty-records from the tables/fields in the fkey_array generated by getGroupFields()
469 *
470 * @param array Array with tables/fields generated by getGroupFields()
471 * @return void
472 * @see getGroupFields()
473 */
474 function selectNonEmptyRecordsWithFkeys($fkey_arrays) {
475 if (is_array($fkey_arrays)) {
476 foreach ($fkey_arrays as $table => $field_list) {
477 if ($GLOBALS['TCA'][$table] && trim($field_list)) {
478 t3lib_div::loadTCA($table);
479 $fieldArr = explode(',', $field_list);
480
481 if (t3lib_extMgm::isLoaded('dbal')) {
482 $fields = $GLOBALS['TYPO3_DB']->admin_get_fields($table);
483 $field = array_shift($fieldArr);
484 $cl_fl = ($GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'I'
485 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'N'
486 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'R')
487 ? $field . '<>0'
488 : $field . '<>\'\'';
489 foreach ($fieldArr as $field) {
490 $cl_fl .= ($GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'I'
491 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'N'
492 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'R')
493 ? ' OR ' . $field . '<>0'
494 : ' OR ' . $field . '<>\'\'';
495 }
496 unset($fields);
497 }
498 else {
499 $cl_fl = implode('<>\'\' OR ', $fieldArr) . '<>\'\'';
500 }
501
502 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,' . $field_list, $table, $cl_fl);
503 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
504 foreach ($fieldArr as $field) {
505 if (trim($row[$field])) {
506 $fieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
507 if ($fieldConf['type'] == 'group') {
508 if ($fieldConf['internal_type'] == 'file') {
509 // files...
510 if ($fieldConf['MM']) {
511 $tempArr = array();
512 /** @var $dbAnalysis t3lib_loadDBGroup */
513 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
514 $dbAnalysis->start('', 'files', $fieldConf['MM'], $row['uid']);
515 foreach ($dbAnalysis->itemArray as $somekey => $someval) {
516 if ($someval['id']) {
517 $tempArr[] = $someval['id'];
518 }
519 }
520 } else {
521 $tempArr = explode(',', trim($row[$field]));
522 }
523 foreach ($tempArr as $file) {
524 $file = trim($file);
525 if ($file) {
526 $this->checkFileRefs[$fieldConf['uploadfolder']][$file] += 1;
527 }
528 }
529 }
530 if ($fieldConf['internal_type'] == 'db') {
531 /** @var $dbAnalysis t3lib_loadDBGroup */
532 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
533 $dbAnalysis->start($row[$field], $fieldConf['allowed'], $fieldConf['MM'], $row['uid'], $table, $fieldConf);
534 foreach ($dbAnalysis->itemArray as $tempArr) {
535 $this->checkGroupDBRefs[$tempArr['table']][$tempArr['id']] += 1;
536 }
537 }
538 }
539 if ($fieldConf['type'] == 'select' && $fieldConf['foreign_table']) {
540 /** @var $dbAnalysis t3lib_loadDBGroup */
541 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
542 $dbAnalysis->start($row[$field], $fieldConf['foreign_table'], $fieldConf['MM'], $row['uid'], $table, $fieldConf);
543 foreach ($dbAnalysis->itemArray as $tempArr) {
544 if ($tempArr['id'] > 0) {
545 $this->checkGroupDBRefs[$fieldConf['foreign_table']][$tempArr['id']] += 1;
546 }
547 }
548 }
549 }
550 }
551 }
552 $GLOBALS['TYPO3_DB']->sql_free_result($mres);
553 }
554 }
555 }
556 }
557
558 /**
559 * Depends on selectNonEmpty.... to be executed first!!
560 *
561 * @return array Report over files; keys are "moreReferences", "noReferences", "noFile", "error"
562 */
563 function testFileRefs() {
564 $output = array();
565 // handle direct references with upload folder setting (workaround)
566 $newCheckFileRefs = array();
567 foreach ($this->checkFileRefs as $folder => $files) {
568 // only direct references without a folder setting
569 if ($folder !== '') {
570 $newCheckFileRefs[$folder] = $files;
571 continue;
572 }
573
574 foreach ($files as $file => $references) {
575
576 // direct file references have often many references (removes occurences in the moreReferences section of the result array)
577 if ($references > 1) {
578 $references = 1;
579 }
580
581 // the directory must be empty (prevents checking of the root directory)
582 $directory = dirname($file);
583 if ($directory !== '') {
584 $newCheckFileRefs[$directory][basename($file)] = $references;
585 }
586 }
587 }
588 $this->checkFileRefs = $newCheckFileRefs;
589
590 foreach ($this->checkFileRefs as $folder => $fileArr) {
591 $path = PATH_site . $folder;
592 if (@is_dir($path)) {
593 $d = dir($path);
594 while ($entry = $d->read()) {
595 if (@is_file($path . '/' . $entry)) {
596 if (isset($fileArr[$entry])) {
597 if ($fileArr[$entry] > 1) {
598 $temp = $this->whereIsFileReferenced($folder, $entry);
599 $tempList = '';
600 foreach ($temp as $inf) {
601 $tempList .= '[' . $inf['table'] . '][' . $inf['uid'] . '][' . $inf['field'] . '] (pid:' . $inf['pid'] . ') - ';
602 }
603 $output['moreReferences'][] = array($path, $entry, $fileArr[$entry], $tempList);
604 }
605 unset($fileArr[$entry]);
606 } else {
607 // contains workaround for direct references
608 if (!strstr($entry, 'index.htm') && !preg_match('/^' . preg_quote($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/', $folder)) {
609 $output['noReferences'][] = array($path, $entry);
610 }
611 }
612 }
613 }
614 $d->close();
615 $tempCounter = 0;
616 foreach ($fileArr as $file => $value) {
617 // workaround for direct file references
618 if (preg_match('/^' . preg_quote($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/', $folder)) {
619 $file = $folder . '/' . $file;
620 $folder = '';
621 $path = substr(PATH_site, 0, -1);
622 }
623 $temp = $this->whereIsFileReferenced($folder, $file);
624 $tempList = '';
625 foreach ($temp as $inf) {
626 $tempList .= '[' . $inf['table'] . '][' . $inf['uid'] . '][' . $inf['field'] . '] (pid:' . $inf['pid'] . ') - ';
627 }
628 $tempCounter++;
629 $output['noFile'][substr($path, -3) . '_' . substr($file, 0, 3) . '_' . $tempCounter] = array($path, $file, $tempList);
630 }
631 } else {
632 $output['error'][] = array($path);
633 }
634 }
635 return $output;
636 }
637
638 /**
639 * Depends on selectNonEmpty.... to be executed first!!
640 *
641 * @param array Table with key/value pairs being table names and arrays with uid numbers
642 * @return string HTML Error message
643 */
644 function testDBRefs($theArray) {
645 $result = '';
646 foreach ($theArray as $table => $dbArr) {
647 if ($GLOBALS['TCA'][$table]) {
648 $idlist = array_keys($dbArr);
649
650 $theList = implode(',', $idlist);
651 if ($theList) {
652 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'uid IN (' . $theList . ')' . t3lib_BEfunc::deleteClause($table));
653 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
654 if (isset($dbArr[$row['uid']])) {
655 unset ($dbArr[$row['uid']]);
656 } else {
657 $result .= 'Strange Error. ...<br />';
658 }
659 }
660 foreach ($dbArr as $theId => $theC) {
661 $result .= 'There are ' . $theC . ' records pointing to this missing or deleted record; [' . $table . '][' . $theId . ']<br />';
662 }
663 }
664 } else {
665 $result .= 'Codeerror. Table is not a table...<br />';
666 }
667 }
668 return $result;
669 }
670
671 /**
672 * Finding all references to record based on table/uid
673 *
674 * @param string Table name
675 * @param integer Uid of database record
676 * @return array Array with other arrays containing information about where references was found
677 */
678 function whereIsRecordReferenced($searchTable, $id) {
679 $fileFields = $this->getDBFields($searchTable); // Gets tables / Fields that reference to files...
680 $theRecordList = array();
681 foreach ($fileFields as $info) {
682 $table = $info[0];
683 $field = $info[1];
684 t3lib_div::loadTCA($table);
685 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
686 'uid,pid,' . $GLOBALS['TCA'][$table]['ctrl']['label'] . ',' . $field,
687 $table,
688 $field . ' LIKE \'%' . $GLOBALS['TYPO3_DB']->quoteStr($id, $table) . '%\''
689 );
690 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
691 // Now this is the field, where the reference COULD come from. But we're not garanteed, so we must carefully examine the data.
692 $fieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
693 $allowedTables = ($fieldConf['type'] == 'group') ? $fieldConf['allowed'] : $fieldConf['foreign_table'];
694 /** @var $dbAnalysis t3lib_loadDBGroup */
695 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
696 $dbAnalysis->start($row[$field], $allowedTables, $fieldConf['MM'], $row['uid'], $table, $fieldConf);
697 foreach ($dbAnalysis->itemArray as $tempArr) {
698 if ($tempArr['table'] == $searchTable && $tempArr['id'] == $id) {
699 $theRecordList[] = array('table' => $table, 'uid' => $row['uid'], 'field' => $field, 'pid' => $row['pid']);
700 }
701 }
702 }
703 $GLOBALS['TYPO3_DB']->sql_free_result($mres);
704 }
705 return $theRecordList;
706 }
707
708 /**
709 * Finding all references to file based on uploadfolder / filename
710 *
711 * @param string Upload folder where file is found
712 * @param string Filename to search for
713 * @return array Array with other arrays containing information about where references was found
714 */
715 function whereIsFileReferenced($uploadfolder, $filename) {
716 $fileFields = $this->getFileFields($uploadfolder); // Gets tables / Fields that reference to files...
717 $theRecordList = array();
718 foreach ($fileFields as $info) {
719 $table = $info[0];
720 $field = $info[1];
721 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
722 'uid,pid,' . $GLOBALS['TCA'][$table]['ctrl']['label'] . ',' . $field,
723 $table,
724 $field . ' LIKE \'%' . $GLOBALS['TYPO3_DB']->quoteStr($filename, $table) . '%\''
725 );
726 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
727 // Now this is the field, where the reference COULD come from. But we're not guaranteed, so we must carefully examine the data.
728 $tempArr = explode(',', trim($row[$field]));
729 foreach ($tempArr as $file) {
730 $file = trim($file);
731 if ($file == $filename) {
732 $theRecordList[] = array('table' => $table, 'uid' => $row['uid'], 'field' => $field, 'pid' => $row['pid']);
733 }
734 }
735 }
736 }
737 return $theRecordList;
738 }
739 }
740
741 ?>