/** * Creates a new version of a page including content and possible subpages. * * @param int $uid Page uid to create new version of. * @param string $label Version label * @param int $versionizeTree Indicating "treeLevel" - "page" (0) or "branch" (>=1) ["element" type must call versionizeRecord() directly] * @param DataHandler $tcemainObj TCEmain object * @return void * @see copyPages() */ protected function versionizePages($uid, $label, $versionizeTree, DataHandler $tcemainObj) { $uid = (int) $uid; // returns the branch $brExist = $tcemainObj->doesBranchExist('', $uid, $tcemainObj->pMap['show'], 1); // Checks if we had permissions if ((int) $brExist === -1) { $tcemainObj->newlog('Could not read all subpages to versionize.', 1); return; } // Make list of tables that should come along with a new version of the page: $verTablesArray = array(); $allTables = array_keys($GLOBALS['TCA']); foreach ($allTables as $tableName) { if ($tableName != 'pages' && ($versionizeTree > 0 || $GLOBALS['TCA'][$tableName]['ctrl']['versioning_followPages'])) { $verTablesArray[] = $tableName; } } // Remove the possible inline child tables from the tables to be versioniozed automatically: $verTablesArray = array_diff($verTablesArray, $this->getPossibleInlineChildTablesOfParentTable('pages')); // Begin to copy pages if we're allowed to: if ($versionizeTree !== -1) { $tcemainObj->newlog('Versioning type "' . $versionizeTree . '" was not allowed in workspace', 1); return; } // Versionize this page: $theNewRootID = $tcemainObj->versionizeRecord('pages', $uid, $label, FALSE, $versionizeTree); if (!$theNewRootID) { $tcemainObj->newlog('The root version could not be created!', 1); return; } $this->rawCopyPageContent($uid, $theNewRootID, $verTablesArray, $tcemainObj); // If we're going to copy recursively...: if ($versionizeTree > 0) { // Get ALL subpages to copy (read permissions respected - they should NOT be...): $CPtable = $tcemainObj->int_pageTreeInfo(array(), $uid, (int) $versionizeTree, $theNewRootID); // Now copying the subpages foreach ($CPtable as $thePageUid => $thePagePid) { $newPid = $tcemainObj->copyMappingArray['pages'][$thePagePid]; if (isset($newPid)) { $theNewRootID = $tcemainObj->copyRecord_raw('pages', $thePageUid, $newPid); $this->rawCopyPageContent($thePageUid, $theNewRootID, $verTablesArray, $tcemainObj); } else { $tcemainObj->newlog('Something went wrong during copying branch (for versioning)', 1); break; } } } }
/** * Hook for \TYPO3\CMS\Core\DataHandling\DataHandler::moveRecord that cares about * moving records that are *not* in the live workspace * * @param string $table the table of the record * @param int $uid the ID of the record * @param int $destPid Position to move to: $destPid: >=0 then it points to * @param array $propArr Record properties, like header and pid (includes workspace overlay) * @param array $moveRec Record properties, like header and pid (without workspace overlay) * @param int $resolvedPid The final page ID of the record * @param bool $recordWasMoved can be set so that other hooks or * @param DataHandler $dataHandler * @return void */ public function moveRecord($table, $uid, $destPid, array $propArr, array $moveRec, $resolvedPid, &$recordWasMoved, DataHandler $dataHandler) { // Only do something in Draft workspace if ($dataHandler->BE_USER->workspace === 0) { return; } if ($destPid < 0) { // Fetch move placeholder, since it might point to a new page in the current workspace $movePlaceHolder = BackendUtility::getMovePlaceholder($table, abs($destPid), 'uid,pid'); if ($movePlaceHolder !== false) { $resolvedPid = $movePlaceHolder['pid']; } } $recordWasMoved = true; $moveRecVersionState = VersionState::cast($moveRec['t3ver_state']); // Get workspace version of the source record, if any: $WSversion = BackendUtility::getWorkspaceVersionOfRecord($dataHandler->BE_USER->workspace, $table, $uid, 'uid,t3ver_oid'); // Handle move-placeholders if the current record is not one already if (BackendUtility::isTableWorkspaceEnabled($table) && !$moveRecVersionState->equals(VersionState::MOVE_PLACEHOLDER)) { // Create version of record first, if it does not exist if (empty($WSversion['uid'])) { $dataHandler->versionizeRecord($table, $uid, 'MovePointer'); $WSversion = BackendUtility::getWorkspaceVersionOfRecord($dataHandler->BE_USER->workspace, $table, $uid, 'uid,t3ver_oid'); $this->moveRecord_processFields($dataHandler, $resolvedPid, $table, $uid); // If the record has been versioned before (e.g. cascaded parent-child structure), create only the move-placeholders } elseif ($dataHandler->isRecordCopied($table, $uid) && (int) $dataHandler->copyMappingArray[$table][$uid] === (int) $WSversion['uid']) { $this->moveRecord_processFields($dataHandler, $resolvedPid, $table, $uid); } } // Check workspace permissions: $workspaceAccessBlocked = []; // Element was in "New/Deleted/Moved" so it can be moved... $recIsNewVersion = $moveRecVersionState->indicatesPlaceholder(); $destRes = $dataHandler->BE_USER->workspaceAllowLiveRecordsInPID($resolvedPid, $table); $canMoveRecord = $recIsNewVersion || BackendUtility::isTableWorkspaceEnabled($table); // Workspace source check: if (!$recIsNewVersion) { $errorCode = $dataHandler->BE_USER->workspaceCannotEditRecord($table, $WSversion['uid'] ? $WSversion['uid'] : $uid); if ($errorCode) { $workspaceAccessBlocked['src1'] = 'Record could not be edited in workspace: ' . $errorCode . ' '; } elseif (!$canMoveRecord && $dataHandler->BE_USER->workspaceAllowLiveRecordsInPID($moveRec['pid'], $table) <= 0) { $workspaceAccessBlocked['src2'] = 'Could not remove record from table "' . $table . '" from its page "' . $moveRec['pid'] . '" '; } } // Workspace destination check: // All records can be inserted if $destRes is greater than zero. // Only new versions can be inserted if $destRes is FALSE. // NO RECORDS can be inserted if $destRes is negative which indicates a stage // not allowed for use. If "versioningWS" is version 2, moving can take place of versions. // since TYPO3 CMS 7, version2 is the default and the only option if (!($destRes > 0 || $canMoveRecord && !$destRes)) { $workspaceAccessBlocked['dest1'] = 'Could not insert record from table "' . $table . '" in destination PID "' . $resolvedPid . '" '; } elseif ($destRes == 1 && $WSversion['uid']) { $workspaceAccessBlocked['dest2'] = 'Could not insert other versions in destination PID '; } if (empty($workspaceAccessBlocked)) { // If the move operation is done on a versioned record, which is // NOT new/deleted placeholder and versioningWS is in version 2, then... // since TYPO3 CMS 7, version2 is the default and the only option if ($WSversion['uid'] && !$recIsNewVersion && BackendUtility::isTableWorkspaceEnabled($table)) { $this->moveRecord_wsPlaceholders($table, $uid, $destPid, $WSversion['uid'], $dataHandler); } else { // moving not needed, just behave like in live workspace $recordWasMoved = false; } } else { $dataHandler->newlog('Move attempt failed due to workspace restrictions: ' . implode(' // ', $workspaceAccessBlocked), 1); } }