Commit c5fe162726c3eacb65020928e0082dba1bffee90

Authored by Megan Watson
1 parent 0a0abfab

Added new KTAPI Bulk Actions class and unit tests. Refactored some of the KTAPI_…

…Document functions to use the core functions.

Committed by: Megan Watson
Reviewed by: Kevin Cyster



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@9727 c91229c3-7414-0410-bfa2-8a42b809f60b
ktapi/KTAPIBulkActions.inc.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Bulk Actions API for KnowledgeTree
  4 + *
  5 + * KnowledgeTree Community Edition
  6 + * Document Management Made Simple
  7 + * Copyright (C) 2008, 2009 KnowledgeTree Inc.
  8 + * Portions copyright The Jam Warehouse Software (Pty) Limited
  9 + *
  10 + * This program is free software; you can redistribute it and/or modify it under
  11 + * the terms of the GNU General Public License version 3 as published by the
  12 + * Free Software Foundation.
  13 + *
  14 + * This program is distributed in the hope that it will be useful, but WITHOUT
  15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  17 + * details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + *
  22 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
  23 + * California 94120-7775, or email info@knowledgetree.com.
  24 + *
  25 + * The interactive user interfaces in modified source and object code versions
  26 + * of this program must display Appropriate Legal Notices, as required under
  27 + * Section 5 of the GNU General Public License version 3.
  28 + *
  29 + * In accordance with Section 7(b) of the GNU General Public License version 3,
  30 + * these Appropriate Legal Notices must retain the display of the "Powered by
  31 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  32 + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
  33 + * must display the words "Powered by KnowledgeTree" and retain the original
  34 + * copyright notice.
  35 + *
  36 + * @copyright 2008-2009, KnowledgeTree Inc.
  37 + * @license GNU General Public License version 3
  38 + * @author KnowledgeTree Team
  39 + * @package KnowledgeTree API
  40 + * @version Version 0.9
  41 + */
  42 +
  43 +/**
  44 + * API for the handling bulk actions on documents and folders within KnowledgeTree
  45 + *
  46 + * @author KnowledgeTree Team
  47 + * @package KnowledgeTree API
  48 + * @version 0.9
  49 + */
  50 +class KTAPI_BulkActions
  51 +{
  52 + /**
  53 + * Instance of the KTAPI object
  54 + *
  55 + * @access private
  56 + */
  57 + private $ktapi;
  58 +
  59 + /**
  60 + * Constructs the bulk actions object
  61 + *
  62 + * @author KnowledgeTree Team
  63 + * @access public
  64 + * @param KTAPI $ktapi Instance of the KTAPI object
  65 + */
  66 + function __construct(&$ktapi)
  67 + {
  68 + $this->ktapi = $ktapi;
  69 + }
  70 +
  71 + /**
  72 + * Bulk copies a list of folders and/or documents into the target folder.
  73 + * If any documents or folders fail to copy, an array is returned containing the document/folder object and the failure message.
  74 + *
  75 + * <code>
  76 + * $ktapi = new KTAPI();
  77 + * $session = $ktapi->start_system_session();
  78 + * $document = $ktapi->get_document_by_id($documentid);
  79 + *
  80 + * $root = $ktapi->get_root_folder();
  81 + * $newFolder = $root->add_folder("New target folder");
  82 + * if(PEAR::isError($newFolder)) return;
  83 + *
  84 + * $aItems = array($document);
  85 + * $bulk = new KTAPI_BulkActions($ktapi);
  86 + * $res = $bulk->copy($aItems, $newFolder, 'Bulk copy');
  87 + *
  88 + * // if documents / folders failed
  89 + * if(!empty($res)) {
  90 + * // display reason for documents failure
  91 + * foreach($res['docs'] as $failedDoc){
  92 + * echo '<br>' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
  93 + * }
  94 + * // display reason for folders failure
  95 + * foreach($res['folders'] as $failedDoc){
  96 + * echo '<br>' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
  97 + * }
  98 + * }
  99 + * </code>
  100 + *
  101 + * @author KnowledgeTree Team
  102 + * @access public
  103 + * @param array $items The folders and/or documents
  104 + * @param KTAPI_Folder $target_folder The target folder object
  105 + * @param string $reason The reason for performing the copy
  106 + * @return array|PEAR_Error Returns an array of documents and folders that couldn't be copied | PEAR_Error on failure
  107 + */
  108 + function copy($items, &$target_folder, $reason)
  109 + {
  110 + if(empty($items)) return;
  111 + assert(!is_null($target_folder));
  112 + assert($target_folder instanceof KTAPI_FOLDER);
  113 +
  114 + if(!is_array($items)){
  115 + $items = array($items);
  116 + }
  117 +
  118 + // Check user has write permission on target folder
  119 + $result = $this->ktapi->can_user_access_object_requiring_permission($target_folder->get_folder(), KTAPI_PERMISSION_WRITE);
  120 +
  121 + if (PEAR::isError($result))
  122 + {
  123 + return $result;
  124 + }
  125 +
  126 + // Copy the document or folder
  127 + // Items that fail are returned in an array with the reason for failure.
  128 +
  129 + $failed = array();
  130 + foreach ($items as $item){
  131 + assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
  132 +
  133 + $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
  134 +
  135 + $res = $item->copy($target_folder, $reason);
  136 +
  137 + if(PEAR::isError($res)){
  138 + $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
  139 + continue;
  140 + }
  141 + }
  142 +
  143 + return $failed;
  144 + }
  145 +
  146 + /**
  147 + * Bulk moves a list of folders and/or documents into the target folder
  148 + *
  149 + * <code>
  150 + * $ktapi = new KTAPI();
  151 + * $session = $ktapi->start_system_session();
  152 + * $document = $ktapi->get_document_by_id($documentid);
  153 + *
  154 + * $root = $ktapi->get_root_folder();
  155 + * $newFolder = $root->add_folder("New target folder");
  156 + * if(PEAR::isError($newFolder)) return;
  157 + *
  158 + * $aItems = array($document);
  159 + * $bulk = new KTAPI_BulkActions($ktapi)
  160 + * $res = $bulk->move($aItems, $newFolder, 'Bulk move');
  161 + *
  162 + * // if documents / folders failed
  163 + * if(!empty($res)) {
  164 + * // display reason for documents failure
  165 + * foreach($res['docs'] as $failedDoc){
  166 + * echo '<br>' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
  167 + * }
  168 + * // display reason for folders failure
  169 + * foreach($res['folders'] as $failedDoc){
  170 + * echo '<br>' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
  171 + * }
  172 + * }
  173 + * </code>
  174 + *
  175 + * @author KnowledgeTree Team
  176 + * @access public
  177 + * @param array $items The folders and/or documents
  178 + * @param KTAPI_Folder $target_folder The target folder object
  179 + * @param string $reason The reason for performing the move
  180 + * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
  181 + */
  182 + function move($items, &$target_folder, $reason)
  183 + {
  184 + if(empty($items)) return;
  185 + assert(!is_null($target_folder));
  186 + assert($target_folder instanceof KTAPI_FOLDER);
  187 +
  188 + if(!is_array($items)){
  189 + $items = array($items);
  190 + }
  191 +
  192 + // Check user has write permission on target folder
  193 + $result = $this->ktapi->can_user_access_object_requiring_permission($target_folder->get_folder(), KTAPI_PERMISSION_WRITE);
  194 +
  195 + if (PEAR::isError($result))
  196 + {
  197 + return $result;
  198 + }
  199 +
  200 + // Move the document or folder
  201 + // Items that fail are returned in an array with the reason for failure.
  202 +
  203 + $failed = array();
  204 + foreach ($items as $item){
  205 + assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
  206 +
  207 + $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
  208 +
  209 + $res = $item->move($target_folder, $reason);
  210 +
  211 + if(PEAR::isError($res)){
  212 + $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
  213 + continue;
  214 + }
  215 + }
  216 +
  217 + return $failed;
  218 + }
  219 +
  220 + /**
  221 + * Performs a bulk checkout on a list of folders and/or documents
  222 + *
  223 + * <code>
  224 + * $ktapi = new KTAPI();
  225 + * $session = $ktapi->start_system_session();
  226 + * $document = $ktapi->get_document_by_id($documentid);
  227 + * $folder = $ktapi->get_folder_by_name('New test folder');
  228 + *
  229 + * $aItems = array($document, $folder);
  230 + * $bulk = new KTAPI_BulkActions($ktapi)
  231 + * $res = $bulk->checkout($aItems, 'Bulk archive');
  232 + *
  233 + * // if documents / folders failed
  234 + * if(!empty($res)) {
  235 + * // display reason for documents failure
  236 + * foreach($res['docs'] as $failedDoc){
  237 + * echo '<br>' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
  238 + * }
  239 + * // display reason for folders failure
  240 + * foreach($res['folders'] as $failedDoc){
  241 + * echo '<br>' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
  242 + * }
  243 + * }
  244 + * </code>
  245 + *
  246 + * @author KnowledgeTree Team
  247 + * @access public
  248 + * @param array $items The folders and/or documents
  249 + * @param string $reason The reason for performing the checkout
  250 + * @return void|PEAR_Error Nothing with download set to false | PEAR_Error on failure
  251 + */
  252 + function checkout($items, $reason)
  253 + {
  254 + if(empty($items)) return;
  255 +
  256 + if(!is_array($items)){
  257 + $items = array($items);
  258 + }
  259 +
  260 + // Checkout the document or folder
  261 + // Items that fail are returned in an array with the reason for failure.
  262 +
  263 + $failed = array();
  264 + foreach ($items as $item){
  265 + // Documents
  266 + if($item instanceof KTAPI_Document){
  267 + $res = $item->checkout($reason);
  268 +
  269 + if(PEAR::isError($res)){
  270 + $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
  271 + continue;
  272 + }
  273 + }else if($item instanceof KTAPI_Folder){
  274 + // Folders - need to recurse in
  275 + DBUtil::startTransaction();
  276 + $res = $this->recurseFolder($item, $reason, 'checkout');
  277 +
  278 + if(PEAR::isError($res)){
  279 + DBUtil::rollback();
  280 + $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
  281 + continue;
  282 + }
  283 + DBUtil::commit();
  284 + }
  285 + }
  286 +
  287 + return $failed;
  288 + }
  289 +
  290 + /**
  291 + * Performs a bulk cancel checkout on a list of folders and/or documents
  292 + *
  293 + * @author KnowledgeTree Team
  294 + * @access public
  295 + * @param array $items The folders and/or documents
  296 + * @param string $reason The reason for cancelling the checkout
  297 + * @return void|PEAR_Error Nothing with download set to false | PEAR_Error on failure
  298 + */
  299 + function undo_checkout($items, $reason)
  300 + {
  301 + if(empty($items)) return;
  302 +
  303 + if(!is_array($items)){
  304 + $items = array($items);
  305 + }
  306 +
  307 + // Cancel checkout on the document or folder contents
  308 + // Items that fail are returned in an array with the reason for failure.
  309 +
  310 + $failed = array();
  311 + foreach ($items as $item){
  312 + // Documents
  313 + if($item instanceof KTAPI_Document){
  314 + $res = $item->undo_checkout($reason);
  315 +
  316 + if(PEAR::isError($res)){
  317 + $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
  318 + continue;
  319 + }
  320 + }else if($item instanceof KTAPI_Folder){
  321 + // Folders - need to recurse in
  322 + DBUtil::startTransaction();
  323 + $res = $this->recurseFolder($item, $reason, 'undo_checkout');
  324 +
  325 + if(PEAR::isError($res)){
  326 + DBUtil::rollback();
  327 + $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
  328 + continue;
  329 + }
  330 + DBUtil::commit();
  331 + }
  332 + }
  333 +
  334 + return $failed;
  335 + }
  336 +
  337 + /**
  338 + * Bulk immutes a list of documents
  339 + *
  340 + * @author KnowledgeTree Team
  341 + * @access public
  342 + * @param array $items The folders and/or documents
  343 + * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
  344 + */
  345 + function immute($items)
  346 + {
  347 + if(empty($items)) return;
  348 +
  349 + if(!is_array($items)){
  350 + $items = array($items);
  351 + }
  352 +
  353 + // Immute the documents
  354 + // Items that fail are returned in an array with the reason for failure.
  355 +
  356 + $failed = array();
  357 + foreach ($items as $item){
  358 + // Documents
  359 + if($item instanceof KTAPI_Document){
  360 + $res = $item->immute();
  361 +
  362 + if(PEAR::isError($res)){
  363 + $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
  364 + continue;
  365 + }
  366 + }else if($item instanceof KTAPI_Folder){
  367 + // Folders - need to recurse in
  368 + DBUtil::startTransaction();
  369 + $res = $this->recurseFolder($item, null, 'immute');
  370 +
  371 + if(PEAR::isError($res)){
  372 + DBUtil::rollback();
  373 + $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
  374 + continue;
  375 + }
  376 + DBUtil::commit();
  377 + }
  378 + }
  379 +
  380 + return $failed;
  381 + }
  382 +
  383 + /**
  384 + * Bulk deletes a list of folders and/or documents
  385 + *
  386 + * <code>
  387 + * $ktapi = new KTAPI();
  388 + * $session = $ktapi->start_system_session();
  389 + * $document = $ktapi->get_document_by_id($documentid);
  390 + * $folder = $ktapi->get_folder_by_name('New test folder');
  391 + *
  392 + * $aItems = array($document, $folder);
  393 + * $bulk = new KTAPI_BulkActions($ktapi)
  394 + * $res = $bulk->delete($aItems, 'Bulk delete');
  395 + *
  396 + * // if documents / folders failed
  397 + * if(!empty($res)) {
  398 + * // display reason for documents failure
  399 + * foreach($res['docs'] as $failedDoc){
  400 + * echo '<br>' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
  401 + * }
  402 + * // display reason for folders failure
  403 + * foreach($res['folders'] as $failedDoc){
  404 + * echo '<br>' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
  405 + * }
  406 + * }
  407 + * </code>
  408 + *
  409 + * @author KnowledgeTree Team
  410 + * @access public
  411 + * @param array $items The folders and/or documents
  412 + * @param string $reason The reason for performing the deletion
  413 + * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
  414 + */
  415 + function delete($items, $reason)
  416 + {
  417 + if(empty($items)) return;
  418 +
  419 + if(!is_array($items)){
  420 + $items = array($items);
  421 + }
  422 +
  423 + // Delete the document or folder
  424 + // Items that fail are returned in an array with the reason for failure.
  425 +
  426 + $failed = array();
  427 + foreach ($items as $item){
  428 + assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
  429 +
  430 + $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
  431 +
  432 + $res = $item->delete($reason);
  433 +
  434 + if(PEAR::isError($res)){
  435 + $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
  436 + continue;
  437 + }
  438 + }
  439 +
  440 + return $failed;
  441 + }
  442 +
  443 + /**
  444 + * Bulk archives a list of folders and/or documents
  445 + *
  446 + * <code>
  447 + * $ktapi = new KTAPI();
  448 + * $session = $ktapi->start_system_session();
  449 + * $document = $ktapi->get_document_by_id($documentid);
  450 + * $folder = $ktapi->get_folder_by_name('New test folder');
  451 + *
  452 + * $aItems = array($document, $folder);
  453 + * $bulk = new KTAPI_BulkActions($ktapi)
  454 + * $res = $bulk->archive($aItems, 'Bulk archive');
  455 + *
  456 + * // if documents / folders failed
  457 + * if(!empty($res)) {
  458 + * // display reason for documents failure
  459 + * foreach($res['docs'] as $failedDoc){
  460 + * echo '<br>' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
  461 + * }
  462 + * // display reason for folders failure
  463 + * foreach($res['folders'] as $failedDoc){
  464 + * echo '<br>' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
  465 + * }
  466 + * }
  467 + * </code>
  468 + *
  469 + * @author KnowledgeTree Team
  470 + * @access public
  471 + * @param array $items The folders and/or documents
  472 + * @param string $reason The reason for performing the archival
  473 + * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
  474 + */
  475 + function archive($items, $reason)
  476 + {
  477 + if(empty($items)) return;
  478 +
  479 + if(!is_array($items)){
  480 + $items = array($items);
  481 + }
  482 +
  483 + // Archive the document or folder
  484 + // Items that fail are returned in an array with the reason for failure.
  485 +
  486 + $failed = array();
  487 + foreach ($items as $item){
  488 + // Documents
  489 + if($item instanceof KTAPI_Document){
  490 + $res = $item->archive($reason);
  491 +
  492 + if(PEAR::isError($res)){
  493 + $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
  494 + continue;
  495 + }
  496 + }else if($item instanceof KTAPI_Folder){
  497 + // Folders - need to recurse in
  498 + DBUtil::startTransaction();
  499 + $res = $this->recurseFolder($item, $reason, 'archive');
  500 +
  501 + if(PEAR::isError($res)){
  502 + DBUtil::rollback();
  503 + $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
  504 + continue;
  505 + }
  506 + DBUtil::commit();
  507 + }
  508 + }
  509 +
  510 + return $failed;
  511 + }
  512 +
  513 + /**
  514 + * Recursive function to perform a given action on a folder and contained documents.
  515 + *
  516 + * @author KnowledgeTree Team
  517 + * @access private
  518 + * @param KTAPI_Folder $folder The instance of the folder object being archived
  519 + * @param string $reason The reason for archiving
  520 + * @param string $action The action to be performed on the documents
  521 + * @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
  522 + */
  523 + private function recurseFolder($folder, $reason = '', $action = 'archive')
  524 + {
  525 + if(!$folder instanceof KTAPI_Folder){
  526 + return PEAR::raiseError('Object is not an instance of KTAPI_Folder');
  527 + }
  528 +
  529 + // Archive contained documents
  530 + $listDocs = $folder->get_listing(1, 'D');
  531 + if(!empty($listDocs)) {
  532 +
  533 + foreach ($listDocs as $docInfo){
  534 + $doc = $this->ktapi->get_document_by_id($docInfo['id']);
  535 +
  536 + switch ($action){
  537 + case 'archive':
  538 + $res = $doc->archive($reason);
  539 + break;
  540 +
  541 + case 'checkout':
  542 + $res = $doc->checkout($reason);
  543 + break;
  544 +
  545 + case 'undo_checkout':
  546 + $res = $doc->undo_checkout($reason);
  547 + break;
  548 +
  549 + case 'immute':
  550 + $res = $doc->immute();
  551 + break;
  552 + }
  553 +
  554 +
  555 + if(PEAR::isError($res)){
  556 + return $res;
  557 + }
  558 + }
  559 + }
  560 +
  561 + // Archive contained folders
  562 + $listFolders = $folder->get_listing(1, 'F');
  563 + if(!empty($listFolders)) {
  564 + foreach ($listFolders as $folderItem){
  565 + $res = $this->archiveFolder($folderItem, $reason);
  566 +
  567 + if(PEAR::isError($res)){
  568 + return $res;
  569 + }
  570 + }
  571 + }
  572 + return;
  573 + }
  574 +}
  575 +?>
0 \ No newline at end of file 576 \ No newline at end of file
ktapi/KTAPIDocument.inc.php
@@ -711,6 +711,7 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -711,6 +711,7 @@ class KTAPI_Document extends KTAPI_FolderItem
711 711
712 DBUtil::commit(); 712 DBUtil::commit();
713 713
  714 + /*
714 // FIXME do we need to refactor all trigger usage into the util function? 715 // FIXME do we need to refactor all trigger usage into the util function?
715 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); 716 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
716 $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate'); 717 $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate');
@@ -725,6 +726,7 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -725,6 +726,7 @@ class KTAPI_Document extends KTAPI_FolderItem
725 $oTrigger->setInfo($aInfo); 726 $oTrigger->setInfo($aInfo);
726 $ret = $oTrigger->postValidate(); 727 $ret = $oTrigger->postValidate();
727 } 728 }
  729 + */
728 730
729 return KTAPI_Document::get($this->ktapi, $new_document->getId()); 731 return KTAPI_Document::get($this->ktapi, $new_document->getId());
730 } 732 }
@@ -1021,6 +1023,16 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -1021,6 +1023,16 @@ class KTAPI_Document extends KTAPI_FolderItem
1021 return $user; 1023 return $user;
1022 } 1024 }
1023 1025
  1026 + DBUtil::startTransaction();
  1027 + $res = KTDocumentUtil::archive($this->document, $reason);
  1028 +
  1029 + if(PEAR::isError($res)){
  1030 + DBUtil::rollback();
  1031 + return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
  1032 + }
  1033 + DBUtil::commit();
  1034 +
  1035 + /*
1024 list($permission, $user) = $perm_and_user; 1036 list($permission, $user) = $perm_and_user;
1025 1037
1026 DBUtil::startTransaction(); 1038 DBUtil::startTransaction();
@@ -1048,6 +1060,7 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -1048,6 +1060,7 @@ class KTAPI_Document extends KTAPI_FolderItem
1048 $oTrigger->setInfo($aInfo); 1060 $oTrigger->setInfo($aInfo);
1049 $ret = $oTrigger->postValidate(); 1061 $ret = $oTrigger->postValidate();
1050 } 1062 }
  1063 + */
1051 } 1064 }
1052 1065
1053 /** 1066 /**
@@ -2321,6 +2334,9 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -2321,6 +2334,9 @@ class KTAPI_Document extends KTAPI_FolderItem
2321 */ 2334 */
2322 public function immute() 2335 public function immute()
2323 { 2336 {
  2337 + if($this->is_checked_out()){
  2338 + return new PEAR_Error('Document is checked out and can\'t be set to immutable.');
  2339 + }
2324 $this->document->setImmutable(true); 2340 $this->document->setImmutable(true);
2325 $this->document->update(); 2341 $this->document->update();
2326 } 2342 }
ktapi/ktapi.inc.php
@@ -58,6 +58,7 @@ require_once(KTAPI_DIR .&#39;/KTAPIFolder.inc.php&#39;); @@ -58,6 +58,7 @@ require_once(KTAPI_DIR .&#39;/KTAPIFolder.inc.php&#39;);
58 require_once(KTAPI_DIR .'/KTAPIDocument.inc.php'); 58 require_once(KTAPI_DIR .'/KTAPIDocument.inc.php');
59 require_once(KTAPI_DIR .'/KTAPIAcl.inc.php'); 59 require_once(KTAPI_DIR .'/KTAPIAcl.inc.php');
60 require_once(KTAPI_DIR .'/KTAPICollection.inc.php'); 60 require_once(KTAPI_DIR .'/KTAPICollection.inc.php');
  61 +require_once(KTAPI_DIR .'/KTAPIBulkActions.inc.php');
61 62
62 /** 63 /**
63 * This class defines functions that MUST exist in the inheriting class 64 * This class defines functions that MUST exist in the inheriting class
lib/documentmanagement/documentutil.inc.php
@@ -152,6 +152,15 @@ class KTDocumentUtil { @@ -152,6 +152,15 @@ class KTDocumentUtil {
152 return PEAR::raiseError(_kt('Already checked out.')); 152 return PEAR::raiseError(_kt('Already checked out.'));
153 } 153 }
154 154
  155 + if($oDocument->getImmutable()){
  156 + return PEAR::raiseError(_kt('Document cannot be checked out as it is immutable'));
  157 + }
  158 +
  159 + // Check if the action is restricted by workflow on the document
  160 + if(!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.checkout')){
  161 + return PEAR::raiseError(_kt('Checkout is restricted by the workflow state.'));
  162 + }
  163 +
155 // FIXME at the moment errors this _does not_ rollback. 164 // FIXME at the moment errors this _does not_ rollback.
156 165
157 $oDocument->setIsCheckedOut(true); 166 $oDocument->setIsCheckedOut(true);
@@ -186,12 +195,8 @@ class KTDocumentUtil { @@ -186,12 +195,8 @@ class KTDocumentUtil {
186 195
187 function archive($oDocument, $sReason) { 196 function archive($oDocument, $sReason) {
188 197
189 - $this->startTransaction();  
190 - $oDocument->setStatusID(ARCHIVED);  
191 - $res = $oDocument->update();  
192 -  
193 - if (PEAR::isError($res) || ($res === false)) {  
194 - return PEAR::raiseError(_kt('There was a database error while trying to archive this file')); 198 + if($oDocument->isSymbolicLink()){
  199 + return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document."));
195 } 200 }
196 201
197 // Ensure the action is not blocked 202 // Ensure the action is not blocked
@@ -199,6 +204,13 @@ class KTDocumentUtil { @@ -199,6 +204,13 @@ class KTDocumentUtil {
199 return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.')); 204 return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.'));
200 } 205 }
201 206
  207 + $oDocument->setStatusID(ARCHIVED);
  208 + $res = $oDocument->update();
  209 +
  210 + if (PEAR::isError($res) || ($res === false)) {
  211 + return PEAR::raiseError(_kt('There was a database error while trying to archive this file'));
  212 + }
  213 +
202 //delete all shortcuts linking to this document 214 //delete all shortcuts linking to this document
203 $aSymlinks = $oDocument->getSymbolicLinks(); 215 $aSymlinks = $oDocument->getSymbolicLinks();
204 foreach($aSymlinks as $aSymlink){ 216 foreach($aSymlinks as $aSymlink){
@@ -220,8 +232,6 @@ class KTDocumentUtil { @@ -220,8 +232,6 @@ class KTDocumentUtil {
220 $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $sReason), 'ktcore.transactions.update'); 232 $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $sReason), 'ktcore.transactions.update');
221 $oDocumentTransaction->create(); 233 $oDocumentTransaction->create();
222 234
223 - $this->commitTransaction();  
224 -  
225 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); 235 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
226 $aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate'); 236 $aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
227 foreach ($aTriggers as $aTrigger) { 237 foreach ($aTriggers as $aTrigger) {
@@ -1213,11 +1223,11 @@ $sourceDocument-&gt;getName(), @@ -1213,11 +1223,11 @@ $sourceDocument-&gt;getName(),
1213 } 1223 }
1214 1224
1215 function rename($oDocument, $sNewFilename, $oUser) { 1225 function rename($oDocument, $sNewFilename, $oUser) {
1216 - $oStorage =& KTStorageManagerUtil::getSingleton();  
1217 - 1226 + $oStorage =& KTStorageManagerUtil::getSingleton();
  1227 +
1218 $oKTConfig = KTConfig::getSingleton(); 1228 $oKTConfig = KTConfig::getSingleton();
1219 - $updateVersion = $oKTConfig->get('tweaks/incrementVersionOnRename', true);  
1220 - 1229 + $updateVersion = $oKTConfig->get('tweaks/incrementVersionOnRename', true);
  1230 +
1221 $iPreviousMetadataVersion = $oDocument->getMetadataVersionId(); 1231 $iPreviousMetadataVersion = $oDocument->getMetadataVersionId();
1222 $oOldContentVersion = $oDocument->_oDocumentContentVersion; 1232 $oOldContentVersion = $oDocument->_oDocumentContentVersion;
1223 1233
@@ -1231,22 +1241,22 @@ $sourceDocument-&gt;getName(), @@ -1231,22 +1241,22 @@ $sourceDocument-&gt;getName(),
1231 1241
1232 KTDocumentUtil::copyMetadata($oDocument, $iPreviousMetadataVersion); 1242 KTDocumentUtil::copyMetadata($oDocument, $iPreviousMetadataVersion);
1233 } 1243 }
1234 - 1244 +
1235 $res = $oStorage->renameDocument($oDocument, $oOldContentVersion, $sNewFilename); 1245 $res = $oStorage->renameDocument($oDocument, $oOldContentVersion, $sNewFilename);
1236 1246
1237 if (!$res) { 1247 if (!$res) {
1238 return PEAR::raiseError(_kt('An error occurred while storing the new file')); 1248 return PEAR::raiseError(_kt('An error occurred while storing the new file'));
1239 } 1249 }
1240 -  
1241 - 1250 +
  1251 +
1242 1252
1243 $oDocument->setLastModifiedDate(getCurrentDateTime()); 1253 $oDocument->setLastModifiedDate(getCurrentDateTime());
1244 $oDocument->setModifiedUserId($oUser->getId()); 1254 $oDocument->setModifiedUserId($oUser->getId());
1245 - 1255 +
1246 if($updateVersion) { // Update version number 1256 if($updateVersion) { // Update version number
1247 $oDocument->setMinorVersionNumber($oDocument->getMinorVersionNumber()+1); 1257 $oDocument->setMinorVersionNumber($oDocument->getMinorVersionNumber()+1);
1248 } 1258 }
1249 - 1259 +
1250 $oDocument->_oDocumentContentVersion->setFilename($sNewFilename); 1260 $oDocument->_oDocumentContentVersion->setFilename($sNewFilename);
1251 1261
1252 $sType = KTMime::getMimeTypeFromFile($sNewFilename); 1262 $sType = KTMime::getMimeTypeFromFile($sNewFilename);
tests/api/testBulkActions.php 0 → 100644
  1 +<?php
  2 +require_once (KT_DIR . '/tests/test.php');
  3 +require_once (KT_DIR . '/ktapi/ktapi.inc.php');
  4 +
  5 +/**
  6 + * Unit tests for the KTAPI_BulkActions class
  7 + *
  8 + * @author KnowledgeTree Team
  9 + * @package KnowledgeTree API
  10 + * @version 0.9
  11 + */
  12 +class APIBulkActionsTestCase extends KTUnitTestCase {
  13 +
  14 + /**
  15 + * @var KTAPI
  16 + */
  17 + var $ktapi;
  18 +
  19 + /**
  20 + * @var KTAPI_Folder
  21 + */
  22 + var $root;
  23 +
  24 + /**
  25 + * @var KTAPI_Session
  26 + */
  27 + var $session;
  28 +
  29 + /**
  30 + * @var KTAPI_BulkActions
  31 + */
  32 + var $bulk;
  33 +
  34 + /**
  35 + * Create a ktapi session
  36 + */
  37 + function setUp() {
  38 + $this->ktapi = new KTAPI();
  39 + $this->session = $this->ktapi->start_system_session();
  40 + $this->root = $this->ktapi->get_root_folder();
  41 + $this->bulk = new KTAPI_BulkActions($this->ktapi);
  42 + }
  43 +
  44 + /**
  45 + * End the ktapi session
  46 + */
  47 + function tearDown() {
  48 + $this->session->logout();
  49 + }
  50 +
  51 + /**
  52 + * Test the bulk copy functionality
  53 + */
  54 + function testCopy()
  55 + {
  56 + // Create documents
  57 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  58 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  59 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  60 + $folder1 = $this->root->add_folder("New copy folder");
  61 + $this->assertNotError($newFolder);
  62 + if(PEAR::isError($newFolder)) return;
  63 +
  64 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  65 +
  66 + // Add a folder
  67 + $targetFolder = $this->root->add_folder("New target folder");
  68 + $this->assertNotError($newFolder);
  69 + if(PEAR::isError($newFolder)) return;
  70 +
  71 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  72 +
  73 + // Copy documents and folder into target folder
  74 + $res = $this->bulk->copy($aItems, $targetFolder, 'Testing bulk copy');
  75 +
  76 + $this->assertTrue(empty($res));
  77 +
  78 + // Check the documents copied
  79 + $listDocs = $targetFolder->get_listing(1, 'D');
  80 + $this->assertTrue(count($listDocs) == 3);
  81 +
  82 + // Check the folder copied
  83 + $listFolders = $targetFolder->get_listing(1, 'F');
  84 + $this->assertTrue(count($listFolders) == 1);
  85 +
  86 + // Check the document contained in the folder copied
  87 + $newFolderId = $listFolders[0]['id'];
  88 + $newFolder = $this->ktapi->get_folder_by_id($newFolderId);
  89 + $listSubDocs = $newFolder->get_listing(1, 'D');
  90 + $this->assertTrue(count($listSubDocs) == 1);
  91 +
  92 + // Delete and expunge documents and folder
  93 + $this->deleteDocument($doc1);
  94 + $this->deleteDocument($doc2);
  95 + $this->deleteDocument($doc3);
  96 + $this->deleteDocument($doc4);
  97 + $targetFolder->delete('Testing bulk copy');
  98 + $folder1->delete('Testing bulk copy');
  99 + }
  100 +
  101 + /**
  102 + * Test the bulk move functionality
  103 + */
  104 + function testMove()
  105 + {
  106 + // Create documents
  107 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  108 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  109 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  110 + $folder1 = $this->root->add_folder("New move folder");
  111 + $this->assertNotError($newFolder);
  112 + if(PEAR::isError($newFolder)) return;
  113 +
  114 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  115 +
  116 + // Add a folder
  117 + $targetFolder = $this->root->add_folder("New target folder");
  118 + $this->assertNotError($newFolder);
  119 + if(PEAR::isError($newFolder)) return;
  120 +
  121 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  122 +
  123 + // Copy documents and folder into target folder
  124 + $res = $this->bulk->move($aItems, $targetFolder, 'Testing bulk move');
  125 +
  126 + $this->assertTrue(empty($res));
  127 +
  128 + // Check document has been moved not copied
  129 + $detail = $doc1->get_detail();
  130 + $this->assertFalse($detail['folder_id'] == $this->root->get_folderid());
  131 + $this->assertTrue($detail['folder_id'] == $targetFolder->get_folderid());
  132 +
  133 + // Check folder has been moved not copied
  134 + $this->assertFalse($folder1->get_parent_folder_id() == $this->root->get_folderid());
  135 + $this->assertTrue($folder1->get_parent_folder_id() == $targetFolder->get_folderid());
  136 +
  137 + // Check the documents copied
  138 + $listDocs = $targetFolder->get_listing(1, 'D');
  139 + $this->assertTrue(count($listDocs) == 3);
  140 +
  141 + // Check the folder copied
  142 + $listFolders = $targetFolder->get_listing(1, 'F');
  143 + $this->assertTrue(count($listFolders) == 1);
  144 +
  145 + // Check the document contained in the folder copied
  146 + $newFolderId = $listFolders[0]['id'];
  147 + $newFolder = $this->ktapi->get_folder_by_id($newFolderId);
  148 + $listSubDocs = $newFolder->get_listing(1, 'D');
  149 + $this->assertTrue(count($listSubDocs) == 1);
  150 +
  151 + // Delete and expunge documents and folder
  152 + $this->deleteDocument($doc1);
  153 + $this->deleteDocument($doc2);
  154 + $this->deleteDocument($doc3);
  155 + $this->deleteDocument($doc4);
  156 + $targetFolder->delete('Testing bulk copy');
  157 + $folder1->delete('Testing bulk copy');
  158 + }
  159 +
  160 + /**
  161 + * Test the bulk checkout and cancel checkout functionality
  162 + */
  163 + function testCheckout()
  164 + {
  165 + // Create documents
  166 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  167 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  168 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  169 + $folder1 = $this->root->add_folder("New test folder");
  170 + $this->assertNotError($newFolder);
  171 + if(PEAR::isError($newFolder)) return;
  172 +
  173 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  174 +
  175 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  176 +
  177 + // Checkout documents and folder
  178 + $res = $this->bulk->checkout($aItems, 'Testing bulk checkout');
  179 +
  180 + $this->assertTrue(empty($res));
  181 +
  182 + $this->assertTrue($doc1->is_checked_out());
  183 + $this->assertTrue($doc2->is_checked_out());
  184 + $this->assertTrue($doc3->is_checked_out());
  185 + $this->assertTrue($doc4->is_checked_out());
  186 +
  187 + $res = $this->bulk->undo_checkout($aItems, 'Testing bulk undo / cancel checkout');
  188 +
  189 + $this->assertTrue(empty($res));
  190 +
  191 + $this->assertFalse($doc1->is_checked_out());
  192 + $this->assertFalse($doc2->is_checked_out());
  193 + $this->assertFalse($doc3->is_checked_out());
  194 + $this->assertFalse($doc4->is_checked_out());
  195 +
  196 + // Delete and expunge documents and folder
  197 + $this->deleteDocument($doc1);
  198 + $this->deleteDocument($doc2);
  199 + $this->deleteDocument($doc3);
  200 + $this->deleteDocument($doc4);
  201 + $folder1->delete('Testing bulk checkout');
  202 + }
  203 +
  204 + /**
  205 + * Test the bulk immute functionality
  206 + */
  207 + function testImmute()
  208 + {
  209 + // Create documents
  210 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  211 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  212 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  213 + $folder1 = $this->root->add_folder("New test folder");
  214 + $this->assertNotError($newFolder);
  215 + if(PEAR::isError($newFolder)) return;
  216 +
  217 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  218 +
  219 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  220 +
  221 + // Immute documents
  222 + $res = $this->bulk->immute($aItems);
  223 +
  224 + $this->assertTrue(empty($res));
  225 +
  226 + $this->assertTrue($doc1->isImmutable());
  227 + $this->assertTrue($doc2->isImmutable());
  228 + $this->assertTrue($doc3->isImmutable());
  229 + $this->assertTrue($doc4->isImmutable());
  230 +
  231 + // remove immutability for deletion
  232 + $doc1->unimmute();
  233 + $doc2->unimmute();
  234 + $doc3->unimmute();
  235 + $doc4->unimmute();
  236 +
  237 + // Delete and expunge documents and folder
  238 + $this->deleteDocument($doc1);
  239 + $this->deleteDocument($doc2);
  240 + $this->deleteDocument($doc3);
  241 + $this->deleteDocument($doc4);
  242 + $folder1->delete('Testing bulk checkout');
  243 + }
  244 +
  245 + /**
  246 + * Test the bulk delete functionality
  247 + */
  248 + function testDelete()
  249 + {
  250 + // Create documents
  251 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  252 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  253 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  254 + $folder1 = $this->root->add_folder("New test folder");
  255 + $this->assertNotError($newFolder);
  256 + if(PEAR::isError($newFolder)) return;
  257 +
  258 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  259 +
  260 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  261 +
  262 + // Delete documents and folder
  263 + $res = $this->bulk->delete($aItems, 'Testing bulk delete');
  264 +
  265 + $this->assertTrue(empty($res));
  266 +
  267 + // Check documents have been deleted
  268 + $this->assertTrue($doc1->is_deleted());
  269 + $this->assertTrue($doc2->is_deleted());
  270 + $this->assertTrue($doc3->is_deleted());
  271 + $this->assertTrue($doc4->is_deleted());
  272 +
  273 + // Check folder has been deleted
  274 + $folder = $this->ktapi->get_folder_by_name('New test folder');
  275 + $this->assertError($folder);
  276 +
  277 + // Expunge documents
  278 + $doc1->expunge();
  279 + $doc2->expunge();
  280 + $doc3->expunge();
  281 + $doc4->expunge();
  282 + }
  283 +
  284 + /**
  285 + * Test the bulk archive functionality
  286 + */
  287 + function testArchive()
  288 + {
  289 + // Create documents
  290 + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
  291 + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
  292 + $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
  293 + $folder1 = $this->root->add_folder("New test folder");
  294 + $this->assertNotError($newFolder);
  295 + if(PEAR::isError($newFolder)) return;
  296 +
  297 + $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
  298 +
  299 + $aItems = array($doc1, $doc2, $doc3, $folder1);
  300 +
  301 + // Archive documents and folder
  302 + $res = $this->bulk->archive($aItems, 'Testing bulk archive');
  303 +
  304 + $this->assertTrue(empty($res));
  305 +
  306 + $document1 = $doc1->getObject();
  307 + $this->assertTrue($document1->getStatusID() == 4);
  308 + $document4 = $doc4->getObject();
  309 + $this->assertTrue($document4->getStatusID() == 4);
  310 +
  311 + // Restore for deletion
  312 + $doc1->restore();
  313 + $doc2->restore();
  314 + $doc3->restore();
  315 + $doc4->restore();
  316 +
  317 + // Delete and expunge documents and folder
  318 + $this->deleteDocument($doc1);
  319 + $this->deleteDocument($doc2);
  320 + $this->deleteDocument($doc3);
  321 + $this->deleteDocument($doc4);
  322 + $folder1->delete('Testing bulk archive');
  323 + }
  324 +
  325 + /**
  326 + * Helper function to delete docs
  327 + */
  328 + function deleteDocument($document)
  329 + {
  330 + $document->delete('Testing bulk actions');
  331 + $document->expunge();
  332 + }
  333 +
  334 + /**
  335 + * Helper function to create a document
  336 + */
  337 + function createDocument($title, $filename, $folder = null)
  338 + {
  339 + if(is_null($folder)){
  340 + $folder = $this->root;
  341 + }
  342 +
  343 + // Create a new document
  344 + $randomFile = $this->createRandomFile();
  345 + $this->assertTrue(is_file($randomFile));
  346 +
  347 + $document = $folder->add_document($title, $filename, 'Default', $randomFile);
  348 + $this->assertNotError($document);
  349 +
  350 + @unlink($randomFile);
  351 + if(PEAR::isError($document)) return false;
  352 +
  353 + return $document;
  354 + }
  355 +
  356 + /**
  357 + * Helper function to create a file
  358 + *
  359 + * @param unknown_type $content
  360 + * @return unknown
  361 + */
  362 + function createRandomFile($content = 'this is some text') {
  363 + $temp = tempnam(dirname(__FILE__), 'myfile');
  364 + file_put_contents($temp, $content);
  365 + return $temp;
  366 + }
  367 +}
  368 +?>
0 \ No newline at end of file 369 \ No newline at end of file
tests/runtests.php
@@ -6,18 +6,24 @@ class UnitTests extends TestSuite { @@ -6,18 +6,24 @@ class UnitTests extends TestSuite {
6 function UnitTests() { 6 function UnitTests() {
7 7
8 $this->TestSuite('Unit tests'); 8 $this->TestSuite('Unit tests');
  9 +
  10 + // KTAPI
9 $this->addFile('api/testAuthentication.php'); 11 $this->addFile('api/testAuthentication.php');
10 $this->addFile('api/testDocument.php'); 12 $this->addFile('api/testDocument.php');
11 $this->addFile('api/testFolder.php'); 13 $this->addFile('api/testFolder.php');
12 - $this->addFile('SQLFile/test_sqlfile.php');  
13 - $this->addFile('cache/testCache.php');  
14 - $this->addFile('config/testConfig.php');  
15 - $this->addFile('document/testDocument.php');  
16 - $this->addFile('document/testDocumentUtil.php'); 14 + $this->addFile('api/testBulkActions.php');
  15 + $this->addFile('api/testCollection.php');
  16 +
  17 +// $this->addFile('SQLFile/test_sqlfile.php');
  18 +// $this->addFile('cache/testCache.php');
  19 +// $this->addFile('config/testConfig.php');
  20 +// $this->addFile('document/testDocument.php');
  21 +// $this->addFile('document/testDocumentUtil.php');
17 // $this->addFile('folder/testFolder.php'); 22 // $this->addFile('folder/testFolder.php');
18 // $this->addFile('browseutil/testBrowseUtil.php'); 23 // $this->addFile('browseutil/testBrowseUtil.php');
19 // $this->addFile('filelike/testStringFileLike.php'); 24 // $this->addFile('filelike/testStringFileLike.php');
20 25
  26 + // Search (2) and indexing
21 $this->addFile('documentProcessor/testExtracters.php'); 27 $this->addFile('documentProcessor/testExtracters.php');
22 // $this->addFile('documentProcessor/testIndexer.php'); 28 // $this->addFile('documentProcessor/testIndexer.php');
23 $this->addFile('documentProcessor/testGuidInserter.php'); 29 $this->addFile('documentProcessor/testGuidInserter.php');