oDocument->getId())));
exit(0);
}
function getDisplayName() {
return _kt('Display Details');
}
}
// }}}
// {{{ KTDocumentHistoryAction
class KTDocumentTransactionHistoryAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.transactionhistory';
function getDisplayName() {
return _kt('Transaction History');
}
function do_main() {
$this->oPage->setSecondaryTitle($this->oDocument->getName());
$this->oPage->setBreadcrumbDetails(_kt("history"));
$aTransactions = array();
// FIXME create a sane "view user information" page somewhere.
// FIXME do we really need to use a raw db-access here? probably...
$sQuery = "SELECT DTT.name AS transaction_name, U.name AS user_name, DT.version AS version, DT.comment AS comment, DT.datetime AS datetime " .
"FROM " . KTUtil::getTableName("document_transactions") . " AS DT INNER JOIN " . KTUtil::getTableName("users") . " AS U ON DT.user_id = U.id " .
"INNER JOIN " . KTUtil::getTableName("transaction_types") . " AS DTT ON DTT.namespace = DT.transaction_namespace " .
"WHERE DT.document_id = ? ORDER BY DT.datetime DESC";
$aParams = array($this->oDocument->getId());
$res = DBUtil::getResultArray(array($sQuery, $aParams));
if (PEAR::isError($res)) {
var_dump($res); // FIXME be graceful on failure.
exit(0);
}
$aTransactions = $res;
// render pass.
$this->oPage->setTitle(_kt("Document History"));
$oTemplate = $this->oValidator->validateTemplate("ktcore/document/transaction_history");
$aTemplateData = array(
"context" => $this,
"document_id" => $this->oDocument->getId(),
"document" => $this->oDocument,
"transactions" => $aTransactions,
);
return $oTemplate->render($aTemplateData);
}
}
// }}}
// {{{ KTDocumentHistoryAction
class KTDocumentVersionHistoryAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.versionhistory';
function getDisplayName() {
return _kt('Version History');
}
function do_main() {
$this->oPage->setSecondaryTitle($this->oDocument->getName());
$this->oPage->setBreadcrumbDetails(_kt("Version History"));
$aMetadataVersions = KTDocumentMetadataVersion::getByDocument($this->oDocument);
$aVersions = array();
foreach ($aMetadataVersions as $oVersion) {
$aVersions[] = Document::get($this->oDocument->getId(), $oVersion->getId());
}
// render pass.
$this->oPage->title = _kt("Document History");
$oTemplate = $this->oValidator->validateTemplate("ktcore/document/metadata_history");
$aActions = KTDocumentActionUtil::getDocumentActionsByNames(array('ktcore.actions.document.view'), 'documentinfo');
$oAction = $aActions[0];
$oAction->setDocument($this->oDocument);
$aTemplateData = array(
"context" => $this,
"document_id" => $this->oDocument->getId(),
"document" => $this->oDocument,
"versions" => $aVersions,
'downloadaction' => $oAction,
);
return $oTemplate->render($aTemplateData);
}
function do_startComparison() {
$comparison_version = KTUtil::arrayGet($_REQUEST, 'fComparisonVersion');
$oDocument =& Document::get($this->oDocument->getId(), $comparison_version);
if (PEAR::isError($oDocument)) {
return $this->redirectToMain(_kt("The document you selected was invalid"));
}
if (!Permission::userHasDocumentReadPermission($oDocument)) {
return $this->errorRedirectToMain(_kt('You are not allowed to view this document'));
}
$this->oDocument =& $oDocument;
$this->oPage->setSecondaryTitle($oDocument->getName());
$this->oPage->setBreadcrumbDetails(_kt("Select Document Version to compare against"));
$aMetadataVersions = KTDocumentMetadataVersion::getByDocument($oDocument);
$aVersions = array();
foreach ($aMetadataVersions as $oVersion) {
$aVersions[] = Document::get($oDocument->getId(), $oVersion->getId());
}
$oTemplating =& KTTemplating::getSingleton();
$oTemplate = $oTemplating->loadTemplate("ktcore/document/comparison_version_select");
$aTemplateData = array(
"context" => $this,
"document_id" => $this->oDocument->getId(),
"document" => $oDocument,
"versions" => $aVersions,
'downloadaction' => $oAction,
);
return $oTemplate->render($aTemplateData);
}
function do_viewComparison() {
// this is just a redirector
$QS = array(
'action' => 'startComparison',
'fDocumentId' => urlencode($this->oDocument->getId()),
'fComparisonVersion' => urlencode($_REQUEST['fComparisonVersion']),
);
redirect(KTUtil::ktLink('view.php',null,implode('&', $QS)));
}
function getUserForId($iUserId) {
$u = User::get($iUserId);
if (PEAR::isError($u) || ($u == false)) { return _kt('User no longer exists'); }
return $u->getName();
}
}
// }}}
// {{{ KTDocumentViewAction
class KTDocumentViewAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.view';
function getDisplayName() {
return _kt('Download');
}
function customiseInfo($aInfo) {
$aInfo['alert'] = _kt("This will download a copy of the document and is not the same as Checking Out a document. Changes to this downloaded file will not be managed in the DMS.");
return $aInfo;
}
function do_main() {
$oStorage =& KTStorageManagerUtil::getSingleton();
$aOptions = array();
$iVersion = KTUtil::arrayGet($_REQUEST, 'version');
if ($iVersion) {
$oVersion = KTDocumentContentVersion::get($iVersion);
$aOptions['version'] = sprintf("%d.%d", $oVersion->getMajorVersionNumber(), $oVersion->getMinorVersionNumber());;
$res = $oStorage->downloadVersion($this->oDocument, $iVersion);
} else {
$res = $oStorage->download($this->oDocument);
}
if ($res === false) {
$this->addErrorMessage(_kt('The file you requested is not available - please contact the system administrator if this is incorrect.'));
redirect(generateControllerLink('viewDocument',sprintf(_kt('fDocumentId=%d'),$this->oDocument->getId())));
exit(0);
}
$oDocumentTransaction = & new DocumentTransaction($this->oDocument, "Document downloaded", 'ktcore.transactions.download', $aOptions);
$oDocumentTransaction->create();
exit(0);
}
}
// }}}
// {{{ KTDocumentCheckOutAction
class KTDocumentCheckOutAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.checkout';
var $_sShowPermission = "ktcore.permissions.write";
var $_bMutator = true;
var $_bMutationAllowedByAdmin = false;
function getDisplayName() {
return _kt('Checkout');
}
function getInfo() {
if ($this->oDocument->getIsCheckedOut()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
// since we actually check the doc out, then download it ...
if (($_REQUEST[$this->event_var] == 'checkout_final') && ($this->oDocument->getCheckedOutUserID() == $_SESSION['userID'])) {
return true;
}
// "normal".
if ($this->oDocument->getIsCheckedOut()) {
$_SESSION['KTErrorMessage'][] = _kt("This document is already checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
return true;
}
function form_checkout() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Checkout"),
'action' => 'checkout',
'fail_action' => 'main',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Checkout document"),
'context' => &$this,
));
$oForm->setWidgets(array(
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are checking out this document. It will assist other users in understanding why you have locked this file. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
array('ktcore.widgets.boolean', array(
'label' => _kt("Download File"),
'description' => _kt("Indicate whether you would like to download this file as part of the checkout."),
'name' => 'download_file',
'value' => true,
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
array('ktcore.validators.boolean', array(
'test' => 'download_file',
'output' => 'download_file',
)),
));
return $oForm;
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("checkout"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/checkout');
$oForm = $this->form_checkout();
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
));
return $oTemplate->render();
}
function do_checkout() {
$oForm = $this->form_checkout();
$res = $oForm->validate();
if (!empty($res['errors'])) {
return $oForm->handleError();
}
$data = $res['results'];
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/checkout_final');
$sReason = $data['reason'];
$this->startTransaction();
$res = KTDocumentUtil::checkout($this->oDocument, $sReason, $this->oUser);
if (PEAR::isError($res)) {
return $this->errorRedirectToMain(sprintf(_kt('Failed to check out the document: %s'), $res->getMessage()));
}
$this->commitTransaction();
if (!$data['download_file']) {
$this->addInfoMessage(_kt("Document checked out."));
redirect(KTBrowseUtil::getUrlForDocument($this->oDocument));
exit(0);
}
$oTemplate->setData(array(
'context' => &$this,
'reason' => $sReason,
));
return $oTemplate->render();
}
function do_checkout_final() {
$sReason = KTUtil::arrayGet($_REQUEST, 'reason');
$this->oValidator->notEmpty($sReason);
$oStorage =& KTStorageManagerUtil::getSingleton();
$oStorage->download($this->oDocument);
exit(0);
}
}
// }}}
// {{{ KTDocumentCheckInAction
class KTDocumentCheckInAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.checkin';
var $_sShowPermission = "ktcore.permissions.write";
function getDisplayName() {
return _kt('Checkin');
}
function getInfo() {
if (!$this->oDocument->getIsCheckedOut()) {
return null;
}
if ($this->oDocument->getCheckedOutUserID() != $this->oUser->getId()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
if (!$this->oDocument->getIsCheckedOut()) {
$_SESSION['KTErrorMessage'][] = _kt("This document is not checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
if ($this->oDocument->getCheckedOutUserID() != $this->oUser->getId()) {
$_SESSION['KTErrorMessage'][] = _kt("This document is checked out, but not by you");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
return true;
}
function form_main() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Checkin Document"),
'action' => 'checkin',
'fail_action' => 'main',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Checkin"),
'context' => &$this,
'file_upload' => true, // otherwise the post is not received.
));
$oForm->setWidgets(array(
array('ktcore.widgets.file', array(
'label' => _kt("File"),
'description' => sprintf(_kt('Please specify the file you wish to upload. Unless you also indicate that you are changing its filename (see "Force Original Filename" below), this will need to be called %s'), $this->oDocument->getFilename()),
'name' => 'file',
'basename' => 'file',
'required' => true,
)),
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are cancelling this document's checked-out status. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
array('ktcore.widgets.boolean',array(
'label' => _kt('Force Original Filename'),
'description' => sprintf(_kt('If this is checked, the uploaded document must have the same filename as the original: %s'), $this->oDocument->getFilename()),
'name' => 'forcefilename',
'value' => true,
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
array('ktcore.validators.file', array(
'test' => 'file',
'output' => 'file',
)),
array('ktcore.validators.boolean', array(
'test' => 'forcefilename',
'output' => 'forcefilename',
)),
));
return $oForm;
}
function do_main() {
$this->oPage->setBreadcrumbDetails("checkin");
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/checkin');
$oForm = $this->form_main();
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
));
return $oTemplate->render();
}
function do_checkin() {
$oForm = $this->form_main();
$res = $oForm->validate();
$data = $res['results'];
$extra_errors = array();
if ($data['forcefilename'] && ($data['file']['name'] != $this->oDocument->getFilename())) {
$extra_errors['file'] = sprintf(_kt('The file you uploaded was not called "%s". If you wish to change the filename, please set "Force Original Filename" below to false. '), $this->oDocument->getFilename());
}
if (!empty($res['errors']) || !empty($extra_errors)) {
return $oForm->handleError(null, $extra_errors);
}
$sReason = $data['reason'];
$sCurrentFilename = $this->oDocument->getFileName();
$sNewFilename = $data['file']['name'];
$aOptions = array();
if ($sCurrentFilename != $sNewFilename) {
$aOptions['newfilename'] = $sNewFilename;
}
$res = KTDocumentUtil::checkin($this->oDocument, $data['file']['tmp_name'], $sReason, $this->oUser, $aOptions);
if (PEAR::isError($res)) {
$this->errorRedirectToMain(_kt("An error occurred while trying to check in the document"), 'fDocumentId=' . $this->oDocument->getId() . '&reason=' . $sReason);
}
redirect(KTBrowseUtil::getUrlForDocument($this->oDocument));
exit(0);
}
}
// }}}
// {{{ KTDocumentCancelCheckOutAction
class KTDocumentCancelCheckOutAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.cancelcheckout';
var $_sShowPermission = "ktcore.permissions.write";
var $bAllowInAdminMode = true;
var $bInAdminMode = null;
function getDisplayName() {
return _kt('Cancel Checkout');
}
function getInfo() {
if (!$this->oDocument->getIsCheckedOut()) {
return null;
}
if (is_null($this->bInAdminMode)) {
$oFolder = Folder::get($this->oDocument->getFolderId());
if (KTBrowseUtil::inAdminMode($this->oUser, $oFolder)) {
$this->bAdminMode = true;
return parent::getInfo();
}
} else if ($this->bInAdminMode == true) {
return parent::getInfo();
}
if ($this->oDocument->getCheckedOutUserID() != $this->oUser->getId()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
if (!$this->oDocument->getIsCheckedOut()) {
$_SESSION['KTErrorMessage'][] = _kt("This document is not checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
// hard override if we're in admin mode for this doc.
if (is_null($this->bInAdminMode)) {
$oFolder = Folder::get($this->oDocument->getFolderId());
if (KTBrowseUtil::inAdminMode($this->oUser, $oFolder)) {
$this->bAdminMode = true;
return true;
}
} else if ($this->bInAdminMode == true) {
return true;
}
if ($this->oDocument->getCheckedOutUserID() != $this->oUser->getId()) {
$_SESSION['KTErrorMessage'][] = _kt("This document is checked out, but not by you");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
return true;
}
function form_main() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Cancel Checkout"),
'action' => 'checkin',
'fail_action' => 'main',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Cancel Checkin"),
'context' => &$this,
));
$oForm->setWidgets(array(
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are cancelling this document's checked-out status. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
));
return $oForm;
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("cancel checkout"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/cancel_checkout');
$oForm = $this->form_main();
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
'document' => $this->oDocument,
));
return $oTemplate->render();
}
function do_checkin() {
$oForm = $this->form_main();
$res = $oForm->validate();
if (!empty($res['errors'])) {
return $oForm->handleError();
}
$data = $res['results'];
$this->startTransaction();
// actually do the checkin.
$this->oDocument->setIsCheckedOut(0);
$this->oDocument->setCheckedOutUserID(-1);
$res = $this->oDocument->update();
if (PEAR::isError($res) || ($res === false)) {
$this->rollbackTransaction();
return $this->errorRedirectToMain(_kt("Failed to force the document's checkin."),sprintf('fDocumentId=%d'),$this->oDocument->getId());
}
// checkout cancelled transaction
$oDocumentTransaction = & new DocumentTransaction($this->oDocument, "Document checked out cancelled", 'ktcore.transactions.force_checkin');
$res = $oDocumentTransaction->create();
if (PEAR::isError($res) || ($res === false)) {
$this->rollbackTransaction();
return $this->errorRedirectToMain(_kt("Failed to force the document's checkin."),sprintf('fDocumentId=%d'),$this->oDocument->getId());
}
$this->commitTransaction();
redirect(KTBrowseUtil::getUrlForDocument($this->oDocument));
}
}
// }}}
// {{{ KTDocumentDeleteAction
class KTDocumentDeleteAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.delete';
var $_sShowPermission = "ktcore.permissions.delete";
var $_bMutator = true;
function getDisplayName() {
return _kt('Delete');
}
function getInfo() {
if ($this->oDocument->getIsCheckedOut()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
if ($this->oDocument->getIsCheckedOut()) {
$_SESSION["KTErrorMessage"][]= _kt("This document can't be deleted because it is checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
return true;
}
function form_main() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Delete Document"),
'action' => 'delete',
'fail_action' => 'main',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Delete Document"),
'context' => &$this,
));
$oForm->setWidgets(array(
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are deleting this document. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
));
return $oForm;
}
function do_main() {
$this->oPage->setBreadcrumbDetails("Delete");
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/delete');
$oForm = $this->form_main();
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
));
return $oTemplate->render();
}
function do_delete() {
$oForm = $this->form_main();
$res = $oForm->validate();
$data = $res['results'];
if (!empty($res['errors'])) {
return $oForm->handleError();
}
$sReason = $data['reason'];
$fFolderId = $this->oDocument->getFolderId();
$res = KTDocumentUtil::delete($this->oDocument, $sReason);
if (PEAR::isError($res)) {
$this->errorRedirectToMain(sprintf(_kt("Unexpected failure deleting document: %s"), $res->getMessage()));
}
$_SESSION['KTInfoMessage'][] = sprintf(_kt('Document "%s" Deleted.'),$this->oDocument->getName());
controllerRedirect('browse', 'fFolderId=' . $fFolderId);
exit(0);
}
}
// }}}
class KTDocumentMoveColumn extends TitleColumn {
function KTDocumentMoveColumn($sLabel, $sName, $oDocument) {
$this->oDocument = $oDocument;
parent::TitleColumn($sLabel, $sName);
}
function buildFolderLink($aDataRow) {
return KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $aDataRow["folder"]->getId()));
}
}
// {{{ KTDocumentMoveAction
class KTDocumentMoveAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.move';
var $_sShowPermission = "ktcore.permissions.write";
var $_bMutator = true;
function getDisplayName() {
return _kt('Move');
}
function getInfo() {
if ($this->oDocument->getIsCheckedOut()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
if ($this->oDocument->getIsCheckedOut()) {
$_SESSION["KTErrorMessage"][]= _kt("This document can't be deleted because it is checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
$this->persistParams(array('fFolderId'));
$iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', $this->oDocument->getFolderId());
$this->oFolder = $this->oValidator->validateFolder($iFolderId);
$this->oDocumentFolder = $this->oValidator->validateFolder($this->oDocument->getFolderId());
return true;
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("move"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/move');
$move_fields = array();
$aNames = $this->oDocumentFolder->getPathArray();
$aNames[] = $this->oDocument->getName();
$sDocumentName = join(" » ", $aNames);
$move_fields[] = new KTStaticTextWidget(_kt('Document to move'), '', 'fDocumentId', $sDocumentName, $this->oPage, false);
$collection = new DocumentCollection();
$collection->addColumn(new KTDocumentMoveColumn("Test 1 (title)","title", $this->oDocument));
$qObj = new FolderBrowseQuery($this->oFolder->getId());
$collection->setQueryObject($qObj);
$batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
$batchSize = 20;
$resultURL = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
$collection->setBatching($resultURL, $batchPage, $batchSize);
// ordering. (direction and column)
$displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
if ($displayOrder !== "asc") { $displayOrder = "desc"; }
$displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title");
$collection->setSorting($displayControl, $displayOrder);
$collection->getResults();
$aBreadcrumbs = array();
$folder_path_names = $this->oFolder->getPathArray();
$folder_path_ids = explode(',', $this->oFolder->getParentFolderIds());
$folder_path_ids[] = $this->oFolder->getId();
if ($folder_path_ids[0] == 0) {
array_shift($folder_path_ids);
array_shift($folder_path_names);
}
foreach (range(0, count($folder_path_ids) - 1) as $index) {
$id = $folder_path_ids[$index];
$url = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $id));
$aBreadcrumbs[] = array("url" => $url, "name" => $folder_path_names[$index]);
}
$oTemplate->setData(array(
'context' => &$this,
'move_fields' => $move_fields,
'collection' => $collection,
'collection_breadcrumbs' => $aBreadcrumbs,
));
return $oTemplate->render();
}
function form_move() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Move Document"),
'action' => 'move_final',
'fail_action' => 'move',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Move Document"),
'context' => &$this,
));
$oForm->setWidgets(array(
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are moving this document. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
));
return $oForm;
}
function do_move() {
$this->persistParams(array('fFolderId'));
$this->oPage->setBreadcrumbDetails(_kt("Move"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/move_final');
if($this->oDocument->getFolderId() === $this->oFolder->getId()) {
$this->errorRedirectTo('main', _kt("The document was already in this folder"), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
$oForm = $this->form_move();
//$sFolderPath = join(" » ", $this->oFolder->getPathArray());
//$aNames = $this->oDocumentFolder->getPathArray();
//$aNames[] = $this->oDocument->getName();
//$sDocumentName = join(" » ", $aNames);
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
));
return $oTemplate->render();
}
function do_move_final() {
$oForm = $this->form_move();
$res = $oForm->validate();
$data = $res['results'];
if (!empty($res['errors'])) {
return $oForm->handleError();
}
$sReason = $data['reason'];
if (!Permission::userHasFolderWritePermission($this->oFolder)) {
$this->errorRedirectToMain(_kt("You do not have permission to move a document to this location"));
exit(0);
}
$this->startTransaction();
$oOriginalFolder = Folder::get($this->oDocument->getFolderId());
$iOriginalFolderPermissionObjectId = $oOriginalFolder->getPermissionObjectId();
$iDocumentPermissionObjectId = $this->oDocument->getPermissionObjectId();
if ($iDocumentPermissionObjectId === $iOriginalFolderPermissionObjectId) {
$this->oDocument->setPermissionObjectId($this->oFolder->getPermissionObjectId());
}
//put the document in the new folder
$this->oDocument->setFolderID($this->oFolder->getId());
$res = $this->oDocument->update();
if (PEAR::isError($res) || ($res === false)) {
$this->errorRedirectToMain(_kt("There was a problem updating the document's location in the database"));
}
//move the document on the file system
$oStorage =& KTStorageManagerUtil::getSingleton();
$res = $oStorage->moveDocument($this->oDocument, $this->oDocumentFolder, $this->oFolder);
if (PEAR::isError($res) || ($res === false)) {
$this->oDocument->setFolderID($oOriginalFolder->getId());
$this->oDocument->update();
$this->errorRedirectToMain(_kt("There was a problem updating the document's location in the repository storage"));
}
$sMoveMessage = sprintf("Moved from %s/%s to %s/%s: %s",
$this->oDocumentFolder->getFullPath(),
$this->oDocumentFolder->getName(),
$this->oFolder->getFullPath(),
$this->oFolder->getName(),
$sReason);
// create the document transaction record
$oDocumentTransaction = & new DocumentTransaction($this->oDocument, $sMoveMessage, 'ktcore.transactions.move');
$oDocumentTransaction->create();
$this->commitTransaction();
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('moveDocument', 'postValidate');
foreach ($aTriggers as $aTrigger) {
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
"document" => $this->oDocument,
"old_folder" => $this->oDocumentFolder,
"new_folder" => $this->oFolder,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
if (PEAR::isError($ret)) {
$this->oDocument->delete();
return $ret;
}
}
redirect(KTBrowseUtil::getUrlForDocument($this->oDocument));
exit(0);
}
}
// }}}
class KTDocumentCopyColumn extends TitleColumn {
function KTDocumentCopyColumn($sLabel, $sName, $oDocument) {
$this->oDocument = $oDocument;
parent::TitleColumn($sLabel, $sName);
}
function buildFolderLink($aDataRow) {
return KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $aDataRow["folder"]->getId()));
}
}
// {{{ KTDocumentMoveAction
class KTDocumentCopyAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.copy';
var $_sShowPermission = "ktcore.permissions.read";
function getDisplayName() {
return _kt('Copy');
}
function getInfo() {
if ($this->oDocument->getIsCheckedOut()) {
return null;
}
return parent::getInfo();
}
function check() {
$res = parent::check();
if ($res !== true) {
return $res;
}
if ($this->oDocument->getIsCheckedOut()) {
$_SESSION["KTErrorMessage"][]= _kt("This document can't be copied because it is checked out");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
$iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', $this->oDocument->getFolderId());
$this->oFolder = $this->oValidator->validateFolder($iFolderId);
$this->oDocumentFolder = $this->oValidator->validateFolder($this->oDocument->getFolderId());
return true;
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("Copy"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/copy');
$move_fields = array();
$aNames = $this->oDocumentFolder->getPathArray();
$aNames[] = $this->oDocument->getName();
$sDocumentName = join(" » ", $aNames);
$move_fields[] = new KTStaticTextWidget(_kt('Document to copy'), '', 'fDocumentId', $sDocumentName, $this->oPage, false);
$collection = new DocumentCollection();
$collection->addColumn(new KTDocumentMoveColumn("Test 1 (title)","title", $this->oDocument));
$qObj = new FolderBrowseQuery($this->oFolder->getId());
$collection->setQueryObject($qObj);
$batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
$batchSize = 20;
$resultURL = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
$collection->setBatching($resultURL, $batchPage, $batchSize);
// ordering. (direction and column)
$displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
if ($displayOrder !== "asc") { $displayOrder = "desc"; }
$displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title");
$collection->setSorting($displayControl, $displayOrder);
$collection->getResults();
$aBreadcrumbs = array();
$folder_path_names = $this->oFolder->getPathArray();
$folder_path_ids = explode(',', $this->oFolder->getParentFolderIds());
$folder_path_ids[] = $this->oFolder->getId();
if ($folder_path_ids[0] == 0) {
array_shift($folder_path_ids);
array_shift($folder_path_names);
}
foreach (range(0, count($folder_path_ids) - 1) as $index) {
$id = $folder_path_ids[$index];
$url = KTUtil::addQueryString($_SERVER['PHP_SELF'], sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $id));
$aBreadcrumbs[] = array("url" => $url, "name" => $folder_path_names[$index]);
}
$oTemplate->setData(array(
'context' => &$this,
'move_fields' => $move_fields,
'collection' => $collection,
'collection_breadcrumbs' => $aBreadcrumbs,
));
return $oTemplate->render();
}
function do_copy() {
$this->oPage->setBreadcrumbDetails(_kt("Copy"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/copy_final');
$sFolderPath = join(" » ", $this->oFolder->getPathArray());
$aNames = $this->oDocumentFolder->getPathArray();
$aNames[] = $this->oDocument->getName();
$sDocumentName = join(" » ", $aNames);
$bNameClash = KTDocumentUtil::nameExists($this->oFolder, $this->oDocument->getName());
$bFileClash = KTDocumentUtil::fileExists($this->oFolder, $this->oDocument->getFilename());
$bIsClash = $bNameClash or $bFileClash;
$copy_fields = array();
$copy_fields[] = new KTStaticTextWidget(_kt('Document to copy'), '', 'fDocumentId', $sDocumentName, $this->oPage, false);
$copy_fields[] = new KTStaticTextWidget(_kt('Target folder'), '', 'fFolderId', $sFolderPath, $this->oPage, false);
$copy_fields[] = new KTStringWidget(_kt('Reason'), _kt('The reason for this document to be copied.'), 'reason', "", $this->oPage, true);
if ($bIsClash) {
if ($bNameClash) {
$copy_fields[] = new KTStringWidget(_kt('Title'), _kt('A document with the same title already exists in the folder. Please supply an alternative filename'), 'name', $this->oDocument->getName(), $this->oPage, true);
}
if ($bFileClash) {
$copy_fields[] = new KTStringWidget(_kt('Filename'), _kt('A document with the same filename already exists in the folder. Please supply an alternative filename'), 'filename', $this->oDocument->getFilename(), $this->oPage, true);
}
}
$oTemplate->setData(array(
'context' => &$this,
'copy_fields' => $copy_fields,
'is_clash' => $bIsClash,
));
return $oTemplate->render();
}
function do_copy_final() {
$sReason = KTUtil::arrayGet($_REQUEST, 'reason');
$aOptions = array(
'message' => _kt("No reason given"),
'redirect_to' => array('copy', sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $this->oFolder->getId())),
);
$this->oValidator->notEmpty($sReason, $aOptions);
if (!Permission::userHasFolderWritePermission($this->oFolder)) {
$this->errorRedirectTo("main", _kt("You do not have permission to copy a document to this location"), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
// FIXME agree on document-duplication rules re: naming, etc.
$this->startTransaction();
// now try update it.
$bNameClash = KTDocumentUtil::nameExists($this->oFolder, $this->oDocument->getName());
$bFileClash = KTDocumentUtil::fileExists($this->oFolder, $this->oDocument->getFilename());
$bIsClash = $bNameClash or $bFileClash;
if ($bIsClash) {
$name = KTUtil::arrayGet($_REQUEST, 'name', $this->oDocument->getName());
$filename = KTUtil::arrayGet($_REQUEST, 'filename', $this->oDocument->getFilename());
if (KTDocumentUtil::nameExists($this->oFolder, $name)) {
$this->errorRedirectTo('copy', _kt('A document with that name also exists in this folder. Please try a different name.'), sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
if (KTDocumentUtil::fileExists($this->oFolder, $filename)) {
$this->errorRedirectTo('copy', _kt('A document with that filename also exists in this folder. Please try a different name.'), sprintf('fDocumentId=%d&fFolderId=%d', $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
}
$oNewDoc = KTDocumentUtil::copy($this->oDocument, $this->oFolder);
if (PEAR::isError($oNewDoc)) {
$this->errorRedirectTo("main", _kt("Failed to copy document: ") . $oNewDoc->getMessage(), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
if ($bIsClash) {
// use earlier supplied and tested versions.
$oNewDoc->setName($name);
$oNewDoc->setFilename($filename);
$res = $oNewDoc->update();
if (PEAR::isError($res)) {
$this->errorRedirectTo("main", _kt("Failed to copy document: ") . $res->getMessage(), sprintf("fDocumentId=%d&fFolderId=%d", $this->oDocument->getId(), $this->oFolder->getId()));
exit(0);
}
}
$this->commitTransaction();
// FIXME do we need to refactor all trigger usage into the util function?
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate');
foreach ($aTriggers as $aTrigger) {
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
"document" => $oNewDocument,
"old_folder" => $this->oDocumentFolder,
"new_folder" => $this->oFolder,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
$aOptions = array('user' => $oUser);
$oDocumentTransaction = & new DocumentTransaction($oNewDoc, "Document copied from old version.", 'ktcore.transactions.create', $aOptions);
$res = $oDocumentTransaction->create();
$_SESSION['KTInfoMessage'][] = _kt('Document copied.');
controllerRedirect('viewDocument', 'fDocumentId=' . $oNewDoc->getId());
exit(0);
}
}
// }}}
// {{{ KTDocumentArchiveAction
class KTDocumentArchiveAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.archive';
var $_sShowPermission = "ktcore.permissions.write";
var $_bMutator = true;
function getDisplayName() {
return _kt('Archive');
}
function getInfo() {
if ($this->oDocument->getIsCheckedOut()) {
return null;
}
return parent::getInfo();
}
function form_main() {
$oForm = new KTForm;
$oForm->setOptions(array(
'label' => _kt("Archive Document"),
'action' => 'archive',
'fail_action' => 'main',
'cancel_url' => KTBrowseUtil::getUrlForDocument($this->oDocument),
'submit_label' => _kt("Archive Document"),
'context' => &$this,
));
$oForm->setWidgets(array(
array('ktcore.widgets.reason', array(
'label' => _kt("Reason"),
'description' => _kt("Please specify why you are archiving this document. Please bear in mind that you can use a maximum of 250 characters."),
'name' => 'reason',
)),
));
$oForm->setValidators(array(
array('ktcore.validators.string', array(
'test' => 'reason',
'max_length' => 250,
'output' => 'reason',
)),
));
return $oForm;
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("Archive Document"));
$oTemplate =& $this->oValidator->validateTemplate('ktcore/action/archive');
$oForm = $this->form_main();
$oTemplate->setData(array(
'context' => &$this,
'form' => $oForm,
));
return $oTemplate->render();
}
function do_archive() {
$oForm = $this->form_main();
$res = $oForm->validate();
$data = $res['results'];
if (!empty($res['errors'])) {
return $oForm->handleError();
}
$sReason = $data['reason'];
$this->startTransaction();
$this->oDocument->setStatusID(ARCHIVED);
$res = $this->oDocument->update();
if (PEAR::isError($res) || ($res === false)) {
$_SESSION['KTErrorMessage'][] = _kt("There was a database error while trying to archive this file");
controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
exit(0);
}
$oDocumentTransaction = & new DocumentTransaction($this->oDocument, sprintf(_kt("Document archived: %s"), $sReason), 'ktcore.transactions.update');
$oDocumentTransaction->create();
$this->commitTransaction();
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
foreach ($aTriggers as $aTrigger) {
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
"document" => $this->oDocument,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
if (PEAR::isError($ret)) {
$this->oDocument->delete();
return $ret;
}
}
$_SESSION['KTInfoMessage'][] = _kt("Document archived.");
controllerRedirect('browse', 'fFolderId=' . $this->oDocument->getFolderID());
exit(0);
}
}
// }}}
// {{{ KTDocumentWorkflowAction
class KTDocumentWorkflowAction extends KTDocumentAction {
var $sName = 'ktcore.actions.document.workflow';
var $_sShowPermission = "ktcore.permissions.read";
var $sHelpPage = 'ktcore/user/workflow.html';
function getDisplayName() {
return _kt('Workflow');
}
function do_main() {
$this->oPage->setBreadcrumbDetails(_kt("workflow"));
$oTemplate =& $this->oValidator->validateTemplate("ktcore/workflow/documentWorkflow");
$oDocument =& $this->oValidator->validateDocument($_REQUEST['fDocumentId']);
$oWorkflow = KTWorkflowUtil::getWorkflowForDocument($oDocument);
$oWorkflowState = KTWorkflowUtil::getWorkflowStateForDocument($oDocument);
$oUser =& User::get($_SESSION['userID']);
$aTransitions = KTWorkflowUtil::getTransitionsForDocumentUser($oDocument, $oUser);
$aWorkflows = KTWorkflow::getList('start_state_id IS NOT NULL');
$bHasPerm = false;
if (KTPermissionUtil::userHasPermissionOnItem($oUser, 'ktcore.permissions.workflow', $oDocument)) {
$bHasPerm = true;
}
$fieldErrors = null;
$transition_fields = array();
if ($aTransitions) {
$aVocab = array();
foreach ($aTransitions as $oTransition) {
$aVocab[$oTransition->getId()] = $oTransition->showDescription();
}
$fieldOptions = array("vocab" => $aVocab);
$transition_fields[] = new KTLookupWidget(_kt('Transition to perform'), _kt('The transition listed will cause the document to change from its current state to the listed destination state.'), 'fTransitionId', null, $this->oPage, true, null, $fieldErrors, $fieldOptions);
$transition_fields[] = new KTTextWidget(
_kt('Reason for transition'), _kt('Describe why this document qualifies to be changed from its current state to the destination state of the transition chosen.'),
'fComments', "",
$this->oPage, true, null, null,
array('cols' => 80, 'rows' => 4));
}
$aTemplateData = array(
'oDocument' => $oDocument,
'oWorkflow' => $oWorkflow,
'oState' => $oWorkflowState,
'aTransitions' => $aTransitions,
'aWorkflows' => $aWorkflows,
'transition_fields' => $transition_fields,
'bHasPerm' => $bHasPerm,
);
return $oTemplate->render($aTemplateData);
}
function do_startWorkflow() {
$oDocument =& $this->oValidator->validateDocument($_REQUEST['fDocumentId']);
if (!empty($_REQUEST['fWorkflowId'])) {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
} else {
$oWorkflow = null;
}
$res = KTWorkflowUtil::startWorkflowOnDocument($oWorkflow, $oDocument);
if (PEAR::isError($res)) {
$this->errorRedirectToMain($res->message, sprintf('fDocumentId=%s',$oDocument->getId()));
}
$this->successRedirectToMain(_kt('Workflow started'),
array('fDocumentId' => $oDocument->getId()));
exit(0);
}
function do_performTransition() {
$oDocument =& $this->oValidator->validateDocument($_REQUEST['fDocumentId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$aErrorOptions = array(
'redirect_to' => array('main', sprintf('fDocumentId=%d', $_REQUEST['fDocumentId'])),
'message' => _kt('You must provide a reason for the transition'),
);
$sComments =& $this->oValidator->validateString($_REQUEST['fComments'], $aErrorOptions);
$oUser =& User::get($_SESSION['userID']);
$res = KTWorkflowUtil::performTransitionOnDocument($oTransition, $oDocument, $oUser, $sComments);
if(!Permission::userHasDocumentReadPermission($oDocument)) {
$this->commitTransaction();
$_SESSION['KTInfoMessage'][] = _kt('Transition performed') . '. ' . _kt('You no longer have permission to view this document');
controllerRedirect('browse', sprintf('fFolderId=%d', $oDocument->getFolderId()));
} else {
$this->successRedirectToMain(_kt('Transition performed'),
array('fDocumentId' => $oDocument->getId()));
}
}
}
// }}}
?>