/** * Gets the query arguments and assembles them for URLs. * Arguments may be removed or set, depending on configuration. * * @param string $conf Configuration * @param array $overruleQueryArguments Multidimensional key/value pairs that overrule incoming query arguments * @param bool $forceOverruleArguments If set, key/value pairs not in the query but the overrule array will be set * @return string The URL query part (starting with a &) */ public function getQueryArguments($conf, $overruleQueryArguments = array(), $forceOverruleArguments = false) { switch ((string) $conf['method']) { case 'GET': $currentQueryArray = GeneralUtility::_GET(); break; case 'POST': $currentQueryArray = GeneralUtility::_POST(); break; case 'GET,POST': $currentQueryArray = GeneralUtility::_GET(); ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_POST()); break; case 'POST,GET': $currentQueryArray = GeneralUtility::_POST(); ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_GET()); break; default: $currentQueryArray = GeneralUtility::explodeUrl2Array($this->getEnvironmentVariable('QUERY_STRING'), true); } if ($conf['exclude']) { $exclude = str_replace(',', '&', $conf['exclude']); $exclude = GeneralUtility::explodeUrl2Array($exclude, true); // never repeat id $exclude['id'] = 0; $newQueryArray = ArrayUtility::arrayDiffAssocRecursive($currentQueryArray, $exclude); } else { $newQueryArray = $currentQueryArray; } if ($forceOverruleArguments) { ArrayUtility::mergeRecursiveWithOverrule($newQueryArray, $overruleQueryArguments); } else { ArrayUtility::mergeRecursiveWithOverrule($newQueryArray, $overruleQueryArguments, false); } return GeneralUtility::implodeArrayForUrl('', $newQueryArray, '', false, true); }
/** * hook that is called when an element shall get deleted * * @param string $table the table of the record * @param int $id the ID of the record * @param array $record The accordant database record * @param bool $recordWasDeleted can be set so that other hooks or * @param DataHandler $tcemainObj reference to the main tcemain object * @return void */ public function processCmdmap_deleteAction($table, $id, array $record, &$recordWasDeleted, DataHandler $tcemainObj) { // only process the hook if it wasn't processed // by someone else before if ($recordWasDeleted) { return; } $recordWasDeleted = TRUE; // For Live version, try if there is a workspace version because if so, rather "delete" that instead // Look, if record is an offline version, then delete directly: if ($record['pid'] != -1) { if ($wsVersion = BackendUtility::getWorkspaceVersionOfRecord($tcemainObj->BE_USER->workspace, $table, $id)) { $record = $wsVersion; $id = $record['uid']; } } $recordVersionState = VersionState::cast($record['t3ver_state']); // Look, if record is an offline version, then delete directly: if ($record['pid'] == -1) { if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) { // In Live workspace, delete any. In other workspaces there must be match. if ($tcemainObj->BE_USER->workspace == 0 || (int) $record['t3ver_wsid'] == $tcemainObj->BE_USER->workspace) { $liveRec = BackendUtility::getLiveVersionOfRecord($table, $id, 'uid,t3ver_state'); // Processing can be skipped if a delete placeholder shall be swapped/published // during the current request. Thus it will be deleted later on... $liveRecordVersionState = VersionState::cast($liveRec['t3ver_state']); if ($recordVersionState->equals(VersionState::DELETE_PLACEHOLDER) && !empty($liveRec['uid']) && !empty($tcemainObj->cmdmap[$table][$liveRec['uid']]['version']['action']) && !empty($tcemainObj->cmdmap[$table][$liveRec['uid']]['version']['swapWith']) && $tcemainObj->cmdmap[$table][$liveRec['uid']]['version']['action'] === 'swap' && $tcemainObj->cmdmap[$table][$liveRec['uid']]['version']['swapWith'] == $id) { return NULL; } if ($record['t3ver_wsid'] > 0 && $recordVersionState->equals(VersionState::DEFAULT_STATE)) { // Change normal versioned record to delete placeholder // Happens when an edited record is deleted $updateFields = array('t3ver_label' => 'DELETED!', 't3ver_state' => 2); $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . $id, $updateFields); // Delete localization overlays: $tcemainObj->deleteL10nOverlayRecords($table, $id); } elseif ($record['t3ver_wsid'] == 0 || !$liveRecordVersionState->indicatesPlaceholder()) { // Delete those in WS 0 + if their live records state was not "Placeholder". $tcemainObj->deleteEl($table, $id); } else { // If live record was placeholder (new/deleted), rather clear // it from workspace (because it clears both version and placeholder). $this->version_clearWSID($table, $id, FALSE, $tcemainObj); } } else { $tcemainObj->newlog('Tried to delete record from another workspace', 1); } } else { $tcemainObj->newlog('Versioning not enabled for record with PID = -1!', 2); } } elseif ($res = $tcemainObj->BE_USER->workspaceAllowLiveRecordsInPID($record['pid'], $table)) { // Look, if record is "online" or in a versionized branch, then delete directly. if ($res > 0) { $tcemainObj->deleteEl($table, $id); } else { $tcemainObj->newlog('Stage of root point did not allow for deletion', 1); } } elseif ($recordVersionState->equals(VersionState::MOVE_PLACEHOLDER)) { // Placeholders for moving operations are deletable directly. // Get record which its a placeholder for and reset the t3ver_state of that: if ($wsRec = BackendUtility::getWorkspaceVersionOfRecord($record['t3ver_wsid'], $table, $record['t3ver_move_id'], 'uid')) { // Clear the state flag of the workspace version of the record // Setting placeholder state value for version (so it can know it is currently a new version...) $updateFields = array('t3ver_state' => (string) new VersionState(VersionState::DEFAULT_STATE)); $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . (int) $wsRec['uid'], $updateFields); } $tcemainObj->deleteEl($table, $id); } else { // Otherwise, try to delete by versioning: $copyMappingArray = $tcemainObj->copyMappingArray; $tcemainObj->versionizeRecord($table, $id, 'DELETED!', TRUE); // Determine newly created versions: // (remove placeholders are copied and modified, thus they appear in the copyMappingArray) $versionizedElements = ArrayUtility::arrayDiffAssocRecursive($tcemainObj->copyMappingArray, $copyMappingArray); // Delete localization overlays: foreach ($versionizedElements as $versionizedTableName => $versionizedOriginalIds) { foreach ($versionizedOriginalIds as $versionizedOriginalId => $_) { $tcemainObj->deleteL10nOverlayRecords($versionizedTableName, $versionizedOriginalId); } } } }
/** * Unsets elements (e.g. of the data map) that shall be deleted. * This avoids to modify records that will be deleted later on. * * @param array $elements Elements to be modified * @return array */ protected function unsetElementsToBeDeleted(array $elements) { $elements = ArrayUtility::arrayDiffAssocRecursive($elements, $this->getCommandMapElements('delete')); foreach ($elements as $key => $value) { if (empty($value)) { unset($elements[$key]); } } return $elements; }
/** * Filters keys off from first array that also exist in second array. Comparison is done by keys. * This method is a recursive version of php array_diff_assoc() * * @param array $array1 Source array * @param array $array2 Reduce source array by this array * @return array Source array reduced by keys also present in second array * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8 - use ArrayUtility::arrayDiffAssocRecursive() instead */ public static function arrayDiffAssocRecursive(array $array1, array $array2) { static::logDeprecatedFunction(); return ArrayUtility::arrayDiffAssocRecursive($array1, $array2); }
/** * Builds the URI, backend flavour * The resulting URI is relative and starts with "index.php". * The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages * will be ignored in the backend. * * @return string The URI */ public function buildBackendUri() { if ($this->addQueryString === true) { if ($this->addQueryStringMethod) { switch ($this->addQueryStringMethod) { case 'GET': $arguments = GeneralUtility::_GET(); break; case 'POST': $arguments = GeneralUtility::_POST(); break; case 'GET,POST': $arguments = array_replace_recursive(GeneralUtility::_GET(), GeneralUtility::_POST()); break; case 'POST,GET': $arguments = array_replace_recursive(GeneralUtility::_POST(), GeneralUtility::_GET()); break; default: $arguments = GeneralUtility::explodeUrl2Array(GeneralUtility::getIndpEnv('QUERY_STRING'), true); } } else { $arguments = GeneralUtility::_GET(); } foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) { $argumentToBeExcluded = GeneralUtility::explodeUrl2Array($argumentToBeExcluded, true); $arguments = ArrayUtility::arrayDiffAssocRecursive($arguments, $argumentToBeExcluded); } } else { $arguments = array('M' => GeneralUtility::_GP('M'), 'id' => GeneralUtility::_GP('id')); } ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments); $arguments = $this->convertDomainObjectsToIdentityArrays($arguments); $this->lastArguments = $arguments; $moduleName = $arguments['M']; unset($arguments['M'], $arguments['moduleToken']); $backendUriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { $uri = (string) $backendUriBuilder->buildUriFromModule($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); } else { $uri = (string) $backendUriBuilder->buildUriFromModule($moduleName, $arguments); } if ($this->section !== '') { $uri .= '#' . $this->section; } return $uri; }
/** * @test */ public function arrayDiffAssocRecursiveHandlesMixedArrays() { $array1 = array('key1' => array('key11' => 'value11', 'key12' => 'value12'), 'key2' => 'value2', 'key3' => 'value3'); $array2 = array('key1' => 'value1', 'key2' => array('key21' => 'value21')); $expectedResult = array('key3' => 'value3'); $actualResult = ArrayUtility::arrayDiffAssocRecursive($array1, $array2); $this->assertEquals($expectedResult, $actualResult); }