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