[TASK] Remove t3lib_superadmin
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_tcemain.php
index 5a3a4d1..2367eef 100644 (file)
  *
  * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
-/**
- * [CLASS/FUNCTION INDEX of SCRIPT]
- *
- *
- *
- *  242: class t3lib_TCEmain
- *  367:        function start($data,$cmd,$altUserObject='')
- *  406:        function setMirror($mirror)
- *  431:        function setDefaultsFromUserTS($userTS)
- *  454:        function process_uploads($postFiles)
- *  492:        function process_uploads_traverseArray(&$outputArr,$inputArr,$keyToSet)
- *
- *                       SECTION: PROCESSING DATA
- *  528:        function process_datamap()
- *  886:        function placeholderShadowing($table,$id)
- *  929:        function fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$realPid,$status,$tscPID)
- *
- *                       SECTION: Evaluation of input values
- * 1152:        function checkValue($table,$field,$value,$id,$status,$realPid,$tscPID)
- * 1212:        function checkValue_SW($res,$value,$tcaFieldConf,$table,$id,$curValue,$status,$realPid,$recFID,$field,$uploadedFiles,$tscPID)
- * 1261:        function checkValue_input($res,$value,$tcaFieldConf,$PP,$field='')
- * 1299:        function checkValue_check($res,$value,$tcaFieldConf,$PP)
- * 1322:        function checkValue_radio($res,$value,$tcaFieldConf,$PP)
- * 1348:        function checkValue_group_select($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field)
- * 1458:        function checkValue_group_select_file($valueArray,$tcaFieldConf,$curValue,$uploadedFileArray,$status,$table,$id,$recFID)
- * 1632:        function checkValue_flex($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field)
- * 1709:        function checkValue_flexArray2Xml($array, $addPrologue=FALSE)
- * 1721:        function _DELETE_FLEX_FORMdata(&$valueArrayToRemoveFrom,$deleteCMDS)
- * 1743:        function _MOVE_FLEX_FORMdata(&$valueArrayToMoveIn, $moveCMDS, $direction)
- * 1783:        function checkValue_inline($res,$value,$tcaFieldConf,$PP,$field)
- * 1825:        function checkValue_checkMax($tcaFieldConf, $valueArray)
- *
- *                       SECTION: Helper functions for evaluation functions.
- * 1877:        function getUnique($table,$field,$value,$id,$newPid=0)
- * 1915:        function checkValue_input_Eval($value,$evalArray,$is_in)
- * 2012:        function checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,$type,$currentTable)
- * 2058:        function checkValue_group_select_explodeSelectGroupValue($value)
- * 2082:        function checkValue_flex_procInData($dataPart,$dataPart_current,$uploadedFiles,$dataStructArray,$pParams,$callBackFunc='')
- * 2121:        function checkValue_flex_procInData_travDS(&$dataValues,$dataValues_current,$uploadedFiles,$DSelements,$pParams,$callBackFunc,$structurePath)
- *
- *                       SECTION: PROCESSING COMMANDS
- * 2267:        function process_cmdmap()
- *
- *                       SECTION: Cmd: Copying
- * 2407:        function copyRecord($table,$uid,$destPid,$first=0,$overrideValues=array(),$excludeFields='')
- * 2529:        function copyPages($uid,$destPid)
- * 2583:        function copySpecificPage($uid,$destPid,$copyTablesArray,$first=0)
- * 2617:        function copyRecord_raw($table,$uid,$pid,$overrideArray=array())
- * 2681:        function rawCopyPageContent($old_pid,$new_pid,$copyTablesArray)
- * 2705:        function insertNewCopyVersion($table,$fieldArray,$realPid)
- * 2757:        function copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf,$realDestPid)
- * 2836:        function copyRecord_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2)
- * 2864:        function copyRecord_procFilesRefs($conf, $uid, $value)
- *
- *                       SECTION: Cmd: Moving, Localizing
- * 2933:        function moveRecord($table,$uid,$destPid)
- * 3128:        function moveRecord_procFields($table,$uid,$destPid)
- * 3148:        function moveRecord_procBasedOnFieldType($table,$uid,$destPid,$field,$value,$conf)
- * 3182:        function localize($table,$uid,$language)
- *
- *                       SECTION: Cmd: Deleting
- * 3296:        function deleteAction($table, $id)
- * 3343:        function deleteEl($table, $uid, $noRecordCheck=FALSE, $forceHardDelete=FALSE)
- * 3360:        function deleteVersionsForRecord($table, $uid, $forceHardDelete)
- * 3382:        function undeleteRecord($table,$uid)
- * 3399:        function deleteRecord($table,$uid, $noRecordCheck=FALSE, $forceHardDelete=FALSE,$undeleteRecord=FALSE)
- * 3512:        function deleteRecord_flexFormCallBack($dsArr, $dataValue, $PA, $structurePath, &$pObj)
- * 3539:        function deletePages($uid,$force=FALSE,$forceHardDelete=FALSE)
- * 3567:        function deleteSpecificPage($uid,$forceHardDelete=FALSE)
- * 3592:        function canDeletePage($uid)
- * 3619:        function cannotDeleteRecord($table,$id)
- * 3638:        function deleteRecord_procFields($table, $uid, $undeleteRecord = FALSE)
- * 3661:        function deleteRecord_procBasedOnFieldType($table, $uid, $field, $value, $conf, $undeleteRecord = FALSE)
- *
- *                       SECTION: Cmd: Versioning
- * 3722:        function versionizeRecord($table,$id,$label,$delete=FALSE,$versionizeTree=-1)
- * 3798:        function versionizePages($uid,$label,$versionizeTree)
- * 3861:        function version_swap($table,$id,$swapWith,$swapIntoWS=0)
- * 4032:        function version_clearWSID($table,$id)
- * 4066:        function version_setStage($table,$id,$stageId,$comment='')
- *
- *                       SECTION: Cmd: Helper functions
- * 4111:        function remapListedDBRecords()
- * 4192:        function remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2)
- * 4219:        function remapListedDBRecords_procDBRefs($conf, $value, $MM_localUid, $table)
- * 4265:        function remapListedDBRecords_procInline($conf, $value, $uid, $table)
- *
- *                       SECTION: Access control / Checking functions
- * 4308:        function checkModifyAccessList($table)
- * 4320:        function isRecordInWebMount($table,$id)
- * 4334:        function isInWebMount($pid)
- * 4348:        function checkRecordUpdateAccess($table,$id)
- * 4372:        function checkRecordInsertAccess($insertTable,$pid,$action=1)
- * 4406:        function isTableAllowedForThisPage($page_uid, $checkTable)
- * 4439:        function doesRecordExist($table,$id,$perms)
- * 4504:        function doesRecordExist_pageLookUp($id, $perms)
- * 4530:        function doesBranchExist($inList,$pid,$perms,$recurse)
- * 4564:        function tableReadOnly($table)
- * 4576:        function tableAdminOnly($table)
- * 4590:        function destNotInsideSelf($dest,$id)
- * 4622:        function getExcludeListArray()
- * 4645:        function doesPageHaveUnallowedTables($page_uid,$doktype)
- *
- *                       SECTION: Information lookup
- * 4694:        function pageInfo($id,$field)
- * 4714:        function recordInfo($table,$id,$fieldList)
- * 4735:        function getRecordProperties($table,$id,$noWSOL=FALSE)
- * 4751:        function getRecordPropertiesFromRow($table,$row)
- *
- *                       SECTION: Storing data to Database Layer
- * 4794:        function updateDB($table,$id,$fieldArray)
- * 4846:        function insertDB($table,$id,$fieldArray,$newVersion=FALSE,$suggestedUid=0,$dontSetNewIdIndex=FALSE)
- * 4919:        function checkStoredRecord($table,$id,$fieldArray,$action)
- * 4956:        function setHistory($table,$id,$logId)
- * 4989:        function clearHistory($maxAgeSeconds=604800,$table)
- * 5003:        function updateRefIndex($table,$id)
- *
- *                       SECTION: Misc functions
- * 5035:        function getSortNumber($table,$uid,$pid)
- * 5108:        function resorting($table,$pid,$sortRow, $return_SortNumber_After_This_Uid)
- * 5139:        function setTSconfigPermissions($fieldArray,$TSConfig_p)
- * 5156:        function newFieldArray($table)
- * 5188:        function addDefaultPermittedLanguageIfNotSet($table,&$incomingFieldArray)
- * 5212:        function overrideFieldArray($table,$data)
- * 5228:        function compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray)
- * 5274:        function assemblePermissions($string)
- * 5291:        function rmComma($input)
- * 5301:        function convNumEntityToByteValue($input)
- * 5323:        function destPathFromUploadFolder($folder)
- * 5333:        function deleteClause($table)
- * 5349:        function getTCEMAIN_TSconfig($tscPID)
- * 5364:        function getTableEntries($table,$TSconfig)
- * 5377:        function getPID($table,$uid)
- * 5390:        function dbAnalysisStoreExec()
- * 5406:        function removeRegisteredFiles()
- * 5418:        function removeCacheFiles()
- * 5432:        function int_pageTreeInfo($CPtable,$pid,$counter, $rootID)
- * 5453:        function compileAdminTables()
- * 5470:        function fixUniqueInPid($table,$uid)
- * 5506:        function fixCopyAfterDuplFields($table,$uid,$prevUid,$update, $newData=array())
- * 5531:        function extFileFields($table)
- * 5552:        function getUniqueFields($table)
- * 5577:        function isReferenceField($conf)
- * 5588:        function getInlineFieldType($conf)
- * 5611:        function getCopyHeader($table,$pid,$field,$value,$count,$prevTitle='')
- * 5640:        function prependLabel($table)
- * 5657:        function resolvePid($table,$pid)
- * 5687:        function clearPrefixFromValue($table,$value)
- * 5702:        function extFileFunctions($table,$field,$filelist,$func)
- * 5732:        function noRecordsFromUnallowedTables($inList)
- * 5758:        function notifyStageChange($stat,$stageId,$table,$id,$comment)
- * 5853:        function notifyStageChange_getEmails($listOfUsers,$noTablePrefix=FALSE)
- *
- *                       SECTION: Clearing cache
- * 5899:        function clear_cache($table,$uid)
- * 6009:        function clear_cacheCmd($cacheCmd)
- *
- *                       SECTION: Logging
- * 6113:        function log($table,$recuid,$action,$recpid,$error,$details,$details_nr=-1,$data=array(),$event_pid=-1,$NEWid='')
- * 6130:        function newlog($message, $error=0)
- * 6140:        function printLogErrorMessages($redirect)
- *
- *                       SECTION: Internal (do not use outside Core!)
- * 6202:        function internal_clearPageCache()
- *
- * TOTAL FUNCTIONS: 126
- * (This index is automatically created/updated by the extension "extdeveval")
- *
- */
 
 
 /**
@@ -283,7 +114,7 @@ class t3lib_TCEmain {
        var $username; // will be set to username of be_user executing this script
        var $admin; // will be set if user is admin
 
-       var $defaultPermissions = array( // Can be overridden from $TYPO3_CONF_VARS
+       var $defaultPermissions = array( // Can be overridden from $GLOBALS['TYPO3_CONF_VARS']
                'user' => 'show,edit,delete,new,editcontent',
                'group' => 'show,edit,new,editcontent',
                'everybody' => ''
@@ -645,7 +476,7 @@ class t3lib_TCEmain {
                                                $old_pid_value = '';
                                                $this->autoVersioningUpdate = FALSE;
 
-                                               if (!t3lib_div::testInt($id)) { // Is it a new record? (Then Id is a string)
+                                               if (!t3lib_utility_Math::canBeInterpretedAsInteger($id)) { // Is it a new record? (Then Id is a string)
                                                        $fieldArray = $this->newFieldArray($table); // Get a fieldArray with default values
                                                        if (isset($incomingFieldArray['pid'])) { // A pid must be set for new records.
                                                                        // $value = the pid
@@ -862,6 +693,7 @@ class t3lib_TCEmain {
                                                                        $newVersion_placeholderFieldArray[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
                                                                }
                                                        }
+                                                               // Set stage to "Editing" to make sure we restart the workflow
                                                        if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
                                                                $fieldArray['t3ver_stage'] = 0;
                                                        }
@@ -880,7 +712,7 @@ class t3lib_TCEmain {
                                                                        if ($createNewVersion) { // This creates a new version of the record with online placeholder and offline version
                                                                                $versioningType = ($table === 'pages'
                                                                                        ? $this->BE_USER->workspaceVersioningTypeGetClosest(
-                                                                                               t3lib_div::intInRange($GLOBALS['TYPO3_CONF_VARS']['BE']['newPagesVersioningType'], -1, 1))
+                                                                                               t3lib_utility_Math::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['BE']['newPagesVersioningType'], -1, 1))
                                                                                        : -1);
                                                                                if ($this->BE_USER->workspaceVersioningTypeAccess($versioningType)) {
                                                                                        $newVersion_placeholderFieldArray['t3ver_label'] = 'INITIAL PLACEHOLDER';
@@ -1988,7 +1820,7 @@ class t3lib_TCEmain {
                        // Example for received data:
                        // $value = 45,NEW4555fdf59d154,12,123
                        // We need to decide whether we use the stack or can save the relation directly.
-               if (strpos($value, 'NEW') !== FALSE || !t3lib_div::testInt($id)) {
+               if (strpos($value, 'NEW') !== FALSE || !t3lib_utility_Math::canBeInterpretedAsInteger($id)) {
                        $this->remapStackRecords[$table][$id] = array('remapStackIndex' => count($this->remapStack));
                        $this->addNewValuesToRemapStackChildIds($valueArray);
                        $this->remapStack[] = array(
@@ -1998,7 +1830,7 @@ class t3lib_TCEmain {
                                'field' => $field
                        );
                        unset($res['value']);
-               } elseif ($value || t3lib_div::testInt($id)) {
+               } elseif ($value || t3lib_utility_Math::canBeInterpretedAsInteger($id)) {
                        $res['value'] = $this->checkValue_inline_processDBdata($valueArray, $tcaFieldConf, $id, $status, $table, $field);
                }
 
@@ -2210,6 +2042,15 @@ class t3lib_TCEmain {
                                case 'alphanum_x':
                                        $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
                                break;
+                               case 'domainname':
+                                       if (!preg_match('/^[a-z0-9\.\-]*$/i', $value)) {
+                                               t3lib_div::requireOnce(PATH_typo3 . 'contrib/idna/idna_convert.class.php');
+                                               $idnaConvert = new idna_convert();
+                                               $idnaConvert->set_parameter('idn_version', '2008');
+                                               $value = $idnaConvert->encode($value);
+                                               unset($idnaConvert);
+                                       }
+                               break;
                                default:
                                        if (t3lib_div::hasValidClassPrefix($func)) {
                                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
@@ -2701,6 +2542,9 @@ class t3lib_TCEmain {
                        }
                }
 
+               if ($this->isOuterMostInstance()) {
+                       $this->resetNestedElementCalls();
+               }
        }
 
 
@@ -3101,37 +2945,60 @@ class t3lib_TCEmain {
                $value = $this->copyRecord_procFilesRefs($conf, $uid, $value);
                $inlineSubType = $this->getInlineFieldType($conf);
 
+                       // Get the localization mode for the current (parent) record (keep|select):
+               $localizationMode = t3lib_BEfunc::getInlineLocalizationMode($table, $field);
+
                        // Register if there are references to take care of or MM is used on an inline field (no change to value):
                if ($this->isReferenceField($conf) || $inlineSubType == 'mm') {
                        $allowedTables = $conf['type'] == 'group' ? $conf['allowed'] : $conf['foreign_table'] . ',' . $conf['neg_foreign_table'];
                        $prependName = $conf['type'] == 'group' ? $conf['prepend_tname'] : $conf['neg_foreign_table'];
-                       $localizeReferences = (isset($conf['foreign_table']) && t3lib_BEfunc::isTableLocalizable($conf['foreign_table']) && isset($conf['localizeReferencesAtParentLocalization']) && $conf['localizeReferencesAtParentLocalization']);
-                       if ($conf['MM'] || $language > 0 && $localizeReferences) {
-                               $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
-                               /** @var $dbAnalysis t3lib_loadDBGroup */
-                               $dbAnalysis->start($value, $allowedTables, $conf['MM'], $uid, $table, $conf);
-                               if (!$conf['MM']) {
-                                               // Localize referenced records of select fields:
-                                       foreach ($dbAnalysis->itemArray as $index => $item) {
-                                                       // Since select fields can reference many records, check whether there's already a localization:
-                                               $recordLocalization = t3lib_BEfunc::getRecordLocalization($item['table'], $item['id'], $language);
-                                               if (!$recordLocalization) {
-                                                       $dbAnalysis->itemArray[$index]['id'] = $this->localize($item['table'], $item['id'], $language);
-                                               } else {
-                                                       $dbAnalysis->itemArray[$index]['id'] = $recordLocalization[0]['uid'];
-                                               }
+
+                       $mmTable = (isset($conf['MM']) && $conf['MM'] ? $conf['MM'] : '');
+                       $localizeForeignTable = (isset($conf['foreign_table']) && t3lib_BEfunc::isTableLocalizable($conf['foreign_table']));
+                       $localizeReferences = ($localizeForeignTable && isset($conf['localizeReferencesAtParentLocalization']) && $conf['localizeReferencesAtParentLocalization']);
+                       $localizeChildren = ($localizeForeignTable && isset($conf['behaviour']['localizeChildrenAtParentLocalization']) && $conf['behaviour']['localizeChildrenAtParentLocalization']);
+
+                       /** @var $dbAnalysis t3lib_loadDBGroup */
+                       $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
+                       $dbAnalysis->start($value, $allowedTables, $mmTable, $uid, $table, $conf);
+
+                               // Localize referenced records of select fields:
+                       if ($language > 0 && ($localizeReferences && empty($mmTable) || $localizeChildren && $localizationMode === 'select' && $inlineSubType === 'mm')) {
+                               foreach ($dbAnalysis->itemArray as $index => $item) {
+                                               // Since select fields can reference many records, check whether there's already a localization:
+                                       $recordLocalization = t3lib_BEfunc::getRecordLocalization($item['table'], $item['id'], $language);
+                                       if ($recordLocalization) {
+                                               $dbAnalysis->itemArray[$index]['id'] = $recordLocalization[0]['uid'];
+                                       } elseif ($this->isNestedElementCallRegistered($item['table'], $item['id'], 'localize') === FALSE) {
+                                               $dbAnalysis->itemArray[$index]['id'] = $this->localize($item['table'], $item['id'], $language);
                                        }
                                }
                                $value = implode(',', $dbAnalysis->getValueArray($prependName));
+
+                               // If IRRE MM references are not followed on localization, use at least the existing ones:
+                       } elseif ($language > 0 && $localizeChildren === FALSE && $localizationMode === 'select' && $inlineSubType === 'mm') {
+                               foreach ($dbAnalysis->itemArray as $index => $item) {
+                                               // Since select fields can reference many records, check whether there's already a localization:
+                                       $recordLocalization = t3lib_BEfunc::getRecordLocalization($item['table'], $item['id'], $language);
+                                       if ($recordLocalization) {
+                                               $dbAnalysis->itemArray[$index]['id'] = $recordLocalization[0]['uid'];
+                                       } elseif ($this->isNestedElementCallRegistered($item['table'], $item['id'], 'localize') === FALSE) {
+                                               unset($dbAnalysis->itemArray[$index]);
+                                       }
+                               }
+                               $value = implode(',', $dbAnalysis->getValueArray($prependName));
+
+                               // Just ensure that the references are correct by using the existing ones:
+                       } elseif ($mmTable) {
+                               $value = implode(',', $dbAnalysis->getValueArray($prependName));
                        }
+
                        if ($value) { // Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected
                                $this->registerDBList[$table][$uid][$field] = $value;
                        }
 
                        // If another inline subtype is used (comma-separated-values or the foreign_field property):
                } elseif ($inlineSubType !== FALSE) {
-                               // Get the localization mode for the current (parent) record (keep|select|all):
-                       $localizationMode = t3lib_BEfunc::getInlineLocalizationMode($table, $field);
                                // Localization in mode 'keep', isn't a real localization, but keeps the children of the original parent record:
                        if ($language > 0 && $localizationMode == 'keep') {
                                $value = ($inlineSubType == 'field' ? 0 : '');
@@ -3155,7 +3022,7 @@ class t3lib_TCEmain {
                                                }
                                                        // If no language it set, this is a regular copy action:
                                        } else {
-                                               if (!t3lib_div::testInt($realDestPid)) {
+                                               if (!t3lib_utility_Math::canBeInterpretedAsInteger($realDestPid)) {
                                                        $newId = $this->copyRecord($v['table'], $v['id'], -$v['id']);
                                                } elseif ($realDestPid == -1 && t3lib_BEfunc::isTableWorkspaceEnabled($v['table'])) {
                                                        $workspaceVersion = t3lib_BEfunc::getWorkspaceVersionOfRecord(
@@ -3312,8 +3179,6 @@ class t3lib_TCEmain {
         * @return      void
         */
        function copyRecord_fixRTEmagicImages($table, $theNewSQLID) {
-               global $TYPO3_DB;
-
                        // Creating fileFunc object.
                if (!$this->fileFunc) {
                        $this->fileFunc = t3lib_div::makeInstance('t3lib_basicFileFunctions');
@@ -3321,14 +3186,13 @@ class t3lib_TCEmain {
                }
 
                        // Select all RTEmagic files in the reference table from the table/ID
-               /* @var $TYPO3_DB t3lib_DB */
-               $recs = $TYPO3_DB->exec_SELECTgetRows(
+               $recs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
                        '*',
                        'sys_refindex',
-                       'ref_table=' . $TYPO3_DB->fullQuoteStr('_FILE', 'sys_refindex') .
-                       ' AND ref_string LIKE ' . $TYPO3_DB->fullQuoteStr('%/RTEmagic%', 'sys_refindex') .
-                       ' AND softref_key=' . $TYPO3_DB->fullQuoteStr('images', 'sys_refindex') .
-                       ' AND tablename=' . $TYPO3_DB->fullQuoteStr($table, 'sys_refindex') .
+                       'ref_table=' . $GLOBALS['TYPO3_DB']->fullQuoteStr('_FILE', 'sys_refindex') .
+                       ' AND ref_string LIKE ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('%/RTEmagic%', 'sys_refindex') .
+                       ' AND softref_key=' . $GLOBALS['TYPO3_DB']->fullQuoteStr('images', 'sys_refindex') .
+                       ' AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_refindex') .
                        ' AND recuid=' . intval($theNewSQLID),
                        '',
                        'sorting DESC'
@@ -3447,7 +3311,7 @@ class t3lib_TCEmain {
                                // In case the record to be moved turns out to be an offline version,
                                // we have to find the live version and work on that one (this case
                                // happens for pages with "branch" versioning type)
-                               // note: as "branch" versioning is deprecated since TYPO3 4.2, this
+                               // @deprecated note: as "branch" versioning is deprecated since TYPO3 4.2, this
                                // functionality will be removed in TYPO3 4.7 (note by benni: a hook could replace this)
                        if ($lookForLiveVersion = t3lib_BEfunc::getLiveVersionOfRecord($table, $uid, 'uid')) {
                                $uid = $lookForLiveVersion['uid'];
@@ -3759,7 +3623,8 @@ class t3lib_TCEmain {
                $newId = FALSE;
                $uid = intval($uid);
 
-               if ($GLOBALS['TCA'][$table] && $uid) {
+               if ($GLOBALS['TCA'][$table] && $uid && $this->isNestedElementCallRegistered($table, $uid, 'localize') === FALSE) {
+                       $this->registerNestedElementCall($table, $uid, 'localize');
                        t3lib_div::loadTCA($table);
 
                        if (($GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
@@ -3890,7 +3755,7 @@ class t3lib_TCEmain {
                $field = $parts[0];
                $type = $parts[1];
 
-               if ($field && (t3lib_div::inList('localize,synchronize', $type) || t3lib_div::testInt($type)) && isset($GLOBALS['TCA'][$table]['columns'][$field]['config'])) {
+               if ($field && (t3lib_div::inList('localize,synchronize', $type) || t3lib_utility_Math::canBeInterpretedAsInteger($type)) && isset($GLOBALS['TCA'][$table]['columns'][$field]['config'])) {
                        $config = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
                        $foreignTable = $config['foreign_table'];
                        $localizationMode = t3lib_BEfunc::getInlineLocalizationMode($table, $config);
@@ -3907,19 +3772,20 @@ class t3lib_TCEmain {
 
                                        if ($inlineSubType !== FALSE) {
                                                $removeArray = array();
+                                               $mmTable = ($inlineSubType == 'mm' && isset($config['MM']) && $config['MM'] ? $config['MM'] : '');
                                                        // Fetch children from original language parent:
                                                /** @var $dbAnalysisOriginal t3lib_loadDBGroup */
                                                $dbAnalysisOriginal = t3lib_div::makeInstance('t3lib_loadDBGroup');
-                                               $dbAnalysisOriginal->start($transOrigRecord[$field], $foreignTable, '', $transOrigRecord['uid'], $table, $config);
+                                               $dbAnalysisOriginal->start($transOrigRecord[$field], $foreignTable, $mmTable, $transOrigRecord['uid'], $table, $config);
                                                $elementsOriginal = array();
                                                foreach ($dbAnalysisOriginal->itemArray as $item) {
                                                        $elementsOriginal[$item['id']] = $item;
                                                }
                                                unset($dbAnalysisOriginal);
                                                        // Fetch children from current localized parent:
-                                                       // @var $dbAnalysisCurrent t3lib_loadDBGroup
+                                               /** @var $dbAnalysisCurrent t3lib_loadDBGroup */
                                                $dbAnalysisCurrent = t3lib_div::makeInstance('t3lib_loadDBGroup');
-                                               $dbAnalysisCurrent->start($parentRecord[$field], $foreignTable, '', $id, $table, $config);
+                                               $dbAnalysisCurrent->start($parentRecord[$field], $foreignTable, $mmTable, $id, $table, $config);
                                                        // Perform synchronization: Possibly removal of already localized records:
                                                if ($type == 'synchronize') {
                                                        foreach ($dbAnalysisCurrent->itemArray as $index => $item) {
@@ -3935,7 +3801,7 @@ class t3lib_TCEmain {
                                                        }
                                                }
                                                        // Perform synchronization/localization: Possibly add unlocalized records for original language:
-                                               if (t3lib_div::testInt($type) && isset($elementsOriginal[$type])) {
+                                               if (t3lib_utility_Math::canBeInterpretedAsInteger($type) && isset($elementsOriginal[$type])) {
                                                        $item = $elementsOriginal[$type];
                                                        $item['id'] = $this->localize($item['table'], $item['id'], $language);
                                                        $item['id'] = $this->overlayAutoVersionId($item['table'], $item['id']);
@@ -3964,6 +3830,9 @@ class t3lib_TCEmain {
                                                } elseif ($inlineSubType == 'field') {
                                                        $dbAnalysisCurrent->writeForeignField($config, $id);
                                                        $updateFields = array($field => $dbAnalysisCurrent->countItems(FALSE));
+                                               } elseif ($inlineSubType == 'mm') {
+                                                       $dbAnalysisCurrent->writeMM($config['MM'], $id);
+                                                       $updateFields = array($field => $dbAnalysisCurrent->countItems(FALSE));
                                                }
                                                        // Update field referencing to child records of localized parent record:
                                                if (is_array($updateFields) && count($updateFields)) {
@@ -3990,16 +3859,14 @@ class t3lib_TCEmain {
         * @return      void
         */
        function deleteAction($table, $id) {
-               global $TYPO3_CONF_VARS;
-
                $recordToDelete = t3lib_BEfunc::getRecord($table, $id);
 
                        // Record asked to be deleted was found:
                if (is_array($recordToDelete)) {
                        $recordWasDeleted = FALSE;
 
-                       if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'])) {
-                               foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'] as $classRef) {
+                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'])) {
+                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'] as $classRef) {
                                        $hookObj = t3lib_div::getUserObj($classRef);
                                        if (method_exists($hookObj, 'processCmdmap_deleteAction')) {
                                                $hookObj->processCmdmap_deleteAction($table, $id, $recordToDelete, $recordWasDeleted, $this);
@@ -5297,7 +5164,7 @@ class t3lib_TCEmain {
                $id = intval($id);
 
                        // Processing the incoming $perms (from possible string to integer that can be AND'ed)
-               if (!t3lib_div::testInt($perms)) {
+               if (!t3lib_utility_Math::canBeInterpretedAsInteger($perms)) {
                        if ($table != 'pages') {
                                switch ($perms) {
                                        case 'edit':
@@ -5493,14 +5360,12 @@ class t3lib_TCEmain {
         * @return      array           Returns a list of the tables that are 'present' on the page but not allowed with the page_uid/doktype
         */
        function doesPageHaveUnallowedTables($page_uid, $doktype) {
-               global $PAGES_TYPES;
-
                $page_uid = intval($page_uid);
                if (!$page_uid) {
                        return FALSE; // Not a number. Probably a new page
                }
 
-               $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables'];
+               $allowedTableList = isset($GLOBALS['PAGES_TYPES'][$doktype]['allowedTables']) ? $GLOBALS['PAGES_TYPES'][$doktype]['allowedTables'] : $GLOBALS['PAGES_TYPES']['default']['allowedTables'];
                $allowedArray = t3lib_div::trimExplode(',', $allowedTableList, 1);
                if (strstr($allowedTableList, '*')) { // If all tables is OK the return TRUE
                        return FALSE; // OK...
@@ -5797,7 +5662,7 @@ class t3lib_TCEmain {
                        $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
 
                        $tE = $this->getTableEntries($table, $TSConfig);
-                       $maxAgeSeconds = 60 * 60 * 24 * (strcmp($tE['history.']['maxAgeDays'], '') ? t3lib_div::intInRange($tE['history.']['maxAgeDays'], 0, 365) : 30); // one month
+                       $maxAgeSeconds = 60 * 60 * 24 * (strcmp($tE['history.']['maxAgeDays'], '') ? t3lib_utility_Math::forceIntegerInRange($tE['history.']['maxAgeDays'], 0, 365) : 30); // one month
 
                                // Garbage collect old entries:
                        $this->clearHistory($maxAgeSeconds, $table);
@@ -5972,13 +5837,13 @@ class t3lib_TCEmain {
                        $fieldArray['perms_groupid'] = intval($TSConfig_p['groupid']);
                }
                if (strcmp($TSConfig_p['user'], '')) {
-                       $fieldArray['perms_user'] = t3lib_div::testInt($TSConfig_p['user']) ? $TSConfig_p['user'] : $this->assemblePermissions($TSConfig_p['user']);
+                       $fieldArray['perms_user'] = t3lib_utility_Math::canBeInterpretedAsInteger($TSConfig_p['user']) ? $TSConfig_p['user'] : $this->assemblePermissions($TSConfig_p['user']);
                }
                if (strcmp($TSConfig_p['group'], '')) {
-                       $fieldArray['perms_group'] = t3lib_div::testInt($TSConfig_p['group']) ? $TSConfig_p['group'] : $this->assemblePermissions($TSConfig_p['group']);
+                       $fieldArray['perms_group'] = t3lib_utility_Math::canBeInterpretedAsInteger($TSConfig_p['group']) ? $TSConfig_p['group'] : $this->assemblePermissions($TSConfig_p['group']);
                }
                if (strcmp($TSConfig_p['everybody'], '')) {
-                       $fieldArray['perms_everybody'] = t3lib_div::testInt($TSConfig_p['everybody']) ? $TSConfig_p['everybody'] : $this->assemblePermissions($TSConfig_p['everybody']);
+                       $fieldArray['perms_everybody'] = t3lib_utility_Math::canBeInterpretedAsInteger($TSConfig_p['everybody']) ? $TSConfig_p['everybody'] : $this->assemblePermissions($TSConfig_p['everybody']);
                }
 
                return $fieldArray;
@@ -6251,7 +6116,7 @@ class t3lib_TCEmain {
                foreach ($this->dbAnalysisStore as $action) {
                        $id = t3lib_BEfunc::wsMapId(
                                $action[4],
-                               (t3lib_div::testInt($action[2]) ? $action[2] : $this->substNEWwithIDs[$action[2]])
+                               (t3lib_utility_Math::canBeInterpretedAsInteger($action[2]) ? $action[2] : $this->substNEWwithIDs[$action[2]])
                        );
                        if ($id) {
                                $action[0]->writeMM($action[1], $id, $action[3]);
@@ -6434,20 +6299,20 @@ class t3lib_TCEmain {
         * @return      mixed           string: inline subtype (field|mm|list), boolean: FALSE
         */
        function getInlineFieldType($conf) {
-               if ($conf['type'] == 'inline' && $conf['foreign_table']) {
-                       if ($conf['foreign_field']) {
-                               return 'field';
-                       } // the reference to the parent is stored in a pointer field in the child record
-                       elseif ($conf['MM'])
-                       {
-                               return 'mm';
-                       } // regular MM intermediate table is used to store data
-                       else
-                       {
-                               return 'list';
-                       } // an item list (separated by comma) is stored (like select type is doing)
+               if ($conf['type'] !== 'inline' || !$conf['foreign_table']) {
+                       return FALSE;
+               }
+
+               if ($conf['foreign_field']) {
+                               // the reference to the parent is stored in a pointer field in the child record
+                       return 'field';
+               } elseif ($conf['MM']) {
+                               // regular MM intermediate table is used to store data
+                       return 'mm';
+               } else {
+                               // an item list (separated by comma) is stored (like select type is doing)
+                       return 'list';
                }
-               return FALSE;
        }
 
 
@@ -6762,7 +6627,7 @@ class t3lib_TCEmain {
         * (an integer).
         *
         * Can call a list of post processing functions as defined in
-        * $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']
+        * $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']
         * (numeric array with values being the function references, called by
         * t3lib_div::callUserFunction()).
         *
@@ -6782,8 +6647,6 @@ class t3lib_TCEmain {
         * @return      void
         */
        public function clear_cacheCmd($cacheCmd) {
-               global $TYPO3_CONF_VARS;
-
                $this->BE_USER->writelog(3, 1, 0, 0, 'User %s has cleared the cache (cacheCmd=%s)', array($this->BE_USER->user['username'], $cacheCmd));
 
                        // Clear cache for either ALL pages or ALL tables!
@@ -6795,19 +6658,16 @@ class t3lib_TCEmain {
                        break;
                        case 'all':
                                if ($this->admin || $this->BE_USER->getTSConfigVal('options.clearCache.all')) {
-
                                                // Clear all caching framework caches
-                                       if (t3lib_cache::isCachingFrameworkInitialized()) {
-                                               $GLOBALS['typo3CacheManager']->flushCaches();
-                                       }
+                                       $GLOBALS['typo3CacheManager']->flushCaches();
 
                                        if (t3lib_extMgm::isLoaded('cms')) {
                                                $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_treelist');
                                        }
 
                                                // Clearing additional cache tables:
-                                       if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'])) {
-                                               foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'] as $tableName) {
+                                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'])) {
+                                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'] as $tableName) {
                                                        if (!preg_match('/[^[:alnum:]_]/', $tableName) && substr($tableName, -5) == 'cache') {
                                                                $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($tableName);
                                                        } else {
@@ -6819,26 +6679,26 @@ class t3lib_TCEmain {
                                                }
                                        }
                                }
-                               if ($this->admin && $TYPO3_CONF_VARS['EXT']['extCache']) {
+                               if ($this->admin && $GLOBALS['TYPO3_CONF_VARS']['EXT']['extCache']) {
                                        $this->removeCacheFiles();
                                }
                        break;
                        case 'temp_CACHED':
-                               if ($this->admin && $TYPO3_CONF_VARS['EXT']['extCache']) {
+                               if ($this->admin && $GLOBALS['TYPO3_CONF_VARS']['EXT']['extCache']) {
                                        $this->removeCacheFiles();
                                }
                        break;
                }
 
                        // Clear cache for a page ID!
-               if (t3lib_div::testInt($cacheCmd)) {
+               if (t3lib_utility_Math::canBeInterpretedAsInteger($cacheCmd)) {
                        if (t3lib_extMgm::isLoaded('cms')) {
 
                                $list_cache = array($cacheCmd);
 
                                        // Call pre-processing function for clearing of cache for page ids:
-                               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearPageCacheEval'])) {
-                                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearPageCacheEval'] as $funcName) {
+                               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearPageCacheEval'])) {
+                                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearPageCacheEval'] as $funcName) {
                                                $_params = array('pageIdArray' => &$list_cache, 'cacheCmd' => $cacheCmd, 'functionID' => 'clear_cacheCmd()');
                                                        // Returns the array of ids to clear, FALSE if nothing should be cleared! Never an empty array!
                                                t3lib_div::callUserFunction($funcName, $_params, $this);
@@ -6864,9 +6724,9 @@ class t3lib_TCEmain {
                }
 
                        // Call post processing function for clear-cache:
-               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'])) {
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'])) {
                        $_params = array('cacheCmd' => $cacheCmd);
-                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) {
                                t3lib_div::callUserFunction($_funcRef, $_params, $this);
                        }
                }
@@ -6957,7 +6817,7 @@ class t3lib_TCEmain {
                        $log_data = unserialize($row['log_data']);
                        $msg = $row['error'] . ': ' . sprintf($row['details'], $log_data[0], $log_data[1], $log_data[2], $log_data[3], $log_data[4]);
                        $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage',
-                                                                                                       $msg,
+                                                                                                       htmlspecialchars($msg),
                                                                                                        '',
                                                                                                        t3lib_FlashMessage::ERROR,
                                                                                                        TRUE
@@ -7000,7 +6860,7 @@ class t3lib_TCEmain {
                        switch ($GLOBALS['TCA'][$table]['columns'][$field]['config']['type']) {
                                case 'inline':
                                        if ($GLOBALS['TCA'][$table]['columns'][$field]['config']['foreign_field']) {
-                                               if (!t3lib_div::testInt($value)) {
+                                               if (!t3lib_utility_Math::canBeInterpretedAsInteger($value)) {
                                                        $result[$field] = count(t3lib_div::trimExplode(',', $value, TRUE));
                                                }
                                        }
@@ -7097,18 +6957,47 @@ class t3lib_TCEmain {
         * @return t3lib_cache_frontend_VariableFrontend
         */
        protected function getMemoryCache() {
-               t3lib_cache::initializeCachingFramework();
-               $cacheIdentifier = 't3lib_TCEmain';
-
-               if ($GLOBALS['typo3CacheManager']->hasCache($cacheIdentifier) === FALSE) {
-                       $GLOBALS['typo3CacheFactory']->create(
-                               $cacheIdentifier,
-                               't3lib_cache_frontend_VariableFrontend',
-                               't3lib_cache_backend_TransientMemoryBackend'
-                       );
-               }
+               return $GLOBALS['typo3CacheManager']->getCache('cache_runtime');
+       }
+
+       /**
+        * Determines nested element calls.
+        *
+        * @param string $table Name of the table
+        * @param integer $id Uid of the record
+        * @param string $identifier Name of the action to be checked
+        * @return boolean
+        */
+       protected function isNestedElementCallRegistered($table, $id, $identifier) {
+               $nestedElementCalls = (array) $this->getMemoryCache()->get('nestedElementCalls');
+               return isset($nestedElementCalls[$identifier][$table][$id]);
+       }
+
+       /**
+        * Registers nested elements calls.
+        * This is used to track nested calls (e.g. for following m:n relations).
+        *
+        * @param string $table Name of the table
+        * @param integer $id Uid of the record
+        * @param string $identifier Name of the action to be tracked
+        * @return void
+        */
+       protected function registerNestedElementCall($table, $id, $identifier) {
+               $nestedElementCalls = (array) $this->getMemoryCache()->get('nestedElementCalls');
+               $nestedElementCalls[$identifier][$table][$id] = TRUE;
+               $this->getMemoryCache()->set(
+                       'nestedElementCalls',
+                       $nestedElementCalls
+               );
+       }
 
-               return $GLOBALS['typo3CacheManager']->getCache($cacheIdentifier);
+       /**
+        * Resets the nested element calls.
+        *
+        * @return void
+        */
+       protected function resetNestedElementCalls() {
+               $this->getMemoryCache()->remove('nestedElementCalls');
        }
 
        /**
@@ -7123,7 +7012,7 @@ class t3lib_TCEmain {
         * @see versionizeRecord
         */
        protected function isElementToBeDeleted($table, $id) {
-               $elementsToBeDeleted = (array) $this->getMemoryCache()->get('elementsToBeDeleted');
+               $elementsToBeDeleted = (array) $this->getMemoryCache()->get('core-t3lib_TCEmain-elementsToBeDeleted');
                return (isset($elementsToBeDeleted[$table][$id]));
        }
 
@@ -7134,9 +7023,9 @@ class t3lib_TCEmain {
         * @see process_datamap
         */
        protected function registerElementsToBeDeleted() {
-               $elementsToBeDeleted = (array) $this->getMemoryCache()->get('elementsToBeDeleted');
+               $elementsToBeDeleted = (array) $this->getMemoryCache()->get('core-t3lib_TCEmain-elementsToBeDeleted');
                $this->getMemoryCache()->set(
-                       'elementsToBeDeleted',
+                       'core-t3lib_TCEmain-elementsToBeDeleted',
                        array_merge($elementsToBeDeleted, $this->getCommandMapElements('delete'))
                );
        }
@@ -7148,7 +7037,7 @@ class t3lib_TCEmain {
         * @see process_datamap
         */
        protected function resetElementsToBeDeleted() {
-               $this->getMemoryCache()->remove('elementsToBeDeleted');
+               $this->getMemoryCache()->remove('core-t3lib_TCEmain-elementsToBeDeleted');
        }
 
        /**