TYPO3 API  SVNRelease
class.tx_version_tcemain_commandmap.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  * Copyright notice
00004  *
00005  * (c) 2010-2011 Oliver Hader <oliver@typo3.org>
00006  * All rights reserved
00007  *
00008  * This script is part of the TYPO3 project. The TYPO3 project is
00009  * free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * The GNU General Public License can be found at
00015  * http://www.gnu.org/copyleft/gpl.html.
00016  * A copy is found in the textfile GPL.txt and important notices to the license
00017  * from the author is found in LICENSE.txt distributed with these scripts.
00018  *
00019  *
00020  * This script is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * This copyright notice MUST APPEAR in all copies of the script!
00026  ***************************************************************/
00027 
00028 /**
00029  * Handles the t3lib_TCEmain command map and is only used in combination with t3lib_TCEmain.
00030  */
00031 class tx_version_tcemain_CommandMap {
00032     const SCOPE_WorkspacesSwap = 'SCOPE_WorkspacesSwap';
00033     const SCOPE_WorkspacesSetStage = 'SCOPE_WorkspacesSetStage';
00034 
00035     const KEY_ScopeErrorMessage = 'KEY_ScopeErrorMessage';
00036     const KEY_ScopeErrorCode = 'KEY_ScopeErrorCode';
00037     const KEY_GetElementPropertiesCallback = 'KEY_GetElementPropertiesCallback';
00038     const KEY_GetCommonPropertiesCallback = 'KEY_GetCommonPropertiesCallback';
00039     const KEY_ElementConstructCallback = 'KEY_EventConstructCallback';
00040     const KEY_ElementCreateChildReferenceCallback = 'KEY_ElementCreateChildReferenceCallback';
00041     const KEY_ElementCreateParentReferenceCallback = 'KEY_ElementCreateParentReferenceCallback';
00042     const KEY_PurgeWithErrorMessageGetIdCallback = 'KEY_PurgeWithErrorMessageGetIdCallback';
00043     const KEY_UpdateGetIdCallback = 'KEY_UpdateGetIdCallback';
00044     const KEY_TransformDependentElementsToUseLiveId = 'KEY_TransformDependentElementsToUseLiveId';
00045 
00046     /**
00047      * @var tx_version_tcemain
00048      */
00049     protected $parent;
00050 
00051     /**
00052      * @var t3lib_TCEmain
00053      */
00054     protected $tceMain;
00055 
00056     /**
00057      * @var array
00058      */
00059     protected $commandMap = array();
00060 
00061     /**
00062      * @var string
00063      */
00064     protected $workspacesSwapMode;
00065 
00066     /**
00067      * @var string
00068      */
00069     protected $workspacesChangeStageMode;
00070 
00071     /**
00072      * @var boolean
00073      */
00074     protected $workspacesConsiderReferences;
00075 
00076     /**
00077      * @var array
00078      */
00079     protected $scopes;
00080 
00081     /**
00082      * Creates this object.
00083      *
00084      * @param t3lib_TCEmain $parent
00085      * @param array $commandMap
00086      */
00087     public function __construct(tx_version_tcemain $parent, t3lib_TCEmain $tceMain, array $commandMap) {
00088         $this->setParent($parent);
00089         $this->setTceMain($tceMain);
00090         $this->set($commandMap);
00091 
00092         $this->setWorkspacesSwapMode($this->getTceMain()->BE_USER->getTSConfigVal('options.workspaces.swapMode'));
00093         $this->setWorkspacesChangeStageMode($this->getTceMain()->BE_USER->getTSConfigVal('options.workspaces.changeStageMode'));
00094         $this->setWorkspacesConsiderReferences($this->getTceMain()->BE_USER->getTSConfigVal('options.workspaces.considerReferences'));
00095 
00096         $this->constructScopes();
00097     }
00098 
00099     /**
00100      * Gets the command map.
00101      *
00102      * @return array
00103      */
00104     public function get() {
00105         return $this->commandMap;
00106     }
00107 
00108     /**
00109      * Sets the command map.
00110      *
00111      * @param array $commandMap
00112      * @return tx_version_tcemain_CommandMap
00113      */
00114     public function set(array $commandMap) {
00115         $this->commandMap = $commandMap;
00116         return $this;
00117     }
00118 
00119     /**
00120      * Gets the parent object.
00121      *
00122      * @return tx_version_tcemain
00123      */
00124     public function getParent() {
00125         return $this->parent;
00126     }
00127 
00128     /**
00129      * Sets the parent object.
00130      *
00131      * @param tx_version_tcemain $parent
00132      * @return tx_version_tcemain_CommandMap
00133      */
00134     public function setParent(tx_version_tcemain $parent) {
00135         $this->parent = $parent;
00136         return $this;
00137     }
00138 
00139     /**
00140      * Gets the parent object.
00141      *
00142      * @return t3lib_TCEmain
00143      */
00144     public function getTceMain() {
00145         return $this->tceMain;
00146     }
00147 
00148     /**
00149      * Sets the parent object.
00150      *
00151      * @param t3lib_TCEmain $parent
00152      * @return tx_version_tcemain_CommandMap
00153      */
00154     public function setTceMain(t3lib_TCEmain $tceMain) {
00155         $this->tceMain = $tceMain;
00156         return $this;
00157     }
00158 
00159     /**
00160      * Sets the workspaces swap mode
00161      * (see options.workspaces.swapMode).
00162      *
00163      * @param string $workspacesSwapMode
00164      * @return tx_version_tcemain_CommandMap
00165      */
00166     public function setWorkspacesSwapMode($workspacesSwapMode) {
00167         $this->workspacesSwapMode = (string)$workspacesSwapMode;
00168         return $this;
00169     }
00170 
00171     /**
00172      * Sets the workspaces change stage mode
00173      * see options.workspaces.changeStageMode)
00174      *
00175      * @param string $workspacesChangeStageMode
00176      * @return tx_version_tcemain_CommandMap
00177      */
00178     public function setWorkspacesChangeStageMode($workspacesChangeStageMode) {
00179         $this->workspacesChangeStageMode = (string)$workspacesChangeStageMode;
00180         return $this;
00181     }
00182 
00183     /**
00184      * Sets the workspace behaviour to automatically consider references
00185      * (see options.workspaces.considerReferences)
00186      *
00187      * @param boolean $workspacesConsiderReferences
00188      * @return tx_version_tcemain_CommandMap
00189      */
00190     public function setWorkspacesConsiderReferences($workspacesConsiderReferences) {
00191         $this->workspacesConsiderReferences = (bool)$workspacesConsiderReferences;
00192         return $this;
00193     }
00194 
00195     /**
00196      * Processes the command map.
00197      *
00198      * @return tx_version_tcemain_CommandMap
00199      */
00200     public function process() {
00201         $this->resolveWorkspacesSwapDependencies();
00202         $this->resolveWorkspacesSetStageDependencies();
00203         return $this;
00204     }
00205 
00206     /**
00207      * Resolves workspaces related dependencies for swapping/publishing of the command map.
00208      * Workspaces records that have children or (relative) parents which are versionized
00209      * but not published with this request, are removed from the command map. Otherwise
00210      * this would produce hanging record sets and lost references.
00211      *
00212      * @return void
00213      */
00214     protected function resolveWorkspacesSwapDependencies() {
00215         $scope = self::SCOPE_WorkspacesSwap;
00216         $dependency = $this->getDependencyUtility($scope);
00217 
00218         foreach ($this->commandMap as $table => $liveIdCollection) {
00219             foreach ($liveIdCollection as $liveId => $commandCollection) {
00220                 foreach ($commandCollection as $command => $properties) {
00221                     if ($command === 'version' && isset($properties['action']) && $properties['action'] === 'swap') {
00222                         if (isset($properties['swapWith']) && t3lib_div::testInt($properties['swapWith'])) {
00223                             $this->addWorkspacesSwapElements($dependency, $table, $liveId, $properties);
00224                         }
00225                     }
00226                 }
00227             }
00228         }
00229 
00230         $this->applyWorkspacesDependencies($dependency, $scope);
00231     }
00232 
00233     /**
00234      * Adds workspaces elements for swapping/publishing and takes care of the swapMode.
00235      *
00236      * @param t3lib_utility_Dependency $dependency
00237      * @param string $table
00238      * @param iteger $liveId
00239      * @param array $properties
00240      * @return void
00241      */
00242     protected function addWorkspacesSwapElements(t3lib_utility_Dependency $dependency, $table, $liveId, array $properties) {
00243         $elementList = array();
00244 
00245         // Fetch accordant elements if the swapMode is 'any' or 'pages':
00246         if ($this->workspacesSwapMode === 'any' || $this->workspacesSwapMode === 'pages' && $table === 'pages') {
00247             $elementList = $this->getParent()->findPageElementsForVersionSwap($table, $liveId, $properties['swapWith']);
00248         }
00249 
00250         foreach ($elementList as $elementTable => $elementIdArray) {
00251             foreach ($elementIdArray as $elementIds) {
00252                 $dependency->addElement(
00253                     $elementTable, $elementIds[1],
00254                     array('liveId' => $elementIds[0], 'properties' => array_merge($properties, array('swapWith' => $elementIds[1])))
00255                 );
00256             }
00257         }
00258 
00259         if (count($elementList) === 0) {
00260             $dependency->addElement(
00261                 $table, $properties['swapWith'], array('liveId' => $liveId, 'properties' => $properties)
00262             );
00263         }
00264     }
00265 
00266     /**
00267      * Resolves workspaces related dependencies for staging of the command map.
00268      * Workspaces records that have children or (relative) parents which are versionized
00269      * but not staged with this request, are removed from the command map.
00270      *
00271      * @return void
00272      */
00273     protected function resolveWorkspacesSetStageDependencies() {
00274         $scope = self::SCOPE_WorkspacesSetStage;
00275         $dependency = $this->getDependencyUtility($scope);
00276 
00277         foreach ($this->commandMap as $table => $liveIdCollection) {
00278             foreach ($liveIdCollection as $liveIdList => $commandCollection) {
00279                 foreach ($commandCollection as $command => $properties) {
00280                     if ($command === 'version' && isset($properties['action']) && $properties['action'] === 'setStage') {
00281                         if (isset($properties['stageId']) && t3lib_div::testInt($properties['stageId'])) {
00282                             $this->addWorkspacesSetStageElements($dependency, $table, $liveIdList, $properties);
00283                             $this->explodeSetStage($table, $liveIdList, $properties);
00284                         }
00285                     }
00286                 }
00287             }
00288         }
00289 
00290         $this->applyWorkspacesDependencies($dependency, $scope);
00291     }
00292 
00293     /**
00294      * Adds workspaces elements for staging and takes care of the changeStageMode.
00295      *
00296      * @param t3lib_utility_Dependency $dependency
00297      * @param string $table
00298      * @param string $liveIdList
00299      * @param array $properties
00300      * @return void
00301      */
00302     protected function addWorkspacesSetStageElements(t3lib_utility_Dependency $dependency, $table, $liveIdList, array $properties) {
00303         $liveIds = t3lib_div::trimExplode(',', $liveIdList, TRUE);
00304         $elementList = array($table => $liveIds);
00305 
00306         if (t3lib_div::inList('any,pages', $this->workspacesChangeStageMode)) {
00307             if (count($liveIds) === 1) {
00308                 $workspaceRecord = t3lib_BEfunc::getRecord($table, $liveIds[0], 't3ver_wsid');
00309                 $workspaceId = $workspaceRecord['t3ver_wsid'];
00310             } else {
00311                 $workspaceId = $this->tceMain()->BE_USER->workspace;
00312             }
00313 
00314             if ($table === 'pages') {
00315                 // Find all elements from the same ws to change stage
00316                 $this->getParent()->findRealPageIds($liveIds);
00317                 $this->getParent()->findPageElementsForVersionStageChange($liveIds, $workspaceId, $elementList);
00318             } elseif ($this->workspacesChangeStageMode === 'any') {
00319                 // Find page to change stage:
00320                 $pageIdList = array();
00321                 $this->getParent()->findPageIdsForVersionStateChange($table, $liveIds, $workspaceId, $pageIdList, $elementList);
00322                 // Find other elements from the same ws to change stage:
00323                 $this->getParent()->findPageElementsForVersionStageChange($pageIdList, $workspaceId, $elementList);
00324             }
00325         }
00326 
00327         foreach ($elementList as $elementTable => $elementIds) {
00328             foreach($elementIds as $elementId) {
00329                 $dependency->addElement(
00330                     $elementTable, $elementId,
00331                     array('properties' => $properties)
00332                 );
00333             }
00334         }
00335     }
00336 
00337     /**
00338      * Explodes id-lists in the command map for staging actions.
00339      *
00340      * @throws RuntimeException
00341      * @param string $table
00342      * @param string $liveIdList
00343      * @param array $properties
00344      * @return void
00345      */
00346     protected function explodeSetStage($table, $liveIdList, array $properties) {
00347         $extractedCommandMap = array();
00348         $liveIds = t3lib_div::trimExplode(',', $liveIdList, TRUE);
00349 
00350         if (count($liveIds) > 1) {
00351             foreach ($liveIds as $liveId) {
00352                 if (isset($this->commandMap[$table][$liveId]['version'])) {
00353                     throw new RuntimeException('Command map for [' . $table . '][' . $liveId . '][version] was already set.', 1289391048);
00354                 }
00355 
00356                 $extractedCommandMap[$table][$liveId]['version'] = $properties;
00357             }
00358 
00359             $this->remove($table, $liveIdList, 'version');
00360             $this->mergeToBottom($extractedCommandMap);
00361         }
00362     }
00363 
00364     /**
00365      * Applies the workspaces dependencies and removes incomplete structures or automatically
00366      * completes them, depending on the options.workspaces.considerReferences setting
00367      *
00368      * @param t3lib_utility_Dependency $dependency
00369      * @param string $scope
00370      * @return void
00371      */
00372     protected function applyWorkspacesDependencies(t3lib_utility_Dependency $dependency, $scope) {
00373         $transformDependentElementsToUseLiveId = $this->getScopeData($scope, self::KEY_TransformDependentElementsToUseLiveId);
00374 
00375         $elementsToBeVersionized = $dependency->getElements();
00376         if ($transformDependentElementsToUseLiveId) {
00377             $elementsToBeVersionized = $this->transformDependentElementsToUseLiveId($elementsToBeVersionized);
00378         }
00379 
00380         $outerMostParents = $dependency->getOuterMostParents();
00381         /** @var $outerMostParent t3lib_utility_Dependency_Element */
00382         foreach ($outerMostParents as $outerMostParent) {
00383             $dependentElements = $dependency->getNestedElements($outerMostParent);
00384             if ($transformDependentElementsToUseLiveId) {
00385                 $dependentElements = $this->transformDependentElementsToUseLiveId($dependentElements);
00386             }
00387 
00388             $intersectingElements = array_intersect_key($dependentElements, $elementsToBeVersionized);
00389 
00390             if (count($intersectingElements) > 0) {
00391                 // If at least one element intersects but not all, throw away all elements of the depdendent structure:
00392                 if (count($intersectingElements) !== count($dependentElements) && $this->workspacesConsiderReferences === FALSE) {
00393                     $this->purgeWithErrorMessage($intersectingElements, $scope);
00394                 // If everything is fine or references shall be considered automatically:
00395                 } else {
00396                     $this->update(current($intersectingElements), $dependentElements, $scope);
00397                 }
00398             }
00399         }
00400     }
00401 
00402     /**
00403      * Purges incomplete structures from the command map and triggers an error message.
00404      *
00405      * @param array $elements
00406      * @param string $scope
00407      * @return void
00408      */
00409     protected function purgeWithErrorMessage(array $elements, $scope) {
00410         /** @var $dependentElement t3lib_utility_Dependency_Element */
00411         foreach ($elements as $element) {
00412             $table = $element->getTable();
00413             $id = $this->processCallback(
00414                 $this->getScopeData($scope, self::KEY_PurgeWithErrorMessageGetIdCallback),
00415                 array($element)
00416             );
00417 
00418             $this->remove($table, $id, 'version');
00419             $this->getTceMain()->log(
00420                 $table, $id,
00421                 5, 0, 1,
00422                 $this->getScopeData($scope, self::KEY_ScopeErrorMessage),
00423                 $this->getScopeData($scope, self::KEY_ScopeErrorCode),
00424                 array(
00425                     t3lib_BEfunc::getRecordTitle($table, t3lib_BEfunc::getRecord($table, $id)),
00426                     $table, $id
00427                 )
00428             );
00429         }
00430     }
00431 
00432     /**
00433      * Updates the command map accordant to valid structures and takes care of the correct order.
00434      *
00435      * @param t3lib_utility_Dependency_Element $intersectingElement
00436      * @param array $elements
00437      * @param string $scope
00438      * @return void
00439      */
00440     protected function update(t3lib_utility_Dependency_Element $intersectingElement, array $elements, $scope) {
00441         $orderedCommandMap = array();
00442 
00443         $commonProperties = $this->processCallback(
00444             $this->getScopeData($scope, self::KEY_GetCommonPropertiesCallback),
00445             array($intersectingElement)
00446         );
00447 
00448         /** @var $dependentElement t3lib_utility_Dependency_Element */
00449         foreach ($elements as $element) {
00450             $table = $element->getTable();
00451             $id = $this->processCallback(
00452                 $this->getScopeData($scope, self::KEY_UpdateGetIdCallback),
00453                 array($element)
00454             );
00455 
00456             $this->remove($table, $id, 'version');
00457             $orderedCommandMap[$table][$id]['version'] = array_merge(
00458                 $commonProperties,
00459                 $this->processCallback(
00460                     $this->getScopeData($scope, self::KEY_GetElementPropertiesCallback),
00461                     array($element)
00462                 )
00463             );
00464         }
00465 
00466         // Ensure that ordered command map is on top of the command map:
00467         $this->mergeToTop($orderedCommandMap);
00468     }
00469 
00470     /**
00471      * Merges command map elements to the top of the current command map..
00472      *
00473      * @param array $commandMap
00474      * @return void
00475      */
00476     protected function mergeToTop(array $commandMap) {
00477         $this->commandMap = t3lib_div::array_merge_recursive_overrule($commandMap, $this->commandMap);
00478     }
00479 
00480     /**
00481      * Merges command map elements to the bottom of the current command map.
00482      *
00483      * @param array $commandMap
00484      * @return void
00485      */
00486     protected function mergeToBottom(array $commandMap) {
00487         $this->commandMap = t3lib_div::array_merge_recursive_overrule($this->commandMap, $commandMap);
00488     }
00489 
00490     /**
00491      * Removes an element from the command map.
00492      *
00493      * @param string $table
00494      * @param string $id
00495      * @param string $command (optional)
00496      * @return void
00497      */
00498     protected function remove($table, $id, $command = NULL) {
00499         if (is_string($command)) {
00500             unset($this->commandMap[$table][$id][$command]);
00501         } else {
00502             unset($this->commandMap[$table][$id]);
00503         }
00504     }
00505 
00506     /**
00507      * Callback to get the liveId of an dependent element.
00508      *
00509      * @param t3lib_utility_Dependency_Element $element
00510      * @return integer
00511      */
00512     protected function getElementLiveIdCallback(t3lib_utility_Dependency_Element $element) {
00513         return $element->getDataValue('liveId');
00514     }
00515 
00516     /**
00517      * Callback to get the real id of an dependent element.
00518      *
00519      * @param t3lib_utility_Dependency_Element $element
00520      * @return integer
00521      */
00522     protected function getElementIdCallback(t3lib_utility_Dependency_Element $element) {
00523         return $element->getId();
00524     }
00525 
00526     /**
00527      * Callback to get the specific properties of a dependent element for swapping/publishing.
00528      *
00529      * @param t3lib_utility_Dependency_Element $element
00530      * @return array
00531      */
00532     protected function getElementSwapPropertiesCallback(t3lib_utility_Dependency_Element $element) {
00533         return array(
00534             'swapWith' => $element->getId(),
00535         );
00536     }
00537 
00538     /**
00539      * Callback to get common properties of dependent elements for swapping/publishing.
00540      *
00541      * @param t3lib_utility_Dependency_Element $element
00542      * @return array
00543      */
00544     protected function getCommonSwapPropertiesCallback(t3lib_utility_Dependency_Element $element) {
00545         $commonSwapProperties = array();
00546 
00547         $elementProperties = $element->getDataValue('properties');
00548         if (isset($elementProperties['action'])) {
00549             $commonSwapProperties['action'] = $elementProperties['action'];
00550         }
00551         if (isset($elementProperties['swapIntoWS'])) {
00552             $commonSwapProperties['swapIntoWS'] = $elementProperties['swapIntoWS'];
00553         }
00554 
00555         return $commonSwapProperties;
00556     }
00557 
00558     /**
00559      * Callback to get the specific properties of a dependent element for staging.
00560      *
00561      * @param t3lib_utility_Dependency_Element $element
00562      * @return array
00563      */
00564     protected function getElementSetStagePropertiesCallback(t3lib_utility_Dependency_Element $element) {
00565         return $this->getCommonSetStagePropertiesCallback($element);
00566     }
00567 
00568     /**
00569      * Callback to get common properties of dependent elements for staging.
00570      *
00571      * @param t3lib_utility_Dependency_Element $element
00572      * @return array
00573      */
00574     protected function getCommonSetStagePropertiesCallback(t3lib_utility_Dependency_Element $element) {
00575         $commonSetStageProperties = array();
00576 
00577         $elementProperties = $element->getDataValue('properties');
00578         if (isset($elementProperties['stageId'])) {
00579             $commonSetStageProperties['stageId'] = $elementProperties['stageId'];
00580         }
00581         if (isset($elementProperties['comment'])) {
00582             $commonSetStageProperties['comment'] = $elementProperties['comment'];
00583         }
00584 
00585         return $commonSetStageProperties;
00586     }
00587 
00588 
00589     /**
00590      * Gets an instance of the depency resolver utility.
00591      *
00592      * @return t3lib_utility_Dependency
00593      */
00594     protected function getDependencyUtility($scope) {
00595 
00596         /** @var $dependency t3lib_utility_Dependency */
00597         $dependency = t3lib_div::makeInstance('t3lib_utility_Dependency');
00598         $dependency->setOuterMostParentsRequireReferences(TRUE);
00599 
00600         if ($this->getScopeData($scope, self::KEY_ElementConstructCallback)) {
00601             $dependency->setEventCallback(
00602                 t3lib_utility_Dependency_Element::EVENT_Construct,
00603                 $this->getDependencyCallback($this->getScopeData($scope, self::KEY_ElementConstructCallback))
00604             );
00605         }
00606         if ($this->getScopeData($scope, self::KEY_ElementCreateChildReferenceCallback)) {
00607             $dependency->setEventCallback(
00608                 t3lib_utility_Dependency_Element::EVENT_CreateChildReference,
00609                 $this->getDependencyCallback($this->getScopeData($scope, self::KEY_ElementCreateChildReferenceCallback))
00610             );
00611         }
00612         if ($this->getScopeData($scope, self::KEY_ElementCreateParentReferenceCallback)) {
00613             $dependency->setEventCallback(
00614                 t3lib_utility_Dependency_Element::EVENT_CreateParentReference,
00615                 $this->getDependencyCallback($this->getScopeData($scope, self::KEY_ElementCreateParentReferenceCallback))
00616             );
00617         }
00618 
00619         return $dependency;
00620     }
00621 
00622     /**
00623      * Callback to determine whether a new child reference shall be considered in the dependency resolver utility.
00624      *
00625      * @param array $callerArguments
00626      * @param array $targetArgument
00627      * @param t3lib_utility_Dependency_Element $caller
00628      * @param string $eventName
00629      * @return string Skip response (if required)
00630      */
00631     public function createNewDependentElementChildReferenceCallback(array $callerArguments, array $targetArgument, t3lib_utility_Dependency_Element $caller, $eventName) {
00632         /** @var $reference t3lib_utility_Dependency_Reference */
00633         $reference = $callerArguments['reference'];
00634 
00635         $fieldCOnfiguration = t3lib_BEfunc::getTcaFieldConfiguration($caller->getTable(), $reference->getField());
00636 
00637         if (!$fieldCOnfiguration || !t3lib_div::inList('field,list', $this->getTceMain()->getInlineFieldType($fieldCOnfiguration))) {
00638             return t3lib_utility_Dependency_Element::RESPONSE_Skip;
00639         }
00640     }
00641 
00642     /**
00643      * Callback to determine whether a new parent reference shall be considered in the dependency resolver utility.
00644      *
00645      * @param array $callerArguments
00646      * @param array $targetArgument
00647      * @param t3lib_utility_Dependency_Element $caller
00648      * @param string $eventName
00649      * @return string Skip response (if required)
00650      */
00651     public function createNewDependentElementParentReferenceCallback(array $callerArguments, array $targetArgument, t3lib_utility_Dependency_Element $caller, $eventName) {
00652         /** @var $reference t3lib_utility_Dependency_Reference */
00653         $reference = $callerArguments['reference'];
00654 
00655         $fieldCOnfiguration = t3lib_BEfunc::getTcaFieldConfiguration($reference->getElement()->getTable(), $reference->getField());
00656 
00657         if (!$fieldCOnfiguration || !t3lib_div::inList('field,list', $this->getTceMain()->getInlineFieldType($fieldCOnfiguration))) {
00658             return t3lib_utility_Dependency_Element::RESPONSE_Skip;
00659         }
00660     }
00661 
00662     /**
00663      * Callback to add additional data to new elements created in the dependency resolver utility.
00664      *
00665      * @param t3lib_utility_Dependency_Element $caller
00666      * @param array $callerArguments
00667      * @param array $targetArgument
00668      * @return void
00669      */
00670     public function createNewDependentElementCallback(array $callerArguments, array $targetArgument, t3lib_utility_Dependency_Element $caller) {
00671         if ($caller->hasDataValue('liveId') === FALSE) {
00672             $liveId = t3lib_BEfunc::getLiveVersionIdOfRecord($caller->getTable(), $caller->getId());
00673             if (is_null($liveId) === FALSE) {
00674                 $caller->setDataValue('liveId', $liveId);
00675             }
00676         }
00677     }
00678 
00679     /**
00680      * Transforms dependent elements to use the liveId as array key.
00681      *
00682      * @param array $elements Depedent elements, each of type t3lib_utility_Dependency_Element
00683      * @return array
00684      */
00685     protected function transformDependentElementsToUseLiveId(array $elements) {
00686         $transformedElements = array();
00687 
00688         /** @var $element t3lib_utility_Dependency_Element */
00689         foreach ($elements as $element) {
00690             $elementName = t3lib_utility_Dependency_Element::getIdentifier(
00691                 $element->getTable(), $element->getDataValue('liveId')
00692             );
00693             $transformedElements[$elementName] = $element;
00694         }
00695 
00696         return $transformedElements;
00697     }
00698 
00699     /**
00700      * Constructs the scope settings.
00701      * Currently the scopes for swapping/publishing and staging are available.
00702      *
00703      * @return void
00704      */
00705     protected function constructScopes() {
00706         $this->scopes = array(
00707             self::SCOPE_WorkspacesSwap => array(
00708                 self::KEY_ScopeErrorMessage => 'Record "%s" (%s:%s) cannot be swapped or published independently, because it is related to other new or modified records.',
00709                 self::KEY_ScopeErrorCode => 1288283630,
00710                 self::KEY_GetElementPropertiesCallback => 'getElementSwapPropertiesCallback',
00711                 self::KEY_GetCommonPropertiesCallback => 'getCommonSwapPropertiesCallback',
00712                 self::KEY_ElementConstructCallback => 'createNewDependentElementCallback',
00713                 self::KEY_ElementCreateChildReferenceCallback => 'createNewDependentElementChildReferenceCallback',
00714                 self::KEY_ElementCreateParentReferenceCallback => 'createNewDependentElementParentReferenceCallback',
00715                 self::KEY_PurgeWithErrorMessageGetIdCallback => 'getElementLiveIdCallback',
00716                 self::KEY_UpdateGetIdCallback => 'getElementLiveIdCallback',
00717                 self::KEY_TransformDependentElementsToUseLiveId => TRUE,
00718             ),
00719             self::SCOPE_WorkspacesSetStage => array(
00720                 self::KEY_ScopeErrorMessage => 'Record "%s" (%s:%s) cannot be sent to another stage independently, because it is related to other new or modified records.',
00721                 self::KEY_ScopeErrorCode => 1289342524,
00722                 self::KEY_GetElementPropertiesCallback => 'getElementSetStagePropertiesCallback',
00723                 self::KEY_GetCommonPropertiesCallback => 'getCommonSetStagePropertiesCallback',
00724                 self::KEY_ElementConstructCallback => NULL,
00725                 self::KEY_ElementCreateChildReferenceCallback => 'createNewDependentElementChildReferenceCallback',
00726                 self::KEY_ElementCreateParentReferenceCallback => 'createNewDependentElementParentReferenceCallback',
00727                 self::KEY_PurgeWithErrorMessageGetIdCallback => 'getElementIdCallback',
00728                 self::KEY_UpdateGetIdCallback => 'getElementIdCallback',
00729                 self::KEY_TransformDependentElementsToUseLiveId => FALSE,
00730             ),
00731         );
00732     }
00733 
00734     /**
00735      * Gets data for a particular scope.
00736      *
00737      * @throws RuntimeException
00738      * @param string $scope
00739      * @param string $key
00740      * @return string
00741      */
00742     protected function getScopeData($scope, $key) {
00743         if (!isset($this->scopes[$scope])) {
00744             throw new RuntimeException('Scope "' . $scope . '" is not defined.', 1289342187);
00745         }
00746 
00747         return $this->scopes[$scope][$key];
00748     }
00749 
00750     /**
00751      * Gets a new callback to be used in the dependency resolver utility.
00752      *
00753      * @param string $callbackMethod
00754      * @param array $targetArguments
00755      * @return t3lib_utility_Dependency_Callback
00756      */
00757     protected function getDependencyCallback($method, array $targetArguments = array()) {
00758         return t3lib_div::makeInstance('t3lib_utility_Dependency_Callback', $this, $method, $targetArguments);
00759     }
00760 
00761     /**
00762      * Processes a local callback inside this object.
00763      *
00764      * @param string $method
00765      * @param array $callbackArguments
00766      * @return mixed
00767      */
00768     protected function processCallback($method, array $callbackArguments) {
00769         return call_user_func_array(array($this, $method), $callbackArguments);
00770     }
00771 }
00772 
00773 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/version/class.tx_version_tcemain_commandmap.php'])) {
00774     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/version/class.tx_version_tcemain_commandmap.php']);
00775 }
00776 ?>