This repository has been archived on 2024-11-28. You can view files and clone it, but cannot push or open issues or pull requests.
Incam_SGD/ktapi/KTAPIDocument.inc.php

2549 lines
70 KiB
PHP
Raw Permalink Normal View History

<?php
/**
* Document API for KnowledgeTree
*
* KnowledgeTree Community Edition
* Document Management Made Simple
* Copyright (C) 2008, 2009 KnowledgeTree Inc.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 3 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
* California 94120-7775, or email info@knowledgetree.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* KnowledgeTree" logo and retain the original copyright notice. If the display of the
* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
* must display the words "Powered by KnowledgeTree" and retain the original
* copyright notice.
*
* @copyright 2008-2009, KnowledgeTree Inc.
* @license GNU General Public License version 3
* @author KnowledgeTree Team
* @package KTAPI
* @version Version 0.9
*/
require_once(KT_DIR . '/ktwebservice/KTDownloadManager.inc.php');
/**
* API for the handling document operations within KnowledgeTree
*
* @author KnowledgeTree Team
* @package KTAPI
* @version 0.9
*/
class KTAPI_Document extends KTAPI_FolderItem
{
/**
* This is a reference to the internal document object.
*
* @access protected
* @var object of Document
*/
var $document;
/**
* This is the id of the document.
*
* @access protected
* @var int
*/
var $documentid;
/**
* This is a reference to the parent folder.
*
* @access protected
* @var object of KTAPI_Folder
*/
var $ktapi_folder;
/**
* Gets the id of the current document
*
* @author KnowledgeTree Team
* @access public
* @return string The document id
*/
function get_documentid()
{
return $this->documentid;
}
/**
* This is used to get a document based on document id.
*
* @author KnowledgeTree Team
* @static
* @access public
* @param KTAPI $ktapi The ktapi object
* @param int $documentid The document id
* @return KTAPI_Document The document object
*/
function &get(&$ktapi, $documentid)
{
assert(!is_null($ktapi));
assert(is_a($ktapi, 'KTAPI'));
assert(is_numeric($documentid));
$documentid += 0;
$document = &Document::get($documentid);
if (is_null($document) || PEAR::isError($document))
{
return new KTAPI_Error(KTAPI_ERROR_DOCUMENT_INVALID,$document );
}
$user = $ktapi->can_user_access_object_requiring_permission($document, KTAPI_PERMISSION_READ);
if (is_null($user) || PEAR::isError($user))
{
return $user;
}
$folderid = $document->getParentID();
if (!is_null($folderid))
{
$ktapi_folder = &KTAPI_Folder::get($ktapi, $folderid);
}
else
{
$ktapi_folder = null;
}
// We don't do any checks on this folder as it could possibly be deleted, and is not required right now.
return new KTAPI_Document($ktapi, $ktapi_folder, $document);
}
/**
* Checks if a document has been deleted
*
* @author KnowledgeTree Team
* @access public
* @return boolean TRUE if deleted | FALSE if in a different state
*/
function is_deleted()
{
return ($this->document->getStatusID() == 3);
}
/**
* Checks if the document is a shortcut
*
* @author KnowledgeTree Team
* @access public
* @return boolean TRUE if it is a shortcut | FALSE if not
*/
function is_shortcut()
{
return $this->document->isSymbolicLink();
}
/**
* Retrieves the shortcuts linking to this document
*
* @author KnowledgeTree Team
* @access public
* @return array The shortcuts linked to the document
*/
function get_shortcuts()
{
return $this->document->getSymbolicLinks();
}
/**
* This is the constructor for the KTAPI_Document
*
* @author KnowledgeTree Team
* @access private
* @param KTAPI $ktapi The KTAPI object
* @param KTAPI_Folder $ktapi_folder The parent folder object
* @param Document $document The internal document object
* @return KTAPI_Document
*/
function KTAPI_Document(&$ktapi, &$ktapi_folder, &$document)
{
assert($ktapi instanceof KTAPI); //is_a($ktapi,'KTAPI'));
assert(is_null($ktapi_folder) || $ktapi_folder instanceof KTAPI_Folder); //is_a($ktapi_folder,'KTAPI_Folder'));
$this->ktapi = &$ktapi;
$this->ktapi_folder = &$ktapi_folder;
$this->document = &$document;
$this->documentid = $document->getId();
}
/**
* This checks a document into the repository.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* if($document->is_checked_out()){
* $document->checkin('filename.txt', 'Reason for checkin', '/tmp/filename');
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param string $filename The name of the file
* @param string $reason The reason for checking the document in
* @param string $tempfilename The location of the temporary file
* @param bool $major_update Determines if the version number should have a major increment (+1) or a minor increment (+0.1)
*/
function checkin($filename, $reason, $tempfilename, $major_update=false)
{
if (!is_file($tempfilename))
{
return new PEAR_Error('File does not exist.');
}
$user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
if (!$this->document->getIsCheckedOut())
{
return new PEAR_Error(KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT);
}
$filename = KTUtil::replaceInvalidCharacters($filename);
$options = array('major_update'=>$major_update);
$currentfilename = $this->document->getFileName();
if ($filename != $currentfilename)
{
$options['newfilename'] = $filename;
}
DBUtil::startTransaction();
$result = KTDocumentUtil::checkin($this->document, $tempfilename, $reason, $user, $options);
if (PEAR::isError($result))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$result);
}
DBUtil::commit();
KTUploadManager::temporary_file_imported($tempfilename);
}
/**
* Removes the update notification for the document
*
* @author KnowledgeTree Team
* @access public
*/
function removeUpdateNotification()
{
$sql = "DELETE FROM notifications WHERE data_int_1=$this->documentid AND data_str_1='ModifyDocument'";
DBUtil::runQuery($sql);
}
/**
* Creates a link between two documents
*
* @author KnowledgeTree Team
* @access public
* @param KTAPI_Document $document The document object
* @param string $type The link relationship type: depended on|Attachment|Reference|Copy|Default
* @return PEAR_Error|void Returns nothing on success | a PEAR_Error object on failure
*
*/
function link_document($document, $type)
{
$typeid = $this->ktapi->get_link_type_id($type);
if (PEAR::isError($typeid))
{
return $typeid;
}
$link = new DocumentLink($this->get_documentid(), $document->get_documentid(), $typeid );
$created = $link->create();
if ($created === false || PEAR::isError($created))
{
return new PEAR_Error(_kt('Could not create link'));
}
}
/**
* Removes the link between two documents
*
* @author KnowledgeTree Team
* @access public
* @param KTAPI_Document $document The document object
* @return PEAR_Error|void Returns nothing on success | a PEAR_Error object on failure
*/
function unlink_document($document)
{
$sql = "DELETE FROM document_link WHERE parent_document_id=$this->documentid AND child_document_id=$document->documentid";
$result = DBUtil::runQuery($sql);
if (empty($result) || PEAR::isError($created))
{
return new PEAR_Error(_kt('Could not remove link'));
}
}
/**
* Checks whether the document has been checked out.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* if($document->is_checked_out()){
* continue;
* }else{
* $document->checkout('Reason for document checkout');
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @return boolean TRUE if checked out | FALSE if not
*/
function is_checked_out()
{
return ($this->document->getIsCheckedOut());
}
/**
* Cancels the checkout on a document
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* if($document->is_checked_out()){
* $document->undo_checkout('Reason for cancelling checkout');
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param string $reason The reason for cancelling
* @return PEAR_Error|void Returns nothing on success | a PEAR_Error on failure
*/
function undo_checkout($reason)
{
$user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
if (!$this->document->getIsCheckedOut())
{
return new PEAR_Error(KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT);
}
DBUtil::startTransaction();
$this->document->setIsCheckedOut(0);
$this->document->setCheckedOutUserID(-1);
$res = $this->document->update();
if (($res === false) || PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res);
}
$oDocumentTransaction = new DocumentTransaction($this->document, $reason, 'ktcore.transactions.force_checkin');
$res = $oDocumentTransaction->create();
if (($res === false) || PEAR::isError($res)) {
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res);
}
DBUtil::commit();
}
/**
* Gets a list of linked documents
*
* @author KnowledgeTree Team
* @access public
* @return array|PEAR_Error Returns a list of linked documents on success | a PEAR_Error on failure
*/
function get_linked_documents()
{
$sql = "
SELECT
dl.child_document_id as document_id,
dmv.name as title,
dcv.size,
w.name as workflow,
ws.name as workflow_state,
dlt.name as link_type, dtl.name as document_type,
dcv.major_version, dcv.minor_version, d.oem_no
FROM
document_link dl
INNER JOIN document_link_types dlt ON dl.link_type_id=dlt.id
INNER JOIN documents d ON dl.child_document_id=d.id
INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id
INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id
INNER JOIN document_types_lookup dtl ON dtl.id=dmv.document_type_id
LEFT OUTER JOIN workflow_documents wd ON d.id=wd.document_id
LEFT OUTER JOIN workflows w ON w.id=wd.workflow_id
LEFT OUTER JOIN workflow_states ws ON wd.state_id=ws.id
WHERE
dl.parent_document_id=$this->documentid
";
$rows = DBUtil::getResultArray($sql);
if (PEAR::isError($rows))
{
return $rows;
}
$result=array();
$read_permission = &KTPermission::getByName(KTAPI_PERMISSION_READ);
$user = $this->ktapi->get_user();
foreach($rows as $row)
{
$document = Document::get($row['document_id']);
if (PEAR::isError($document) || is_null($document))
{
continue;
}
if(!KTPermissionUtil::userHasPermissionOnItem($user, $read_permission, $document))
{
continue;
}
$oem_no = $row['oem_no'];
if (empty($oem_no)) $oem_no = 'n/a';
$result[] = array(
'document_id'=>(int)$row['document_id'],
'custom_document_no'=>'n/a',
'oem_document_no'=>$oem_no,
'title'=> $row['title'],
'document_type'=> $row['document_type'],
'version'=> (float) ($row['major_version'] . '.' . $row['minor_version']),
'filesize'=>(int)$row['size'],
'workflow'=>empty($row['workflow'])?'n/a':$row['workflow'],
'workflow_state'=>empty($row['workflow_state'])?'n/a':$row['workflow_state'],
'link_type'=>empty($row['link_type'])?'unknown':$row['link_type'],
);
}
return $result;
}
/**
* Checks out a document
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $document->checkout('Reason for document checkout');
* if($document->is_checked_out()){
* continue;
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param string $reason The reason for checking out the document
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function checkout($reason)
{
$user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
//if the document is checked-out by the current user, just return
//as no need to check-out again BUT we do need to download
//returning here will allow download, but skip check-out
if ( ($this->document->getIsCheckedOut()) &&
($this->document->getCheckedOutUserID() == $_SESSION['userID']) )
{
return;
}
DBUtil::startTransaction();
$res = KTDocumentUtil::checkout($this->document, $reason, $user);
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
}
DBUtil::commit();
}
/**
* Deletes a document from the folder.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $document->delete('Reason for deletion');
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param string $reason The reason for deleting the document
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function delete($reason)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_DELETE);
if (PEAR::isError($user))
{
return $user;
}
if ($this->document->getIsCheckedOut())
{
return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
}
DBUtil::startTransaction();
$res = KTDocumentUtil::delete($this->document, $reason);
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
}
DBUtil::commit();
}
/**
* Changes the owner of a document and updates its permissions.
*
* @author KnowledgeTree Team
* @access public
* @param string $newusername The username of the new owner
* @param string $reason The reason for changing the owner
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function change_owner($newusername, $reason='Changing of owner.')
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_CHANGE_OWNERSHIP);
if (PEAR::isError($user))
{
return $user;
}
DBUtil::startTransaction();
$user = &User::getByUserName($newusername);
if (is_null($user) || PEAR::isError($user))
{
return new KTAPI_Error('User could not be found',$user);
}
$newuserid = $user->getId();
$this->document->setOwnerID($newuserid);
$res = $this->document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR ,$res );
}
$res = KTPermissionUtil::updatePermissionLookup($this->document);
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
$oDocumentTransaction = new DocumentTransaction($this->document, $reason, 'ktcore.transactions.permissions_change');
$res = $oDocumentTransaction->create();
if (($res === false) || PEAR::isError($res)) {
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
DBUtil::commit();
}
/**
* Copies the document from one folder to another.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $newFolder = $this->root->add_folder("New folder");
* $copyOfDoc = $document->copy($newFolder, 'Reason for copying document');
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param KTAPI_Folder $ktapi_target_folder The new parent folder where the document is being copied into
* @param string $reason The reason for the copy
* @param string $newname Optional. The title of the document to be used in the case of a name clash
* @param string $newfilename Optional. The filename of the document to be used in the case of a name clash
* @return KTAPI_Document|PEAR_Error Returns the new KTAPI Document object | a PEAR_Error on failure
*/
function copy(&$ktapi_target_folder, $reason, $newname=null, $newfilename=null)
{
assert(!is_null($ktapi_target_folder));
assert($ktapi_target_folder instanceof KTAPI_FOLDER); //is_a($ktapi_target_folder,'KTAPI_Folder'));
if (empty($newname))
{
$newname=null;
}
if (empty($newfilename))
{
$newfilename=null;
}
$user = $this->ktapi->get_user();
if ($this->document->getIsCheckedOut())
{
return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
}
$target_folder = &$ktapi_target_folder->get_folder();
$result = $this->can_user_access_object_requiring_permission($target_folder, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($result))
{
return $result;
}
$name = $this->document->getName();
$clash = KTDocumentUtil::nameExists($target_folder, $name);
if ($clash && !is_null($newname))
{
$name = $newname;
$clash = KTDocumentUtil::nameExists($target_folder, $name);
}
if ($clash)
{
if (is_null($newname))
{
$name = KTDocumentUtil::getUniqueDocumentName($target_folder, $name);
}
else
{
return new PEAR_Error('A document with this title already exists in your chosen folder. '
. 'Please choose a different folder, or specify a new title for the copied document.');
}
}
$filename=$this->document->getFilename();
$clash = KTDocumentUtil::fileExists($target_folder, $filename);
if ($clash && !is_null($newname))
{
$filename = $newfilename;
$clash = KTDocumentUtil::fileExists($target_folder, $filename);
}
if ($clash)
{
if (is_null($newfilename))
{
$filename = KTDocumentUtil::getUniqueFilename($target_folder, $newfilename);
}
else
{
return new PEAR_Error('A document with this filename already exists in your chosen folder. '
. 'Please choose a different folder, or specify a new filename for the copied document.');
}
}
DBUtil::startTransaction();
$new_document = KTDocumentUtil::copy($this->document, $target_folder, $reason);
if (PEAR::isError($new_document))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$new_document );
}
$new_document->setName($name);
$new_document->setFilename($filename);
$res = $new_document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
DBUtil::commit();
/*
// 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' => $new_document,
'old_folder' => $this->ktapi_folder->get_folder(),
'new_folder' => $target_folder,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
*/
return KTAPI_Document::get($this->ktapi, $new_document->getId());
}
/**
* Moves the document from one folder to another.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $newFolder = $this->root->add_folder("New folder");
* $document->move($newFolder, 'Reason for moving the document');
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param KTAPI_Folder $ktapi_target_folder The folder object where the document is being moved into
* @param string $reason The reason for the move
* @param string $newname Optional. The title of the document to be used in the case of a name clash
* @param string $newfilename Optional. The filename of the document to be used in the case of a name clash
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function move(&$ktapi_target_folder, $reason, $newname=null, $newfilename=null)
{
assert(!is_null($ktapi_target_folder));
assert($ktapi_target_folder instanceof KTAPI_Folder); // is_a($ktapi_target_folder,'KTAPI_Folder'));
if (empty($newname))
{
$newname=null;
}
if (empty($newfilename))
{
$newfilename=null;
}
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_DOCUMENT_MOVE);
if (PEAR::isError($user))
{
return $user;
}
if ($this->document->getIsCheckedOut())
{
return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
}
$target_folder = $ktapi_target_folder->get_folder();
$result= $this->can_user_access_object_requiring_permission( $target_folder, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($result))
{
return $result;
}
if (!KTDocumentUtil::canBeMoved($this->document, $error))
{
if (PEAR::isError($error))
{
return $error;
}
else
{
return new PEAR_Error('Document cannot be moved.');
}
}
$name = $this->document->getName();
$clash = KTDocumentUtil::nameExists($target_folder, $name);
if ($clash && !is_null($newname))
{
$name = $newname;
$clash = KTDocumentUtil::nameExists($target_folder, $name);
}
if ($clash)
{
return new PEAR_Error('A document with this title already exists in your chosen folder. '
. 'Please choose a different folder, or specify a new title for the moved document.');
}
$filename=$this->document->getFilename();
$clash = KTDocumentUtil::fileExists($target_folder, $filename);
if ($clash && !is_null($newname))
{
$filename = $newfilename;
$clash = KTDocumentUtil::fileExists($target_folder, $filename);
}
if ($clash)
{
return new PEAR_Error('A document with this filename already exists in your chosen folder. '
. 'Please choose a different folder, or specify a new filename for the moved document.');
}
DBUtil::startTransaction();
$res = KTDocumentUtil::move($this->document, $target_folder, $user, $reason);
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res );
}
$this->document->setName($name);
$this->document->setFilename($filename);
$res = $this->document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
DBUtil::commit();
}
/**
* Changes the filename of the document.
* If the filename contains any invalid characters they are replaced with a dash (-). For example: ?, *, %, \, /
*
* @author KnowledgeTree Team
* @access public
* @param string $newname The new filename
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function renameFile($newname)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
$newname = KTUtil::replaceInvalidCharacters($newname);
DBUtil::startTransaction();
$res = KTDocumentUtil::rename($this->document, $newname, $user);
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
DBUtil::commit();
}
/**
* Changes the document type of the document.
*
* @author KnowledgeTree Team
* @access public
* @param string $documenttype The new document type
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function change_document_type($documenttype)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
$doctypeid = KTAPI::get_documenttypeid($documenttype);
if (PEAR::isError($doctypeid))
{
return $doctypeid;
}
if ($this->document->getDocumentTypeId() != $doctypeid)
{
// Get the current document type, fieldsets and metadata
$iOldDocTypeID = $this->document->getDocumentTypeID();
$fieldsets = KTMetadataUtil::fieldsetsForDocument($this->document, $iOldDocTypeID);
$mdlist = DocumentFieldLink::getByDocument($this->document);
$field_values = array();
foreach ($mdlist as $oFieldLink) {
$field_values[$oFieldLink->getDocumentFieldID()] = $oFieldLink->getValue();
}
DBUtil::startTransaction();
$this->document->startNewMetadataVersion($user);
$this->document->setDocumentTypeId($doctypeid);
$res = $this->document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR,$res );
}
// Ensure all values for fieldsets common to both document types are retained
$fs_ids = array();
$doctype_fieldsets = KTFieldSet::getForDocumentType($doctypeid);
foreach($doctype_fieldsets as $fieldset)
{
$fs_ids[] = $fieldset->getId();
}
$MDPack = array();
foreach ($fieldsets as $oFieldset)
{
if ($oFieldset->getIsGeneric() || in_array($oFieldset->getId(), $fs_ids))
{
$fields = $oFieldset->getFields();
foreach ($fields as $oField)
{
$val = isset($field_values[$oField->getId()]) ? $field_values[$oField->getId()] : '';
if (!empty($val))
{
$MDPack[] = array($oField, $val);
}
}
}
}
$core_res = KTDocumentUtil::saveMetadata($this->document, $MDPack, array('novalidate' => true));
if (PEAR::isError($core_res)) {
DBUtil::rollback();
return $core_res;
}
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('edit', 'postValidate');
foreach ($aTriggers as $aTrigger)
{
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
"document" => $this->document,
"aOptions" => $packed,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
DBUtil::commit();
}
}
/**
* Changes the title of the document.
* If the title contains any invalid characters they are replaced with a dash (-). For example: ?, *, %, \, /
*
* @author KnowledgeTree Team
* @access public
* @param string $newname The new document title
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function rename($newname)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
$newname = KTUtil::replaceInvalidCharacters($newname);
if ($this->document->getName() != $newname)
{
DBUtil::startTransaction();
$this->document->setName($newname);
$res = $this->document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
}
DBUtil::commit();
}
}
/**
* Sets the status of the document to 'archived'.
*
* @author KnowledgeTree Team
* @access public
* @param string $reason The reason for archiving the document
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function archive($reason)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
if (PEAR::isError($user))
{
return $user;
}
DBUtil::startTransaction();
$res = KTDocumentUtil::archive($this->document, $reason);
if(PEAR::isError($res)){
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
}
DBUtil::commit();
/*
list($permission, $user) = $perm_and_user;
DBUtil::startTransaction();
$this->document->setStatusID(ARCHIVED);
$res = $this->document->update();
if (($res === false) || PEAR::isError($res)) {
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
}
$oDocumentTransaction = new DocumentTransaction($this->document, sprintf(_kt('Document archived: %s'), $reason), 'ktcore.transactions.update');
$oDocumentTransaction->create();
DBUtil::commit();
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
foreach ($aTriggers as $aTrigger)
{
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
'document' => $this->document,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
*/
}
/**
* Starts a workflow on a document.
*
* @author KnowledgeTree Team
* @access public
* @param string $workflow The workflow being applied
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function start_workflow($workflow)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
if (PEAR::isError($user))
{
return $user;
}
$workflowid = $this->document->getWorkflowId();
if (!empty($workflowid))
{
return new PEAR_Error('A workflow is already defined.');
}
$workflow = KTWorkflow::getByName($workflow);
if (is_null($workflow) || PEAR::isError($workflow))
{
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $workflow);
}
DBUtil::startTransaction();
$result = KTWorkflowUtil::startWorkflowOnDocument($workflow, $this->document);
if (is_null($result) || PEAR::isError($result))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $result);
}
DBUtil::commit();
}
/**
* This deletes the workflow on the document.
*
* @author KnowledgeTree Team
* @access public
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function delete_workflow()
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
if (PEAR::isError($user))
{
return $user;
}
$workflowid=$this->document->getWorkflowId();
if (empty($workflowid))
{
return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
}
DBUtil::startTransaction();
$result = KTWorkflowUtil::startWorkflowOnDocument(null, $this->document);
if (is_null($result) || PEAR::isError($result))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID,$result);
}
DBUtil::commit();
}
/**
* This performs a transition to a new state of the workflow on the document
*
* @author KnowledgeTree Team
* @access public
* @param string $transition The transition to perform
* @param string $reason The reason for transitioning the document to a new state
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function perform_workflow_transition($transition, $reason)
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
if (PEAR::isError($user))
{
return $user;
}
$workflowid=$this->document->getWorkflowId();
if (empty($workflowid))
{
return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
}
$transition = &KTWorkflowTransition::getByName($transition);
if (is_null($transition) || PEAR::isError($transition))
{
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $transition);
}
DBUtil::startTransaction();
$result = KTWorkflowUtil::performTransitionOnDocument($transition, $this->document, $user, $reason);
if (is_null($result) || PEAR::isError($result))
{
DBUtil::rollback();
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $transition);
}
DBUtil::commit();
}
/**
* This returns all metadata for the document.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $metadata = $document->get_metadata();
* foreach($metadata as $fieldset){
* echo '<br><br>Fieldset: '.$fieldset['fieldset'];
*
* foreach($fieldset['fields'] as $field){
* echo '<br>Field name: '.$field['name'] . ' Value: '. $field['value'];
* }
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @return array An array of metadata fieldsets and fields
*/
function get_metadata()
{
$doctypeid = $this->document->getDocumentTypeID();
$fieldsets = (array) KTMetadataUtil::fieldsetsForDocument($this->document, $doctypeid);
if (is_null($fieldsets) || PEAR::isError($fieldsets))
{
return array();
}
$results = array();
foreach ($fieldsets as $fieldset)
{
if ($fieldset->getIsConditional()) { /* this is not implemented...*/ continue; }
$fields = $fieldset->getFields();
$result = array('fieldset' => $fieldset->getName(),
'description' => $fieldset->getDescription());
$fieldsresult = array();
foreach ($fields as $field)
{
$value = '';
$fieldvalue = DocumentFieldLink::getByDocumentAndField($this->document, $field);
if (!is_null($fieldvalue) && (!PEAR::isError($fieldvalue)))
{
$value = $fieldvalue->getValue();
}
// Old
//$controltype = 'string';
// Replace with true
$controltype = strtolower($field->getDataType());
if ($field->getHasLookup())
{
$controltype = 'lookup';
if ($field->getHasLookupTree())
{
$controltype = 'tree';
}
}
// Options - Required for Custom Properties
$options = array();
if ($field->getInetLookupType() == 'multiwithcheckboxes' || $field->getInetLookupType() == 'multiwithlist') {
$controltype = 'multiselect';
}
switch ($controltype)
{
case 'lookup':
$selection = KTAPI::get_metadata_lookup($field->getId());
break;
case 'tree':
$selection = KTAPI::get_metadata_tree($field->getId());
break;
case 'large text':
$options = array(
'ishtml' => $field->getIsHTML(),
'maxlength' => $field->getMaxLength()
);
$selection= array();
break;
case 'multiselect':
$selection = KTAPI::get_metadata_lookup($field->getId());
$options = array(
'type' => $field->getInetLookupType()
);
break;
default:
$selection= array();
}
$fieldsresult[] = array(
'name' => $field->getName(),
'required' => $field->getIsMandatory(),
'value' => $value == '' ? 'n/a' : $value,
'blankvalue' => $value=='' ? '1' : '0',
'description' => $field->getDescription(),
'control_type' => $controltype,
'selection' => $selection,
'options' => $options,
);
}
$result['fields'] = $fieldsresult;
$results [] = $result;
}
return $results;
}
/**
* Gets a simple array of document metadata fields
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $metadata = $document->get_packed_metadata();
* foreach($metadata as $field){
* echo '<br><br>Fieldset: ' . $field[0]->getParentFieldset();
* echo '<br>Field name: ' .$field[0]->getName();
* echo ' Value: ' . $field[1];
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param array $metadata The full metadata fieldsets and fields
* @return array An array of metadata field object and value pairs
*/
function get_packed_metadata($metadata=null)
{
global $default;
if (is_null($metadata))
{
$metadata = $this->get_metadata();
}
$packed = array();
foreach($metadata as $fieldset_metadata)
{
if (is_array($fieldset_metadata))
{
$fieldsetname=$fieldset_metadata['fieldset'];
$fields=$fieldset_metadata['fields'];
}
elseif ($fieldset_metadata instanceof stdClass) //is_a($fieldset_metadata, 'stdClass'))
{
$fieldsetname=$fieldset_metadata->fieldset;
$fields=$fieldset_metadata->fields;
}
else
{
$default->log->debug("unexpected fieldset type");
continue;
}
$fieldset = KTFieldset::getByName($fieldsetname);
if (is_null($fieldset) || PEAR::isError($fieldset) || $fieldset instanceof KTEntityNoObjects) //is_a($fieldset, 'KTEntityNoObjects'))
{
$default->log->debug("could not resolve fieldset: $fieldsetname for document id: $this->documentid");
// exit graciously
continue;
}
foreach($fields as $fieldinfo)
{
if (is_array($fieldinfo))
{
$fieldname = $fieldinfo['name'];
$value = $fieldinfo['value'];
}
elseif ($fieldinfo instanceof stdClass) // is_a($fieldinfo, 'stdClass'))
{
$fieldname = $fieldinfo->name;
$value = $fieldinfo->value;
}
else
{
$default->log->debug("unexpected fieldinfo type");
continue;
}
$field = DocumentField::getByFieldsetAndName($fieldset, $fieldname);
if (is_null($field) || PEAR::isError($field) || is_a($field, 'KTEntityNoObjects'))
{
$default->log->debug("Could not resolve field: $fieldname on fieldset $fieldsetname for document id: $this->documentid");
// exit graciously
continue;
}
$packed[] = array($field, $value);
}
}
return $packed;
}
/**
* This updates the metadata on the document. This includes the 'title'.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $metadata = $document->get_metadata();
* foreach($metadata as $key => $fieldset){
* if($fieldset['fieldset'] == 'XYZ'){
*
* foreach($fieldset['fields'] as $k => $field){
* if($field['name'] == 'ABC'){
* $metadata[$key][fields][$k]['value'] = 'new value';
* }
* }
* }
* }
*
* $res = $document->update_metadata($metadata);
* </code>
*
* @author KnowledgeTree Team
* @access public
* @param array This is an array containing the metadata to be associated with the document.
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function update_metadata($metadata)
{
global $default;
if (empty($metadata))
{
return;
}
$packed = $this->get_packed_metadata($metadata);
DBUtil::startTransaction();
$user = $this->ktapi->get_user();
$this->document->setLastModifiedDate(getCurrentDateTime());
$this->document->setModifiedUserId($user->getId());
// Update the content version / document version
if($default->updateContentVersion){
$this->document->startNewContentVersion($user);
$this->document->setMinorVersionNumber($this->document->getMinorVersionNumber()+1);
}else {
$this->document->startNewMetadataVersion($user);
}
$res = $this->document->update();
if (PEAR::isError($res))
{
DBUtil::rollback();
return new KTAPI_Error('Unexpected failure updating document', $res);
}
$result = KTDocumentUtil::saveMetadata($this->document, $packed, array('novalidate'=>true));
if (is_null($result))
{
DBUtil::rollback();
return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR . ': Null result returned but not expected.');
}
if (PEAR::isError($result))
{
DBUtil::rollback();
return new KTAPI_Error('Unexpected validation failure', $result);
}
DBUtil::commit();
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('edit', 'postValidate');
foreach ($aTriggers as $aTrigger) {
$sTrigger = $aTrigger[0];
$oTrigger = new $sTrigger;
$aInfo = array(
"document" => $this->document,
"aOptions" => $packed,
);
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
}
/**
* This updates the system metadata on the document.
*
* @author KnowledgeTree Team
* @access public
* @param array $sysdata The system metadata to be applied
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function update_sysdata($sysdata)
{
global $default;
if (empty($sysdata))
{
return;
}
$owner_mapping = array(
'created_by'=>'creator_id',
'modified_by'=>'modified_user_id',
'owner'=>'owner_id'
);
$documents = array();
$document_content = array();
$indexContent = null;
$uniqueOemNo = false;
foreach($sysdata as $rec)
{
if (is_object($rec))
{
$name = $rec->name;
$value = sanitizeForSQL($rec->value);
}
elseif(is_array($rec))
{
$name = $rec['name'];
$value = sanitizeForSQL($rec['value']);
}
else
{
// just ignore
continue;
}
switch(strtolower($name))
{
case 'unique_oem_document_no':
$documents['oem_no'] = $value;
$uniqueOemNo = true;
break;
case 'oem_document_no':
$documents['oem_no'] = $value;
break;
case 'index_content':
$indexContent = $value;
break;
case 'created_date':
if (!empty($value)) $documents['created'] = $value;
break;
case 'modified_date':
if (!empty($value)) $documents['modified'] = $value;
break;
case 'is_immutable':
$documents['immutable'] = in_array(strtolower($value), array('1','true','on','yes'))?'1':'0';
break;
case 'filename':
$value = KTUtil::replaceInvalidCharacters($value);
$document_content['filename'] = $value;
break;
case 'major_version':
$document_content['major_version'] = $value;
break;
case 'minor_version':
$document_content['minor_version'] = $value;
break;
case 'version':
list($major_version, $minor_version) = explode('.', $value);
$document_content['major_version'] = $major_version;
$document_content['minor_version'] = $minor_version;
break;
case 'mime_type':
$sql = "select id from mime_types where mimetypes='$value'";
$value = DBUtil::getResultArray($sql);
if (PEAR::isError($value))
{
$default->log->error("Problem resolving mime type '$value' for document id $this->documentid. Reason: " . $value->getMessage());
return $value;
}
if (count($value) == 0)
{
$default->log->error("Problem resolving mime type '$value' for document id $this->documentid. None found.");
break;
}
$value = $value[0]['id'];
$document_content['mime_id'] = $value;
break;
case 'owner':
case 'created_by':
case 'modified_by':
$sql = "select id from users where name='$value'";
$userId = DBUtil::getResultArray($sql);
if (PEAR::isError($userId))
{
$default->log->error("Problem resolving user '$value' for document id $this->documentid. Reason: " . $userId->getMessage());
return $userId;
}
if (empty($userId))
{
$sql = "select id from users where username='$value'";
$userId = DBUtil::getResultArray($sql);
if (PEAR::isError($userId))
{
$default->log->error("Problem resolving username '$value' for document id $this->documentid. Reason: " . $userId->getMessage());
return $userId;
}
}
if (empty($userId))
{
$default->log->error("Problem resolving user based on '$value' for document id $this->documentid. No user found");
// if not found, not much we can do
break;
}
$userId=$userId[0];
$userId=$userId['id'];
$name = $owner_mapping[$name];
$documents[$name] = $userId;
break;
default:
$default->log->error("Problem updating field '$name' with value '$value' for document id $this->documentid. Field is unknown.");
// TODO: we should do some logging
//return new PEAR_Error('Unexpected field: ' . $name);
}
}
if (count($documents) > 0)
{
$sql = "UPDATE documents SET ";
$i=0;
foreach($documents as $name=>$value)
{
if ($i++ > 0) $sql .= ",";
$value = sanitizeForSQL($value);
$sql .= "$name='$value'";
}
$sql .= " WHERE id=$this->documentid";
$result = DBUtil::runQuery($sql);
if (PEAR::isError($result))
{
return $result;
}
if ($uniqueOemNo)
{
$oem_no = sanitizeForSQL($documents['oem_no']);
$sql = "UPDATE documents SET oem_no=null WHERE oem_no = '$oem_no' AND id != $this->documentid";
$result = DBUtil::runQuery($sql);
}
}
if (count($document_content) > 0)
{
$content_id = $this->document->getContentVersionId();
$sql = "UPDATE document_content_version SET ";
$i=0;
foreach($document_content as $name=>$value)
{
if ($i++ > 0) $sql .= ",";
$value = sanitizeForSQL($value);
$sql .= "$name='$value'";
}
$sql .= " WHERE id=$content_id";
$result = DBUtil::runQuery($sql);
if (PEAR::isError($result))
{
return $result;
}
}
if (!is_null($indexContent))
{
$indexer = Indexer::get();
$result = $indexer->diagnose();
if (empty($result))
{
$indexer->updateDocumentIndex($this->documentid, $indexContent);
}
else
{
$default->log->error("Problem updating index with value '$value' for document id $this->documentid. Problem with indexer.");
}
}
}
/**
* Clears the cached data on the document and refreshes the document object.
*
* @author KnowledgeTree Team
* @access public
*/
function clearCache()
{
// TODO: we should only clear the cache for the document we are working on
// this is a quick fix but not optimal!!
$metadataid = $this->document->getMetadataVersionId();
$contentid = $this->document->getContentVersionId();
$cache = KTCache::getSingleton();
$cache->remove('KTDocumentMetadataVersion/id', $metadataid);
$cache->remove('KTDocumentContentVersion/id', $contentid);
$cache->remove('KTDocumentCore/id', $this->documentid);
$cache->remove('Document/id', $this->documentid);
unset($GLOBALS['_OBJECTCACHE']['KTDocumentMetadataVersion'][$metadataid]);
unset($GLOBALS['_OBJECTCACHE']['KTDocumentContentVersion'][$contentid]);
unset($GLOBALS['_OBJECTCACHE']['KTDocumentCore'][$this->documentid]);
$this->document = &Document::get($this->documentid);
}
/**
* Merge new metadata with previous metadata version
*
* @author KnowledgeTree Team
* @access public
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function mergeWithLastMetadataVersion()
{
// keep latest metadata version
$metadata_version = $this->document->getMetadataVersion();
if ($metadata_version == 0)
{
// this could theoretically happen in the case we are updating metadata and sysdata, but no metadata fields are specified.
return;
}
$metadata_id = $this->document->getMetadataVersionId();
// get previous version
$sql = "SELECT id, metadata_version FROM document_metadata_version WHERE id<$metadata_id AND document_id=$this->documentid order by id desc";
$old = DBUtil::getResultArray($sql);
if (is_null($old) || PEAR::isError($old))
{
return new PEAR_Error('Previous version could not be resolved');
}
// only interested in the first one
$old=$old[0];
$old_metadata_id = $old['id'];
$old_metadata_version = $old['metadata_version'];
DBUtil::startTransaction();
// delete previous metadata version
$sql = "DELETE FROM document_metadata_version WHERE id=$old_metadata_id";
$rs = DBUtil::runQuery($sql);
if (PEAR::isError($rs))
{
DBUtil::rollback();
return $rs;
}
// make latest equal to previous
$sql = "UPDATE document_metadata_version SET metadata_version=$old_metadata_version WHERE id=$metadata_id";
$rs = DBUtil::runQuery($sql);
if (PEAR::isError($rs))
{
DBUtil::rollback();
return $rs;
}
$sql = "UPDATE documents SET metadata_version=$old_metadata_version WHERE id=$this->documentid";
$rs = DBUtil::runQuery($sql);
if (PEAR::isError($rs))
{
DBUtil::rollback();
return $rs;
}
DBUtil::commit();
$this->clearCache();
}
/**
* This returns the workflow transitions available for the user on the document
*
* @author KnowledgeTree Team
* @access public
* @return array|PEAR_Error Array of the workflow transitions | a PEAR_Error on failure
*/
function get_workflow_transitions()
{
$user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
if (PEAR::isError($user))
{
return $user;
}
$workflowid=$this->document->getWorkflowId();
if (empty($workflowid))
{
return array();
}
$result = array();
$transitions = KTWorkflowUtil::getTransitionsForDocumentUser($this->document, $user);
if (is_null($transitions) || PEAR::isError($transitions))
{
return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $transitions);
}
foreach($transitions as $transition)
{
$result[] = $transition->getName();
}
return $result;
}
/**
* This returns the current workflow state
*
* @author KnowledgeTree Team
* @access public
* @return string Returns the name of the state | a PEAR_Error on failure
*/
function get_workflow_state()
{
$user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WORKFLOW);
if (PEAR::isError($user))
{
return $user;
}
$workflowid=$this->document->getWorkflowId();
if (empty($workflowid))
{
return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
}
$result = array();
$state = KTWorkflowUtil::getWorkflowStateForDocument($this->document);
if (is_null($state) || PEAR::isError($state))
{
return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
}
$statename = $state->getName();
return $statename;
}
/**
* Get the available permissions on the document.
* R = read, W = write, E = edit - if the document is checked out by the user.
* The method assumes read permissions is available.
*
* @author KnowledgeTree Team
* @access public
* @param Document $document The internal document object
* @return string The available permissions
*/
function get_permission_string($document)
{
$perms = 'R';
if (Permission::userHasDocumentWritePermission($document))
{
$perms .= 'W';
$user_id = $_SESSION['userID'];
$co_user_id = $document->getCheckedOutUserID();
if (!empty($co_user_id) && ($user_id == $co_user_id))
{
$perms .= 'E';
}
}
return $perms;
}
/**
* This returns detailed information on the document.
*
* @author KnowledgeTree Team
* @access public
* @return array The document information
*/
function get_detail()
{
global $default;
// make sure we ge tthe latest
$this->clearCache();
$config = KTConfig::getSingleton();
$wsversion = $config->get('webservice/version', LATEST_WEBSERVICE_VERSION);
$detail = array();
$document = $this->document;
// get the document id
$detail['document_id'] = (int) $document->getId();
$oem_document_no = null;
if ($wsversion >= 2)
{
$oem_document_no = $document->getOemNo();
}
if (empty($oem_document_no))
{
$oem_document_no = 'n/a';
}
$detail['custom_document_no'] = 'n/a';
$detail['oem_document_no'] = $oem_document_no;
// get the title
$detail['title'] = $document->getName();
// get the document type
$documenttypeid=$document->getDocumentTypeID();
$documenttype = '* unknown *';
if (is_numeric($documenttypeid))
{
$dt = DocumentType::get($documenttypeid);
if (!is_null($dt) && !PEAR::isError($dt))
{
$documenttype=$dt->getName();
}
}
$detail['document_type'] = $documenttype;
// get the filename
$detail['filename'] = $document->getFilename();
// get the filesize
$detail['filesize'] = (int) $document->getFileSize();
// get the folder id
$detail['folder_id'] = (int) $document->getFolderID();
// get the creator
$userid = $document->getCreatorID();
$username='n/a';
if (is_numeric($userid))
{
$username = '* unknown *';
$user = User::get($userid);
if (!is_null($user) && !PEAR::isError($user))
{
$username = $user->getName();
}
}
$detail['created_by'] = $username;
// get the creation date
$detail['created_date'] = $document->getCreatedDateTime();
// get the checked out user
$userid = $document->getCheckedOutUserID();
$username='n/a';
if (is_numeric($userid))
{
$username = '* unknown *';
$user = User::get($userid);
if (!is_null($user) && !PEAR::isError($user))
{
$username = $user->getName();
}
}
$detail['checked_out_by'] = $username;
// get the checked out date
list($major, $minor, $fix) = explode('.', $default->systemVersion);
if ($major == 3 && $minor >= 5)
{
$detail['checked_out_date'] = $document->getCheckedOutDate();
}
else
{
$detail['checked_out_date'] = $detail['modified_date'];
}
if (is_null($detail['checked_out_date'])) $detail['checked_out_date'] = 'n/a';
// get the modified user
$userid = $document->getModifiedUserId();
$username='n/a';
if (is_numeric($userid))
{
$username = '* unknown *';
$user = User::get($userid);
if (!is_null($user) && !PEAR::isError($user))
{
$username = $user->getName();
}
}
$detail['modified_by'] = $detail['updated_by'] = $username;
// get the modified date
$detail['updated_date'] = $detail['modified_date'] = $document->getLastModifiedDate();
// get the owner
$userid = $document->getOwnerID();
$username='n/a';
if (is_numeric($userid))
{
$username = '* unknown *';
$user = User::get($userid);
if (!is_null($user) && !PEAR::isError($user))
{
$username = $user->getName();
}
}
$detail['owned_by'] = $username;
// get the version
$detail['version'] = $document->getVersion();
if ($wsversion >= 2)
{
$detail['version'] = (float) $detail['version'];
}
//get the content_id
$detail['content_id'] = $document->getContentVersionId();
//might be unset at the bottom in case of old webservice version
//make sure we're using the real document for this one
$this->document->switchToRealCore();
$detail['linked_document_id'] = $document->getLinkedDocumentId();
$this->document->switchToLinkedCore();
// check immutability
$detail['is_immutable'] = (bool) $document->getImmutable();
// check permissions
$detail['permissions'] = KTAPI_Document::get_permission_string($document);
// get workflow name
$workflowid = $document->getWorkflowId();
$workflowname='n/a';
if (is_numeric($workflowid))
{
$workflow = KTWorkflow::get($workflowid);
if (!is_null($workflow) && !PEAR::isError($workflow))
{
$workflowname = $workflow->getName();
}
}
$detail['workflow'] = $workflowname;
// get the workflow state
$stateid = $document->getWorkflowStateId();
$workflowstate = 'n/a';
if (is_numeric($stateid))
{
$state = KTWorkflowState::get($stateid);
if (!is_null($state) && !PEAR::isError($state))
{
$workflowstate = $state->getName();
}
}
$detail['workflow_state']=$workflowstate;
// get the full path
$detail['full_path'] = '/' . $this->document->getFullPath();
// get mime info
$mimetypeid = $document->getMimeTypeID();
$detail['mime_type'] =KTMime::getMimeTypeName($mimetypeid);
$detail['mime_icon_path'] =KTMime::getIconPath($mimetypeid);
$detail['mime_display'] =KTMime::getFriendlyNameForString($detail['mime_type']);
// get the storage path
$detail['storage_path'] = $document->getStoragePath();
if ($wsversion >= 2)
{
unset($detail['updated_by']);
unset($detail['updated_date']);
}
if($wsversion < 3){
unset($detail['linked_document_id']);
}
return $detail;
}
/**
* Gets the title of the document
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* $title = $document->get_title();
* </code>
*
* @author KnowledgeTree Team
* @access public
* @return string The document title
*/
function get_title()
{
return $this->document->getDescription();
}
/**
* Gets the url which can be used to download the document.
*
* @param int $version Not implemented. The content version of the document
*/
function get_download_url($version = null)
{
$session = $this->ktapi->get_session();
// Create the url that can be used to download the document
$download_manager = new KTDownloadManager();
$download_manager->set_session($session->session);
$download_manager->cleanup();
$url = $download_manager->allow_download($this);
// Log the transaction
$this->download();
return $url;
}
/**
* Logs the document transaction for a download.
*
* @author KnowledgeTree Team
* @access public
*/
function download()
{
$storage =& KTStorageManagerUtil::getSingleton();
$options = array();
$oDocumentTransaction = new DocumentTransaction($this->document, 'Document downloaded', 'ktcore.transactions.download', $aOptions);
$oDocumentTransaction->create();
}
/**
* Function to fetch the actual file content of a document
*
* @return $content the document file content
*/
function get_document_content()
{
// fetch the content
$content = KTDocumentUtil::getDocumentContent($this->document);
// TODO what if the file could not be found?
// Log the transaction
$this->download();
// return the document content
return $content;
}
/**
* This returns the transaction history for the document.
*
* @author KnowledgeTree Team
* @access public
* @return array The list of transactions | a PEAR_Error on failure
*/
function get_transaction_history()
{
$sQuery = 'SELECT DTT.name AS transaction_name, U.name AS username, 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->documentid);
$transactions = DBUtil::getResultArray(array($sQuery, $aParams));
if (is_null($transactions) || PEAR::isError($transactions))
{
return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $transactions );
}
$config = KTConfig::getSingleton();
$wsversion = $config->get('webservice/version', LATEST_WEBSERVICE_VERSION);
foreach($transactions as $key=>$transaction)
{
$transactions[$key]['version'] = (float) $transaction['version'];
}
return $transactions;
}
/**
* This returns the version history on the document.
*
* @author KnowledgeTree Team
* @access public
* @return array The version history
*/
function get_version_history()
{
$metadata_versions = KTDocumentMetadataVersion::getByDocument($this->document);
$config = KTConfig::getSingleton();
$wsversion = $config->get('webservice/version', LATEST_WEBSERVICE_VERSION);
$versions = array();
foreach ($metadata_versions as $version)
{
$document = &Document::get($this->documentid, $version->getId());
$version = array();
$userid = $document->getModifiedUserId();
$user = User::get($userid);
$username = 'Unknown';
if (!PEAR::isError($user))
{
$username = is_null($user)?'n/a':$user->getName();
}
$version['user'] = $username;
$version['metadata_version'] = $document->getMetadataVersion();
$version['content_version'] = $document->getVersion();
if ($wsversion >= 2)
{
$version['metadata_version'] = (int) $version['metadata_version'];
$version['content_version'] = (float) $version['content_version'];
}
$versions[] = $version;
}
return $versions;
}
/**
* This expunges a document from the system.
*
* <code>
* $ktapi = new KTAPI();
* $session = $ktapi->start_system_session();
* $document = $ktapi->get_document_by_id($documentid);
* if($document->is_deleted()){
* $document->expunge();
* }
* </code>
*
* @author KnowledgeTree Team
* @access public
* @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
*/
function expunge()
{
if ($this->document->getStatusID() != 3)
{
return new PEAR_Error('You should not purge this');
}
DBUtil::startTransaction();
$transaction = new DocumentTransaction($this->document, "Document expunged", 'ktcore.transactions.expunge');
$transaction->create();
$this->document->delete();
$this->document->cleanupDocumentData($this->documentid);
$storage =& KTStorageManagerUtil::getSingleton();
$result= $storage->expunge($this->document);
DBUtil::commit();
}
/**
* Restores a deleted document
*
* @author KnowledgeTree Team
* @access public
*/
function restore()
{
DBUtil::startTransaction();
$storage =& KTStorageManagerUtil::getSingleton();
$folder = Folder::get($this->document->getRestoreFolderId());
if (PEAR::isError($folder))
{
$this->document->setFolderId(1);
$folder = Folder::get(1);
}
else
{
$this->document->setFolderId($this->document->getRestoreFolderId());
}
$storage->restore($this->document);
$this->document->setStatusId(LIVE);
$this->document->setPermissionObjectId($folder->getPermissionObjectId());
$res = $this->document->update();
$res = KTPermissionUtil::updatePermissionLookup($this->document);
$user = $this->ktapi->get_user();
$oTransaction = new DocumentTransaction($this->document, 'Restored from deleted state by ' . $user->getName(), 'ktcore.transactions.update');
$oTransaction->create();
DBUtil::commit();
}
/**
* Returns the internal document object
*
* @author KnowledgeTree Team
* @access public
* @return Document The document object
*/
public function getObject()
{
return $this->document;
}
/**
* Get the role allocation for the document
*
* @return KTAPI_RoleAllocation Instance of the role allocation object
*/
public function getRoleAllocation()
{
$allocation = KTAPI_RoleAllocation::getAllocation($this->ktapi, $this);
return $allocation;
}
/**
* Get the permission allocation for the document
*
* @return KTAPI_PermissionAllocation Instance of the permission allocation object
*/
public function getPermissionAllocation()
{
$allocation = KTAPI_PermissionAllocation::getAllocation($this->ktapi, $this);
return $allocation;
}
/**
* Checks if the user is subscribed to the document
*
* @author KnowledgeTree Team
* @access public
* @return bool $result TRUE if subscribed | FALSE if not
*/
public function isSubscribed()
{
$subscriptionType = SubscriptionEvent::subTypes('Document');
$user = $this->ktapi->get_user();
$document = $this->document;
$result = Subscription::exists($user->getId(), $document->getId(), $subscriptionType);
return $result;
}
/**
* Removes the users subscription to the document
*
* @author KnowledgeTree Team
* @access public
* @return boolean|object $result SUCCESS Boolean result of operation | FAILURE - a pear error object
*/
public function unsubscribe()
{
if (!$this->isSubscribed())
{
return TRUE;
}
$subscriptionType = SubscriptionEvent::subTypes('Document');
$user = $this->ktapi->get_user();
$document = $this->document;
$subscription = & Subscription::getByIDs($user->getId(), $document->getId(), $subscriptionType);
$result = $subscription->delete();
if(PEAR::isError($result)){
return $result->getMessage();
}
if($result){
return $result;
}
return $_SESSION['errorMessage'];
}
/**
* Subscribes the user to the document
*
* @author KnowledgeTree Team
* @access public
* @return boolean|object $result SUCCESS Boolean result of operation | FAILURE - a pear error object
*/
public function subscribe()
{
if ($this->isSubscribed())
{
return TRUE;
}
$subscriptionType = SubscriptionEvent::subTypes('Document');
$user = $this->ktapi->get_user();
$document = $this->document;
$subscription = new Subscription($user->getId(), $document->getId(), $subscriptionType);
$result = $subscription->create();
if(PEAR::isError($result)){
return $result->getMessage();
}
if($result){
return $result;
}
return $_SESSION['errorMessage'];
}
/**
* Checks if the document is immutable
*
* @author KnowledgeTree Team
* @access public
* @return bool TRUE if it is immutable | FALSE if not
*/
public function isImmutable()
{
return $this->document->getImmutable();
}
/**
* Sets a document to be immutable
*
* @author KnowledgeTree Team
* @access public
*/
public function immute()
{
if($this->is_checked_out()){
return new PEAR_Error('Document is checked out and can\'t be set to immutable.');
}
$this->document->setImmutable(true);
$this->document->update();
}
/**
* Removes the immutability of a document
*
* @author KnowledgeTree Team
* @access public
*/
public function unimmute()
{
$this->document->setImmutable(false);
$this->document->update();
}
/**
* Emails a document as an attachment or hyperlink to a list of users, groups or external email addresses.
* In the case of external addresses, if a hyperlink is used then a timed download link (via webservices) is sent
* allowing the recipient a window period in which to download the document.
* The period is set through the webservices config option webservice/downloadExpiry. Defaults to 30 minutes.
*
* @author KnowledgeTree Team
* @access public
* @param array $members The email recipients - KTPAI_Users, KTAPI_Groups or email addresses
* @param string $comment Content to be appended to the email
* @param bool $attachDocument TRUE if document is an attachment | FALSE if using a hyperlink to the document
*
* NOTE this function requires that the Email Plugin be active.
* It seems that it is possible for this to be unintentionally turned off during a plugin re-read.
*/
public function email($members, $comment, $attachDocument = true)
{
// check for active email plugin
if (!KTPluginUtil::pluginIsActive('ktstandard.email.plugin')) {
return new PEAR_Error('Email Plugin is not active');
}
if (empty($members)) {
return new PEAR_Error('No recipients specified');
}
$userIds = array();
$groupIds = array();
$emailAddrs = array();
foreach($members as $member)
{
if ($member instanceof KTAPI_User) {
$userIds[] = $member->Id;
}
else if ($member instanceof KTAPI_Group) {
$groupIds[] = $member->Id;
}
else if (is_string($member)) {
$emailAddrs[] = $member;
}
}
$config = KTConfig::getSingleton();
$allowAttachment = $config->get('email/allowAttachment', false);
$allowEmailAddresses = $config->get('email/allowEmailAddresses', false);
// if attachments aren't allowed, set $attachDocument to false
if(!$allowAttachment) {
$attachDocument = false;
}
// If sending to external email addresses is not allowed - set array of external recipients to empty
if(!$allowEmailAddresses) {
$emailAddrs = array();
}
$emailErrors = array();
$userEmails = array();
$listEmails = array();
sendGroupEmails($groupIds, $userEmails, $emailErrors);
sendUserEmails($userIds, $userEmails, $emailErrors);
if ($attachDocument) {
sendManualEmails($emailAddrs, $userEmails, $emailErrors);
}
else {
sendExternalEmails($emailAddrs, $this->documentid, $this->get_title(), $comment, $emailErrors);
}
if(empty($userEmails)) {
return;
}
$listEmails = array_keys($userEmails);
sendEmail($listEmails, $this->documentid, $this->get_title(), $comment, (boolean)$attachDocument, $emailErrors);
}
/**
* Get a list of Documents
*
* @param String Where clause (not required)
* @return Array array of Documents objects, false otherwise.
*/
static public function getList($whereClause = null)
{
return Document::getList($whereClause);
}
}
?>