/** * Write local configuration array to typo3conf/LocalConfiguration.php * * @param array $configuration The local configuration to be written * @throws \RuntimeException * @return boolean TRUE on success * @access private */ public function writeLocalConfiguration(array $configuration) { $localConfigurationFile = $this->getLocalConfigurationFileLocation(); if (!$this->canWriteConfiguration()) { throw new \RuntimeException($localConfigurationFile . ' is not writable.', 1346323822); } $configuration = Utility\ArrayUtility::sortByKeyRecursive($configuration); $result = Utility\GeneralUtility::writeFile($localConfigurationFile, '<?php' . LF . 'return ' . Utility\ArrayUtility::arrayExport(Utility\ArrayUtility::renumberKeysToAvoidLeapsIfKeysAreAllNumeric($configuration)) . ';' . LF . '?>', TRUE); Utility\OpcodeCacheUtility::clearAllActive($localConfigurationFile); return $result; }
/** * Write local configuration array to typo3conf/LocalConfiguration.php * * @param array $configuration The local configuration to be written * @throws \RuntimeException * @return boolean TRUE on success * @access private */ public function writeLocalConfiguration(array $configuration) { $localConfigurationFile = $this->getLocalConfigurationFileResource(); if (!@is_file($localConfigurationFile) || !@is_writable($localConfigurationFile)) { throw new \RuntimeException($localConfigurationFile . ' does not exist or is not writable.', 1346323822); } $configuration = Utility\ArrayUtility::sortByKeyRecursive($configuration); $result = Utility\GeneralUtility::writeFile($localConfigurationFile, '<?php' . LF . 'return ' . Utility\ArrayUtility::arrayExport($configuration) . ';' . LF . '?>'); return $result === FALSE ? FALSE : TRUE; }
/** * Migrate localconf.php to LocalConfiguration if needed. This is done early in * install tool to ease further handling. * * If typo3conf and typo3conf/localconf.php exist, but no typo3conf/LocalConfiguration, * create LocalConfiguration.php / AdditionalConfiguration.php from localconf.php * Might throw exception if typo3conf directory is not writable. * * @return void */ protected function migrateLocalconfToLocalConfigurationIfNeeded() { /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */ $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager'); $localConfigurationFileLocation = $configurationManager->getLocalConfigurationFileLocation(); $localConfigurationFileExists = is_file($localConfigurationFileLocation); $localConfFileLocation = PATH_typo3conf . 'localconf.php'; $localConfFileExists = is_file($localConfFileLocation); if (is_dir(PATH_typo3conf) && $localConfFileExists && !$localConfigurationFileExists) { $localConfContent = file($localConfFileLocation); // Line array for the three categories: localConfiguration, db settings, additionalConfiguration $typo3ConfigurationVariables = array(); $typo3DatabaseVariables = array(); $additionalConfiguration = array(); foreach ($localConfContent as $line) { $line = trim($line); $matches = array(); // Convert extList to array if (preg_match('/^\\$TYPO3_CONF_VARS\\[\'EXT\'\\]\\[\'extList\'\\] *={1} *\'(.+)\';{1}/', $line, $matches) === 1 || preg_match('/^\\$GLOBALS\\[\'TYPO3_CONF_VARS\'\\]\\[\'EXT\'\\]\\[\'extList\'\\] *={1} *\'(.+)\';{1}/', $line, $matches) === 1) { $extListAsArray = GeneralUtility::trimExplode(',', $matches[1], TRUE); $typo3ConfigurationVariables[] = '$TYPO3_CONF_VARS[\'EXT\'][\'extListArray\'] = ' . var_export($extListAsArray, TRUE) . ';'; } elseif (preg_match('/^\\$TYPO3_CONF_VARS.+;{1}/', $line, $matches) === 1) { $typo3ConfigurationVariables[] = $matches[0]; } elseif (preg_match('/^\\$GLOBALS\\[\'TYPO3_CONF_VARS\'\\].+;{1}/', $line, $matches) === 1) { $lineWithoutGlobals = str_replace('$GLOBALS[\'TYPO3_CONF_VARS\']', '$TYPO3_CONF_VARS', $matches[0]); $typo3ConfigurationVariables[] = $lineWithoutGlobals; } elseif (preg_match('/^\\$typo_db.+;{1}/', $line, $matches) === 1) { eval($matches[0]); if (isset($typo_db_host)) { $typo3DatabaseVariables['host'] = $typo_db_host; } elseif (isset($typo_db)) { $typo3DatabaseVariables['database'] = $typo_db; } elseif (isset($typo_db_username)) { $typo3DatabaseVariables['username'] = $typo_db_username; } elseif (isset($typo_db_password)) { $typo3DatabaseVariables['password'] = $typo_db_password; } elseif (isset($typo_db_extTableDef_script)) { $typo3DatabaseVariables['extTablesDefinitionScript'] = $typo_db_extTableDef_script; } unset($typo_db_host, $typo_db, $typo_db_username, $typo_db_password, $typo_db_extTableDef_script); } elseif (strlen($line) > 0 && preg_match('/^\\/\\/.+|^#.+|^<\\?php$|^<\\?$|^\\?>$/', $line, $matches) === 0) { $additionalConfiguration[] = $line; } } // Build new TYPO3_CONF_VARS array $TYPO3_CONF_VARS = NULL; // Issue #39434: Combining next two lines into one triggers a weird issue in some PHP versions $evalData = implode(LF, $typo3ConfigurationVariables); eval($evalData); // Add db settings to array $TYPO3_CONF_VARS['DB'] = $typo3DatabaseVariables; $TYPO3_CONF_VARS = \TYPO3\CMS\Core\Utility\ArrayUtility::sortByKeyRecursive($TYPO3_CONF_VARS); // Write out new LocalConfiguration file $configurationManager->writeLocalConfiguration($TYPO3_CONF_VARS); // Write out new AdditionalConfiguration file if (sizeof($additionalConfiguration) > 0) { $configurationManager->writeAdditionalConfiguration($additionalConfiguration); } else { @unlink($configurationManager->getAdditionalConfigurationFileLocation()); } // Move localconf.php to localconf.obsolete.php rename($localConfFileLocation, PATH_site . 'typo3conf/localconf.obsolete.php'); // Perform a reload to self, so bootstrap now uses new LocalConfiguration.php $this->redirect(); } }
/** * @test */ public function sortByKeyRecursiveCheckIfSortingIsCorrect() { $unsortedArray = array('z' => NULL, 'a' => NULL, 'd' => array('c' => NULL, 'b' => NULL, 'd' => NULL, 'a' => NULL)); $expectedResult = array('a' => NULL, 'd' => array('a' => NULL, 'b' => NULL, 'c' => NULL, 'd' => NULL), 'z' => NULL); $this->assertSame($expectedResult, ArrayUtility::sortByKeyRecursive($unsortedArray)); }
/** * Performs the update action. * * The methods reads localconf.php line by line and classifies every line * to be either part of LocalConfiguration (everything that starts with TYPO3_CONF_VARS), * belongs to the database settings (those will be merged to TYPO3_CONF_VARS), * and everything else (those will be moved to the AdditionalConfiguration file. * * @param array &$dbQueries: Queries done in this update * @param mixed &$customMessages: Custom messages * @return boolean TRUE if everything went well */ public function performUpdate(array &$dbQueries, &$customMessages) { $result = FALSE; try { $localConfigurationContent = file(PATH_typo3conf . 'localconf.php'); // Line array for the three categories: localConfiguration, db settings, additionalConfiguration $typo3ConfigurationVariables = array(); $typo3DatabaseVariables = array(); $additionalConfiguration = array(); foreach ($localConfigurationContent as $line) { $line = trim($line); $matches = array(); // Convert extList to array if (preg_match('/^\\$TYPO3_CONF_VARS\\[\'EXT\'\\]\\[\'extList\'\\] *={1} *\'(.+)\';{1}/', $line, $matches) === 1) { $extListAsArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $matches[1], TRUE); $typo3ConfigurationVariables[] = '$TYPO3_CONF_VARS[\'EXT\'][\'extListArray\'] = ' . var_export($extListAsArray, TRUE) . ';'; } elseif (preg_match('/^\\$TYPO3_CONF_VARS.+;{1}/', $line, $matches) === 1) { $typo3ConfigurationVariables[] = $matches[0]; } elseif (preg_match('/^\\$typo_db.+;{1}/', $line, $matches) === 1) { eval($matches[0]); if (isset($typo_db_host)) { $typo3DatabaseVariables['host'] = $typo_db_host; } elseif (isset($typo_db)) { $typo3DatabaseVariables['database'] = $typo_db; } elseif (isset($typo_db_username)) { $typo3DatabaseVariables['username'] = $typo_db_username; } elseif (isset($typo_db_password)) { $typo3DatabaseVariables['password'] = $typo_db_password; } elseif (isset($typo_db_extTableDef_script)) { $typo3DatabaseVariables['extTablesDefinitionScript'] = $typo_db_extTableDef_script; } unset($typo_db_host, $typo_db, $typo_db_username, $typo_db_password, $typo_db_extTableDef_script); } elseif (strlen($line) > 0 && preg_match('/^\\/\\/.+|^#.+|^<\\?php$|^<\\?$|^\\?>$/', $line, $matches) === 0) { $additionalConfiguration[] = $line; } } // Build new TYPO3_CONF_VARS array $TYPO3_CONF_VARS = NULL; eval(implode(LF, $typo3ConfigurationVariables)); // Add db settings to array $TYPO3_CONF_VARS['DB'] = $typo3DatabaseVariables; $TYPO3_CONF_VARS = \TYPO3\CMS\Core\Utility\ArrayUtility::sortByKeyRecursive($TYPO3_CONF_VARS); // Build new (empty) LocalConfiguration file if not exists as the function writeLocalConfiguration depends on it \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')->getLocalConfigurationFileResource(), ''); // Write out new LocalConfiguration file \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')->writeLocalConfiguration($TYPO3_CONF_VARS); // Write out new AdditionalConfiguration file if (sizeof($additionalConfiguration) > 0) { \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')->writeAdditionalConfiguration($additionalConfiguration); } else { @unlink(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')->getAdditionalConfigurationFileResource()); } rename(PATH_site . 'typo3conf/localconf.php', PATH_site . 'typo3conf/localconf.obsolete.php'); $result = TRUE; } catch (\Exception $e) { } return $result; }
/** * Write local configuration array to typo3conf/LocalConfiguration.php * * @param array $configuration The local configuration to be written * @return boolean TRUE on success */ protected static function writeLocalConfiguration(array $configuration) { $configuration = \TYPO3\CMS\Core\Utility\ArrayUtility::sortByKeyRecursive($configuration); $result = \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile(PATH_site . static::LOCAL_CONFIGURATION_FILE, '<?php' . LF . 'return ' . \TYPO3\CMS\Core\Utility\ArrayUtility::arrayExport($configuration) . ';' . LF . '?>'); return $result === FALSE ? FALSE : TRUE; }
/** * Write local configuration array to typo3conf/LocalConfiguration.php * * @param array $configuration The local configuration to be written * @throws \RuntimeException * @return bool TRUE on success * @access private */ public function writeLocalConfiguration(array $configuration) { $localConfigurationFile = $this->getLocalConfigurationFileLocation(); if (!$this->canWriteConfiguration()) { throw new \RuntimeException($localConfigurationFile . ' is not writable.', 1346323822); } $configuration = ArrayUtility::sortByKeyRecursive($configuration); $result = GeneralUtility::writeFile($localConfigurationFile, '<?php' . LF . 'return ' . ArrayUtility::arrayExport(ArrayUtility::renumberKeysToAvoidLeapsIfKeysAreAllNumeric($configuration)) . ';' . LF, true); GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($localConfigurationFile); return $result; }
/** * Find files which are referenced multiple times in uploads/ folder * * @return array an array of files and their reference hashes that are referenced multiple times */ protected function findMultipleReferencedFiles() : array { $multipleReferencesList = []; // Select all files in the reference table not found by a soft reference parser (thus TCA configured) $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex'); $result = $queryBuilder->select('*')->from('sys_refindex')->where($queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter('_FILE', \PDO::PARAM_STR)), $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)))->execute(); // Traverse the files and put into a large table $allReferencesToFiles = []; while ($record = $result->fetch()) { // Compile info string for location of reference $infoString = $this->formatReferenceIndexEntryToString($record); $hash = $record['hash']; $fileName = $record['ref_string']; // Add entry if file has multiple references pointing to it if (isset($allReferencesToFiles[$fileName])) { if (!is_array($multipleReferencesList[$fileName])) { $multipleReferencesList[$fileName] = []; $multipleReferencesList[$fileName][$allReferencesToFiles[$fileName]['hash']] = $allReferencesToFiles[$fileName]['infoString']; } $multipleReferencesList[$fileName][$hash] = $infoString; } else { $allReferencesToFiles[$fileName] = ['infoString' => $infoString, 'hash' => $hash]; } } return ArrayUtility::sortByKeyRecursive($multipleReferencesList); }
/** * Find relations pointing to non-existing records (in managed references or soft-references) * * @return array an array of records within sys_refindex */ protected function findRelationsToNonExistingRecords() : array { $deletedRecords = []; $deletedRecordsInSoftReferenceRelations = []; $nonExistingRecords = []; $nonExistingRecordsInSoftReferenceRelations = []; $offlineVersionRecords = []; $offlineVersionRecordsInSoftReferenceRelations = []; // Select DB relations from reference table $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex'); $rowIterator = $queryBuilder->select('ref_uid', 'ref_table', 'softref_key', 'hash', 'tablename', 'recuid', 'field', 'flexpointer', 'deleted')->from('sys_refindex')->where($queryBuilder->expr()->neq('ref_table', $queryBuilder->createNamedParameter('_FILE', \PDO::PARAM_STR)), $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)))->execute(); $existingRecords = []; while ($rec = $rowIterator->fetch()) { $isSoftReference = !empty($rec['softref_key']); $idx = $rec['ref_table'] . ':' . $rec['ref_uid']; // Get referenced record: if (!isset($existingRecords[$idx])) { $existingRecords[$idx] = BackendUtility::getRecordRaw($rec['ref_table'], 'uid=' . (int) $rec['ref_uid'], 'uid,pid' . (isset($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']) ? ',' . $GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete'] : '')); } // Compile info string for location of reference: $infoString = $this->formatReferenceIndexEntryToString($rec); // Handle missing file: if ($existingRecords[$idx]['uid']) { // Record exists, but is a reference to an offline version if ((int) $existingRecords[$idx]['pid'] === -1) { if ($isSoftReference) { $offlineVersionRecordsInSoftReferenceRelations[] = $infoString; } else { $offlineVersionRecords[$idx][$rec['hash']] = $infoString; } // reference to a deleted record } elseif (isset($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']) && $existingRecords[$idx][$GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']]) { if ($isSoftReference) { $deletedRecordsInSoftReferenceRelations[] = $infoString; } else { $deletedRecords[] = $infoString; } } } else { if ($isSoftReference) { $nonExistingRecordsInSoftReferenceRelations[] = $infoString; } else { $nonExistingRecords[$idx][$rec['hash']] = $infoString; } } } return ['nonExistingRecords' => ArrayUtility::sortByKeyRecursive($nonExistingRecords), 'nonExistingRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($nonExistingRecordsInSoftReferenceRelations), 'offlineVersionRecords' => ArrayUtility::sortByKeyRecursive($offlineVersionRecords), 'offlineVersionRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($offlineVersionRecordsInSoftReferenceRelations), 'deletedRecords' => ArrayUtility::sortByKeyRecursive($deletedRecords), 'deletedRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($deletedRecordsInSoftReferenceRelations)]; }