[TASK] Remove t3lib_superadmin
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_tcemain.php
index bfe1df1..2367eef 100644 (file)
@@ -476,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
@@ -693,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;
                                                        }
@@ -711,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';
@@ -1819,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(
@@ -1829,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);
                }
 
@@ -2041,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);
@@ -2532,6 +2542,9 @@ class t3lib_TCEmain {
                        }
                }
 
+               if ($this->isOuterMostInstance()) {
+                       $this->resetNestedElementCalls();
+               }
        }
 
 
@@ -2932,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 : '');
@@ -2986,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(
@@ -3275,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'];
@@ -3587,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']
@@ -3718,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);
@@ -3735,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) {
@@ -3763,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']);
@@ -3792,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)) {
@@ -5123,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':
@@ -5621,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);
@@ -5796,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;
@@ -6075,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]);
@@ -6258,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;
        }
 
 
@@ -6617,11 +6658,8 @@ 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');
@@ -6653,7 +6691,7 @@ class t3lib_TCEmain {
                }
 
                        // 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);
@@ -6779,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
@@ -6822,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));
                                                }
                                        }
@@ -6923,6 +6961,46 @@ class t3lib_TCEmain {
        }
 
        /**
+        * 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
+               );
+       }
+
+       /**
+        * Resets the nested element calls.
+        *
+        * @return void
+        */
+       protected function resetNestedElementCalls() {
+               $this->getMemoryCache()->remove('nestedElementCalls');
+       }
+
+       /**
         * Determines whether an element was registered to be deleted in the registry.
         *
         * @param string $table Name of the table
@@ -7009,4 +7087,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']);
 }
 
-?>
+?>
\ No newline at end of file