Commit 3f0f6da41a8d5a8eaef9901c8c429e1260f9a3b7

Authored by Kevin G Fourie
2 parents 85c8a845 cae7096f

Merge branch 'master' of git@github.com:ktgit/knowledgetree

bin/luceneserver/ktlucene.jar
No preview for this file type
ktapi/KTAPIDocument.inc.php
@@ -1980,6 +1980,8 @@ class KTAPI_Document extends KTAPI_FolderItem @@ -1980,6 +1980,8 @@ class KTAPI_Document extends KTAPI_FolderItem
1980 { 1980 {
1981 $detail['version'] = (float) $detail['version']; 1981 $detail['version'] = (float) $detail['version'];
1982 } 1982 }
  1983 + //get the content_id
  1984 + $detail['content_id'] = $document->getContentVersionId();
1983 1985
1984 //might be unset at the bottom in case of old webservice version 1986 //might be unset at the bottom in case of old webservice version
1985 //make sure we're using the real document for this one 1987 //make sure we're using the real document for this one
ktapi/KTAPIFolder.inc.php
@@ -689,6 +689,7 @@ class KTAPI_Folder extends KTAPI_FolderItem @@ -689,6 +689,7 @@ class KTAPI_Folder extends KTAPI_FolderItem
689 'owned_by' => is_null($owned_by)?'n/a':$owned_by->getName(), 689 'owned_by' => is_null($owned_by)?'n/a':$owned_by->getName(),
690 690
691 'version' => $document->getMajorVersionNumber() . '.' . $document->getMinorVersionNumber(), 691 'version' => $document->getMajorVersionNumber() . '.' . $document->getMinorVersionNumber(),
  692 + 'content_id' => $document->getContentVersionId(),
692 693
693 'is_immutable'=> $document->getImmutable()?'true':'false', 694 'is_immutable'=> $document->getImmutable()?'true':'false',
694 'permissions' => KTAPI_Document::get_permission_string($document), 695 'permissions' => KTAPI_Document::get_permission_string($document),
lib/actions/bulkaction.php
1 -<?php  
2 -  
3 -/**  
4 - * $Id$  
5 - *  
6 - * KnowledgeTree Community Edition  
7 - * Document Management Made Simple  
8 - * Copyright (C) 2008, 2009 KnowledgeTree Inc.  
9 - * Portions copyright The Jam Warehouse Software (Pty) Limited  
10 - *  
11 - * This program is free software; you can redistribute it and/or modify it under  
12 - * the terms of the GNU General Public License version 3 as published by the  
13 - * Free Software Foundation.  
14 - *  
15 - * This program is distributed in the hope that it will be useful, but WITHOUT  
16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  
17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more  
18 - * details.  
19 - *  
20 - * You should have received a copy of the GNU General Public License  
21 - * along with this program. If not, see <http://www.gnu.org/licenses/>.  
22 - *  
23 - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,  
24 - * California 94120-7775, or email info@knowledgetree.com.  
25 - *  
26 - * The interactive user interfaces in modified source and object code versions  
27 - * of this program must display Appropriate Legal Notices, as required under  
28 - * Section 5 of the GNU General Public License version 3.  
29 - *  
30 - * In accordance with Section 7(b) of the GNU General Public License version 3,  
31 - * these Appropriate Legal Notices must retain the display of the "Powered by  
32 - * KnowledgeTree" logo and retain the original copyright notice. If the display of the  
33 - * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices  
34 - * must display the words "Powered by KnowledgeTree" and retain the original  
35 - * copyright notice.  
36 - * Contributor( s): ______________________________________  
37 - *  
38 - */  
39 -  
40 -require_once(KT_LIB_DIR . '/actions/actionregistry.inc.php');  
41 -require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php');  
42 -require_once(KT_LIB_DIR . '/dispatcher.inc.php');  
43 -require_once(KT_LIB_DIR . '/browse/browseutil.inc.php');  
44 -require_once(KT_LIB_DIR . '/actions/entitylist.php');  
45 -  
46 -require_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');  
47 -require_once(KT_LIB_DIR . '/documentmanagement/documentutil.inc.php');  
48 -  
49 -require_once(KT_LIB_DIR . '/widgets/forms.inc.php');  
50 -  
51 -require_once(KT_LIB_DIR . "/util/sanitize.inc");  
52 -  
53 -class KTBulkAction extends KTStandardDispatcher {  
54 - var $sName;  
55 - var $sDescription;  
56 -  
57 - var $_sDisablePermission;  
58 - var $bAllowInAdminMode = false;  
59 - var $sHelpPage = 'ktcore/browse.html';  
60 -  
61 - var $sSection = 'view_details';  
62 -  
63 - var $_bMutator = false;  
64 - var $_bMutationAllowedByAdmin = true;  
65 -  
66 - var $sIconClass;  
67 -  
68 - // not 'sShowPermission' - mass actions are always shown  
69 - // this is used to check against individual entities  
70 - var $_sPermission = 'ktcore.permissions.read';  
71 -  
72 - function KTBulkAction($oUser = null, $oPlugin = null) {  
73 - $this->oEntityList = null;  
74 - $this->oActiveEntityList = null;  
75 - $this->oUser =& $oUser;  
76 - $this->oPlugin =& $oPlugin;  
77 -  
78 - $this->aBreadcrumbs = array(  
79 - array('action' => 'browse', 'name' => _kt('Browse')),  
80 - );  
81 -  
82 - $this->persistParams('fEntityListCode');  
83 - parent::KTStandardDispatcher();  
84 - }  
85 -  
86 - function setEntityList(&$oEntityList) {  
87 - $this->oEntityList =& $oEntityList;  
88 - }  
89 -  
90 - function setUser(&$oUser) {  
91 - $this->oUser =& $oUser;  
92 - }  
93 -  
94 - function _show() {  
95 - return true;  
96 - }  
97 -  
98 - function getURL() {  
99 - $oKTConfig =& KTConfig::getSingleton();  
100 - $sExt = '.php';  
101 - if (KTUtil::arrayGet($_SERVER, 'kt_no_extensions')) {  
102 - $sExt = '';  
103 - }  
104 - if ($oKTConfig->get('KnowledgeTree/pathInfoSupport')) {  
105 - return sprintf('%s/action%s/%s', $GLOBALS['KTRootUrl'], $sExt, $this->sName);  
106 - } else {  
107 - return sprintf('%s/action%s?kt_path_info=%s', $GLOBALS['KTRootUrl'], $sExt, $this->sName);  
108 - }  
109 - }  
110 -  
111 - function getInfo() {  
112 - if ($this->_show() === false) {  
113 - return null;  
114 - }  
115 -  
116 - $url = $this->getURL();  
117 -  
118 - $aInfo = array(  
119 - 'description' => $this->sDescription,  
120 - 'name' => $this->getDisplayName(),  
121 - 'ns' => $this->sName,  
122 - 'url' => $url,  
123 - 'icon_class' => $this->sIconClass,  
124 - );  
125 -  
126 - $aInfo = $this->customiseInfo($aInfo);  
127 - return $aInfo;  
128 - }  
129 -  
130 - function getName() {  
131 - return sanitizeForSQLtoHTML($this->sName);  
132 - }  
133 -  
134 - function getDisplayName() {  
135 - return sanitizeForSQLtoHTML($this->sDisplayName);  
136 - }  
137 -  
138 - function getDescription() {  
139 - return sanitizeForSQLtoHTML($this->sDescription);  
140 - }  
141 -  
142 - function customiseInfo($aInfo) {  
143 - return $aInfo;  
144 - }  
145 -  
146 - // helper function  
147 - function _getNames($aIds, $sEntity) {  
148 - if(count($aIds)) {  
149 - $aNames = array();  
150 - $aFunc = array($sEntity, 'get');  
151 -  
152 - foreach($aIds as $id) {  
153 - $oE =& call_user_func($aFunc, $id);  
154 - $name = array();  
155 - $name['name'] = $oE->getName();  
156 - //add shortcut notice if the entity is a shortcut  
157 - if($oE->isSymbolicLink()){  
158 - $name['notice'] = _kt("Shortcut");  
159 - }  
160 - $aNames[] = $name;  
161 - }  
162 - return $aNames;  
163 - } else {  
164 - return array();  
165 - }  
166 - }  
167 -  
168 - /**  
169 - * Checks if there are symlinks that are linking to items in the current list  
170 - * Useful if you want to prompt the user with a confirmation because they're  
171 - * automatically deleted when their targets are deleted or archived.  
172 - *  
173 - * @return boolean  
174 - */  
175 - function symlinksLinkingToCurrentList(){  
176 - $symlinksPresent = false;  
177 - foreach($this->oActiveEntityList->getDocumentIds() as $iDocument){  
178 - $oDocument = Document::get($iDocument);  
179 - if(count($oDocument->getSymbolicLinks()) > 0){  
180 - $symlinksPresent = true;  
181 - break;  
182 - }  
183 - }  
184 - if($symlinksPresent == false){  
185 - foreach($this->oActiveEntityList->getFolderIds() as $iFolder){  
186 - $oStartFolder = Folder::get($iFolder);  
187 - $aRemainingFolders = array($oStartFolder->getId());  
188 - while (!empty($aRemainingFolders)) {  
189 - $iFolderId = array_pop($aRemainingFolders);  
190 - $oFolder = Folder::get($iFolderId);  
191 -  
192 - if(count($oFolder->getSymbolicLinks()) > 0){  
193 - $symlinksPresent = true;  
194 - break;  
195 - }  
196 -  
197 - $aChildDocs = Document::getList(array('folder_id = ?',array($iFolderId)));  
198 - foreach ($aChildDocs as $oDoc) {  
199 - if(count($oDoc->getSymbolicLinks()) > 0){  
200 - $symlinksPresent = true;  
201 - break;  
202 - }  
203 - }  
204 -  
205 - $aCFIds = Folder::getList(array('parent_id = ?', array($iFolderId)), array('ids' => true));  
206 - $aRemainingFolders = kt_array_merge($aRemainingFolders, $aCFIds);  
207 - }  
208 - }  
209 - }  
210 - return $symlinksPresent;  
211 - }  
212 -  
213 -/**  
214 - * checks a folderList for shortcuts and queries the repositories for all folders  
215 - * that are somehow connected to these folders.  
216 - */  
217 - function getLinkingEntities($aFolderList){  
218 - $aSearchFolders = array();  
219 - if(!empty($aFolderList)){  
220 - foreach($aFolderList as $oFolderItem){  
221 - if(Permission::userHasFolderReadPermission($oFolderItem)){  
222 - // If it is a shortcut, we should do some more searching  
223 - if($oFolderItem->isSymbolicLink()){  
224 - $oFolderItem = $oFolderItem->getLinkedFolder();  
225 - $aSearchFolders[] = $oFolderItem->getID();  
226 - }  
227 - }  
228 - }  
229 - }  
230 - $aLinkingFolders = array();  
231 - $aSearchCompletedFolders = array();  
232 - $count = 0;  
233 - while(count($aSearchFolders)>0){  
234 - $count++;  
235 - $oFolder = Folder::get(array_pop($aSearchFolders));  
236 - $sFolderId = $oFolder->getId();  
237 - // Get all the folders within the current folder  
238 - $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR  
239 - parent_folder_ids LIKE '{$sFolderId},%' OR  
240 - parent_folder_ids LIKE '%,{$sFolderId},%' OR  
241 - parent_folder_ids LIKE '%,{$sFolderId}'";  
242 - $aFolderList = $this->oFolder->getList($sWhereClause);  
243 - foreach($aFolderList as $oFolderItem){  
244 - if($oFolderItem->isSymbolicLink()){  
245 - $oFolderItem = $oFolderItem->getLinkedFolder();  
246 - }  
247 - if(Permission::userHasFolderReadPermission($oFolderItem)){  
248 - if($aSearchCompletedFolders[$oFolderItem->getID()] != true){  
249 - $aSearchFolders[] = $oFolderItem->getID();  
250 - $aSearchCompletedFolders[$oFolderItem->getID()] = true;  
251 - }  
252 - }  
253 - }  
254 - if(!isset($aLinkingFolders[$oFolder->getId()])){  
255 - $aLinkingFolders[$oFolder->getId()] = $oFolder;  
256 - }  
257 - }  
258 - return $aLinkingFolders;  
259 - }  
260 -  
261 - // doesn't actually do checks, as they have to be performed per-entity  
262 - function check() {  
263 - // not necessarily coming from a folder...  
264 - $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', 1);  
265 - $this->oFolder = Folder::get($iFolderId);  
266 - //$this->oFolder =& $this->oValidator->validateFolder($_REQUEST['fFolderId']);  
267 -  
268 - $aOptions = array(  
269 - 'final' => false,  
270 - 'documentaction' => 'viewDocument',  
271 - 'folderaction' => 'browse',  
272 - );  
273 -  
274 - $this->aBreadcrumbs = array(array('name'=>_kt('Bulk Actions')),  
275 - array('name'=>$this->getDisplayName()));  
276 -  
277 - return true;  
278 - }  
279 -  
280 -  
281 - // check the entire entity list. this needn't be overrided at any point  
282 - function check_entities() {  
283 - $aFailed = array('documents' => array(), 'folders' => array());  
284 - $aSucceeded = array('documents' => array(), 'folders' => array());  
285 -  
286 - if(!$this->oEntityList) {  
287 - return true;  
288 - }  
289 -  
290 - foreach($this->oEntityList->getDocumentIds() as $iId) {  
291 - $oDocument =& Document::get($iId);  
292 -  
293 - if(PEAR::isError($oDocument)) {  
294 - $aFailed['documents'][] = array($iId, _kt('No such document'));  
295 - } else {  
296 - $res = $this->check_entity($oDocument);  
297 -  
298 - // all these checks allow a return from check_entity of:  
299 - // 1. a PEAR error, indicating failure, with the message in the error  
300 - // 2. false, for unknown error  
301 - // 3. true, to pass  
302 -  
303 - if(PEAR::isError($res)) {  
304 - $aFailed['documents'][] = array($oDocument->getName(), $res->getMessage());  
305 - } else if($res === false) {  
306 - $aFailed['documents'][] = array($oDocument->getName(), _kt('Failed (unknown reason)'));  
307 - } else {  
308 - $aSucceeded['documents'][] = $oDocument->getId();  
309 - }  
310 - }  
311 - }  
312 -  
313 - foreach($this->oEntityList->getFolderIds() as $iId) {  
314 - $oFolder =& Folder::get($iId);  
315 -  
316 - if(PEAR::isError($oFolder)) {  
317 - $aFailed['folders'][] = array($iId, _kt('No such folder'));  
318 - } else {  
319 - $res = $this->check_entity($oFolder);  
320 -  
321 - if(PEAR::isError($res)) {  
322 - $aFailed['folders'][] = array($oFolder->getName(), $res->getMessage());  
323 - } else if($res === false) {  
324 - $aFailed['folders'][] = array($oFolder->getName(), _kt('Failed (unknown reason)'));  
325 - } else {  
326 - $aSucceeded['folders'][] = $oFolder->getId();  
327 - }  
328 - }  
329 - }  
330 - $this->oActiveEntityList = new KTEntityList($aSucceeded['documents'], $aSucceeded['folders']);  
331 - $this->aFailed = $aFailed;  
332 -  
333 - return count($aSucceeded['documents']) + count($aSucceeded['folders']);  
334 - }  
335 -  
336 -  
337 - // iterate over all entites to act on them  
338 - function perform_action_on_list() {  
339 - $this->aActionResults = array('folders'=>array(), 'documents'=>array());  
340 -  
341 - foreach($this->oActiveEntityList->getDocumentIds() as $iId) {  
342 - $oDocument =& Document::get($iId);  
343 - if(!PEAR::isError($oDocument)) {  
344 - $sName = $oDocument->getName();  
345 - } else {  
346 - $sName = _kt('Error fetching document name');  
347 - }  
348 -  
349 - $res = $this->perform_action($oDocument);  
350 -  
351 - //check for shortcut notice  
352 - $notice = null;  
353 - if($oDocument->isSymbolicLink()){  
354 - $notice = _kt("Shortcut");  
355 - }  
356 -  
357 - if(PEAR::isError($res)) {  
358 - $this->aActionResults['documents'][] = array($sName, $res->getMessage(), $notice);  
359 - } else {  
360 - $this->aActionResults['documents'][] = array($sName, _kt('Success'), $notice);  
361 - }  
362 - }  
363 -  
364 - foreach($this->oActiveEntityList->getFolderIds() as $iId) {  
365 - $oFolder =& Folder::get($iId);  
366 - if(!PEAR::isError($oFolder)) {  
367 - $sName = $oFolder->getName();  
368 - } else {  
369 - $sName = _kt('Error fetching folder name');  
370 - }  
371 -  
372 - $res = $this->perform_action($oFolder);  
373 -  
374 - //check for shortcut notice  
375 - $notice = null;  
376 - if($oFolder->isSymbolicLink()){  
377 - $notice = _kt("Shortcut");  
378 - }  
379 -  
380 - if(PEAR::isError($res)) {  
381 - $this->aActionResults['folders'][] = array($sName, $res->getMessage(), $notice);  
382 - } else {  
383 - $this->aActionResults['folders'][] = array($sName, _kt('Success'), $notice);  
384 - }  
385 - }  
386 - }  
387 -  
388 -  
389 -  
390 - // list persistance  
391 - // fetch existing lists  
392 - function get_lists() {  
393 - $this->oEntityList = KTEntityList::retrieveList(KTUtil::arrayGet($_REQUEST, 'fListCode', null));  
394 - $this->oActiveEntityList = KTEntityList::retrieveList(KTUtil::arrayGet($_REQUEST, 'fActiveListCode', null));  
395 - if(PEAR::isError($this->oActiveEntityList)) {  
396 - $this->oActiveEntityList = null;  
397 - }  
398 - }  
399 -  
400 - // persist  
401 - function store_lists() {  
402 - $this->persistParams(array('fListCode', 'fActiveListCode', 'fFolderId', 'fReturnData', 'fReturnAction'));  
403 - }  
404 -  
405 - /**  
406 - * Get the return url based on the return action and data  
407 - */  
408 - function getReturnUrl()  
409 - {  
410 - $sReturnAction = $_REQUEST['fReturnAction'];  
411 - $sReturnData = $_REQUEST['fReturnData'];  
412 - $sAction = 'main';  
413 - $qs = '';  
414 -  
415 - switch ($sReturnAction){  
416 - case 'browse':  
417 - $sReturnData = (empty($sReturnData)) ? $_REQUEST['fFolderId'] : $sReturnData;  
418 - $sTargetUrl = KTBrowseUtil::getUrlForFolder(Folder::get($sReturnData));  
419 - break;  
420 - case 'simpleSearch':  
421 - $sTargetUrl = KTBrowseUtil::getSimpleSearchBaseUrl();  
422 - $extra = 'fSearchableText='.$sReturnData;  
423 - break;  
424 - case 'booleanSearch':  
425 - $sTargetUrl = KTBrowseUtil::getBooleanSearchBaseUrl();  
426 - $sAction = 'performSearch';  
427 - $extra = 'boolean_search_id='.$sReturnData;  
428 - break;  
429 - case 'search2':  
430 - $sTargetUrl = KTBrowseUtil::getSearchResultURL();  
431 - $sAction = 'searchResults';  
432 - break;  
433 - default:  
434 - $sTargetUrl = $sReturnAction;  
435 - $sAction = '';  
436 - }  
437 -  
438 - $qs = (!empty($sAction))? 'action='.$sAction : '';  
439 - $qs .= (!empty($extra))? '&'.$extra : '';  
440 - $sTargetUrl = KTUtil::addQueryString($sTargetUrl, $qs);  
441 -  
442 - return $sTargetUrl;  
443 - }  
444 -  
445 - // forms  
446 - // form to list the entites after checking each one  
447 - function form_listing() {  
448 - $sListCode = $this->oEntityList->getCode();  
449 - $sActiveListCode = $this->oActiveEntityList->getCode();  
450 -  
451 - $sTargetUrl = $this->getReturnUrl();  
452 -  
453 - $oForm = new KTForm;  
454 - $oForm->setOptions(array(  
455 - 'identifier' => 'ktcore.actions.bulk.listing.form',  
456 - 'submit_label' => _kt('Continue'),  
457 - 'targeturl' => $this->getURL(),  
458 - 'action' => 'collectinfo',  
459 - 'fail_action' => 'main',  
460 - 'cancel_url' => $sTargetUrl,  
461 - 'noframe' => true,  
462 - 'extraargs' => array('fListCode' => $sListCode,  
463 - 'fActiveListCode' => $sActiveListCode,  
464 - 'fFolderId' => $this->oFolder->getId(),  
465 - 'fReturnAction' => KTUtil::arrayGet($_REQUEST, 'fReturnAction'),  
466 - 'fReturnData' => KTUtil::arrayGet($_REQUEST, 'fReturnData'),  
467 - ),  
468 - 'context' => $this,  
469 - ));  
470 - return $oForm;  
471 - }  
472 -  
473 - // form to show on action completion, and list results  
474 - function form_complete() {  
475 - $sReturnAction = KTUtil::arrayGet($_REQUEST, 'fReturnAction');  
476 - $sReturnData = KTUtil::arrayGet($_REQUEST, 'fReturnData');  
477 - $sAction = 'main';  
478 -  
479 - switch ($sReturnAction){  
480 - case 'browse':  
481 - $sReturnData = (empty($sReturnData)) ? $_REQUEST['fFolderId'] : $sReturnData;  
482 - $sTargetUrl = KTBrowseUtil::getUrlForFolder(Folder::get($sReturnData));  
483 - break;  
484 - case 'simpleSearch': // do we use this?  
485 - $sTargetUrl = KTBrowseUtil::getSimpleSearchBaseUrl();  
486 - $extraargs = array('fSearchableText'=>$sReturnData);  
487 - break;  
488 - case 'booleanSearch': // do we use this?  
489 - $sTargetUrl = KTBrowseUtil::getBooleanSearchBaseUrl();  
490 - $sAction = 'performSearch';  
491 - $extraargs = array('boolean_search_id'=>$sReturnData);  
492 - break;  
493 - case 'search2':  
494 - $sTargetUrl = KTBrowseUtil::getSearchResultURL();  
495 - $sAction = 'refresh';  
496 - break;  
497 - default:  
498 - $sTargetUrl = $sReturnAction;  
499 - $sAction = '';  
500 - }  
501 -  
502 - $oForm = new KTForm;  
503 - $oForm->setOptions(array(  
504 - 'identifier' => 'ktcore.actions.bulk.complete.form',  
505 - 'submit_label' => _kt('Return'),  
506 - 'targeturl' => $sTargetUrl,  
507 - 'context' => $this,  
508 - 'action' => $sAction,  
509 - 'extraargs' => $extraargs,  
510 - 'noframe' => true,  
511 - ));  
512 - return $oForm;  
513 - }  
514 -  
515 -  
516 - // main entry point - checks the entity list and displays lists  
517 - function do_main() {  
518 - // get entities (using the checkboxes atm)  
519 - $aFolders = KTUtil::arrayGet($_REQUEST, 'selection_f' , array());  
520 - $aDocuments = KTUtil::arrayGet($_REQUEST, 'selection_d' , array());  
521 - $this->oEntityList = new KTEntityList($aDocuments, $aFolders);  
522 -  
523 - // gives us $this->aFailed  
524 - $iActiveCount = $this->check_entities();  
525 -  
526 - $oTemplating =& KTTemplating::getSingleton();  
527 - $oTemplate = $oTemplating->loadTemplate('ktcore/bulk_action_listing');  
528 -  
529 - $this->store_lists();  
530 -  
531 - return $oTemplate->render(array('context' => $this,  
532 - 'form' => $this->form_listing(),  
533 - 'failed' => $this->aFailed,  
534 - 'active' => $this->oActiveEntityList,  
535 - 'activecount' => $iActiveCount,  
536 - 'failedform' => $this->form_complete(),  
537 - 'folders' => $this->_getNames($this->oActiveEntityList->getFolderIds(), 'Folder'),  
538 - 'documents' => $this->_getNames($this->oActiveEntityList->getDocumentIds(), 'Document')));  
539 -  
540 - }  
541 -  
542 - // override to add a screen to get a reason, or whatever  
543 - // remember to pass to perform action next, and call the super's method  
544 - function do_collectinfo() {  
545 - $this->store_lists();  
546 - return $this->do_performaction();  
547 - }  
548 -  
549 - // perform the action itself, and list results (completion action)  
550 - function do_performaction() {  
551 - $this->get_lists();  
552 - $this->aPersistParams = array();  
553 - $this->perform_action_on_list();  
554 -  
555 - $oTemplating =& KTTemplating::getSingleton();  
556 - $oTemplate = $oTemplating->loadTemplate('ktcore/bulk_action_complete');  
557 - return $oTemplate->render(array('context' => $this,  
558 - 'list' => $this->aActionResults,  
559 - 'form' => $this->form_complete()));  
560 - }  
561 -  
562 -  
563 -  
564 -  
565 -  
566 -  
567 - // main overrides  
568 -  
569 - // override to do the actual action, on an individual entity  
570 - function perform_action($oEntity) {  
571 - return PEAR::raiseError(_kt('Action component not implemented'));  
572 - }  
573 -  
574 - // check an individual entity - this should be overrided with additional  
575 - // checks required for the specific action, but should always call its  
576 - // parent implementation  
577 - function check_entity($oEntity) {  
578 - $oPermission =& KTPermission::getByName($this->_sPermission);  
579 - if(PEAR::isError($oPermission)) {  
580 - return true;  
581 - }  
582 -  
583 - // basic document checks  
584 -  
585 - // TODO: check if this is appropriate  
586 - // should probably store the 'equivalent' action (ie. document.delete)  
587 - // and check that, rather than add a new list of actions to the workflow  
588 - // section  
589 - if(is_a($oEntity, 'Document')) {  
590 - if(!KTWorkflowUtil::actionEnabledForDocument($oEntity, $this->sName)) {  
591 - return PEAR::raiseError(_kt('Action is disabled by workflow'));  
592 - }  
593 - $status = $oEntity->getStatusID();  
594 - if($status==DELETED||$status==ARCHIVED) {  
595 - return PEAR::raiseError(_kt('Document is archived or deleted'));  
596 - }  
597 - }  
598 -  
599 - // admin check  
600 - if($this->bAllowInAdminMode) {  
601 - if(KTBrowseUtil::inAdminMode($this->oUser, null)) {  
602 - return true;  
603 - }  
604 - }  
605 -  
606 - if(!KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $oEntity)) {  
607 - return PEAR::raiseError(_kt('You do not have the required permissions'));  
608 - }  
609 -  
610 - return true;  
611 - }  
612 -  
613 -  
614 -}  
615 -  
616 -class KTBulkDocumentAction extends KTBulkAction {  
617 - function check_entity($oEntity) {  
618 - if(!is_a($oEntity, 'Document')) {  
619 - return false;  
620 - }  
621 - return parent::check_entity($oEntity);  
622 - }  
623 -}  
624 -  
625 -class KTBulkFolderAction extends KTBulkAction {  
626 - function check_entity($oEntity) {  
627 - if(!is_a($oEntity, 'Folder')) {  
628 - return false;  
629 - }  
630 - return parent::check_entity($oEntity);  
631 - }  
632 -}  
633 -  
634 -  
635 -  
636 -// util class for bulk actions  
637 -  
638 -class KTBulkActionUtil {  
639 - function getBulkActionInfo($slot = 'bulkaction') {  
640 - $oRegistry =& KTActionRegistry::getSingleton();  
641 - return $oRegistry->getActions($slot);  
642 - }  
643 -  
644 - function getAllBulkActions($slot = 'bulkaction') {  
645 - $aObjects = array();  
646 -  
647 - foreach (KTBulkActionUtil::getBulkActionInfo($slot) as $aAction) {  
648 - list($sClassName, $sPath, $sName, $sPlugin) = $aAction;  
649 - $oRegistry =& KTPluginRegistry::getSingleton();  
650 - $oPlugin =& $oRegistry->getPlugin($sPlugin);  
651 - if (!empty($sPath)) {  
652 - require_once($sPath);  
653 - }  
654 - $aObjects[] = new $sClassName(null, null, $oPlugin);  
655 - }  
656 - return $aObjects;  
657 - }  
658 -  
659 - function getBulkActionsByNames($aNames, $slot = 'bulkaction', $oUser = null) {  
660 - $aObjects = array();  
661 - foreach (KTBulkActionUtil::getBulkActionInfo($slot) as $aAction) {  
662 - list($sClassName, $sPath, $sName, $sPlugin) = $aAction;  
663 - $oRegistry =& KTPluginRegistry::getSingleton();  
664 - $oPlugin =& $oRegistry->getPlugin($sPlugin);  
665 - if (!in_array($sName, $aNames)) {  
666 - continue;  
667 - }  
668 - if (!empty($sPath)) {  
669 - require_once($sPath);  
670 - }  
671 - $aObjects[] = new $sClassName(null, $oUser, $oPlugin);  
672 - }  
673 - return $aObjects;  
674 - }  
675 -}  
676 -  
677 -?> 1 +<?php
  2 +
  3 +/**
  4 + * $Id$
  5 + *
  6 + * KnowledgeTree Community Edition
  7 + * Document Management Made Simple
  8 + * Copyright (C) 2008, 2009 KnowledgeTree Inc.
  9 + * Portions copyright The Jam Warehouse Software (Pty) Limited
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify it under
  12 + * the terms of the GNU General Public License version 3 as published by the
  13 + * Free Software Foundation.
  14 + *
  15 + * This program is distributed in the hope that it will be useful, but WITHOUT
  16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  18 + * details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22 + *
  23 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
  24 + * California 94120-7775, or email info@knowledgetree.com.
  25 + *
  26 + * The interactive user interfaces in modified source and object code versions
  27 + * of this program must display Appropriate Legal Notices, as required under
  28 + * Section 5 of the GNU General Public License version 3.
  29 + *
  30 + * In accordance with Section 7(b) of the GNU General Public License version 3,
  31 + * these Appropriate Legal Notices must retain the display of the "Powered by
  32 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  33 + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
  34 + * must display the words "Powered by KnowledgeTree" and retain the original
  35 + * copyright notice.
  36 + * Contributor( s): ______________________________________
  37 + *
  38 + */
  39 +
  40 +require_once(KT_LIB_DIR . '/actions/actionregistry.inc.php');
  41 +require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php');
  42 +require_once(KT_LIB_DIR . '/dispatcher.inc.php');
  43 +require_once(KT_LIB_DIR . '/browse/browseutil.inc.php');
  44 +require_once(KT_LIB_DIR . '/actions/entitylist.php');
  45 +
  46 +require_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
  47 +require_once(KT_LIB_DIR . '/documentmanagement/documentutil.inc.php');
  48 +
  49 +require_once(KT_LIB_DIR . '/widgets/forms.inc.php');
  50 +
  51 +require_once(KT_LIB_DIR . "/util/sanitize.inc");
  52 +
  53 +// // Jarrett Jordaan: Deal with bulk action
  54 +require_once(KT_LIB_DIR . '/subscriptions/subscriptions.inc.php');
  55 +
  56 +class KTBulkAction extends KTStandardDispatcher {
  57 + var $sName;
  58 + var $sDescription;
  59 +
  60 + var $_sDisablePermission;
  61 + var $bAllowInAdminMode = false;
  62 + var $sHelpPage = 'ktcore/browse.html';
  63 +
  64 + var $sSection = 'view_details';
  65 +
  66 + var $_bMutator = false;
  67 + var $_bMutationAllowedByAdmin = true;
  68 +
  69 + var $sIconClass;
  70 +
  71 + // not 'sShowPermission' - mass actions are always shown
  72 + // this is used to check against individual entities
  73 + var $_sPermission = 'ktcore.permissions.read';
  74 +
  75 + // Bulk Action Notification
  76 + var $uploadedDocs;
  77 + var $uploadedFolders;
  78 + var $eventAction;
  79 +
  80 + function KTBulkAction($oUser = null, $oPlugin = null) {
  81 + $this->oEntityList = null;
  82 + $this->oActiveEntityList = null;
  83 + $this->oUser =& $oUser;
  84 + $this->oPlugin =& $oPlugin;
  85 + // Bulk Action Notification
  86 + $this->uploadedDocs = array();
  87 + $this->uploadedFolders = array();
  88 + $this->eventAction = null;
  89 + $this->aBreadcrumbs = array(
  90 + array('action' => 'browse', 'name' => _kt('Browse')),
  91 + );
  92 +
  93 + $this->persistParams('fEntityListCode');
  94 + parent::KTStandardDispatcher();
  95 + }
  96 +
  97 + function setEntityList(&$oEntityList) {
  98 + $this->oEntityList =& $oEntityList;
  99 + }
  100 +
  101 + function setUser(&$oUser) {
  102 + $this->oUser =& $oUser;
  103 + }
  104 +
  105 + function _show() {
  106 + return true;
  107 + }
  108 +
  109 + function getURL() {
  110 + $oKTConfig =& KTConfig::getSingleton();
  111 + $sExt = '.php';
  112 + if (KTUtil::arrayGet($_SERVER, 'kt_no_extensions')) {
  113 + $sExt = '';
  114 + }
  115 + if ($oKTConfig->get('KnowledgeTree/pathInfoSupport')) {
  116 + return sprintf('%s/action%s/%s', $GLOBALS['KTRootUrl'], $sExt, $this->sName);
  117 + } else {
  118 + return sprintf('%s/action%s?kt_path_info=%s', $GLOBALS['KTRootUrl'], $sExt, $this->sName);
  119 + }
  120 + }
  121 +
  122 + function getInfo() {
  123 + if ($this->_show() === false) {
  124 + return null;
  125 + }
  126 +
  127 + $url = $this->getURL();
  128 +
  129 + $aInfo = array(
  130 + 'description' => $this->sDescription,
  131 + 'name' => $this->getDisplayName(),
  132 + 'ns' => $this->sName,
  133 + 'url' => $url,
  134 + 'icon_class' => $this->sIconClass,
  135 + );
  136 +
  137 + $aInfo = $this->customiseInfo($aInfo);
  138 + return $aInfo;
  139 + }
  140 +
  141 + function getName() {
  142 + return sanitizeForSQLtoHTML($this->sName);
  143 + }
  144 +
  145 + function getDisplayName() {
  146 + return sanitizeForSQLtoHTML($this->sDisplayName);
  147 + }
  148 +
  149 + function getDescription() {
  150 + return sanitizeForSQLtoHTML($this->sDescription);
  151 + }
  152 +
  153 + function customiseInfo($aInfo) {
  154 + return $aInfo;
  155 + }
  156 +
  157 + // helper function
  158 + function _getNames($aIds, $sEntity) {
  159 + if(count($aIds)) {
  160 + $aNames = array();
  161 + $aFunc = array($sEntity, 'get');
  162 +
  163 + foreach($aIds as $id) {
  164 + $oE =& call_user_func($aFunc, $id);
  165 + $name = array();
  166 + $name['name'] = $oE->getName();
  167 + //add shortcut notice if the entity is a shortcut
  168 + if($oE->isSymbolicLink()){
  169 + $name['notice'] = _kt("Shortcut");
  170 + }
  171 + $aNames[] = $name;
  172 + }
  173 + return $aNames;
  174 + } else {
  175 + return array();
  176 + }
  177 + }
  178 +
  179 + /**
  180 + * Checks if there are symlinks that are linking to items in the current list
  181 + * Useful if you want to prompt the user with a confirmation because they're
  182 + * automatically deleted when their targets are deleted or archived.
  183 + *
  184 + * @return boolean
  185 + */
  186 + function symlinksLinkingToCurrentList(){
  187 + $symlinksPresent = false;
  188 + foreach($this->oActiveEntityList->getDocumentIds() as $iDocument){
  189 + $oDocument = Document::get($iDocument);
  190 + if(count($oDocument->getSymbolicLinks()) > 0){
  191 + $symlinksPresent = true;
  192 + break;
  193 + }
  194 + }
  195 + if($symlinksPresent == false){
  196 + foreach($this->oActiveEntityList->getFolderIds() as $iFolder){
  197 + $oStartFolder = Folder::get($iFolder);
  198 + $aRemainingFolders = array($oStartFolder->getId());
  199 + while (!empty($aRemainingFolders)) {
  200 + $iFolderId = array_pop($aRemainingFolders);
  201 + $oFolder = Folder::get($iFolderId);
  202 +
  203 + if(count($oFolder->getSymbolicLinks()) > 0){
  204 + $symlinksPresent = true;
  205 + break;
  206 + }
  207 +
  208 + $aChildDocs = Document::getList(array('folder_id = ?',array($iFolderId)));
  209 + foreach ($aChildDocs as $oDoc) {
  210 + if(count($oDoc->getSymbolicLinks()) > 0){
  211 + $symlinksPresent = true;
  212 + break;
  213 + }
  214 + }
  215 +
  216 + $aCFIds = Folder::getList(array('parent_id = ?', array($iFolderId)), array('ids' => true));
  217 + $aRemainingFolders = kt_array_merge($aRemainingFolders, $aCFIds);
  218 + }
  219 + }
  220 + }
  221 + return $symlinksPresent;
  222 + }
  223 +
  224 +/**
  225 + * checks a folderList for shortcuts and queries the repositories for all folders
  226 + * that are somehow connected to these folders.
  227 + */
  228 + function getLinkingEntities($aFolderList){
  229 + $aSearchFolders = array();
  230 + if(!empty($aFolderList)){
  231 + foreach($aFolderList as $oFolderItem){
  232 + if(Permission::userHasFolderReadPermission($oFolderItem)){
  233 + // If it is a shortcut, we should do some more searching
  234 + if($oFolderItem->isSymbolicLink()){
  235 + $oFolderItem = $oFolderItem->getLinkedFolder();
  236 + $aSearchFolders[] = $oFolderItem->getID();
  237 + }
  238 + }
  239 + }
  240 + }
  241 + $aLinkingFolders = array();
  242 + $aSearchCompletedFolders = array();
  243 + $count = 0;
  244 + while(count($aSearchFolders)>0){
  245 + $count++;
  246 + $oFolder = Folder::get(array_pop($aSearchFolders));
  247 + $sFolderId = $oFolder->getId();
  248 + // Get all the folders within the current folder
  249 + $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR
  250 + parent_folder_ids LIKE '{$sFolderId},%' OR
  251 + parent_folder_ids LIKE '%,{$sFolderId},%' OR
  252 + parent_folder_ids LIKE '%,{$sFolderId}'";
  253 + $aFolderList = $this->oFolder->getList($sWhereClause);
  254 + foreach($aFolderList as $oFolderItem){
  255 + if($oFolderItem->isSymbolicLink()){
  256 + $oFolderItem = $oFolderItem->getLinkedFolder();
  257 + }
  258 + if(Permission::userHasFolderReadPermission($oFolderItem)){
  259 + if($aSearchCompletedFolders[$oFolderItem->getID()] != true){
  260 + $aSearchFolders[] = $oFolderItem->getID();
  261 + $aSearchCompletedFolders[$oFolderItem->getID()] = true;
  262 + }
  263 + }
  264 + }
  265 + if(!isset($aLinkingFolders[$oFolder->getId()])){
  266 + $aLinkingFolders[$oFolder->getId()] = $oFolder;
  267 + }
  268 + }
  269 + return $aLinkingFolders;
  270 + }
  271 +
  272 + // doesn't actually do checks, as they have to be performed per-entity
  273 + function check() {
  274 + // not necessarily coming from a folder...
  275 + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', 1);
  276 + $this->oFolder = Folder::get($iFolderId);
  277 + //$this->oFolder =& $this->oValidator->validateFolder($_REQUEST['fFolderId']);
  278 +
  279 + $aOptions = array(
  280 + 'final' => false,
  281 + 'documentaction' => 'viewDocument',
  282 + 'folderaction' => 'browse',
  283 + );
  284 +
  285 + $this->aBreadcrumbs = array(array('name'=>_kt('Bulk Actions')),
  286 + array('name'=>$this->getDisplayName()));
  287 +
  288 + return true;
  289 + }
  290 +
  291 +
  292 + // check the entire entity list. this needn't be overrided at any point
  293 + function check_entities() {
  294 + $aFailed = array('documents' => array(), 'folders' => array());
  295 + $aSucceeded = array('documents' => array(), 'folders' => array());
  296 +
  297 + if(!$this->oEntityList) {
  298 + return true;
  299 + }
  300 +
  301 + foreach($this->oEntityList->getDocumentIds() as $iId) {
  302 + $oDocument =& Document::get($iId);
  303 +
  304 + if(PEAR::isError($oDocument)) {
  305 + $aFailed['documents'][] = array($iId, _kt('No such document'));
  306 + } else {
  307 + $res = $this->check_entity($oDocument);
  308 +
  309 + // all these checks allow a return from check_entity of:
  310 + // 1. a PEAR error, indicating failure, with the message in the error
  311 + // 2. false, for unknown error
  312 + // 3. true, to pass
  313 +
  314 + if(PEAR::isError($res)) {
  315 + $aFailed['documents'][] = array($oDocument->getName(), $res->getMessage());
  316 + } else if($res === false) {
  317 + $aFailed['documents'][] = array($oDocument->getName(), _kt('Failed (unknown reason)'));
  318 + } else {
  319 + $aSucceeded['documents'][] = $oDocument->getId();
  320 + }
  321 + }
  322 + }
  323 +
  324 + foreach($this->oEntityList->getFolderIds() as $iId) {
  325 + $oFolder =& Folder::get($iId);
  326 +
  327 + if(PEAR::isError($oFolder)) {
  328 + $aFailed['folders'][] = array($iId, _kt('No such folder'));
  329 + } else {
  330 + $res = $this->check_entity($oFolder);
  331 +
  332 + if(PEAR::isError($res)) {
  333 + $aFailed['folders'][] = array($oFolder->getName(), $res->getMessage());
  334 + } else if($res === false) {
  335 + $aFailed['folders'][] = array($oFolder->getName(), _kt('Failed (unknown reason)'));
  336 + } else {
  337 + $aSucceeded['folders'][] = $oFolder->getId();
  338 + }
  339 + }
  340 + }
  341 + $this->oActiveEntityList = new KTEntityList($aSucceeded['documents'], $aSucceeded['folders']);
  342 + $this->aFailed = $aFailed;
  343 +
  344 + return count($aSucceeded['documents']) + count($aSucceeded['folders']);
  345 + }
  346 +
  347 +
  348 + // iterate over all entites to act on them
  349 + function perform_action_on_list() {
  350 + $this->aActionResults = array('folders'=>array(), 'documents'=>array());
  351 + foreach($this->oActiveEntityList->getDocumentIds() as $iId) {
  352 + $oDocument =& Document::get($iId);
  353 + // Store document
  354 + $this->uploadedDocs[] = $oDocument;
  355 + if(!PEAR::isError($oDocument)) {
  356 + $sName = $oDocument->getName();
  357 + } else {
  358 + $sName = _kt('Error fetching document name');
  359 + }
  360 +
  361 + $res = $this->perform_action($oDocument);
  362 +
  363 + //check for shortcut notice
  364 + $notice = null;
  365 + if($oDocument->isSymbolicLink()){
  366 + $notice = _kt("Shortcut");
  367 + }
  368 +
  369 + if(PEAR::isError($res)) {
  370 + $this->aActionResults['documents'][] = array($sName, $res->getMessage(), $notice);
  371 + } else {
  372 + // TODO better way of getting the bulk action type
  373 + if($this->eventAction == null) {
  374 + $this->eventAction = $res;
  375 + }
  376 + $this->aActionResults['documents'][] = array($sName, _kt('Success'), $notice);
  377 + }
  378 + }
  379 +
  380 + // List of ducument objects
  381 + $oFolderObjects = array();
  382 + foreach($this->oActiveEntityList->getFolderIds() as $iId) {
  383 + $oFolder =& Folder::get($iId);
  384 + // Store folder
  385 + $this->uploadedFolders[] = $oFolder;
  386 + if(!PEAR::isError($oFolder)) {
  387 + $sName = $oFolder->getName();
  388 + } else {
  389 + $sName = _kt('Error fetching folder name');
  390 + }
  391 +
  392 + $res = $this->perform_action($oFolder);
  393 +
  394 + //check for shortcut notice
  395 + $notice = null;
  396 + if($oFolder->isSymbolicLink()){
  397 + $notice = _kt("Shortcut");
  398 + }
  399 +
  400 + if(PEAR::isError($res)) {
  401 + $this->aActionResults['folders'][] = array($sName, $res->getMessage(), $notice);
  402 + } else {
  403 + // // TODO better way of getting the bulk action type
  404 + if($this->eventAction == null) {
  405 + $this->eventAction = $res;
  406 + }
  407 + $this->aActionResults['folders'][] = array($sName, _kt('Success'), $notice);
  408 + }
  409 + }
  410 +
  411 + }
  412 +
  413 +
  414 +
  415 + // list persistance
  416 + // fetch existing lists
  417 + function get_lists() {
  418 + $this->oEntityList = KTEntityList::retrieveList(KTUtil::arrayGet($_REQUEST, 'fListCode', null));
  419 + $this->oActiveEntityList = KTEntityList::retrieveList(KTUtil::arrayGet($_REQUEST, 'fActiveListCode', null));
  420 + if(PEAR::isError($this->oActiveEntityList)) {
  421 + $this->oActiveEntityList = null;
  422 + }
  423 + }
  424 +
  425 + // persist
  426 + function store_lists() {
  427 + $this->persistParams(array('fListCode', 'fActiveListCode', 'fFolderId', 'fReturnData', 'fReturnAction'));
  428 + }
  429 +
  430 + /**
  431 + * Get the return url based on the return action and data
  432 + */
  433 + function getReturnUrl()
  434 + {
  435 + $sReturnAction = $_REQUEST['fReturnAction'];
  436 + $sReturnData = $_REQUEST['fReturnData'];
  437 + $sAction = 'main';
  438 + $qs = '';
  439 +
  440 + switch ($sReturnAction){
  441 + case 'browse':
  442 + $sReturnData = (empty($sReturnData)) ? $_REQUEST['fFolderId'] : $sReturnData;
  443 + $sTargetUrl = KTBrowseUtil::getUrlForFolder(Folder::get($sReturnData));
  444 + break;
  445 + case 'simpleSearch':
  446 + $sTargetUrl = KTBrowseUtil::getSimpleSearchBaseUrl();
  447 + $extra = 'fSearchableText='.$sReturnData;
  448 + break;
  449 + case 'booleanSearch':
  450 + $sTargetUrl = KTBrowseUtil::getBooleanSearchBaseUrl();
  451 + $sAction = 'performSearch';
  452 + $extra = 'boolean_search_id='.$sReturnData;
  453 + break;
  454 + case 'search2':
  455 + $sTargetUrl = KTBrowseUtil::getSearchResultURL();
  456 + $sAction = 'searchResults';
  457 + break;
  458 + default:
  459 + $sTargetUrl = $sReturnAction;
  460 + $sAction = '';
  461 + }
  462 +
  463 + $qs = (!empty($sAction))? 'action='.$sAction : '';
  464 + $qs .= (!empty($extra))? '&'.$extra : '';
  465 + $sTargetUrl = KTUtil::addQueryString($sTargetUrl, $qs);
  466 +
  467 + return $sTargetUrl;
  468 + }
  469 +
  470 + // forms
  471 + // form to list the entites after checking each one
  472 + function form_listing() {
  473 + $sListCode = $this->oEntityList->getCode();
  474 + $sActiveListCode = $this->oActiveEntityList->getCode();
  475 +
  476 + $sTargetUrl = $this->getReturnUrl();
  477 +
  478 + $oForm = new KTForm;
  479 + $oForm->setOptions(array(
  480 + 'identifier' => 'ktcore.actions.bulk.listing.form',
  481 + 'submit_label' => _kt('Continue'),
  482 + 'targeturl' => $this->getURL(),
  483 + 'action' => 'collectinfo',
  484 + 'fail_action' => 'main',
  485 + 'cancel_url' => $sTargetUrl,
  486 + 'noframe' => true,
  487 + 'extraargs' => array('fListCode' => $sListCode,
  488 + 'fActiveListCode' => $sActiveListCode,
  489 + 'fFolderId' => $this->oFolder->getId(),
  490 + 'fReturnAction' => KTUtil::arrayGet($_REQUEST, 'fReturnAction'),
  491 + 'fReturnData' => KTUtil::arrayGet($_REQUEST, 'fReturnData'),
  492 + ),
  493 + 'context' => $this,
  494 + ));
  495 + return $oForm;
  496 + }
  497 +
  498 + // form to show on action completion, and list results
  499 + function form_complete() {
  500 + $sReturnAction = KTUtil::arrayGet($_REQUEST, 'fReturnAction');
  501 + $sReturnData = KTUtil::arrayGet($_REQUEST, 'fReturnData');
  502 + $sAction = 'main';
  503 +
  504 + switch ($sReturnAction){
  505 + case 'browse':
  506 + $sReturnData = (empty($sReturnData)) ? $_REQUEST['fFolderId'] : $sReturnData;
  507 + $sTargetUrl = KTBrowseUtil::getUrlForFolder(Folder::get($sReturnData));
  508 + break;
  509 + case 'simpleSearch': // do we use this?
  510 + $sTargetUrl = KTBrowseUtil::getSimpleSearchBaseUrl();
  511 + $extraargs = array('fSearchableText'=>$sReturnData);
  512 + break;
  513 + case 'booleanSearch': // do we use this?
  514 + $sTargetUrl = KTBrowseUtil::getBooleanSearchBaseUrl();
  515 + $sAction = 'performSearch';
  516 + $extraargs = array('boolean_search_id'=>$sReturnData);
  517 + break;
  518 + case 'search2':
  519 + $sTargetUrl = KTBrowseUtil::getSearchResultURL();
  520 + $sAction = 'refresh';
  521 + break;
  522 + default:
  523 + $sTargetUrl = $sReturnAction;
  524 + $sAction = '';
  525 + }
  526 +
  527 + $oForm = new KTForm;
  528 + $oForm->setOptions(array(
  529 + 'identifier' => 'ktcore.actions.bulk.complete.form',
  530 + 'submit_label' => _kt('Return'),
  531 + 'targeturl' => $sTargetUrl,
  532 + 'context' => $this,
  533 + 'action' => $sAction,
  534 + 'extraargs' => $extraargs,
  535 + 'noframe' => true,
  536 + ));
  537 + return $oForm;
  538 + }
  539 +
  540 +
  541 + // main entry point - checks the entity list and displays lists
  542 + function do_main() {
  543 + // get entities (using the checkboxes atm)
  544 + $aFolders = KTUtil::arrayGet($_REQUEST, 'selection_f' , array());
  545 + $aDocuments = KTUtil::arrayGet($_REQUEST, 'selection_d' , array());
  546 + $this->oEntityList = new KTEntityList($aDocuments, $aFolders);
  547 +
  548 + // gives us $this->aFailed
  549 + $iActiveCount = $this->check_entities();
  550 +
  551 + $oTemplating =& KTTemplating::getSingleton();
  552 + $oTemplate = $oTemplating->loadTemplate('ktcore/bulk_action_listing');
  553 +
  554 + $this->store_lists();
  555 +
  556 + return $oTemplate->render(array('context' => $this,
  557 + 'form' => $this->form_listing(),
  558 + 'failed' => $this->aFailed,
  559 + 'active' => $this->oActiveEntityList,
  560 + 'activecount' => $iActiveCount,
  561 + 'failedform' => $this->form_complete(),
  562 + 'folders' => $this->_getNames($this->oActiveEntityList->getFolderIds(), 'Folder'),
  563 + 'documents' => $this->_getNames($this->oActiveEntityList->getDocumentIds(), 'Document')));
  564 +
  565 + }
  566 +
  567 + // override to add a screen to get a reason, or whatever
  568 + // remember to pass to perform action next, and call the super's method
  569 + function do_collectinfo() {
  570 + $this->store_lists();
  571 + return $this->do_performaction();
  572 + }
  573 +
  574 + // perform the action itself, and list results (completion action)
  575 + function do_performaction() {
  576 + $this->get_lists();
  577 + $this->aPersistParams = array();
  578 + $targetFolderId = $_REQUEST['fFolderId'];
  579 + $targetFolder =& Folder::get($targetFolderId);
  580 + $this->perform_action_on_list();
  581 + // Parse affected documents and folders
  582 + if(count($this->uploadedDocs) > 0)
  583 + $this->do_notification($this->uploadedDocs, $this->eventAction, $targetFolder);
  584 + elseif(count($this->uploadedFolders) > 0)
  585 + $this->do_notification($this->uploadedFolders, $this->eventAction, $targetFolder);
  586 + // Action specific Emails
  587 + // Check if its a move action
  588 + if($this->eventAction == "MovedDocument") {
  589 + // Notify the folder from which the action happened
  590 + $originalFolderId = $_REQUEST['fOriginalFolderId'];
  591 + $originalFolder =& Folder::get($originalFolderId);
  592 + if(count($this->uploadedDocs) > 0)
  593 + $this->do_notification($this->uploadedDocs, $this->eventAction, $originalFolder);
  594 + elseif(count($this->uploadedFolders) > 0)
  595 + $this->do_notification($this->uploadedFolders, $this->eventAction, $originalFolder);
  596 + }
  597 +
  598 + $oTemplating =& KTTemplating::getSingleton();
  599 + $oTemplate = $oTemplating->loadTemplate('ktcore/bulk_action_complete');
  600 +
  601 + return $oTemplate->render(array('context' => $this,
  602 + 'list' => $this->aActionResults,
  603 + 'form' => $this->form_complete()));
  604 + }
  605 +
  606 + // Jarrett Jordaan: Deal with bulk actions
  607 + function do_notification($objects, $eventAction, $targetFolder) {
  608 + echo $eventAction." on folder ".$targetFolder->getId()."<br/>";
  609 + // Make sure there were documents/folders affected
  610 + if ($targetFolder && count($objects) > 0 && $eventAction != '') {
  611 + $oSubscriptionEvent = new SubscriptionEvent();
  612 + $oSubscriptionEvent->notifyBulkDocumentAction($objects, $eventAction, $targetFolder);
  613 + }
  614 + }
  615 +
  616 +
  617 +
  618 +
  619 + // main overrides
  620 +
  621 + // override to do the actual action, on an individual entity
  622 + function perform_action($oEntity) {
  623 + return PEAR::raiseError(_kt('Action component not implemented'));
  624 + }
  625 +
  626 + // check an individual entity - this should be overrided with additional
  627 + // checks required for the specific action, but should always call its
  628 + // parent implementation
  629 + function check_entity($oEntity) {
  630 + $oPermission =& KTPermission::getByName($this->_sPermission);
  631 + if(PEAR::isError($oPermission)) {
  632 + return true;
  633 + }
  634 +
  635 + // basic document checks
  636 +
  637 + // TODO: check if this is appropriate
  638 + // should probably store the 'equivalent' action (ie. document.delete)
  639 + // and check that, rather than add a new list of actions to the workflow
  640 + // section
  641 + if(is_a($oEntity, 'Document')) {
  642 + if(!KTWorkflowUtil::actionEnabledForDocument($oEntity, $this->sName)) {
  643 + return PEAR::raiseError(_kt('Action is disabled by workflow'));
  644 + }
  645 + $status = $oEntity->getStatusID();
  646 + if($status==DELETED||$status==ARCHIVED) {
  647 + return PEAR::raiseError(_kt('Document is archived or deleted'));
  648 + }
  649 + }
  650 +
  651 + // admin check
  652 + if($this->bAllowInAdminMode) {
  653 + if(KTBrowseUtil::inAdminMode($this->oUser, null)) {
  654 + return true;
  655 + }
  656 + }
  657 +
  658 + if(!KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $oEntity)) {
  659 + return PEAR::raiseError(_kt('You do not have the required permissions'));
  660 + }
  661 +
  662 + return true;
  663 + }
  664 +
  665 +
  666 +}
  667 +
  668 +class KTBulkDocumentAction extends KTBulkAction {
  669 + function check_entity($oEntity) {
  670 + if(!is_a($oEntity, 'Document')) {
  671 + return false;
  672 + }
  673 + return parent::check_entity($oEntity);
  674 + }
  675 +}
  676 +
  677 +class KTBulkFolderAction extends KTBulkAction {
  678 + function check_entity($oEntity) {
  679 + if(!is_a($oEntity, 'Folder')) {
  680 + return false;
  681 + }
  682 + return parent::check_entity($oEntity);
  683 + }
  684 +}
  685 +
  686 +
  687 +
  688 +// util class for bulk actions
  689 +
  690 +class KTBulkActionUtil {
  691 + function getBulkActionInfo($slot = 'bulkaction') {
  692 + $oRegistry =& KTActionRegistry::getSingleton();
  693 + return $oRegistry->getActions($slot);
  694 + }
  695 +
  696 + function getAllBulkActions($slot = 'bulkaction') {
  697 + $aObjects = array();
  698 +
  699 + foreach (KTBulkActionUtil::getBulkActionInfo($slot) as $aAction) {
  700 + list($sClassName, $sPath, $sName, $sPlugin) = $aAction;
  701 + $oRegistry =& KTPluginRegistry::getSingleton();
  702 + $oPlugin =& $oRegistry->getPlugin($sPlugin);
  703 + if (!empty($sPath)) {
  704 + require_once($sPath);
  705 + }
  706 + $aObjects[] = new $sClassName(null, null, $oPlugin);
  707 + }
  708 + return $aObjects;
  709 + }
  710 +
  711 + function getBulkActionsByNames($aNames, $slot = 'bulkaction', $oUser = null) {
  712 + $aObjects = array();
  713 + foreach (KTBulkActionUtil::getBulkActionInfo($slot) as $aAction) {
  714 + list($sClassName, $sPath, $sName, $sPlugin) = $aAction;
  715 + $oRegistry =& KTPluginRegistry::getSingleton();
  716 + $oPlugin =& $oRegistry->getPlugin($sPlugin);
  717 + if (!in_array($sName, $aNames)) {
  718 + continue;
  719 + }
  720 + if (!empty($sPath)) {
  721 + require_once($sPath);
  722 + }
  723 + $aObjects[] = new $sClassName(null, $oUser, $oPlugin);
  724 + }
  725 + return $aObjects;
  726 + }
  727 +}
  728 +
  729 +?>
lib/database/schema.inc.php
@@ -1012,7 +1012,7 @@ class KTSchemaUtil @@ -1012,7 +1012,7 @@ class KTSchemaUtil
1012 1012
1013 if (!$result) 1013 if (!$result)
1014 { 1014 {
1015 - print "..."; 1015 + //print "...";
1016 } 1016 }
1017 1017
1018 return $result; 1018 return $result;
lib/documentmanagement/documentutil.inc.php
@@ -45,8 +45,6 @@ require_once(KT_LIB_DIR . &#39;/documentmanagement/DocumentFieldLink.inc&#39;); @@ -45,8 +45,6 @@ require_once(KT_LIB_DIR . &#39;/documentmanagement/DocumentFieldLink.inc&#39;);
45 require_once(KT_LIB_DIR . '/documentmanagement/DocumentTransaction.inc'); 45 require_once(KT_LIB_DIR . '/documentmanagement/DocumentTransaction.inc');
46 require_once(KT_LIB_DIR . '/documentmanagement/Document.inc'); 46 require_once(KT_LIB_DIR . '/documentmanagement/Document.inc');
47 47
48 -require_once(KT_LIB_DIR . '/storage/storagemanager.inc.php');  
49 -  
50 // NEW PATHS 48 // NEW PATHS
51 require_once(KT_LIB_DIR . '/storage/storagemanager.inc.php'); 49 require_once(KT_LIB_DIR . '/storage/storagemanager.inc.php');
52 require_once(KT_LIB_DIR . '/filelike/filelikeutil.inc.php'); 50 require_once(KT_LIB_DIR . '/filelike/filelikeutil.inc.php');
@@ -62,7 +60,7 @@ require_once(KT_LIB_DIR . &#39;/browse/browseutil.inc.php&#39;); @@ -62,7 +60,7 @@ require_once(KT_LIB_DIR . &#39;/browse/browseutil.inc.php&#39;);
62 require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php'); 60 require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php');
63 61
64 class KTDocumentUtil { 62 class KTDocumentUtil {
65 - function checkin($oDocument, $sFilename, $sCheckInComment, $oUser, $aOptions = false) { 63 + function checkin($oDocument, $sFilename, $sCheckInComment, $oUser, $aOptions = false, $bulk_action = false) {
66 $oStorage =& KTStorageManagerUtil::getSingleton(); 64 $oStorage =& KTStorageManagerUtil::getSingleton();
67 65
68 $iFileSize = filesize($sFilename); 66 $iFileSize = filesize($sFilename);
@@ -149,16 +147,17 @@ class KTDocumentUtil { @@ -149,16 +147,17 @@ class KTDocumentUtil {
149 } 147 }
150 148
151 Indexer::index($oDocument); 149 Indexer::index($oDocument);
152 -  
153 - // fire subscription alerts for the checked in document  
154 - $oSubscriptionEvent = new SubscriptionEvent();  
155 - $oFolder = Folder::get($oDocument->getFolderID());  
156 - $oSubscriptionEvent->CheckinDocument($oDocument, $oFolder); 150 + if(!$bulk_action) {
  151 + // fire subscription alerts for the checked in document
  152 + $oSubscriptionEvent = new SubscriptionEvent();
  153 + $oFolder = Folder::get($oDocument->getFolderID());
  154 + $oSubscriptionEvent->CheckinDocument($oDocument, $oFolder);
  155 + }
157 156
158 return true; 157 return true;
159 } 158 }
160 159
161 - function checkout($oDocument, $sCheckoutComment, $oUser) { 160 + function checkout($oDocument, $sCheckoutComment, $oUser, $bulk_action = false) {
162 //automatically check out the linked document if this is a shortcut 161 //automatically check out the linked document if this is a shortcut
163 if($oDocument->isSymbolicLink()){ 162 if($oDocument->isSymbolicLink()){
164 $oDocument->switchToLinkedCore(); 163 $oDocument->switchToLinkedCore();
@@ -191,7 +190,7 @@ class KTDocumentUtil { @@ -191,7 +190,7 @@ class KTDocumentUtil {
191 'document' => $oDocument, 190 'document' => $oDocument,
192 ); 191 );
193 $oTrigger->setInfo($aInfo); 192 $oTrigger->setInfo($aInfo);
194 - $ret = $oTrigger->postValidate(); 193 + $ret = $oTrigger->postValidate(true);
195 if (PEAR::isError($ret)) { 194 if (PEAR::isError($ret)) {
196 return $ret; 195 return $ret;
197 } 196 }
@@ -200,15 +199,17 @@ class KTDocumentUtil { @@ -200,15 +199,17 @@ class KTDocumentUtil {
200 $oDocumentTransaction = new DocumentTransaction($oDocument, $sCheckoutComment, 'ktcore.transactions.check_out'); 199 $oDocumentTransaction = new DocumentTransaction($oDocument, $sCheckoutComment, 'ktcore.transactions.check_out');
201 $oDocumentTransaction->create(); 200 $oDocumentTransaction->create();
202 201
203 - // fire subscription alerts for the downloaded document  
204 - $oSubscriptionEvent = new SubscriptionEvent();  
205 - $oFolder = Folder::get($oDocument->getFolderID());  
206 - $oSubscriptionEvent->CheckOutDocument($oDocument, $oFolder); 202 + if(!$bulk_action) {
  203 + // fire subscription alerts for the downloaded document
  204 + $oSubscriptionEvent = new SubscriptionEvent();
  205 + $oFolder = Folder::get($oDocument->getFolderID());
  206 + $oSubscriptionEvent->CheckOutDocument($oDocument, $oFolder);
  207 + }
207 208
208 return true; 209 return true;
209 } 210 }
210 211
211 - function archive($oDocument, $sReason) { 212 + function archive($oDocument, $sReason, $bulk_action = false) {
212 213
213 if($oDocument->isSymbolicLink()){ 214 if($oDocument->isSymbolicLink()){
214 return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document.")); 215 return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document."));
@@ -256,17 +257,18 @@ class KTDocumentUtil { @@ -256,17 +257,18 @@ class KTDocumentUtil {
256 'document' => $oDocument, 257 'document' => $oDocument,
257 ); 258 );
258 $oTrigger->setInfo($aInfo); 259 $oTrigger->setInfo($aInfo);
259 - $ret = $oTrigger->postValidate(); 260 + $ret = $oTrigger->postValidate(true);
260 if (PEAR::isError($ret)) { 261 if (PEAR::isError($ret)) {
261 $oDocument->delete(); 262 $oDocument->delete();
262 return $ret; 263 return $ret;
263 } 264 }
264 } 265 }
265 -  
266 - // fire subscription alerts for the archived document  
267 - $oSubscriptionEvent = new SubscriptionEvent();  
268 - $oFolder = Folder::get($oDocument->getFolderID());  
269 - $oSubscriptionEvent->ArchivedDocument($oDocument, $oFolder); 266 + if(!$bulk_action) {
  267 + // fire subscription alerts for the archived document
  268 + $oSubscriptionEvent = new SubscriptionEvent();
  269 + $oFolder = Folder::get($oDocument->getFolderID());
  270 + $oSubscriptionEvent->ArchivedDocument($oDocument, $oFolder);
  271 + }
270 272
271 return true; 273 return true;
272 } 274 }
@@ -698,11 +700,21 @@ $sourceDocument-&gt;getName(), @@ -698,11 +700,21 @@ $sourceDocument-&gt;getName(),
698 } 700 }
699 } 701 }
700 // }}} 702 // }}}
701 - 703 + /*
  704 + * Document Add
  705 + * Author : Jarrett Jordaan
  706 + * Modified : 28/04/09
  707 + *
  708 + * @params : KTFolderUtil $oFolder
  709 + * string $sFilename
  710 + * KTUser $oUser
  711 + * array $aOptions
  712 + * boolean $bulk_action
  713 + */
702 // {{{ add 714 // {{{ add
703 - function &add($oFolder, $sFilename, $oUser, $aOptions) { 715 + function &add($oFolder, $sFilename, $oUser, $aOptions, $bulk_action = false) {
704 $GLOBALS['_IN_ADD'] = true; 716 $GLOBALS['_IN_ADD'] = true;
705 - $ret = KTDocumentUtil::_in_add($oFolder, $sFilename, $oUser, $aOptions); 717 + $ret = KTDocumentUtil::_in_add($oFolder, $sFilename, $oUser, $aOptions, $bulk_action);
706 unset($GLOBALS['_IN_ADD']); 718 unset($GLOBALS['_IN_ADD']);
707 return $ret; 719 return $ret;
708 } 720 }
@@ -731,8 +743,19 @@ $sourceDocument-&gt;getName(), @@ -731,8 +743,19 @@ $sourceDocument-&gt;getName(),
731 return $sFilename; 743 return $sFilename;
732 } 744 }
733 745
  746 + /*
  747 + * Document Add
  748 + * Author : Jarrett Jordaan
  749 + * Modified : 28/04/09
  750 + *
  751 + * @params : KTFolderUtil $oFolder
  752 + * string $sFilename
  753 + * KTUser $oUser
  754 + * array $aOptions
  755 + * boolean $bulk_action
  756 + */
734 // {{{ _in_add 757 // {{{ _in_add
735 - function &_in_add($oFolder, $sFilename, $oUser, $aOptions) { 758 + function &_in_add($oFolder, $sFilename, $oUser, $aOptions, $bulk_action = false) {
736 $aOrigOptions = $aOptions; 759 $aOrigOptions = $aOptions;
737 760
738 $sFilename = KTDocumentUtil::getUniqueFilename($oFolder, $sFilename); 761 $sFilename = KTDocumentUtil::getUniqueFilename($oFolder, $sFilename);
@@ -785,9 +808,9 @@ $sourceDocument-&gt;getName(), @@ -785,9 +808,9 @@ $sourceDocument-&gt;getName(),
785 } 808 }
786 809
787 $oUploadChannel->sendMessage(new KTUploadGenericMessage(_kt('Sending subscriptions'))); 810 $oUploadChannel->sendMessage(new KTUploadGenericMessage(_kt('Sending subscriptions')));
788 - // fire subscription alerts for the checked in document  
789 // TODO : better way of checking if its a bulk upload 811 // TODO : better way of checking if its a bulk upload
790 - if($_SERVER['PATH_INFO'] != "ktcore.actions.folder.bulkUpload") { 812 + if(!$bulk_action) {
  813 + // fire subscription alerts for the checked in document
791 $oSubscriptionEvent = new SubscriptionEvent(); 814 $oSubscriptionEvent = new SubscriptionEvent();
792 $oFolder = Folder::get($oDocument->getFolderID()); 815 $oFolder = Folder::get($oDocument->getFolderID());
793 $oSubscriptionEvent->AddDocument($oDocument, $oFolder); 816 $oSubscriptionEvent->AddDocument($oDocument, $oFolder);
@@ -939,8 +962,18 @@ $sourceDocument-&gt;getName(), @@ -939,8 +962,18 @@ $sourceDocument-&gt;getName(),
939 } 962 }
940 // }}} 963 // }}}
941 964
  965 + /*
  966 + * Document Delete
  967 + * Author : Jarrett Jordaan
  968 + * Modified : 28/04/09
  969 + *
  970 + * @params : KTDocumentUtil $oDocument
  971 + * string $sReason
  972 + * int $iDestFolderId
  973 + * boolean $bulk_action
  974 + */
942 // {{{ delete 975 // {{{ delete
943 - function delete($oDocument, $sReason, $iDestFolderId = null) { 976 + function delete($oDocument, $sReason, $iDestFolderId = null, $bulk_action = false) {
944 // use the deleteSymbolicLink function is this is a symlink 977 // use the deleteSymbolicLink function is this is a symlink
945 if ($oDocument->isSymbolicLink()) 978 if ($oDocument->isSymbolicLink())
946 { 979 {
@@ -1044,12 +1077,12 @@ $sourceDocument-&gt;getName(), @@ -1044,12 +1077,12 @@ $sourceDocument-&gt;getName(),
1044 $oDocument->setFolderID(1); 1077 $oDocument->setFolderID(1);
1045 1078
1046 DBUtil::commit(); 1079 DBUtil::commit();
1047 -  
1048 -  
1049 - // we weren't doing notifications on this one  
1050 - $oSubscriptionEvent = new SubscriptionEvent();  
1051 - $oSubscriptionEvent->RemoveDocument($oDocument, $oOrigFolder);  
1052 - 1080 + // TODO : better way of checking if its a bulk delete
  1081 + if(!$bulk_action) {
  1082 + // we weren't doing notifications on this one
  1083 + $oSubscriptionEvent = new SubscriptionEvent();
  1084 + $oSubscriptionEvent->RemoveDocument($oDocument, $oOrigFolder);
  1085 + }
1053 1086
1054 // document is now deleted: triggers are best-effort. 1087 // document is now deleted: triggers are best-effort.
1055 1088
@@ -1062,7 +1095,7 @@ $sourceDocument-&gt;getName(), @@ -1062,7 +1095,7 @@ $sourceDocument-&gt;getName(),
1062 'document' => $oDocument, 1095 'document' => $oDocument,
1063 ); 1096 );
1064 $oTrigger->setInfo($aInfo); 1097 $oTrigger->setInfo($aInfo);
1065 - $ret = $oTrigger->postValidate(); 1098 + $ret = $oTrigger->postValidate(true);
1066 if (PEAR::isError($ret)) { 1099 if (PEAR::isError($ret)) {
1067 $oDocument->delete(); // FIXME nbm: review that on-fail => delete is correct ?! 1100 $oDocument->delete(); // FIXME nbm: review that on-fail => delete is correct ?!
1068 return $ret; 1101 return $ret;
@@ -1135,7 +1168,7 @@ $sourceDocument-&gt;getName(), @@ -1135,7 +1168,7 @@ $sourceDocument-&gt;getName(),
1135 return true; 1168 return true;
1136 } 1169 }
1137 1170
1138 - function copy($oDocument, $oDestinationFolder, $sReason = null, $sDestinationDocName = null) { 1171 + function copy($oDocument, $oDestinationFolder, $sReason = null, $sDestinationDocName = null, $bulk_action = false) {
1139 // 1. generate a new triad of content, metadata and core objects. 1172 // 1. generate a new triad of content, metadata and core objects.
1140 // 2. update the storage path. 1173 // 2. update the storage path.
1141 //print '--------------------------------- BEFORE'; 1174 //print '--------------------------------- BEFORE';
@@ -1284,11 +1317,12 @@ $sourceDocument-&gt;getName(), @@ -1284,11 +1317,12 @@ $sourceDocument-&gt;getName(),
1284 return $ret; 1317 return $ret;
1285 } 1318 }
1286 } 1319 }
1287 -  
1288 - // fire subscription alerts for the copied document  
1289 - $oSubscriptionEvent = new SubscriptionEvent();  
1290 - $oFolder = Folder::get($oDocument->getFolderID());  
1291 - $oSubscriptionEvent->MoveDocument($oDocument, $oDestinationFolder, $oSrcFolder, 'CopiedDocument'); 1320 + if(!$bulk_action) {
  1321 + // fire subscription alerts for the copied document
  1322 + $oSubscriptionEvent = new SubscriptionEvent();
  1323 + $oFolder = Folder::get($oDocument->getFolderID());
  1324 + $oSubscriptionEvent->MoveDocument($oDocument, $oDestinationFolder, $oSrcFolder, 'CopiedDocument');
  1325 + }
1292 1326
1293 return $oNewDocument; 1327 return $oNewDocument;
1294 } 1328 }
@@ -1369,7 +1403,18 @@ $sourceDocument-&gt;getName(), @@ -1369,7 +1403,18 @@ $sourceDocument-&gt;getName(),
1369 return true; 1403 return true;
1370 } 1404 }
1371 1405
1372 - function move($oDocument, $oToFolder, $oUser = null, $sReason = null) { 1406 + /*
  1407 + * Document Move
  1408 + * Author : Jarrett Jordaan
  1409 + * Modified : 28/04/09
  1410 + *
  1411 + * @params : KTDocumentUtil $oDocument
  1412 + * KTFolderUtil $oToFolder
  1413 + * KTUser $oUser
  1414 + * string $sReason
  1415 + * boolean $bulk_action
  1416 + */
  1417 + function move($oDocument, $oToFolder, $oUser = null, $sReason = null, $bulk_action = false) {
1373 //make sure we move the symlink, and the document it's linking to 1418 //make sure we move the symlink, and the document it's linking to
1374 if($oDocument->isSymbolicLink()){ 1419 if($oDocument->isSymbolicLink()){
1375 $oDocument->switchToRealCore(); 1420 $oDocument->switchToRealCore();
@@ -1425,9 +1470,9 @@ $sourceDocument-&gt;getName(), @@ -1425,9 +1470,9 @@ $sourceDocument-&gt;getName(),
1425 $oDocumentTransaction = new DocumentTransaction($oDocument, $sMoveMessage, 'ktcore.transactions.move'); 1470 $oDocumentTransaction = new DocumentTransaction($oDocument, $sMoveMessage, 'ktcore.transactions.move');
1426 $oDocumentTransaction->create(); 1471 $oDocumentTransaction->create();
1427 1472
1428 -  
1429 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); 1473 $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
1430 $aTriggers = $oKTTriggerRegistry->getTriggers('moveDocument', 'postValidate'); 1474 $aTriggers = $oKTTriggerRegistry->getTriggers('moveDocument', 'postValidate');
  1475 +
1431 foreach ($aTriggers as $aTrigger) { 1476 foreach ($aTriggers as $aTrigger) {
1432 $sTrigger = $aTrigger[0]; 1477 $sTrigger = $aTrigger[0];
1433 $oTrigger = new $sTrigger; 1478 $oTrigger = new $sTrigger;
@@ -1437,15 +1482,17 @@ $sourceDocument-&gt;getName(), @@ -1437,15 +1482,17 @@ $sourceDocument-&gt;getName(),
1437 'new_folder' => $oFolder, 1482 'new_folder' => $oFolder,
1438 ); 1483 );
1439 $oTrigger->setInfo($aInfo); 1484 $oTrigger->setInfo($aInfo);
1440 - $ret = $oTrigger->postValidate(); 1485 + $ret = $oTrigger->postValidate(true);
1441 if (PEAR::isError($ret)) { 1486 if (PEAR::isError($ret)) {
1442 return $ret; 1487 return $ret;
1443 } 1488 }
1444 } 1489 }
1445 1490
1446 - // fire subscription alerts for the moved document  
1447 - $oSubscriptionEvent = new SubscriptionEvent();  
1448 - $oSubscriptionEvent->MoveDocument($oDocument, $oFolder, $oOriginalFolder); 1491 + if(!$bulk_action) {
  1492 + // fire subscription alerts for the moved document
  1493 + $oSubscriptionEvent = new SubscriptionEvent();
  1494 + $oSubscriptionEvent->MoveDocument($oDocument, $oFolder, $oOriginalFolder);
  1495 + }
1449 1496
1450 return KTPermissionUtil::updatePermissionLookup($oDocument); 1497 return KTPermissionUtil::updatePermissionLookup($oDocument);
1451 } 1498 }
lib/foldermanagement/compressionArchiveUtil.inc.php
@@ -614,6 +614,7 @@ class DownloadQueue @@ -614,6 +614,7 @@ class DownloadQueue
614 // Get all the folders within the current folder 614 // Get all the folders within the current folder
615 $sWhereClause = "parent_folder_ids like '%,{$folderId}' 615 $sWhereClause = "parent_folder_ids like '%,{$folderId}'
616 OR parent_folder_ids like '%,{$folderId},%' 616 OR parent_folder_ids like '%,{$folderId},%'
  617 + OR parent_folder_ids like '{$folderId},%'
617 OR parent_id = {$folderId}"; 618 OR parent_id = {$folderId}";
618 619
619 $aFolderList = $oFolder->getList($sWhereClause); 620 $aFolderList = $oFolder->getList($sWhereClause);
lib/foldermanagement/folderutil.inc.php
@@ -75,7 +75,17 @@ class KTFolderUtil { @@ -75,7 +75,17 @@ class KTFolderUtil {
75 return $oFolder; 75 return $oFolder;
76 } 76 }
77 77
78 - function add($oParentFolder, $sFolderName, $oUser) { 78 + /*
  79 + * Folder Add
  80 + * Author : Jarrett Jordaan
  81 + * Modified : 28/04/09
  82 + *
  83 + * @params : KTDocumentUtil $oParentFolder
  84 + * string $sFolderName
  85 + * KTUser $oUser
  86 + * boolean $bulk_action
  87 + */
  88 + function add($oParentFolder, $sFolderName, $oUser, $bulk_action = false) {
79 89
80 90
81 $folderid=$oParentFolder->getId(); 91 $folderid=$oParentFolder->getId();
@@ -97,15 +107,16 @@ class KTFolderUtil { @@ -97,15 +107,16 @@ class KTFolderUtil {
97 'userid' => $oUser->getId(), 107 'userid' => $oUser->getId(),
98 'ip' => Session::getClientIP(), 108 'ip' => Session::getClientIP(),
99 )); 109 ));
100 -  
101 - // fire subscription alerts for the new folder  
102 - $oSubscriptionEvent = new SubscriptionEvent();  
103 - $oSubscriptionEvent->AddFolder($oFolder, $oParentFolder); 110 + if(!$bulk_action) {
  111 + // fire subscription alerts for the new folder
  112 + $oSubscriptionEvent = new SubscriptionEvent();
  113 + $oSubscriptionEvent->AddFolder($oFolder, $oParentFolder);
  114 + }
104 115
105 return $oFolder; 116 return $oFolder;
106 } 117 }
107 118
108 - function move($oFolder, $oNewParentFolder, $oUser, $sReason=null) { 119 + function move($oFolder, $oNewParentFolder, $oUser, $sReason=null, $bulk_action = false) {
109 if ($oFolder->getId() == 1) 120 if ($oFolder->getId() == 1)
110 { 121 {
111 return PEAR::raiseError(_kt('Cannot move root folder!')); 122 return PEAR::raiseError(_kt('Cannot move root folder!'));
@@ -312,7 +323,7 @@ class KTFolderUtil { @@ -312,7 +323,7 @@ class KTFolderUtil {
312 * - step-by-step delete. 323 * - step-by-step delete.
313 */ 324 */
314 325
315 - function delete($oStartFolder, $oUser, $sReason, $aOptions = null) { 326 + function delete($oStartFolder, $oUser, $sReason, $aOptions = null, $bulk_action = false) {
316 require_once(KT_LIB_DIR . '/unitmanagement/Unit.inc'); 327 require_once(KT_LIB_DIR . '/unitmanagement/Unit.inc');
317 328
318 $oPerm = KTPermission::getByName('ktcore.permissions.delete'); 329 $oPerm = KTPermission::getByName('ktcore.permissions.delete');
lib/import/bulkimport.inc.php
@@ -40,17 +40,22 @@ @@ -40,17 +40,22 @@
40 require_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php'); 40 require_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
41 require_once(KT_LIB_DIR . '/documentmanagement/documentutil.inc.php'); 41 require_once(KT_LIB_DIR . '/documentmanagement/documentutil.inc.php');
42 require_once(KT_LIB_DIR . '/filelike/filelikeutil.inc.php'); 42 require_once(KT_LIB_DIR . '/filelike/filelikeutil.inc.php');
43 -// // Jarrett Jordaan: Deal with bulk uploads 43 +// // Jarrett Jordaan: Deal with bulk action
44 require_once(KT_LIB_DIR . '/subscriptions/subscriptions.inc.php'); 44 require_once(KT_LIB_DIR . '/subscriptions/subscriptions.inc.php');
45 45
46 class KTBulkImportManager { 46 class KTBulkImportManager {
47 var $oStorage; 47 var $oStorage;
  48 + // Bulk Action Notification
  49 + var $uploadedDocs;
  50 + var $uploadedFolders;
48 51
49 function KTBulkImportManager($oFolder, $oStorage, $oUser, $aOptions = null) { 52 function KTBulkImportManager($oFolder, $oStorage, $oUser, $aOptions = null) {
50 $this->oFolder =& $oFolder; 53 $this->oFolder =& $oFolder;
51 $this->oStorage =& $oStorage; 54 $this->oStorage =& $oStorage;
52 $this->oUser =& $oUser; 55 $this->oUser =& $oUser;
53 $this->aOptions =& $aOptions; 56 $this->aOptions =& $aOptions;
  57 + $this->uploadedDocs = array();
  58 + $this->uploadedFolders = array();
54 if (is_null($aOptions)) { 59 if (is_null($aOptions)) {
55 $aOptions = array(); 60 $aOptions = array();
56 } 61 }
@@ -69,13 +74,21 @@ class KTBulkImportManager { @@ -69,13 +74,21 @@ class KTBulkImportManager {
69 $this->oStorage->cleanup(); 74 $this->oStorage->cleanup();
70 return $res; 75 return $res;
71 } 76 }
  77 + if(count($this->uploadedDocs) > 0) {
  78 + // Bulk action subscription notification
  79 + $oSubscriptionEvent = new SubscriptionEvent();
  80 + $oSubscriptionEvent->notifyBulkDocumentAction($this->uploadedDocs, 'AddDocument', $this->oFolder);
  81 + } elseif(count($this->uploadedFolders) > 0) {
  82 + $oSubscriptionEvent = new SubscriptionEvent();
  83 + $oSubscriptionEvent->notifyBulkDocumentAction($this->uploadedFolders, 'AddFolder', $this->oFolder);
  84 + }
72 $this->oStorage->cleanup(); 85 $this->oStorage->cleanup();
  86 +
73 return; 87 return;
74 } 88 }
75 89
76 function _importfolder($oFolder, $sPath) { 90 function _importfolder($oFolder, $sPath) {
77 $oPermission = KTPermission::getByName('ktcore.permissions.addFolder'); 91 $oPermission = KTPermission::getByName('ktcore.permissions.addFolder');
78 -  
79 $aDocPaths = $this->oStorage->listDocuments($sPath); 92 $aDocPaths = $this->oStorage->listDocuments($sPath);
80 if (PEAR::isError($aDocPaths)) { 93 if (PEAR::isError($aDocPaths)) {
81 return $aDocPaths; 94 return $aDocPaths;
@@ -86,16 +99,15 @@ class KTBulkImportManager { @@ -86,16 +99,15 @@ class KTBulkImportManager {
86 if (PEAR::isError($res)) { 99 if (PEAR::isError($res)) {
87 return $res; 100 return $res;
88 } 101 }
89 - $oDocObjects[] = $res; 102 + // Store document object
  103 + $this->uploadedDocs[] = $res;
90 } 104 }
91 - // Jarrett Jordaan: Deal with bulk uploads  
92 - $oSubscriptionEvent = new SubscriptionEvent();  
93 - $oSubscriptionEvent->notifyBulkDocumentUpload($oDocObjects, $oFolder);  
94 105
95 $aFolderPaths = $this->oStorage->listFolders($sPath); 106 $aFolderPaths = $this->oStorage->listFolders($sPath);
96 if (PEAR::isError($aFolderPaths)) { 107 if (PEAR::isError($aFolderPaths)) {
97 return $aFolderPaths; 108 return $aFolderPaths;
98 } 109 }
  110 + $oFolderObjects = array();
99 foreach ($aFolderPaths as $sFolderPath) { 111 foreach ($aFolderPaths as $sFolderPath) {
100 $sFolderBasePath = basename($sFolderPath); 112 $sFolderBasePath = basename($sFolderPath);
101 $sFolderBasePath = ($this->is_utf8($sFolderBasePath)) ? $sFolderBasePath : utf8_encode($sFolderBasePath); 113 $sFolderBasePath = ($this->is_utf8($sFolderBasePath)) ? $sFolderBasePath : utf8_encode($sFolderBasePath);
@@ -115,7 +127,7 @@ class KTBulkImportManager { @@ -115,7 +127,7 @@ class KTBulkImportManager {
115 127
116 if(KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $oFolder)) 128 if(KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $oFolder))
117 { 129 {
118 - $oThisFolder = KTFolderUtil::add($oFolder, $sFolderBasePath, $this->oUser); 130 + $oThisFolder = KTFolderUtil::add($oFolder, $sFolderBasePath, $this->oUser, true);
119 } 131 }
120 else 132 else
121 { 133 {
@@ -135,7 +147,10 @@ class KTBulkImportManager { @@ -135,7 +147,10 @@ class KTBulkImportManager {
135 if (PEAR::isError($res)) { 147 if (PEAR::isError($res)) {
136 return $res; 148 return $res;
137 } 149 }
  150 + // Store folder object
  151 + $this->uploadedFolders[] = $res;
138 } 152 }
  153 +
139 } 154 }
140 155
141 function _importdocument($oFolder, $sPath) { 156 function _importdocument($oFolder, $sPath) {
@@ -165,7 +180,7 @@ class KTBulkImportManager { @@ -165,7 +180,7 @@ class KTBulkImportManager {
165 $aOptions = array_merge($aOptions, $this->aOptions); 180 $aOptions = array_merge($aOptions, $this->aOptions);
166 $sPath = basename($sPath); 181 $sPath = basename($sPath);
167 $sPath = ($this->is_utf8($sPath)) ? $sPath : utf8_encode($sPath); 182 $sPath = ($this->is_utf8($sPath)) ? $sPath : utf8_encode($sPath);
168 - $oDocument =& KTDocumentUtil::add($oFolder, $sPath, $this->oUser, $aOptions); 183 + $oDocument =& KTDocumentUtil::add($oFolder, $sPath, $this->oUser, $aOptions, true);
169 return $oDocument; 184 return $oDocument;
170 } 185 }
171 186
lib/subscriptions/subscriptions.inc.php
@@ -103,11 +103,14 @@ class SubscriptionEvent { @@ -103,11 +103,14 @@ class SubscriptionEvent {
103 * @params : KTDocumentUtil $oDocObjects 103 * @params : KTDocumentUtil $oDocObjects
104 * KTFolderUtil $oParentFolder 104 * KTFolderUtil $oParentFolder
105 */ 105 */
106 - function notifyBulkDocumentUpload($oDocObjects, $oParentFolder) { 106 + function notifyBulkDocumentAction($oDocObjects, $eventType, $oParentFolder) {
107 $content = new SubscriptionContent(); // needed for i18n 107 $content = new SubscriptionContent(); // needed for i18n
108 - $parentId = $oParentFolder->getId();  
109 - $aUsers = $this->_getSubscribers($parentId, $this->subscriptionTypes["Folder"]);  
110 - $this->bulkNotification($aUsers, 'AddDocument', $oDocObjects, $parentId); 108 + // TODO Better way to check if this is a folder object
  109 + if (is_object($oParentFolder)) {
  110 + $parentId = $oParentFolder->getId();
  111 + $aUsers = $this->_getSubscribers($parentId, $this->subscriptionTypes["Folder"]);
  112 + $this->bulkNotification($aUsers, $eventType, $oDocObjects, $parentId);
  113 + }
111 } 114 }
112 115
113 /* 116 /*
@@ -124,11 +127,25 @@ class SubscriptionEvent { @@ -124,11 +127,25 @@ class SubscriptionEvent {
124 $content = new SubscriptionContent(); // needed for i18n 127 $content = new SubscriptionContent(); // needed for i18n
125 $locationName = Folder::generateFullFolderPath($parentId); 128 $locationName = Folder::generateFullFolderPath($parentId);
126 $userId = $_SESSION['userID']; 129 $userId = $_SESSION['userID'];
  130 + $oUser = & User::get($userId);
  131 + $oUserName = $oUser->getName();
  132 +
127 foreach ($aUsers as $oSubscriber) { 133 foreach ($aUsers as $oSubscriber) {
128 $userNotifications = array(); 134 $userNotifications = array();
129 $aNotificationOptions = array(); 135 $aNotificationOptions = array();
130 $userSubscriberId = $oSubscriber->getID(); 136 $userSubscriberId = $oSubscriber->getID();
131 $emailAddress = $oSubscriber->getEmail(); 137 $emailAddress = $oSubscriber->getEmail();
  138 + // Email type details
  139 + $actionTypeEmail = $this->actionTypeEmail($eventType);
  140 + // Better subject header with just the modified folder location
  141 + $eSubject = "Subscription Notification: Bulk {$actionTypeEmail['message']}";
  142 + // now the email content.
  143 + $eContent .= "You are receiving this notification because you are subscribed to the \"$locationName\"<br/>";
  144 + $eContent .= "Your colleague, {$oUser->getName()}, has performed a Bulk {$actionTypeEmail['type']} in the \"$locationName\" folder.<br/>";
  145 + // REMOVE: debugger
  146 + global $default;
  147 + // Get first document/folders details into a notification
  148 + $oNotification = false;
132 foreach($oDocObjects as $oDocObject) { 149 foreach($oDocObjects as $oDocObject) {
133 $targetName = $oDocObject->getName(); 150 $targetName = $oDocObject->getName();
134 $objectId = $oDocObject->getId(); 151 $objectId = $oDocObject->getId();
@@ -139,25 +156,61 @@ class SubscriptionEvent { @@ -139,25 +156,61 @@ class SubscriptionEvent {
139 $aNotificationOptions['object_id'] = $objectId; 156 $aNotificationOptions['object_id'] = $objectId;
140 $aNotificationOptions['event_type'] = $eventType; 157 $aNotificationOptions['event_type'] = $eventType;
141 $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions); 158 $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
142 - $userNotifications[] = $oNotification;  
143 - }  
144 - $eContent = '';  
145 - $eSubject = '';  
146 - // now the email content.  
147 - // might not be a good idea to notify on each file  
148 - //foreach($userNotifications as $userNotification) {  
149 - // $eContent .= $content->getEmailAlertContent($userNotification)."<br/><br/>";  
150 - // Might be an over kill subject  
151 - //$eSubject .= $content->getEmailAlertSubject($userNotification)." ";  
152 - //}  
153 - // Better subject header with just the modified folder location  
154 - $eSubject = "KnowledgeTree: Subscription notification for Bulk Upload In Folder \"$locationName\"";  
155 - $eContent = "KnowledgeTree: Subscription notification for Bulk Upload In Folder \"$locationName\"";  
156 - if($eContent != '' && $eSubject != '') {  
157 - //echo $eContent;  
158 - $oEmail = new EmailAlert($emailAddress, $eSubject, $eContent);  
159 - $oEmail->send(); 159 + break;
160 } 160 }
  161 + $eContent .= $content->getEmailAlertContent($oNotification, $parentId);
  162 + $oEmail = new EmailAlert($emailAddress, $eSubject, $eContent);
  163 + $oEmail->send();
  164 + }
  165 + }
  166 +
  167 + function actionTypeEmail($eventType) {
  168 + switch($eventType){
  169 + case 'AddFolder':
  170 + return array("message"=>"Folders/Documents Added", "type"=>"Add");
  171 + break;
  172 + case 'RemoveSubscribedFolder':
  173 + return array("message"=>"Removed Subscribed Folders/Documents", "type"=>"Remove");
  174 + break;
  175 + case 'RemoveChildFolder':
  176 + return array("message"=>"Removed Folders/Documents", "type"=>"Remove");
  177 + break;
  178 + case 'AddDocument':
  179 + return array("message"=>"Added Folders/Documents", "type"=>"Add");
  180 + break;
  181 + case 'RemoveSubscribedDocument':
  182 + return array("message"=>"Removed Subscribed Folders/Documents", "type"=>"Remove");
  183 + break;
  184 + case 'RemoveChildDocument':
  185 + return array("message"=>"Removed Folders/Documents", "type"=>"Remove");
  186 + break;
  187 + case 'ModifyDocument':
  188 + return array("message"=>"Modified Folders/Documents", "type"=>"Modify");
  189 + break;
  190 + case 'CheckInDocument':
  191 + return array("message"=>"Checked In Documents", "type"=>"Check In");
  192 + break;
  193 + case 'CheckOutDocument':
  194 + return array("message"=>"Checked Out Documents", "type"=>"Check Out");
  195 + break;
  196 + case 'MovedDocument':
  197 + return array("message"=>"Moved Documents/Folders", "type"=>"Move");
  198 + break;
  199 + case 'CopiedDocument':
  200 + return array("message"=>"Copied Folders/Documents", "type"=>"Copy");
  201 + break;
  202 + case 'ArchivedDocument':
  203 + return array("message"=>"Archived Folders/Documents", "type"=>"Archive");
  204 + break;
  205 + case 'RestoreArchivedDocument':
  206 + return array("message"=>"Restored Archived Documents", "type"=>"Archive Restore");
  207 + break;
  208 + case 'DownloadDocument':
  209 + return array("message"=>"Downloaded Folders/Documents", "type"=>"Download");
  210 + break;
  211 + default :
  212 + return array("message"=>"Unknown Operations", "type"=>"Unknown");
  213 + break;
161 } 214 }
162 } 215 }
163 216
@@ -505,7 +558,8 @@ class SubscriptionContent { @@ -505,7 +558,8 @@ class SubscriptionContent {
505 * @param object $oKTNotification: The notification object 558 * @param object $oKTNotification: The notification object
506 * @return string $str: The html string that will be sent via email 559 * @return string $str: The html string that will be sent via email
507 */ 560 */
508 - function getEmailAlertContent($oKTNotification) { 561 + function getEmailAlertContent($oKTNotification, $bulk_action = 0) {
  562 + if($bulk_action == 0) $bulk_action = false;
509 // set up logo and title 563 // set up logo and title
510 $rootUrl = KTUtil::kt_url(); 564 $rootUrl = KTUtil::kt_url();
511 565
@@ -528,7 +582,7 @@ class SubscriptionContent { @@ -528,7 +582,7 @@ class SubscriptionContent {
528 $downloadDocumentText = _kt('The document "').$info['object_name']._kt('"'); 582 $downloadDocumentText = _kt('The document "').$info['object_name']._kt('"');
529 $documentAlertText = _kt('An alert on the document "').$info['object_name']._kt('" has been added or modified'); 583 $documentAlertText = _kt('An alert on the document "').$info['object_name']._kt('" has been added or modified');
530 584
531 - if($info['location_name'] !== NULL){ 585 + if($info['location_name'] !== NULL && !$bulk_action){
532 $addFolderText .= _kt(' to "').$info['location_name']._kt('"'); 586 $addFolderText .= _kt(' to "').$info['location_name']._kt('"');
533 $removeChildFolderText .= _kt(' from the folder "').$info['location_name']._kt('"'); 587 $removeChildFolderText .= _kt(' from the folder "').$info['location_name']._kt('"');
534 $addDocumentText .= _kt(' to "').$info['location_name']._kt('"'); 588 $addDocumentText .= _kt(' to "').$info['location_name']._kt('"');
@@ -542,13 +596,16 @@ class SubscriptionContent { @@ -542,13 +596,16 @@ class SubscriptionContent {
542 $downloadDocumentText .= _kt(' in the folder "').$info['location_name']._kt('" has been downloaded'); 596 $downloadDocumentText .= _kt(' in the folder "').$info['location_name']._kt('" has been downloaded');
543 $documentAlertText .= _kt(' in the folder "').$info['location_name']._kt('"'); 597 $documentAlertText .= _kt(' in the folder "').$info['location_name']._kt('"');
544 } 598 }
545 - 599 + if($bulk_action && $info['event_type']!="RemoveSubscribedFolder") {
  600 + $browse = "$rootUrl/browse.php?fFolderId=$bulk_action";
  601 + $subFolder = '<a href="'.$browse.'">'._kt('View Subscription Folder ').'</a>';
  602 + }
546 // set up links 603 // set up links
547 switch($info['event_type']){ 604 switch($info['event_type']){
548 case 'AddFolder': 605 case 'AddFolder':
549 $text = $addFolderText; 606 $text = $addFolderText;
550 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 607 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
551 - $links = '<a href="'.$url.'">'._kt('View New Folder').'</a>'; 608 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View New Folder').'</a>';
552 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 609 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
553 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 610 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
554 break; 611 break;
@@ -560,14 +617,14 @@ class SubscriptionContent { @@ -560,14 +617,14 @@ class SubscriptionContent {
560 case 'RemoveChildFolder': 617 case 'RemoveChildFolder':
561 $text = $removeChildFolderText; 618 $text = $removeChildFolderText;
562 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 619 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
563 - $links = '<a href="'.$url.'">'._kt('View Folder').'</a>'; 620 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Folder').'</a>';
564 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 621 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
565 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 622 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
566 break; 623 break;
567 case 'AddDocument': 624 case 'AddDocument':
568 $text = $addDocumentText; 625 $text = $addDocumentText;
569 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 626 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
570 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 627 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
571 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 628 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
572 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 629 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
573 break; 630 break;
@@ -584,7 +641,7 @@ class SubscriptionContent { @@ -584,7 +641,7 @@ class SubscriptionContent {
584 case 'ModifyDocument': 641 case 'ModifyDocument':
585 $text = $modifyDocumentText; 642 $text = $modifyDocumentText;
586 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 643 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
587 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 644 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
588 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 645 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
589 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 646 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
590 break; 647 break;
@@ -598,21 +655,21 @@ class SubscriptionContent { @@ -598,21 +655,21 @@ class SubscriptionContent {
598 case 'CheckOutDocument': 655 case 'CheckOutDocument':
599 $text = $checkOutDocumentText; 656 $text = $checkOutDocumentText;
600 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 657 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
601 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 658 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
602 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 659 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
603 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 660 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
604 break; 661 break;
605 case 'MovedDocument': 662 case 'MovedDocument':
606 $text = $modifyDocumentText; 663 $text = $modifyDocumentText;
607 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 664 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
608 - $links = '<a href="'.$url.'">'._kt('View New Location').'</a>'; 665 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View New Location').'</a>';
609 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 666 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
610 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 667 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
611 break; 668 break;
612 case 'CopiedDocument': 669 case 'CopiedDocument':
613 $text = $copiedDocumentText; 670 $text = $copiedDocumentText;
614 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 671 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
615 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 672 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
616 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 673 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
617 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 674 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
618 break; 675 break;
@@ -624,14 +681,14 @@ class SubscriptionContent { @@ -624,14 +681,14 @@ class SubscriptionContent {
624 case 'RestoreArchivedDocument': 681 case 'RestoreArchivedDocument':
625 $text = $restoreArchivedDocumentText; 682 $text = $restoreArchivedDocumentText;
626 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 683 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
627 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 684 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
628 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 685 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
629 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 686 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
630 break; 687 break;
631 case 'DownloadDocument': 688 case 'DownloadDocument':
632 $text = $downloadDocumentText; 689 $text = $downloadDocumentText;
633 $url = $rootUrl.'/notify.php?id='.$info['notify_id']; 690 $url = $rootUrl.'/notify.php?id='.$info['notify_id'];
634 - $links = '<a href="'.$url.'">'._kt('View Document').'</a>'; 691 + if(!$bulk_action) $links = '<a href="'.$url.'">'._kt('View Document').'</a>';
635 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear'; 692 $url = $rootUrl.'/notify.php?id='.$info['notify_id'].'&notify_action=clear';
636 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>'; 693 $links .= '&#160;|&#160;<a href="'.$url.'">'._kt('Clear Alert').'</a>';
637 break; 694 break;
@@ -652,16 +709,25 @@ class SubscriptionContent { @@ -652,16 +709,25 @@ class SubscriptionContent {
652 // we can re-use the normal template. 709 // we can re-use the normal template.
653 // however, we need to wrap it - no need for a second template here. 710 // however, we need to wrap it - no need for a second template here.
654 //$str = '<html><body>' . $this->getNotificationAlertContent($oKTNotification) . '</body></html>'; 711 //$str = '<html><body>' . $this->getNotificationAlertContent($oKTNotification) . '</body></html>';
655 - $str = '<br />  
656 - &#160;&#160;&#160;&#160;<b>'._kt('Subscription notification').': '.$this->_eventTypeNames[$info['event_type']].'</b>  
657 - <br />  
658 - <br />  
659 - &#160;&#160;&#160;&#160;'.$text.'  
660 - <br />  
661 - <br />  
662 - &#160;&#160;&#160;&#160;'.$links.'  
663 - <br />  
664 - <br />'; 712 + if(!$bulk_action) {
  713 + $str = '<br />
  714 + &#160;&#160;&#160;&#160;<b>'._kt('Subscription notification').': '.$this->_eventTypeNames[$info['event_type']].'</b>
  715 + <br />
  716 + <br />
  717 + &#160;&#160;&#160;&#160;'.$text.'
  718 + <br />
  719 + <br />
  720 + &#160;&#160;&#160;&#160;'.$links.'
  721 + <br />
  722 + <br />';
  723 + } else {
  724 + $str = '<br />
  725 + <br />
  726 + '.$subFolder.'
  727 + &#160;'.$links.'
  728 + <br />
  729 + <br />';
  730 + }
665 return $str; 731 return $str;
666 } 732 }
667 733
plugins/ktcore/KTBulkActions.php
@@ -259,16 +259,34 @@ class KTBulkDeleteAction extends KTBulkAction { @@ -259,16 +259,34 @@ class KTBulkDeleteAction extends KTBulkAction {
259 return parent::do_performaction(); 259 return parent::do_performaction();
260 } 260 }
261 261
  262 + /*
  263 + * Bulk delete
  264 + * Author : Jarrett Jordaan
  265 + * Modified : 28/04/09
  266 + *
  267 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  268 + *
  269 + * Description : Since its a bulk operation, the delete function needs to
  270 + * know that. Added extra boolean param to the delete
  271 + * function.
  272 + */
262 function perform_action($oEntity) { 273 function perform_action($oEntity) {
263 $sReason = $this->res['reason']; 274 $sReason = $this->res['reason'];
264 275
265 if(is_a($oEntity, 'Document')) { 276 if(is_a($oEntity, 'Document')) {
266 - $res = KTDocumentUtil::delete($oEntity, $sReason); 277 + $res = KTDocumentUtil::delete($oEntity, $sReason, null, true);
  278 + if (PEAR::isError($res)) {
  279 + return $res;
  280 + }
  281 + return "RemoveChildDocument";
267 } else if(is_a($oEntity, 'Folder')) { 282 } else if(is_a($oEntity, 'Folder')) {
268 - $res = KTFolderUtil::delete($oEntity, $this->oUser, $sReason); 283 + $res = KTFolderUtil::delete($oEntity, $this->oUser, $sReason, null, true);
  284 + if (PEAR::isError($res)) {
  285 + return $res;
  286 + }
  287 + return "RemoveChildFolder";
269 } 288 }
270 289
271 - return $res;  
272 } 290 }
273 } 291 }
274 292
@@ -484,7 +502,8 @@ class KTBulkMoveAction extends KTBulkAction { @@ -484,7 +502,8 @@ class KTBulkMoveAction extends KTBulkAction {
484 $this->oTargetFolder = Folder::get($this->iTargetFolderId); 502 $this->oTargetFolder = Folder::get($this->iTargetFolderId);
485 $_REQUEST['fReturnData'] = ''; 503 $_REQUEST['fReturnData'] = '';
486 $_REQUEST['fFolderId'] = $this->iTargetFolderId; 504 $_REQUEST['fFolderId'] = $this->iTargetFolderId;
487 - 505 + // Jarrett Jordaan : Store initial folder
  506 + $_REQUEST['fOriginalFolderId'] = $this->oFolder->getId();
488 // does it exists 507 // does it exists
489 if(PEAR::isError($this->oTargetFolder)) { 508 if(PEAR::isError($this->oTargetFolder)) {
490 $this->errorRedirectTo('collectinfo', _kt('Invalid target folder selected')); 509 $this->errorRedirectTo('collectinfo', _kt('Invalid target folder selected'));
@@ -507,12 +526,27 @@ class KTBulkMoveAction extends KTBulkAction { @@ -507,12 +526,27 @@ class KTBulkMoveAction extends KTBulkAction {
507 return parent::do_performaction(); 526 return parent::do_performaction();
508 } 527 }
509 528
  529 + /*
  530 + * Bulk move
  531 + * Author : Jarrett Jordaan
  532 + * Modified : 28/04/09
  533 + *
  534 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  535 + *
  536 + * Description : Since its a bulk operation, the move function needs to
  537 + * know that. Added extra boolean param to the move
  538 + * function.
  539 + */
510 function perform_action($oEntity) { 540 function perform_action($oEntity) {
511 if(is_a($oEntity, 'Document')) { 541 if(is_a($oEntity, 'Document')) {
512 - return KTDocumentUtil::move($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason); 542 + $res = KTDocumentUtil::move($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason, true);
513 } else if(is_a($oEntity, 'Folder')) { 543 } else if(is_a($oEntity, 'Folder')) {
514 - return KTFolderUtil::move($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason); 544 + $res = KTFolderUtil::move($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason, true);
515 } 545 }
  546 + if (PEAR::isError($res))
  547 + return $res;
  548 +
  549 + return 'MovedDocument';
516 } 550 }
517 } 551 }
518 552
@@ -737,12 +771,32 @@ class KTBulkCopyAction extends KTBulkAction { @@ -737,12 +771,32 @@ class KTBulkCopyAction extends KTBulkAction {
737 return parent::do_performaction(); 771 return parent::do_performaction();
738 } 772 }
739 773
  774 + /*
  775 + * Bulk copy
  776 + * Author : Jarrett Jordaan
  777 + * Modified : 28/04/09
  778 + *
  779 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  780 + *
  781 + * Description : Since its a bulk operation, the copy function needs to
  782 + * know that. Added extra boolean param to the copy
  783 + * function.
  784 + */
740 function perform_action($oEntity) { 785 function perform_action($oEntity) {
741 if(is_a($oEntity, 'Document')) { 786 if(is_a($oEntity, 'Document')) {
742 - return KTDocumentUtil::copy($oEntity, $this->oTargetFolder, $this->sReason); 787 + $res = KTDocumentUtil::copy($oEntity, $this->oTargetFolder, null, $this->sReason, true);
  788 + if (PEAR::isError($res)) {
  789 + return $res;
  790 + }
  791 +
743 } else if(is_a($oEntity, 'Folder')) { 792 } else if(is_a($oEntity, 'Folder')) {
744 - return KTFolderUtil::copy($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason); 793 + $res = KTFolderUtil::copy($oEntity, $this->oTargetFolder, $this->oUser, $this->sReason, true);
  794 + if (PEAR::isError($res)) {
  795 + return $res;
  796 + }
745 } 797 }
  798 +
  799 + return 'CopiedDocument';
746 } 800 }
747 } 801 }
748 802
@@ -975,15 +1029,25 @@ class KTBulkArchiveAction extends KTBulkAction { @@ -975,15 +1029,25 @@ class KTBulkArchiveAction extends KTBulkAction {
975 return parent::do_performaction(); 1029 return parent::do_performaction();
976 } 1030 }
977 1031
  1032 + /*
  1033 + * Bulk archive
  1034 + * Author : Jarrett Jordaan
  1035 + * Modified : 28/04/09
  1036 + *
  1037 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  1038 + *
  1039 + * Description : Since its a bulk operation, the archive function needs
  1040 + * to know that. Added extra boolean param to the archive
  1041 + * function.
  1042 + */
978 function perform_action($oEntity) { 1043 function perform_action($oEntity) {
979 if(is_a($oEntity, 'Document')) { 1044 if(is_a($oEntity, 'Document')) {
980 1045
981 - $res = KTDocumentUtil::archive($oEntity, $this->sReason); 1046 + $res = KTDocumentUtil::archive($oEntity, $this->sReason, true);
982 1047
983 if(PEAR::isError($res)){ 1048 if(PEAR::isError($res)){
984 return $res; 1049 return $res;
985 } 1050 }
986 - return true;  
987 }else if(is_a($oEntity, 'Folder')) { 1051 }else if(is_a($oEntity, 'Folder')) {
988 $aDocuments = array(); 1052 $aDocuments = array();
989 $aChildFolders = array(); 1053 $aChildFolders = array();
@@ -1028,7 +1092,7 @@ class KTBulkArchiveAction extends KTBulkAction { @@ -1028,7 +1092,7 @@ class KTBulkArchiveAction extends KTBulkAction {
1028 return $oDocument; 1092 return $oDocument;
1029 } 1093 }
1030 1094
1031 - $res = KTDocumentUtil::archive($oDocument, $this->sReason); 1095 + $res = KTDocumentUtil::archive($oDocument, $this->sReason, true);
1032 1096
1033 if(PEAR::isError($res)){ 1097 if(PEAR::isError($res)){
1034 return $res; 1098 return $res;
@@ -1037,8 +1101,10 @@ class KTBulkArchiveAction extends KTBulkAction { @@ -1037,8 +1101,10 @@ class KTBulkArchiveAction extends KTBulkAction {
1037 }else { 1101 }else {
1038 return PEAR::raiseError(_kt('The folder contains no documents to archive.')); 1102 return PEAR::raiseError(_kt('The folder contains no documents to archive.'));
1039 } 1103 }
1040 - return true; 1104 +
  1105 +
1041 } 1106 }
  1107 + return "ArchivedDocument";
1042 } 1108 }
1043 } 1109 }
1044 1110
@@ -1150,8 +1216,19 @@ class KTBrowseBulkExportAction extends KTBulkAction { @@ -1150,8 +1216,19 @@ class KTBrowseBulkExportAction extends KTBulkAction {
1150 return $str; 1216 return $str;
1151 } 1217 }
1152 1218
  1219 + /*
  1220 + * Bulk export
  1221 + * Author : Jarrett Jordaan
  1222 + * Modified : 28/04/09
  1223 + *
  1224 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  1225 + *
  1226 + * Description : Since its a bulk operation, the export function needs
  1227 + * to know that. Added extra boolean param to the export
  1228 + * function.
  1229 + */
1153 function perform_action($oEntity) { 1230 function perform_action($oEntity) {
1154 - 1231 +// TODO find a way to do bulk email
1155 $exportCode = $_SESSION['exportcode']; 1232 $exportCode = $_SESSION['exportcode'];
1156 $this->oZip = ZipFolder::get($exportCode); 1233 $this->oZip = ZipFolder::get($exportCode);
1157 1234
@@ -1189,7 +1266,8 @@ class KTBrowseBulkExportAction extends KTBulkAction { @@ -1189,7 +1266,8 @@ class KTBrowseBulkExportAction extends KTBulkAction {
1189 $oQueue->addFolder($this->oZip, $sFolderId); 1266 $oQueue->addFolder($this->oZip, $sFolderId);
1190 } 1267 }
1191 } 1268 }
1192 - return true; 1269 +
  1270 + return "DownloadDocument";
1193 } 1271 }
1194 1272
1195 function do_downloadZipFile() { 1273 function do_downloadZipFile() {
@@ -1411,6 +1489,17 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction { @@ -1411,6 +1489,17 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
1411 return $result; 1489 return $result;
1412 } 1490 }
1413 1491
  1492 + /*
  1493 + * Bulk checkout
  1494 + * Author : Jarrett Jordaan
  1495 + * Modified : 28/04/09
  1496 + *
  1497 + * @params : KTDocumentUtil/KTFolderUtil $oEntity
  1498 + *
  1499 + * Description : Since its a bulk operation, the checkout function needs
  1500 + * to know that. Added extra boolean param to the checkout
  1501 + * function.
  1502 + */
1414 function perform_action($oEntity) { 1503 function perform_action($oEntity) {
1415 // checkout document 1504 // checkout document
1416 $sReason = $this->sReason; 1505 $sReason = $this->sReason;
@@ -1431,7 +1520,7 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction { @@ -1431,7 +1520,7 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
1431 return PEAR::raiseError($oEntity->getName().': '._kt('Document has already been checked out by ').$oCheckedOutUser->getName()); 1520 return PEAR::raiseError($oEntity->getName().': '._kt('Document has already been checked out by ').$oCheckedOutUser->getName());
1432 } 1521 }
1433 }else{ 1522 }else{
1434 - $res = KTDocumentUtil::checkout($oEntity, $sReason, $this->oUser); 1523 + $res = KTDocumentUtil::checkout($oEntity, $sReason, $this->oUser, true);
1435 1524
1436 if(PEAR::isError($res)) { 1525 if(PEAR::isError($res)) {
1437 return PEAR::raiseError($oEntity->getName().': '.$res->getMessage()); 1526 return PEAR::raiseError($oEntity->getName().': '.$res->getMessage());
@@ -1460,7 +1549,8 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction { @@ -1460,7 +1549,8 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
1460 } 1549 }
1461 $this->oZip->addDocumentToZip($oEntity); 1550 $this->oZip->addDocumentToZip($oEntity);
1462 } 1551 }
1463 - 1552 + if(!PEAR::isError($res)) {
  1553 + }
1464 }else if(is_a($oEntity, 'Folder')) { 1554 }else if(is_a($oEntity, 'Folder')) {
1465 // get documents and subfolders 1555 // get documents and subfolders
1466 $aDocuments = array(); 1556 $aDocuments = array();
@@ -1553,7 +1643,7 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction { @@ -1553,7 +1643,7 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
1553 } 1643 }
1554 }else{ 1644 }else{
1555 // Check out document 1645 // Check out document
1556 - $res = KTDocumentUtil::checkout($oDocument, $sReason, $this->oUser); 1646 + $res = KTDocumentUtil::checkout($oDocument, $sReason, $this->oUser, true);
1557 1647
1558 if(PEAR::isError($res)) { 1648 if(PEAR::isError($res)) {
1559 $this->addErrorMessage($oDocument->getName().': '._kt('Document could not be checked out. ').$res->getMessage()); 1649 $this->addErrorMessage($oDocument->getName().': '._kt('Document could not be checked out. ').$res->getMessage());
@@ -1590,7 +1680,8 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction { @@ -1590,7 +1680,8 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
1590 } 1680 }
1591 } 1681 }
1592 } 1682 }
1593 - return true; 1683 +
  1684 + return "CheckOutDocument";
1594 } 1685 }
1595 1686
1596 function do_downloadZipFile() { 1687 function do_downloadZipFile() {
plugins/ktcore/KTPermissions.php
@@ -874,7 +874,7 @@ class KTDocumentRolesAction extends KTDocumentAction { @@ -874,7 +874,7 @@ class KTDocumentRolesAction extends KTDocumentAction {
874 function do_main() { 874 function do_main() {
875 $this->oPage->setTitle(_kt("View Roles")); 875 $this->oPage->setTitle(_kt("View Roles"));
876 $this->oPage->setBreadcrumbDetails(_kt("View Roles")); 876 $this->oPage->setBreadcrumbDetails(_kt("View Roles"));
877 - $oTemplating = new KTTemplating; 877 + $oTemplating =& KTTemplating::getSingleton();
878 $oTemplate = $oTemplating->loadTemplate("ktcore/action/view_roles"); 878 $oTemplate = $oTemplating->loadTemplate("ktcore/action/view_roles");
879 879
880 // we need to have: 880 // we need to have:
plugins/ktstandard/KTBulkExportPlugin.php
@@ -178,8 +178,8 @@ class KTBulkExportAction extends KTFolderAction { @@ -178,8 +178,8 @@ class KTBulkExportAction extends KTFolderAction {
178 178
179 // fire subscription alerts for the downloaded document 179 // fire subscription alerts for the downloaded document
180 if($bNotifications){ 180 if($bNotifications){
181 - $oSubscriptionEvent = new SubscriptionEvent();  
182 - $oSubscriptionEvent->DownloadDocument($oDocument, $oFolder); 181 + //$oSubscriptionEvent = new SubscriptionEvent();
  182 + //$oSubscriptionEvent->DownloadDocument($oDocument, $oFolder);
183 } 183 }
184 184
185 $this->oZip->addDocumentToZip($oDocument, $oFolder); 185 $this->oZip->addDocumentToZip($oDocument, $oFolder);
plugins/ktstandard/KTSubscriptions.php
@@ -316,16 +316,16 @@ class KTCheckoutSubscriptionTrigger { @@ -316,16 +316,16 @@ class KTCheckoutSubscriptionTrigger {
316 $this->aInfo =& $aInfo; 316 $this->aInfo =& $aInfo;
317 } 317 }
318 318
319 - function postValidate() { 319 + function postValidate($bulk_action = false) {
320 global $default; 320 global $default;
321 $oDocument =& $this->aInfo["document"]; 321 $oDocument =& $this->aInfo["document"];
322 // fire subscription alerts for the checked out document 322 // fire subscription alerts for the checked out document
323 323
324 - // fire subscription alerts for the checked in document  
325 - $oSubscriptionEvent = new SubscriptionEvent();  
326 - $oFolder = Folder::get($oDocument->getFolderID());  
327 - $oSubscriptionEvent->CheckoutDocument($oDocument, $oFolder);  
328 - 324 + if(!$bulk_action) {
  325 + $oSubscriptionEvent = new SubscriptionEvent();
  326 + $oFolder = Folder::get($oDocument->getFolderID());
  327 + $oSubscriptionEvent->CheckoutDocument($oDocument, $oFolder);
  328 + }
329 } 329 }
330 } 330 }
331 // }}} 331 // }}}
@@ -359,16 +359,17 @@ class KTDeleteSubscriptionTrigger { @@ -359,16 +359,17 @@ class KTDeleteSubscriptionTrigger {
359 $this->aInfo =& $aInfo; 359 $this->aInfo =& $aInfo;
360 } 360 }
361 361
362 - function postValidate() { 362 + function postValidate($bulk_action = false) {
363 global $default; 363 global $default;
364 $oDocument =& $this->aInfo["document"]; 364 $oDocument =& $this->aInfo["document"];
365 365
366 // fire subscription alerts for the deleted document 366 // fire subscription alerts for the deleted document
367 -  
368 - // fire subscription alerts for the checked in document  
369 - $oSubscriptionEvent = new SubscriptionEvent();  
370 - $oFolder = Folder::get($oDocument->getFolderID());  
371 - // $oSubscriptionEvent->RemoveDocument($oDocument, $oFolder); 367 + if(!$bulk_action) {
  368 + // fire subscription alerts for the checked in document
  369 + $oSubscriptionEvent = new SubscriptionEvent();
  370 + $oFolder = Folder::get($oDocument->getFolderID());
  371 + //$oSubscriptionEvent->RemoveDocument($oDocument, $oFolder);
  372 + }
372 } 373 }
373 } 374 }
374 // }}} 375 // }}}
@@ -380,16 +381,17 @@ class KTDocumentMoveSubscriptionTrigger { @@ -380,16 +381,17 @@ class KTDocumentMoveSubscriptionTrigger {
380 $this->aInfo =& $aInfo; 381 $this->aInfo =& $aInfo;
381 } 382 }
382 383
383 - function postValidate() { 384 + function postValidate($bulk_action = false) {
384 global $default; 385 global $default;
385 $oDocument =& $this->aInfo["document"]; 386 $oDocument =& $this->aInfo["document"];
386 $oOldFolder =& $this->aInfo["old_folder"]; 387 $oOldFolder =& $this->aInfo["old_folder"];
387 $oNewFolder =& $this->aInfo["new_folder"]; 388 $oNewFolder =& $this->aInfo["new_folder"];
388 389
389 -  
390 - // fire subscription alerts for the checked in document  
391 - $oSubscriptionEvent = new SubscriptionEvent();  
392 - $oSubscriptionEvent->MoveDocument($oDocument, $oNewFolder, $oNewFolder); 390 + if(!$bulk_action) {
  391 + // fire subscription alerts for the checked in document
  392 + $oSubscriptionEvent = new SubscriptionEvent();
  393 + $oSubscriptionEvent->MoveDocument($oDocument, $oNewFolder, $oNewFolder);
  394 + }
393 } 395 }
394 } 396 }
395 // }}} 397 // }}}
@@ -401,14 +403,15 @@ class KTArchiveSubscriptionTrigger { @@ -401,14 +403,15 @@ class KTArchiveSubscriptionTrigger {
401 $this->aInfo =& $aInfo; 403 $this->aInfo =& $aInfo;
402 } 404 }
403 405
404 - function postValidate() { 406 + function postValidate($bulk_action = false) {
405 global $default; 407 global $default;
406 $oDocument =& $this->aInfo["document"]; 408 $oDocument =& $this->aInfo["document"];
407 -  
408 - // fire subscription alerts for the checked in document  
409 - $oSubscriptionEvent = new SubscriptionEvent();  
410 - $oFolder = Folder::get($oDocument->getFolderID());  
411 - $oSubscriptionEvent->ArchivedDocument($oDocument, $oFolder); 409 + if(!$bulk_action) {
  410 + // fire subscription alerts for the checked in document
  411 + $oSubscriptionEvent = new SubscriptionEvent();
  412 + $oFolder = Folder::get($oDocument->getFolderID());
  413 + $oSubscriptionEvent->ArchivedDocument($oDocument, $oFolder);
  414 + }
412 } 415 }
413 } 416 }
414 // }}} 417 // }}}
search2/documentProcessor/documentProcessor.inc.php
@@ -173,7 +173,6 @@ class DocumentProcessor @@ -173,7 +173,6 @@ class DocumentProcessor
173 // indexing starting - create lock file 173 // indexing starting - create lock file
174 touch($lockFile); 174 touch($lockFile);
175 175
176 -  
177 // Process queue 176 // Process queue
178 foreach($queue as $item){ 177 foreach($queue as $item){
179 178
search2/indexing/extractorCore.inc.php
@@ -695,7 +695,6 @@ abstract class TextExtractor extends DocumentExtractor @@ -695,7 +695,6 @@ abstract class TextExtractor extends DocumentExtractor
695 */ 695 */
696 public function extractTextContent() 696 public function extractTextContent()
697 { 697 {
698 -  
699 $config = KTConfig::getSingleton(); 698 $config = KTConfig::getSingleton();
700 $maxTextSize = $config->get('indexer/maxTextSize', 1024 * 1024 * 10); // we'll only take 10 meg by default 699 $maxTextSize = $config->get('indexer/maxTextSize', 1024 * 1024 * 10); // we'll only take 10 meg by default
701 $content = file_get_contents($this->sourcefile, null, null, null, $maxTextSize); 700 $content = file_get_contents($this->sourcefile, null, null, null, $maxTextSize);
search2/indexing/extractors/PlainTextExtractor.inc.php
@@ -7,31 +7,31 @@ @@ -7,31 +7,31 @@
7 * Document Management Made Simple 7 * Document Management Made Simple
8 * Copyright (C) 2008, 2009 KnowledgeTree Inc. 8 * Copyright (C) 2008, 2009 KnowledgeTree Inc.
9 * Portions copyright The Jam Warehouse Software (Pty) Limited 9 * Portions copyright The Jam Warehouse Software (Pty) Limited
10 - * 10 + *
11 * This program is free software; you can redistribute it and/or modify it under 11 * This program is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License version 3 as published by the 12 * the terms of the GNU General Public License version 3 as published by the
13 * Free Software Foundation. 13 * Free Software Foundation.
14 - * 14 + *
15 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details. 18 * details.
19 - * 19 + *
20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 - *  
23 - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, 22 + *
  23 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
24 * California 94120-7775, or email info@knowledgetree.com. 24 * California 94120-7775, or email info@knowledgetree.com.
25 - * 25 + *
26 * The interactive user interfaces in modified source and object code versions 26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under 27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU General Public License version 3. 28 * Section 5 of the GNU General Public License version 3.
29 - * 29 + *
30 * In accordance with Section 7(b) of the GNU General Public License version 3, 30 * In accordance with Section 7(b) of the GNU General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by 31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 - * KnowledgeTree" logo and retain the original copyright notice. If the display of the 32 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
34 - * must display the words "Powered by KnowledgeTree" and retain the original 34 + * must display the words "Powered by KnowledgeTree" and retain the original
35 * copyright notice. 35 * copyright notice.
36 * Contributor( s): ______________________________________ 36 * Contributor( s): ______________________________________
37 * 37 *
@@ -46,6 +46,7 @@ class PlainTextExtractor extends TextExtractor @@ -46,6 +46,7 @@ class PlainTextExtractor extends TextExtractor
46 46
47 public function getSupportedMimeTypes() 47 public function getSupportedMimeTypes()
48 { 48 {
  49 + return array();
49 return array( 50 return array(
50 'text/plain', 51 'text/plain',
51 'text/csv', 52 'text/csv',
search2/indexing/extractors/TikaApacheExtractor.inc.php
@@ -56,6 +56,11 @@ class TikaApacheExtractor extends DocumentExtractor @@ -56,6 +56,11 @@ class TikaApacheExtractor extends DocumentExtractor
56 return _kt('Tika Apache Extractor'); 56 return _kt('Tika Apache Extractor');
57 } 57 }
58 58
  59 + public function needsIntermediateSourceFile()
  60 + {
  61 + return true;
  62 + }
  63 +
59 /** 64 /**
60 * The mime types supported by the extractor 65 * The mime types supported by the extractor
61 * 66 *
@@ -64,10 +69,47 @@ class TikaApacheExtractor extends DocumentExtractor @@ -64,10 +69,47 @@ class TikaApacheExtractor extends DocumentExtractor
64 public function getSupportedMimeTypes() 69 public function getSupportedMimeTypes()
65 { 70 {
66 return array( 71 return array(
  72 + // pdf
67 'application/pdf', 73 'application/pdf',
  74 + // office OLE2 format - 2003, xp, etc
68 'application/vnd.ms-excel', 75 'application/vnd.ms-excel',
69 'application/vnd.ms-powerpoint', 76 'application/vnd.ms-powerpoint',
70 - 'application/msword' 77 + 'application/msword',
  78 + // rtf
  79 + 'text/rtf',
  80 + // staroffice
  81 + 'application/vnd.sun.xml.writer',
  82 + 'application/vnd.sun.xml.writer.template',
  83 + 'application/vnd.sun.xml.calc',
  84 + 'application/vnd.sun.xml.calc.template',
  85 + // text
  86 + 'text/plain',
  87 + 'text/csv',
  88 + 'text/tab-separated-values',
  89 + 'text/css',
  90 + // open xml
  91 + /*
  92 + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  93 + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  94 + 'application/vnd.openxmlformats-officedocument.presentationml.template',
  95 + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
  96 + 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  97 + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  98 + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  99 + // openoffice
  100 + 'application/vnd.oasis.opendocument.presentation',
  101 + 'application/vnd.oasis.opendocument.presentation-template',
  102 + 'application/vnd.oasis.opendocument.spreadsheet',
  103 + 'application/vnd.oasis.opendocument.spreadsheet-template',
  104 + 'application/vnd.oasis.opendocument.text',
  105 + 'application/vnd.oasis.opendocument.text-template',
  106 + 'application/vnd.oasis.opendocument.text-master',
  107 + // xml
  108 + 'text/xml',
  109 + 'application/xml',
  110 + 'text/html',
  111 + 'text/enriched'
  112 + */
71 ); 113 );
72 } 114 }
73 115
@@ -78,6 +120,18 @@ class TikaApacheExtractor extends DocumentExtractor @@ -78,6 +120,18 @@ class TikaApacheExtractor extends DocumentExtractor
78 */ 120 */
79 public function extractTextContent() 121 public function extractTextContent()
80 { 122 {
  123 + $filename = $this->sourcefile;
  124 + $targetFile = $this->targetfile;
  125 +
  126 + $result = $this->xmlrpc->extractTextContent($filename, $targetFile);
  127 +
  128 + if($result === false){
  129 + $this->output = _kt('Tika Extractor: XML-RPC failed to extract text.');
  130 + return false;
  131 + }
  132 + return true;
  133 +
  134 + /* Using streamed content
81 // stream document content 135 // stream document content
82 $filename = $this->sourcefile; 136 $filename = $this->sourcefile;
83 $buffer = file_get_contents($filename); 137 $buffer = file_get_contents($filename);
@@ -99,6 +153,7 @@ class TikaApacheExtractor extends DocumentExtractor @@ -99,6 +153,7 @@ class TikaApacheExtractor extends DocumentExtractor
99 file_put_contents($this->targetfile, $extractedText); 153 file_put_contents($this->targetfile, $extractedText);
100 unset($extractedText); 154 unset($extractedText);
101 return true; 155 return true;
  156 + */
102 } 157 }
103 158
104 /** 159 /**
search2/indexing/indexerCore.inc.php
@@ -1255,6 +1255,15 @@ abstract class Indexer @@ -1255,6 +1255,15 @@ abstract class Indexer
1255 // increment indexed documents count 1255 // increment indexed documents count
1256 Indexer::incrementCount(); 1256 Indexer::incrementCount();
1257 1257
  1258 + // if document is a zero byte file, let's just unqueue and return
  1259 + if ($document->getFileSize() == 0)
  1260 + {
  1261 + Indexer::unqueueDocument($docinfo['document_id'],
  1262 + sprintf(_kt("Zero Byte documents do not need to be indexed: %d"),
  1263 + $docinfo['document_id']));
  1264 + return;
  1265 + }
  1266 +
1258 $docId = $docinfo['document_id']; 1267 $docId = $docinfo['document_id'];
1259 $extension = $docinfo['filetypes']; 1268 $extension = $docinfo['filetypes'];
1260 $mimeType = $docinfo['mimetypes']; 1269 $mimeType = $docinfo['mimetypes'];
@@ -1312,7 +1321,7 @@ abstract class Indexer @@ -1312,7 +1321,7 @@ abstract class Indexer
1312 Indexer::unqueueDocument($docId,sprintf(_kt("indexDocuments: Filename for document id %d starts with a tilde (~). This is assumed to be a temporary file. This is ignored."),$docId), 'error'); 1321 Indexer::unqueueDocument($docId,sprintf(_kt("indexDocuments: Filename for document id %d starts with a tilde (~). This is assumed to be a temporary file. This is ignored."),$docId), 'error');
1313 return ; 1322 return ;
1314 } 1323 }
1315 - 1324 +
1316 $removeFromQueue = true; 1325 $removeFromQueue = true;
1317 if ($indexDocument) 1326 if ($indexDocument)
1318 { 1327 {
search2/indexing/lib/XmlRpcLucene.inc.php
@@ -285,11 +285,37 @@ class XmlRpcLucene @@ -285,11 +285,37 @@ class XmlRpcLucene
285 } 285 }
286 286
287 /** 287 /**
  288 + * Extracts the text from a given document and writes it to the target file
  289 + *
  290 + * @param string $sourceFile The full path to the document
  291 + * @param string $targetFile The full path to the target / output file
  292 + * @return boolean true on success | false on failure
  293 + */
  294 + function extractTextContent($sourceFile, $targetFile)
  295 + {
  296 + $function = new xmlrpcmsg('textextraction.getTextFromFile',
  297 + array(
  298 + php_xmlrpc_encode((string) $sourceFile),
  299 + php_xmlrpc_encode((string) $targetFile)
  300 + )
  301 + );
  302 +
  303 + $result =& $this->client->send($function, 120);
  304 +
  305 + if($result->faultCode()) {
  306 + $this->error($result, 'extractTextContent');
  307 + return false;
  308 + }
  309 + return php_xmlrpc_decode($result->value()) == 0;
  310 + }
  311 +
  312 + /**
288 * Extracts the text from a given document stream 313 * Extracts the text from a given document stream
289 * 314 *
290 - * @return unknown 315 + * @param string $content The document content
  316 + * @return string The extracted text on success | false on failure
291 */ 317 */
292 - function extractTextContent($content) 318 + function extractTextContentByStreaming($content)
293 { 319 {
294 $function = new xmlrpcmsg('textextraction.getText', 320 $function = new xmlrpcmsg('textextraction.getText',
295 array( 321 array(
setup/upgrade.php
@@ -183,10 +183,11 @@ if (PEAR::isError($dbSupport)) { @@ -183,10 +183,11 @@ if (PEAR::isError($dbSupport)) {
183 183
184 184
185 ?> 185 ?>
  186 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
186 <html> 187 <html>
187 <head> 188 <head>
188 <title><?php echo APP_NAME;?> Upgrade</title> 189 <title><?php echo APP_NAME;?> Upgrade</title>
189 - <style> 190 + <style type="text/css">
190 th { text-align: left; } 191 th { text-align: left; }
191 td { vertical-align: top; } 192 td { vertical-align: top; }
192 .foo { float: left; } 193 .foo { float: left; }
@@ -203,13 +204,13 @@ td { vertical-align: top; } @@ -203,13 +204,13 @@ td { vertical-align: top; }
203 echo $oKTConfig->get('ui/mainLogo'); 204 echo $oKTConfig->get('ui/mainLogo');
204 }else{ 205 }else{
205 echo '../resources/graphics/ktlogo-topbar_base.png'; 206 echo '../resources/graphics/ktlogo-topbar_base.png';
206 - }?>"> 207 + }?>"/>
207 <p> 208 <p>
208 - <img src="upgrade-title.jpg">  
209 - <table width=800 height=500> 209 + <img src="upgrade-title.jpg"/>
  210 + <table style="width:800; height:500">
210 <tr><td> 211 <tr><td>
211 <P> 212 <P>
212 - <script> 213 + <script type="text/javascript">
213 function do_start(action) 214 function do_start(action)
214 { 215 {
215 document.location='?go=' + action; 216 document.location='?go=' + action;
@@ -458,8 +459,8 @@ function create_restore_stmt($targetfile) @@ -458,8 +459,8 @@ function create_restore_stmt($targetfile)
458 459
459 $tmpdir=resolveTempDir(); 460 $tmpdir=resolveTempDir();
460 461
461 - $stmt = $prefix ."mysqladmin --user=\"$adminUser\" -p $mechanism drop \"$dbName\"<br>";  
462 - $stmt .= $prefix ."mysqladmin --user=\"$adminUser\" -p $mechanism create \"$dbName\"<br>"; 462 + $stmt = $prefix ."mysqladmin --user=\"$adminUser\" -p $mechanism drop \"$dbName\"<br/>";
  463 + $stmt .= $prefix ."mysqladmin --user=\"$adminUser\" -p $mechanism create \"$dbName\"<br/>";
463 464
464 465
465 $stmt .= $prefix ."mysql --user=\"$adminUser\" -p $mechanism \"$dbName\" < \"$targetfile\"\n"; 466 $stmt .= $prefix ."mysql --user=\"$adminUser\" -p $mechanism \"$dbName\" < \"$targetfile\"\n";
@@ -478,7 +479,7 @@ function title($title) @@ -478,7 +479,7 @@ function title($title)
478 { 479 {
479 if (!isset($_SESSION['setup_user'])) 480 if (!isset($_SESSION['setup_user']))
480 { 481 {
481 - print "<script>document.location='?go=Login'</script>"; 482 + print "<script type='text/javascript'>document.location='?go=Login'</script>";
482 } 483 }
483 print "<h1>$title</h1>"; 484 print "<h1>$title</h1>";
484 } 485 }
@@ -511,10 +512,10 @@ function upgradeConfirm() @@ -511,10 +512,10 @@ function upgradeConfirm()
511 if (!isset($_SESSION['backupStatus']) || $_SESSION['backupStatus'] === false) 512 if (!isset($_SESSION['backupStatus']) || $_SESSION['backupStatus'] === false)
512 { 513 {
513 ?> 514 ?>
514 -<br> 515 +<br/>
515 <font color="Red">Please ensure that you have made a backup before continuing with the upgrade process.</font> 516 <font color="Red">Please ensure that you have made a backup before continuing with the upgrade process.</font>
516 <p> 517 <p>
517 -<br> 518 +<br/>
518 <?php 519 <?php
519 } 520 }
520 ?> 521 ?>
@@ -550,7 +551,7 @@ Your mysql installation has been resolved. Manually, you would do the following: @@ -550,7 +551,7 @@ Your mysql installation has been resolved. Manually, you would do the following:
550 <tr> 551 <tr>
551 <td> 552 <td>
552 <nobr>cd "<?php echo $dir;?>"</nobr> 553 <nobr>cd "<?php echo $dir;?>"</nobr>
553 -<br> 554 +<br/>
554 <?php 555 <?php
555 } 556 }
556 else 557 else
@@ -617,7 +618,7 @@ function restoreSelect() @@ -617,7 +618,7 @@ function restoreSelect()
617 <P> 618 <P>
618 Select a backup to restore from the list below: 619 Select a backup to restore from the list below:
619 <P> 620 <P>
620 - <script> 621 + <script type="text/javascript">
621 function selectRestore(filename) 622 function selectRestore(filename)
622 { 623 {
623 document.location='?go=RestoreSelected&file=' + filename; 624 document.location='?go=RestoreSelected&file=' + filename;
@@ -659,7 +660,7 @@ function restoreSelected() @@ -659,7 +660,7 @@ function restoreSelected()
659 $dir = resolveTempDir(); 660 $dir = resolveTempDir();
660 $_SESSION['backupFile'] = $dir . '/' . $file; 661 $_SESSION['backupFile'] = $dir . '/' . $file;
661 ?> 662 ?>
662 -<script> 663 +<script type="text/javascript">
663 document.location='?go=RestoreConfirm'; 664 document.location='?go=RestoreConfirm';
664 </script> 665 </script>
665 <?php 666 <?php
@@ -691,7 +692,7 @@ Manually, you would do the following to restore the backup: @@ -691,7 +692,7 @@ Manually, you would do the following to restore the backup:
691 <tr> 692 <tr>
692 <td> 693 <td>
693 <nobr>cd "<?php echo $dir;?>"</nobr> 694 <nobr>cd "<?php echo $dir;?>"</nobr>
694 -<br> 695 +<br/>
695 <?php 696 <?php
696 } 697 }
697 else 698 else
@@ -709,6 +710,8 @@ You can continue to do the restore manually using the following command(s): @@ -709,6 +710,8 @@ You can continue to do the restore manually using the following command(s):
709 } 710 }
710 ?> 711 ?>
711 <nobr><?php echo $stmt['display'];?></nobr> 712 <nobr><?php echo $stmt['display'];?></nobr>
  713 +</td>
  714 +</tr>
712 </table> 715 </table>
713 <P> 716 <P>
714 <?php 717 <?php
@@ -729,7 +732,7 @@ Press &lt;i&gt;continue to restore&lt;/i&gt; to attempt the command(s) above. @@ -729,7 +732,7 @@ Press &lt;i&gt;continue to restore&lt;/i&gt; to attempt the command(s) above.
729 if ($dir != '') 732 if ($dir != '')
730 { 733 {
731 ?> 734 ?>
732 -<script> 735 +<script type="text/javascript">
733 function restore() 736 function restore()
734 { 737 {
735 if (confirm('Are you sure you want to restore? This is your last chance if the current data has not been backed up.')) 738 if (confirm('Are you sure you want to restore? This is your last chance if the current data has not been backed up.'))
@@ -758,7 +761,7 @@ function backupDone() @@ -758,7 +761,7 @@ function backupDone()
758 { 761 {
759 $stmt=create_restore_stmt($filename); 762 $stmt=create_restore_stmt($filename);
760 ?> 763 ?>
761 - The backup file <nobr><I>"<?php echo $filename;?>"</i></nobr> has been created. 764 + The backup file <nobr><i>"<?php echo $filename;?>"</i></nobr> has been created.
762 <P> It appears as though the <font color=green>backup has been successful</font>. 765 <P> It appears as though the <font color=green>backup has been successful</font>.
763 <P> 766 <P>
764 <?php 767 <?php
@@ -771,7 +774,7 @@ function backupDone() @@ -771,7 +774,7 @@ function backupDone()
771 <tr> 774 <tr>
772 <td> 775 <td>
773 <nobr>cd <?php echo $stmt['dir'];?></nobr> 776 <nobr>cd <?php echo $stmt['dir'];?></nobr>
774 - <br> 777 + <br/>
775 <?php 778 <?php
776 } 779 }
777 else 780 else
@@ -809,7 +812,7 @@ We appologise for the inconvenience. @@ -809,7 +812,7 @@ We appologise for the inconvenience.
809 812
810 } 813 }
811 ?> 814 ?>
812 -<br> 815 +<br/>
813 816
814 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('welcome')"> 817 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('welcome')">
815 <?php 818 <?php
@@ -833,7 +836,7 @@ function restoreDone() @@ -833,7 +836,7 @@ function restoreDone()
833 { 836 {
834 837
835 ?> 838 ?>
836 - The restore of <nobr><I>"<?php echo $filename;?>"</i></nobr> has been completed. 839 + The restore of <nobr><i>"<?php echo $filename;?>"</i></nobr> has been completed.
837 <P> 840 <P>
838 It appears as though the <font color=green>restore has been successful</font>. 841 It appears as though the <font color=green>restore has been successful</font>.
839 <P> 842 <P>
@@ -861,7 +864,7 @@ We appologise for the inconvenience. @@ -861,7 +864,7 @@ We appologise for the inconvenience.
861 } 864 }
862 ?> 865 ?>
863 866
864 -<br> 867 +<br/>
865 868
866 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('welcome')"> 869 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('welcome')">
867 870
@@ -878,7 +881,7 @@ function check_state($value, $state=&#39;Home&#39;) @@ -878,7 +881,7 @@ function check_state($value, $state=&#39;Home&#39;)
878 if ($_SESSION['state'] != $value) 881 if ($_SESSION['state'] != $value)
879 { 882 {
880 ?> 883 ?>
881 - <script> 884 + <script type="text/javascript">
882 document.location="?go=<?php echo $state;?>"; 885 document.location="?go=<?php echo $state;?>";
883 </script> 886 </script>
884 <?php 887 <?php
@@ -935,7 +938,7 @@ function backup() @@ -935,7 +938,7 @@ function backup()
935 $_SESSION['backupStatus'] = false; 938 $_SESSION['backupStatus'] = false;
936 } 939 }
937 ?> 940 ?>
938 - <script> 941 + <script type="text/javascript">
939 document.location="?go=BackupDone"; 942 document.location="?go=BackupDone";
940 </script> 943 </script>
941 <?php 944 <?php
@@ -1007,7 +1010,7 @@ function restore() @@ -1007,7 +1010,7 @@ function restore()
1007 1010
1008 1011
1009 ?> 1012 ?>
1010 - <script> 1013 + <script type="text/javascript">
1011 document.location="?go=RestoreDone"; 1014 document.location="?go=RestoreDone";
1012 </script> 1015 </script>
1013 <?php 1016 <?php
@@ -1033,22 +1036,22 @@ function welcome() @@ -1033,22 +1036,22 @@ function welcome()
1033 { 1036 {
1034 set_state(1); 1037 set_state(1);
1035 ?> 1038 ?>
1036 -<br> 1039 +<br/>
1037 Welcome to the <?php echo APP_NAME;?> Database Upgrade Wizard.<P> If you have just updated 1040 Welcome to the <?php echo APP_NAME;?> Database Upgrade Wizard.<P> If you have just updated
1038 your <?php echo APP_NAME;?> code base, you will need to complete the upgrade process in order to ensure your system is fully operational with the new version. 1041 your <?php echo APP_NAME;?> code base, you will need to complete the upgrade process in order to ensure your system is fully operational with the new version.
1039 <P> 1042 <P>
1040 You will not be able to log into <?php echo APP_NAME;?> until your the database upgrade process is completed. 1043 You will not be able to log into <?php echo APP_NAME;?> until your the database upgrade process is completed.
1041 <P> 1044 <P>
1042 -<font color=orange>!!NB!! You are advised to backup the database before attempting the upgrade. !!NB!!</font> 1045 +<font color="#ffa500">!!NB!! You are advised to backup the database before attempting the upgrade. !!NB!!</font>
1043 <P> 1046 <P>
1044 If you have already done this, you may skip this step can continue directly to the upgrade. 1047 If you have already done this, you may skip this step can continue directly to the upgrade.
1045 <P> 1048 <P>
1046 1049
1047 1050
1048 -&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="cancel" onclick="document.location='..';">  
1049 -&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="backup now" onclick="javascript:do_start('BackupConfirm');">  
1050 -&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="next" onclick="javascript:do_start('UpgradeConfirm');">  
1051 -&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="restore database" onclick="javascript:do_start('RestoreConfirm');"> 1051 +&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="cancel" onclick="document.location='..';"/>
  1052 +&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="backup now" onclick="javascript:do_start('BackupConfirm');"/>
  1053 +&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="next" onclick="javascript:do_start('UpgradeConfirm');"/>
  1054 +&nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="restore database" onclick="javascript:do_start('RestoreConfirm');"/>
1052 1055
1053 1056
1054 <?php 1057 <?php
@@ -1069,7 +1072,7 @@ function UpgradePreview() @@ -1069,7 +1072,7 @@ function UpgradePreview()
1069 $upgradeTable = generateUpgradeTable(); 1072 $upgradeTable = generateUpgradeTable();
1070 print $upgradeTable; 1073 print $upgradeTable;
1071 ?> 1074 ?>
1072 - <br> 1075 + <br/>
1073 1076
1074 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('home')"> 1077 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="back" onclick="javascript:do_start('home')">
1075 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="next" onclick="javascript:do_start('Upgrade')"> 1078 &nbsp;&nbsp; &nbsp; &nbsp; <input type=button value="next" onclick="javascript:do_start('Upgrade')">
@@ -1091,14 +1094,14 @@ function Upgrade() @@ -1091,14 +1094,14 @@ function Upgrade()
1091 if (PEAR::isError($pre_res)) 1094 if (PEAR::isError($pre_res))
1092 { 1095 {
1093 ?> 1096 ?>
1094 -<font color="red">Pre-Upgrade actions failed.</font><br> 1097 +<font color="red">Pre-Upgrade actions failed.</font><br/>
1095 <?php 1098 <?php
1096 } 1099 }
1097 else 1100 else
1098 { 1101 {
1099 ?> 1102 ?>
1100 <p> 1103 <p>
1101 -<font color="green">Pre-Upgrade actions succeeded.</font><br> 1104 +<font color="green">Pre-Upgrade actions succeeded.</font><br/>
1102 <?php 1105 <?php
1103 } 1106 }
1104 ?> 1107 ?>
@@ -1125,15 +1128,15 @@ function Upgrade() @@ -1125,15 +1128,15 @@ function Upgrade()
1125 if (PEAR::isError($post_res)) 1128 if (PEAR::isError($post_res))
1126 { 1129 {
1127 ?> 1130 ?>
1128 -<font color="red">Post-Upgrade actions failed.</font><br><br> 1131 +<font color="red">Post-Upgrade actions failed.</font><br/><br/>
1129 <?php 1132 <?php
1130 } 1133 }
1131 else 1134 else
1132 { 1135 {
1133 ?> 1136 ?>
1134 <p> 1137 <p>
1135 -<font color="green">Post-Upgrade actions succeeded.</font><br><br>  
1136 -<script> 1138 +<font color="green">Post-Upgrade actions succeeded.</font><br/><br/>
  1139 +<script type="text/javascript">
1137 alert("To complete the upgrade please do the following before continuing:\n\n1. Restart the services as appropriate for your environment.\n\n\nOn first run of your upgraded installaton please do the following:\n\n1. Hard refresh your bowser (CTRL-F5) on first view of the Dashboard.\n2. Enable the new plugins you wish to use.\n\n\nSelect 'next' at the bottom of this page to continue.") 1140 alert("To complete the upgrade please do the following before continuing:\n\n1. Restart the services as appropriate for your environment.\n\n\nOn first run of your upgraded installaton please do the following:\n\n1. Hard refresh your bowser (CTRL-F5) on first view of the Dashboard.\n2. Enable the new plugins you wish to use.\n\n\nSelect 'next' at the bottom of this page to continue.")
1138 </script> 1141 </script>
1139 <?php 1142 <?php
sql/mysql/upgrade/3.1.6.3/groups-integrity.sql
@@ -2,13 +2,37 @@ @@ -2,13 +2,37 @@
2 2
3 -- parent_group_id 3 -- parent_group_id
4 4
5 -DELETE FROM `groups_groups_link` as gg USING `groups_groups_link` as gg, groups_lookup  
6 - WHERE not exists(select 1 from `groups_lookup` as g where gg.parent_group_id = g.id); 5 +CREATE TEMPORARY TABLE cleanup (
  6 + `id` int(11) NOT NULL auto_increment,
  7 + `parent_group_id` int(11) NOT NULL default '0',
  8 + `member_group_id` int(11) NOT NULL default '0',
  9 + PRIMARY KEY (`id`),
  10 + KEY `parent_group_id` (`parent_group_id`),
  11 + KEY `member_group_id` (`member_group_id`)
  12 +);
  13 +INSERT INTO cleanup (id, parent_group_id, member_group_id)
  14 +SELECT * FROM `groups_groups_link` AS gg WHERE ( SELECT 1 FROM `groups_lookup` AS g WHERE gg.parent_group_id = g.id);
  15 +SELECT * FROM cleanup;
  16 +TRUNCATE groups_groups_link;
  17 +INSERT groups_groups_link SELECT * FROM cleanup;
  18 +DROP TABLE cleanup;
7 19
8 -- member_group_id 20 -- member_group_id
9 21
10 -DELETE FROM `groups_groups_link` as gg USING `groups_groups_link` as gg, groups_lookup  
11 - WHERE not exists(select 1 from `groups_lookup` as g where gg.member_group_id = g.id); 22 +CREATE TEMPORARY TABLE cleanup (
  23 + `id` int(11) NOT NULL auto_increment,
  24 + `parent_group_id` int(11) NOT NULL default '0',
  25 + `member_group_id` int(11) NOT NULL default '0',
  26 + PRIMARY KEY (`id`),
  27 + KEY `parent_group_id` (`parent_group_id`),
  28 + KEY `member_group_id` (`member_group_id`)
  29 +);
  30 +INSERT INTO cleanup (id, parent_group_id, member_group_id)
  31 +SELECT * FROM `groups_groups_link` AS gg WHERE ( SELECT 1 FROM `groups_lookup` AS g WHERE gg.member_group_id = g.id);
  32 +SELECT * FROM cleanup;
  33 +TRUNCATE groups_groups_link;
  34 +INSERT groups_groups_link SELECT * FROM cleanup;
  35 +DROP TABLE cleanup;
12 36
13 -- ADD CONSTRAINT 37 -- ADD CONSTRAINT
14 38
@@ -16,21 +40,44 @@ ALTER TABLE `groups_groups_link` @@ -16,21 +40,44 @@ ALTER TABLE `groups_groups_link`
16 ADD CONSTRAINT `groups_groups_link_ibfk_1` FOREIGN KEY (`parent_group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE, 40 ADD CONSTRAINT `groups_groups_link_ibfk_1` FOREIGN KEY (`parent_group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE,
17 ADD CONSTRAINT `groups_groups_link_ibfk_2` FOREIGN KEY (`member_group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE; 41 ADD CONSTRAINT `groups_groups_link_ibfk_2` FOREIGN KEY (`member_group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE;
18 42
  43 +
19 -- PREPARE FOR ADDING CONSTRAINTS ON `users_groups_link` 44 -- PREPARE FOR ADDING CONSTRAINTS ON `users_groups_link`
20 45
21 -- group_id 46 -- group_id
22 -  
23 -DELETE FROM `users_groups_link` as ug USING `users_groups_link` as ug, groups_lookup  
24 - WHERE not exists(select 1 from `groups_lookup` as g where ug.group_id = g.id); 47 +CREATE TEMPORARY TABLE cleanup (
  48 + `id` int(11) NOT NULL auto_increment,
  49 + `user_id` int(11) NOT NULL default '0',
  50 + `group_id` int(11) NOT NULL default '0',
  51 + PRIMARY KEY (`id`),
  52 + KEY `user_id` (`user_id`),
  53 + KEY `group_id` (`group_id`)
  54 +);
  55 +INSERT INTO cleanup (id, user_id, group_id)
  56 +SELECT * FROM `users_groups_link` AS ug WHERE ( SELECT 1 FROM `groups_lookup` AS g WHERE ug.group_id = g.id);
  57 +SELECT * FROM cleanup;
  58 +TRUNCATE groups_groups_link;
  59 +INSERT groups_groups_link SELECT * FROM cleanup;
  60 +DROP TABLE cleanup;
25 61
26 -- user_id 62 -- user_id
27 -  
28 -DELETE FROM `users_groups_link` as ug USING `users_groups_link` as ug, users  
29 - WHERE not exists(select 1 from `users` as u where ug.user_id = u.id); 63 +CREATE TEMPORARY TABLE cleanup (
  64 + `id` int(11) NOT NULL auto_increment,
  65 + `user_id` int(11) NOT NULL default '0',
  66 + `group_id` int(11) NOT NULL default '0',
  67 + PRIMARY KEY (`id`),
  68 + KEY `user_id` (`user_id`),
  69 + KEY `group_id` (`group_id`)
  70 +);
  71 +INSERT INTO cleanup (id, user_id, group_id)
  72 +SELECT * FROM `users_groups_link` AS ug WHERE ( SELECT 1 FROM `groups_lookup` AS g WHERE ug.user_id = g.id);
  73 +SELECT * FROM cleanup;
  74 +TRUNCATE groups_groups_link;
  75 +INSERT groups_groups_link SELECT * FROM cleanup;
  76 +DROP TABLE cleanup;
30 77
31 -- ADD CONSTRAINT 78 -- ADD CONSTRAINT
32 79
33 ALTER TABLE `users_groups_link` 80 ALTER TABLE `users_groups_link`
34 ADD CONSTRAINT `users_groups_link_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE, 81 ADD CONSTRAINT `users_groups_link_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups_lookup` (`id`) ON DELETE CASCADE,
35 - ADD CONSTRAINT `users_groups_link_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; 82 + ADD CONSTRAINT `users_groups_link_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
36 83
templates/ktcore/search2/adv_query_builder.smarty
@@ -426,7 +426,7 @@ function addFieldTypeSelection(groupid, fid, type, options) @@ -426,7 +426,7 @@ function addFieldTypeSelection(groupid, fid, type, options)
426 var html = ''; 426 var html = '';
427 var callback = null; 427 var callback = null;
428 var params = null; 428 var params = null;
429 -alert(type); 429 +
430 switch(type) 430 switch(type)
431 { 431 {
432 case 'FILESIZE': 432 case 'FILESIZE':
templates/ktcore/search2/search_results.smarty
@@ -156,10 +156,10 @@ function onShowAll(showall) @@ -156,10 +156,10 @@ function onShowAll(showall)
156 <span class="contenttype {$hit->MimeIconPath}"> 156 <span class="contenttype {$hit->MimeIconPath}">
157 157
158 {if $hit->IsDocument} 158 {if $hit->IsDocument}
159 - &nbsp;&nbsp;<a href="{$rootUrl}/view.php?fDocumentId={$hit->Id}"><B>{$hit->Title|mb_truncate:30:'...':true}</b></a> 159 + &nbsp;&nbsp;<a href="{$rootUrl}/view.php?fDocumentId={$hit->Id}" title="{$hit->Title}"><B>{$hit->Title|mb_truncate:80:'...':true}</b></a>
160 {if $hit->Title != $hit->Filename} 160 {if $hit->Title != $hit->Filename}
161 - &nbsp;&nbsp;  
162 - <font style=" color: green "> - {i18n}Filename:{/i18n} {$hit->Filename|mb_truncate:30:'...':true}</font> 161 + <br/>
  162 + <font style=" color: green ">{i18n}Filename:{/i18n} {$hit->Filename|mb_truncate:80:'...':true}</font>
163 {/if} 163 {/if}
164 {if $hit->IsAvailable} 164 {if $hit->IsAvailable}
165 &nbsp;&nbsp; 165 &nbsp;&nbsp;
tests/api/testElectronicSignatures.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 +* These are the unit tests for the main KTAPI class
  7 +*
  8 +*/
  9 +class APIElectronicSignaturesTestCase extends KTUnitTestCase {
  10 +
  11 + /**
  12 + * @var object $ktapi The main ktapi object
  13 + */
  14 + var $ktapi;
  15 +
  16 + /**
  17 + * @var object $session The KT session object
  18 + */
  19 + var $session;
  20 +
  21 + /**
  22 + * @var object $root The KT folder object
  23 + */
  24 + var $root;
  25 +
  26 + /**
  27 + * @var bool $esig_enabled True if electronic signatures for api are enabled | False if not enabled
  28 + */
  29 + var $esig_enabled;
  30 +
  31 + /**
  32 + * This method sets up the KT session
  33 + *
  34 + */
  35 + public function setUp() {
  36 + $this->ktapi = new KTAPI();
  37 + $this->session = $this->ktapi->start_session('admin', 'admin');
  38 + $this->root = $this->ktapi->get_root_folder();
  39 + $this->assertTrue($this->root instanceof KTAPI_Folder);
  40 + $this->esig_enabled = $this->ktapi->electronic_sig_enabled();
  41 + $this->assertTrue($this->esig_enabled);
  42 + }
  43 +
  44 + /**
  45 + * This method emds the KT session
  46 + *
  47 + */
  48 + public function tearDown() {
  49 + $this->session->logout();
  50 + }
  51 +
  52 + /* *** Test webservice functions *** */
  53 +
  54 + /**
  55 + * Testing folder creation and deletion, add document, get folder contents, folder detail
  56 + * Folder shortcuts and actions
  57 + */
  58 + public function testFolderApiFunctions()
  59 + {
  60 + // Create a folder
  61 + // test without authentication - should fail
  62 + $result1 = $this->ktapi->create_folder(1, 'New test api folder');
  63 + $this->assertEqual($result1['status_code'], 1);
  64 +
  65 + // test with authentication
  66 + $result2 = $this->ktapi->create_folder(1, 'New test api folder', 'admin', 'admin', 'Testing API');
  67 + $folder_id = $result2['results']['id'];
  68 + $this->assertEqual($result2['status_code'], 0);
  69 + $this->assertTrue($result2['results']['parent_id'] == 1);
  70 +
  71 + // Create a sub folder
  72 + // test without authentication - should fail
  73 + $result3 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder');
  74 + $this->assertEqual($result3['status_code'], 1);
  75 +
  76 + // test with authentication
  77 + $result4 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder', 'admin', 'admin', 'Testing API');
  78 + $folder_id2 = $result4['results']['id'];
  79 + $this->assertEqual($result4['status_code'], 0);
  80 +
  81 + // Add a document
  82 + global $default;
  83 + $dir = $default->uploadDirectory;
  84 + $tempfilename = $this->createRandomFile('some text', $dir);
  85 +
  86 + // test without authentication - should fail
  87 + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename);
  88 + $this->assertEqual($doc['status_code'], 1);
  89 +
  90 + // test with authentication
  91 + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename,
  92 + 'admin', 'admin', 'Testing API');
  93 + $this->assertEqual($doc['status_code'], 0);
  94 + $doc_id = $doc['results']['document_id'];
  95 + $this->assertEqual($doc['results']['title'], 'New API test doc');
  96 +
  97 + // Rename the folder
  98 + // test without authentication - should fail
  99 + $renamed = $this->ktapi->rename_folder($folder_id, 'Renamed test folder');
  100 + $this->assertEqual($renamed['status_code'], 1);
  101 +
  102 + // test with authentication
  103 + $renamed = $this->ktapi->rename_folder($folder_id, 'Renamed test folder', 'admin', 'admin', 'Testing API');
  104 + $this->assertEqual($renamed['status_code'], 0);
  105 +
  106 + /**
  107 + * Copy and move appear to fail in other parts of the code, so only going to test failure here
  108 + *
  109 + * Must be VERY careful here with skipping the valid submissions, 3 failed auth attempts in a row locks out the user!
  110 + */
  111 + // Copy folder
  112 + // test without authentication - should fail
  113 + $copied = $this->ktapi->copy_folder($source_id, $target_id, $reason);
  114 + $this->assertEqual($copied['status_code'], 1);
  115 +
  116 +// // test with authentication
  117 +// $copied = $this->ktapi->copy_folder($source_id, $target_id, $reason, 'admin', 'admin');
  118 +// echo $copied['status_code']."sd<BR>";
  119 +// $this->assertEqual($copied['status_code'], 0);
  120 +
  121 + // Move folder
  122 + // test without authentication - should fail
  123 + $moved = $this->ktapi->move_folder($source_id, $target_id, $reason);
  124 + $this->assertEqual($moved['status_code'], 1);
  125 +
  126 + // before we end up with 3 fails in a row (see note above the first copy attempt,) force a successful auth
  127 + $renamed = $this->ktapi->rename_folder($folder_id, 'A New Name', 'admin', 'admin', 'Testing API');
  128 +
  129 +// // test with authentication
  130 +// $moved = $this->ktapi->move_folder($source_id, $target_id, $reason, 'admin', 'admin');
  131 +// $this->assertEqual($moved['status_code'], 0);
  132 +
  133 + // before we end up with 3 fails in a row (see note above the first copy attempt,) force a successful auth
  134 + $renamed = $this->ktapi->rename_folder($folder_id, 'A New Name', 'admin', 'admin', 'Testing API');
  135 +
  136 + // Clean up - delete the folder
  137 + // test without authentication - should fail
  138 + $deleted = $this->ktapi->delete_folder($folder_id, 'Testing API');
  139 + $this->assertEqual($deleted['status_code'], 1);
  140 +
  141 + // test with authentication
  142 + $deleted = $this->ktapi->delete_folder($folder_id, 'Testing API', 'admin', 'admin');
  143 + $this->assertEqual($deleted['status_code'], 0);
  144 + }
  145 +
  146 + /**
  147 + * Testing document get, update, actions, delete, shortcuts and detail
  148 + */
  149 + public function testDocumentApiFunctions()
  150 + {
  151 + // Create a folder
  152 + // test without authentication - should fail
  153 + $result1 = $this->ktapi->create_folder(1, 'New test api folder');
  154 + $this->assertEqual($result1['status_code'], 1);
  155 +
  156 + // test with authentication
  157 + $result2 = $this->ktapi->create_folder(1, 'New test api folder', 'admin', 'admin', 'Testing API');
  158 + $folder_id = $result2['results']['id'];
  159 + $this->assertEqual($result2['status_code'], 0);
  160 +
  161 + // Create a sub folder
  162 + // test without authentication - should fail
  163 + $result3 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder');
  164 + $this->assertEqual($result3['status_code'], 1);
  165 +
  166 + // test with authentication
  167 + $result4 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder', 'admin', 'admin', 'Testing API');
  168 + $folder_id2 = $result4['results']['id'];
  169 + $this->assertEqual($result4['status_code'], 0);
  170 +
  171 + // Add a document
  172 + global $default;
  173 + $dir = $default->uploadDirectory;
  174 + $tempfilename = $this->createRandomFile('some text', $dir);
  175 +
  176 + // test without authentication - should fail
  177 + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename);
  178 + $this->assertEqual($doc['status_code'], 1);
  179 +
  180 + // test with authentication
  181 + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename,
  182 + 'admin', 'admin', 'Testing API');
  183 + $this->assertEqual($doc['status_code'], 0);
  184 + $doc_id = $doc['results']['document_id'];
  185 +
  186 + // Checkout the document
  187 + // test without authentication - should fail
  188 + $result1 = $this->ktapi->checkout_document($doc_id, 'Testing API', true);
  189 + $this->assertEqual($result1['status_code'], 1);
  190 +
  191 + // test with authentication
  192 + $result2 = $this->ktapi->checkout_document($doc_id, 'Testing API', true, 'admin', 'admin');
  193 + $this->assertEqual($doc['status_code'], 0);
  194 + $this->assertTrue(!empty($result2['results']));
  195 +
  196 + // Checkin the document
  197 + $dir = $default->uploadDirectory;
  198 + $tempfilename = $this->createRandomFile('some text', $dir);
  199 + // test without authentication - should fail
  200 + $result3 = $this->ktapi->checkin_document($doc_id, 'testdoc1.txt', 'Testing API', $tempfilename, false);
  201 + $this->assertEqual($result3['status_code'], 1);
  202 +
  203 + // test with authentication
  204 + $result4 = $this->ktapi->checkin_document($doc_id, 'testdoc1.txt', 'Testing API', $tempfilename, false, 'admin', 'admin');
  205 + $this->assertEqual($result4['status_code'], 0);
  206 + $this->assertEqual($result4['results']['document_id'], $doc_id);
  207 +
  208 + // Delete the document
  209 + // test without authentication - should fail
  210 + $result5 = $this->ktapi->delete_document($doc_id, 'Testing API');
  211 + $this->assertEqual($result5['status_code'], 1);
  212 +
  213 + // test with authentication
  214 + $result6 = $this->ktapi->delete_document($doc_id, 'Testing API', 'admin', 'admin', true);
  215 + $this->assertEqual($result6['status_code'], 0);
  216 +
  217 + // Clean up - delete the folder
  218 + // test without authentication - should fail
  219 + $result7 = $this->ktapi->delete_folder($folder_id, 'Testing API');
  220 + $this->assertEqual($result7['status_code'], 1);
  221 +
  222 + $result8 = $this->ktapi->delete_folder($folder_id, 'Testing API', 'admin', 'admin');
  223 + $this->assertEqual($result8['status_code'], 0);
  224 + }
  225 +
  226 + /**
  227 + * Helper function to create a document
  228 + */
  229 + function createDocument($title, $filename, $folder = null)
  230 + {
  231 + if(is_null($folder)){
  232 + $folder = $this->root;
  233 + }
  234 +
  235 + // Create a new document
  236 + $randomFile = $this->createRandomFile();
  237 + $this->assertTrue(is_file($randomFile));
  238 +
  239 + if ($this->esig_enabled)
  240 + {
  241 + $document = $folder->add_document($title, $filename, 'Default', $randomFile, 'admin', 'admin', 'Testing API');
  242 + }
  243 + else
  244 + {
  245 + $document = $folder->add_document($title, $filename, 'Default', $randomFile);
  246 + }
  247 + $this->assertNotError($document);
  248 +
  249 + @unlink($randomFile);
  250 + if(PEAR::isError($document)) return false;
  251 +
  252 + return $document;
  253 + }
  254 +
  255 + /**
  256 + * Helper function to delete docs
  257 + */
  258 + function deleteDocument($document)
  259 + {
  260 + $document->delete('Testing API');
  261 + $document->expunge();
  262 + }
  263 +
  264 + function createRandomFile($content = 'this is some text', $uploadDir = null) {
  265 + if(is_null($uploadDir)){
  266 + $uploadDir = dirname(__FILE__);
  267 + }
  268 + $temp = tempnam($uploadDir, 'myfile');
  269 + $fp = fopen($temp, 'wt');
  270 + fwrite($fp, $content);
  271 + fclose($fp);
  272 + return $temp;
  273 + }
  274 +}
  275 +?>
0 \ No newline at end of file 276 \ No newline at end of file
tests/runtests.php
@@ -8,6 +8,9 @@ class UnitTests extends TestSuite { @@ -8,6 +8,9 @@ class UnitTests extends TestSuite {
8 $this->TestSuite('Unit tests'); 8 $this->TestSuite('Unit tests');
9 9
10 // KTAPI 10 // KTAPI
  11 + // Some of these tests will fail if Electronic Signatures are enabled for the API.
  12 + // To fix, check the failing functions and add 'admin', 'admin' as username and password,
  13 + // and where necessary send 'Testing API' as a reason
11 $this->addFile('api/testApi.php'); 14 $this->addFile('api/testApi.php');
12 $this->addFile('api/testAuto.php'); 15 $this->addFile('api/testAuto.php');
13 $this->addFile('api/testSavedSearches.php'); 16 $this->addFile('api/testSavedSearches.php');
@@ -17,6 +20,8 @@ class UnitTests extends TestSuite { @@ -17,6 +20,8 @@ class UnitTests extends TestSuite {
17 $this->addFile('api/testFolder.php'); 20 $this->addFile('api/testFolder.php');
18 $this->addFile('api/testBulkActions.php'); 21 $this->addFile('api/testBulkActions.php');
19 $this->addFile('api/testCollection.php'); 22 $this->addFile('api/testCollection.php');
  23 + // Only activate this test if Electronic Signatures are enabled for the API
  24 +// $this->addFile('api/testElectronicSignatures.php');
20 25
21 // $this->addFile('SQLFile/test_sqlfile.php'); 26 // $this->addFile('SQLFile/test_sqlfile.php');
22 // $this->addFile('cache/testCache.php'); 27 // $this->addFile('cache/testCache.php');
@@ -28,9 +33,9 @@ class UnitTests extends TestSuite { @@ -28,9 +33,9 @@ class UnitTests extends TestSuite {
28 // $this->addFile('filelike/testStringFileLike.php'); 33 // $this->addFile('filelike/testStringFileLike.php');
29 34
30 // Search (2) and indexing 35 // Search (2) and indexing
31 - $this->addFile('documentProcessor/testExtracters.php');  
32 - $this->addFile('documentProcessor/testGuidInserter.php');  
33 - $this->addFile('search2/testSearch.php'); 36 +// $this->addFile('documentProcessor/testExtracters.php');
  37 +// $this->addFile('documentProcessor/testGuidInserter.php');
  38 +// $this->addFile('search2/testSearch.php');
34 } 39 }
35 } 40 }
36 41