110 public function get() {
225 if (!isset($this->elementEntityProcessor)) {
227 'TYPO3\\CMS\\Version\\Dependency\\ElementEntityProcessor' 229 $this->elementEntityProcessor->setWorkspace($this->
getWorkspace());
255 foreach ($this->commandMap as $table => $liveIdCollection) {
256 foreach ($liveIdCollection as $liveId => $commandCollection) {
257 foreach ($commandCollection as $command => $properties) {
258 if ($command ===
'version' && isset($properties[
'action']) && $properties[
'action'] ===
'swap') {
259 if (isset($properties[
'swapWith']) && \
TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($properties[
'swapWith'])) {
260 call_user_func_array(array($this, $callbackMethod), array_merge($arguments, array($table, $liveId, $properties)));
277 $scope = self::SCOPE_WorkspacesSwap;
278 $dependency = $this->getDependencyUtility($scope);
283 $this->applyWorkspacesDependencies($dependency, $scope);
295 $extendedCommandMap = array();
296 $elementList = array();
298 if ($this->workspacesSwapMode ===
'any' || $this->workspacesSwapMode ===
'pages' && $table ===
'pages') {
299 $elementList = $this->
getParent()->findPageElementsForVersionSwap($table, $liveId, $properties[
'swapWith']);
301 foreach ($elementList as $elementTable => $elementIdArray) {
302 foreach ($elementIdArray as $elementIds) {
303 $extendedCommandMap[$elementTable][$elementIds[0]][
'version'] = array_merge($properties, array(
'swapWith' => $elementIds[1]));
306 if (count($elementList) > 0) {
307 $this->
remove($table, $liveId,
'version');
322 $elementList = array();
324 if ($this->workspacesSwapMode ===
'any' || $this->workspacesSwapMode ===
'pages' && $table ===
'pages') {
325 $elementList = $this->
getParent()->findPageElementsForVersionSwap($table, $liveId, $properties[
'swapWith']);
327 foreach ($elementList as $elementTable => $elementIdArray) {
328 foreach ($elementIdArray as $elementIds) {
329 $dependency->addElement($elementTable, $elementIds[1], array(
'liveId' => $elementIds[0],
'properties' => array_merge($properties, array(
'swapWith' => $elementIds[1]))));
332 if (count($elementList) === 0) {
333 $dependency->addElement($table, $properties[
'swapWith'], array(
'liveId' => $liveId,
'properties' => $properties));
346 foreach ($this->commandMap as $table => $versionIdCollection) {
347 foreach ($versionIdCollection as $versionIdList => $commandCollection) {
348 foreach ($commandCollection as $command => $properties) {
349 if ($command ===
'version' && isset($properties[
'action']) && $properties[
'action'] ===
'setStage') {
350 if (isset($properties[
'stageId']) && \
TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($properties[
'stageId'])) {
351 call_user_func_array(array($this, $callbackMethod), array_merge($arguments, array($table, $versionIdList, $properties)));
367 $scope = self::SCOPE_WorkspacesSetStage;
368 $dependency = $this->getDependencyUtility($scope);
374 $this->applyWorkspacesDependencies($dependency, $scope);
386 $extendedCommandMap = array();
388 $elementList = array($table => $versionIds);
390 if (count($versionIds) === 1) {
391 $workspaceRecord = BackendUtility::getRecord($table, $versionIds[0],
't3ver_wsid');
392 $workspaceId = $workspaceRecord[
't3ver_wsid'];
396 if ($table ===
'pages') {
398 $livePageIds = $versionIds;
399 $this->
getParent()->findRealPageIds($livePageIds);
400 $this->
getParent()->findPageElementsForVersionStageChange($livePageIds, $workspaceId, $elementList);
401 } elseif ($this->workspacesChangeStageMode ===
'any') {
403 $pageIdList = array();
404 $this->
getParent()->findPageIdsForVersionStateChange($table, $versionIds, $workspaceId, $pageIdList, $elementList);
406 $this->
getParent()->findPageElementsForVersionStageChange($pageIdList, $workspaceId, $elementList);
409 foreach ($elementList as $elementTable => $elementIds) {
410 foreach ($elementIds as $elementId) {
411 $extendedCommandMap[$elementTable][$elementId][
'version'] = $properties;
414 $this->
remove($table, $versionIds,
'version');
428 $dependency->addElement($table, $versionId, array(
'versionId' => $versionId,
'properties' => $properties));
439 $scope = self::SCOPE_WorkspacesClear;
440 $dependency = $this->getDependencyUtility($scope);
442 foreach ($this->commandMap as $table => $versionIdCollection) {
443 foreach ($versionIdCollection as $versionId => $commandCollection) {
444 foreach ($commandCollection as $command => $properties) {
445 if ($command ===
'version' && isset($properties[
'action']) && ($properties[
'action'] ===
'clearWSID' || $properties[
'action'] ===
'flush')) {
446 $dependency->addElement($table, $versionId, array(
'versionId' => $versionId,
'properties' => $properties));
451 $this->applyWorkspacesDependencies($dependency, $scope);
464 $extractedCommandMap = array();
466 if (count($versionIds) > 1) {
467 foreach ($versionIds as $versionId) {
468 if (isset($this->commandMap[$table][$versionId][
'version'])) {
469 throw new \RuntimeException(
'Command map for [' . $table .
'][' . $versionId .
'][version] was already set.', 1289391048);
471 $extractedCommandMap[$table][$versionId][
'version'] = $properties;
473 $this->
remove($table, $versionIdList,
'version');
486 protected function applyWorkspacesDependencies(\
TYPO3\CMS\Version\Dependency\DependencyResolver $dependency, $scope) {
487 $transformDependentElementsToUseLiveId = $this->
getScopeData($scope, self::KEY_TransformDependentElementsToUseLiveId);
488 $elementsToBeVersioned = $dependency->getElements();
490 if ($transformDependentElementsToUseLiveId) {
491 $elementsToBeVersioned = $this->
getElementEntityProcessor()->transformDependentElementsToUseLiveId($elementsToBeVersioned);
493 $outerMostParents = $dependency->getOuterMostParents();
495 foreach ($outerMostParents as $outerMostParent) {
496 $dependentElements = $dependency->getNestedElements($outerMostParent);
497 if ($transformDependentElementsToUseLiveId) {
502 $intersectingElements = array_intersect_key($dependentElements, $elementsToBeVersioned);
503 if (count($intersectingElements) > 0) {
505 if (count($intersectingElements) !== count($dependentElements) && $this->workspacesConsiderReferences === FALSE) {
506 $this->purgeWithErrorMessage($intersectingElements, $scope);
508 $this->update(current($intersectingElements), $dependentElements, $scope);
521 protected function purgeWithErrorMessage(array $elements, $scope) {
523 foreach ($elements as $element) {
524 $table = $element->getTable();
526 $this->
remove($table, $id,
'version');
527 $this->
getTceMain()->log($table, $id, 5, 0, 1, $this->
getScopeData($scope, self::KEY_ScopeErrorMessage), $this->
getScopeData($scope, self::KEY_ScopeErrorCode), array(
543 protected function update(
ElementEntity $intersectingElement, array $elements, $scope) {
544 $orderedCommandMap = array();
545 $commonProperties = array();
546 if ($this->
getScopeData($scope, self::KEY_GetCommonPropertiesCallback)) {
547 $commonProperties = $this->
processCallback($this->
getScopeData($scope, self::KEY_GetCommonPropertiesCallback), array($intersectingElement));
550 foreach ($elements as $element) {
551 $table = $element->getTable();
553 $this->
remove($table, $id,
'version');
554 if ($element->isInvalid()) {
557 $orderedCommandMap[$table][$id][
'version'] = $commonProperties;
558 if ($this->
getScopeData($scope, self::KEY_GetElementPropertiesCallback)) {
559 $orderedCommandMap[$table][$id][
'version'] = array_merge($commonProperties, $this->
processCallback($this->
getScopeData($scope, self::KEY_GetElementPropertiesCallback), array($element)));
595 protected function remove($table, $id, $command = NULL) {
596 if (is_string($command)) {
597 unset($this->commandMap[$table][$id][$command]);
599 unset($this->commandMap[$table][$id]);
620 return $element->
getId();
631 'swapWith' => $element->
getId()
642 $commonSwapProperties = array();
643 $elementProperties = $element->
getDataValue(
'properties');
644 if (isset($elementProperties[
'action'])) {
645 $commonSwapProperties[
'action'] = $elementProperties[
'action'];
647 return $commonSwapProperties;
657 $commonSwapProperties = array();
658 $elementProperties = $element->
getDataValue(
'properties');
659 if (isset($elementProperties[
'action'])) {
660 $commonSwapProperties[
'action'] = $elementProperties[
'action'];
662 if (isset($elementProperties[
'swapIntoWS'])) {
663 $commonSwapProperties[
'swapIntoWS'] = $elementProperties[
'swapIntoWS'];
665 if (isset($elementProperties[
'comment'])) {
666 $commonSwapProperties[
'comment'] = $elementProperties[
'comment'];
668 if (isset($elementProperties[
'notificationAlternativeRecipients'])) {
669 $commonSwapProperties[
'notificationAlternativeRecipients'] = $elementProperties[
'notificationAlternativeRecipients'];
672 return $commonSwapProperties;
692 $commonSetStageProperties = array();
693 $elementProperties = $element->
getDataValue(
'properties');
694 if (isset($elementProperties[
'stageId'])) {
695 $commonSetStageProperties[
'stageId'] = $elementProperties[
'stageId'];
697 if (isset($elementProperties[
'comment'])) {
698 $commonSetStageProperties[
'comment'] = $elementProperties[
'comment'];
700 if (isset($elementProperties[
'action'])) {
701 $commonSetStageProperties[
'action'] = $elementProperties[
'action'];
703 if (isset($elementProperties[
'notificationAlternativeRecipients'])) {
704 $commonSetStageProperties[
'notificationAlternativeRecipients'] = $elementProperties[
'notificationAlternativeRecipients'];
706 return $commonSetStageProperties;
715 protected function getDependencyUtility($scope) {
719 $dependency->setOuterMostParentsRequireReferences(TRUE);
720 if ($this->
getScopeData($scope, self::KEY_ElementConstructCallback)) {
723 if ($this->
getScopeData($scope, self::KEY_ElementCreateChildReferenceCallback)) {
726 if ($this->
getScopeData($scope, self::KEY_ElementCreateParentReferenceCallback)) {
739 $this->scopes = array(
741 self::SCOPE_WorkspacesSwap => array(
743 self::KEY_ScopeErrorMessage =>
'Record "%s" (%s:%s) cannot be swapped or published independently, because it is related to other new or modified records.',
744 self::KEY_ScopeErrorCode => 1288283630,
748 self::KEY_GetElementPropertiesCallback =>
'getElementSwapPropertiesCallback',
749 self::KEY_GetCommonPropertiesCallback =>
'getCommonSwapPropertiesCallback',
751 self::KEY_ElementConstructCallback =>
'createNewDependentElementCallback',
753 self::KEY_ElementCreateChildReferenceCallback =>
'createNewDependentElementChildReferenceCallback',
754 self::KEY_ElementCreateParentReferenceCallback =>
'createNewDependentElementParentReferenceCallback',
756 self::KEY_PurgeWithErrorMessageGetIdCallback =>
'getElementLiveIdCallback',
758 self::KEY_UpdateGetIdCallback =>
'getElementLiveIdCallback',
760 self::KEY_TransformDependentElementsToUseLiveId => TRUE
763 self::SCOPE_WorkspacesSetStage => array(
765 self::KEY_ScopeErrorMessage =>
'Record "%s" (%s:%s) cannot be sent to another stage independently, because it is related to other new or modified records.',
766 self::KEY_ScopeErrorCode => 1289342524,
770 self::KEY_GetElementPropertiesCallback =>
'getElementSetStagePropertiesCallback',
771 self::KEY_GetCommonPropertiesCallback =>
'getCommonSetStagePropertiesCallback',
773 self::KEY_ElementConstructCallback => NULL,
775 self::KEY_ElementCreateChildReferenceCallback =>
'createNewDependentElementChildReferenceCallback',
776 self::KEY_ElementCreateParentReferenceCallback =>
'createNewDependentElementParentReferenceCallback',
778 self::KEY_PurgeWithErrorMessageGetIdCallback =>
'getElementIdCallback',
780 self::KEY_UpdateGetIdCallback =>
'getElementIdCallback',
782 self::KEY_TransformDependentElementsToUseLiveId => FALSE
785 self::SCOPE_WorkspacesClear => array(
787 self::KEY_ScopeErrorMessage =>
'Record "%s" (%s:%s) cannot be flushed independently, because it is related to other new or modified records.',
788 self::KEY_ScopeErrorCode => 1300467990,
792 self::KEY_GetElementPropertiesCallback => NULL,
793 self::KEY_GetCommonPropertiesCallback =>
'getCommonClearPropertiesCallback',
795 self::KEY_ElementConstructCallback => NULL,
797 self::KEY_ElementCreateChildReferenceCallback =>
'createClearDependentElementChildReferenceCallback',
798 self::KEY_ElementCreateParentReferenceCallback =>
'createClearDependentElementParentReferenceCallback',
800 self::KEY_PurgeWithErrorMessageGetIdCallback =>
'getElementIdCallback',
802 self::KEY_UpdateGetIdCallback =>
'getElementIdCallback',
804 self::KEY_TransformDependentElementsToUseLiveId => FALSE
818 if (!isset($this->scopes[$scope])) {
819 throw new \RuntimeException(
'Scope "' . $scope .
'" is not defined.', 1289342187);
821 return $this->scopes[$scope][$key];
833 'TYPO3\\CMS\\Version\\Dependency\\EventCallback',
846 return call_user_func_array(array($this, $method), $callbackArguments);
getScopeData($scope, $key)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
getCommonSetStagePropertiesCallback(ElementEntity $element)
getElementEntityProcessor()
applyWorkspacesSetStageBehaviour($table, $versionIdList, array $properties)
getDependencyCallback($method, array $targetArguments=array())
const KEY_ScopeErrorMessage
getElementSwapPropertiesCallback(ElementEntity $element)
const SCOPE_WorkspacesClear
addWorkspacesSwapElements(\TYPO3\CMS\Version\Dependency\DependencyResolver $dependency, $table, $liveId, array $properties)
addWorkspacesSetStageElements(\TYPO3\CMS\Version\Dependency\DependencyResolver $dependency, $table, $versionId, array $properties)
setWorkspacesChangeStageMode($workspacesChangeStageMode)
const KEY_ElementConstructCallback
getElementIdCallback(ElementEntity $element)
const KEY_TransformDependentElementsToUseLiveId
setWorkspacesSwapMode($workspacesSwapMode)
const KEY_ElementCreateChildReferenceCallback
__construct(\TYPO3\CMS\Version\Hook\DataHandlerHook $parent, \TYPO3\CMS\Core\DataHandling\DataHandler $tceMain, array $commandMap, $workspace)
const KEY_PurgeWithErrorMessageGetIdCallback
static makeInstance($className)
const EVENT_CreateParentReference
processCallback($method, array $callbackArguments)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
setWorkspacesConsiderReferences($workspacesConsiderReferences)
static getRecordTitle($table, $row, $prep=FALSE, $forceResult=TRUE)
const KEY_GetElementPropertiesCallback
getElementSetStagePropertiesCallback(ElementEntity $element)
const SCOPE_WorkspacesSwap
const KEY_ElementCreateParentReferenceCallback
explodeSetStage($table, $versionIdList, array $properties)
applyWorkspacesSwapBehaviour($table, $liveId, array $properties)
getCommonClearPropertiesCallback(ElementEntity $element)
invokeWorkspacesSetStageItems($callbackMethod, array $arguments=array())
resolveWorkspacesClearDependencies()
const KEY_UpdateGetIdCallback
setParent(\TYPO3\CMS\Version\Hook\DataHandlerHook $parent)
getElementLiveIdCallback(ElementEntity $element)
resolveWorkspacesSwapDependencies()
mergeToTop(array $commandMap)
const KEY_GetCommonPropertiesCallback
static inList($list, $item)
const EVENT_CreateChildReference
getCommonSwapPropertiesCallback(ElementEntity $element)
$workspacesChangeStageMode
invokeWorkspacesSwapItems($callbackMethod, array $arguments=array())
resolveWorkspacesSetStageDependencies()
$workspacesConsiderReferences
mergeToBottom(array $commandMap)
setTceMain(\TYPO3\CMS\Core\DataHandling\DataHandler $tceMain)
const SCOPE_WorkspacesSetStage