Commit c22b8a428810cbb71dfa274befb34555c9879860
1 parent
0cf52d8f
Brad Shuttleworth 2006-02-09 add copy action.
Brad Shuttleworth 2006-02-09 fix for KTS-352
Brad Shuttleworth 2006-02-09 - first pass of copy support.
git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4890 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
8 changed files
with
303 additions
and
2 deletions
browse.php
| ... | ... | @@ -155,6 +155,10 @@ class BrowseDispatcher extends KTStandardDispatcher { |
| 155 | 155 | exit(0); |
| 156 | 156 | } |
| 157 | 157 | $this->oQuery = new ValueBrowseQuery($oField, $oValue); |
| 158 | + $this->resultURL = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fBrowseMode=lookup_value&fField=%d&fValue=%d", $field, $value)); | |
| 159 | + $this->aBreadcrumbs[] = array('name' => _('Lookup Values'), 'url' => KTUtil::addQueryString($_SERVER['PHP_SELF'], 'action=selectField')); | |
| 160 | + $this->aBreadcrumbs[] = array('name' => $oField->getName(), 'url' => KTUtil::addQueryString($_SERVER['PHP_SELF'], 'action=selectLookup&fField=' . $oField->getId())); | |
| 161 | + $this->aBreadcrumbs[] = array('name' => $oField->getName(), 'url' => KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fBrowseMode=lookup_value&fField=%d&fValue=%d", $field, $value))); | |
| 158 | 162 | } else if ($this->browse_mode == 'document_type') { |
| 159 | 163 | $this->editable = false; |
| 160 | 164 | // FIXME implement document_type browsing. |
| ... | ... | @@ -168,7 +172,8 @@ class BrowseDispatcher extends KTStandardDispatcher { |
| 168 | 172 | $this->oQuery = new TypeBrowseQuery($oDocType); |
| 169 | 173 | |
| 170 | 174 | // FIXME probably want to redirect to self + action=selectType |
| 171 | - $this->aBreadcrumbs[] = array('name' => _('Document Types')); | |
| 175 | + $this->aBreadcrumbs[] = array('name' => _('Document Types'), 'url' => KTUtil::addQueryString($_SERVER['PHP_SELF'], 'action=selectType')); | |
| 176 | + $this->aBreadcrumbs[] = array('name' => $oDocType->getName(), 'url' => KTUtil::addQueryString($_SERVER['PHP_SELF'], 'fBrowseMode=document_type&fType=' . $oDocType->getId())); | |
| 172 | 177 | |
| 173 | 178 | $this->resultURL = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fType=%s&fBrowseMode=document_type", $doctype));; |
| 174 | 179 | } else { | ... | ... |
lib/documentmanagement/documentmetadataversion.inc.php
| ... | ... | @@ -59,6 +59,7 @@ class KTDocumentMetadataVersion extends KTEntity { |
| 59 | 59 | function getMetadataVersion() { return $this->iMetadataVersion; } |
| 60 | 60 | function setMetadataVersion($iNewValue) { $this->iMetadataVersion = $iNewValue; } |
| 61 | 61 | function getContentVersionId() { return $this->iContentVersionId; } |
| 62 | + function setContentVersionId($iNewValue) { $this->iContentVersionId = $iNewValue; } | |
| 62 | 63 | function setContentVersion($iNewValue) { $this->iContentVersion = $iNewValue; } |
| 63 | 64 | function getDocumentTypeId() { return $this->iDocumentTypeId; } |
| 64 | 65 | function setDocumentTypeId($iNewValue) { $this->iDocumentTypeId = $iNewValue; } | ... | ... |
lib/documentmanagement/documentutil.inc.php
| ... | ... | @@ -627,6 +627,7 @@ class KTDocumentUtil { |
| 627 | 627 | KTDocumentUtil::updateSearchableText($oDocument); |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | + | |
| 630 | 631 | function canBeMoved($oDocument) { |
| 631 | 632 | if ($oDocument->getIsCheckedOut()) { |
| 632 | 633 | return false; |
| ... | ... | @@ -636,6 +637,78 @@ class KTDocumentUtil { |
| 636 | 637 | } |
| 637 | 638 | return true; |
| 638 | 639 | } |
| 640 | + | |
| 641 | + | |
| 642 | + function copy($oDocument, $oDestinationFolder) { | |
| 643 | + // 1. generate a new triad of content, metadata and core objects. | |
| 644 | + // 2. update the storage path. | |
| 645 | + | |
| 646 | + | |
| 647 | + // grab the "source "data | |
| 648 | + $sTable = KTUtil::getTableName('documents'); | |
| 649 | + $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?'; | |
| 650 | + $aParams = array($oDocument->getId()); | |
| 651 | + $aCoreRow = DBUtil::getOneResult(array($sQuery, $aParams)); | |
| 652 | + unset($aCoreRow['id']); | |
| 653 | + | |
| 654 | + $aCoreRow['folder_id'] = $oDestinationFolder->getId(); // new location. | |
| 655 | + $id = DBUtil::autoInsert($sTable, $aCoreRow); | |
| 656 | + if (PEAR::isError($id)) { return $id; } | |
| 657 | + // we still have a bogus md_version, but integrity holds, so fix it now. | |
| 658 | + $oCore = KTDocumentCore::get($id); | |
| 659 | + | |
| 660 | + $sTable = KTUtil::getTableName('document_metadata_version'); | |
| 661 | + $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?'; | |
| 662 | + $aParams = array($oDocument->getMetadataVersionId()); | |
| 663 | + $aMDRow = DBUtil::getOneResult(array($sQuery, $aParams)); | |
| 664 | + unset($aMDRow['id']); | |
| 665 | + $aMDRow['document_id'] = $oCore->getId(); | |
| 666 | + $id = DBUtil::autoInsert($sTable, $aMDRow); | |
| 667 | + if (PEAR::isError($id)) { return $id; } | |
| 668 | + $oCore->setMetadataVersionId($id); | |
| 669 | + $oMDV = KTDocumentMetadataVersion::get($id); | |
| 670 | + | |
| 671 | + $sTable = KTUtil::getTableName('document_content_version'); | |
| 672 | + $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?'; | |
| 673 | + $aParams = array($oDocument->_oDocumentContentVersion->getId()); | |
| 674 | + $aContentRow = DBUtil::getOneResult(array($sQuery, $aParams)); | |
| 675 | + unset($aContentRow['id']); | |
| 676 | + $aContentRow['document_id'] = $oCore->getId(); | |
| 677 | + $id = DBUtil::autoInsert($sTable, $aContentRow); | |
| 678 | + if (PEAR::isError($id)) { return $id; } | |
| 679 | + $oMDV->setContentVersionId($id); | |
| 680 | + | |
| 681 | + $res = $oCore->update(); | |
| 682 | + if (PEAR::isError($res)) { return $res; } | |
| 683 | + $res = $oMDV->update(); | |
| 684 | + if (PEAR::isError($res)) { return $res; } | |
| 685 | + | |
| 686 | + // now, we have a semi-sane document object. get it. | |
| 687 | + $oNewDocument = Document::get($oCore->getId()); | |
| 688 | + | |
| 689 | + // copy the metadata from old to new. | |
| 690 | + $res = KTDocumentUtil::copyMetadata($oNewDocument, $oDocument->getMetadataVersionId()); | |
| 691 | + if (PEAR::isError($res)) { return $res; } | |
| 692 | + | |
| 693 | + // finally, copy the actual file. | |
| 694 | + $oStorage =& KTStorageManagerUtil::getSingleton(); | |
| 695 | + $res = $oStorage->copy($oDocument, $oNewDocument); | |
| 696 | + | |
| 697 | + | |
| 698 | + $oOriginalFolder = Folder::get($oDocument->getFolderId()); | |
| 699 | + $iOriginalFolderPermissionObjectId = $oOriginalFolder->getPermissionObjectId(); | |
| 700 | + $iDocumentPermissionObjectId = $oDocument->getPermissionObjectId(); | |
| 701 | + | |
| 702 | + if ($iDocumentPermissionObjectId === $iOriginalFolderPermissionObjectId) { | |
| 703 | + $oNewDocument->setPermissionObjectId($oDestinationFolder->getPermissionObjectId()); | |
| 704 | + } | |
| 705 | + | |
| 706 | + $res = $oNewDocument->update(); | |
| 707 | + if (PEAR::isError($res)) { return $res; } | |
| 708 | + | |
| 709 | + return $oNewDocument; | |
| 710 | + } | |
| 711 | + | |
| 639 | 712 | } |
| 640 | 713 | |
| 641 | 714 | class KTMetadataValidationError extends PEAR_Error { | ... | ... |
lib/storage/ondiskpathstoragemanager.inc.php
| ... | ... | @@ -239,7 +239,27 @@ class KTOnDiskPathStorageManager extends KTStorageManager { |
| 239 | 239 | return KTUtil::moveDirectory($sSrc, $sDst); |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | - | |
| 242 | + /** | |
| 243 | + * Perform any storage changes necessary to account for a copied | |
| 244 | + * document object. | |
| 245 | + */ | |
| 246 | + function copy($oSrcDocument, &$oNewDocument) { | |
| 247 | + // we get the Folder object | |
| 248 | + $oVersion = $oNewDocument->_oDocumentContentVersion; | |
| 249 | + $oConfig =& KTConfig::getSingleton(); | |
| 250 | + $sDocumentRoot = $oConfig->get('urls/documentRoot'); | |
| 251 | + | |
| 252 | + $sOldPath = sprintf("%s/%s-%s", KTDocumentCore::_generateFolderPath($oSrcDocument->getFolderID()), $oSrcDocument->_oDocumentContentVersion->getId(), $oSrcDocument->_oDocumentContentVersion->getFileName()); | |
| 253 | + $sNewPath = sprintf("%s/%s-%s", KTDocumentCore::_generateFolderPath($oNewDocument->getFolderID()), $oNewDocument->_oDocumentContentVersion->getId(), $oNewDocument->_oDocumentContentVersion->getFileName()); | |
| 254 | + $sFullOldPath = sprintf("%s/%s", $sDocumentRoot, $sOldPath); | |
| 255 | + $sFullNewPath = sprintf("%s/%s", $sDocumentRoot, $sNewPath); | |
| 256 | + | |
| 257 | + $res = KTUtil::copyFile($sFullOldPath, $sFullNewPath); | |
| 258 | + if (PEAR::isError($res)) { return $res; } | |
| 259 | + $oVersion->setStoragePath($sNewPath); | |
| 260 | + $oVersion->update(); | |
| 261 | + } | |
| 262 | + | |
| 243 | 263 | /** |
| 244 | 264 | * Deletes a document- moves it to the Deleted/ folder |
| 245 | 265 | * | ... | ... |
lib/storage/storagemanager.inc.php
| ... | ... | @@ -67,6 +67,14 @@ class KTStorageManager { |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | /** |
| 70 | + * Perform any storage changes necessary to account for a copied | |
| 71 | + * document object. | |
| 72 | + */ | |
| 73 | + function copy ($oSrcDocument, &$oNewDocument) { | |
| 74 | + return PEAR::raiseError("Not implemented"); | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 70 | 78 | * Performs any storage changes necessary to account for the |
| 71 | 79 | * document being marked as deleted. |
| 72 | 80 | */ | ... | ... |
lib/util/ktutil.inc
| ... | ... | @@ -318,6 +318,33 @@ class KTUtil { |
| 318 | 318 | } |
| 319 | 319 | } |
| 320 | 320 | // }}} |
| 321 | + | |
| 322 | + // {{{ copyFile | |
| 323 | + function copyFile ($sSrc, $sDst) { | |
| 324 | + // Only 4.3.3 and above allow us to use rename across partitions | |
| 325 | + // on Unix-like systems. | |
| 326 | + if (OS_UNIX) { | |
| 327 | + $aSrcStat = stat($sSrc); | |
| 328 | + if ($aSrcStat === false) { | |
| 329 | + return PEAR::raiseError("Couldn't stat source file: $sSrc"); | |
| 330 | + } | |
| 331 | + $aDstStat = stat(dirname($sDst)); | |
| 332 | + if ($aDstStat === false) { | |
| 333 | + return PEAR::raiseError("Couldn't stat destination location: $sDst"); | |
| 334 | + } | |
| 335 | + | |
| 336 | + $res = @copy($sSrc, $sDst); | |
| 337 | + if ($res === false) { | |
| 338 | + return PEAR::raiseError("Could not copy to destination: $sDst"); | |
| 339 | + } | |
| 340 | + } else { | |
| 341 | + $res = @copy($sSrc, $sDst); | |
| 342 | + if ($res === false) { | |
| 343 | + return PEAR::raiseError("Could not copy to destination: $sDst"); | |
| 344 | + } | |
| 345 | + } | |
| 346 | + } | |
| 347 | + // }}} | |
| 321 | 348 | |
| 322 | 349 | // {{{ getTableName |
| 323 | 350 | /** | ... | ... |
plugins/ktcore/KTCorePlugin.php
| ... | ... | @@ -16,6 +16,7 @@ class KTCorePlugin extends KTPlugin { |
| 16 | 16 | $this->registerAction('documentaction', 'KTDocumentEditAction', 'ktcore.actions.document.edit', 'KTDocumentActions.php'); |
| 17 | 17 | $this->registerAction('documentaction', 'KTDocumentDeleteAction', 'ktcore.actions.document.delete', 'KTDocumentActions.php'); |
| 18 | 18 | $this->registerAction('documentaction', 'KTDocumentMoveAction', 'ktcore.actions.document.move', 'KTDocumentActions.php'); |
| 19 | + $this->registerAction('documentaction', 'KTDocumentCopyAction', 'ktcore.actions.document.copy', 'KTDocumentActions.php'); | |
| 19 | 20 | $this->registerAction('documentaction', 'KTDocumentTransactionHistoryAction', 'ktcore.actions.document.transactionhistory', 'KTDocumentActions.php'); |
| 20 | 21 | $this->registerAction('documentaction', 'KTDocumentVersionHistoryAction', 'ktcore.actions.document.versionhistory', 'KTDocumentActions.php'); |
| 21 | 22 | $this->registerAction('documentaction', 'KTDocumentArchiveAction', 'ktcore.actions.document.archive', 'KTDocumentActions.php'); | ... | ... |
plugins/ktcore/KTDocumentActions.php
| ... | ... | @@ -553,6 +553,172 @@ class KTDocumentMoveAction extends KTDocumentAction { |
| 553 | 553 | } |
| 554 | 554 | // }}} |
| 555 | 555 | |
| 556 | + | |
| 557 | +class KTDocumentCopyColumn extends TitleColumn { | |
| 558 | + function KTDocumentCopyColumn($sLabel, $sName, $oDocument) { | |
| 559 | + $this->oDocument = $oDocument; | |
| 560 | + parent::TitleColumn($sLabel, $sName); | |
| 561 | + } | |
| 562 | + function buildFolderLink($aDataRow) { | |
| 563 | + return KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $aDataRow["folder"]->getId())); | |
| 564 | + } | |
| 565 | +} | |
| 566 | + | |
| 567 | +// {{{ KTDocumentMoveAction | |
| 568 | +class KTDocumentCopyAction extends KTDocumentAction { | |
| 569 | + var $sDisplayName = 'Copy'; | |
| 570 | + var $sName = 'ktcore.actions.document.copy'; | |
| 571 | + | |
| 572 | + var $_sShowPermission = "ktcore.permissions.read"; | |
| 573 | + | |
| 574 | + function getInfo() { | |
| 575 | + if ($this->oDocument->getIsCheckedOut()) { | |
| 576 | + return null; | |
| 577 | + } | |
| 578 | + return parent::getInfo(); | |
| 579 | + } | |
| 580 | + | |
| 581 | + function check() { | |
| 582 | + $res = parent::check(); | |
| 583 | + if ($res !== true) { | |
| 584 | + return $res; | |
| 585 | + } | |
| 586 | + if ($this->oDocument->getIsCheckedOut()) { | |
| 587 | + $_SESSION["KTErrorMessage"][]= _("This document can't be copied because it is checked out"); | |
| 588 | + controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId()); | |
| 589 | + exit(0); | |
| 590 | + } | |
| 591 | + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', $this->oDocument->getFolderId()); | |
| 592 | + $this->oFolder = $this->oValidator->validateFolder($iFolderId); | |
| 593 | + $this->oDocumentFolder = $this->oValidator->validateFolder($this->oDocument->getFolderId()); | |
| 594 | + return true; | |
| 595 | + } | |
| 596 | + | |
| 597 | + function do_main() { | |
| 598 | + $this->oPage->setBreadcrumbDetails(_("Copy")); | |
| 599 | + $oTemplate =& $this->oValidator->validateTemplate('ktcore/action/copy'); | |
| 600 | + $move_fields = array(); | |
| 601 | + $aNames = $this->oDocumentFolder->getPathArray(); | |
| 602 | + $aNames[] = $this->oDocument->getName(); | |
| 603 | + $sDocumentName = join(" » ", $aNames); | |
| 604 | + $move_fields[] = new KTStaticTextWidget(_('Document to copy'), '', 'fDocumentId', $sDocumentName, $this->oPage, false); | |
| 605 | + | |
| 606 | + $collection = new DocumentCollection(); | |
| 607 | + $collection->addColumn(new KTDocumentMoveColumn("Test 1 (title)","title", $this->oDocument)); | |
| 608 | + $qObj = new FolderBrowseQuery($this->oFolder->getId()); | |
| 609 | + $collection->setQueryObject($qObj); | |
| 610 | + | |
| 611 | + $batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0); | |
| 612 | + $batchSize = 20; | |
| 613 | + | |
| 614 | + $resultURL = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId())); | |
| 615 | + $collection->setBatching($resultURL, $batchPage, $batchSize); | |
| 616 | + | |
| 617 | + // ordering. (direction and column) | |
| 618 | + $displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc"); | |
| 619 | + if ($displayOrder !== "asc") { $displayOrder = "desc"; } | |
| 620 | + $displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title"); | |
| 621 | + | |
| 622 | + $collection->setSorting($displayControl, $displayOrder); | |
| 623 | + | |
| 624 | + $collection->getResults(); | |
| 625 | + | |
| 626 | + $aBreadcrumbs = array(); | |
| 627 | + $folder_path_names = $this->oFolder->getPathArray(); | |
| 628 | + $folder_path_ids = explode(',', $this->oFolder->getParentFolderIds()); | |
| 629 | + $folder_path_ids[] = $this->oFolder->getId(); | |
| 630 | + if ($folder_path_ids[0] == 0) { | |
| 631 | + array_shift($folder_path_ids); | |
| 632 | + array_shift($folder_path_names); | |
| 633 | + } | |
| 634 | + | |
| 635 | + foreach (range(0, count($folder_path_ids) - 1) as $index) { | |
| 636 | + $id = $folder_path_ids[$index]; | |
| 637 | + $url = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $id)); | |
| 638 | + $aBreadcrumbs[] = array("url" => $url, "name" => $folder_path_names[$index]); | |
| 639 | + } | |
| 640 | + | |
| 641 | + $oTemplate->setData(array( | |
| 642 | + 'context' => &$this, | |
| 643 | + 'move_fields' => $move_fields, | |
| 644 | + 'collection' => $collection, | |
| 645 | + 'collection_breadcrumbs' => $aBreadcrumbs, | |
| 646 | + )); | |
| 647 | + return $oTemplate->render(); | |
| 648 | + } | |
| 649 | + | |
| 650 | + function do_copy() { | |
| 651 | + $this->oPage->setBreadcrumbDetails(_("Copy")); | |
| 652 | + $oTemplate =& $this->oValidator->validateTemplate('ktcore/action/copy_final'); | |
| 653 | + $sFolderPath = join(" » ", $this->oFolder->getPathArray()); | |
| 654 | + $aNames = $this->oDocumentFolder->getPathArray(); | |
| 655 | + $aNames[] = $this->oDocument->getName(); | |
| 656 | + $sDocumentName = join(" » ", $aNames); | |
| 657 | + $move_fields = array(); | |
| 658 | + $move_fields[] = new KTStaticTextWidget(_('Document to move'), '', 'fDocumentId', $sDocumentName, $this->oPage, false); | |
| 659 | + $move_fields[] = new KTStaticTextWidget(_('Target folder'), '', 'fFolderId', $sFolderPath, $this->oPage, false); | |
| 660 | + $move_fields[] = new KTStringWidget(_('Reason'), _('The reason for this document to be moved.'), 'reason', "", $this->oPage, true); | |
| 661 | + | |
| 662 | + $oTemplate->setData(array( | |
| 663 | + 'context' => &$this, | |
| 664 | + 'move_fields' => $move_fields, | |
| 665 | + )); | |
| 666 | + return $oTemplate->render(); | |
| 667 | + } | |
| 668 | + | |
| 669 | + function do_copy_final() { | |
| 670 | + $sReason = KTUtil::arrayGet($_REQUEST, 'reason'); | |
| 671 | + $aOptions = array( | |
| 672 | + 'message' => _("No reason given"), | |
| 673 | + 'redirect_to' => array('move', sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $this->oFolder->getId())), | |
| 674 | + ); | |
| 675 | + $this->oValidator->notEmpty($sReason, $aOptions); | |
| 676 | + | |
| 677 | + if (!Permission::userHasFolderWritePermission($this->oFolder)) { | |
| 678 | + $this->errorRedirectTo("main", _("You do not have permission to move a document to this location"), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId())); | |
| 679 | + exit(0); | |
| 680 | + } | |
| 681 | + | |
| 682 | + // FIXME agree on document-duplication rules re: naming, etc. | |
| 683 | + | |
| 684 | + $this->startTransaction(); | |
| 685 | + | |
| 686 | + $oNewDoc = KTDocumentUtil::copy($this->oDocument, $this->oFolder); | |
| 687 | + if (PEAR::isError($oNewDoc)) { | |
| 688 | + $this->errorRedirectTo("main", _("Failed to move document: ") . $oNewDoc->getMessage(), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId())); | |
| 689 | + exit(0); | |
| 690 | + } | |
| 691 | + | |
| 692 | + $this->commitTransaction(); | |
| 693 | + | |
| 694 | + | |
| 695 | + // FIXME do we need to refactor all trigger usage into the util function? | |
| 696 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | |
| 697 | + $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate'); | |
| 698 | + foreach ($aTriggers as $aTrigger) { | |
| 699 | + $sTrigger = $aTrigger[0]; | |
| 700 | + $oTrigger = new $sTrigger; | |
| 701 | + $aInfo = array( | |
| 702 | + "document" => $oNewDocument, | |
| 703 | + "old_folder" => $this->oDocumentFolder, | |
| 704 | + "new_folder" => $this->oFolder, | |
| 705 | + ); | |
| 706 | + $oTrigger->setInfo($aInfo); | |
| 707 | + $ret = $oTrigger->postValidate(); | |
| 708 | + } | |
| 709 | + | |
| 710 | + $aOptions = array('user' => $oUser); | |
| 711 | + $oDocumentTransaction = & new DocumentTransaction($oNewDoc, "Document copied from old version.", 'ktcore.transactions.create', $aOptions); | |
| 712 | + $res = $oDocumentTransaction->create(); | |
| 713 | + | |
| 714 | + $_SESSION['KTInfoMessage'][] = _('Document copied.'); | |
| 715 | + | |
| 716 | + controllerRedirect('viewDocument', 'fDocumentId=' . $oNewDoc->getId()); | |
| 717 | + exit(0); | |
| 718 | + } | |
| 719 | +} | |
| 720 | +// }}} | |
| 721 | + | |
| 556 | 722 | // {{{ KTDocumentHistoryAction |
| 557 | 723 | class KTDocumentTransactionHistoryAction extends KTDocumentAction { |
| 558 | 724 | var $sDisplayName = 'Transaction History'; | ... | ... |