|
TYPO3 API
SVNRelease
|
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 * Contains a class for evaluation of database integrity according to $TCA 00029 * Most of these functions are considered obsolete! 00030 * 00031 * $Id: class.t3lib_admin.php 10121 2011-01-18 20:15:30Z ohader $ 00032 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj 00033 * XHTML compliant 00034 * 00035 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00036 */ 00037 /** 00038 * [CLASS/FUNCTION INDEX of SCRIPT] 00039 * 00040 * 00041 * 00042 * 93: class t3lib_admin 00043 * 128: function genTree($theID, $depthData, $versions=FALSE) 00044 * 217: function genTree_records($theID, $depthData, $table='', $versions=FALSE) 00045 * 292: function genTreeStatus() 00046 * 315: function lostRecords($pid_list) 00047 * 346: function fixLostRecord($table,$uid) 00048 * 367: function countRecords($pid_list) 00049 * 395: function getGroupFields($mode) 00050 * 429: function getFileFields($uploadfolder) 00051 * 452: function getDBFields($theSearchTable) 00052 * 480: function selectNonEmptyRecordsWithFkeys($fkey_arrays) 00053 * 569: function testFileRefs () 00054 * 620: function testDBRefs($theArray) 00055 * 658: function whereIsRecordReferenced($searchTable,$id) 00056 * 695: function whereIsFileReferenced($uploadfolder,$filename) 00057 * 00058 * TOTAL FUNCTIONS: 14 00059 * (This index is automatically created/updated by the extension "extdeveval") 00060 * 00061 */ 00062 00063 00064 /** 00065 * This class holds functions used by the TYPO3 backend to check the integrity of the database (The DBint module, 'lowlevel' extension) 00066 * 00067 * Depends on: Depends on loaddbgroup from t3lib/ 00068 * 00069 * @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! 00070 * @see SC_mod_tools_dbint_index::func_relations(), SC_mod_tools_dbint_index::func_records() 00071 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00072 * @package TYPO3 00073 * @subpackage t3lib 00074 */ 00075 class t3lib_admin { 00076 /** @var bool If set, genTree() includes deleted pages. This is default.*/ 00077 var $genTree_includeDeleted = TRUE; 00078 00079 /** @var bool If set, genTree() includes versionized pages/records. This is default.*/ 00080 var $genTree_includeVersions = TRUE; 00081 00082 /** @var bool If set, genTree() includes records from pages. */ 00083 var $genTree_includeRecords = FALSE; 00084 00085 /** @var string Extra where-clauses for the tree-selection */ 00086 var $perms_clause = ''; 00087 00088 /** @var int If set, genTree() generates HTML, that visualizes the tree. */ 00089 var $genTree_makeHTML = 0; 00090 00091 // internal 00092 /** @var array Will hold id/rec pairs from genTree() */ 00093 var $page_idArray = array(); 00094 00095 /** @var array */ 00096 var $rec_idArray = array(); 00097 00098 /** @var string Will hold the HTML-code visualising the tree. genTree() */ 00099 var $genTree_HTML = ''; 00100 00101 /** @var string */ 00102 var $backPath = ''; 00103 00104 // internal 00105 /** @var array */ 00106 var $checkFileRefs = array(); 00107 00108 /** @var array From the select-fields */ 00109 var $checkSelectDBRefs = array(); 00110 00111 /** @var array From the group-fields */ 00112 var $checkGroupDBRefs = array(); 00113 00114 /** @var array Statistics */ 00115 var $recStats = array( 00116 'allValid' => array(), 00117 'published_versions' => array(), 00118 'deleted' => array(), 00119 ); 00120 00121 /** @var array */ 00122 var $lRecords = array(); 00123 00124 /** @var string */ 00125 var $lostPagesList = ''; 00126 00127 00128 /** 00129 * 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. 00130 * 00131 * @param integer a pid (page-record id) from which to start making the tree 00132 * @param string HTML-code (image-tags) used when this function calls itself recursively. 00133 * @param boolean Internal variable, don't set from outside! 00134 * @return void 00135 */ 00136 function genTree($theID, $depthData, $versions = FALSE) { 00137 00138 if ($versions) { 00139 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00140 'uid,title,doktype,deleted,t3ver_wsid,t3ver_id,t3ver_count,t3ver_swapmode' . (t3lib_extMgm::isLoaded('cms') ? ',hidden' : ''), 00141 'pages', 00142 'pid=-1 AND t3ver_oid=' . intval($theID) . ' ' . ((!$this->genTree_includeDeleted) ? 'AND deleted=0' : '') . $this->perms_clause, 00143 '', 00144 'sorting' 00145 ); 00146 } else { 00147 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00148 'uid,title,doktype,deleted' . (t3lib_extMgm::isLoaded('cms') ? ',hidden' : ''), 00149 'pages', 00150 'pid=' . intval($theID) . ' ' . ((!$this->genTree_includeDeleted) ? 'AND deleted=0' : '') . $this->perms_clause, 00151 '', 00152 'sorting' 00153 ); 00154 } 00155 00156 // Traverse the records selected: 00157 $a = 0; 00158 $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res); 00159 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00160 00161 // Prepare the additional label used in the HTML output in case of versions: 00162 if ($versions) { 00163 $versionLabel = '[v1.' . $row['t3ver_id'] . '; WS#' . $row['t3ver_wsid'] . ']'; 00164 } else { 00165 $versionLabel = ''; 00166 } 00167 00168 $a++; 00169 $newID = $row['uid']; 00170 00171 // Build HTML output: 00172 if ($this->genTree_makeHTML) { 00173 $this->genTree_HTML .= LF . '<div><span class="nobr">'; 00174 $PM = 'join'; 00175 $LN = ($a == $c) ? 'blank' : 'line'; 00176 $BTM = ($a == $c) ? 'bottom' : ''; 00177 $this->genTree_HTML .= $depthData . 00178 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $PM . $BTM . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' . 00179 $versionLabel . 00180 t3lib_iconWorks::getSpriteIconForRecord('pages', $row) . 00181 htmlspecialchars($row['uid'] . ': ' . t3lib_div::fixed_lgd_cs(strip_tags($row['title']), 50)) . '</span></div>'; 00182 } 00183 00184 // Register various data for this item: 00185 $this->page_idArray[$newID] = $row; 00186 00187 $this->recStats['all_valid']['pages'][$newID] = $newID; 00188 # if ($versions) $this->recStats['versions']['pages'][$newID] = $newID; 00189 if ($row['deleted']) { 00190 $this->recStats['deleted']['pages'][$newID] = $newID; 00191 } 00192 if ($versions && $row['t3ver_count'] >= 1) { 00193 $this->recStats['published_versions']['pages'][$newID] = $newID; 00194 } 00195 00196 if ($row['deleted']) { 00197 $this->recStats['deleted']++; 00198 } 00199 if ($row['hidden']) { 00200 $this->recStats['hidden']++; 00201 } 00202 $this->recStats['doktype'][$row['doktype']]++; 00203 00204 // Create the HTML code prefix for recursive call: 00205 $genHTML = $depthData . '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $LN . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' . $versionLabel; 00206 00207 // If all records should be shown, do so: 00208 if ($this->genTree_includeRecords) { 00209 foreach ($GLOBALS['TCA'] as $tableName => $cfg) { 00210 if ($tableName != 'pages') { 00211 $this->genTree_records($newID, $this->genTree_HTML ? $genHTML : '', $tableName); 00212 } 00213 } 00214 } 00215 00216 // Add sub pages: 00217 $this->genTree($newID, $this->genTree_HTML ? $genHTML : ''); 00218 00219 // If versions are included in the tree, add those now: 00220 if ($this->genTree_includeVersions) { 00221 $this->genTree($newID, $this->genTree_HTML ? $genHTML : '', TRUE); 00222 } 00223 } 00224 } 00225 00226 /** 00227 * @param integer a pid (page-record id) from which to start making the tree 00228 * @param string HTML-code used when this function calls itself recursively. 00229 * @param string Table to get the records from 00230 * @param bool Internal variable, don't set from outside! 00231 * @return void 00232 */ 00233 function genTree_records($theID, $depthData, $table = '', $versions = FALSE) { 00234 global $TCA; 00235 00236 if ($versions) { 00237 // Select all records from table pointing to this page: 00238 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00239 t3lib_BEfunc::getCommonSelectFields($table), 00240 $table, 00241 'pid=-1 AND t3ver_oid=' . intval($theID) . 00242 (!$this->genTree_includeDeleted ? t3lib_BEfunc::deleteClause($table) : '') 00243 ); 00244 } else { 00245 // Select all records from table pointing to this page: 00246 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00247 t3lib_BEfunc::getCommonSelectFields($table), 00248 $table, 00249 'pid=' . intval($theID) . 00250 (!$this->genTree_includeDeleted ? t3lib_BEfunc::deleteClause($table) : '') 00251 ); 00252 } 00253 00254 // Traverse selected: 00255 $a = 0; 00256 $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res); 00257 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00258 00259 // Prepare the additional label used in the HTML output in case of versions: 00260 if ($versions) { 00261 $versionLabel = '[v1.' . $row['t3ver_id'] . '; WS#' . $row['t3ver_wsid'] . ']'; 00262 } else { 00263 $versionLabel = ''; 00264 } 00265 00266 $a++; 00267 $newID = $row['uid']; 00268 00269 // Build HTML output: 00270 if ($this->genTree_makeHTML) { 00271 $this->genTree_HTML .= LF . '<div><span class="nobr">'; 00272 $PM = 'join'; 00273 $LN = ($a == $c) ? 'blank' : 'line'; 00274 $BTM = ($a == $c) ? 'bottom' : ''; 00275 $this->genTree_HTML .= $depthData . 00276 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $PM . $BTM . '.gif', 'width="18" height="16"') . ' align="top" alt="" />' . 00277 $versionLabel . 00278 t3lib_iconWorks::getSpriteIconForRecord($table, $row, array('title' => $table)) . htmlspecialchars($row['uid'] . ': ' . t3lib_BEfunc::getRecordTitle($table, $row)) . '</span></div>'; 00279 } 00280 00281 // Register various data for this item: 00282 $this->rec_idArray[$table][$newID] = $row; 00283 00284 $this->recStats['all_valid'][$table][$newID] = $newID; 00285 # $this->recStats[$versions?'versions':'live'][$table][$newID] = $newID; 00286 if ($row['deleted']) { 00287 $this->recStats['deleted'][$table][$newID] = $newID; 00288 } 00289 if ($versions && $row['t3ver_count'] >= 1 && $row['t3ver_wsid'] == 0) { 00290 $this->recStats['published_versions'][$table][$newID] = $newID; 00291 } 00292 00293 # if ($row['deleted']) {$this->recStat['deleted']++;} 00294 # if ($row['hidden']) {$this->recStat['hidden']++;} 00295 00296 00297 // Select all versions of this record: 00298 if ($this->genTree_includeVersions && $TCA[$table]['ctrl']['versioningWS']) { 00299 $genHTML = $depthData . '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/ol/' . $LN . '.gif', 'width="18" height="16"') . ' align="top" alt="" />'; 00300 00301 $this->genTree_records($newID, $genHTML, $table, TRUE); 00302 } 00303 } 00304 } 00305 00306 /** 00307 * Generates tree and returns statistics 00308 * 00309 * @return array Record statistics 00310 */ 00311 function genTreeStatus($root = 0) { 00312 $this->genTree_includeDeleted = TRUE; // if set, genTree() includes deleted pages. This is default. 00313 $this->genTree_includeVersions = TRUE; // if set, genTree() includes verisonized pages/records. This is default. 00314 $this->genTree_includeRecords = TRUE; // if set, genTree() includes records from pages. 00315 $this->perms_clause = ''; // extra where-clauses for the tree-selection 00316 $this->genTree_makeHTML = 0; // if set, genTree() generates HTML, that visualizes the tree. 00317 00318 $this->genTree($root, ''); 00319 00320 return $this->recStats; 00321 } 00322 00323 00324 /** 00325 * Fills $this->lRecords with the records from all tc-tables that are not attached to a PID in the pid-list. 00326 * 00327 * @param string list of pid's (page-record uid's). This list is probably made by genTree() 00328 * @return void 00329 */ 00330 function lostRecords($pid_list) { 00331 global $TCA; 00332 $this->lostPagesList = ''; 00333 if ($pid_list) { 00334 foreach ($TCA as $table => $tableConf) { 00335 t3lib_div::loadTCA($table); 00336 00337 $pid_list_tmp = $pid_list; 00338 if (!isset($TCA[$table]['ctrl']['versioningWS']) || !$TCA[$table]['ctrl']['versioningWS']) { 00339 // Remove preceding "-1," for non-versioned tables 00340 $pid_list_tmp = preg_replace('/^\-1,/', '', $pid_list_tmp); 00341 } 00342 00343 $garbage = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00344 'uid,pid,' . $TCA[$table]['ctrl']['label'], 00345 $table, 00346 'pid NOT IN (' . $pid_list_tmp . ')' 00347 ); 00348 $lostIdList = array(); 00349 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($garbage)) { 00350 $this->lRecords[$table][$row['uid']] = array('uid' => $row['uid'], 'pid' => $row['pid'], 'title' => strip_tags($row[$TCA[$table]['ctrl']['label']])); 00351 $lostIdList[] = $row['uid']; 00352 } 00353 if ($table == 'pages') { 00354 $this->lostPagesList = implode(',', $lostIdList); 00355 } 00356 } 00357 } 00358 } 00359 00360 /** 00361 * 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. 00362 * 00363 * @param string Database tablename 00364 * @param integer The uid of the record which will have the PID value set to 0 (zero) 00365 * @return boolean True if done. 00366 */ 00367 function fixLostRecord($table, $uid) { 00368 if ($table && $GLOBALS['TCA'][$table] && $uid && is_array($this->lRecords[$table][$uid]) && $GLOBALS['BE_USER']->user['admin']) { 00369 00370 $updateFields = array(); 00371 $updateFields['pid'] = 0; 00372 if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']) { // If possible a lost record restored is hidden as default 00373 $updateFields[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']] = 1; 00374 } 00375 00376 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), $updateFields); 00377 00378 return TRUE; 00379 } else { 00380 return FALSE; 00381 } 00382 } 00383 00384 /** 00385 * Counts records from $TCA-tables that ARE attached to an existing page. 00386 * 00387 * @param string list of pid's (page-record uid's). This list is probably made by genTree() 00388 * @return array an array with the number of records from all $TCA-tables that are attached to a PID in the pid-list. 00389 */ 00390 function countRecords($pid_list) { 00391 global $TCA; 00392 $list = array(); 00393 $list_n = array(); 00394 if ($pid_list) { 00395 foreach ($TCA as $table => $tableConf) { 00396 t3lib_div::loadTCA($table); 00397 00398 $pid_list_tmp = $pid_list; 00399 if (!isset($TCA[$table]['ctrl']['versioningWS']) || !$TCA[$table]['ctrl']['versioningWS']) { 00400 // Remove preceding "-1," for non-versioned tables 00401 $pid_list_tmp = preg_replace('/^\-1,/', '', $pid_list_tmp); 00402 } 00403 00404 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', $table, 'pid IN (' . $pid_list_tmp . ')'); 00405 if ($count) { 00406 $list[$table] = $count; 00407 } 00408 00409 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', $table, 'pid IN (' . $pid_list_tmp . ')' . t3lib_BEfunc::deleteClause($table)); 00410 if ($count) { 00411 $list_n[$table] = $count; 00412 } 00413 } 00414 } 00415 return array('all' => $list, 'non_deleted' => $list_n); 00416 } 00417 00418 /** 00419 * Finding relations in database based on type 'group' (files or database-uid's in a list) 00420 * 00421 * @param string $mode = file, $mode = db, $mode = '' (all...) 00422 * @return array An array with all fields listed that somehow are references to other records (foreign-keys) or files 00423 */ 00424 function getGroupFields($mode) { 00425 global $TCA; 00426 $result = array(); 00427 foreach ($TCA as $table => $tableConf) { 00428 t3lib_div::loadTCA($table); 00429 $cols = $TCA[$table]['columns']; 00430 foreach ($cols as $field => $config) { 00431 if ($config['config']['type'] == 'group') { 00432 if ( 00433 ((!$mode || $mode == 'file') && $config['config']['internal_type'] == 'file') || 00434 ((!$mode || $mode == 'db') && $config['config']['internal_type'] == 'db') 00435 ) { 00436 $result[$table][] = $field; 00437 } 00438 } 00439 if ((!$mode || $mode == 'db') && $config['config']['type'] == 'select' && $config['config']['foreign_table']) { 00440 $result[$table][] = $field; 00441 } 00442 } 00443 if ($result[$table]) { 00444 $result[$table] = implode(',', $result[$table]); 00445 } 00446 } 00447 return $result; 00448 } 00449 00450 /** 00451 * Finds all fields that hold filenames from uploadfolder 00452 * 00453 * @param string Path to uploadfolder 00454 * @return array An array with all fields listed that have references to files in the $uploadfolder 00455 */ 00456 function getFileFields($uploadfolder) { 00457 global $TCA; 00458 $result = array(); 00459 foreach ($TCA as $table => $tableConf) { 00460 t3lib_div::loadTCA($table); 00461 $cols = $TCA[$table]['columns']; 00462 foreach ($cols as $field => $config) { 00463 if ($config['config']['type'] == 'group' && $config['config']['internal_type'] == 'file' && $config['config']['uploadfolder'] == $uploadfolder) { 00464 $result[] = array($table, $field); 00465 } 00466 } 00467 } 00468 return $result; 00469 } 00470 00471 /** 00472 * Returns an array with arrays of table/field pairs which are allowed to hold references to the input table name - according to $TCA 00473 * 00474 * @param string Table name 00475 * @return array 00476 */ 00477 function getDBFields($theSearchTable) { 00478 global $TCA; 00479 $result = array(); 00480 reset($TCA); 00481 foreach ($TCA as $table => $tableConf) { 00482 t3lib_div::loadTCA($table); 00483 $cols = $TCA[$table]['columns']; 00484 foreach ($cols as $field => $config) { 00485 if ($config['config']['type'] == 'group' && $config['config']['internal_type'] == 'db') { 00486 if (trim($config['config']['allowed']) == '*' || strstr($config['config']['allowed'], $theSearchTable)) { 00487 $result[] = array($table, $field); 00488 } 00489 } elseif ($config['config']['type'] == 'select' && $config['config']['foreign_table'] == $theSearchTable) { 00490 $result[] = array($table, $field); 00491 } 00492 } 00493 } 00494 return $result; 00495 } 00496 00497 /** 00498 * This selects non-empty-records from the tables/fields in the fkey_array generated by getGroupFields() 00499 * 00500 * @param array Array with tables/fields generated by getGroupFields() 00501 * @return void 00502 * @see getGroupFields() 00503 */ 00504 function selectNonEmptyRecordsWithFkeys($fkey_arrays) { 00505 global $TCA; 00506 if (is_array($fkey_arrays)) { 00507 foreach ($fkey_arrays as $table => $field_list) { 00508 if ($TCA[$table] && trim($field_list)) { 00509 t3lib_div::loadTCA($table); 00510 $fieldArr = explode(',', $field_list); 00511 00512 if (t3lib_extMgm::isLoaded('dbal')) { 00513 $fields = $GLOBALS['TYPO3_DB']->admin_get_fields($table); 00514 $field = array_shift($fieldArr); 00515 $cl_fl = ($GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'I' 00516 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'N' 00517 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'R') 00518 ? $field . '!=0' 00519 : $field . '!=\'\''; 00520 foreach ($fieldArr as $field) { 00521 $cl_fl .= ($GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'I' 00522 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'N' 00523 || $GLOBALS['TYPO3_DB']->MetaType($fields[$field]['type'], $table) == 'R') 00524 ? ' OR ' . $field . '!=0' 00525 : ' OR ' . $field . '!=\'\''; 00526 } 00527 unset($fields); 00528 } 00529 else { 00530 $cl_fl = implode('!=\'\' OR ', $fieldArr) . '!=\'\''; 00531 } 00532 00533 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,' . $field_list, $table, $cl_fl); 00534 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 00535 foreach ($fieldArr as $field) { 00536 if (trim($row[$field])) { 00537 $fieldConf = $TCA[$table]['columns'][$field]['config']; 00538 if ($fieldConf['type'] == 'group') { 00539 if ($fieldConf['internal_type'] == 'file') { 00540 // files... 00541 if ($fieldConf['MM']) { 00542 $tempArr = array(); 00543 /** @var $dbAnalysis t3lib_loadDBGroup */ 00544 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 00545 $dbAnalysis->start('', 'files', $fieldConf['MM'], $row['uid']); 00546 foreach ($dbAnalysis->itemArray as $somekey => $someval) { 00547 if ($someval['id']) { 00548 $tempArr[] = $someval['id']; 00549 } 00550 } 00551 } else { 00552 $tempArr = explode(',', trim($row[$field])); 00553 } 00554 foreach ($tempArr as $file) { 00555 $file = trim($file); 00556 if ($file) { 00557 $this->checkFileRefs[$fieldConf['uploadfolder']][$file] += 1; 00558 } 00559 } 00560 } 00561 if ($fieldConf['internal_type'] == 'db') { 00562 /** @var $dbAnalysis t3lib_loadDBGroup */ 00563 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 00564 $dbAnalysis->start($row[$field], $fieldConf['allowed'], $fieldConf['MM'], $row['uid'], $table, $fieldConf); 00565 foreach ($dbAnalysis->itemArray as $tempArr) { 00566 $this->checkGroupDBRefs[$tempArr['table']][$tempArr['id']] += 1; 00567 } 00568 } 00569 } 00570 if ($fieldConf['type'] == 'select' && $fieldConf['foreign_table']) { 00571 /** @var $dbAnalysis t3lib_loadDBGroup */ 00572 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 00573 $dbAnalysis->start($row[$field], $fieldConf['foreign_table'], $fieldConf['MM'], $row['uid'], $table, $fieldConf); 00574 foreach ($dbAnalysis->itemArray as $tempArr) { 00575 if ($tempArr['id'] > 0) { 00576 $this->checkGroupDBRefs[$fieldConf['foreign_table']][$tempArr['id']] += 1; 00577 } 00578 } 00579 } 00580 } 00581 } 00582 } 00583 $GLOBALS['TYPO3_DB']->sql_free_result($mres); 00584 } 00585 } 00586 } 00587 } 00588 00589 /** 00590 * Depends on selectNonEmpty.... to be executed first!! 00591 * 00592 * @return array Report over files; keys are "moreReferences", "noReferences", "noFile", "error" 00593 */ 00594 function testFileRefs() { 00595 $output = array(); 00596 // handle direct references with upload folder setting (workaround) 00597 $newCheckFileRefs = array(); 00598 foreach ($this->checkFileRefs as $folder => $files) { 00599 // only direct references without a folder setting 00600 if ($folder !== '') { 00601 $newCheckFileRefs[$folder] = $files; 00602 continue; 00603 } 00604 00605 foreach ($files as $file => $references) { 00606 00607 // direct file references have often many references (removes occurences in the moreReferences section of the result array) 00608 if ($references > 1) { 00609 $references = 1; 00610 } 00611 00612 // the directory must be empty (prevents checking of the root directory) 00613 $directory = dirname($file); 00614 if ($directory !== '') { 00615 $newCheckFileRefs[$directory][basename($file)] = $references; 00616 } 00617 } 00618 } 00619 $this->checkFileRefs = $newCheckFileRefs; 00620 00621 foreach ($this->checkFileRefs as $folder => $fileArr) { 00622 $path = PATH_site . $folder; 00623 if (@is_dir($path)) { 00624 $d = dir($path); 00625 while ($entry = $d->read()) { 00626 if (@is_file($path . '/' . $entry)) { 00627 if (isset($fileArr[$entry])) { 00628 if ($fileArr[$entry] > 1) { 00629 $temp = $this->whereIsFileReferenced($folder, $entry); 00630 $tempList = ''; 00631 foreach ($temp as $inf) { 00632 $tempList .= '[' . $inf['table'] . '][' . $inf['uid'] . '][' . $inf['field'] . '] (pid:' . $inf['pid'] . ') - '; 00633 } 00634 $output['moreReferences'][] = array($path, $entry, $fileArr[$entry], $tempList); 00635 } 00636 unset($fileArr[$entry]); 00637 } else { 00638 // contains workaround for direct references 00639 if (!strstr($entry, 'index.htm') && !preg_match('/^' . preg_quote($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/', $folder)) { 00640 $output['noReferences'][] = array($path, $entry); 00641 } 00642 } 00643 } 00644 } 00645 $d->close(); 00646 $tempCounter = 0; 00647 foreach ($fileArr as $file => $value) { 00648 // workaround for direct file references 00649 if (preg_match('/^' . preg_quote($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/', $folder)) { 00650 $file = $folder . '/' . $file; 00651 $folder = ''; 00652 $path = substr(PATH_site, 0, -1); 00653 } 00654 $temp = $this->whereIsFileReferenced($folder, $file); 00655 $tempList = ''; 00656 foreach ($temp as $inf) { 00657 $tempList .= '[' . $inf['table'] . '][' . $inf['uid'] . '][' . $inf['field'] . '] (pid:' . $inf['pid'] . ') - '; 00658 } 00659 $tempCounter++; 00660 $output['noFile'][substr($path, -3) . '_' . substr($file, 0, 3) . '_' . $tempCounter] = array($path, $file, $tempList); 00661 } 00662 } else { 00663 $output['error'][] = array($path); 00664 } 00665 } 00666 return $output; 00667 } 00668 00669 /** 00670 * Depends on selectNonEmpty.... to be executed first!! 00671 * 00672 * @param array Table with key/value pairs being table names and arrays with uid numbers 00673 * @return string HTML Error message 00674 */ 00675 function testDBRefs($theArray) { 00676 global $TCA; 00677 foreach ($theArray as $table => $dbArr) { 00678 if ($TCA[$table]) { 00679 $idlist = array_keys($dbArr); 00680 00681 $theList = implode(',', $idlist); 00682 if ($theList) { 00683 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'uid IN (' . $theList . ')' . t3lib_BEfunc::deleteClause($table)); 00684 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 00685 if (isset($dbArr[$row['uid']])) { 00686 unset ($dbArr[$row['uid']]); 00687 } else { 00688 $result .= 'Strange Error. ...<br />'; 00689 } 00690 } 00691 foreach ($dbArr as $theId => $theC) { 00692 $result .= 'There are ' . $theC . ' records pointing to this missing or deleted record; [' . $table . '][' . $theId . ']<br />'; 00693 } 00694 } 00695 } else { 00696 $result .= 'Codeerror. Table is not a table...<br />'; 00697 } 00698 } 00699 return $result; 00700 } 00701 00702 /** 00703 * Finding all references to record based on table/uid 00704 * 00705 * @param string Table name 00706 * @param integer Uid of database record 00707 * @return array Array with other arrays containing information about where references was found 00708 */ 00709 function whereIsRecordReferenced($searchTable, $id) { 00710 global $TCA; 00711 $fileFields = $this->getDBFields($searchTable); // Gets tables / Fields that reference to files... 00712 $theRecordList = array(); 00713 foreach ($fileFields as $info) { 00714 $table = $info[0]; 00715 $field = $info[1]; 00716 t3lib_div::loadTCA($table); 00717 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00718 'uid,pid,' . $TCA[$table]['ctrl']['label'] . ',' . $field, 00719 $table, 00720 $field . ' LIKE \'%' . $GLOBALS['TYPO3_DB']->quoteStr($id, $table) . '%\'' 00721 ); 00722 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 00723 // Now this is the field, where the reference COULD come from. But we're not garanteed, so we must carefully examine the data. 00724 $fieldConf = $TCA[$table]['columns'][$field]['config']; 00725 $allowedTables = ($fieldConf['type'] == 'group') ? $fieldConf['allowed'] : $fieldConf['foreign_table']; 00726 /** @var $dbAnalysis t3lib_loadDBGroup */ 00727 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 00728 $dbAnalysis->start($row[$field], $allowedTables, $fieldConf['MM'], $row['uid'], $table, $fieldConf); 00729 foreach ($dbAnalysis->itemArray as $tempArr) { 00730 if ($tempArr['table'] == $searchTable && $tempArr['id'] == $id) { 00731 $theRecordList[] = array('table' => $table, 'uid' => $row['uid'], 'field' => $field, 'pid' => $row['pid']); 00732 } 00733 } 00734 } 00735 $GLOBALS['TYPO3_DB']->sql_free_result($mres); 00736 } 00737 return $theRecordList; 00738 } 00739 00740 /** 00741 * Finding all references to file based on uploadfolder / filename 00742 * 00743 * @param string Upload folder where file is found 00744 * @param string Filename to search for 00745 * @return array Array with other arrays containing information about where references was found 00746 */ 00747 function whereIsFileReferenced($uploadfolder, $filename) { 00748 global $TCA; 00749 $fileFields = $this->getFileFields($uploadfolder); // Gets tables / Fields that reference to files... 00750 $theRecordList = array(); 00751 foreach ($fileFields as $info) { 00752 $table = $info[0]; 00753 $field = $info[1]; 00754 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00755 'uid,pid,' . $TCA[$table]['ctrl']['label'] . ',' . $field, 00756 $table, 00757 $field . ' LIKE \'%' . $GLOBALS['TYPO3_DB']->quoteStr($filename, $table) . '%\'' 00758 ); 00759 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 00760 // Now this is the field, where the reference COULD come from. But we're not guaranteed, so we must carefully examine the data. 00761 $tempArr = explode(',', trim($row[$field])); 00762 foreach ($tempArr as $file) { 00763 $file = trim($file); 00764 if ($file == $filename) { 00765 $theRecordList[] = array('table' => $table, 'uid' => $row['uid'], 'field' => $field, 'pid' => $row['pid']); 00766 } 00767 } 00768 } 00769 } 00770 return $theRecordList; 00771 } 00772 } 00773 00774 00775 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_admin.php'])) { 00776 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_admin.php']); 00777 } 00778 ?>
1.8.0