Commit 2b8c62f1c90d271d85ace810693bf8b83a54271f

Authored by conradverm
1 parent 81be23b6

KTS-1678

"Abstract KnowledgeTree API"
Implemented. Note that it is implemented for PHP5.

Reviewed By: Jalaloedien Abrahams

git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@6446 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing 1 changed file with 2508 additions and 0 deletions
ktapi/ktapi.inc.php 0 → 100644
  1 +<?
  2 +
  3 +/**
  4 + *
  5 + * Implements a cleaner wrapper API for KnowledgeTree.
  6 + *
  7 + * The contents of this file are subject to the KnowledgeTree Public
  8 + * License Version 1.1 ("License"); You may not use this file except in
  9 + * compliance with the License. You may obtain a copy of the License at
  10 + * http://www.knowledgetree.com/KPL
  11 + *
  12 + * Software distributed under the License is distributed on an "AS IS"
  13 + * basis,
  14 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15 + * for the specific language governing rights and limitations under the
  16 + * License.
  17 + *
  18 + * The Original Code is: KnowledgeTree Open Source
  19 + *
  20 + * The Initial Developer of the Original Code is The Jam Warehouse Software
  21 + * (Pty) Ltd, trading as KnowledgeTree.
  22 + * Portions created by The Jam Warehouse Software (Pty) Ltd are Copyright
  23 + * (C) 2007 The Jam Warehouse Software (Pty) Ltd;
  24 + * All Rights Reserved.
  25 + *
  26 + */
  27 +
  28 +require_once('../config/dmsDefaults.php');
  29 +require_once(KT_LIB_DIR . '/filelike/fsfilelike.inc.php');
  30 +require_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
  31 +
  32 +// Generic error messages used in the API. There may be some others specific to functionality
  33 +// directly in the code.
  34 +// TODO: Check that they are all relevant.
  35 +
  36 +define('KTAPI_ERROR_SESSION_INVALID', 'The session could not be resolved.');
  37 +define('KTAPI_ERROR_PERMISSION_INVALID', 'The permission could not be resolved.');
  38 +define('KTAPI_ERROR_FOLDER_INVALID', 'The folder could not be resolved.');
  39 +define('KTAPI_ERROR_DOCUMENT_INVALID', 'The document could not be resolved.');
  40 +define('KTAPI_ERROR_USER_INVALID', 'The user could not be resolved.');
  41 +define('KTAPI_ERROR_KTAPI_INVALID', 'The ktapi could not be resolved.');
  42 +define('KTAPI_ERROR_INSUFFICIENT_PERMISSIONS', 'The user does not have sufficient permissions to access the resource.');
  43 +define('KTAPI_ERROR_INTERNAL_ERROR', 'An internal error occurred. Please review the logs.');
  44 +define('KTAPI_ERROR_DOCUMENT_TYPE_INVALID', 'The document type could not be resolved.');
  45 +define('KTAPI_ERROR_DOCUMENT_CHECKED_OUT', 'The document is checked out.');
  46 +define('KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT', 'The document is not checked out.');
  47 +define('KTAPI_ERROR_WORKFLOW_INVALID', 'The workflow could not be resolved.');
  48 +define('KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS', 'The workflow is not in progress.');
  49 +
  50 +// Mapping of permissions to actions.
  51 +// TODO: Check that they are all correct.
  52 +// Note, currently, all core actions have permissions that are defined in the plugins.
  53 +// As the permissions are currently associated with actions which are quite closely linked
  54 +// to the web interface, it is not the nicest way to do things. They should be associated at
  55 +// a lower level, such as in the api. probably, better, would be at some stage to assocate
  56 +// the permissions to the action/transaction in the database so administrators can really customise
  57 +// as required.
  58 +
  59 +define('KTAPI_PERMISSION_DELETE', 'ktcore.permissions.delete');
  60 +define('KTAPI_PERMISSION_READ', 'ktcore.permissions.read');
  61 +define('KTAPI_PERMISSION_WRITE', 'ktcore.permissions.write');
  62 +define('KTAPI_PERMISSION_ADD_FOLDER', 'ktcore.permissions.addFolder');
  63 +define('KTAPI_PERMISSION_RENAME_FOLDER', 'ktcore.permissions.folder_rename');
  64 +define('KTAPI_PERMISSION_CHANGE_OWNERSHIP', 'ktcore.permissions.security');
  65 +define('KTAPI_PERMISSION_DOCUMENT_MOVE', 'ktcore.permissions.write');
  66 +define('KTAPI_PERMISSION_WORKFLOW', 'ktcore.permissions.workflow');
  67 +
  68 +//
  69 +
  70 +class KTAPI_Session
  71 +{
  72 + var $ktapi;
  73 + var $user = null;
  74 + var $session = '';
  75 + var $sessionid = -1;
  76 + var $ip = null;
  77 +
  78 + function KTAPI_Session($ktapi, $user, $session, $sessionid, $ip)
  79 + {
  80 + assert(!is_null($ktapi));
  81 + assert(is_a($ktapi,'KTAPI'));
  82 + assert(!is_null($user));
  83 + assert(is_a($user,'User'));
  84 +
  85 + $this->ktapi = $ktapi;
  86 + $this->user = $user;
  87 + $this->session = $session;
  88 + $this->sessionid = $sessionid;
  89 + $this->ip = $ip;
  90 +
  91 + // TODO: get documenttransaction to not look at the session variable!
  92 + $_SESSION["userID"] = $user->getId();
  93 + $_SESSION["sessionID"] = $this->sessionid;
  94 + }
  95 +
  96 + /**
  97 + * This returns the session string
  98 + *
  99 + * @return string
  100 + */
  101 + function get_session()
  102 + {
  103 + return $this->session;
  104 + }
  105 +
  106 + /**
  107 + * This returns the sessionid in the database.
  108 + *
  109 + * @return int
  110 + */
  111 + function get_sessionid()
  112 + {
  113 + return $this->sessionid;
  114 + }
  115 +
  116 + /**
  117 + * This returns a user object for the use rassociated with the session.
  118 + *
  119 + * @return KTAPI_User
  120 + */
  121 + function get_user()
  122 + {
  123 + return $this->user;
  124 + }
  125 +
  126 + /**
  127 + * This resolves the user's ip
  128 + *
  129 + * @access static
  130 + * @return string
  131 + */
  132 + function resolveIP()
  133 + {
  134 + if (getenv("REMOTE_ADDR"))
  135 + {
  136 + $ip = getenv("REMOTE_ADDR");
  137 + }
  138 + elseif (getenv("HTTP_X_FORWARDED_FOR"))
  139 + {
  140 + $forwardedip = getenv("HTTP_X_FORWARDED_FOR");
  141 + list($ip,$ip2,$ip3,$ip4)= split (",", $forwardedip);
  142 + }
  143 + elseif (getenv("HTTP_CLIENT_IP"))
  144 + {
  145 + $ip = getenv("HTTP_CLIENT_IP");
  146 + }
  147 +
  148 + if ($ip == '')
  149 + {
  150 + $ip = '127.0.0.1';
  151 + }
  152 +
  153 + return $ip;
  154 + }
  155 +
  156 + /**
  157 + * This returns a session object based on authentication credentials.
  158 + *
  159 + * @access static
  160 + * @param string $username
  161 + * @param string $password
  162 + * @return KTAPI_Session
  163 + */
  164 + function start_session($ktapi, $username, $password, $ip=null)
  165 + {
  166 +
  167 + if ( empty($username) )
  168 + {
  169 + return new PEAR_Error(_kt('The username is empty.'));
  170 + }
  171 +
  172 + $user =& User::getByUsername($username);
  173 + if (PEAR::isError($user) || ($user === false))
  174 + {
  175 + return new PEAR_Error(_kt("The user '$username' cound not be found."));
  176 + }
  177 +
  178 + if ($user->isAnonymous())
  179 + {
  180 + $authenticated = true;
  181 +
  182 + $config = KTConfig::getSingleton();
  183 + $allow_anonymous = $config->get('session/allowAnonymousLogin', false);
  184 +
  185 + if (!$allow_anonymous)
  186 + {
  187 + return new PEAR_Error(_kt('Anonymous user not allowed'));
  188 + }
  189 +
  190 + }
  191 + else
  192 + {
  193 +
  194 + if ( empty($password) )
  195 + {
  196 + return new PEAR_Error(_kt('The password is empty.'));
  197 + }
  198 +
  199 + $authenticated = KTAuthenticationUtil::checkPassword($user, $password);
  200 +
  201 + if (PEAR::isError($authenticated) || $authenticated === false)
  202 + {
  203 + return new PEAR_Error(_kt("The password is invalid."));
  204 + }
  205 + }
  206 +
  207 +
  208 +
  209 +
  210 + if (is_null($ip))
  211 + {
  212 + $ip = KTAPI_Session::resolveIP();
  213 + }
  214 +
  215 + session_start();
  216 +
  217 + $user_id = $user->getId();
  218 +
  219 + $sql = "SELECT count(*) >= u.max_sessions as over_limit FROM active_sessions ass INNER JOIN users u ON ass.user_id=u.id WHERE ass.user_id = $user_id";
  220 + $row = DBUtil::getOneResult($sql);
  221 + if (PEAR::isError($row))
  222 + {
  223 + return $row;
  224 + }
  225 + if (is_null($row))
  226 + {
  227 + return new PEAR_Error('No record found for user?');
  228 + }
  229 + if ($row['over_limit'] == 1)
  230 + {
  231 + return new PEAR_Error('Session limit exceeded. Logout of any active sessions.');
  232 + }
  233 +
  234 + $session = session_id();
  235 +
  236 + $sessionid = DBUtil::autoInsert('active_sessions',
  237 + array(
  238 + 'user_id' => $user_id,
  239 + 'session_id' => session_id(),
  240 + 'lastused' => date('Y-m-d H:i:s'),
  241 + 'ip' => $ip
  242 + ));
  243 + if (PEAR::isError($sessionid) )
  244 + {
  245 + return $sessionid;
  246 + }
  247 +
  248 + $session = new KTAPI_Session($ktapi, $user, $session, $sessionid, $ip);
  249 +
  250 + return $session;
  251 + }
  252 +
  253 + /**
  254 + * This returns an active session.
  255 + *
  256 + * @param KTAPI $ktapi
  257 + * @param string $session
  258 + * @param string $ip
  259 + * @return unknown
  260 + */
  261 + function get_active_session($ktapi, $session, $ip)
  262 + {
  263 + $sql = "SELECT id, user_id FROM active_sessions WHERE session_id='$session'";
  264 + if (!empty($ip))
  265 + {
  266 + $sql .= " AND ip='$ip'";
  267 + }
  268 +
  269 + $row = DBUtil::getOneResult($sql);
  270 + if (is_null($row) || PEAR::isError($row))
  271 + {
  272 + return new PEAR_Error(KTAPI_ERROR_SESSION_INVALID);
  273 + }
  274 +
  275 + $sessionid = $row['id'];
  276 + $userid = $row['user_id'];
  277 +
  278 + $user = User::get($userid);
  279 + if (is_null($user) || PEAR::isError($user))
  280 + {
  281 + return new PEAR_Error(KTAPI_ERROR_USER_INVALID);
  282 + }
  283 +
  284 +
  285 +
  286 + $now=date('Y-m-d H:i:s');
  287 + $sql = "UPDATE active_sessions SET last_used='$now' WHERE id=$sessionid";
  288 + DBUtil::runQuery($sql);
  289 +
  290 + $session = new KTAPI_Session($ktapi, $user, $session, $sessionid, $ip);
  291 + return $session;
  292 + }
  293 +
  294 + /**
  295 + * This closes the current session.
  296 + *
  297 + */
  298 + function logout()
  299 + {
  300 + $sql = "DELETE FROM active_sessions WHERE id=$this->sessionid";
  301 + $result = DBUtil::runQuery($sql);
  302 + if (PEAR::isError($result))
  303 + {
  304 + return $result;
  305 + }
  306 +
  307 + $this->user = null;
  308 + $this->session = '';
  309 + $this->sessionid = -1;
  310 + return true;
  311 + }
  312 +
  313 +}
  314 +
  315 +class KTAPI_FolderItem
  316 +{
  317 + /**
  318 + * This is a reference to the core KTAPI controller
  319 + *
  320 + * @access protected
  321 + * @var KTAPI
  322 + */
  323 + var $ktapi;
  324 +
  325 + function can_user_access_object_requiring_permission($object, $permission)
  326 + {
  327 + $user = $this->ktapi->can_user_access_object_requiring_permission($object, $permission);
  328 +
  329 + return $user;
  330 + }
  331 +}
  332 +
  333 +
  334 +class KTAPI_Folder extends KTAPI_FolderItem
  335 +{
  336 + /**
  337 + * This is a reference to a base Folder object.
  338 + *
  339 + * @access private
  340 + * @var Folder
  341 + */
  342 + var $folder;
  343 +
  344 + /**
  345 + * This is the id of the folder on the database.
  346 + *
  347 + * @access private
  348 + * @var int
  349 + */
  350 + var $folderid;
  351 +
  352 + /**
  353 + * This is used to get a folder based on a folder id.
  354 + *
  355 + * @access static
  356 + * @param KTAPI $ktapi
  357 + * @param int $folderid
  358 + * @return KTAPI_Folder
  359 + */
  360 + function get($ktapi, $folderid)
  361 + {
  362 + assert(!is_null($ktapi));
  363 + assert(is_a($ktapi, 'KTAPI'));
  364 + assert(is_numeric($folderid));
  365 +
  366 + $folderid += 0;
  367 +
  368 + $folder = Folder::get($folderid);
  369 + if (is_null($folder) || PEAR::isError($folder))
  370 + {
  371 + return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  372 + }
  373 +
  374 + $user = $ktapi->can_user_access_object_requiring_permission($folder, KTAPI_PERMISSION_READ);
  375 +
  376 + if (is_null($user) || PEAR::isError($user))
  377 + {
  378 + return $user;
  379 + }
  380 +
  381 + return new KTAPI_Folder($ktapi, $folder);
  382 + }
  383 +
  384 + /**
  385 + * This is the constructor for the KTAPI_Folder.
  386 + *
  387 + * @access private
  388 + * @param KTAPI $ktapi
  389 + * @param Folder $folder
  390 + * @return KTAPI_Folder
  391 + */
  392 + function KTAPI_Folder($ktapi, $folder)
  393 + {
  394 + $this->ktapi = $ktapi;
  395 + $this->folder = $folder;
  396 + $this->folderid = $folder->getId();
  397 + }
  398 +
  399 + /**
  400 + * This returns a reference to the internal folder object.
  401 + *
  402 + * @access protected
  403 + * @return Folder
  404 + */
  405 + function get_folder()
  406 + {
  407 + return $this->folder;
  408 + }
  409 +
  410 +
  411 + /**
  412 + * This returns detailed information on the document.
  413 + *
  414 + * @return array
  415 + */
  416 + function get_detail()
  417 + {
  418 + $detail = array(
  419 + 'id'=>$this->folderid,
  420 + 'folder_name'=>$this->get_folder_name(),
  421 + 'parent_id'=>$this->get_parent_folder_id(),
  422 + 'full_path'=>$this->get_full_path(),
  423 + );
  424 +
  425 + return $detail;
  426 + }
  427 +
  428 + function get_parent_folder_id()
  429 + {
  430 + return $this->folder->getParentID();
  431 + }
  432 +
  433 + function get_folder_name()
  434 + {
  435 + return $this->folder->getFolderName($this->folderid);
  436 + }
  437 +
  438 +
  439 + /**
  440 + * This returns the folderid.
  441 + *
  442 + * @return int
  443 + */
  444 + function get_folderid()
  445 + {
  446 + return $this->folderid;
  447 + }
  448 +
  449 + /**
  450 + * This can resolve a folder relative to the current directy by name
  451 + *
  452 + * @access public
  453 + * @param string $foldername
  454 + * @return KTAPI_Folder
  455 + */
  456 + function get_folder_by_name($foldername)
  457 + {
  458 + $foldername=trim($foldername);
  459 + if (empty($foldername))
  460 + {
  461 + return new PEAR_Error('A valid folder name must be specified.');
  462 + }
  463 +
  464 + $split = explode('/', $foldername);
  465 +
  466 + $folderid=$this->folderid;
  467 + foreach($split as $foldername)
  468 + {
  469 + $sql = "SELECT id FROM folders WHERE name='$foldername' and parent_id=$folderid";
  470 + $row = DBUtil::getOneResult($sql);
  471 + if (is_null($row) || PEAR::isError($row))
  472 + {
  473 + return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  474 + }
  475 + $folderid = $row['id'];
  476 + }
  477 +
  478 + return KTAPI_Folder::get($this->ktapi, $folderid);
  479 + }
  480 +
  481 + function get_full_path()
  482 + {
  483 + $path = $this->folder->getFullPath() . '/' . $this->folder->getName();
  484 +
  485 +// $path = substr($path,11);
  486 +
  487 + return $path;
  488 + }
  489 +
  490 + /**
  491 + * This gets a document by filename or name.
  492 + *
  493 + * @access private
  494 + * @param string $documentname
  495 + * @param string $function
  496 + * @return KTAPI_Document
  497 + */
  498 + function _get_document_by_name($documentname, $function='getByNameAndFolder')
  499 + {
  500 + $documentname=trim($documentname);
  501 + if (empty($documentname))
  502 + {
  503 + return new PEAR_Error('A valid document name must be specified.');
  504 + }
  505 +
  506 + $foldername = dirname($documentname);
  507 + $documentname = basename($documentname);
  508 +
  509 + $ktapi_folder = $this;
  510 +
  511 + if (!empty($foldername) && ($foldername != '.'))
  512 + {
  513 + $ktapi_folder = $this->get_folder_by_name($foldername);
  514 + }
  515 +
  516 + if (is_null($ktapi_folder) || PEAR::isError($ktapi_folder))
  517 + {
  518 + return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  519 + }
  520 +
  521 + //$folder = $ktapi_folder->get_folder();
  522 + $folderid = $ktapi_folder->folderid;
  523 +
  524 + $document = Document::$function($documentname, $folderid);
  525 + if (is_null($document) || PEAR::isError($document))
  526 + {
  527 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_INVALID);
  528 + }
  529 +
  530 + $user = $this->can_user_access_object_requiring_permission($document, KTAPI_PERMISSION_READ);
  531 + if (PEAR::isError($user))
  532 + {
  533 + return $user;
  534 + }
  535 +
  536 + $document = new KTAPI_Document($this->ktapi, $ktapi_folder, $document);
  537 +
  538 + return $document;
  539 + }
  540 +
  541 + /**
  542 + * This can resolve a document relative to the current directy by name.
  543 + *
  544 + * @access public
  545 + * @param string $documentname
  546 + * @return KTAPI_Document
  547 + */
  548 + function get_document_by_name($documentname)
  549 + {
  550 + return $this->_get_document_by_name($documentname,'getByNameAndFolder');
  551 + }
  552 +
  553 + /**
  554 + * This can resolve a document relative to the current directy by filename .
  555 + *
  556 + * @access public
  557 + * @param string $documentname
  558 + * @return KTAPI_Document
  559 + */
  560 + function get_document_by_filename($documentname)
  561 + {
  562 + return $this->_get_document_by_name($documentname,'getByFilenameAndFolder');
  563 + }
  564 +
  565 + function get_listing($depth=1, $what='DF')
  566 + {
  567 + if ($depth < 1)
  568 + {
  569 + return array();
  570 + }
  571 + $permission = KTPermission::getByName(KTAPI_PERMISSION_READ);
  572 + $permissionid= $permission->getId();
  573 +
  574 + $user = $this->ktapi->get_user();
  575 + $aPermissionDescriptors = implode(',',KTPermissionUtil::getPermissionDescriptorsForUser($user));
  576 +
  577 + $sql = '';
  578 + if (strpos($what,'D') !== false)
  579 + {
  580 + $sql .= "SELECT
  581 + d.id,
  582 + 'D' as item_type,
  583 + dmv.name as title,
  584 + ifnull(uc.name, 'n/a') AS creator,
  585 + ifnull(cou.name, 'n/a') AS checkedoutby,
  586 + ifnull(mu.name, 'n/a') AS modifiedby,
  587 + dcv.filename,
  588 + dcv.size,
  589 + dcv.major_version,
  590 + dcv.minor_version,
  591 + dcv.storage_path,
  592 + ifnull(mt.mimetypes, 'unknown') as mime_type,
  593 + ifnull(mt.icon_path, 'unknown') as mime_icon_path,
  594 + ifnull(mt.friendly_name, 'unknown') as mime_display
  595 + FROM
  596 + documents d
  597 + INNER JOIN permission_lookups AS PL ON d.permission_lookup_id = PL.id
  598 + INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = $permissionid
  599 + INNER JOIN document_metadata_version AS dmv ON d.metadata_version_id=dmv.id
  600 + INNER JOIN document_content_version AS dcv ON dmv.content_version_id=dcv.id
  601 + LEFT OUTER JOIN mime_types mt ON dcv.mime_id = mt.id
  602 + LEFT OUTER JOIN users AS uc ON d.creator_id=uc.id
  603 + LEFT OUTER JOIN users AS cou ON d.checked_out_user_id=cou.id
  604 + LEFT OUTER JOIN users AS mu ON d.modified_user_id=mu.id
  605 + WHERE
  606 + d.folder_id=$this->folderid
  607 + AND d.status_id = 1
  608 + AND PLA.permission_descriptor_id IN ($aPermissionDescriptors)";
  609 + }
  610 +
  611 + if (strpos($what,'F') !== false)
  612 + {
  613 + if (strpos($what,'D') !== false)
  614 + {
  615 + $sql .= ' UNION ';
  616 + }
  617 +
  618 + $sql .= "
  619 + SELECT
  620 + f.id,
  621 + 'F' as item_type,
  622 + f.name as title,
  623 + ifnull(uc.name, 'n/a') AS creator,
  624 + 'n/a' checkedoutby,
  625 + 'n/a' AS modifiedby,
  626 + f.name as filename,
  627 + 'n/a' as size,
  628 + 'n/a' as major_version,
  629 + 'n/a' as minor_version,
  630 + 'n/a' as storage_path,
  631 + 'folder' as mime_type,
  632 + 'folder' as mime_icon_path,
  633 + 'Folder' as mime_display
  634 + FROM
  635 + folders f
  636 + INNER JOIN permission_lookups AS PL ON f.permission_lookup_id = PL.id
  637 + INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = $permissionid
  638 + LEFT OUTER JOIN users AS uc ON f.creator_id=uc.id
  639 +
  640 + WHERE
  641 + f.parent_id=$this->folderid
  642 +
  643 + AND PLA.permission_descriptor_id IN ($aPermissionDescriptors)
  644 + ORDER BY item_type DESC, title, filename
  645 + ";
  646 + }
  647 +
  648 + $contents = DBUtil::getResultArray($sql);
  649 + if (is_null($contents) || PEAR::isError($contents))
  650 + {
  651 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  652 + }
  653 +
  654 + foreach($contents as & $item)
  655 + {
  656 + if ($item['item_type'] == 'D')
  657 + {
  658 + $item['items'] = array();
  659 + }
  660 + else
  661 + {
  662 + if ($depth-1 > 0)
  663 + {
  664 + $folder = $this->ktapi->get_folder_by_id($item['id']);
  665 + $item['items'] = $folder->get_listing($depth-1);
  666 + }
  667 + else
  668 + {
  669 + $item['items'] = array();
  670 + }
  671 + }
  672 + }
  673 +
  674 + return $contents;
  675 + }
  676 +
  677 + /**
  678 + * This adds a document to the current folder.
  679 + *
  680 + * @access public
  681 + * @param string $title This is the title for the file in the repository.
  682 + * @param string $filename This is the filename in the system for the file.
  683 + * @param string $documenttype This is the name or id of the document type. It first looks by name, then by id.
  684 + * @param string $tempfilename This is a reference to the file that is accessible locally on the file system.
  685 + * @return KTAPI_Document
  686 + */
  687 + function add_document($title, $filename, $documenttype, $tempfilename)
  688 + {
  689 + if (!is_file($tempfilename))
  690 + {
  691 + return new PEAR_Error('File does not exist.');
  692 + }
  693 +
  694 + $user = $this->can_user_access_object_requiring_permission($this->folder, KTAPI_PERMISSION_WRITE);
  695 + if (PEAR::isError($user))
  696 + {
  697 + return $user;
  698 + }
  699 +
  700 + $filename = basename($filename);
  701 + $documenttypeid = KTAPI::get_documenttypeid($documenttype);
  702 +
  703 + $options = array(
  704 + 'contents' => new KTFSFileLike($tempfilename),
  705 + 'novalidate' => true,
  706 + 'documenttype' => DocumentType::get($documenttypeid),
  707 + 'description' => $title,
  708 + 'metadata'=>array(),
  709 + 'cleanup_initial_file' => true
  710 + );
  711 +
  712 + DBUtil::startTransaction();
  713 + $document =& KTDocumentUtil::add($this->folder, $filename, $user, $options);
  714 +
  715 + if (!is_a($document,'Document'))
  716 + {
  717 + DBUtil::rollback();
  718 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  719 + }
  720 + DBUtil::commit();
  721 +
  722 + $tempfilename=addslashes($tempfilename);
  723 + $sql = "DELETE FROM uploaded_files WHERE tempfilename='$tempfilename'";
  724 + $result = DBUtil::runQuery($sql);
  725 + if (PEAR::isError($result))
  726 + {
  727 + return $result;
  728 + }
  729 +
  730 +
  731 + $ktapi_document = new KTAPI_Document($this->ktapi, $this, $document);
  732 +
  733 + return $ktapi_document;
  734 + }
  735 +
  736 + /**
  737 + * This adds a subfolder folder to the current folder.
  738 + *
  739 + * @access public
  740 + * @param string $foldername
  741 + * @return KTAPI_Folder
  742 + */
  743 + function add_folder($foldername)
  744 + {
  745 + $user = $this->can_user_access_object_requiring_permission($this->folder, KTAPI_PERMISSION_ADD_FOLDER);
  746 +
  747 + if (PEAR::isError($user))
  748 + {
  749 + return $user;
  750 + }
  751 +
  752 + DBUtil::startTransaction();
  753 + $result = KTFolderUtil::add($this->folder, $foldername, $user);
  754 +
  755 +
  756 + if (PEAR::isError($result))
  757 + {
  758 + DBUtil::rollback();
  759 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  760 + }
  761 + DBUtil::commit();
  762 + $folderid = $result->getId();
  763 +
  764 + $ktapi_folder = $this->ktapi->get_folder_by_id($folderid);
  765 +
  766 + return $ktapi_folder;
  767 + }
  768 +
  769 + /**
  770 + * This deletes the current folder.
  771 + *
  772 + * @param string $reason
  773 + * @return true
  774 + */
  775 + function delete($reason)
  776 + {
  777 + $user = $this->can_user_access_object_requiring_permission($this->folder, KTAPI_PERMISSION_DELETE);
  778 +
  779 + if (PEAR::isError($user))
  780 + {
  781 + return $user;
  782 + }
  783 +
  784 + if ($this->folderid == 1)
  785 + {
  786 + return new PEAR_Error('Cannot delete root folder!');
  787 + }
  788 +
  789 + DBUtil::startTransaction();
  790 + $result = KTFolderUtil::delete($this->folder, $user, $reason);
  791 +
  792 + if (PEAR::isError($result))
  793 + {
  794 + DBUtil::rollback();
  795 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  796 + }
  797 + DBUtil::commit();
  798 +
  799 + return true;
  800 + }
  801 +
  802 + /**
  803 + * This renames the folder
  804 + *
  805 + * @param string $newname
  806 + * @return true
  807 + */
  808 + function rename($newname)
  809 + {
  810 +
  811 + $user = $this->can_user_access_object_requiring_permission($this->folder, KTAPI_PERMISSION_RENAME_FOLDER);
  812 +
  813 + if (PEAR::isError($user))
  814 + {
  815 + return $user;
  816 + }
  817 +
  818 + DBUtil::startTransaction();
  819 + $result = KTFolderUtil::rename($this->folder, $newname, $user);
  820 +
  821 + if (PEAR::isError($result))
  822 + {
  823 + DBUtil::rollback();
  824 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  825 + }
  826 + DBUtil::commit();
  827 +
  828 + return true;
  829 + }
  830 +
  831 + /**
  832 + * This moves the folder to another location.
  833 + *
  834 + * @param KTAPI_Folder $ktapi_target_folder
  835 + * @param string $reason
  836 + * @return true
  837 + */
  838 + function move($ktapi_target_folder, $reason='')
  839 + {
  840 + assert(!is_null($ktapi_target_folder));
  841 + assert(is_a($ktapi_target_folder,'KTAPI_Folder'));
  842 +
  843 + $user = $this->ktapi->get_user();
  844 +
  845 + $target_folder = $ktapi_target_folder->get_folder();
  846 +
  847 + $result = $this->can_user_access_object_requiring_permission($target_folder, KTAPI_PERMISSION_WRITE);
  848 + if (PEAR::isError($result))
  849 + {
  850 + return $result;
  851 + }
  852 +
  853 + DBUtil::startTransaction();
  854 + $result = KTFolderUtil::copy($this->folder, $target_folder, $user, $reason);
  855 +
  856 + if (PEAR::isError($result))
  857 + {
  858 + DBUtil::rollback();
  859 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  860 + }
  861 + DBUtil::commit();
  862 +
  863 + return true;
  864 + }
  865 +
  866 + /**
  867 + * This copies a folder to another location.
  868 + *
  869 + * @param KTAPI_Folder $ktapi_target_folder
  870 + * @param string $reason
  871 + * @return true
  872 + */
  873 + function copy($ktapi_target_folder, $reason='')
  874 + {
  875 + assert(!is_null($ktapi_target_folder));
  876 + assert(is_a($ktapi_target_folder,'KTAPI_Folder'));
  877 +
  878 + $user = $this->ktapi->get_user();
  879 +
  880 + $target_folder = $ktapi_target_folder->get_folder();
  881 +
  882 + $result =$this->can_user_access_object_requiring_permission($target_folder, KTAPI_PERMISSION_WRITE);
  883 +
  884 + if (PEAR::isError($result))
  885 + {
  886 + return $result;
  887 + }
  888 +
  889 + DBUtil::startTransaction();
  890 + $result = KTFolderUtil::copy($this->folder, $target_folder, $user, $reason);
  891 +
  892 + if (PEAR::isError($result))
  893 + {
  894 + DBUtil::rollback();
  895 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  896 + }
  897 + DBUtil::commit();
  898 +
  899 + return true;
  900 + }
  901 +
  902 + /**
  903 + * This returns all permissions linked to the folder.
  904 + *
  905 + * @access public
  906 + * @return array
  907 + */
  908 + function get_permissions()
  909 + {
  910 + return new PEAR_Error('TODO');
  911 + }
  912 +
  913 + /**
  914 + * This returns a transaction history listing.
  915 + *
  916 + * @access public
  917 + * @return array
  918 + */
  919 + function get_transaction_history()
  920 + {
  921 + return new PEAR_Error('TODO');
  922 + }
  923 +
  924 +
  925 +
  926 +}
  927 +
  928 +class KTAPI_Document extends KTAPI_FolderItem
  929 +{
  930 + /**
  931 + * This is a reference to the internal document object.
  932 + *
  933 + * @var Document
  934 + */
  935 + var $document;
  936 + /**
  937 + * This is the id of the document.
  938 + *
  939 + * @var int
  940 + */
  941 + var $documentid;
  942 + /**
  943 + * This is a reference to the parent folder.
  944 + *
  945 + * @var KTAPI_Folder
  946 + */
  947 + var $ktapi_folder;
  948 +
  949 + /**
  950 + * This is used to get a document based on document id.
  951 + *
  952 + * @access static
  953 + * @param KTAPI $ktapi
  954 + * @param int $documentid
  955 + * @return KTAPI_Document
  956 + */
  957 + function get($ktapi, $documentid)
  958 + {
  959 + assert(!is_null($ktapi));
  960 + assert(is_a($ktapi, 'KTAPI'));
  961 + assert(is_numeric($documentid));
  962 +
  963 + $documentid += 0;
  964 +
  965 + $document = Document::get($documentid);
  966 + if (is_null($document) || PEAR::isError($document))
  967 + {
  968 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_INVALID);
  969 + }
  970 +
  971 + $user = $ktapi->can_user_access_object_requiring_permission($document, KTAPI_PERMISSION_READ);
  972 +
  973 + if (is_null($user) || PEAR::isError($user))
  974 + {
  975 + return $user;
  976 + }
  977 +
  978 + $folderid = $document->getParentID();
  979 +
  980 + $ktapi_folder = KTAPI_Folder::get($ktapi, $folderid);
  981 + // We don't do any checks on this folder as it could possibly be deleted, and is not required right now.
  982 +
  983 + return new KTAPI_Document($ktapi, $ktapi_folder, $document);
  984 + }
  985 +
  986 + /**
  987 + * This is the constructor for the KTAPI_Folder.
  988 + *
  989 + * @access private
  990 + * @param KTAPI $ktapi
  991 + * @param Document $document
  992 + * @return KTAPI_Document
  993 + */
  994 + function KTAPI_Document($ktapi, $ktapi_folder, $document)
  995 + {
  996 + assert(is_a($ktapi,'KTAPI'));
  997 + assert(is_a($ktapi_folder,'KTAPI_Folder'));
  998 +
  999 + $this->ktapi = $ktapi;
  1000 + $this->ktapi_folder = $ktapi_folder;
  1001 + $this->document = $document;
  1002 + $this->documentid = $document->getId();
  1003 + }
  1004 +
  1005 + /**
  1006 + * This checks a document into the repository
  1007 + *
  1008 + * @param string $filename
  1009 + * @param string $reason
  1010 + * @param string $tempfilename
  1011 + * @param bool $major_update
  1012 + * @return true
  1013 + */
  1014 + function checkin($filename, $reason, $tempfilename, $major_update=false)
  1015 + {
  1016 + if (!is_file($tempfilename))
  1017 + {
  1018 + return new PEAR_Error('File does not exist.');
  1019 + }
  1020 +
  1021 + $user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
  1022 +
  1023 + if (PEAR::isError($user))
  1024 + {
  1025 + return $user;
  1026 + }
  1027 +
  1028 + if (!$this->document->getIsCheckedOut())
  1029 + {
  1030 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT);
  1031 + }
  1032 +
  1033 + $options = array('major_update'=>$major_update);
  1034 +
  1035 + $currentfilename = $this->document->getFileName();
  1036 + if ($filename != $currentfilename)
  1037 + {
  1038 + $options['newfilename'] = $filename;
  1039 + }
  1040 +
  1041 + DBUtil::startTransaction();
  1042 + $result = KTDocumentUtil::checkin($this->document, $tempfilename, $reason, $user, $options);
  1043 +
  1044 + if (PEAR::isError($result))
  1045 + {
  1046 + DBUtil::rollback();
  1047 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1048 + }
  1049 + DBUtil::commit();
  1050 + return true;
  1051 + }
  1052 +
  1053 + /**
  1054 + * This reverses the checkout process.
  1055 + *
  1056 + * @param string $reason
  1057 + * @return true
  1058 + */
  1059 + function undo_checkout($reason)
  1060 + {
  1061 + $user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
  1062 +
  1063 + if (PEAR::isError($user))
  1064 + {
  1065 + return $user;
  1066 + }
  1067 +
  1068 + if (!$this->document->getIsCheckedOut())
  1069 + {
  1070 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT);
  1071 + }
  1072 +
  1073 + DBUtil::startTransaction();
  1074 +
  1075 + $this->document->setIsCheckedOut(0);
  1076 + $this->document->setCheckedOutUserID(-1);
  1077 + $res = $this->document->update();
  1078 + if (($res === false) || PEAR::isError($res))
  1079 + {
  1080 + DBUtil::rollback();
  1081 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1082 + }
  1083 +
  1084 + $oDocumentTransaction = & new DocumentTransaction($this->document, $reason, 'ktcore.transactions.force_checkin');
  1085 +
  1086 + $res = $oDocumentTransaction->create();
  1087 + if (($res === false) || PEAR::isError($res)) {
  1088 + DBUtil::rollback();
  1089 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1090 + }
  1091 + DBUtil::commit();
  1092 + return true;
  1093 + }
  1094 +
  1095 + /**
  1096 + * This returns a URL to the file that can be downloaded.
  1097 + *
  1098 + * @param string $reason
  1099 + * @return true;
  1100 + */
  1101 + function checkout($reason)
  1102 + {
  1103 + $user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WRITE);
  1104 +
  1105 + if (PEAR::isError($user))
  1106 + {
  1107 + return $user;
  1108 + }
  1109 +
  1110 + if ($this->document->getIsCheckedOut())
  1111 + {
  1112 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
  1113 + }
  1114 +
  1115 + DBUtil::startTransaction();
  1116 + $res = KTDocumentUtil::checkout($this->document, $reason, $user);
  1117 + if (PEAR::isError($res))
  1118 + {
  1119 + DBUtil::rollback();
  1120 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1121 + }
  1122 +
  1123 + DBUtil::commit();
  1124 +
  1125 + return true;
  1126 + }
  1127 +
  1128 + /**
  1129 + * This deletes a document from the folder.
  1130 + *
  1131 + * @param string $reason
  1132 + * @return mixed This returns true or a PEAR::Error
  1133 + */
  1134 + function delete($reason)
  1135 + {
  1136 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_DELETE);
  1137 +
  1138 + if (PEAR::isError($user))
  1139 + {
  1140 + return $user;
  1141 + }
  1142 +
  1143 + if ($this->document->getIsCheckedOut())
  1144 + {
  1145 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
  1146 + }
  1147 +
  1148 + DBUtil::startTransaction();
  1149 + $res = KTDocumentUtil::delete($this->document, $reason);
  1150 + if (PEAR::isError($res))
  1151 + {
  1152 + DBUtil::rollback();
  1153 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1154 + }
  1155 +
  1156 + DBUtil::commit();
  1157 +
  1158 + return true;
  1159 + }
  1160 +
  1161 + /**
  1162 + * This changes the owner of the file.
  1163 + *
  1164 + * @param string $ktapi_newuser
  1165 + * @return true
  1166 + */
  1167 + function change_owner($newusername, $reason='Changing of owner.')
  1168 + {
  1169 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_CHANGE_OWNERSHIP);
  1170 +
  1171 + if (PEAR::isError($user))
  1172 + {
  1173 + return $user;
  1174 + }
  1175 +
  1176 + DBUtil::startTransaction();
  1177 +
  1178 + $user = User::getByUserName($newusername);
  1179 + if (is_null($user) || PEAR::isError($user))
  1180 + {
  1181 + return new PEAR_Error('User could not be found');
  1182 + }
  1183 +
  1184 + $newuserid = $user->getId();
  1185 +
  1186 + $this->document->setOwnerID($newuserid);
  1187 +
  1188 + $res = $this->document->update();
  1189 +
  1190 + if (PEAR::isError($res))
  1191 + {
  1192 + DBUtil::rollback();
  1193 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1194 + }
  1195 +
  1196 + $res = KTPermissionUtil::updatePermissionLookup($this->document);
  1197 + if (PEAR::isError($res))
  1198 + {
  1199 + DBUtil::rollback();
  1200 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1201 + }
  1202 +
  1203 + $oDocumentTransaction = & new DocumentTransaction($this->document, $reason, 'ktcore.transactions.permissions_change');
  1204 +
  1205 + $res = $oDocumentTransaction->create();
  1206 + if (($res === false) || PEAR::isError($res)) {
  1207 + DBUtil::rollback();
  1208 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1209 + }
  1210 +
  1211 +
  1212 + DBUtil::commit();
  1213 + return true;
  1214 + }
  1215 +
  1216 + /**
  1217 + * This copies the document to another folder.
  1218 + *
  1219 + * @param KTAPI_Folder $ktapi_target_folder
  1220 + * @param string $reason
  1221 + * @param string $newname
  1222 + * @param string $newfilename
  1223 + * @return true
  1224 + */
  1225 + function copy($ktapi_target_folder, $reason, $newname=null, $newfilename=null)
  1226 + {
  1227 + assert(!is_null($ktapi_target_folder));
  1228 + assert(is_a($ktapi_target_folder,'KTAPI_Folder'));
  1229 +
  1230 + if (empty($newname))
  1231 + {
  1232 + $newname=null;
  1233 + }
  1234 + if (empty($newfilename))
  1235 + {
  1236 + $newfilename=null;
  1237 + }
  1238 +
  1239 +
  1240 + $user = $this->ktapi->get_user();
  1241 +
  1242 + if ($this->document->getIsCheckedOut())
  1243 + {
  1244 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
  1245 + }
  1246 +
  1247 + $target_folder = $ktapi_target_folder->get_folder();
  1248 +
  1249 + $result = $this->can_user_access_object_requiring_permission( $target_folder, KTAPI_PERMISSION_WRITE);
  1250 +
  1251 + if (PEAR::isError($result))
  1252 + {
  1253 + return $result;
  1254 + }
  1255 +
  1256 + $name = $this->document->getName();
  1257 + $clash = KTDocumentUtil::nameExists($target_folder, $name);
  1258 + if ($clash && !is_null($newname))
  1259 + {
  1260 + $name = $newname;
  1261 + $clash = KTDocumentUtil::nameExists($target_folder, $name);
  1262 + }
  1263 + if ($clash)
  1264 + {
  1265 + 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.');
  1266 + }
  1267 +
  1268 + $filename=$this->document->getFilename();
  1269 + $clash = KTDocumentUtil::fileExists($target_folder, $filename);
  1270 +
  1271 + if ($clash && !is_null($newname))
  1272 + {
  1273 + $filename = $newfilename;
  1274 + $clash = KTDocumentUtil::fileExists($target_folder, $filename);
  1275 + }
  1276 + if ($clash)
  1277 + {
  1278 + 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.');
  1279 + }
  1280 +
  1281 + DBUtil::startTransaction();
  1282 +
  1283 + $new_document = KTDocumentUtil::copy($this->document, $target_folder, $reason);
  1284 + if (PEAR::isError($new_document))
  1285 + {
  1286 + DBUtil::rollback();
  1287 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1288 + }
  1289 +
  1290 + $new_document->setName($name);
  1291 + $new_document->setFilename($filename);
  1292 +
  1293 + $res = $new_document->update();
  1294 +
  1295 + if (PEAR::isError($res))
  1296 + {
  1297 + DBUtil::rollback();
  1298 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1299 + }
  1300 +
  1301 + DBUtil::commit();
  1302 +
  1303 + // FIXME do we need to refactor all trigger usage into the util function?
  1304 + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
  1305 + $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate');
  1306 + foreach ($aTriggers as $aTrigger) {
  1307 + $sTrigger = $aTrigger[0];
  1308 + $oTrigger = new $sTrigger;
  1309 + $aInfo = array(
  1310 + 'document' => $new_document,
  1311 + 'old_folder' => $this->folder->get_folder(),
  1312 + 'new_folder' => $target_folder,
  1313 + );
  1314 + $oTrigger->setInfo($aInfo);
  1315 + $ret = $oTrigger->postValidate();
  1316 + }
  1317 +
  1318 + return true;
  1319 + }
  1320 +
  1321 + /**
  1322 + * This moves the document to another folder.
  1323 + *
  1324 + * @param KTAPI_Folder $ktapi_target_folder
  1325 + * @param string $reason
  1326 + * @param string $newname
  1327 + * @param string $newfilename
  1328 + * @return true
  1329 + */
  1330 + function move($ktapi_target_folder, $reason, $newname=null, $newfilename=null)
  1331 + {
  1332 + assert(!is_null($ktapi_target_folder));
  1333 + assert(is_a($ktapi_target_folder,'KTAPI_Folder'));
  1334 +
  1335 + if (empty($newname))
  1336 + {
  1337 + $newname=null;
  1338 + }
  1339 + if (empty($newfilename))
  1340 + {
  1341 + $newfilename=null;
  1342 + }
  1343 +
  1344 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_DOCUMENT_MOVE);
  1345 +
  1346 + if (PEAR::isError($user))
  1347 + {
  1348 + return $user;
  1349 + }
  1350 +
  1351 + if ($this->document->getIsCheckedOut())
  1352 + {
  1353 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_CHECKED_OUT);
  1354 + }
  1355 +
  1356 + $target_folder = $ktapi_target_folder->get_folder();
  1357 +
  1358 + $result= $this->can_user_access_object_requiring_permission( $target_folder, KTAPI_PERMISSION_WRITE);
  1359 +
  1360 + if (PEAR::isError($result))
  1361 + {
  1362 + return $result;
  1363 + }
  1364 +
  1365 + if (!KTDocumentUtil::canBeMoved($this->document))
  1366 + {
  1367 + return new PEAR_Error('Document cannot be moved.');
  1368 + }
  1369 +
  1370 + $name = $this->document->getName();
  1371 + $clash = KTDocumentUtil::nameExists($target_folder, $name);
  1372 + if ($clash && !is_null($newname))
  1373 + {
  1374 + $name = $newname;
  1375 + $clash = KTDocumentUtil::nameExists($target_folder, $name);
  1376 + }
  1377 + if ($clash)
  1378 + {
  1379 + 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.');
  1380 + }
  1381 +
  1382 + $filename=$this->document->getFilename();
  1383 + $clash = KTDocumentUtil::fileExists($target_folder, $filename);
  1384 +
  1385 + if ($clash && !is_null($newname))
  1386 + {
  1387 + $filename = $newfilename;
  1388 + $clash = KTDocumentUtil::fileExists($target_folder, $filename);
  1389 + }
  1390 + if ($clash)
  1391 + {
  1392 + 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.');
  1393 + }
  1394 +
  1395 + DBUtil::startTransaction();
  1396 +
  1397 + $res = KTDocumentUtil::move($this->document, $target_folder, $user, $reason);
  1398 + if (PEAR::isError($res))
  1399 + {
  1400 + DBUtil::rollback();
  1401 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1402 + }
  1403 +
  1404 + $this->document->setName($name);
  1405 + $this->document->setFilename($filename);
  1406 +
  1407 + $res = $this->document->update();
  1408 +
  1409 + if (PEAR::isError($res))
  1410 + {
  1411 + DBUtil::rollback();
  1412 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1413 + }
  1414 +
  1415 + DBUtil::commit();
  1416 +
  1417 + return true;
  1418 + }
  1419 +
  1420 + /**
  1421 + * This changes the filename of the document.
  1422 + *
  1423 + * @param string $newname
  1424 + * @return true
  1425 + */
  1426 + function renameFile($newname)
  1427 + {
  1428 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
  1429 +
  1430 + if (PEAR::isError($user))
  1431 + {
  1432 + return $user;
  1433 + }
  1434 +
  1435 + DBUtil::startTransaction();
  1436 + $res = KTDocumentUtil::rename($this->document, $newname, $user);
  1437 + if (PEAR::isError($res))
  1438 + {
  1439 + DBUtil::rollback();
  1440 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1441 + }
  1442 + DBUtil::commit();
  1443 +
  1444 + return true;
  1445 + }
  1446 +
  1447 + /**
  1448 + * This changes the document type of the document.
  1449 + *
  1450 + * @param string $newname
  1451 + * @return true
  1452 + */
  1453 + function change_document_type($documenttype)
  1454 + {
  1455 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
  1456 +
  1457 + if (PEAR::isError($user))
  1458 + {
  1459 + return $user;
  1460 + }
  1461 +
  1462 + $doctypeid = KTAPI::get_documenttypeid($documenttype);
  1463 +
  1464 + if ($this->document->getDocumentTypeId() != $doctypeid)
  1465 + {
  1466 + DBUtil::startTransaction();
  1467 + $this->document->setDocumentTypeId($doctypeid);
  1468 + $res = $this->document->update();
  1469 +
  1470 + if (PEAR::isError($res))
  1471 + {
  1472 + DBUtil::rollback();
  1473 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1474 + }
  1475 + DBUtil::commit();
  1476 + }
  1477 + return true;
  1478 + }
  1479 +
  1480 + /**
  1481 + * This changes the title of the document.
  1482 + *
  1483 + * @param string $newname
  1484 + * @return true
  1485 + */
  1486 + function rename($newname)
  1487 + {
  1488 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
  1489 +
  1490 + if (PEAR::isError($user))
  1491 + {
  1492 + return $user;
  1493 + }
  1494 +
  1495 + if ($this->document->getName() != $newname)
  1496 + {
  1497 +
  1498 + DBUtil::startTransaction();
  1499 + $this->document->setName($newname);
  1500 + $res = $this->document->update();
  1501 +
  1502 + if (PEAR::isError($res))
  1503 + {
  1504 + DBUtil::rollback();
  1505 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1506 + }
  1507 + DBUtil::commit();
  1508 + }
  1509 +
  1510 + return true;
  1511 + }
  1512 +
  1513 + /**
  1514 + * This flags the document as 'archived'.
  1515 + *
  1516 + * @param string $reason
  1517 + * @return true
  1518 + */
  1519 + function archive($reason)
  1520 + {
  1521 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WRITE);
  1522 +
  1523 + if (PEAR::isError($user))
  1524 + {
  1525 + return $user;
  1526 + }
  1527 +
  1528 + list($permission, $user) = $perm_and_user;
  1529 +
  1530 + DBUtil::startTransaction();
  1531 + $this->document->setStatusID(ARCHIVED);
  1532 + $res = $this->document->update();
  1533 + if (($res === false) || PEAR::isError($res)) {
  1534 + DBUtil::rollback();
  1535 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1536 + }
  1537 +
  1538 + $oDocumentTransaction = & new DocumentTransaction($this->document, sprintf(_kt('Document archived: %s'), $reason), 'ktcore.transactions.update');
  1539 + $oDocumentTransaction->create();
  1540 +
  1541 + DBUtil::commit();
  1542 +
  1543 + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
  1544 + $aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
  1545 + foreach ($aTriggers as $aTrigger)
  1546 + {
  1547 + $sTrigger = $aTrigger[0];
  1548 + $oTrigger = new $sTrigger;
  1549 + $aInfo = array(
  1550 + 'document' => $this->document,
  1551 + );
  1552 + $oTrigger->setInfo($aInfo);
  1553 + $ret = $oTrigger->postValidate();
  1554 + }
  1555 +
  1556 + return true;
  1557 + }
  1558 +
  1559 + /**
  1560 + * This starts a workflow on a document.
  1561 + *
  1562 + * @param string $workflow
  1563 + * @return true
  1564 + */
  1565 + function start_workflow($workflow)
  1566 + {
  1567 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
  1568 +
  1569 + if (PEAR::isError($user))
  1570 + {
  1571 + return $user;
  1572 + }
  1573 +
  1574 + $workflowid = $this->document->getWorkflowId();
  1575 +
  1576 + if (!empty($workflowid))
  1577 + {
  1578 + return new PEAR_Error('A workflow is already defined.');
  1579 + }
  1580 +
  1581 + $workflow = KTWorkflow::getByName($workflow);
  1582 + if (is_null($workflow) || PEAR::isError($workflow))
  1583 + {
  1584 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1585 + }
  1586 +
  1587 + DBUtil::startTransaction();
  1588 + $result = KTWorkflowUtil::startWorkflowOnDocument($workflow, $this->document);
  1589 + if (is_null($result) || PEAR::isError($result))
  1590 + {
  1591 + DBUtil::rollback();
  1592 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1593 + }
  1594 + DBUtil::commit();
  1595 +
  1596 + return true;
  1597 + }
  1598 +
  1599 + /**
  1600 + * This deletes the workflow on the document.
  1601 + *
  1602 + * @return true
  1603 + */
  1604 + function delete_workflow()
  1605 + {
  1606 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
  1607 +
  1608 + if (PEAR::isError($user))
  1609 + {
  1610 + return $user;
  1611 + }
  1612 +
  1613 + $workflowid=$this->document->getWorkflowId();
  1614 + if (!empty($workflowid))
  1615 + {
  1616 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
  1617 + }
  1618 +
  1619 + DBUtil::startTransaction();
  1620 + $result = KTWorkflowUtil::startWorkflowOnDocument(null, $this->document);
  1621 + if (is_null($result) || PEAR::isError($result))
  1622 + {
  1623 + DBUtil::rollback();
  1624 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1625 + }
  1626 + DBUtil::commit();
  1627 +
  1628 + return true;
  1629 + }
  1630 +
  1631 + /**
  1632 + * This performs a transition on the workflow
  1633 + *
  1634 + * @param string $transition
  1635 + * @param string $reason
  1636 + * @return true
  1637 + */
  1638 + function perform_workflow_transition($transition, $reason)
  1639 + {
  1640 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
  1641 +
  1642 + if (PEAR::isError($user))
  1643 + {
  1644 + return $user;
  1645 + }
  1646 +
  1647 + $workflowid=$this->document->getWorkflowId();
  1648 + if (empty($workflowid))
  1649 + {
  1650 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
  1651 + }
  1652 +
  1653 + $transition = KTWorkflowTransition::getByName($transition);
  1654 + if (is_null($transition) || PEAR::isError($transition))
  1655 + {
  1656 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1657 + }
  1658 +
  1659 + list($permission, $user) = $perm_and_user;
  1660 +
  1661 + DBUtil::startTransaction();
  1662 + $result = KTWorkflowUtil::performTransitionOnDocument($transition, $this->document, $user, $reason);
  1663 + if (is_null($result) || PEAR::isError($result))
  1664 + {
  1665 + DBUtil::rollback();
  1666 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1667 + }
  1668 + DBUtil::commit();
  1669 +
  1670 + return true;
  1671 + }
  1672 +
  1673 +
  1674 +
  1675 + /**
  1676 + * This returns all metadata for the document.
  1677 + *
  1678 + * @return array
  1679 + */
  1680 + function get_metadata()
  1681 + {
  1682 + $doctypeid = $this->document->getDocumentTypeID();
  1683 + $fieldsets = (array) KTMetadataUtil::fieldsetsForDocument($this->document, $doctypeid);
  1684 +
  1685 + $results = array();
  1686 +
  1687 + foreach ($fieldsets as $fieldset)
  1688 + {
  1689 + if ($fieldset->getIsConditional()) { /* this is not implemented...*/ continue; }
  1690 +
  1691 + $fields = $fieldset->getFields();
  1692 + $result = array('fieldset' => $fieldset->getName(),
  1693 + 'description' => $fieldset->getDescription());
  1694 +
  1695 + $fieldsresult = array();
  1696 +
  1697 + foreach ($fields as $field)
  1698 + {
  1699 + $value = 'n/a';
  1700 +
  1701 + $fieldvalue = DocumentFieldLink::getByDocumentAndField($this->document, $field);
  1702 + if (!is_null($fieldvalue) && (!PEAR::isError($fieldvalue)))
  1703 + {
  1704 + $value = $fieldvalue->getValue();
  1705 + }
  1706 +
  1707 + $controltype = 'string';
  1708 + if ($field->getHasLookup())
  1709 + {
  1710 + $controltype = 'lookup';
  1711 + if ($field->getHasLookupTree())
  1712 + {
  1713 + $controltype = 'tree';
  1714 + }
  1715 + }
  1716 +
  1717 + switch ($controltype)
  1718 + {
  1719 + case 'lookup':
  1720 + $selection = KTAPI::get_metadata_lookup($field->getId());
  1721 + break;
  1722 + case 'tree':
  1723 + $selection = KTAPI::get_metadata_tree($field->getId());
  1724 + break;
  1725 + default:
  1726 + $selection= array();
  1727 + }
  1728 +
  1729 +
  1730 + $fieldsresult[] = array(
  1731 + 'name' => $field->getName(),
  1732 + 'required' => $field->getIsMandatory(),
  1733 + 'value' => $value,
  1734 + 'description' => $field->getDescription(),
  1735 + 'control_type' => $controltype,
  1736 + 'selection' => $selection
  1737 +
  1738 + );
  1739 +
  1740 + }
  1741 + $result['fields'] = $fieldsresult;
  1742 + $results [] = $result;
  1743 + }
  1744 +
  1745 + return $results;
  1746 + }
  1747 +
  1748 + /**
  1749 + * This updates the metadata on the file. This includes the 'title'.
  1750 + *
  1751 + * @param array This is an array containing the metadata to be associated with the file.
  1752 + * @return mixed This returns true or a PEAR::Error
  1753 + */
  1754 + function update_metadata($metadata)
  1755 + {
  1756 + $packed = array();
  1757 +
  1758 + foreach($metadata as $fieldset_metadata)
  1759 + {
  1760 + $fieldsetname=$fieldset_metadata['fieldset'];
  1761 + $fieldset = KTFieldset::getByName($fieldsetname);
  1762 + if (is_null($fieldset) || PEAR::isError($fieldset))
  1763 + {
  1764 + // exit graciously
  1765 + continue;
  1766 + }
  1767 +
  1768 + foreach($fieldset_metadata['fields'] as $fieldinfo)
  1769 + {
  1770 + $fieldname = $fieldinfo['name'];
  1771 + $field = DocumentField::getByFieldsetAndName($fieldset, $fieldname);
  1772 + if (is_null($field) || PEAR::isError($fieldset))
  1773 + {
  1774 + // exit graciously
  1775 + continue;
  1776 + }
  1777 + $value = $fieldinfo['value'];
  1778 +
  1779 + $packed[] = array($field, $value);
  1780 + }
  1781 + }
  1782 +
  1783 + DBUtil::startTransaction();
  1784 + $result = KTDocumentUtil::saveMetadata($this->document, $packed);
  1785 +
  1786 + if (is_null($result))
  1787 + {
  1788 + DBUtil::rollback();
  1789 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1790 + }
  1791 + if (PEAR::isError($result))
  1792 + {
  1793 + DBUtil::rollback();
  1794 + return new PEAR_Error(sprintf(_kt("Unexpected validation failure: %s."), $result->getMessage()));
  1795 + }
  1796 + DBUtil::commit();
  1797 +
  1798 + return true;
  1799 + }
  1800 +
  1801 +
  1802 + /**
  1803 + * This returns a workflow transition
  1804 + *
  1805 + * @return array
  1806 + */
  1807 + function get_workflow_transitions()
  1808 + {
  1809 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
  1810 +
  1811 + if (PEAR::isError($user))
  1812 + {
  1813 + return $user;
  1814 + }
  1815 +
  1816 + $workflowid=$this->document->getWorkflowId();
  1817 + if (empty($workflowid))
  1818 + {
  1819 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
  1820 + }
  1821 +
  1822 + list($permission, $user) = $perm_and_user;
  1823 +
  1824 + $result = array();
  1825 +
  1826 + $transitions = KTWorkflowUtil::getTransitionsForDocumentUser($this->document, $user);
  1827 + if (is_null($transitions) || PEAR::isError($transitions))
  1828 + {
  1829 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1830 + }
  1831 + foreach($transitions as $transition)
  1832 + {
  1833 + $result[] = $transition->getName();
  1834 + }
  1835 +
  1836 + return $result;
  1837 + }
  1838 +
  1839 + /**
  1840 + * This returns the current workflow state
  1841 + *
  1842 + * @return string
  1843 + */
  1844 + function get_workflow_state()
  1845 + {
  1846 + $user = $this->can_user_access_object_requiring_permission( $this->document, KTAPI_PERMISSION_WORKFLOW);
  1847 +
  1848 + if (PEAR::isError($user))
  1849 + {
  1850 + return $user;
  1851 + }
  1852 +
  1853 + $workflowid=$this->document->getWorkflowId();
  1854 + if (empty($workflowid))
  1855 + {
  1856 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
  1857 + }
  1858 +
  1859 + list($permission, $user) = $perm_and_user;
  1860 +
  1861 + $result = array();
  1862 +
  1863 + $state = KTWorkflowUtil::getWorkflowStateForDocument($this->document);
  1864 + if (is_null($state) || PEAR::isError($state))
  1865 + {
  1866 + return new PEAR_Error(KTAPI_ERROR_WORKFLOW_INVALID);
  1867 + }
  1868 +
  1869 + $statename = $state->getName();
  1870 +
  1871 + return $statename;
  1872 +
  1873 + }
  1874 +
  1875 + /**
  1876 + * This returns detailed information on the document.
  1877 + *
  1878 + * @return array
  1879 + */
  1880 + function get_detail()
  1881 + {
  1882 + $detail = array();
  1883 + $document = $this->document;
  1884 +
  1885 + $detail['title'] = $document->getName();
  1886 +
  1887 + $documenttypeid=$document->getDocumentTypeID();
  1888 + if (is_numeric($documenttypeid))
  1889 + {
  1890 + $documenttype = DocumentType::get($documenttypeid);
  1891 +
  1892 + $detail['document_type'] = $documenttype->getName();
  1893 + }
  1894 +
  1895 + $detail['version'] = $document->getVersion();
  1896 + $detail['filename'] = $document->getFilename();
  1897 +
  1898 + $detail['created_date'] = $document->getCreatedDateTime();
  1899 +
  1900 + $userid = $document->getCreatorID();
  1901 + if (is_numeric($userid))
  1902 + {
  1903 + $user = User::get($userid);
  1904 + $username=(is_null($user) || PEAR::isError($user))?'* unknown *':$user->getName();
  1905 +
  1906 +
  1907 + $detail['created_by'] = $username;
  1908 + }
  1909 +
  1910 + $detail['updated_date'] = $document->getLastModifiedDate();
  1911 +
  1912 + $userid = $document->getModifiedUserId();
  1913 + if (is_numeric($userid))
  1914 + {
  1915 + $user = User::get($userid);
  1916 + $username=(is_null($user) || PEAR::isError($user))?'* unknown *':$user->getName();
  1917 +
  1918 + $detail['updated_by'] = $username;
  1919 + }
  1920 +
  1921 + $detail['document_id'] = $document->getId();
  1922 + $detail['folder_id'] = $document->getFolderID();
  1923 +
  1924 + $workflowid = $document->getWorkflowId();
  1925 + if (is_numeric($workflowid))
  1926 + {
  1927 + $workflow = KTWorkflow::get($workflowid);
  1928 + $workflowname=(is_null($workflow) || PEAR::isError($workflow))?'* unknown *':$workflow->getName();
  1929 + $detail['workflow'] = $workflowname;
  1930 + }
  1931 +
  1932 + $stateid = $document->getWorkflowStateId();
  1933 + if (is_numeric($stateid))
  1934 + {
  1935 + $state = KTWorkflowState::get($stateid);
  1936 + $workflowstate=(is_null($state) || PEAR::isError($state))?'* unknown *':$state->getName();
  1937 +
  1938 + $detail['workflow_state'] = $workflowstate;
  1939 + }
  1940 +
  1941 + $userid = $document->getCheckedOutUserID();
  1942 +
  1943 + if (is_numeric($userid))
  1944 + {
  1945 + $user = User::get($userid);
  1946 + $username=(is_null($user) || PEAR::isError($user))?'* unknown *':$user->getName();
  1947 +
  1948 + $detail['checkout_by'] = $username;
  1949 + }
  1950 +
  1951 + $detail['full_path'] = $this->ktapi_folder->get_full_path() . '/' . $this->get_title();
  1952 +
  1953 + return $detail;
  1954 + }
  1955 +
  1956 + function get_title()
  1957 + {
  1958 + return $this->document->getDescription();
  1959 + }
  1960 +
  1961 + /**
  1962 + * This does a download of a version of the document.
  1963 + *
  1964 + * @param string $version
  1965 + * @return true
  1966 + */
  1967 + function download($version=null)
  1968 + {
  1969 + $storage =& KTStorageManagerUtil::getSingleton();
  1970 + $options = array();
  1971 +
  1972 +
  1973 +
  1974 + $oDocumentTransaction = & new DocumentTransaction($this->document, 'Document downloaded', 'ktcore.transactions.download', $aOptions);
  1975 + $oDocumentTransaction->create();
  1976 +
  1977 + return true;
  1978 + }
  1979 +
  1980 + /**
  1981 + * This returns the transaction history for the document.
  1982 + *
  1983 + * @return array
  1984 + */
  1985 + function get_transaction_history()
  1986 + {
  1987 + $sQuery = 'SELECT DTT.name AS transaction_name, U.name AS username, DT.version AS version, DT.comment AS comment, DT.datetime AS datetime ' .
  1988 + 'FROM ' . KTUtil::getTableName('document_transactions') . ' AS DT INNER JOIN ' . KTUtil::getTableName('users') . ' AS U ON DT.user_id = U.id ' .
  1989 + 'INNER JOIN ' . KTUtil::getTableName('transaction_types') . ' AS DTT ON DTT.namespace = DT.transaction_namespace ' .
  1990 + 'WHERE DT.document_id = ? ORDER BY DT.datetime DESC';
  1991 + $aParams = array($this->documentid);
  1992 +
  1993 + $transactions = DBUtil::getResultArray(array($sQuery, $aParams));
  1994 + if (is_null($transactions) || PEAR::isError($transactions))
  1995 + {
  1996 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  1997 + }
  1998 +
  1999 + return $transactions;
  2000 + }
  2001 +
  2002 + /**
  2003 + * This returns the version history on the document.
  2004 + *
  2005 + * @return array
  2006 + */
  2007 + function get_version_history()
  2008 + {
  2009 + $metadata_versions = KTDocumentMetadataVersion::getByDocument($this->document);
  2010 +
  2011 + $versions = array();
  2012 + foreach ($metadata_versions as $version)
  2013 + {
  2014 + $document = Document::get($this->documentid, $version->getId());
  2015 +
  2016 + $version = array();
  2017 +
  2018 + $userid = $document->getModifiedUserId();
  2019 + $user = User::get($userid);
  2020 +
  2021 + $version['user'] = $user->getName();
  2022 + $version['metadata_version'] = $document->getMetadataVersion();
  2023 + $version['content_version'] = $document->getVersion();
  2024 +
  2025 + $versions[] = $version;
  2026 + }
  2027 + return $versions;
  2028 + }
  2029 +
  2030 + /**
  2031 + * This expunges a document from the system.
  2032 + *
  2033 + * @access public
  2034 + * @return mixed This returns true or a PEAR::Error
  2035 + */
  2036 + function expunge()
  2037 + {
  2038 + if ($this->document->getStatusID())
  2039 + DBUtil::startTransaction();
  2040 +
  2041 + $transaction = & new DocumentTransaction($this->document, "Document expunged", 'ktcore.transactions.expunge');
  2042 +
  2043 + $transaction->create();
  2044 +
  2045 + $this->document->delete();
  2046 +
  2047 + $this->document->cleanupDocumentData($this->documentid);
  2048 +
  2049 + $storage =& KTStorageManagerUtil::getSingleton();
  2050 +
  2051 + $result= $storage->expunge($this->document);
  2052 +
  2053 + $this->commitTransaction();
  2054 +
  2055 + return true;
  2056 + }
  2057 +
  2058 + /**
  2059 + * This expunges a document from the system.
  2060 + *
  2061 + * @access public
  2062 + * @return mixed This returns true or a PEAR::Error
  2063 + */
  2064 + function restore()
  2065 + {
  2066 + $this->startTransaction();
  2067 +
  2068 + $storage =& KTStorageManagerUtil::getSingleton();
  2069 +
  2070 + $folder = Folder::get($this->document->getRestoreFolderId());
  2071 + if (PEAR::isError($folder))
  2072 + {
  2073 + $this->document->setFolderId(1);
  2074 + $folder = Folder::get(1);
  2075 + }
  2076 + else
  2077 + {
  2078 + $this->document->setFolderId($this->document->getRestoreFolderId());
  2079 + }
  2080 +
  2081 + $storage->restore($this->document);
  2082 +
  2083 + $this->document->setStatusId(LIVE);
  2084 + $this->document->setPermissionObjectId($folder->getPermissionObjectId());
  2085 + $res = $this->document->update();
  2086 +
  2087 + $res = KTPermissionUtil::updatePermissionLookup($this->document);
  2088 +
  2089 + $user = $this->ktapi->get_user();
  2090 +
  2091 + $oTransaction = new DocumentTransaction($this->document, 'Restored from deleted state by ' . $user->getName(), 'ktcore.transactions.update');
  2092 + $oTransaction->create();
  2093 +
  2094 + $this->commitTransaction();
  2095 + }
  2096 +}
  2097 +
  2098 +class KTAPI
  2099 +{
  2100 + /**
  2101 + * This is the current session.
  2102 + *
  2103 + * @access private
  2104 + * @var KTAPI_Session
  2105 + */
  2106 + var $session = null;
  2107 +
  2108 + /**
  2109 + * This returns the current session.
  2110 + *
  2111 + * @access public
  2112 + * @return KTAPI_Session
  2113 + */
  2114 + function get_session()
  2115 + {
  2116 + return $this->session;
  2117 + }
  2118 +
  2119 + /**
  2120 + * This returns the session user.
  2121 + *
  2122 + * @access public
  2123 + * @return User
  2124 + */
  2125 + function get_user()
  2126 + {
  2127 + $ktapi_session = $this->get_session();
  2128 + if (is_null($ktapi_session) || PEAR::isError($ktapi_session))
  2129 + {
  2130 + return new PEAR_Error(KTAPI_ERROR_SESSION_INVALID);
  2131 + }
  2132 +
  2133 + $user = $ktapi_session->get_user();
  2134 + if (is_null($user) || PEAR::isError($user))
  2135 + {
  2136 + return new PEAR_Error(KTAPI_ERROR_USER_INVALID);
  2137 + }
  2138 +
  2139 + return $user;
  2140 + }
  2141 +
  2142 + /**
  2143 + * This returns a permission.
  2144 + *
  2145 + * @access static
  2146 + * @param string $permission
  2147 + * @return KTPermission
  2148 + */
  2149 + function get_permission($permission)
  2150 + {
  2151 + $permission = KTPermission::getByName($permission);
  2152 + if (is_null($permission) || PEAR::isError($permission))
  2153 + {
  2154 + return new PEAR_Error(KTAPI_ERROR_PERMISSION_INVALID);
  2155 + }
  2156 +
  2157 + return $permission;
  2158 + }
  2159 +
  2160 + /**
  2161 + * This checks if a user can access an object with a certain permission.
  2162 + *
  2163 + * @access public
  2164 + * @param object $object
  2165 + * @param string $permission
  2166 + * @return User
  2167 + */
  2168 + function can_user_access_object_requiring_permission($object, $permission)
  2169 + {
  2170 + assert(!is_null($object));
  2171 + assert(is_a($object,'DocumentProxy') || is_a($object,'FolderProxy') || is_a($object,'Document') || is_a($object,'Folder'));
  2172 +
  2173 + $permission = KTAPI::get_permission($permission);
  2174 + if (is_null($permission) || PEAR::isError($permission))
  2175 + {
  2176 + return $permission;
  2177 + }
  2178 +
  2179 + $user = KTAPI::get_user();
  2180 + if (is_null($user) || PEAR::isError($user))
  2181 + {
  2182 + return $user;
  2183 + }
  2184 +
  2185 + if (!KTPermissionUtil::userHasPermissionOnItem($user, $permission, $object))
  2186 + {
  2187 + return new PEAR_Error(KTAPI_ERROR_INSUFFICIENT_PERMISSIONS);
  2188 + }
  2189 +
  2190 + return $user;
  2191 + }
  2192 +
  2193 + /**
  2194 + * This returns a session object based on a session string.
  2195 + *
  2196 + * @access public
  2197 + * @param string $session
  2198 + * @return KTAPI_Session
  2199 + */
  2200 + function & get_active_session($session, $ip=null)
  2201 + {
  2202 + if (!is_null($this->session))
  2203 + {
  2204 + return new PEAR_Error('A session is currently active.');
  2205 + }
  2206 +
  2207 + $session = KTAPI_Session::get_active_session($this, $session, $ip);
  2208 +
  2209 + if (is_null($session) || PEAR::isError($session))
  2210 + {
  2211 + return new PEAR_Error('Session is invalid');
  2212 + }
  2213 +
  2214 + $this->session = $session;
  2215 + return $session;
  2216 + }
  2217 +
  2218 + /**
  2219 + * This returns a session object based on authentication credentials.
  2220 + *
  2221 + * @access public
  2222 + * @param string $username
  2223 + * @param string $password
  2224 + * @return KTAPI_Session
  2225 + */
  2226 + function & start_session($username, $password, $ip=null)
  2227 + {
  2228 + if (!is_null($this->session))
  2229 + {
  2230 + return new PEAR_Error('A session is currently active.');
  2231 + }
  2232 +
  2233 + $session = KTAPI_Session::start_session($this, $username, $password, $ip);
  2234 + if (is_null($session) || PEAR::isError($session))
  2235 + {
  2236 + return new PEAR_Error('Session is invalid');
  2237 + }
  2238 + $this->session = $session;
  2239 +
  2240 + return $session;
  2241 + }
  2242 +
  2243 + function start_anonymous_session($ip=null)
  2244 + {
  2245 + return $this->start_session('anonymous','',$ip);
  2246 + }
  2247 +
  2248 +
  2249 + /**
  2250 + * Obtains the root folder.
  2251 + *
  2252 + * @access public
  2253 + * @return KTAPI_Folder
  2254 + */
  2255 + function get_root_folder()
  2256 + {
  2257 + return $this->get_folder_by_id(1);
  2258 + }
  2259 +
  2260 + /**
  2261 + * Obtains the folder using a folder id.
  2262 + *
  2263 + * @access public
  2264 + * @param int $folderid
  2265 + * @return KTAPI_Folder
  2266 + */
  2267 + function get_folder_by_id($folderid)
  2268 + {
  2269 + if (is_null($this->session))
  2270 + {
  2271 + return new PEAR_Error('A session is not active');
  2272 + }
  2273 +
  2274 + $folder = KTAPI_Folder::get($this, $folderid);
  2275 +
  2276 + return $folder;
  2277 + }
  2278 +
  2279 + /**
  2280 + * This returns a refererence to a document based on document id.
  2281 + *
  2282 + * @access public
  2283 + * @param int $documentid
  2284 + * @return KTAPI_Document
  2285 + */
  2286 + function get_document_by_id($documentid)
  2287 + {
  2288 + $document = KTAPI_Document::get($this, $documentid);
  2289 +
  2290 + return $document;
  2291 + }
  2292 +
  2293 + /**
  2294 + * This returns a document type id based on the name.
  2295 + *
  2296 + * @access static
  2297 + * @param string $documenttype
  2298 + * @return int
  2299 + */
  2300 + function get_documenttypeid($documenttype)
  2301 + {
  2302 + $sql = "SELECT id FROM document_types_lookup WHERE name='$documenttype' and disabled=0";
  2303 + $row = DBUtil::getOneResult($sql);
  2304 + if (is_null($row) || PEAR::isError($row))
  2305 + {
  2306 + return new PEAR_Error(KTAPI_ERROR_DOCUMENT_TYPE_INVALID);
  2307 + }
  2308 + list($documenttypeid) = $row['id'];
  2309 + return $documenttypeid;
  2310 + }
  2311 +
  2312 + /**
  2313 + * Returns an array of document types.
  2314 + *
  2315 + * @access static
  2316 + * @return array
  2317 + */
  2318 + function get_documenttypes()
  2319 + {
  2320 + $sql = "SELECT name FROM document_types_lookup WHERE disabled=0";
  2321 + $rows = DBUtil::getResultArray($sql);
  2322 + if (is_null($rows) || PEAR::isError($rows))
  2323 + {
  2324 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  2325 + }
  2326 +
  2327 + $result = array();
  2328 + foreach($rows as $row)
  2329 + {
  2330 + $result[] = $row['name'];
  2331 + }
  2332 +
  2333 + return $result;
  2334 + }
  2335 +
  2336 + /**
  2337 + * Returns an array of username/name combinations.
  2338 + *
  2339 + * @access static
  2340 + * @return array
  2341 + */
  2342 + function get_users()
  2343 + {
  2344 + $sql = "SELECT username, name FROM users WHERE disabled=0";
  2345 + $rows = DBUtil::getResultArray($sql);
  2346 + if (is_null($rows) || PEAR::isError($rows))
  2347 + {
  2348 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  2349 + }
  2350 + return $rows;
  2351 + }
  2352 +
  2353 + /**
  2354 + * This returns an array for a lookup.
  2355 + *
  2356 + * @access static
  2357 + * @param int $fieldid
  2358 + * @return array
  2359 + */
  2360 + function get_metadata_lookup($fieldid)
  2361 + {
  2362 + $sql = "SELECT name FROM metadata_lookup WHERE disabled=0 AND document_field_id=$fieldid ORDER BY name";
  2363 + $rows = DBUtil::getResultArray($sql);
  2364 + if (is_null($rows) || PEAR::isError($rows))
  2365 + {
  2366 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  2367 + }
  2368 + $results=array();
  2369 + foreach($rows as $row)
  2370 + {
  2371 + $results[] = $row['name'];
  2372 + }
  2373 + return $results;
  2374 + }
  2375 +
  2376 + /**
  2377 + * This returns a metadata tree.
  2378 + *
  2379 + * @access private
  2380 + * @param int $fieldid
  2381 + * @param int $parentid
  2382 + * @return array
  2383 + */
  2384 + function _load_metadata_tree($fieldid, $parentid=0)
  2385 + {
  2386 + $sql = "SELECT id, name FROM metadata_lookup_tree WHERE document_field_id=$fieldid AND metadata_lookup_tree_parent=$parentid";
  2387 + $rows = DBUtil::getResultArray($sql);
  2388 + if (is_null($rows) || PEAR::isError($rows))
  2389 + {
  2390 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  2391 + }
  2392 + $results=array();
  2393 + foreach($rows as $row)
  2394 + {
  2395 + $result=array(
  2396 + 'name' => $row['name'],
  2397 + 'children' => load($fieldid, $row['id'])
  2398 + );
  2399 + $results[] = $result;
  2400 + }
  2401 + return $results;
  2402 + }
  2403 +
  2404 + /**
  2405 + * This returns a metadata tree.
  2406 + *
  2407 + * @access static
  2408 + * @param int $fieldid
  2409 + * @return array
  2410 + */
  2411 + function get_metadata_tree($fieldid)
  2412 + {
  2413 + return KTAPI::_load_metadata_tree($fieldid);
  2414 + }
  2415 +
  2416 + /**
  2417 + * Returns a list of workflows that are active.
  2418 + *
  2419 + * @access static
  2420 + * @return array
  2421 + */
  2422 + function get_workflows()
  2423 + {
  2424 + $sql = "SELECT name FROM workflows WHERE enabled=1";
  2425 + $rows=DBUtil::getResultArray($sql);
  2426 + if (is_null($rows) || PEAR::isError($rows))
  2427 + {
  2428 + return new PEAR_Error(KTAPI_ERROR_INTERNAL_ERROR);
  2429 + }
  2430 + $results=array();
  2431 + foreach($rows as $row)
  2432 + {
  2433 + $results[] = $row['name'];
  2434 + }
  2435 + return $results;
  2436 + }
  2437 +
  2438 +}
  2439 +
  2440 +class KTIndexingManager
  2441 +{
  2442 + /**
  2443 + * This is the maximum number of documents to index in one session.
  2444 + *
  2445 + * @var int
  2446 + */
  2447 + var $max_workload;
  2448 +
  2449 + function KTIndexingManager()
  2450 + {
  2451 + $this->max_workload = 5;
  2452 + }
  2453 +
  2454 + /**
  2455 + * This starts and indexing session.
  2456 + *
  2457 + * @access public
  2458 + * @return bool
  2459 + */
  2460 + function start_indexing()
  2461 + {
  2462 + throw new PEAR_Error('TODO');
  2463 + }
  2464 +
  2465 + /**
  2466 + * This indexes a new document.
  2467 + *
  2468 + * @access private
  2469 + * @return bool
  2470 + */
  2471 + function process_file()
  2472 + {
  2473 + throw new PEAR_Error('TODO');
  2474 + }
  2475 +
  2476 + /**
  2477 + * This returns a complete list of documents to be indexed. This is ideally used in reporting.
  2478 + *
  2479 + * @access public
  2480 + * @return array
  2481 + */
  2482 + function report_pending_indexing()
  2483 + {
  2484 + throw new PEAR_Error('TODO');
  2485 + }
  2486 +
  2487 + /**
  2488 + * This returns a list of documents to be indexed. This is used by start_indexing().
  2489 + *
  2490 + * @access public
  2491 + * @param int $workload
  2492 + */
  2493 + function get_pending_indexing($workload=null)
  2494 + {
  2495 + if (is_null($workload))
  2496 + {
  2497 + $workload=$this->max_workload;
  2498 + }
  2499 +
  2500 +
  2501 + throw new PEAR_Error('TODO');
  2502 + }
  2503 +
  2504 +
  2505 +}
  2506 +
  2507 +
  2508 +?>
0 \ No newline at end of file 2509 \ No newline at end of file