"TYPO3 4.0.1: typo3_src-4.0.1/t3lib/class.t3lib_refindex.php Source File", "datetime" => "Sat Dec 2 19:22:18 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.t3lib_refindex.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2006 Kasper Skaarhoj (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 ***************************************************************/
00064 require_once(PATH_t3lib.'class.t3lib_tcemain.php');
00065 require_once(PATH_t3lib.'class.t3lib_flexformtools.php');
00066 
00067 
00068 
00083 class t3lib_refindex {
00084 
00085         var $temp_flexRelations = array();
00086         var $errorLog = array();
00087         var $WSOL = FALSE;
00088         var $relations = array();
00089         var $hashVersion = 1;   // Number which we can increase if a change in the code means we will have to force a re-generation of the index.
00090 
00091 
00101         function updateRefIndexTable($table,$uid,$testOnly=FALSE)       {
00102 
00103                         // First, secure that the index table is not updated with workspace tainted relations:
00104                 $this->WSOL = FALSE;
00105 
00106                         // Init:
00107                 $result = array(
00108                         'keptNodes' => 0,
00109                         'deletedNodes' => 0,
00110                         'addedNodes' => 0
00111                 );
00112 
00113                         // Get current index from Database:
00114                 $currentRels = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00115                         '*',
00116                         'sys_refindex',
00117                         'tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex').
00118                                 ' AND recuid='.intval($uid),
00119                         '','','','hash'
00120                 );
00121 
00122                         // First, test to see if the record exists (being deleted also means it doesn't exist!)
00123                 if (t3lib_BEfunc::getRecordRaw($table,'uid='.intval($uid),'uid'))       {
00124 
00125                                 // Then, get relations:
00126                         $relations = $this->generateRefIndexData($table,$uid);
00127 
00128                         if (is_array($relations))       {
00129 
00130                                         // Traverse the generated index:
00131                                 foreach($relations as $k => $datRec)    {
00132                                         $relations[$k]['hash'] = md5(implode('
00133 
00134                                                 // First, check if already indexed and if so, unset that row (so in the end we know which rows to remove!)
00135                                         if (isset($currentRels[$relations[$k]['hash']]))        {
00136                                                 unset($currentRels[$relations[$k]['hash']]);
00137                                                 $result['keptNodes']++;
00138                                                 $relations[$k]['_ACTION'] = 'KEPT';
00139                                         } else {
00140                                                         // If new, add it:
00141                                                 if (!$testOnly) $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_refindex',$relations[$k]);
00142                                                 $result['addedNodes']++;
00143                                                 $relations[$k]['_ACTION'] = 'ADDED';
00144                                         }
00145                                 }
00146 
00147                                 $result['relations'] = $relations;
00148                         } else return FALSE;    // Weird mistake I would say...
00149                 }
00150 
00151                         // If any old are left, remove them:
00152                 if (count($currentRels))        {
00153                         $hashList = array_keys($currentRels);
00154                         if (count($hashList))   {
00155                                 $result['deletedNodes'] = count($hashList);
00156                                 $result['deletedNodes_hashList'] = implode(',',$hashList);
00157                                 if (!$testOnly) $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_refindex','hash IN ('.implode(',',$GLOBALS['TYPO3_DB']->fullQuoteArray($hashList,'sys_refindex')).')');
00158                         }
00159                 }
00160 
00161                 return $result;
00162         }
00163 
00172         function generateRefIndexData($table,$uid)      {
00173                 global $TCA;
00174 
00175                 if (isset($TCA[$table]))        {
00176                                 // Get raw record from DB:
00177                         list($record) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*',$table,'uid='.intval($uid));
00178 
00179                         if (is_array($record))  {
00180 
00181                                         // Deleted:
00182                                 $deleted = $TCA[$table]['ctrl']['delete'] ? ($record[$TCA[$table]['ctrl']['delete']]?1:0) : 0;
00183 
00184                                         // Get all relations from record:
00185                                 $dbrels = $this->getRelations($table,$record);
00186 
00187                                         // Traverse those relations, compile records to insert in table:
00188                                 $this->relations = array();
00189                                 foreach($dbrels as $fieldname => $dat)  {
00190 
00191                                                 // Based on type,
00192                                         switch((string)$dat['type'])    {
00193                                                 case 'db':
00194                                                         $this->createEntryData_dbRels($table,$uid,$fieldname,'',$deleted,$dat['itemArray']);
00195                                                 break;
00196                                                 case 'file':
00197                                                         $this->createEntryData_fileRels($table,$uid,$fieldname,'',$deleted,$dat['newValueFiles']);
00198                                                 break;
00199                                                 case 'flex':
00200                                                                 // DB references:
00201                                                         if (is_array($dat['flexFormRels']['db']))       {
00202                                                                 foreach($dat['flexFormRels']['db'] as $flexpointer => $subList) {
00203                                                                         $this->createEntryData_dbRels($table,$uid,$fieldname,$flexpointer,$deleted,$subList);
00204                                                                 }
00205                                                         }
00206                                                                 // File references (NOT TESTED!)
00207                                                         if (is_array($dat['flexFormRels']['file']))     {       // Not tested
00208                                                                 foreach($dat['flexFormRels']['file'] as $flexpointer => $subList)       {
00209                                                                         $this->createEntryData_fileRels($table,$uid,$fieldname,$flexpointer,$deleted,$subList);
00210                                                                 }
00211                                                         }
00212                                                                 // Soft references in flexforms (NOT TESTED!)
00213                                                         if (is_array($dat['flexFormRels']['softrefs'])) {
00214                                                                 foreach($dat['flexFormRels']['softrefs'] as $flexpointer => $subList)   {
00215                                                                         $this->createEntryData_softreferences($table,$uid,$fieldname,$flexpointer,$deleted,$subList['keys']);
00216                                                                 }
00217                                                         }
00218                                                 break;
00219                                         }
00220 
00221                                                 // Softreferences in the field:
00222                                         if (is_array($dat['softrefs'])) {
00223                                                 $this->createEntryData_softreferences($table,$uid,$fieldname,'',$deleted,$dat['softrefs']['keys']);
00224                                         }
00225                                 }
00226 
00227                                 return $this->relations;
00228                         }
00229                 }
00230         }
00231 
00249         function createEntryData($table,$uid,$field,$flexpointer,$deleted,$ref_table,$ref_uid,$ref_string='',$sort=-1,$softref_key='',$softref_id='')   {
00250                 return array(
00251                         'tablename' => $table,
00252                         'recuid' => $uid,
00253                         'field' => $field,
00254                         'flexpointer' => $flexpointer,
00255                         'softref_key' => $softref_key,
00256                         'softref_id' => $softref_id,
00257                         'sorting' => $sort,
00258                         'deleted' => $deleted,
00259                         'ref_table' => $ref_table,
00260                         'ref_uid' => $ref_uid,
00261                         'ref_string' => $ref_string,
00262                 );
00263         }
00264 
00276         function createEntryData_dbRels($table,$uid,$fieldname,$flexpointer,$deleted,$items)    {
00277                 foreach($items as $sort => $i)  {
00278                         $this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,$i['table'],$i['id'],'',$sort);
00279                 }
00280         }
00281 
00293         function createEntryData_fileRels($table,$uid,$fieldname,$flexpointer,$deleted,$items)  {
00294                 foreach($items as $sort => $i)  {
00295                         $filePath = $i['ID_absFile'];
00296                         if (t3lib_div::isFirstPartOfStr($filePath,PATH_site))   {
00297                                 $filePath = substr($filePath,strlen(PATH_site));
00298                         }
00299                         $this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,'_FILE',0,$filePath,$sort);
00300                 }
00301         }
00302 
00314         function createEntryData_softreferences($table,$uid,$fieldname,$flexpointer,$deleted,$keys)     {
00315                 if (is_array($keys))    {
00316                         foreach($keys as $spKey => $elements)   {
00317                                 if (is_array($elements))        {
00318                                         foreach($elements as $subKey => $el)    {
00319                                                 if (is_array($el['subst']))     {
00320                                                         switch((string)$el['subst']['type'])    {
00321                                                                  case 'db':
00322                                                                         list($tableName,$recordId) = explode(':',$el['subst']['recordRef']);
00323                                                                         $this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,$tableName,$recordId,'',-1,$spKey,$subKey);
00324                                                                  break;
00325                                                                  case 'file':
00326                                                                         $this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,'_FILE',0,$el['subst']['relFileName'],-1,$spKey,$subKey);
00327                                                                  break;
00328                                                                  case 'string':
00329                                                                         $this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,'_STRING',0,$el['subst']['tokenValue'],-1,$spKey,$subKey);
00330                                                                  break;
00331                                                         }
00332                                                 }
00333                                         }
00334                                 }
00335                         }
00336                 }
00337         }
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353         /*******************************
00354          *
00355          * Get relations from table row
00356          *
00357          *******************************/
00358 
00369         function getRelations($table,$row)      {
00370                 global $TCA;
00371 
00372                         // Load full table description
00373                 t3lib_div::loadTCA($table);
00374 
00375                         // Initialize:
00376                 $uid = $row['uid'];
00377                 $nonFields = explode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,pid');
00378 
00379                 $outRow = array();
00380                 foreach($row as $field => $value)       {
00381                         if (!in_array($field,$nonFields) && is_array($TCA[$table]['columns'][$field]))  {
00382                                 $conf = $TCA[$table]['columns'][$field]['config'];
00383 
00384                                         // Add files
00385                                 if ($result = $this->getRelations_procFiles($value, $conf, $uid))       {
00386                                                 // Creates an entry for the field with all the files:
00387                                         $outRow[$field] = array(
00388                                                 'type' => 'file',
00389                                                 'newValueFiles' => $result,
00390                                         );
00391                                 }
00392 
00393                                         // Add DB:
00394                                 if ($result = $this->getRelations_procDB($value, $conf, $uid))  {
00395                                                 // Create an entry for the field with all DB relations:
00396                                         $outRow[$field] = array(
00397                                                 'type' => 'db',
00398                                                 'itemArray' => $result,
00399                                         );
00400                                 }
00401 
00402                                         // For "flex" fieldtypes we need to traverse the structure looking for file and db references of course!
00403                                 if ($conf['type']=='flex')      {
00404 
00405                                                 // Get current value array:
00406                                         $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $row, $table,'',$this->WSOL);
00407                                         $currentValueArray = t3lib_div::xml2array($value);
00408 
00409                                                 // Traversing the XML structure, processing files:
00410                                         if (is_array($currentValueArray))       {
00411                                                 $this->temp_flexRelations = array(
00412                                                         'db' => array(),
00413                                                         'file' => array(),
00414                                                         'softrefs' => array()
00415                                                 );
00416 
00417                                                         // Create and call iterator object:
00418                                                 $flexObj = t3lib_div::makeInstance('t3lib_flexformtools');
00419                                                 $flexObj->traverseFlexFormXMLData($table,$field,$row,$this,'getRelations_flexFormCallBack');
00420 
00421                                                         // Create an entry for the field:
00422                                                 $outRow[$field] = array(
00423                                                         'type' => 'flex',
00424                                                         'flexFormRels' => $this->temp_flexRelations,
00425                                                 );
00426                                         }
00427                                 }
00428 
00429                                         // Soft References:
00430                                 if (strlen($value) && $softRefs = t3lib_BEfunc::explodeSoftRefParserList($conf['softref']))     {
00431                                         $softRefValue = $value;
00432                                         foreach($softRefs as $spKey => $spParams)       {
00433                                                 $softRefObj = &t3lib_BEfunc::softRefParserObj($spKey);
00434                                                 if (is_object($softRefObj))     {
00435                                                         $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams);
00436                                                         if (is_array($resultArray))     {
00437                                                                 $outRow[$field]['softrefs']['keys'][$spKey] = $resultArray['elements'];
00438                                                                 if (strlen($resultArray['content'])) {
00439                                                                         $softRefValue = $resultArray['content'];
00440                                                                 }
00441                                                         }
00442                                                 }
00443                                         }
00444 
00445                                         if (is_array($outRow[$field]['softrefs']) && count($outRow[$field]['softrefs']) && strcmp($value,$softRefValue) && strstr($softRefValue,'{softref:'))   {
00446                                                 $outRow[$field]['softrefs']['tokenizedContent'] = $softRefValue;
00447                                         }
00448                                 }
00449                         }
00450                 }
00451 
00452                 return $outRow;
00453         }
00454 
00466         function getRelations_flexFormCallBack($dsArr, $dataValue, $PA, $structurePath, &$pObj) {
00467                 $structurePath = substr($structurePath,5).'/';  // removing "data/" in the beginning of path (which points to location in data array)
00468 
00469                 $dsConf = $dsArr['TCEforms']['config'];
00470 
00471                         // Implode parameter values:
00472                 list($table, $uid, $field) = array($PA['table'],$PA['uid'],$PA['field']);
00473 
00474                         // Add files
00475                 if ($result = $this->getRelations_procFiles($dataValue, $dsConf, $uid)) {
00476 
00477                                 // Creates an entry for the field with all the files:
00478                         $this->temp_flexRelations['file'][$structurePath] = $result;
00479                 }
00480 
00481                         // Add DB:
00482                 if ($result = $this->getRelations_procDB($dataValue, $dsConf, $uid))    {
00483 
00484                                 // Create an entry for the field with all DB relations:
00485                         $this->temp_flexRelations['db'][$structurePath] = $result;
00486                 }
00487 
00488                         // Soft References:
00489                 if (strlen($dataValue) && $softRefs = t3lib_BEfunc::explodeSoftRefParserList($dsConf['softref']))       {
00490                         $softRefValue = $dataValue;
00491                         foreach($softRefs as $spKey => $spParams)       {
00492                                 $softRefObj = &t3lib_BEfunc::softRefParserObj($spKey);
00493                                 if (is_object($softRefObj))     {
00494                                         $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams, $structurePath);
00495                                         if (is_array($resultArray) && is_array($resultArray['elements']))       {
00496                                                 $this->temp_flexRelations['softrefs'][$structurePath]['keys'][$spKey] = $resultArray['elements'];
00497                                                 if (strlen($resultArray['content'])) $softRefValue = $resultArray['content'];
00498                                         }
00499                                 }
00500                         }
00501 
00502                         if (count($this->temp_flexRelations['softrefs']) && strcmp($dataValue,$softRefValue))   {
00503                                 $this->temp_flexRelations['softrefs'][$structurePath]['tokenizedContent'] = $softRefValue;
00504                         }
00505                 }
00506         }
00507 
00516         function getRelations_procFiles($value, $conf, $uid)    {
00517                         // Take care of files...
00518                 if ($conf['type']=='group' && $conf['internal_type']=='file')   {
00519 
00520                                 // Collect file values in array:
00521                         if ($conf['MM'])        {
00522                                 $theFileValues = array();
00523                                 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
00524                                 $dbAnalysis->start('', 'files', $conf['MM'], $uid);
00525 
00526                                 foreach($dbAnalysis->itemArray as $somekey => $someval) {
00527                                         if ($someval['id'])     {
00528                                                 $theFileValues[] = $someval['id'];
00529                                         }
00530                                 }
00531                         } else {
00532                                 $theFileValues = explode(',',$value);
00533                         }
00534 
00535                                 // Traverse the files and add them:
00536                         $uploadFolder = $conf['uploadfolder'];
00537                         $dest = $this->destPathFromUploadFolder($uploadFolder);
00538                         $newValue = array();
00539                         $newValueFiles = array();
00540 
00541                         foreach($theFileValues as $file)        {
00542                                 if (trim($file))        {
00543                                         $realFile = $dest.'/'.trim($file);
00544                                         if (@is_file($realFile))        {
00545                                                 $newValueFiles[] = array(
00546                                                         'filename' => $file,
00547                                                         'ID' => md5($realFile),
00548                                                         'ID_absFile' => $realFile
00549                                                 );      // the order should be preserved here because.. (?)
00550                                         } else $this->error('Missing file: '.$realFile);
00551                                 }
00552                         }
00553 
00554                         return $newValueFiles;
00555                 }
00556         }
00557 
00566         function getRelations_procDB($value, $conf, $uid)       {
00567 
00568                         // DB record lists:
00569                 if ($this->isReferenceField($conf))     {
00570                         $allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table'];
00571                         $prependName = $conf['type']=='group' ? $conf['prepend_tname'] : $conf['neg_foreign_table'];
00572 
00573                         $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
00574                         $dbAnalysis->start($value,$allowedTables,$conf['MM'],$uid);
00575 
00576                         return $dbAnalysis->itemArray;
00577                 }
00578         }
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591         /*******************************
00592          *
00593          * Helper functions
00594          *
00595          *******************************/
00596 
00603         function isReferenceField($conf)        {
00604                 return ($conf['type']=='group' && $conf['internal_type']=='db') ||      ($conf['type']=='select' && $conf['foreign_table']);
00605         }
00606 
00613         function destPathFromUploadFolder($folder)      {
00614                 return PATH_site.$folder;
00615         }
00616 
00623         function error($msg)    {
00624                 $this->errorLog[]=$msg;
00625         }
00626 
00634         function updateIndex($testOnly,$cli_echo=FALSE) {
00635                 global $TCA, $TYPO3_DB;
00636 
00637                 $errors = array();
00638                 $tableNames = array();
00639                 $recCount=0;
00640                 $tableCount=0;
00641 
00642                 $headerContent = $testOnly ? 'Reference Index TESTED (nothing written)' : 'Reference Index Updated';
00643                 if ($cli_echo) echo
00644                                                 '*******************************************'.chr(10).
00645                                                 $headerContent.chr(10).
00646                                                 '*******************************************'.chr(10);
00647 
00648                         // Traverse all tables:
00649                 foreach ($TCA as $tableName => $cfg)    {
00650                         $tableNames[] = $tableName;
00651                         $tableCount++;
00652 
00653                                 // Traverse all non-deleted records in tables:
00654                         $allRecs = $TYPO3_DB->exec_SELECTgetRows('uid',$tableName,'1=1');       //.t3lib_BEfunc::deleteClause($tableName)
00655                         $uidList = array(0);
00656                         foreach ($allRecs as $recdat)   {
00657                                 $refIndexObj = t3lib_div::makeInstance('t3lib_refindex');
00658                                 $result = $refIndexObj->updateRefIndexTable($tableName,$recdat['uid'],$testOnly);
00659                                 $uidList[]= $recdat['uid'];
00660                                 $recCount++;
00661 
00662                                 if ($result['addedNodes'] || $result['deletedNodes'])   {
00663                                         $Err = 'Record '.$tableName.':'.$recdat['uid'].' had '.$result['addedNodes'].' added indexes and '.$result['deletedNodes'].' deleted indexes';
00664                                         $errors[]= $Err;
00665                                         if ($cli_echo) echo $Err.chr(10);
00666                                         #$errors[] = t3lib_div::view_array($result);
00667                                 }
00668                         }
00669 
00670                                 // Searching lost indexes for this table:
00671                         $where = 'tablename='.$TYPO3_DB->fullQuoteStr($tableName,'sys_refindex').' AND recuid NOT IN ('.implode(',',$uidList).')';
00672                         $lostIndexes = $TYPO3_DB->exec_SELECTgetRows('hash','sys_refindex',$where);
00673                         if (count($lostIndexes))        {
00674                                 $Err = 'Table '.$tableName.' has '.count($lostIndexes).' lost indexes which are now deleted';
00675                                 $errors[]= $Err;
00676                                 if ($cli_echo) echo $Err.chr(10);
00677                                 if (!$testOnly) $TYPO3_DB->exec_DELETEquery('sys_refindex',$where);
00678                         }
00679                 }
00680 
00681                         // Searching lost indexes for non-existing tables:
00682                 $where = 'tablename NOT IN ('.implode(',',$TYPO3_DB->fullQuoteArray($tableNames,'sys_refindex')).')';
00683                 $lostTables = $TYPO3_DB->exec_SELECTgetRows('hash','sys_refindex',$where);
00684                 if (count($lostTables)) {
00685                         $Err = 'Index table hosted '.count($lostTables).' indexes for non-existing tables, now removed';
00686                         $errors[]= $Err;
00687                         if ($cli_echo) echo $Err.chr(10);
00688                         if (!$testOnly) $TYPO3_DB->exec_DELETEquery('sys_refindex',$where);
00689                 }
00690 
00691                 $testedHowMuch = $recCount.' records from '.$tableCount.' tables were checked/updated.'.chr(10);
00692 
00693                 $bodyContent = $testedHowMuch.(count($errors)?implode(chr(10),$errors):'Index Integrity was perfect!');
00694                 if ($cli_echo) echo $testedHowMuch.(count($errors)?'Updates: '.count($errors):'Index Integrity was perfect!').chr(10);
00695 
00696                 return array($headerContent,$bodyContent);
00697         }
00698 }
00699 
00700 
00701 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_refindex.php'])  {
00702         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_refindex.php']);
00703 }
00704 ?>