Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2004 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 ***************************************************************/ 00163 // ******************************* 00164 // Including necessary libraries 00165 // ******************************* 00166 require_once (PATH_t3lib.'class.t3lib_loaddbgroup.php'); 00167 require_once (PATH_t3lib.'class.t3lib_parsehtml_proc.php'); 00168 require_once (PATH_t3lib.'class.t3lib_stdgraphic.php'); 00169 require_once (PATH_t3lib.'class.t3lib_basicfilefunc.php'); 00170 00171 00172 00173 00174 00175 00176 00177 00178 00179 00180 00181 00182 00199 class t3lib_TCEmain { 00200 var $log_table = 'sys_log'; 00201 00202 var $checkStoredRecords = 1; // This will read the record after having updated or inserted it. If anything is not properly submitted an error is written to the log. This feature consumes extra time by selecting records 00203 var $checkStoredRecords_loose=1; // If set, values '' and 0 will equal each other when the stored records are checked. 00204 var $sortIntervals = 256; // The interval between sorting numbers used with tables with a 'sorting' field defined. Min 1 00205 00206 var $deleteTree = 0; // Boolean. If this is set, then a page is deleted by deleting the whole branch under it (user must have deletepermissions to it all). If not set, then the page is delete ONLY if it has no branch 00207 var $copyTree = 0; // int. If 0 then branch is NOT copied. If 1 then pages on the 1st level is copied. If 2 then pages on the second level is copied ... and so on 00208 var $versionizeTree = 0; // int. If 0 then branch is NOT versionized. If 1 then pages on the 1st level is versionized. If 2 then pages on the second level is versionized ... and so on 00209 var $neverHideAtCopy = 0; // Boolean. If set, then the 'hideAtCopy' flag for tables will be ignored. 00210 var $reverseOrder=0; // boolean. If set, the dataarray is reversed in the order, which is a nice thing if you're creating a whole new bunch of records. 00211 var $copyWhichTables = '*'; // This list of tables decides which tables will be copied. If empty then none will. If '*' then all will (that the user has permission to of course) 00212 var $stripslashes_values=1; // If set, incoming values in the data-array have their slashes stripped. ALWAYS SET THIS TO ZERO and supply an unescaped data array instead. This switch may totally disappear in future versions of this class! 00213 var $storeLogMessages=1; // If set, the default log-messages will be stored. This should not be necessary if the locallang-file for the log-display is properly configured. So disabling this will just save some database-space as the default messages are not saved. 00214 var $enableLogging=1; // If set, actions are logged. 00215 00216 // var $history=1; // Bit-array: Bit0: History on/off. DEPENDS on checkSimilar to be set! 00217 var $checkSimilar=1; // Boolean: If set, only fields which are different from the database values are saved! In fact, if a whole input array is similar, it's not saved then. 00218 var $dontProcessTransformations=0; // Boolean: If set, then transformations are NOT performed on the input. 00219 # var $disableRTE = 0; // Boolean: If set, the RTE is expected to have been disabled in the interface which submitted information. Thus transformations related to the RTE is not done. 00220 00221 var $pMap = Array( // Permission mapping 00222 'show' => 1, // 1st bit 00223 'edit' => 2, // 2nd bit 00224 'delete' => 4, // 3rd bit 00225 'new' => 8, // 4th bit 00226 'editcontent' => 16 // 5th bit 00227 ); 00228 var $defaultPermissions = array( // Can be overridden from $TYPO3_CONF_VARS 00229 'user' => 'show,edit,delete,new,editcontent', 00230 'group' => 'show,edit,new,editcontent', 00231 'everybody' => '' 00232 ); 00233 00234 00235 var $alternativeFileName=array(); // Use this array to force another name onto a file. Eg. if you set ['/tmp/blablabal'] = 'my_file.txt' and '/tmp/blablabal' is set for a certain file-field, then 'my_file.txt' will be used as the name instead. 00236 var $data_disableFields=array(); // If entries are set in this array corresponding to fields for update, they are ignored and thus NOT updated. You could set this array from a series of checkboxes with value=0 and hidden fields before the checkbox with 1. Then an empty checkbox will disable the field. 00237 var $defaultValues=array(); // You can set this array on the form $defaultValues[$table][$field] = $value to override the default values fetched from TCA. You must set this externally. 00238 var $overrideValues=array(); // You can set this array on the form $overrideValues[$table][$field] = $value to override the incoming data. You must set this externally. You must make sure the fields in this array are also found in the table, because it's not checked. All columns can be set by this array! 00239 00240 // ********* 00241 // internal 00242 // ********* 00243 var $fileFunc; // May contain an object 00244 var $last_log_id; 00245 var $BE_USER; // The user-object the the script uses. If not set from outside, this is set to the current global $BE_USER. 00246 var $userid; // will be set to uid of be_user executing this script 00247 var $username; // will be set to username of be_user executing this script 00248 var $admin; // will be set if user is admin 00249 var $exclude_array; // the list of <table>-<fields> that cannot be edited. This is compiled from TCA/exclude-flag combined with non_exclude_fields for the user. 00250 00251 var $data = Array(); 00252 var $datamap = Array(); 00253 var $cmd = Array(); 00254 var $cmdmap = Array(); 00255 var $uploadedFileArray = array(); 00256 00257 var $cachedTSconfig = array(); 00258 var $substNEWwithIDs = Array(); 00259 var $substNEWwithIDs_table = Array(); 00260 var $recUpdateAccessCache = Array(); // Used by function checkRecordUpdateAccess() to store whether a record is updateable or not. 00261 var $recInsertAccessCache = Array(); 00262 var $isRecordInWebMount_Cache=array(); 00263 var $isInWebMount_Cache=array(); 00264 var $pageCache = Array(); // Used for caching page records in pageInfo() 00265 var $copyMappingArray = Array(); // Use by the copy action to track the ids of new pages so subpages are correctly inserted! 00266 var $copyMappingArray_merged = Array(); // This array is the sum of all copying operations in this class 00267 var $registerDBList=array(); 00268 var $dbAnalysisStore=array(); 00269 var $removeFilesStore=array(); 00270 var $copiedFileMap=array(); 00271 00272 var $checkValue_currentRecord=array(); // Set to "currentRecord" during checking of values. 00273 00274 00285 function start($data,$cmd,$altUserObject='') { 00286 // Initializing BE_USER 00287 $this->BE_USER = is_object($altUserObject) ? $altUserObject : $GLOBALS['BE_USER']; 00288 $this->userid = $this->BE_USER->user['uid']; 00289 $this->username = $this->BE_USER->user['username']; 00290 $this->admin = $this->BE_USER->user['admin']; 00291 00292 // Initializing default permissions for pages 00293 $defaultPermissions = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPermissions']; 00294 if (isset($defaultPermissions['user'])) {$this->defaultPermissions['user'] = $defaultPermissions['user'];} 00295 if (isset($defaultPermissions['group'])) {$this->defaultPermissions['group'] = $defaultPermissions['group'];} 00296 if (isset($defaultPermissions['everybody'])) {$this->defaultPermissions['everybody'] = $defaultPermissions['everybody'];} 00297 00298 // generates the excludelist, based on TCA/exclude-flag and non_exclude_fields for the user: 00299 $this->exclude_array = ($this->admin) ? array() : $this->getExcludeListArray(); 00300 00301 // Setting the data and cmd arrays 00302 if (is_array($data)) { 00303 reset($data); 00304 $this->datamap = $data; 00305 } 00306 if (is_array($cmd)) { 00307 reset($cmd); 00308 $this->cmdmap = $cmd; 00309 } 00310 } 00311 00318 function setMirror($mirror) { 00319 if (is_array($mirror)) { 00320 reset($mirror); 00321 while(list($table,$uid_array)=each($mirror)) { 00322 if (isset($this->datamap[$table])) { 00323 reset($uid_array); 00324 while (list($id,$uidList) = each($uid_array)) { 00325 if (isset($this->datamap[$table][$id])) { 00326 $theIdsInArray = t3lib_div::trimExplode(',',$uidList,1); 00327 while(list(,$copyToUid)=each($theIdsInArray)) { 00328 $this->datamap[$table][$copyToUid] = $this->datamap[$table][$id]; 00329 } 00330 } 00331 } 00332 } 00333 } 00334 } 00335 } 00336 00343 function setDefaultsFromUserTS($userTS) { 00344 global $TCA; 00345 if (is_array($userTS)) { 00346 foreach($userTS as $k => $v) { 00347 $k = substr($k,0,-1); 00348 if ($k && is_array($v) && isset($TCA[$k])) { 00349 if (is_array($this->defaultValues[$k])) { 00350 $this->defaultValues[$k] = array_merge($this->defaultValues[$k],$v); 00351 } else { 00352 $this->defaultValues[$k] = $v; 00353 } 00354 } 00355 } 00356 } 00357 } 00358 00366 function process_uploads($postFiles) { 00367 if (is_array($postFiles)) { 00368 reset($postFiles); 00369 $subA = current($postFiles); 00370 if (is_array($subA)) { 00371 if (is_array($subA['name']) && is_array($subA['type']) && is_array($subA['tmp_name']) && is_array($subA['size'])) { 00372 // Initialize the uploadedFilesArray: 00373 $this->uploadedFileArray=array(); 00374 00375 // For each entry: 00376 foreach($subA as $key => $values) { 00377 $this->process_uploads_traverseArray($this->uploadedFileArray,$values,$key); 00378 } 00379 } else { 00380 $this->uploadedFileArray=$subA; 00381 } 00382 } 00383 } 00384 } 00385 00396 function process_uploads_traverseArray(&$outputArr,$inputArr,$keyToSet) { 00397 if (is_array($inputArr)) { 00398 foreach($inputArr as $key => $value) { 00399 $this->process_uploads_traverseArray($outputArr[$key],$inputArr[$key],$keyToSet); 00400 } 00401 } else { 00402 $outputArr[$keyToSet]=$inputArr; 00403 } 00404 } 00405 00406 00407 00408 00409 00410 00411 00412 00413 00414 00415 00416 00417 00418 00419 00420 /********************************************* 00421 * 00422 * PROCESSING DATA 00423 * 00424 *********************************************/ 00425 00432 function process_datamap() { 00433 global $TCA, $TYPO3_CONF_VARS; 00434 00435 // First prepare user defined objects (if any) for hooks which extend this function: 00436 $hookObjectsArr = array(); 00437 if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'])) { 00438 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] as $classRef) { 00439 $hookObjectsArr[] = &t3lib_div::getUserObj($classRef); 00440 } 00441 } 00442 00443 // Organize tables so that the pages-table are always processed first. This is required if you want to make sure that content pointing to a new page will be created. 00444 $orderOfTables = Array(); 00445 if (isset($this->datamap['pages'])) { // Set pages first. 00446 $orderOfTables[]='pages'; 00447 } 00448 reset($this->datamap); 00449 while (list($table,) = each($this->datamap)) { 00450 if ($table!='pages') { 00451 $orderOfTables[]=$table; 00452 } 00453 } 00454 00455 // Process the tables... 00456 foreach($orderOfTables as $table) { 00457 /* Check if 00458 - table is set in $TCA, 00459 - table is NOT readOnly, 00460 - the table is set with content in the data-array (if not, there's nothing to process...) 00461 - permissions for tableaccess OK 00462 */ 00463 $modifyAccessList = $this->checkModifyAccessList($table); 00464 if (!$modifyAccessList) { 00465 $this->log($table,$id,2,0,1,"Attempt to modify table '%s' without permission",1,array($table)); 00466 } 00467 if (isset($TCA[$table]) && !$this->tableReadOnly($table) && is_array($this->datamap[$table]) && $modifyAccessList) { 00468 if ($this->reverseOrder) { 00469 $this->datamap[$table] = array_reverse($this->datamap[$table], 1); 00470 } 00471 00472 // For each record from the table, do: 00473 // $id is the record uid, may be a string if new records... 00474 // $incomingFieldArray is the array of fields 00475 foreach($this->datamap[$table] as $id => $incomingFieldArray) { 00476 if (is_array($incomingFieldArray)) { 00477 00478 // Hook: processDatamap_preProcessIncomingFieldArray 00479 foreach($hookObjectsArr as $hookObj) { 00480 if (method_exists($hookObj, 'processDatamap_preProcessIncomingFieldArray')) { 00481 $hookObj->processDatamap_preProcessFieldArray($incomingFieldArray, $table, $id, $this); 00482 } 00483 } 00484 00485 // ****************************** 00486 // Checking access to the record 00487 // ****************************** 00488 $recordAccess = 0; 00489 $old_pid_value = ''; 00490 if (!t3lib_div::testInt($id)) { // Is it a new record? (Then Id is a string) 00491 $fieldArray = $this->newFieldArray($table); // Get a fieldArray with default values 00492 if (isset($incomingFieldArray['pid'])) { // A pid must be set for new records. 00493 // $value = the pid 00494 $pid_value = $incomingFieldArray['pid']; 00495 00496 // Checking and finding numerical pid, it may be a string-reference to another value 00497 $OK = 1; 00498 if (strstr($pid_value,'NEW')) { // If a NEW... id 00499 if (substr($pid_value,0,1)=='-') {$negFlag=-1;$pid_value=substr($pid_value,1);} else {$negFlag=1;} 00500 if (isset($this->substNEWwithIDs[$pid_value])) { // Trying to find the correct numerical value as it should be mapped by earlier processing of another new record. 00501 $old_pid_value = $pid_value; 00502 $pid_value=intval($negFlag*$this->substNEWwithIDs[$pid_value]); 00503 } else {$OK = 0;} // If not found in the substArray we must stop the proces... 00504 } 00505 $pid_value = intval($pid_value); 00506 00507 // The $pid_value is now the numerical pid at this point 00508 if ($OK) { 00509 $sortRow = $TCA[$table]['ctrl']['sortby']; 00510 if ($pid_value>=0) { // Points to a page on which to insert the element, possibly in the top of the page 00511 if ($sortRow) { // If this table is sorted we better find the top sorting number 00512 $fieldArray[$sortRow] = $this->getSortNumber($table,0,$pid_value); 00513 } 00514 $fieldArray['pid'] = $pid_value; // The numerical pid is inserted in the data array 00515 } else { // points to another record before ifself 00516 if ($sortRow) { // If this table is sorted we better find the top sorting number 00517 $tempArray=$this->getSortNumber($table,0,$pid_value); // Because $pid_value is < 0, getSortNumber returns an array 00518 $fieldArray['pid'] = $tempArray['pid']; 00519 $fieldArray[$sortRow] = $tempArray['sortNumber']; 00520 } else { // Here we fetch the PID of the record that we point to... 00521 $tempdata = $this->recordInfo($table,abs($pid_value),'pid'); 00522 $fieldArray['pid']=$tempdata['pid']; 00523 } 00524 } 00525 } 00526 } 00527 $theRealPid = $fieldArray['pid']; 00528 // Now, check if we may insert records on this pid. 00529 if ($theRealPid>=0) { 00530 $recordAccess = $this->checkRecordInsertAccess($table,$theRealPid); // Checks if records can be inserted on this $pid. 00531 } else { 00532 debug('Internal ERROR: pid should not be less than zero!'); 00533 } 00534 $status = 'new'; // Yes new record, change $record_status to 'insert' 00535 } else { // Nope... $id is a number 00536 $fieldArray = Array(); 00537 $recordAccess = $this->checkRecordUpdateAccess($table,$id); 00538 if (!$recordAccess) { 00539 $propArr = $this->getRecordProperties($table,$id); 00540 $this->log($table,$id,2,0,1,"Attempt to modify record '%s' (%s) without permission. Or non-existing page.",2,array($propArr['header'],$table.':'.$id),$propArr['event_pid']); 00541 } else { // Next check of the record permissions (internals) 00542 $recordAccess = $this->BE_USER->recordEditAccessInternals($table,$id); 00543 if (!$recordAccess) { 00544 $propArr = $this->getRecordProperties($table,$id); 00545 $this->log($table,$id,2,0,1,"recordEditAccessInternals() check failed. [".$this->BE_USER->errorMsg."]",2,array($propArr['header'],$table.':'.$id),$propArr['event_pid']); 00546 } else { // Here we fetch the PID of the record that we point to... 00547 $tempdata = $this->recordInfo($table,$id,'pid'); 00548 $theRealPid = $tempdata['pid']; 00549 } 00550 } 00551 $status = 'update'; // the default is 'update' 00552 } 00553 00554 // ************************************** 00555 // If access was granted above, proceed: 00556 // ************************************** 00557 if ($recordAccess) { 00558 00559 list($tscPID) = t3lib_BEfunc::getTSCpid($table,$id,$old_pid_value ? $old_pid_value : $fieldArray['pid']); // Here the "pid" is sent IF NOT the old pid was a string pointing to a place in the subst-id array. 00560 $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); 00561 if ($status=='new' && $table=='pages' && is_array($TSConfig['permissions.'])) { 00562 $fieldArray = $this->setTSconfigPermissions($fieldArray,$TSConfig['permissions.']); 00563 } 00564 00565 $fieldArray = $this->fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$theRealPid,$status,$tscPID); 00566 00567 // NOTICE! All manipulation beyond this point bypasses both "excludeFields" AND possible "MM" relations / file uploads to field! 00568 00569 $fieldArray = $this->overrideFieldArray($table,$fieldArray); // NOTICE: This overriding is potentially dangerous; permissions per field is not checked!!! 00570 00571 // Setting system fields 00572 if ($status=='new') { 00573 if ($TCA[$table]['ctrl']['crdate']) { 00574 $fieldArray[$TCA[$table]['ctrl']['crdate']]=time(); 00575 } 00576 if ($TCA[$table]['ctrl']['cruser_id']) { 00577 $fieldArray[$TCA[$table]['ctrl']['cruser_id']]=$this->userid; 00578 } 00579 } elseif ($this->checkSimilar) { // Removing fields which are equal to the current value: 00580 $fieldArray = $this->compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray); 00581 } 00582 if ($TCA[$table]['ctrl']['tstamp']) { 00583 $fieldArray[$TCA[$table]['ctrl']['tstamp']]=time(); 00584 } 00585 00586 // Hook: processDatamap_postProcessFieldArray 00587 foreach($hookObjectsArr as $hookObj) { 00588 if (method_exists($hookObj, 'processDatamap_postProcessFieldArray')) { 00589 $hookObj->processDatamap_postProcessFieldArray($status, $table, $id, $fieldArray, $this); 00590 } 00591 } 00592 00593 // Performing insert/update. If fieldArray has been unset by some userfunction (see hook above), don't do anything 00594 // Kasper: Unsetting the fieldArray is dangerous; MM relations might be saved already and files could have been uploaded that are now "lost" 00595 if (is_array($fieldArray)) { 00596 if ($status=='new') { 00597 // if ($pid_value<0) {$fieldArray = $this->fixCopyAfterDuplFields($table,$id,abs($pid_value),0,$fieldArray);} // Out-commented 02-05-02: I couldn't understand WHY this is needed for NEW records. Obviously to proces records being copied? Problem is that the fields are not set anyways and the copying function should basically take care of this! 00598 $this->insertDB($table,$id,$fieldArray); 00599 } else { 00600 $this->updateDB($table,$id,$fieldArray); 00601 } 00602 } 00603 } // if ($recordAccess) { 00604 } // if (is_array($incomingFieldArray)) { 00605 } 00606 } 00607 } 00608 $this->dbAnalysisStoreExec(); 00609 $this->removeRegisteredFiles(); 00610 } 00611 00625 function fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$realPid,$status,$tscPID) { 00626 global $TCA; 00627 00628 // Initialize: 00629 t3lib_div::loadTCA($table); 00630 unset($originalLanguageRecord); 00631 unset($originalLanguage_diffStorage); 00632 $diffStorageFlag = FALSE; 00633 00634 // Setting 'currentRecord' and 'checkValueRecord': 00635 if (strstr($id,'NEW')) { 00636 $currentRecord = $checkValueRecord = $fieldArray; // must have the 'current' array - not the values after processing below... 00637 00638 // IF $incomingFieldArray is an array, overlay it. 00639 // The point is that when new records are created as copies with flex type fields there might be a field containing information about which DataStructure to use and without that information the flexforms cannot be correctly processed.... This should be OK since the $checkValueRecord is used by the flexform evaluation only anyways... 00640 if (is_array($incomingFieldArray) && is_array($checkValueRecord)) { 00641 $checkValueRecord = t3lib_div::array_merge_recursive_overrule($checkValueRecord, $incomingFieldArray); 00642 } 00643 } else { 00644 $currentRecord = $checkValueRecord = $this->recordInfo($table,$id,'*'); // We must use the current values as basis for this! 00645 00646 // Get original language record if available: 00647 if (is_array($currentRecord) 00648 && $TCA[$table]['ctrl']['transOrigDiffSourceField'] 00649 && $TCA[$table]['ctrl']['languageField'] 00650 && $currentRecord[$TCA[$table]['ctrl']['languageField']] > 0 00651 && $TCA[$table]['ctrl']['transOrigPointerField'] 00652 && intval($currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']]) > 0) { 00653 00654 $lookUpTable = $TCA[$table]['ctrl']['transOrigPointerTable'] ? $TCA[$table]['ctrl']['transOrigPointerTable'] : $table; 00655 $originalLanguageRecord = $this->recordInfo($lookUpTable,$currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']],'*'); 00656 $originalLanguage_diffStorage = unserialize($currentRecord[$TCA[$table]['ctrl']['transOrigDiffSourceField']]); 00657 } 00658 } 00659 $this->checkValue_currentRecord = $checkValueRecord; 00660 00661 /* 00662 In the following all incoming value-fields are tested: 00663 - Are the user allowed to change the field? 00664 - Is the field uid/pid (which are already set) 00665 - perms-fields for pages-table, then do special things... 00666 - If the field is nothing of the above and the field is configured in TCA, the fieldvalues are evaluated by ->checkValue 00667 00668 If everything is OK, the field is entered into $fieldArray[] 00669 */ 00670 foreach($incomingFieldArray as $field => $fieldValue) { 00671 if (!in_array($table.'-'.$field, $this->exclude_array) && !$this->data_disableFields[$table][$id][$field]) { // The field must be editable. 00672 00673 // Checking language: 00674 $languageDeny = $TCA[$table]['ctrl']['languageField'] && !strcmp($TCA[$table]['ctrl']['languageField'], $field) && !$this->BE_USER->checkLanguageAccess($fieldValue); 00675 00676 if (!$languageDeny) { 00677 // Stripping slashes - will probably be removed the day $this->stripslashes_values is removed as an option... 00678 if ($this->stripslashes_values) { 00679 if (is_array($fieldValue)) { 00680 t3lib_div::stripSlashesOnArray($fieldValue); 00681 } else $fieldValue = stripslashes($fieldValue); 00682 } 00683 00684 switch ($field) { 00685 case 'uid': 00686 case 'pid': 00687 // Nothing happens, already set 00688 break; 00689 case 'perms_userid': 00690 case 'perms_groupid': 00691 case 'perms_user': 00692 case 'perms_group': 00693 case 'perms_everybody': 00694 // Permissions can be edited by the owner or the administrator 00695 if ($table=='pages' && ($this->admin || $status=='new' || $this->pageInfo($id,'perms_userid')==$this->userid) ) { 00696 $value=intval($fieldValue); 00697 switch($field) { 00698 case 'perms_userid': 00699 $fieldArray[$field]=$value; 00700 break; 00701 case 'perms_groupid': 00702 $fieldArray[$field]=$value; 00703 break; 00704 default: 00705 if ($value>=0 && $value<pow(2,5)) { 00706 $fieldArray[$field]=$value; 00707 } 00708 break; 00709 } 00710 } 00711 break; 00712 case 't3ver_oid': 00713 case 't3ver_id': 00714 // t3ver_label is not here because it CAN be edited as a regular field! 00715 break; 00716 default: 00717 if (isset($TCA[$table]['columns'][$field])) { 00718 // Evaluating the value. 00719 $res = $this->checkValue($table,$field,$fieldValue,$id,$status,$realPid,$tscPID); 00720 if (isset($res['value'])) { 00721 $fieldArray[$field]=$res['value']; 00722 00723 // Add the value of the original record to the diff-storage content: 00724 if ($TCA[$table]['ctrl']['transOrigDiffSourceField']) { 00725 $originalLanguage_diffStorage[$field] = $originalLanguageRecord[$field]; 00726 $diffStorageFlag = TRUE; 00727 } 00728 } 00729 } 00730 00731 00732 break; 00733 } 00734 } // Checking language. 00735 } // Check exclude fields / disabled fields... 00736 } 00737 00738 // Add diff-storage information: 00739 if ($diffStorageFlag && !isset($fieldArray[$TCA[$table]['ctrl']['transOrigDiffSourceField']])) { // If the field is set it would probably be because of an undo-operation - in which case we should not update the field of course... 00740 $fieldArray[$TCA[$table]['ctrl']['transOrigDiffSourceField']] = serialize($originalLanguage_diffStorage); 00741 } 00742 00743 // Checking for RTE-transformations of fields: 00744 $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table,$currentRecord); 00745 $theTypeString = t3lib_BEfunc::getTCAtypeValue($table,$currentRecord); 00746 if (is_array($types_fieldConfig)) { 00747 reset($types_fieldConfig); 00748 while(list(,$vconf) = each($types_fieldConfig)) { 00749 // Write file configuration: 00750 $eFile = t3lib_parsehtml_proc::evalWriteFile($vconf['spec']['static_write'],array_merge($currentRecord,$fieldArray)); // inserted array_merge($currentRecord,$fieldArray) 170502 00751 00752 // RTE transformations: 00753 if (!$this->dontProcessTransformations) { 00754 if (isset($fieldArray[$vconf['field']])) { 00755 // Look for transformation flag: 00756 switch((string)$incomingFieldArray['_TRANSFORM_'.$vconf['field']]) { 00757 case 'RTE': 00758 $RTEsetup = $this->BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($tscPID)); 00759 $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'],$table,$vconf['field'],$theTypeString); 00760 00761 // Set alternative relative path for RTE images/links: 00762 $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : ''; 00763 00764 // Get RTE object, draw form and set flag: 00765 $RTEobj = &t3lib_BEfunc::RTEgetObj(); 00766 if (is_object($RTEobj)) { 00767 $fieldArray[$vconf['field']] = $RTEobj->transformContent('db',$fieldArray[$vconf['field']],$table,$vconf['field'],$currentRecord,$vconf['spec'],$thisConfig,$RTErelPath,$currentRecord['pid']); 00768 } else { 00769 debug('NO RTE OBJECT FOUND!'); 00770 } 00771 break; 00772 } 00773 } 00774 } 00775 00776 // Write file configuration: 00777 if (is_array($eFile)) { 00778 $mixedRec = array_merge($currentRecord,$fieldArray); 00779 $SW_fileContent = t3lib_div::getUrl($eFile['editFile']); 00780 $parseHTML = t3lib_div::makeInstance('t3lib_parsehtml_proc'); 00781 $parseHTML->init('',''); 00782 00783 $eFileMarker = $eFile['markerField']&&trim($mixedRec[$eFile['markerField']]) ? trim($mixedRec[$eFile['markerField']]) : '###TYPO3_STATICFILE_EDIT###'; 00784 $insertContent = str_replace($eFileMarker,'',$mixedRec[$eFile['contentField']]); // must replace the marker if present in content! 00785 00786 $SW_fileNewContent = $parseHTML->substituteSubpart($SW_fileContent, $eFileMarker, chr(10).$insertContent.chr(10), 1, 1); 00787 t3lib_div::writeFile($eFile['editFile'],$SW_fileNewContent); 00788 00789 // Write status: 00790 if (!strstr($id,'NEW') && $eFile['statusField']) { 00791 $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 00792 $table, 00793 'uid='.intval($id), 00794 array( 00795 $eFile['statusField'] => $eFile['relEditFile'].' updated '.date('d-m-Y H:i:s').', bytes '.strlen($mixedRec[$eFile['contentField']]) 00796 ) 00797 ); 00798 } 00799 } elseif ($eFile && is_string($eFile)) { 00800 $this->log($insertTable,$id,2,0,1,"Write-file error: '%s'",13,array($eFile),$realPid); 00801 } 00802 } 00803 } 00804 // Return fieldArray 00805 return $fieldArray; 00806 } 00807 00816 function checkModifyAccessList($table) { 00817 $res = ($this->admin || (!$this->tableAdminOnly($table) && t3lib_div::inList($this->BE_USER->groupData['tables_modify'],$table))); 00818 return $res; 00819 } 00820 00828 function isRecordInWebMount($table,$id) { 00829 if (!isset($this->isRecordInWebMount_Cache[$table.':'.$id])) { 00830 $recP=$this->getRecordProperties($table,$id); 00831 $this->isRecordInWebMount_Cache[$table.':'.$id]=$this->isInWebMount($recP['event_pid']); 00832 } 00833 return $this->isRecordInWebMount_Cache[$table.':'.$id]; 00834 } 00835 00842 function isInWebMount($pid) { 00843 if (!isset($this->isInWebMount_Cache[$pid])) { 00844 $this->isInWebMount_Cache[$pid]=$this->BE_USER->isInWebMount($pid); 00845 } 00846 //debug($this->isInWebMount_Cache); 00847 return $this->isInWebMount_Cache[$pid]; 00848 } 00849 00859 function checkRecordUpdateAccess($table,$id) { 00860 global $TCA; 00861 $res = 0; 00862 if ($TCA[$table] && intval($id)>0) { 00863 if (isset($this->recUpdateAccessCache[$table][$id])) { // If information is cached, return it 00864 return $this->recUpdateAccessCache[$table][$id]; 00865 // Check if record exists and 1) if 'pages' the page may be edited, 2) if page-content the page allows for editing 00866 } elseif ($this->doesRecordExist($table,$id,'edit')) { 00867 $res = 1; 00868 } 00869 $this->recUpdateAccessCache[$table][$id]=$res; // Cache the result 00870 } 00871 return $res; 00872 } 00873 00884 function checkRecordInsertAccess($insertTable,$pid,$action=1) { 00885 global $TCA; 00886 $res = 0; 00887 $pid = intval($pid); 00888 if ($pid>=0) { 00889 if (isset($this->recInsertAccessCache[$insertTable][$pid])) { // If information is cached, return it 00890 return $this->recInsertAccessCache[$insertTable][$pid]; 00891 } else { 00892 // If either admin and root-level or if page record exists and 1) if 'pages' you may create new ones 2) if page-content, new content items may be inserted on the $pid page 00893 if ( (!$pid && $this->admin) || $this->doesRecordExist('pages',$pid,($insertTable=='pages'?$this->pMap['new']:$this->pMap['editcontent'])) ) { // Check permissions 00894 if ($this->isTableAllowedForThisPage($pid, $insertTable)) { 00895 $res = 1; 00896 $this->recInsertAccessCache[$insertTable][$pid]=$res; // Cache the result 00897 } else { 00898 $propArr = $this->getRecordProperties('pages',$pid); 00899 $this->log($insertTable,$pid,$action,0,1,"Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed",11,array($propArr['header'],$pid,$insertTable),$propArr['event_pid']); 00900 } 00901 } else { 00902 $propArr = $this->getRecordProperties('pages',$pid); 00903 $this->log($insertTable,$pid,$action,0,1,"Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.",12,array($propArr['header'],$pid,$insertTable),$propArr['event_pid']); 00904 } 00905 } 00906 } 00907 return $res; 00908 } 00909 00920 function isTableAllowedForThisPage($page_uid, $checkTable) { 00921 global $TCA, $PAGES_TYPES; 00922 $page_uid = intval($page_uid); 00923 00924 // Check if rootLevel flag is set and we're trying to insert on rootLevel - and reversed - and that the table is not "pages" which are allowed anywhere. 00925 if (($TCA[$checkTable]['ctrl']['rootLevel'] xor !$page_uid) && $TCA[$checkTable]['ctrl']['rootLevel']!=-1 && $checkTable!='pages') { 00926 return false; 00927 } 00928 00929 // Check root-level 00930 if (!$page_uid) { 00931 if ($this->admin) { 00932 return true; 00933 } 00934 } else { 00935 // Check non-root-level 00936 $doktype = $this->pageInfo($page_uid,'doktype'); 00937 $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables']; 00938 $allowedArray = t3lib_div::trimExplode(',',$allowedTableList,1); 00939 if (strstr($allowedTableList,'*') || in_array($checkTable,$allowedArray)) { // If all tables or the table is listed as a allowed type, return true 00940 return true; 00941 } 00942 } 00943 } 00944 00955 function doesRecordExist($table,$id,$perms) { 00956 global $TCA; 00957 00958 $res = 0; 00959 $id = intval($id); 00960 00961 // Processing the incoming $perms (from possible string to integer that can be AND'ed) 00962 if (!t3lib_div::testInt($perms)) { 00963 if ($table!='pages') { 00964 switch($perms) { 00965 case 'edit': 00966 case 'delete': 00967 case 'new': 00968 $perms = 'editcontent'; // This holds it all in case the record is not page!! 00969 break; 00970 } 00971 } 00972 $perms = intval($this->pMap[$perms]); 00973 } else { 00974 $perms = intval($perms); 00975 } 00976 00977 if (!$perms) {debug('Internal ERROR: no permissions to check for non-admin user.');} 00978 00979 // For all tables: Check if record exists: 00980 // Notice: If $perms are 0 (zero) no perms-clause is added! 00981 if (is_array($TCA[$table]) && $id>0 && ($this->isRecordInWebMount($table,$id) || $this->admin)) { 00982 if ($table != 'pages') { 00983 00984 // Find record without checking page: 00985 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid', $table, 'uid='.intval($id).$this->deleteClause($table)); 00986 $output = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres); 00987 t3lib_BEfunc::fixVersioningPid($table,$output); 00988 00989 // If record found, check page as well: 00990 if (is_array($output)) { 00991 00992 // Looking up the page for record: 00993 $mres = $this->doesRecordExist_pageLookUp($output['pid'], $perms); 00994 $pageRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres); 00995 00996 // Return true if either a page was found OR if the PID is zero AND the user is ADMIN (in which case the record is at root-level): 00997 if (is_array($pageRec) || (!$output['pid'] && $this->admin)) { 00998 return TRUE; 00999 } 01000 } 01001 return FALSE; 01002 } else { 01003 $mres = $this->doesRecordExist_pageLookUp($id, $perms); 01004 return $GLOBALS['TYPO3_DB']->sql_num_rows($mres); 01005 } 01006 } 01007 } 01008 01018 function doesRecordExist_pageLookUp($id, $perms) { 01019 global $TCA; 01020 01021 return $GLOBALS['TYPO3_DB']->exec_SELECTquery( 01022 'uid', 01023 'pages', 01024 'uid='.intval($id). 01025 $this->deleteClause('pages'). 01026 ($perms && !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($perms) : ''). 01027 (!$this->admin && $TCA['pages']['ctrl']['editlock'] && ($perms & (2+4+16)) ? ' AND '.$TCA['pages']['ctrl']['editlock'].'=0':'') // admin users don't need check 01028 ); 01029 } 01030 01044 function doesBranchExist($inList,$pid,$perms, $recurse) { 01045 global $TCA; 01046 $pid = intval($pid); 01047 $perms = intval($perms); 01048 if ($pid>=0) { 01049 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 01050 'uid, perms_userid, perms_groupid, perms_user, perms_group, perms_everybody', 01051 'pages', 01052 'pid='.intval($pid).$this->deleteClause('pages'), 01053 '', 01054 'sorting' 01055 ); 01056 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 01057 if ($this->admin || $this->BE_USER->doesUserHaveAccess($row,$perms)) { // IF admin, then it's OK 01058 $inList.=$row['uid'].','; 01059 if ($recurse) { // Follow the subpages recursively... 01060 $inList = $this->doesBranchExist($inList, $row['uid'], $perms, $recurse); 01061 if ($inList == -1) {return -1;} // No permissions somewhere in the branch 01062 } 01063 } else { 01064 return -1; // No permissions 01065 } 01066 } 01067 } 01068 return $inList; 01069 } 01070 01079 function pageInfo($id,$field) { 01080 if (!isset($this->pageCache[$id])) { 01081 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages', 'uid='.intval($id)); 01082 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) { 01083 $this->pageCache[$id] = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 01084 } 01085 $GLOBALS['TYPO3_DB']->sql_free_result($res); 01086 } 01087 return $this->pageCache[$id][$field]; 01088 } 01089 01099 function recordInfo($table,$id,$fieldList) { 01100 global $TCA; 01101 if (is_array($TCA[$table])) { 01102 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldList, $table, 'uid='.intval($id)); 01103 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) { 01104 return $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 01105 } 01106 } 01107 } 01108 01116 function getRecordProperties($table,$id) { 01117 $row = ($table=='pages' && !$id) ? array('title'=>'[root-level]', 'uid' => 0, 'pid' => 0) :$this->recordInfo($table,$id,'*'); 01118 t3lib_BEfunc::fixVersioningPid($table,$row); 01119 return $this->getRecordPropertiesFromRow($table,$row); 01120 } 01121 01129 function getRecordPropertiesFromRow($table,$row) { 01130 global $TCA; 01131 if ($TCA[$table]) { 01132 $out = array( 01133 'header' => $row[$TCA[$table]['ctrl']['label']], 01134 'pid' => $row['pid'], 01135 'event_pid' => ($table=='pages'?$row['uid']:$row['pid']) 01136 ); 01137 return $out; 01138 } 01139 } 01140 01148 function setTSconfigPermissions($fieldArray,$TSConfig_p) { 01149 if (strcmp($TSConfig_p['userid'],'')) $fieldArray['perms_userid']=intval($TSConfig_p['userid']); 01150 if (strcmp($TSConfig_p['groupid'],'')) $fieldArray['perms_groupid']=intval($TSConfig_p['groupid']); 01151 if (strcmp($TSConfig_p['user'],'')) $fieldArray['perms_user']=t3lib_div::testInt($TSConfig_p['user']) ? $TSConfig_p['user'] : $this->assemblePermissions($TSConfig_p['user']); 01152 if (strcmp($TSConfig_p['group'],'')) $fieldArray['perms_group']=t3lib_div::testInt($TSConfig_p['group']) ? $TSConfig_p['group'] : $this->assemblePermissions($TSConfig_p['group']); 01153 if (strcmp($TSConfig_p['everybody'],'')) $fieldArray['perms_everybody']=t3lib_div::testInt($TSConfig_p['everybody']) ? $TSConfig_p['everybody'] : $this->assemblePermissions($TSConfig_p['everybody']); 01154 01155 return $fieldArray; 01156 } 01157 01164 function newFieldArray($table) { 01165 global $TCA; 01166 t3lib_div::loadTCA($table); 01167 $fieldArray=Array(); 01168 if (is_array($TCA[$table]['columns'])) { 01169 reset ($TCA[$table]['columns']); 01170 while (list($field,$content)=each($TCA[$table]['columns'])) { 01171 if (isset($this->defaultValues[$table][$field])) { 01172 $fieldArray[$field] = $this->defaultValues[$table][$field]; 01173 } elseif (isset($content['config']['default'])) { 01174 $fieldArray[$field] = $content['config']['default']; 01175 } 01176 } 01177 } 01178 if ($table=='pages') { // Set default permissions for a page. 01179 $fieldArray['perms_userid'] = $this->userid; 01180 $fieldArray['perms_groupid'] = intval($this->BE_USER->firstMainGroup); 01181 $fieldArray['perms_user'] = $this->assemblePermissions($this->defaultPermissions['user']); 01182 $fieldArray['perms_group'] = $this->assemblePermissions($this->defaultPermissions['group']); 01183 $fieldArray['perms_everybody'] = $this->assemblePermissions($this->defaultPermissions['everybody']); 01184 } 01185 return $fieldArray; 01186 } 01187 01195 function overrideFieldArray($table,$data) { 01196 if (is_array($this->overrideValues[$table])) { 01197 $data = array_merge($data,$this->overrideValues[$table]); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble... 01198 } 01199 return $data; 01200 } 01201 01208 function assemblePermissions($string) { 01209 $keyArr = t3lib_div::trimExplode(',',$string,1); 01210 $value=0; 01211 while(list(,$key)=each($keyArr)) { 01212 if ($key && isset($this->pMap[$key])) { 01213 $value |= $this->pMap[$key]; 01214 } 01215 } 01216 return $value; 01217 } 01218 01219 01220 01221 01222 01223 01224 01225 01226 01227 01228 01229 01230 01231 01232 01233 01234 01235 01236 01237 01238 /********************************************* 01239 * 01240 * Evaluation of input values 01241 * 01242 ********************************************/ 01243 01258 function checkValue($table,$field,$value,$id,$status,$realPid,$tscPID) { 01259 global $TCA, $PAGES_TYPES; 01260 t3lib_div::loadTCA($table); 01261 01262 $res = Array(); // result array 01263 $recFID = $table.':'.$id.':'.$field; 01264 01265 // Processing special case of field pages.doktype 01266 if ($table=='pages' && $field=='doktype') { 01267 // If the user may not use this specific doktype, we issue a warning 01268 if (! ($this->admin || t3lib_div::inList($this->BE_USER->groupData['pagetypes_select'],$value))) { 01269 $propArr = $this->getRecordProperties($table,$id); 01270 $this->log($table,$id,5,0,1,"You cannot change the 'doktype' of page '%s' to the desired value.",1,array($propArr['header']),$propArr['event_pid']); 01271 return $res; 01272 }; 01273 if ($status=='update') { 01274 // This checks if 1) we should check for disallowed tables and 2) the there are records from disallowed tables on the current page 01275 $onlyAllowedTables = isset($PAGES_TYPES[$value]['onlyAllowedTables']) ? $PAGES_TYPES[$value]['onlyAllowedTables'] : $PAGES_TYPES['default']['onlyAllowedTables']; 01276 if ($onlyAllowedTables) { 01277 $theWrongTables = $this->doesPageHaveUnallowedTables($id,$value); 01278 if ($theWrongTables) { 01279 $propArr = $this->getRecordProperties($table,$id); 01280 $this->log($table,$id,5,0,1,"'doktype' of page '%s' could not be changed because the page contains records from disallowed tables; %s",2,array($propArr['header'],$theWrongTables),$propArr['event_pid']); 01281 return $res; 01282 } 01283 } 01284 } 01285 } 01286 01287 // Get current value: 01288 $curValueRec = $this->recordInfo($table,$id,$field); 01289 $curValue = $curValueRec[$field]; 01290 01291 // Getting config for the field 01292 $tcaFieldConf = $TCA[$table]['columns'][$field]['config']; 01293 01294 // Preform processing: 01295 $res = $this->checkValue_SW($res,$value,$tcaFieldConf,$table,$id,$curValue,$status,$realPid,$recFID,$field,$this->uploadedFileArray[$table][$id][$field],$tscPID); 01296 01297 return $res; 01298 } 01299 01318 function checkValue_SW($res,$value,$tcaFieldConf,$table,$id,$curValue,$status,$realPid,$recFID,$field,$uploadedFiles,$tscPID) { 01319 01320 $PP = array($table,$id,$curValue,$status,$realPid,$recFID,$tscPID); 01321 01322 switch ($tcaFieldConf['type']) { 01323 case 'text': 01324 case 'passthrough': 01325 case 'user': 01326 $res['value'] = $value; 01327 break; 01328 case 'input': 01329 $res = $this->checkValue_input($res,$value,$tcaFieldConf,$PP,$field); 01330 break; 01331 case 'check': 01332 $res = $this->checkValue_check($res,$value,$tcaFieldConf,$PP); 01333 break; 01334 case 'radio': 01335 $res = $this->checkValue_radio($res,$value,$tcaFieldConf,$PP); 01336 break; 01337 case 'group': 01338 case 'select': 01339 $res = $this->checkValue_group_select($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field); 01340 break; 01341 case 'flex': 01342 if ($field) { // FlexForms are only allowed for real fields. 01343 $res = $this->checkValue_flex($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field); 01344 } 01345 break; 01346 default: 01347 #debug(array($tcaFieldConf,$res,$value),'NON existing field type:'); 01348 break; 01349 } 01350 01351 return $res; 01352 } 01353 01364 function checkValue_input($res,$value,$tcaFieldConf,$PP,$field='') { 01365 list($table,$id,$curValue,$status,$realPid,$recFID) = $PP; 01366 01367 // Secures the string-length to be less than max. Will probably make problems with multi-byte strings! 01368 if (intval($tcaFieldConf['max'])>0) {$value = substr($value,0,intval($tcaFieldConf['max']));} 01369 01370 // Checking range of value: 01371 if ($tcaFieldConf['range'] && $value!=$tcaFieldConf['checkbox']) { // If value is not set to the allowed checkbox-value then it is checked against the ranges 01372 if (isset($tcaFieldConf['range']['upper'])&&$value>$tcaFieldConf['range']['upper']) {$value=$tcaFieldConf['range']['upper'];} 01373 if (isset($tcaFieldConf['range']['lower'])&&$value<$tcaFieldConf['range']['lower']) {$value=$tcaFieldConf['range']['lower'];} 01374 } 01375 01376 // Process evaluation settings: 01377 $evalCodesArray = t3lib_div::trimExplode(',',$tcaFieldConf['eval'],1); 01378 $res = $this->checkValue_input_Eval($value,$evalCodesArray,$tcaFieldConf['is_in']); 01379 01380 // Process UNIQUE settings: 01381 if ($field && $realPid>=0) { // Field is NOT set for flexForms - which also means that uniqueInPid and unique is NOT available for flexForm fields! Also getUnique should not be done for versioning and if PID is -1 ($realPid<0) then versioning is happening... 01382 if ($res['value'] && in_array('uniqueInPid',$evalCodesArray)) { 01383 $res['value'] = $this->getUnique($table,$field,$res['value'],$id,$realPid); 01384 } 01385 if ($res['value'] && in_array('unique',$evalCodesArray)) { 01386 $res['value'] = $this->getUnique($table,$field,$res['value'],$id); 01387 } 01388 } 01389 01390 return $res; 01391 } 01392 01402 function checkValue_check($res,$value,$tcaFieldConf,$PP) { 01403 list($table,$id,$curValue,$status,$realPid,$recFID) = $PP; 01404 01405 $itemC = count($tcaFieldConf['items']); 01406 if (!$itemC) {$itemC=1;} 01407 $maxV = pow(2,$itemC); 01408 01409 if ($value<0) {$value=0;} 01410 if ($value>$maxV) {$value=$maxV;} 01411 $res['value'] = $value; 01412 01413 return $res; 01414 } 01415 01425 function checkValue_radio($res,$value,$tcaFieldConf,$PP) { 01426 list($table,$id,$curValue,$status,$realPid,$recFID) = $PP; 01427 01428 if (is_array($tcaFieldConf['items'])) { 01429 foreach($tcaFieldConf['items'] as $set) { 01430 if (!strcmp($set[1],$value)) { 01431 $res['value'] = $value; 01432 break; 01433 } 01434 } 01435 } 01436 01437 return $res; 01438 } 01439 01451 function checkValue_group_select($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field) { 01452 list($table,$id,$curValue,$status,$realPid,$recFID) = $PP; 01453 01454 // Detecting if value send is an array and if so, implode it around a comma: 01455 if (is_array($value)) { 01456 $value = implode(',',$value); 01457 } 01458 01459 // This converts all occurencies of '{' to the byte 123 in the string - this is needed in very rare cases where filenames with special characters (like ćřĺ, umlaud etc) gets sent to the server as HTML entities instead of bytes. The error is done only by MSIE, not Mozilla and Opera. 01460 // Anyways, this should NOT disturb anything else: 01461 $value = $this->convNumEntityToByteValue($value); 01462 01463 // When values are send as group or select they come as comma-separated values which are exploded by this function: 01464 $valueArray = $this->checkValue_group_select_explodeSelectGroupValue($value); 01465 01466 // If not multiple is set, then remove duplicates: 01467 if (!$tcaFieldConf['multiple']) { 01468 $valueArray = array_unique($valueArray); 01469 } 01470 01471 // This could be a good spot for parsing the array through a validation-function which checks if the values are allright (except that database references are not in their final form - but that is the point, isn't it?) 01472 // NOTE!!! Must check max-items of files before the later check because that check would just leave out filenames if there are too many!! 01473 01474 // Checking for select / authMode, removing elements from $valueArray if any of them is not allowed! 01475 if ($tcaFieldConf['type']=='select' && $tcaFieldConf['authMode']) { 01476 $preCount = count($valueArray); 01477 foreach($valueArray as $kk => $vv) { 01478 if (!$this->BE_USER->checkAuthMode($table,$field,$vv,$tcaFieldConf['authMode'])) { 01479 unset($valueArray[$kk]); 01480 } 01481 } 01482 01483 // During the check it turns out that the value / all values were removed - we respond by simply returning an empty array so nothing is written to DB for this field. 01484 if ($preCount && !count($valueArray)) { 01485 return array(); 01486 } 01487 } 01488 01489 // For group types: 01490 if ($tcaFieldConf['type']=='group') { 01491 switch($tcaFieldConf['internal_type']) { 01492 case 'file': 01493 $valueArray = $this->checkValue_group_select_file( 01494 $valueArray, 01495 $tcaFieldConf, 01496 $curValue, 01497 $uploadedFiles, 01498 $status, 01499 $table, 01500 $id, 01501 $recFID 01502 ); 01503 break; 01504 case 'db': 01505 $valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'group'); 01506 break; 01507 } 01508 } 01509 // For select types which has a foreign table attached: 01510 if ($tcaFieldConf['type']=='select' && $tcaFieldConf['foreign_table']) { 01511 $valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'select'); 01512 } 01513 01514 // BTW, checking for min and max items here does NOT make any sense when MM is used because the above function calls will just return an array with a single item (the count) if MM is used... Why didn't I perform the check before? Probably because we could not evaluate the validity of record uids etc... Hmm... 01515 01516 // Checking the number of items, that it is correct. 01517 // If files, there MUST NOT be too many files in the list at this point, so check that prior to this code. 01518 $valueArrayC = count($valueArray); 01519 $minI = isset($tcaFieldConf['minitems']) ? intval($tcaFieldConf['minitems']):0; 01520 01521 // NOTE to the comment: It's not really possible to check for too few items, because you must then determine first, if the field is actual used regarding the CType. 01522 $maxI = isset($tcaFieldConf['maxitems']) ? intval($tcaFieldConf['maxitems']):1; 01523 if ($valueArrayC > $maxI) {$valueArrayC=$maxI;} // Checking for not too many elements 01524 01525 // Dumping array to list 01526 $newVal=array(); 01527 foreach($valueArray as $nextVal) { 01528 if ($valueArrayC==0) {break;} 01529 $valueArrayC--; 01530 $newVal[]=$nextVal; 01531 } 01532 $res['value'] = implode(',',$newVal); 01533 01534 return $res; 01535 } 01536 01551 function checkValue_group_select_file($valueArray,$tcaFieldConf,$curValue,$uploadedFileArray,$status,$table,$id,$recFID) { 01552 01553 // If any files are uploaded: 01554 if (is_array($uploadedFileArray) && 01555 $uploadedFileArray['name'] && 01556 strcmp($uploadedFileArray['tmp_name'],'none')) { 01557 $valueArray[]=$uploadedFileArray['tmp_name']; 01558 $this->alternativeFileName[$uploadedFileArray['tmp_name']] = $uploadedFileArray['name']; 01559 } 01560 01561 // Creating fileFunc object. 01562 if (!$this->fileFunc) { 01563 $this->fileFunc = t3lib_div::makeInstance('t3lib_basicFileFunctions'); 01564 $this->include_filefunctions=1; 01565 } 01566 // Setting permitted extensions. 01567 $all_files = Array(); 01568 $all_files['webspace']['allow'] = $tcaFieldConf['allowed']; 01569 $all_files['webspace']['deny'] = $tcaFieldConf['disallowed'] ? $tcaFieldConf['disallowed'] : '*'; 01570 $all_files['ftpspace'] = $all_files['webspace']; 01571 $this->fileFunc->init('', $all_files); 01572 01573 // If there is an upload folder defined: 01574 if ($tcaFieldConf['uploadfolder']) { 01575 // For logging.. 01576 $propArr = $this->getRecordProperties($table,$id); 01577 01578 // Get destrination path: 01579 $dest = $this->destPathFromUploadFolder($tcaFieldConf['uploadfolder']); 01580 01581 // If we are updating: 01582 if ($status=='update') { 01583 01584 // Finding the CURRENT files listed, either from MM or from the current record. 01585 $theFileValues=array(); 01586 if ($tcaFieldConf['MM']) { // If MM relations for the files also! 01587 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 01588 $dbAnalysis->start('','files',$tcaFieldConf['MM'],$id); 01589 reset($dbAnalysis->itemArray); 01590 while (list($somekey,$someval)=each($dbAnalysis->itemArray)) { 01591 if ($someval['id']) { 01592 $theFileValues[]=$someval['id']; 01593 } 01594 } 01595 } else { 01596 $theFileValues=t3lib_div::trimExplode(',',$curValue,1); 01597 } 01598 01599 // DELETE files: If existing files were found, traverse those and register files for deletion which has been removed: 01600 if (count($theFileValues)) { 01601 // Traverse the input values and for all input values which match an EXISTING value, remove the existing from $theFileValues array (this will result in an array of all the existing files which should be deleted!) 01602 foreach($valueArray as $key => $theFile) { 01603 if ($theFile && !strstr(t3lib_div::fixWindowsFilePath($theFile),'/')) { 01604 $theFileValues = t3lib_div::removeArrayEntryByValue($theFileValues,$theFile); 01605 } 01606 } 01607 01608 // This array contains the filenames in the uploadfolder that should be deleted: 01609 foreach($theFileValues as $key => $theFile) { 01610 $theFile = trim($theFile); 01611 if (@is_file($dest.'/'.$theFile)) { 01612 $this->removeFilesStore[]=$dest.'/'.$theFile; 01613 } elseif ($theFile) { 01614 $this->log($table,$id,5,0,1,"Could not delete file '%s' (does not exist). (%s)",10,array($dest.'/'.$theFile, $recFID),$propArr['event_pid']); 01615 } 01616 } 01617 } 01618 } 01619 01620 // Traverse the submitted values: 01621 foreach($valueArray as $key => $theFile) { 01622 // NEW FILES? If the value contains '/' it indicates, that the file is new and should be added to the uploadsdir (whether its absolute or relative does not matter here) 01623 if (strstr(t3lib_div::fixWindowsFilePath($theFile),'/')) { 01624 // Init: 01625 $maxSize = intval($tcaFieldConf['max_size']); 01626 $cmd=''; 01627 $theDestFile=''; // Must be cleared. Else a faulty fileref may be inserted if the below code returns an error!! (Change: 22/12/2000) 01628 01629 // Check various things before copying file: 01630 if (@is_dir($dest) && (@is_file($theFile) || @is_uploaded_file($theFile))) { // File and destination must exist 01631 01632 // Finding size. For safe_mode we have to rely on the size in the upload array if the file is uploaded. 01633 if (is_uploaded_file($theFile) && $theFile==$uploadedFileArray['tmp_name']) { 01634 $fileSize = $uploadedFileArray['size']; 01635 } else { 01636 $fileSize = filesize($theFile); 01637 } 01638 01639 if (!$maxSize || $fileSize<=($maxSize*1024)) { // Check file size: 01640 // Prepare filename: 01641 $theEndFileName = isset($this->alternativeFileName[$theFile]) ? $this->alternativeFileName[$theFile] : $theFile; 01642 $fI = t3lib_div::split_fileref($theEndFileName); 01643 01644 // Check for allowed extension: 01645 if ($this->fileFunc->checkIfAllowed($fI['fileext'], $dest, $theEndFileName)) { 01646 $theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($fI['file']), $dest); 01647 01648 // If we have a unique destination filename, then write the file: 01649 if ($theDestFile) { 01650 t3lib_div::upload_copy_move($theFile,$theDestFile); 01651 $this->copiedFileMap[$theFile] = $theDestFile; 01652 clearstatcache(); 01653 if (!@is_file($theDestFile)) $this->log($table,$id,5,0,1,"Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s)",16,array($theFile, dirname($theDestFile), $recFID),$propArr['event_pid']); 01654 } else $this->log($table,$id,5,0,1,"Copying file '%s' failed!: No destination file (%s) possible!. (%s)",11,array($theFile, $theDestFile, $recFID),$propArr['event_pid']); 01655 } else $this->log($table,$id,5,0,1,"Fileextension '%s' not allowed. (%s)",12,array($fI['fileext'], $recFID),$propArr['event_pid']); 01656 } else $this->log($table,$id,5,0,1,"Filesize (%s) of file '%s' exceeds limit (%s). (%s)",13,array(t3lib_div::formatSize($fileSize),$theFile,t3lib_div::formatSize($maxSize*1024),$recFID),$propArr['event_pid']); 01657 } else $this->log($table,$id,5,0,1,'The destination (%s) or the source file (%s) does not exist. (%s)',14,array($dest, $theFile, $recFID),$propArr['event_pid']); 01658 01659 // If the destination file was created, we will set the new filename in the value array, otherwise unset the entry in the value array! 01660 if (@is_file($theDestFile)) { 01661 $info = t3lib_div::split_fileref($theDestFile); 01662 $valueArray[$key]=$info['file']; // The value is set to the new filename 01663 } else { 01664 unset($valueArray[$key]); // The value is set to the new filename 01665 } 01666 } 01667 } 01668 01669 // If MM relations for the files, we will set the relations as MM records and change the valuearray to contain a single entry with a count of the number of files! 01670 if ($tcaFieldConf['MM']) { 01671 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 01672 $dbAnalysis->tableArray['files']=array(); // dummy 01673 01674 reset($valueArray); 01675 while (list($key,$theFile)=each($valueArray)) { 01676 // explode files 01677 $dbAnalysis->itemArray[]['id']=$theFile; 01678 } 01679 if ($status=='update') { 01680 $dbAnalysis->writeMM($tcaFieldConf['MM'],$id,0); 01681 } else { 01682 $this->dbAnalysisStore[] = array($dbAnalysis, $tcaFieldConf['MM'], $id, 0); // This will be traversed later to execute the actions 01683 } 01684 $cc=count($dbAnalysis->itemArray); 01685 $valueArray = array($cc); 01686 } 01687 } 01688 01689 return $valueArray; 01690 } 01691 01704 function checkValue_flex($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field) { 01705 list($table,$id,$curValue,$status,$realPid,$recFID) = $PP; 01706 01707 if (is_array($value)) { 01708 01709 // Get current value array: 01710 $dataStructArray = t3lib_BEfunc::getFlexFormDS($tcaFieldConf,$this->checkValue_currentRecord,$table); 01711 #debug($this->checkValue_currentRecord); 01712 $currentValueArray = t3lib_div::xml2array($curValue); 01713 if (!is_array($currentValueArray)) $currentValueArray = array(); 01714 if (is_array($currentValueArray['meta']['currentLangId'])) unset($currentValueArray['meta']['currentLangId']); // Remove all old meta for languages... 01715 01716 // Evaluation of input values: 01717 $value['data'] = $this->checkValue_flex_procInData($value['data'],$currentValueArray['data'],$uploadedFiles['data'],$dataStructArray,$PP); 01718 01719 // Create XML and convert charsets from input value: 01720 $xmlValue = $this->checkValue_flexArray2Xml($value); 01721 01722 // If we wanted to set UTF fixed: 01723 // $storeInCharset='utf-8'; 01724 // $currentCharset=$GLOBALS['LANG']->charSet; 01725 // $xmlValue = $GLOBALS['LANG']->csConvObj->conv($xmlValue,$currentCharset,$storeInCharset,1); 01726 $storeInCharset=$GLOBALS['LANG']->charSet; 01727 01728 // Merge them together IF they are both arrays: 01729 // Here we convert the currently submitted values BACK to an array, then merge the two and then BACK to XML again. This is needed to ensure the charsets are the same (provided that the current value was already stored IN the charset that the new value is converted to). 01730 if (is_array($currentValueArray)) { 01731 $arrValue = t3lib_div::xml2array($xmlValue); 01732 $arrValue = t3lib_div::array_merge_recursive_overrule($currentValueArray,$arrValue); 01733 $xmlValue = $this->checkValue_flexArray2Xml($arrValue); 01734 } 01735 01736 // Temporary fix to delete elements: 01737 $deleteCMDs = t3lib_div::_GP('_DELETE_FLEX_FORMdata'); 01738 01739 if (is_array($deleteCMDs[$table][$id][$field]['data'])) { 01740 $arrValue = t3lib_div::xml2array($xmlValue); 01741 $this->_DELETE_FLEX_FORMdata($arrValue['data'],$deleteCMDs[$table][$id][$field]['data']); 01742 $xmlValue = $this->checkValue_flexArray2Xml($arrValue); 01743 } 01744 01745 // Create the value XML: 01746 $res['value']=''; 01747 $res['value'].='<?xml version="1.0" encoding="'.$storeInCharset.'" standalone="yes" ?>'.chr(10); 01748 $res['value'].=$xmlValue; 01749 } else { // Passthrough...: 01750 $res['value']=$value; 01751 } 01752 01753 return $res; 01754 } 01755 01762 function checkValue_flexArray2Xml($array) { 01763 $output = t3lib_div::array2xml($array,'',0,'T3FlexForms',4,array('parentTagMap' => array( 01764 /* 'data' => 'sheets', 01765 'sheets' => 'language', 01766 'language' => 'fieldname', 01767 'el' => 'fieldname' */ 01768 ))); 01769 return $output; 01770 } 01771 01779 function _DELETE_FLEX_FORMdata(&$valueArrayToRemoveFrom,$deleteCMDS) { 01780 if (is_array($valueArrayToRemoveFrom) && is_array($deleteCMDS)) { 01781 foreach($deleteCMDS as $key => $value) { 01782 if (is_array($deleteCMDS[$key])) { 01783 $this->_DELETE_FLEX_FORMdata($valueArrayToRemoveFrom[$key],$deleteCMDS[$key]); 01784 } else { 01785 unset($valueArrayToRemoveFrom[$key]); 01786 } 01787 } 01788 } 01789 } 01790 01791 01792 01793 01794 01795 01796 01797 01798 01799 01800 01801 01802 01803 01804 01805 01806 01807 01808 01809 01810 /********************************************* 01811 * 01812 * Helper functions for evaluation functions. 01813 * 01814 ********************************************/ 01815 01816 01827 function getUnique($table,$field,$value,$id,$newPid=0) { 01828 global $TCA; 01829 01830 // Initialize: 01831 t3lib_div::loadTCA($table); 01832 $whereAdd=''; 01833 $newValue=''; 01834 if (intval($newPid)) { $whereAdd.=' AND pid='.intval($newPid); } else { $whereAdd.=' AND pid>=0'; } // "AND pid>=0" for versioning 01835 $whereAdd.=$this->deleteClause($table); 01836 01837 // If the field is configured in TCA, proceed: 01838 if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$field])) { 01839 01840 // Look for a record which might already have the value: 01841 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, $field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($value, $table).'" AND uid!='.intval($id).$whereAdd); 01842 $counter = 0; 01843 01844 // For as long as records with the test-value existing, try again (with incremented numbers appended). 01845 while ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) { 01846 $newValue = $value.$counter; 01847 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, $field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($newValue, $table).'" AND uid!='.intval($id).$whereAdd); 01848 $counter++; 01849 if ($counter>100) { break; } // At "100" it will give up and accept a duplicate - should probably be fixed to a small hash string instead...! 01850 } 01851 // If the new value is there: 01852 $value = strlen($newValue) ? $newValue : $value; 01853 } 01854 return $value; 01855 } 01856 01865 function checkValue_input_Eval($value,$evalArray,$is_in) { 01866 $res = Array(); 01867 $newValue = $value; 01868 $set = true; 01869 01870 foreach($evalArray as $func) { 01871 switch($func) { 01872 case 'int': 01873 case 'year': 01874 case 'date': 01875 case 'datetime': 01876 case 'time': 01877 case 'timesec': 01878 $value = intval($value); 01879 break; 01880 case 'double2': 01881 $theDec = 0; 01882 for ($a=strlen($value); $a>0; $a--) { 01883 if (substr($value,$a-1,1)=='.' || substr($value,$a-1,1)==',') { 01884 $theDec = substr($value,$a); 01885 $value = substr($value,0,$a-1); 01886 break; 01887 } 01888 } 01889 $theDec = ereg_replace('[^0-9]','',$theDec).'00'; 01890 $value = intval(str_replace(' ','',$value)).'.'.substr($theDec,0,2); 01891 break; 01892 case 'md5': 01893 if (strlen($value)!=32){$set=false;} 01894 break; 01895 case 'trim': 01896 $value = trim($value); 01897 break; 01898 case 'upper': 01899 $value = strtoupper($value); 01900 # $value = strtr($value, 'áéúíâęűôîćřĺäöü', 'ÁÉÚÍÂĘŰÔÎĆŘĹÄÖÜ'); // WILL make trouble with other charsets than ISO-8859-1, so what do we do here? PHP-function which can handle this for other charsets? Currently the browsers JavaScript will fix it. 01901 break; 01902 case 'lower': 01903 $value = strtolower($value); 01904 # $value = strtr($value, 'ÁÉÚÍÂĘŰÔÎĆŘĹÄÖÜ', 'áéúíâęűôîćřĺäöü'); // WILL make trouble with other charsets than ISO-8859-1, so what do we do here? PHP-function which can handle this for other charsets? Currently the browsers JavaScript will fix it. 01905 break; 01906 case 'required': 01907 if (!$value) {$set=0;} 01908 break; 01909 case 'is_in': 01910 $c=strlen($value); 01911 if ($c) { 01912 $newVal = ''; 01913 for ($a=0;$a<$c;$a++) { 01914 $char = substr($value,$a,1); 01915 if (strstr($is_in,$char)) { 01916 $newVal.=$char; 01917 } 01918 } 01919 $value = $newVal; 01920 } 01921 break; 01922 case 'nospace': 01923 $value = str_replace(' ','',$value); 01924 break; 01925 case 'alpha': 01926 $value = ereg_replace('[^a-zA-Z]','',$value); 01927 break; 01928 case 'num': 01929 $value = ereg_replace('[^0-9]','',$value); 01930 break; 01931 case 'alphanum': 01932 $value = ereg_replace('[^a-zA-Z0-9]','',$value); 01933 break; 01934 case 'alphanum_x': 01935 $value = ereg_replace('[^a-zA-Z0-9_-]','',$value); 01936 break; 01937 } 01938 } 01939 if ($set) {$res['value'] = $value;} 01940 return $res; 01941 } 01942 01953 function checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,$type) { 01954 $tables = $type=='group'?$tcaFieldConf['allowed']:$tcaFieldConf['foreign_table'].','.$tcaFieldConf['neg_foreign_table']; 01955 $prep = $type=='group'?$tcaFieldConf['prepend_tname']:$tcaFieldConf['neg_foreign_table']; 01956 01957 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 01958 $dbAnalysis->registerNonTableValues=$tcaFieldConf['allowNonIdValues'] ? 1 : 0; 01959 $dbAnalysis->start(implode(',',$valueArray),$tables); 01960 01961 if ($tcaFieldConf['MM']) { 01962 if ($status=='update') { 01963 $dbAnalysis->writeMM($tcaFieldConf['MM'],$id,$prep); 01964 } else { 01965 $this->dbAnalysisStore[] = array($dbAnalysis,$tcaFieldConf['MM'],$id,$prep); // This will be traversed later to execute the actions 01966 } 01967 $cc=count($dbAnalysis->itemArray); 01968 $valueArray = array($cc); 01969 } else { 01970 $valueArray = $dbAnalysis->getValueArray($prep); 01971 if ($type=='select' && $prep) { 01972 $valueArray = $dbAnalysis->convertPosNeg($valueArray,$tcaFieldConf['foreign_table'],$tcaFieldConf['neg_foreign_table']); 01973 } 01974 } 01975 01976 // Here we should se if 1) the records exist anymore, 2) which are new and check if the BE_USER has read-access to the new ones. 01977 return $valueArray; 01978 } 01979 01986 function checkValue_group_select_explodeSelectGroupValue($value) { 01987 $valueArray = t3lib_div::trimExplode(',',$value,1); 01988 reset($valueArray); 01989 while(list($key,$newVal)=each($valueArray)) { 01990 $temp=explode('|',$newVal,2); 01991 $valueArray[$key] = str_replace(',','',str_replace('|','',rawurldecode($temp[0]))); 01992 } 01993 return $valueArray; 01994 } 01995 02009 function checkValue_flex_procInData($dataPart,$dataPart_current,$uploadedFiles,$dataStructArray,$pParams,$callBackFunc='') { 02010 #debug(array($dataPart,$dataPart_current,$dataStructArray)); 02011 if (is_array($dataPart)) { 02012 foreach($dataPart as $sKey => $sheetDef) { 02013 list ($dataStruct,$actualSheet) = t3lib_div::resolveSheetDefInDS($dataStructArray,$sKey); 02014 #debug(array($dataStruct,$actualSheet,$sheetDef,$actualSheet,$sKey)); 02015 if (is_array($dataStruct) && $actualSheet==$sKey && is_array($sheetDef)) { 02016 foreach($sheetDef as $lKey => $lData) { 02017 $this->checkValue_flex_procInData_travDS( 02018 $dataPart[$sKey][$lKey], 02019 $dataPart_current[$sKey][$lKey], 02020 $uploadedFiles[$sKey][$lKey], 02021 $dataStruct['ROOT']['el'], 02022 $pParams, 02023 $callBackFunc 02024 ); 02025 } 02026 } 02027 } 02028 } 02029 02030 return $dataPart; 02031 } 02032 02046 function checkValue_flex_procInData_travDS(&$dataValues,$dataValues_current,$uploadedFiles,$DSelements,$pParams,$callBackFunc='') { 02047 if (is_array($DSelements)) { 02048 02049 // For each DS element: 02050 foreach($DSelements as $key => $dsConf) { 02051 02052 // Array/Section: 02053 if ($DSelements[$key]['type']=='array') { 02054 if (is_array($dataValues[$key]['el'])) { 02055 if ($DSelements[$key]['section']) { 02056 foreach($dataValues[$key]['el'] as $ik => $el) { 02057 $theKey = key($el); 02058 if (is_array($dataValues[$key]['el'][$ik][$theKey]['el'])) { 02059 $this->checkValue_flex_procInData_travDS( 02060 $dataValues[$key]['el'][$ik][$theKey]['el'], 02061 $dataValues_current[$key]['el'][$ik][$theKey]['el'], 02062 $uploadedFiles[$key]['el'][$ik][$theKey]['el'], 02063 $DSelements[$key]['el'][$theKey]['el'], 02064 $pParams, 02065 $callBackFunc 02066 ); 02067 } 02068 } 02069 } else { 02070 if (!isset($dataValues[$key]['el'])) $dataValues[$key]['el']=array(); 02071 $this->checkValue_flex_procInData_travDS( 02072 $dataValues[$key]['el'], 02073 $dataValues_current[$key]['el'], 02074 $uploadedFiles[$key]['el'], 02075 $DSelements[$key]['el'], 02076 $pParams, 02077 $callBackFunc 02078 ); 02079 } 02080 } 02081 } else { 02082 if (is_array($dsConf['TCEforms']['config']) && is_array($dataValues[$key])) { 02083 foreach($dataValues[$key] as $vKey => $data) { 02084 02085 if ($callBackFunc) { 02086 $res = $this->$callBackFunc( 02087 $pParams, 02088 $dsConf['TCEforms']['config'], 02089 $dataValues[$key][$vKey], 02090 $dataValues_current[$key][$vKey], 02091 $uploadedFiles[$key][$vKey] 02092 ); 02093 } else { // Default 02094 list($CVtable,$CVid,$CVcurValue,$CVstatus,$CVrealPid,$CVrecFID,$CVtscPID) = $pParams; 02095 02096 $res = $this->checkValue_SW( 02097 array(), 02098 $dataValues[$key][$vKey], 02099 $dsConf['TCEforms']['config'], 02100 $CVtable, 02101 $CVid, 02102 $dataValues_current[$key][$vKey], 02103 $CVstatus, 02104 $CVrealPid, 02105 $CVrecFID, 02106 '', 02107 $uploadedFiles[$key][$vKey], 02108 array(), 02109 $CVtscPID 02110 ); 02111 02112 // Look for RTE transformation of field: 02113 if ($dataValues[$key]['_TRANSFORM_'.$vKey] == 'RTE' && !$this->dontProcessTransformations) { 02114 02115 // Unsetting trigger field - we absolutely don't want that into the data storage! 02116 unset($dataValues[$key]['_TRANSFORM_'.$vKey]); 02117 02118 if (isset($res['value'])) { 02119 02120 // Calculating/Retrieving some values here: 02121 list(,,$recFieldName) = explode(':', $CVrecFID); 02122 $theTypeString = t3lib_BEfunc::getTCAtypeValue($CVtable,$this->checkValue_currentRecord); 02123 $specConf = t3lib_BEfunc::getSpecConfParts('',$dsConf['TCEforms']['defaultExtras']); 02124 02125 // Find, thisConfig: 02126 $RTEsetup = $this->BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($CVtscPID)); 02127 $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'],$CVtable,$recFieldName,$theTypeString); 02128 02129 // Get RTE object, draw form and set flag: 02130 $RTEobj = &t3lib_BEfunc::RTEgetObj(); 02131 if (is_object($RTEobj)) { 02132 $res['value'] = $RTEobj->transformContent('db',$res['value'],$CVtable,$recFieldName,$this->checkValue_currentRecord,$specConf,$thisConfig,'',$CVrealPid); 02133 } else { 02134 debug('NO RTE OBJECT FOUND!'); 02135 } 02136 } 02137 } 02138 } 02139 02140 // Adding the value: 02141 if (isset($res['value'])) { 02142 $dataValues[$key][$vKey] = $res['value']; 02143 } 02144 } 02145 } 02146 } 02147 } 02148 } 02149 } 02150 02151 02152 02153 02154 02155 02156 02157 02158 02159 02160 02161 02162 02163 02164 02165 02166 02167 02168 02169 02170 /********************************************* 02171 * 02172 * Storing data to Database Layer 02173 * 02174 ********************************************/ 02175 02176 02186 function updateDB($table,$id,$fieldArray) { 02187 global $TCA; 02188 02189 if (is_array($fieldArray) && is_array($TCA[$table]) && intval($id)) { 02190 unset($fieldArray['uid']); // Do NOT update the UID field, ever! 02191 02192 if (count($fieldArray)) { 02193 02194 // Execute the UPDATE query: 02195 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($id), $fieldArray); 02196 02197 // If succees, do...: 02198 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 02199 if ($this->checkStoredRecords) { 02200 $newRow = $this->checkStoredRecord($table,$id,$fieldArray,2); 02201 } 02202 02203 // Set log entry: 02204 $propArr = $this->getRecordPropertiesFromRow($table,$newRow); 02205 $theLogId = $this->log($table,$id,2,$recpid,0,"Record '%s' (%s) was updated.",10,array($propArr['header'],$table.':'.$id),$propArr['event_pid']); 02206 02207 // Set History data: 02208 $this->setHistory($table,$id,$theLogId); 02209 02210 // Clear cache for relavant pages: 02211 $this->clear_cache($table,$id); 02212 02213 // Unset the pageCache for the id if table was page. 02214 if ($table=='pages') unset($this->pageCache[$id]); 02215 } else { 02216 $this->log($table,$id,2,0,2,"SQL error: '%s' (%s)",12,array($GLOBALS['TYPO3_DB']->sql_error(),$table.':'.$id)); 02217 } 02218 } 02219 } 02220 } 02221 02232 function compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray) { 02233 02234 // Fetch the original record: 02235 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid='.intval($id)); 02236 $currentRecord = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 02237 02238 // If the current record exists (which it should...), begin comparison: 02239 if (is_array($currentRecord)) { 02240 02241 // Read all field types: 02242 $c = 0; 02243 $cRecTypes = array(); 02244 foreach($currentRecord as $col => $val) { 02245 $cRecTypes[$col] = $GLOBALS['TYPO3_DB']->sql_field_type($res,$c); 02246 $c++; 02247 } 02248 02249 // Free result: 02250 $GLOBALS['TYPO3_DB']->sql_free_result($res); 02251 02252 // Unset the fields which are similar: 02253 foreach($fieldArray as $col => $val) { 02254 if ( 02255 #!isset($currentRecord[$col]) || // Unset fields which were NOT found in the current record! [Uncommented because NULL fields will not return an entry in the array!] 02256 !strcmp($val,$currentRecord[$col]) || // Unset fields which matched exactly. 02257 ($cRecTypes[$col]=='int' && $currentRecord[$col]==0 && !strcmp($val,'')) // Now, a situation where TYPO3 tries to put an empty string into an integer field, we should not strcmp the integer-zero and '', but rather accept them to be similar. 02258 ) { 02259 unset($fieldArray[$col]); 02260 } else { 02261 $this->historyRecords[$table.':'.$id]['oldRecord'][$col] = $currentRecord[$col]; 02262 $this->historyRecords[$table.':'.$id]['newRecord'][$col] = $fieldArray[$col]; 02263 } 02264 } 02265 } else { // If the current record does not exist this is an error anyways and we just return an empty array here. 02266 $fieldArray = array(); 02267 } 02268 02269 return $fieldArray; 02270 } 02271 02282 function insertDB($table,$id,$fieldArray,$newVersion=FALSE) { 02283 global $TCA; 02284 02285 if (is_array($fieldArray) && is_array($TCA[$table]) && isset($fieldArray['pid'])) { 02286 unset($fieldArray['uid']); // Do NOT insert the UID field, ever! 02287 02288 if (count($fieldArray)) { 02289 02290 // Execute the INSERT query: 02291 $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $fieldArray); 02292 02293 // If succees, do...: 02294 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 02295 02296 // Set mapping for NEW... -> real uid: 02297 $NEW_id = $id; // the NEW_id now holds the 'NEW....' -id 02298 $id = $GLOBALS['TYPO3_DB']->sql_insert_id(); 02299 $this->substNEWwithIDs[$NEW_id] = $id; 02300 $this->substNEWwithIDs_table[$NEW_id] = $table; 02301 02302 // Checking the record is properly saved and writing to log 02303 if ($this->checkStoredRecords) { 02304 $newRow = $this->checkStoredRecord($table,$id,$fieldArray,1); 02305 } 02306 02307 if ($newVersion) { 02308 $this->log($table,$id,1,0,0,"New version created of table '%s', uid '%s'",10,array($table,$fieldArray['t3ver_oid']),$newRow['pid'],$NEW_id); 02309 } else { 02310 // Set log entry: 02311 if ($table=='pages') { 02312 $thePositionID = $this->getInterfacePagePositionID($id); 02313 } else { 02314 $thePositionID = 0; 02315 } 02316 $propArr = $this->getRecordPropertiesFromRow($table,$newRow); 02317 $page_propArr = $this->getRecordProperties('pages',$propArr['pid']); 02318 $this->log($table,$id,1,$thePositionID,0,"Record '%s' (%s) was inserted on page '%s' (%s)",10,array($propArr['header'],$table.':'.$id,$page_propArr['header'],$newRow['pid']),$newRow['pid'],$NEW_id); 02319 02320 // Clear cache for relavant pages: 02321 $this->clear_cache($table,$id); 02322 } 02323 } else { 02324 $this->log($table,$id,1,0,2,"SQL error: '%s' (%s)",12,array($GLOBALS['TYPO3_DB']->sql_error(),$table.':'.$id)); 02325 } 02326 } 02327 } 02328 } 02329 02340 function checkStoredRecord($table,$id,$fieldArray,$action) { 02341 global $TCA; 02342 02343 $id = intval($id); 02344 if (is_array($TCA[$table]) && $id) { 02345 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid='.intval($id)); 02346 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 02347 02348 // Traverse arrow of values that was inserted into the database and compare with the actually stored value: 02349 $errorString = array(); 02350 foreach($fieldArray as $key => $value) { 02351 if ($this->checkStoredRecords_loose && !$value && !$row[$key]) { 02352 // Nothing... 02353 } elseif (strcmp($value,$row[$key])) { 02354 $errorString[] = $key; 02355 } 02356 } 02357 02358 // Set log message if there were fields with unmatching values: 02359 if (count($errorString)) { 02360 $this->log($table,$id,$action,0,102,'These fields are not properly updated in database: ('.implode(',',$errorString).') Probably value mismatch with fieldtype.'); 02361 } 02362 02363 // Return selected rows: 02364 return $row; 02365 } 02366 $GLOBALS['TYPO3_DB']->sql_free_result($res); 02367 } 02368 } 02369 02375 function dbAnalysisStoreExec() { 02376 reset($this->dbAnalysisStore); 02377 while(list($k,$v)=each($this->dbAnalysisStore)) { 02378 $id = $this->substNEWwithIDs[$v[2]]; 02379 if ($id) { 02380 $v[2] = $id; 02381 $v[0]->writeMM($v[1],$v[2],$v[3]); 02382 } 02383 } 02384 } 02385 02391 function removeRegisteredFiles() { 02392 reset($this->removeFilesStore); 02393 while(list($k,$v)=each($this->removeFilesStore)) { 02394 unlink($v); 02395 // debug($v,1); 02396 } 02397 } 02398 02408 function clear_cache($table,$uid) { 02409 global $TCA; 02410 02411 $uid = intval($uid); 02412 if (is_array($TCA[$table]) && $uid > 0) { 02413 02414 // Get Page TSconfig relavant: 02415 list($tscPID) = t3lib_BEfunc::getTSCpid($table,$uid,''); 02416 $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); 02417 02418 if (!$TSConfig['clearCache_disable']) { 02419 // If table is "pages": 02420 if (t3lib_extMgm::isLoaded('cms')) { 02421 if ($table=='pages') { 02422 02423 // Builds list of pages on the SAME level as this page (siblings) 02424 $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 02425 'A.pid AS pid, B.uid AS uid', 02426 'pages AS A, pages AS B', 02427 'A.uid='.intval($uid).' AND B.pid=A.pid AND B.deleted=0' 02428 ); 02429 02430 $list_cache = array(); 02431 $pid_tmp = 0; 02432 while ($row_tmp = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp)) { 02433 $list_cache[] = $row_tmp['uid']; 02434 $pid_tmp = $row_tmp['pid']; 02435 02436 // Add children as well: 02437 if ($TSConfig['clearCache_pageSiblingChildren']) { 02438 $res_tmp2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 02439 'uid', 02440 'pages', 02441 'pid='.intval($row_tmp['uid']).' AND deleted=0' 02442 ); 02443 while ($row_tmp2 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp2)) { 02444 $list_cache[] = $row_tmp2['uid']; 02445 } 02446 } 02447 } 02448 02449 // Finally, add the parent page as well: 02450 $list_cache[] = $pid_tmp; 02451 02452 // Add grand-parent as well: 02453 if ($TSConfig['clearCache_pageGrandParent']) { 02454 $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 02455 'pid', 02456 'pages', 02457 'uid='.intval($pid_tmp) 02458 ); 02459 if ($row_tmp = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp)) { 02460 $list_cache[] = $row_tmp['pid']; 02461 } 02462 } 02463 02464 // Delete cache for selected pages: 02465 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages','page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')'); 02466 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')'); 02467 } else { // For other tables than "pages", delete cache for the records "parent page". 02468 $uid_page = $this->getPID($table,$uid); 02469 if ($uid_page>0) { 02470 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id='.intval($uid_page)); 02471 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id='.intval($uid_page)); 02472 } 02473 } 02474 } 02475 } 02476 02477 // Clear cache for pages entered in TSconfig: 02478 if ($TSConfig['clearCacheCmd']) { 02479 $Commands = t3lib_div::trimExplode(',',strtolower($TSConfig['clearCacheCmd']),1); 02480 $Commands = array_unique($Commands); 02481 foreach($Commands as $cmdPart) { 02482 $this->clear_cacheCmd($cmdPart); 02483 } 02484 } 02485 02486 // Call post processing function for clear-cache: 02487 global $TYPO3_CONF_VARS; 02488 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'])) { 02489 $_params = array('table' => $table,'uid' => $uid,'uid_page' => $uid_page,'TSConfig' => $TSConfig); 02490 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) { 02491 t3lib_div::callUserFunction($_funcRef,$_params,$this); 02492 } 02493 } 02494 } 02495 } 02496 02504 function getPID($table,$uid) { 02505 $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid', $table, 'uid='.intval($uid)); 02506 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp)) { 02507 return $row['pid']; 02508 } 02509 } 02510 02511 02512 02513 02514 02515 02516 02517 02518 02519 02520 02521 02522 02523 02524 02525 02526 02527 02528 02529 02530 02531 02532 02533 02534 02535 /********************************************* 02536 * 02537 * PROCESSING COMMANDS 02538 * 02539 ********************************************/ 02540 02547 function process_cmdmap() { 02548 global $TCA; 02549 02550 // Traverse command map: 02551 reset ($this->cmdmap); 02552 while (list($table,) = each($this->cmdmap)) { 02553 02554 // Check if the table may be modified! 02555 $modifyAccessList = $this->checkModifyAccessList($table); 02556 if (!$modifyAccessList) { 02557 $this->log($table,$id,2,0,1,"Attempt to modify table '%s' without permission",1,array($table)); 02558 } 02559 02560 // Check basic permissions and circumstances: 02561 if (isset($TCA[$table]) && !$this->tableReadOnly($table) && is_array($this->cmdmap[$table]) && $modifyAccessList) { 02562 02563 // Traverse the command map: 02564 foreach($this->cmdmap[$table] as $id => $incomingCmdArray) { 02565 if (is_array($incomingCmdArray)) { // have found a command. 02566 02567 // Get command and value (notice, only one command is observed at a time!): 02568 reset($incomingCmdArray); 02569 $command = key($incomingCmdArray); 02570 $value = current($incomingCmdArray); 02571 02572 // Init copyMapping array: 02573 $this->copyMappingArray = Array(); // Must clear this array before call from here to those functions: Contains mapping information between new and old id numbers. 02574 02575 // Branch, based on command 02576 switch ($command) { 02577 case 'move': 02578 $this->moveRecord($table,$id,$value); 02579 break; 02580 case 'copy': 02581 if ($table == 'pages') { 02582 $this->copyPages($id,$value); 02583 } else { 02584 $this->copyRecord($table,$id,$value,1); 02585 } 02586 break; 02587 case 'localize': 02588 $this->copyRecord_localize($table,$id,$value); 02589 break; 02590 case 'version': 02591 switch ((string)$value['action']) { 02592 case 'new': 02593 $this->versionizeTree = t3lib_div::intInRange($value['treeLevels'],-1,4); // Max 4 levels of versioning... 02594 if ($table == 'pages' && $this->versionizeTree>=0) { 02595 $this->versionizePages($id,$value['label']); 02596 } else { 02597 $this->versionizeRecord($table,$id,$value['label']); 02598 } 02599 break; 02600 case 'swap': 02601 $this->version_swap($table,$id,$value['swapWith'],$value['swapContent']); 02602 break; 02603 } 02604 break; 02605 case 'delete': 02606 if ($table == 'pages') { 02607 $this->deletePages($id); 02608 } else { 02609 $this->deleteRecord($table,$id, 0); 02610 } 02611 break; 02612 } 02613 // Merging the copy-array info together for remapping purposes. 02614 $this->copyMappingArray_merged= t3lib_div::array_merge_recursive_overrule($this->copyMappingArray_merged,$this->copyMappingArray); 02615 } 02616 } 02617 } 02618 } 02619 02620 #debug($this->copyMappingArray_merged,'$this->copyMappingArray_merged'); 02621 #debug($this->registerDBList,'$this->registerDBList'); 02622 02623 // Finally, before exit, check if there are ID references to remap. This might be the case if versioning or copying has taken place! 02624 $this->remapListedDBRecords(); 02625 } 02626 02635 function moveRecord($table,$uid,$destPid) { 02636 global $TCA; 02637 02638 // Initialize: 02639 $sortRow = $TCA[$table]['ctrl']['sortby']; 02640 $destPid = intval($destPid); 02641 $origDestPid = $destPid; 02642 02643 if ($TCA[$table]) { 02644 $propArr = $this->getRecordProperties($table,$uid); // Get this before we change the pid (for logging) 02645 $resolvedPid = $this->resolvePid($table,$destPid); // This is the actual pid of the moving. 02646 02647 // Finding out, if the record may be moved from where it is. If the record is a non-page, then it depends on edit-permissions. 02648 // If the record is a page, then there are two options: If the page is moved within itself, (same pid) it's edit-perms of the pid. If moved to another place then its both delete-perms of the pid and new-page perms on the destination. 02649 if ($table!='pages' || $resolvedPid==$propArr['pid']) { 02650 $mayMoveAccess = $this->checkRecordUpdateAccess($table,$uid); // Edit rights for the record... 02651 } else { 02652 $mayMoveAccess = $this->doesRecordExist($table,$uid,'delete'); 02653 } 02654 02655 // Finding out, if the record may be moved TO another place. Here we check insert-rights (non-pages = edit, pages = new), unless the pages is moved on the same pid, then edit-rights are checked 02656 if ($table!='pages' || $resolvedPid!=$propArr['pid']) { 02657 $mayInsertAccess = $this->checkRecordInsertAccess($table,$resolvedPid,4); // Edit rights for the record... 02658 } else { 02659 $mayInsertAccess = $this->checkRecordUpdateAccess($table,$uid); 02660 } 02661 02662 // Checking if the pid is negativ, but no sorting row is defined. In that case, find the correct pid. Basically this check make the error message 4-13 meaning less... But you can always remove this check if you prefer the error instead of a no-good action (which is to move the record to its own page...) 02663 if ($destPid<0 && !$sortRow) { 02664 $destPid = $resolvedPid; 02665 } 02666 02667 // Timestamp field: 02668 $updateFields = array(); 02669 if ($TCA[$table]['ctrl']['tstamp']) { 02670 $updateFields[$TCA[$table]['ctrl']['tstamp']] = time(); 02671 } 02672 02673 // If moving is allowed, begin the processing: 02674 if ($mayMoveAccess) { 02675 if ($destPid>=0) { // insert as first element on page (where uid = $destPid) 02676 if ($mayInsertAccess) { 02677 if ($table!='pages' || $this->destNotInsideSelf ($destPid,$uid)) { 02678 $this->clear_cache($table,$uid); // clear cache before moving 02679 02680 $updateFields['pid'] = $destPid; // Setting PID 02681 02682 // table is sorted by 'sortby' 02683 if ($sortRow) { 02684 $sortNumber = $this->getSortNumber($table,$uid,$destPid); 02685 $updateFields[$sortRow] = $sortNumber; 02686 } 02687 02688 // Create query for update: 02689 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); 02690 02691 // Logging... 02692 $newPropArr = $this->getRecordProperties($table,$uid); 02693 $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']); 02694 $newpagePropArr = $this->getRecordProperties('pages',$destPid); 02695 02696 if ($destPid!=$propArr['pid']) { 02697 $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']); // Logged to old page 02698 $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page 02699 } else { 02700 $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page 02701 } 02702 $this->clear_cache($table,$uid); // clear cache after moving 02703 $this->fixUniqueInPid($table,$uid); 02704 // fixCopyAfterDuplFields 02705 if ($origDestPid<0) {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);} // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before. 02706 } else { 02707 $destPropArr = $this->getRecordProperties('pages',$destPid); 02708 $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']); 02709 } 02710 } 02711 } else { // Put after another record 02712 if ($sortRow) { // table is being sorted 02713 $sortInfo = $this->getSortNumber($table,$uid,$destPid); 02714 $destPid = $sortInfo['pid']; // Setting the destPid to the new pid of the record. 02715 if (is_array($sortInfo)) { // If not an array, there was an error (which is already logged) 02716 if ($mayInsertAccess) { 02717 if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid)) { 02718 $this->clear_cache($table,$uid); // clear cache before moving 02719 02720 // We now update the pid and sortnumber 02721 $updateFields['pid'] = $destPid; 02722 $updateFields[$sortRow] = $sortInfo['sortNumber']; 02723 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); 02724 02725 // Logging... 02726 if ($table=='pages') { 02727 $thePositionID = $this->getInterfacePagePositionID($uid); 02728 } else { 02729 $thePositionID = 0; 02730 } 02731 $this->log($table,$uid,4,$thePositionID,0,''); 02732 02733 // Logging... 02734 $newPropArr = $this->getRecordProperties($table,$uid); 02735 $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']); 02736 if ($destPid!=$propArr['pid']) { 02737 $newpagePropArr = $this->getRecordProperties('pages',$destPid); 02738 $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']); // Logged to old page 02739 $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page 02740 } else { 02741 $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page 02742 } 02743 02744 // clear cache after moving 02745 $this->clear_cache($table,$uid); 02746 02747 // fixUniqueInPid 02748 $this->fixUniqueInPid($table,$uid); 02749 02750 // fixCopyAfterDuplFields 02751 if ($origDestPid<0) {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);} 02752 } else { 02753 $destPropArr = $this->getRecordProperties('pages',$destPid); 02754 $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']); 02755 } 02756 } 02757 } 02758 } else { 02759 $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.",13,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']); 02760 } 02761 } 02762 } else { 02763 $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) without having permissions to do so",14,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']); 02764 } 02765 } 02766 } 02767 02779 function copyRecord($table,$uid,$destPid,$first=0,$overrideValues=array(),$excludeFields='') { 02780 global $TCA; 02781 02782 $uid = intval($uid); 02783 if ($TCA[$table] && $uid) { 02784 t3lib_div::loadTCA($table); 02785 if ($this->doesRecordExist($table,$uid,'show')) { // This checks if the record can be selected which is all that a copy action requires. 02786 $data = Array(); 02787 02788 $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_id,t3ver_label,'.$excludeFields,1)); 02789 02790 $row = $this->recordInfo($table,$uid,'*'); 02791 if (is_array($row)) { 02792 02793 // Initializing: 02794 $theNewID = uniqid('NEW'); 02795 $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : ''; 02796 $headerField = $TCA[$table]['ctrl']['label']; 02797 02798 // Getting default data: 02799 $defaultData = $this->newFieldArray($table); 02800 02801 // Getting "copy-after" fields if applicable: 02802 // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before. 02803 $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array(); 02804 02805 // Page TSconfig related: 02806 $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid); // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the id of a page, if the input is a page... 02807 $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); 02808 $tE = $this->getTableEntries($table,$TSConfig); 02809 02810 // Traverse ALL fields of the selected record: 02811 foreach($row as $field => $value) { 02812 if (!in_array($field,$nonFields)) { 02813 02814 // Get TCA configuration for the field: 02815 $conf = $TCA[$table]['columns'][$field]['config']; 02816 02817 // Preparation/Processing of the value: 02818 if ($field=='pid') { // "pid" is hardcoded of course: 02819 $value = $destPid; 02820 } elseif (isset($overrideValues[$field])) { // Override value... 02821 $value = $overrideValues[$field]; 02822 } elseif (isset($copyAfterFields[$field])) { // Copy-after value if available: 02823 $value = $copyAfterFields[$field]; 02824 } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) { // Revert to default for some fields: 02825 $value = $defaultData[$field]; 02826 } else { 02827 // Hide at copy may override: 02828 if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) { 02829 $value=1; 02830 } 02831 // Prepend label on copy: 02832 if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) { 02833 $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0); 02834 } 02835 // Processing based on the TCA config field type (files, references, flexforms...) 02836 $value = $this->copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf); 02837 } 02838 02839 // Add value to array. 02840 $data[$table][$theNewID][$field] = $value; 02841 } 02842 02843 // Overriding values: 02844 if ($TCA[$table]['ctrl']['editlock']) { 02845 $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0; 02846 } 02847 } 02848 02849 // Do the copy by simply submitting the array through TCEmain: 02850 $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain'); 02851 $copyTCE->stripslashes_values = 0; 02852 $copyTCE->copyTree = $this->copyTree; 02853 $copyTCE->cachedTSconfig = $this->cachedTSconfig; // Copy forth the cached TSconfig 02854 $copyTCE->dontProcessTransformations=1; // Transformations should NOT be carried out during copy 02855 // $copyTCE->enableLogging = $table=='pages'?1:0; // If enabled the list-view does not update... 02856 02857 $copyTCE->start($data,'',$this->BE_USER); 02858 $copyTCE->process_datamap(); 02859 02860 // Getting the new UID: 02861 $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID]; 02862 if ($theNewSQLID) { 02863 $this->copyMappingArray[$table][$uid] = $theNewSQLID; 02864 } 02865 02866 // Copy back the cached TSconfig 02867 $this->cachedTSconfig = $copyTCE->cachedTSconfig; 02868 unset($copyTCE); 02869 } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!'); 02870 } else $this->log($table,$uid,3,0,1,'Attempt to copy record without permission'); 02871 } 02872 } 02873 02888 function copyRecord_raw($table,$uid,$pid,$overrideArray=array()) { 02889 global $TCA; 02890 02891 $uid = intval($uid); 02892 if ($TCA[$table] && $uid) { 02893 t3lib_div::loadTCA($table); 02894 if ($this->doesRecordExist($table,$uid,'show')) { 02895 02896 // Set up fields which should not be processed. They are still written - just passed through no-questions-asked! 02897 $nonFields = array('uid','pid','t3ver_id','t3ver_oid','t3ver_label','perms_userid','perms_groupid','perms_user','perms_group','perms_everybody'); 02898 02899 // Select main record: 02900 $row = $this->recordInfo($table,$uid,'*'); 02901 if (is_array($row)) { 02902 02903 // Merge in override array. 02904 $row = array_merge($row,$overrideArray); 02905 02906 // Traverse ALL fields of the selected record: 02907 foreach($row as $field => $value) { 02908 if (!in_array($field,$nonFields)) { 02909 02910 // Get TCA configuration for the field: 02911 $conf = $TCA[$table]['columns'][$field]['config']; 02912 if (is_array($conf)) { 02913 // Processing based on the TCA config field type (files, references, flexforms...) 02914 $value = $this->copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf); 02915 } 02916 02917 // Add value to array. 02918 $row[$field] = $value; 02919 } 02920 } 02921 02922 // Force versioning related fields: 02923 $row['pid'] = $pid; 02924 02925 // Do the copy by internal function 02926 $theNewSQLID = $this->insertNewCopyVersion($table,$row,$pid); 02927 if ($theNewSQLID) { 02928 return $this->copyMappingArray[$table][$uid] = $theNewSQLID; 02929 } 02930 } else $this->log($table,$uid,3,0,1,'Attempt to rawcopy/versionize record that did not exist!'); 02931 } else $this->log($table,$uid,3,0,1,'Attempt to rawcopy/versionize record without copy permission'); 02932 } 02933 } 02934 02944 function insertNewCopyVersion($table,$fieldArray,$realPid) { 02945 global $TCA; 02946 02947 $id = uniqid('NEW'); 02948 02949 // $fieldArray is set as current record. 02950 // The point is that when new records are created as copies with flex type fields there might be a field containing information about which DataStructure to use and without that information the flexforms cannot be correctly processed.... This should be OK since the $checkValueRecord is used by the flexform evaluation only anyways... 02951 $this->checkValue_currentRecord = $fieldArray; 02952 02953 // Traverse record and input-process each value: 02954 foreach($fieldArray as $field => $fieldValue) { 02955 if (isset($TCA[$table]['columns'][$field])) { 02956 // Evaluating the value. 02957 $res = $this->checkValue($table,$field,$fieldValue,$id,'new',$realPid,0); 02958 if (isset($res['value'])) { 02959 $fieldArray[$field] = $res['value']; 02960 } 02961 } 02962 } 02963 02964 // System fields being set: 02965 if ($TCA[$table]['ctrl']['crdate']) { 02966 $fieldArray[$TCA[$table]['ctrl']['crdate']]=time(); 02967 } 02968 if ($TCA[$table]['ctrl']['cruser_id']) { 02969 $fieldArray[$TCA[$table]['ctrl']['cruser_id']]=$this->userid; 02970 } 02971 if ($TCA[$table]['ctrl']['tstamp']) { 02972 $fieldArray[$TCA[$table]['ctrl']['tstamp']]=time(); 02973 } 02974 02975 // Finally, insert record: 02976 $this->insertDB($table,$id,$fieldArray, TRUE); 02977 02978 // Return new id: 02979 return $this->substNEWwithIDs[$id]; 02980 } 02981 02995 function copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf) { 02996 global $TCA; 02997 02998 // Process references and files, currently that means only the files, prepending absolute paths (so the TCEmain engine will detect the file as new and one that should be made into a copy) 02999 $value = $this->copyRecord_procFilesRefs($conf, $uid, $value); 03000 03001 03002 // Register if there are references to take care of (no change to value): 03003 if ($this->isReferenceField($conf)) { 03004 $allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table']; 03005 $prependName = $conf['type']=='group' ? $conf['prepend_tname'] : $conf['neg_foreign_table']; 03006 if ($conf['MM']) { 03007 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 03008 $dbAnalysis->start('',$allowedTables,$conf['MM'],$uid); 03009 $value = implode(',',$dbAnalysis->getValueArray($prependName)); 03010 } 03011 if ($value) { // Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected 03012 $this->registerDBList[$table][$uid][$field] = $value; 03013 } 03014 } 03015 03016 // For "flex" fieldtypes we need to traverse the structure for two reasons: If there are file references they have to be prepended with absolute paths and if there are database reference they MIGHT need to be remapped (still done in remapListedDBRecords()) 03017 if ($conf['type']=='flex') { 03018 03019 // Get current value array: 03020 $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $row, $table); 03021 $currentValueArray = t3lib_div::xml2array($value); 03022 03023 // Traversing the XML structure, processing files: 03024 if (is_array($currentValueArray)) { 03025 $currentValueArray['data'] = $this->checkValue_flex_procInData( 03026 $currentValueArray['data'], 03027 array(), // Not used. 03028 array(), // Not used. 03029 $dataStructArray, 03030 array($table,$uid,$field), // Parameters. 03031 'copyRecord_flexFormCallBack' 03032 ); 03033 $value = $currentValueArray; // Setting value as an array! -> which means the input will be processed according to the 'flex' type when the new copy is created. 03034 } 03035 } 03036 03037 return $value; 03038 } 03039 03048 function copyRecord_localize($table,$uid,$language) { 03049 global $TCA; 03050 03051 $uid = intval($uid); 03052 03053 if ($TCA[$table] && $uid) { 03054 t3lib_div::loadTCA($table); 03055 03056 if ($TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField']) { 03057 if ($langRec = t3lib_BEfunc::getRecord('sys_language',intval($language),'uid,title')) { 03058 if ($this->doesRecordExist($table,$uid,'show')) { 03059 03060 $row = $this->recordInfo($table,$uid,'*'); 03061 if (is_array($row)) { 03062 if ($row[$TCA[$table]['ctrl']['languageField']] <= 0) { 03063 if ($row[$TCA[$table]['ctrl']['transOrigPointerField']] == 0) { 03064 if (!t3lib_BEfunc::getRecordsByField($table,$TCA[$table]['ctrl']['transOrigPointerField'],$uid,'AND pid='.intval($row['pid']).' AND '.$TCA[$table]['ctrl']['languageField'].'='.$langRec['uid'])) { 03065 03066 // Initialize: 03067 $overrideValues = array(); 03068 $excludeFields = array(); 03069 03070 // Set override values: 03071 $overrideValues[$TCA[$table]['ctrl']['languageField']] = $langRec['uid']; 03072 $overrideValues[$TCA[$table]['ctrl']['transOrigPointerField']] = $uid; 03073 03074 // Set exclude Fields: 03075 foreach($TCA[$table]['columns'] as $fN => $fCfg) { 03076 if ($fCfg['l10n_mode']=='prefixLangTitle') { // Check if we are just prefixing: 03077 if ($fCfg['config']['type']=='text' || $fCfg['config']['type']=='input') { 03078 $overrideValues[$fN] = '[Translate to '.$langRec['title'].':] '.$row[$fN]; 03079 } 03080 } elseif (t3lib_div::inList('exclude,noCopy,mergeIfNotBlank',$fCfg['l10n_mode']) && $fN!=$TCA[$table]['ctrl']['languageField'] && $fN!=$TCA[$table]['ctrl']['transOrigPointerField']) { // Otherwise, do not copy field (unless it is the language field or pointer to the original language) 03081 $excludeFields[] = $fN; 03082 } 03083 } 03084 // Execute the copy: 03085 $this->copyRecord($table,$uid,-$uid,1,$overrideValues,implode(',',$excludeFields)); 03086 } else $this->log($table,$uid,3,0,1,'Localization failed; There already was a localization for this language of the record!'); 03087 } else $this->log($table,$uid,3,0,1,'Localization failed; Source record contained a reference to an original default record (which is strange)!'); 03088 } else $this->log($table,$uid,3,0,1,'Localization failed; Source record had another language than "Default" or "All" defined!'); 03089 } else $this->log($table,$uid,3,0,1,'Attempt to localize record that did not exist!'); 03090 } else $this->log($table,$uid,3,0,1,'Attempt to localize record without permission'); 03091 } else $this->log($table,$uid,3,0,1,'Sys language UID "'.$language.'" not found valid!'); 03092 } else $this->log($table,$uid,3,0,1,'Localization failed; "languageField" and "transOrigPointerField" must be defined for the table!'); 03093 } 03094 } 03095 03107 function copyRecord_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2) { 03108 03109 // Extract parameters: 03110 list($table, $uid, $field) = $pParams; 03111 03112 // Process references and files, currently that means only the files, prepending absolute paths: 03113 $dataValue = $this->copyRecord_procFilesRefs($dsConf, $uid, $dataValue); 03114 03115 // If references are set for this field, set flag so they can be corrected later (in ->remapListedDBRecords()) 03116 if ($this->isReferenceField($dsConf) && strlen($dataValue)) { 03117 $this->registerDBList[$table][$uid][$field] = 'FlexForm_reference'; 03118 } 03119 03120 // Return 03121 return array('value' => $dataValue); 03122 } 03123 03135 function copyRecord_procFilesRefs($conf, $uid, $value) { 03136 03137 // Prepend absolute paths to files: 03138 if ($conf['type']=='group' && $conf['internal_type']=='file') { 03139 03140 // Get an array with files as values: 03141 if ($conf['MM']) { 03142 $theFileValues = array(); 03143 03144 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 03145 $dbAnalysis->start('', 'files', $conf['MM'], $uid); 03146 03147 foreach($dbAnalysis->itemArray as $somekey => $someval) { 03148 if ($someval['id']) { 03149 $theFileValues[] = $someval['id']; 03150 } 03151 } 03152 } else { 03153 $theFileValues = t3lib_div::trimExplode(',',$value,1); 03154 } 03155 03156 // Traverse this array of files: 03157 $uploadFolder = $conf['uploadfolder']; 03158 $dest = $this->destPathFromUploadFolder($uploadFolder); 03159 $newValue = array(); 03160 03161 foreach($theFileValues as $file) { 03162 if (trim($file)) { 03163 $realFile = $dest.'/'.trim($file); 03164 if (@is_file($realFile)) { 03165 $newValue[] = $realFile; 03166 } 03167 } 03168 } 03169 03170 // Implode the new filelist into the new value (all files have absolute paths now which means they will get copied when entering TCEmain as new values...) 03171 $value = implode(',',$newValue); 03172 } 03173 03174 // Return the new value: 03175 return $value; 03176 } 03177 03186 function copyPages($uid,$destPid) { 03187 03188 // Initialize: 03189 $uid = intval($uid); 03190 $destPid = intval($destPid); 03191 03192 // Finding list of tables to copy. 03193 $copyTablesArray = $this->admin ? $this->compileAdminTables() : explode(',',$this->BE_USER->groupData['tables_modify']); // These are the tables, the user may modify 03194 if (!strstr($this->copyWhichTables,'*')) { // If not all tables are allowed then make a list of allowed tables: That is the tables that figure in both allowed tables AND the copyTable-list 03195 foreach($copyTablesArray as $k => $table) { 03196 if (!$table || !t3lib_div::inList($this->copyWhichTables.',pages',$table)) { // pages are always going... 03197 unset($copyTablesArray[$k]); 03198 } 03199 } 03200 } 03201 $copyTablesArray = array_unique($copyTablesArray); 03202 03203 // Begin to copy pages if we're allowed to: 03204 if ($this->admin || in_array('pages',$copyTablesArray)) { 03205 03206 // Copy this page we're on. And set first-flag (this will trigger that the record is hidden if that is configured)! 03207 $this->copySpecificPage($uid,$destPid,$copyTablesArray,1); 03208 $theNewRootID = $this->copyMappingArray['pages'][$uid]; // This is the new ID of the rootpage of the copy-action. This ID is excluded when the list is gathered lateron 03209 03210 // If we're going to copy recursively...: 03211 if ($theNewRootID && $this->copyTree) { 03212 03213 // Get ALL subpages to copy: 03214 $CPtable = $this->int_pageTreeInfo(Array(), $uid, intval($this->copyTree), $theNewRootID); 03215 03216 // Now copying the subpages: 03217 foreach($CPtable as $thePageUid => $thePagePid) { 03218 $newPid = $this->copyMappingArray['pages'][$thePagePid]; 03219 if (isset($newPid)) { 03220 $this->copySpecificPage($thePageUid,$newPid,$copyTablesArray); 03221 } else { 03222 $this->log('pages',$uid,5,0,1,'Something went wrong during copying branch'); 03223 break; 03224 } 03225 } 03226 } // else the page was not copied. Too bad... 03227 } else { 03228 $this->log('pages',$uid,5,0,1,'Attempt to copy page without permission to this table'); 03229 } 03230 } 03231 03241 function copySpecificPage($uid,$destPid,$copyTablesArray,$first=0) { 03242 global $TCA; 03243 03244 // Copy the page itself: 03245 $this->copyRecord('pages',$uid,$destPid,$first); 03246 $theNewRootID = $this->copyMappingArray['pages'][$uid]; // The new uid 03247 03248 // If a new page was created upon the copy operation we will proceed with all the tables ON that page: 03249 if ($theNewRootID) { 03250 foreach($copyTablesArray as $table) { 03251 if ($table && is_array($TCA[$table]) && $table!='pages') { // all records under the page is copied. 03252 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($uid).$this->deleteClause($table), '', ($TCA[$table]['ctrl']['sortby'] ? $TCA[$table]['ctrl']['sortby'].' DESC' : '')); 03253 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 03254 $this->copyRecord($table,$row['uid'], $theNewRootID); // Copying each of the underlying records... 03255 } 03256 } 03257 } 03258 } 03259 } 03260 03271 function versionizeRecord($table,$id,$label) { 03272 global $TCA; 03273 03274 $id = intval($id); 03275 03276 if ($TCA[$table] && $TCA[$table]['ctrl']['versioning'] && $id>0) { 03277 if ($this->doesRecordExist($table,$id,'show') && $this->doesRecordExist($table,$id,'edit')) { 03278 03279 // Select main record: 03280 $row = $this->recordInfo($table,$id,'pid,t3ver_id'); 03281 if (is_array($row)) { 03282 if ($row['pid']>=0) { 03283 03284 // Look for next version number: 03285 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 03286 't3ver_id', 03287 $table, 03288 '(t3ver_oid='.$id.' || uid='.$id.')'.$this->deleteClause($table), 03289 '', 03290 't3ver_id DESC', 03291 '1' 03292 ); 03293 list($highestVerNumber) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 03294 03295 // Look for version number of the current: 03296 $subVer = $row['t3ver_id'].'.'.($highestVerNumber+1); 03297 03298 // Set up the values to override when making a raw-copy: 03299 $overrideArray = array( 03300 't3ver_id' => $highestVerNumber+1, 03301 't3ver_oid' => $id, 03302 't3ver_label' => ($label ? $label : $subVer.' / '.date('d-m-Y H:m:s')) 03303 ); 03304 if ($TCA[$table]['ctrl']['editlock']) { 03305 $overrideArray[$TCA[$table]['ctrl']['editlock']] = 0; 03306 } 03307 03308 // Create raw-copy and return result: 03309 return $this->copyRecord_raw($table,$id,-1,$overrideArray); 03310 } else $this->log($table,$id,0,0,1,'Record you wanted to versionize was already a version in archive (pid=-1)!'); 03311 } else $this->log($table,$id,0,0,1,'Record you wanted to versionize didnt exist!'); 03312 } else $this->log($table,$id,0,0,1,'You didnt have correct permissions to make a new version (copy) of this record "'.$table.'" / '.$id); 03313 } else $this->log($table,$id,0,0,1,'Versioning is not supported for this table "'.$table.'" / '.$id); 03314 } 03315 03324 function versionizePages($uid,$label) { 03325 global $TCA; 03326 03327 $uid = intval($uid); 03328 03329 // Finding list of tables ALLOWED to be copied 03330 $allowedTablesArray = $this->admin ? $this->compileAdminTables() : explode(',',$this->BE_USER->groupData['tables_modify']); // These are the tables, the user may modify 03331 03332 // Make list of tables that should come along with a new version of the page: 03333 $verTablesArray = array(); 03334 $allTables = array_keys($TCA); 03335 foreach($allTables as $tN) { 03336 if ($tN!='pages' && $TCA[$tN]['ctrl']['versioning_followPages'] && ($this->admin || in_array($tN, $allowedTablesArray))) { 03337 $verTablesArray[] = $tN; 03338 } 03339 } 03340 03341 // Begin to copy pages if we're allowed to: 03342 if ($this->admin || in_array('pages',$allowedTablesArray)) { 03343 03344 // Versionize this page: 03345 $theNewRootID = $this->versionizeRecord('pages',$uid,$label); 03346 $this->rawCopyPageContent($uid,$theNewRootID,$verTablesArray); 03347 03348 // If we're going to copy recursively...: 03349 if ($theNewRootID && $this->versionizeTree > 0) { 03350 03351 // Get ALL subpages to copy: 03352 $CPtable = $this->int_pageTreeInfo(Array(), $uid, intval($this->versionizeTree), $theNewRootID); 03353 03354 // Now copying the subpages: 03355 foreach($CPtable as $thePageUid => $thePagePid) { 03356 $newPid = $this->copyMappingArray['pages'][$thePagePid]; 03357 if (isset($newPid)) { 03358 $theNewRootID = $this->copyRecord_raw('pages',$thePageUid,$newPid); 03359 $this->rawCopyPageContent($thePageUid,$theNewRootID,$verTablesArray); 03360 } else { 03361 $this->log('pages',$uid,0,0,1,'Something went wrong during copying branch (for versioning)'); 03362 break; 03363 } 03364 } 03365 } // else the page was not copied. Too bad... 03366 } else { 03367 $this->log('pages',$uid,0,0,1,'Attempt to versionize page without permission to this table'); 03368 } 03369 } 03370 03381 function rawCopyPageContent($old_pid,$new_pid,$copyTablesArray) { 03382 global $TCA; 03383 03384 if ($new_pid) { 03385 foreach($copyTablesArray as $table) { 03386 if ($table && is_array($TCA[$table]) && $table!='pages') { // all records under the page is copied. 03387 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($old_pid).$this->deleteClause($table)); 03388 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 03389 $this->copyRecord_raw($table,$row['uid'],$new_pid); // Copying each of the underlying records (method RAW) 03390 } 03391 } 03392 } 03393 } 03394 } 03395 03406 function version_swap($table,$id,$swapWith,$swapContent) { 03407 global $TCA; 03408 03409 /* 03410 Version ID swapping principles: 03411 - Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also 03412 03413 uid pid uid t3ver_oid pid 03414 1: 13 123 --> -13 247 123 (Original has negated UID, and sets t3ver_oid to the final UID (which is nice to know for recovery). PID is unchanged at this point) 03415 2: 247 -1 --> 13 13 123 (Swap version gets original UID, correct t3ver_oid (not required for online version) and is moved to the final PID (123)) 03416 3: -13 123 --> 247 13 -1 (Original gets the swap versions old UID, has t3ver_oid set correctly (important) and the ver. repository PID set right.) 03417 03418 13 is online UID, 03419 247 is specific versions UID 03420 123 is the PID of the original record 03421 -1 is the versioning repository PID 03422 03423 Recovery Process: 03424 Search for negative UID (here "-13"): 03425 YES: Step 1 completed, but at least step 3 didn't. 03426 Search for the negativ UIDs positive (here: "13") 03427 YES: Step 2 completed: Rollback: "t3ver_oid" of the -uid record shows the original UID of the swap record. Use that to change back UID and pid to -1. After that, proceed with recovery for step 1 (see below) 03428 NO: Only Step 1 completed! Rollback: Just change uid "-13" to "13" and "t3ver_oid" to "13" (not important) 03429 NO: No problems. 03430 */ 03431 03432 // First, check if we may actually edit this record: 03433 if ($this->checkRecordUpdateAccess($table,$id)) { 03434 03435 // Find fields to select: 03436 $keepFields = array(); // Keep-fields can be used for other fields than "sortby" if needed in the future... 03437 $selectFields = array('uid','pid','t3ver_oid'); 03438 if ($TCA[$table]['ctrl']['sortby']) { 03439 $selectFields[] = $keepFields[] = $TCA[$table]['ctrl']['sortby']; 03440 } 03441 $selectFields = array_unique($selectFields); 03442 03443 // Select the two versions: 03444 $curVersion = t3lib_BEfunc::getRecord($table,$id,implode(',',$selectFields)); 03445 $swapVersion = t3lib_BEfunc::getRecord($table,$swapWith,implode(',',$selectFields)); 03446 03447 if (is_array($curVersion) && is_array($swapVersion)) { 03448 if (!is_array(t3lib_BEfunc::getRecord($table,-$id,'uid'))) { 03449 03450 // Add "keepfields" 03451 $swapVerBaseArray = array(); 03452 foreach($keepFields as $fN) { 03453 $swapVerBaseArray[$fN] = $curVersion[$fN]; 03454 } 03455 #debug($swapVerBaseArray); 03456 // Check if the swapWith record really IS a version of the original! 03457 if ($swapVersion['pid']==-1 && $swapVersion['t3ver_oid']==$id) { 03458 #debug($curVersion,'$curVersion'); 03459 #debug($swapVersion,'$swapVersion'); 03460 $sqlErrors=array(); 03461 03462 // Step 1: 03463 $sArray = array(); 03464 $sArray['uid'] = -intval($id); 03465 $sArray['t3ver_oid'] = intval($swapWith); 03466 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($id),$sArray); 03467 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03468 03469 // Step 2: 03470 $sArray = $swapVerBaseArray; 03471 $sArray['uid'] = intval($id); 03472 $sArray['t3ver_oid'] = intval($id); 03473 $sArray['pid'] = intval($curVersion['pid']); 03474 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($swapWith),$sArray); 03475 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03476 03477 // Step 3: 03478 $sArray = array(); 03479 $sArray['uid'] = intval($swapWith); 03480 $sArray['t3ver_oid'] = intval($id); 03481 $sArray['pid'] = -1; 03482 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid=-'.intval($id),$sArray); 03483 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03484 03485 if (!count($sqlErrors)) { 03486 $this->log($table,$id,0,0,0,'Swapping successful for table "'.$table.'" uid '.$id.'=>'.$swapWith); 03487 03488 // SWAPPING pids for subrecords: 03489 if ($table=='pages' && $swapContent) { 03490 03491 // Collect table names that should be copied along with the tables: 03492 foreach($TCA as $tN => $tCfg) { 03493 if ($TCA[$tN]['ctrl']['versioning_followPages'] || ($tN=='pages' && $swapContent==='ALL')) { // THIS produces the problem that some records might be left inside a versionized branch. Question is; Should ALL records swap pids, not only the versioning_followPages ones? 03494 $temporaryPid = -($id+1000000); 03495 03496 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($id),array('pid'=>$temporaryPid)); 03497 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03498 03499 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($swapWith),array('pid'=>$id)); 03500 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03501 03502 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($temporaryPid),array('pid'=>$swapWith)); 03503 if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error(); 03504 03505 if (count($sqlErrors)) { 03506 $this->log($table,$id,0,0,1,'During Swapping: SQL errors happend: '.implode('; ',$sqlErrors)); 03507 } 03508 } 03509 } 03510 } 03511 // Clear cache: 03512 $this->clear_cache($table,$id); 03513 03514 } else $this->log($table,$id,0,0,1,'During Swapping: SQL errors happend: '.implode('; ',$sqlErrors)); 03515 } else $this->log($table,$id,0,0,1,'In swap version, either pid was not -1 or the t3ver_oid didn\'t match the id of the online version as it must!'); 03516 } else $this->log($table,$id,0,0,1,'Error: A record with a negative UID existed - that indicates some inconsistency in the database from prior versioning actions!'); 03517 } else $this->log($table,$id,0,0,1,'Error: Either online or swap version could not be selected!'); 03518 } else $this->log($table,$id,0,0,1,'Error: You cannot swap versions for a record you do not have access to edit!'); 03519 } 03520 03530 function int_pageTreeInfo($CPtable,$pid,$counter, $rootID) { 03531 if ($counter) { 03532 $addW = !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($this->pMap['show']) : ''; 03533 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid='.intval($pid).$this->deleteClause('pages').$addW, '', 'sorting DESC'); 03534 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 03535 if ($row['uid']!=$rootID) { 03536 $CPtable[$row['uid']] = $pid; 03537 if ($counter-1) { // If the uid is NOT the rootID of the copyaction and if we are supposed to walk further down 03538 $CPtable = $this->int_pageTreeInfo($CPtable,$row['uid'],$counter-1, $rootID); 03539 } 03540 } 03541 } 03542 } 03543 return $CPtable; 03544 } 03545 03551 function compileAdminTables() { 03552 global $TCA; 03553 reset ($TCA); 03554 $listArr = array(); 03555 while (list($table)=each($TCA)) { 03556 $listArr[]=$table; 03557 } 03558 return $listArr; 03559 } 03560 03568 function fixUniqueInPid($table,$uid) { 03569 global $TCA; 03570 if ($TCA[$table]) { 03571 t3lib_div::loadTCA($table); 03572 reset ($TCA[$table]['columns']); 03573 $curData=$this->recordInfo($table,$uid,'*'); 03574 $newData=array(); 03575 while (list($field,$conf)=each($TCA[$table]['columns'])) { 03576 if ($conf['config']['type']=='input') { 03577 $evalCodesArray = t3lib_div::trimExplode(',',$conf['config']['eval'],1); 03578 if (in_array('uniqueInPid',$evalCodesArray)) { 03579 $newV = $this->getUnique($table,$field,$curData[$field],$uid,$curData['pid']); 03580 if (strcmp($newV,$curData[$field])) { 03581 $newData[$field]=$newV; 03582 } 03583 } 03584 } 03585 } 03586 // IF there are changed fields, then update the database 03587 if (count($newData)) { 03588 $this->updateDB($table,$uid,$newData); 03589 } 03590 } 03591 } 03592 03604 function fixCopyAfterDuplFields($table,$uid,$prevUid,$update, $newData=array()) { 03605 global $TCA; 03606 if ($TCA[$table] && $TCA[$table]['ctrl']['copyAfterDuplFields']) { 03607 t3lib_div::loadTCA($table); 03608 $prevData=$this->recordInfo($table,$prevUid,'*'); 03609 $theFields = t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['copyAfterDuplFields'],1); 03610 reset($theFields); 03611 while(list(,$field)=each($theFields)) { 03612 if ($TCA[$table]['columns'][$field] && ($update || !isset($newData[$field]))) { 03613 $newData[$field]=$prevData[$field]; 03614 } 03615 } 03616 if ($update && count($newData)) { 03617 $this->updateDB($table,$uid,$newData); 03618 } 03619 } 03620 return $newData; 03621 } 03622 03629 function extFileFields ($table) { 03630 global $TCA; 03631 $listArr=array(); 03632 t3lib_div::loadTCA($table); 03633 if ($TCA[$table]['columns']) { 03634 reset($TCA[$table]['columns']); 03635 while (list($field,$configArr)=each($TCA[$table]['columns'])) { 03636 if ($configArr['config']['type']=='group' && $configArr['config']['internal_type']=='file') { 03637 $listArr[]=$field; 03638 } 03639 } 03640 } 03641 return $listArr; 03642 } 03643 03655 function getCopyHeader($table,$pid,$field,$value,$count,$prevTitle='') { 03656 global $TCA; 03657 03658 // Set title value to check for: 03659 if ($count) { 03660 $checkTitle = $value.rtrim(' '.sprintf($this->prependLabel($table),$count)); 03661 } else { 03662 $checkTitle = $value; 03663 } 03664 03665 // Do check: 03666 if ($prevTitle != $checkTitle || $count<100) { 03667 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($pid).' AND '.$field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($checkTitle, $table).'"'.$this->deleteClause($table), '', '', '1'); 03668 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) { 03669 return $this->getCopyHeader($table,$pid,$field,$value,$count+1,$checkTitle); 03670 } 03671 } 03672 03673 // Default is to just return the current input title if no other was returned before: 03674 return $checkTitle; 03675 } 03676 03684 function prependLabel($table) { 03685 global $TCA; 03686 if (is_object($GLOBALS['LANG'])) { 03687 $label = $GLOBALS['LANG']->sL($TCA[$table]['ctrl']['prependAtCopy']); 03688 } else { 03689 list($label) = explode('|',$TCA[$table]['ctrl']['prependAtCopy']); 03690 } 03691 return $label; 03692 } 03693 03701 function resolvePid($table,$pid) { 03702 global $TCA; 03703 $pid=intval($pid); 03704 if ($pid < 0) { 03705 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid', $table, 'uid='.abs($pid)); 03706 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 03707 $pid = intval($row['pid']); 03708 } 03709 return $pid; 03710 } 03711 03719 function clearPrefixFromValue($table,$value) { 03720 global $TCA; 03721 $regex = sprintf(quotemeta($this->prependLabel($table)),'[0-9]*').'$'; 03722 return @ereg_replace($regex,'',$value); 03723 } 03724 03730 function remapListedDBRecords() { 03731 global $TCA; 03732 #debug($this->registerDBList); 03733 #debug($this->copyMappingArray_merged); 03734 if (count($this->registerDBList)) { 03735 reset($this->registerDBList); 03736 while(list($table,$records)=each($this->registerDBList)) { 03737 t3lib_div::loadTCA($table); 03738 reset($records); 03739 while(list($uid,$fields)=each($records)) { 03740 $newData = array(); 03741 $theUidToUpdate = $this->copyMappingArray_merged[$table][$uid]; 03742 03743 foreach($fields as $fieldName => $value) { 03744 $conf = $TCA[$table]['columns'][$fieldName]['config']; 03745 03746 switch($conf['type']) { 03747 case 'group': 03748 case 'select': 03749 $vArray = $this->remapListedDBRecords_procDBRefs($conf, $value, $theUidToUpdate); 03750 if (is_array($vArray)) { 03751 $newData[$fieldName] = implode(',',$vArray); 03752 } 03753 break; 03754 case 'flex': 03755 if ($value=='FlexForm_reference') { 03756 $origRecordRow = $this->recordInfo($table,$theUidToUpdate,'*'); // This will fetch the new row for the element 03757 03758 if (is_array($origRecordRow)) { 03759 03760 // Get current data structure and value array: 03761 $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $origRecordRow, $table); 03762 $currentValueArray = t3lib_div::xml2array($origRecordRow[$fieldName]); 03763 #debug($dataStructArray); 03764 #debug($currentValueArray); 03765 #debug($origRecordRow); 03766 #debug($currentValueArray['data']); 03767 // Do recursive processing of the XML data: 03768 $currentValueArray['data'] = $this->checkValue_flex_procInData( 03769 $currentValueArray['data'], 03770 array(), // Not used. 03771 array(), // Not used. 03772 $dataStructArray, 03773 array($table,$theUidToUpdate,$fieldName), // Parameters. 03774 'remapListedDBRecords_flexFormCallBack' 03775 ); 03776 #debug($currentValueArray['data']); 03777 // The return value should be compiled back into XML, ready to insert directly in the field (as we call updateDB() directly later): 03778 if (is_array($currentValueArray['data'])) { 03779 $newData[$fieldName] = 03780 '<?xml version="1.0" encoding="'.$GLOBALS['LANG']->charSet.'" standalone="yes" ?>'.chr(10). 03781 $this->checkValue_flexArray2Xml($currentValueArray); 03782 } 03783 } 03784 } 03785 break; 03786 default: 03787 debug('Field type should not appear here: '. $conf['type']); 03788 break; 03789 } 03790 } 03791 03792 if (count($newData)) { // If any fields were changed, those fields are updated! 03793 $this->updateDB($table,$theUidToUpdate,$newData); 03794 #debug($this->recordInfo($table,$theUidToUpdate,'*'),'Stored result:'); 03795 // debug($newData); 03796 } 03797 } 03798 } 03799 } 03800 } 03801 03813 function remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2) { 03814 03815 // Extract parameters: 03816 list($table,$uid,$field) = $pParams; 03817 03818 // If references are set for this field, set flag so they can be corrected later: 03819 if ($this->isReferenceField($dsConf) && strlen($dataValue)) { 03820 $vArray = $this->remapListedDBRecords_procDBRefs($dsConf, $dataValue, $uid); 03821 if (is_array($vArray)) { 03822 $dataValue = implode(',',$vArray); 03823 } 03824 } 03825 03826 // Return 03827 return array('value' => $dataValue); 03828 } 03829 03839 function remapListedDBRecords_procDBRefs($conf, $value, $MM_localUid) { 03840 03841 // Initialize variables 03842 $set = FALSE; // Will be set true if an upgrade should be done... 03843 $allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table']; // Allowed tables for references. 03844 $prependName = $conf['type']=='group' ? $conf['prepend_tname'] : ''; // Table name to prepend the UID 03845 $dontRemapTables = t3lib_div::trimExplode(',',$conf['dontRemapTablesOnCopy'],1); // Which tables that should possibly not be remapped 03846 03847 // Convert value to list of references: 03848 $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup'); 03849 $dbAnalysis->registerNonTableValues = ($conf['type']=='select' && $conf['allowNonIdValues']) ? 1 : 0; 03850 $dbAnalysis->start($value, $allowedTables, $conf['MM'], $MM_localUid); 03851 03852 // Traverse those references and map IDs: 03853 foreach($dbAnalysis->itemArray as $k => $v) { 03854 $mapID = $this->copyMappingArray_merged[$v['table']][$v['id']]; 03855 if ($mapID && !in_array($v['table'],$dontRemapTables)) { 03856 $dbAnalysis->itemArray[$k]['id'] = $mapID; 03857 $set = TRUE; 03858 } 03859 } 03860 03861 // If a change has been done, set the new value(s) 03862 if ($set) { 03863 if ($conf['MM']) { 03864 $dbAnalysis->writeMM($conf['MM'], $theUidToUpdate, $prependName); 03865 } else { 03866 $vArray = $dbAnalysis->getValueArray($prependName); 03867 if ($conf['type']=='select') { 03868 $vArray = $dbAnalysis->convertPosNeg($vArray, $conf['foreign_table'], $conf['neg_foreign_table']); 03869 } 03870 return $vArray; 03871 } 03872 } 03873 } 03874 03884 function extFileFunctions($table,$field,$filelist,$func) { 03885 global $TCA; 03886 t3lib_div::loadTCA($table); 03887 $uploadFolder = $TCA[$table]['columns'][$field]['config']['uploadfolder']; 03888 if ($uploadFolder && trim($filelist)) { 03889 $uploadPath = $this->destPathFromUploadFolder($uploadFolder); 03890 $fileArray = explode(',',$filelist); 03891 while (list(,$theFile)=each($fileArray)) { 03892 $theFile=trim($theFile); 03893 if ($theFile) { 03894 switch($func) { 03895 case 'deleteAll': 03896 if (@is_file($uploadPath.'/'.$theFile)) { 03897 unlink ($uploadPath.'/'.$theFile); 03898 } else { 03899 $this->log($table,0,3,0,100,"Delete: Referenced file that was supposed to be deleted together with it's record didn't exist"); 03900 } 03901 break; 03902 } 03903 } 03904 } 03905 } 03906 } 03907 03916 function deleteRecord($table,$uid, $noRecordCheck) { 03917 // This function may not be used to delete pages-records unless the underlying records are already deleted 03918 // If $noRecordCheck is set, then the function does not check permissions 03919 global $TCA; 03920 $uid = intval($uid); 03921 if ($TCA[$table] && $uid) { 03922 $deleteRow = $TCA[$table]['ctrl']['delete']; 03923 if ($noRecordCheck || $this->doesRecordExist($table,$uid,'delete')) { 03924 if ($deleteRow) { 03925 $updateFields = array( 03926 $deleteRow => 1 03927 ); 03928 03929 // If the table is sorted, then the sorting number is set very high 03930 if ($TCA[$table]['ctrl']['sortby']) { 03931 $updateFields[$TCA[$table]['ctrl']['sortby']] = 1000000000; 03932 } 03933 03934 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); 03935 } else { 03936 03937 // Fetches all fields that holds references to files 03938 $fileFieldArr = $this->extFileFields($table); 03939 if (count($fileFieldArr)) { 03940 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',',$fileFieldArr), $table, 'uid='.intval($uid)); 03941 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 03942 $fArray = $fileFieldArr; 03943 03944 foreach($fArray as $theField) { // MISSING: Support for MM file relations! 03945 $this->extFileFunctions($table,$theField,$row[$theField],'deleteAll'); // This deletes files that belonged to this record. 03946 } 03947 } else { 03948 $this->log($table,$uid,3,0,100,'Delete: Zero rows in result when trying to read filenames from record which should be deleted'); 03949 } 03950 } 03951 03952 $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid='.intval($uid)); 03953 } 03954 03955 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 03956 $this->log($table,$uid,3,0,0,''); 03957 } else { 03958 $this->log($table,$uid,3,0,100,$GLOBALS['TYPO3_DB']->sql_error()); 03959 } 03960 03961 $this->clear_cache($table,$uid); // clear cache 03962 } else { 03963 $this->log($table,$uid,3,0,1,'Attempt to delete record without delete-permissions'); 03964 } 03965 } 03966 } 03967 03974 function deletePages($uid) { 03975 if ($this->doesRecordExist('pages',$uid,'delete')) { // If we may at all delete this page 03976 if ($this->deleteTree) { 03977 $brExist = $this->doesBranchExist('',$uid,$this->pMap['delete'],1); // returns the branch 03978 if ($brExist != -1) { // Checks if we had permissions 03979 if ($this->noRecordsFromUnallowedTables($brExist.$uid)) { 03980 $uidArray = explode(',',$brExist); 03981 while (list(,$listUid)=each($uidArray)) { 03982 if (trim($listUid)) { 03983 $this->deleteSpecificPage($listUid); 03984 } 03985 } 03986 $this->deleteSpecificPage($uid); 03987 } else { 03988 $this->log('pages',$uid,3,0,1,'Attempt to delete records from disallowed tables'); 03989 } 03990 } else { 03991 $this->log('pages',$uid,3,0,1,'Attempt to delete pages in branch without permissions'); 03992 } 03993 } else { 03994 $brExist = $this->doesBranchExist('',$uid,$this->pMap['delete'],1); // returns the branch 03995 if ($brExist == '') { // Checks if branch exists 03996 if ($this->noRecordsFromUnallowedTables($uid)) { 03997 $this->deleteSpecificPage($uid); 03998 } else { 03999 $this->log('pages',$uid,3,0,1,'Attempt to delete records from disallowed tables'); 04000 } 04001 } else { 04002 $this->log('pages',$uid,3,0,1,'Attempt to delete page which has subpages'); 04003 } 04004 } 04005 } else { 04006 $this->log('pages',$uid,3,0,1,'Attempt to delete page without permissions'); 04007 } 04008 } 04009 04016 function deleteSpecificPage($uid) { 04017 // internal function !! 04018 global $TCA; 04019 reset ($TCA); 04020 $uid = intval($uid); 04021 if ($uid) { 04022 while (list($table)=each($TCA)) { 04023 if ($table!='pages') { 04024 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($uid).$this->deleteClause($table)); 04025 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 04026 $this->deleteRecord($table,$row['uid'], 1); 04027 } 04028 } 04029 } 04030 $this->deleteRecord('pages',$uid, 1); 04031 } 04032 } 04033 04040 function noRecordsFromUnallowedTables($inList) { 04041 // used by the deleteFunctions to check if there are records from disallowed tables under the pages to be deleted. Return true, if permission granted 04042 global $TCA; 04043 reset ($TCA); 04044 $inList = trim($this->rmComma(trim($inList))); 04045 if ($inList && !$this->admin) { 04046 while (list($table) = each($TCA)) { 04047 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, 'pid IN ('.$inList.')'); 04048 $count = $GLOBALS['TYPO3_DB']->sql_fetch_row($mres); 04049 if ($count[0] && ($this->tableReadOnly($table) || !$this->checkModifyAccessList($table))) { 04050 return false; 04051 } 04052 } 04053 } 04054 return true; 04055 } 04056 04057 04058 04059 04060 04061 04062 04063 04064 04065 04066 04067 04068 04069 04070 04071 04072 04073 04074 04075 04076 04077 04078 04079 04080 04081 04082 /********************************************* 04083 * 04084 * MISC FUNCTIONS 04085 * 04086 ********************************************/ 04087 04102 function getSortNumber($table,$uid,$pid) { 04103 global $TCA; 04104 if ($TCA[$table] && $TCA[$table]['ctrl']['sortby']) { 04105 $sortRow = $TCA[$table]['ctrl']['sortby']; 04106 if ($pid>=0) { // Sorting number is in the top 04107 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($sortRow.',pid,uid', $table, 'pid='.intval($pid).$this->deleteClause($table), '', $sortRow.' ASC', '1'); // Fetches the first record under this pid 04108 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // There was a page 04109 if ($row['uid']==$uid) { // The top record was the record it self, so we return its current sortnumber 04110 return $row[$sortRow]; 04111 } 04112 if ($row[$sortRow] < 1) { // If the pages sortingnumber < 1 we must resort the records under this pid 04113 $this->resorting($table,$pid,$sortRow,0); 04114 return $this->sortIntervals; 04115 } else { 04116 return floor($row[$sortRow]/2); 04117 } 04118 } else { // No pages, so we choose the default value as sorting-number 04119 return $this->sortIntervals; 04120 } 04121 } else { // Sorting number is inside the list 04122 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($sortRow.',pid,uid', $table, 'uid='.abs($pid).$this->deleteClause($table)); // Fetches the record which is supposed to be the prev record 04123 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // There was a record 04124 if ($row['uid']==$uid) { // If the record happends to be it self 04125 $sortNumber = $row[$sortRow]; 04126 } else { 04127 $subres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 04128 $sortRow.',pid,uid', 04129 $table, 04130 'pid='.intval($row['pid']).' AND '.$sortRow.'>='.intval($row[$sortRow]).$this->deleteClause($table), 04131 '', 04132 $sortRow.' ASC', 04133 '2' 04134 ); // Fetches the next record in order to calculate the in between sortNumber 04135 if ($GLOBALS['TYPO3_DB']->sql_num_rows($subres)==2) { // There was a record afterwards 04136 $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres); // Forward to the second result... 04137 $subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres); // There was a record afterwards 04138 $sortNumber = $row[$sortRow]+ floor(($subrow[$sortRow]-$row[$sortRow])/2); // The sortNumber is found in between these values 04139 if ($sortNumber<=$row[$sortRow] || $sortNumber>=$subrow[$sortRow]) { // The sortNumber happend NOT to be between the two surrounding numbers, so we'll have to resort the list 04140 $sortNumber = $this->resorting($table,$row['pid'],$sortRow, $row['uid']); // By this special param, resorting reserves and returns the sortnumber after the uid 04141 } 04142 } else { // If after the last record in the list, we just add the sortInterval to the last sortvalue 04143 $sortNumber = $row[$sortRow]+$this->sortIntervals; 04144 } 04145 } 04146 return Array('pid' => $row['pid'], 'sortNumber' => $sortNumber); 04147 } else { 04148 $propArr = $this->getRecordProperties($table,$uid); 04149 $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after a non-existing record (uid=%s)",1,array($propArr['header'],$table.':'.$uid,abs($pid)),$propArr['pid']); // OK, dont insert $propArr['event_pid'] here... 04150 return false; // There MUST be a page or else this cannot work 04151 } 04152 } 04153 } 04154 } 04155 04167 function resorting($table,$pid,$sortRow, $return_SortNumber_After_This_Uid) { 04168 global $TCA; 04169 if ($TCA[$table] && $sortRow && $TCA[$table]['ctrl']['sortby']==$sortRow) { 04170 $returnVal = 0; 04171 $intervals = $this->sortIntervals; 04172 $i = $intervals*2; 04173 04174 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($pid).$this->deleteClause($table), '', $sortRow.' ASC'); 04175 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 04176 $uid=intval($row['uid']); 04177 if ($uid) { 04178 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), array($sortRow=>$i)); 04179 if ($uid==$return_SortNumber_After_This_Uid) { // This is used to return a sortingValue if the list is resorted because of inserting records inside the list and not in the top 04180 $i = $i+$intervals; 04181 $returnVal=$i; 04182 } 04183 } else {die ('Fatal ERROR!! No Uid at resorting.');} 04184 $i = $i+$intervals; 04185 } 04186 return $returnVal; 04187 } 04188 } 04189 04196 function rmComma ($input) { 04197 return ereg_replace(',$','',$input); 04198 } 04199 04206 function convNumEntityToByteValue($input) { 04207 $token = md5(microtime()); 04208 $parts = explode($token,ereg_replace('(&#([0-9]+);)',$token.'\2'.$token,$input)); 04209 04210 foreach($parts as $k => $v) { 04211 if ($k%2) { 04212 $v = intval($v); 04213 if ($v > 32) { // Just to make sure that control bytes are not converted. 04214 $parts[$k] =chr(intval($v)); 04215 } 04216 } 04217 } 04218 04219 return implode('',$parts); 04220 } 04221 04228 function destPathFromUploadFolder ($folder) { 04229 return PATH_site.$folder; 04230 } 04231 04239 function destNotInsideSelf ($dest,$id) { 04240 $loopCheck = 100; 04241 $dest = intval($dest); 04242 $id = intval($id); 04243 if ($dest==$id) { 04244 return false; 04245 } 04246 while ($dest!=0 && $loopCheck>0) { 04247 $loopCheck--; 04248 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid, uid', 'pages', 'uid='.intval($dest).$this->deleteClause('pages')); 04249 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 04250 if ($row['pid']==$id) { 04251 return false; 04252 } 04253 } else { 04254 return false; 04255 } 04256 } 04257 return true; 04258 } 04259 04265 function getExcludeListArray() { 04266 global $TCA; 04267 $list = array(); 04268 reset($TCA); 04269 while (list($table)=each($TCA)) { 04270 t3lib_div::loadTCA($table); 04271 while (list($field,$config)=each($TCA[$table]['columns'])) { 04272 if ($config['exclude'] && !t3lib_div::inList($this->BE_USER->groupData['non_exclude_fields'],$table.':'.$field)) { 04273 $list[]=$table.'-'.$field; 04274 } 04275 } 04276 } 04277 return $list; 04278 } 04279 04289 function doesPageHaveUnallowedTables($page_uid,$doktype) { 04290 global $TCA, $PAGES_TYPES; 04291 $page_uid = intval($page_uid); 04292 if (!$page_uid) { 04293 return FALSE; // Not a number. Probably a new page 04294 } 04295 04296 $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables']; 04297 $allowedArray = t3lib_div::trimExplode(',',$allowedTableList,1); 04298 if (strstr($allowedTableList,'*')) { // If all tables is OK the return true 04299 return FALSE; // OK... 04300 } 04301 04302 reset ($TCA); 04303 $tableList = array(); 04304 while (list($table)=each($TCA)) { 04305 if (!in_array($table,$allowedArray)) { // If the table is not in the allowed list, check if there are records... 04306 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, 'pid='.intval($page_uid)); 04307 $count = $GLOBALS['TYPO3_DB']->sql_fetch_row($mres); 04308 if ($count[0]) { 04309 $tableList[]=$table; 04310 } 04311 } 04312 } 04313 return implode(',',$tableList); 04314 } 04315 04322 function deleteClause($table) { 04323 // Returns the proper delete-clause if any for a table from TCA 04324 global $TCA; 04325 if ($TCA[$table]['ctrl']['delete']) { 04326 return ' AND NOT '.$table.'.'.$TCA[$table]['ctrl']['delete']; 04327 } else { 04328 return ''; 04329 } 04330 } 04331 04338 function tableReadOnly($table) { 04339 // returns true if table is readonly 04340 global $TCA; 04341 return ($TCA[$table]['ctrl']['readOnly'] ? 1 : 0); 04342 } 04343 04350 function tableAdminOnly($table) { 04351 // returns true if table is admin-only 04352 global $TCA; 04353 return ($TCA[$table]['ctrl']['adminOnly'] ? 1 : 0); 04354 } 04355 04364 function getInterfacePagePositionID($uid) { 04365 global $TCA; 04366 $perms_clause = $this->BE_USER->getPagePermsClause(1); 04367 $deleted = $TCA['pages']['ctrl']['delete'] ? 'AND NOT A.'.$TCA['pages']['ctrl']['delete'].' AND NOT pages.'.$TCA['pages']['ctrl']['delete'].' ' : ''; 04368 04369 // This fetches a list of 1 or 2 pages, where - if 2 - the 2nd is the page BEFORE this ($uid). If 1 then the page ($uid) is at the top itself 04370 $subres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 04371 'pages.uid, pages.pid', 04372 'pages AS A, pages', 04373 'A.pid=pages.pid AND A.uid="'.$uid.'" 04374 '.$deleted.' 04375 AND pages.sorting<=A.sorting 04376 AND '.$perms_clause, 04377 '', 04378 'pages.sorting DESC', 04379 '2' 04380 ); 04381 if ($GLOBALS['TYPO3_DB']->sql_num_rows($subres)==2) { // There was a record before 04382 $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres); // forwards to the second result 04383 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres); 04384 return -$row['uid']; 04385 } else { 04386 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres); 04387 return $row['pid']; 04388 } 04389 } 04390 04397 function isReferenceField($conf) { 04398 return ($conf['type']=='group' && $conf['internal_type']=='db') || ($conf['type']=='select' && $conf['foreign_table']); 04399 } 04400 04407 function getTCEMAIN_TSconfig($tscPID) { 04408 if (!isset($this->cachedTSconfig[$tscPID])) { 04409 $this->cachedTSconfig[$tscPID] = $this->BE_USER->getTSConfig('TCEMAIN',t3lib_BEfunc::getPagesTSconfig($tscPID)); 04410 } 04411 return $this->cachedTSconfig[$tscPID]['properties']; 04412 } 04413 04421 function getTableEntries($table,$TSconfig) { 04422 $tA = is_array($TSconfig['table.'][$table.'.']) ? $TSconfig['table.'][$table.'.'] : array();; 04423 $dA = is_array($TSconfig['default.']) ? $TSconfig['default.'] : array(); 04424 return t3lib_div::array_merge_recursive_overrule($dA,$tA); 04425 } 04426 04435 function setHistory($table,$id,$logId) { 04436 if (isset($this->historyRecords[$table.':'.$id])) { 04437 04438 list($tscPID) = t3lib_BEfunc::getTSCpid($table,$id,''); 04439 $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); 04440 04441 $tE = $this->getTableEntries($table,$TSConfig); 04442 $keepEntries = strcmp($tE['history.']['keepEntries'],'') ? t3lib_div::intInRange($tE['history.']['keepEntries'],0,200) : 10; 04443 $maxAgeSeconds = 60*60*24*(strcmp($tE['history.']['maxAgeDays'],'') ? t3lib_div::intInRange($tE['history.']['maxAgeDays'],0,200) : 7); // one week 04444 $this->clearHistory($table,$id,t3lib_div::intInRange($keepEntries-1,0),$maxAgeSeconds); 04445 04446 if ($keepEntries) { 04447 $fields_values = array(); 04448 $fields_values['history_data'] = serialize($this->historyRecords[$table.':'.$id]); 04449 $fields_values['fieldlist'] = implode(',',array_keys($this->historyRecords[$table.':'.$id]['newRecord'])); 04450 $fields_values['tstamp'] = time(); 04451 $fields_values['tablename'] = $table; 04452 $fields_values['recuid'] = $id; 04453 $fields_values['sys_log_uid'] = $logId; 04454 04455 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_history', $fields_values); 04456 } 04457 } 04458 } 04459 04472 function clearHistory($table,$id,$keepEntries=10,$maxAgeSeconds=604800) { 04473 $tstampLimit = $maxAgeSeconds ? time()-$maxAgeSeconds : 0; 04474 04475 $where = ' 04476 tablename="'.$GLOBALS['TYPO3_DB']->quoteStr($table, 'sys_history').'" 04477 AND recuid='.intval($id).' 04478 AND snapshot=0'; 04479 04480 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,tstamp', 'sys_history', $where, '', 'uid DESC', intval($keepEntries).',1'); 04481 $resRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 04482 if ($tstampLimit && intval($resRow['tstamp'])<$tstampLimit) { 04483 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,tstamp', 'sys_history', $where.' AND tstamp<'.intval($tstampLimit), '', 'uid DESC', '1'); 04484 $resRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 04485 04486 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_history', $where.' AND uid<='.intval($resRow['uid'])); 04487 } elseif (is_array($resRow)) { 04488 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_history', $where.' AND uid<='.intval($resRow['uid'])); 04489 } 04490 } 04491 04520 function log($table,$recuid,$action,$recpid,$error,$details,$details_nr=0,$data=array(),$event_pid=-1,$NEWid='') { 04521 if ($this->enableLogging) { 04522 $type=1; // Type value for tce_db.php 04523 if (!$this->storeLogMessages) {$details='';} 04524 return $this->BE_USER->writelog($type,$action,$error,$details_nr,$details,$data,$table,$recuid,$recpid,$event_pid,$NEWid); 04525 } 04526 } 04527 04534 function printLogErrorMessages($redirect) { 04535 $res_log = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 04536 '*', 04537 'sys_log', 04538 'type=1 AND userid='.intval($this->BE_USER->user['uid']).' AND tstamp='.intval($GLOBALS['EXEC_TIME']).' AND error!=0' 04539 ); 04540 $errorJS = array(); 04541 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_log)) { 04542 $log_data = unserialize($row['log_data']); 04543 $errorJS[] = $row[error].': '.sprintf($row['details'], $log_data[0],$log_data[1],$log_data[2],$log_data[3],$log_data[4]); 04544 } 04545 04546 if (count($errorJS)) { 04547 $error_doc = t3lib_div::makeInstance('template'); 04548 $error_doc->backPath = ''; 04549 04550 $content.= $error_doc->startPage('tce_db.php Error output'); 04551 04552 $lines[] = ' 04553 <tr class="bgColor5"> 04554 <td colspan="2" align="center"><strong>Errors:</strong></td> 04555 </tr>'; 04556 04557 foreach($errorJS as $line) { 04558 $lines[] = ' 04559 <tr class="bgColor4"> 04560 <td valign="top"><img'.t3lib_iconWorks::skinImg('','gfx/icon_fatalerror.gif','width="18" height="16"').' alt="" /></td> 04561 <td>'.htmlspecialchars($line).'</td> 04562 </tr>'; 04563 } 04564 04565 $lines[] = ' 04566 <tr> 04567 <td colspan="2" align="center"><br />'. 04568 '<form action=""><input type="submit" value="Continue" onclick="'.htmlspecialchars('document.location=\''.$redirect.'\';return false;').'"></form>'. 04569 '</td> 04570 </tr>'; 04571 04572 $content.= ' 04573 <br/><br/> 04574 <table border="0" cellpadding="1" cellspacing="1" width="300" align="center"> 04575 '.implode('',$lines).' 04576 </table>'; 04577 04578 $content.= $error_doc->endPage(); 04579 echo $content; 04580 exit; 04581 } 04582 } 04583 04596 function clear_cacheCmd($cacheCmd) { 04597 global $TYPO3_CONF_VARS; 04598 04599 // Clear cache for either ALL pages or ALL tables! 04600 switch($cacheCmd) { 04601 case 'pages': 04602 if ($this->admin || $this->BE_USER->getTSConfigVal('options.clearCache.pages')) { 04603 if (t3lib_extMgm::isLoaded('cms')) { 04604 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages',''); 04605 } 04606 } 04607 break; 04608 case 'all': 04609 if ($this->admin || $this->BE_USER->getTSConfigVal('options.clearCache.all')) { 04610 if (t3lib_extMgm::isLoaded('cms')) { 04611 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages',''); 04612 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection',''); 04613 } 04614 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_hash',''); 04615 04616 // Clearing additional cache tables: 04617 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'])) { 04618 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'] as $tableName) { 04619 if (!ereg('[^[:alnum:]_]',$tableName) && substr($tableName,-5)=='cache') { 04620 $GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName,''); 04621 } else { 04622 die('Fatal Error: Trying to flush table "'.$tableName.'" with "Clear All Cache"'); 04623 } 04624 } 04625 } 04626 } 04627 break; 04628 case 'temp_CACHED': 04629 if ($this->admin && $TYPO3_CONF_VARS['EXT']['extCache']) { 04630 $this->removeCacheFiles(); 04631 } 04632 break; 04633 } 04634 04635 // Clear cache for a page ID! 04636 if (t3lib_div::testInt($cacheCmd)) { 04637 if (t3lib_extMgm::isLoaded('cms')) { 04638 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id='.intval($cacheCmd)); 04639 } 04640 } 04641 04642 // Call post processing function for clear-cache: 04643 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'])) { 04644 $_params = array('cacheCmd'=>$cacheCmd); 04645 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) { 04646 t3lib_div::callUserFunction($_funcRef,$_params,$this); 04647 } 04648 } 04649 } 04650 04656 function removeCacheFiles() { 04657 $cacheFiles=t3lib_extMgm::currentCacheFiles(); 04658 $out=0; 04659 if (is_array($cacheFiles)) { 04660 reset($cacheFiles); 04661 while(list(,$cfile)=each($cacheFiles)) { 04662 @unlink($cfile); 04663 clearstatcache(); 04664 $out++; 04665 } 04666 } 04667 04668 return $out; 04669 } 04670 } 04671 04672 04673 04674 04675 /* 04676 Log messages: 04677 [action]-[details_nr.] 04678 04679 REMEMBER to UPDATE the real messages set in tools/log/localconf_log.php 04680 04681 0-1: Referer host '%s' and server host '%s' did not match! 04682 1-11: Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed 04683 1-12: Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page. 04684 2-1: Attempt to modify table '%s' without permission 04685 2-2: Attempt to modify record '%s' (%s) without permission. Or non-existing page. 04686 2-10: Record '%s' (%s) was updated. 04687 2-12: SQL error: '%s' (%s) 04688 2-13: Write-file error: '%s' 04689 4-1: Attempt to move record '%s' (%s) to after a non-existing record (uid=%s) 04690 4-2: Moved record '%s' (%s) to page '%s' (%s) 04691 4-3: Moved record '%s' (%s) from page '%s' (%s) 04692 4-4: Moved record '%s' (%s) on page '%s' (%s) 04693 4-10: Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s)) 04694 4-11: Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed 04695 4-12: Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page. 04696 4-13: Attempt to move record '%s' (%s) to after another record, although the table has no sorting row. 04697 4-14: Attempt to move record '%s' (%s) without having permissions to do so 04698 5-1: You cannot change the 'doktype' of page '%s' to the desired value. 04699 5-2: 'doktype' of page '%s' could not be changed because the page contains records from disallowed tables; %s 04700 5-3: Too few items in the list of values. (%s) 04701 5-10: Could not delete file '%s' (does not exist). (%s) 04702 5-11: Copying file '%s' failed!: No destination file (%s) possible!. (%s) 04703 5-12: Fileextension '%' not allowed. (%s) 04704 5-13: Filesize (%s) of file '%s' exceeds limit (%s). (%s) 04705 5-14: The destination (%s) or the source file (%s) does not exist. (%s) 04706 5-15: Copying to file '%s' failed! (%s) 04707 5-16: Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s) 04708 04709 */ 04710 04711 04712 04713 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']) { 04714 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']); 04715 } 04716 ?>