Commit 13d376494938b26c355b4c07e061eb874c56e5b2

Authored by kevin_fourie
1 parent 9c84b55c

Merged in from DEV trunk...

KTS-2455
"Capitalise the U in "Bulk upload""
Fixed. Changed successfully to uppercase

Committed By:Yusuf Davids
Reviewed By:Jalaloedien Abrahams

KTS-2527
"Change the usage of 'search expression' and 'expression' to 'search criteria' and 'criteria' respectively when working with search."
Fixed.

Committed By: Conrad Vermeulen
Reviewed By: Kevin Fourie

KTS-2521
"No notifications when you are subscribed to a folder"
Fixed. Added notifications to the functions in document util. Refactored archive into documentutil. Added notifications to export.

Committed by: Megan Watson
Reviewed by: Conrad Vermeulen

KTS-673
"The search algorithm needs some work"
Updated. Parameters to command not passed correctly

Committed By: Conrad Vermeulen
Reviewed By: Kevin Fourie

KTS-673
"The search algorithm needs some work"
Updated. 

KTS-2514
"Indexing requirements is harsh currently as it requires all indexing issues to be resolved"
Fixed.

Committed By: Conrad Vermeulen
Reviewed By: Kevin Fourie

KTS-2525
"Create windows service to wrap around scheduler"
Updated. Modified service scripts.

Committed By: Kevin Fourie
Reviewed By: Conrad Vermeulen



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/STABLE/trunk@7446 c91229c3-7414-0410-bfa2-8a42b809f60b
bin/win32/installScheduler.php
1 1 <?php
2 2  
3   -$dir = realpath(dirname(__FILE__) . '/schedulerService.php');
  3 +$scriptPath = realpath(dirname(__FILE__) . '/schedulerService.php');
  4 +
  5 +// Setup php binary path
  6 +$phpPath = realpath('../../php/php.exe');
  7 +if (!is_file($phpPath))
  8 +{
  9 + die('Cannot find php.exe');
  10 +}
4 11  
5   -win32_create_service(array(
6   - 'service' => 'ktscheduler',
7   - 'display' => 'KnowledgeTree Scheduler Service',
8   - 'params' => $dir
9   - ));
  12 +win32_create_service(array(
  13 + 'service' => 'ktscheduler',
  14 + 'display' => 'ktdmsScheduler',
  15 + 'params' => $scriptPath,
  16 + 'path' => $phpPath
  17 + ));
10 18  
11   -?>
12 19 \ No newline at end of file
  20 +?>
... ...
bin/win32/schedulerService.php
1 1 <?php
2 2  
  3 +$myservicename = 'ktscheduler';
3 4  
4   -$dir = realpath(dirname(__FILE__) . '/..');
5   -chdir($dir);
  5 +// Connect to service dispatcher and notify that startup was successful
  6 +if (!win32_start_service_ctrl_dispatcher($myservicename)) die('Could not connect to service :'.$myservicename);
  7 +win32_set_service_status(WIN32_SERVICE_RUNNING);
6 8  
7   -$phpPath = realpath('../../../php/php.exe');
8   -if (!is_file($phpPath))
9   -{
10   - die('Cannot find php.exe');
11   -}
  9 +// Main Scheduler Service Loop
  10 +while (1) {
  11 +
  12 + switch (win32_get_last_control_message()) {
  13 +
  14 + case WIN32_SERVICE_CONTROL_CONTINUE: break; // Continue server routine
  15 + case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_NO_ERROR); break; // Respond with status
  16 + case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
  17 + default: win32_set_service_status(WIN32_ERROR_CALL_NOT_IMPLEMENTED); // Add more cases to handle other service calls
  18 + }
12 19  
  20 + // Change to knowledgeTree/bin folder
  21 + $dir = realpath(dirname(__FILE__) . '/..');
  22 + chdir($dir);
13 23  
14   - win32_start_service_ctrl_dispatcher('ktscheduler');
  24 + // Setup php binary path
  25 + $phpPath = realpath('../../php/php.exe');
  26 + if (!is_file($phpPath))
  27 + {
  28 + die('Cannot find php.exe');
  29 + }
  30 +
  31 + // Run the scheduler script
  32 + system("$phpPath scheduler.php");
15 33  
16   - while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message())
17   - {
18   - system("$phpPath scheduler.php");
19   - sleep(60);
20   - }
  34 + sleep(10); // Run every 10 seconds
  35 +
  36 +}
  37 +win32_set_service_status(WIN32_SERVICE_STOPPED);
21 38  
22   -?>
23 39 \ No newline at end of file
  40 +?>
... ...
lib/documentmanagement/documentutil.inc.php
... ... @@ -178,13 +178,52 @@ class KTDocumentUtil {
178 178 $oDocumentTransaction = new DocumentTransaction($oDocument, $sCheckoutComment, 'ktcore.transactions.check_out');
179 179 $oDocumentTransaction->create();
180 180  
181   - // fire subscription alerts for the checked in document
  181 + // fire subscription alerts for the downloaded document
182 182 $oSubscriptionEvent = new SubscriptionEvent();
183 183 $oFolder = Folder::get($oDocument->getFolderID());
184 184 $oSubscriptionEvent->CheckOutDocument($oDocument, $oFolder);
185 185  
186 186 return true;
187 187 }
  188 +
  189 + function archive($oDocument, $sReason) {
  190 +
  191 + $this->startTransaction();
  192 + $oDocument->setStatusID(ARCHIVED);
  193 + $res = $oDocument->update();
  194 +
  195 + if (PEAR::isError($res) || ($res === false)) {
  196 + return PEAR::raiseError(_kt('There was a database error while trying to archive this file'));
  197 + }
  198 +
  199 + $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $sReason), 'ktcore.transactions.update');
  200 + $oDocumentTransaction->create();
  201 +
  202 + $this->commitTransaction();
  203 +
  204 + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
  205 + $aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
  206 + foreach ($aTriggers as $aTrigger) {
  207 + $sTrigger = $aTrigger[0];
  208 + $oTrigger = new $sTrigger;
  209 + $aInfo = array(
  210 + 'document' => $oDocument,
  211 + );
  212 + $oTrigger->setInfo($aInfo);
  213 + $ret = $oTrigger->postValidate();
  214 + if (PEAR::isError($ret)) {
  215 + $oDocument->delete();
  216 + return $ret;
  217 + }
  218 + }
  219 +
  220 + // fire subscription alerts for the archived document
  221 + $oSubscriptionEvent = new SubscriptionEvent();
  222 + $oFolder = Folder::get($oDocument->getFolderID());
  223 + $oSubscriptionEvent->ArchivedDocument($oDocument, $oFolder);
  224 +
  225 + return true;
  226 + }
188 227  
189 228 function &_add($oFolder, $sFilename, $oUser, $aOptions) {
190 229 global $default;
... ... @@ -922,6 +961,11 @@ class KTDocumentUtil {
922 961 return $ret;
923 962 }
924 963 }
  964 +
  965 + // fire subscription alerts for the copied document
  966 + $oSubscriptionEvent = new SubscriptionEvent();
  967 + $oFolder = Folder::get($oDocument->getFolderID());
  968 + $oSubscriptionEvent->MoveDocument($oDocument, $oDestinationFolder, $oSrcFolder, 'CopiedDocument');
925 969  
926 970 return $oNewDocument;
927 971 }
... ... @@ -1027,6 +1071,10 @@ class KTDocumentUtil {
1027 1071 return $ret;
1028 1072 }
1029 1073 }
  1074 +
  1075 + // fire subscription alerts for the moved document
  1076 + $oSubscriptionEvent = new SubscriptionEvent();
  1077 + $oSubscriptionEvent->MoveDocument($oDocument, $oFolder, $oOriginalFolder);
1030 1078  
1031 1079 return KTPermissionUtil::updatePermissionLookup($oDocument);
1032 1080 }
... ...
lib/subscriptions/subscriptions.inc.php
... ... @@ -57,8 +57,10 @@ class SubscriptionEvent {
57 57 "CheckInDocument",
58 58 "CheckOutDocument",
59 59 "MovedDocument",
  60 + "CopiedDocument",
60 61 "ArchivedDocument",
61 62 "RestoredArchivedDocument",
  63 + "DownloadDocument",
62 64 );
63 65  
64 66 var $subscriptionTypes = array(
... ... @@ -480,82 +482,83 @@ class SubscriptionEvent {
480 482 }
481 483 }
482 484  
483   - function MoveDocument($oMovedDocument, $oToFolder, $oFromFolder) {
  485 + function MoveDocument($oMovedDocument, $oToFolder, $oFromFolder, $moveOrCopy = "MovedDocument") {
484 486 $content = new SubscriptionContent(); // needed for i18n
485   - // OK: two actions: document registrants, folder registrants.
  487 + // OK: two actions: document registrants, folder registrants.
486 488 $aUsers = $this->_getSubscribers($oMovedDocument->getId(), $this->subscriptionTypes["Document"]);
487   - $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
488   -
489   - foreach ($aUsers as $oSubscriber) {
490   - // notification object first.
491   - $aNotificationOptions = array();
492   - $aNotificationOptions['target_user'] = $oSubscriber->getID();
493   - $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
494   - $aNotificationOptions['target_name'] = $oMovedDocument->getName();
495   - $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oToFolder->getId());
496   - $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
497   - $aNotificationOptions['event_type'] = "MovedDocument";
498   - $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
499   -
500   - // now the email content.
501   - // FIXME this needs to be handled entirely within notifications from now on.
502   - if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
503   - $emailContent = $content->getEmailAlertContent($oNotification);
504   - $emailSubject = $content->getEmailAlertSubject($oNotification);
505   - $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
506   - $oEmail->send();
507   - }
508   - }
  489 + $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
  490 +
  491 + foreach ($aUsers as $oSubscriber) {
  492 + // notification object first.
  493 + $aNotificationOptions = array();
  494 + $aNotificationOptions['target_user'] = $oSubscriber->getID();
  495 + $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
  496 + $aNotificationOptions['target_name'] = $oMovedDocument->getName();
  497 + $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oToFolder->getId());
  498 + $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
  499 + $aNotificationOptions['event_type'] = $moveOrCopy;
  500 + $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
  501 +
  502 + // now the email content.
  503 + // FIXME this needs to be handled entirely within notifications from now on.
  504 + if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
  505 + $emailContent = $content->getEmailAlertContent($oNotification);
  506 + $emailSubject = $content->getEmailAlertSubject($oNotification);
  507 + $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
  508 + $oEmail->send();
  509 + }
  510 + }
509 511  
510 512  
511 513 $aUsers = $this->_getSubscribers($oFromFolder->getId(), $this->subscriptionTypes["Folder"]);
512   - $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
513   - foreach ($aUsers as $oSubscriber) {
514   -
515   - // notification object first.
516   - $aNotificationOptions = array();
517   - $aNotificationOptions['target_user'] = $oSubscriber->getID();
518   - $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
519   - $aNotificationOptions['target_name'] = $oMovedDocument->getName();
520   - $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oToFolder->getId());
521   - $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
522   - $aNotificationOptions['event_type'] = "MovedDocument";
523   - $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
524   -
525   - // now the email content.
526   - // FIXME this needs to be handled entirely within notifications from now on.
527   - if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
528   - $emailContent = $content->getEmailAlertContent($oNotification);
529   - $emailSubject = $content->getEmailAlertSubject($oNotification);
530   - $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
531   - $oEmail->send();
532   - }
533   - }
  514 + $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
  515 + foreach ($aUsers as $oSubscriber) {
  516 +
  517 + // notification object first.
  518 + $aNotificationOptions = array();
  519 + $aNotificationOptions['target_user'] = $oSubscriber->getID();
  520 + $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
  521 + $aNotificationOptions['target_name'] = $oMovedDocument->getName();
  522 + $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oToFolder->getId());
  523 + $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
  524 + $aNotificationOptions['event_type'] = $moveOrCopy;
  525 + $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
  526 +
  527 + // now the email content.
  528 + // FIXME this needs to be handled entirely within notifications from now on.
  529 + if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
  530 + $emailContent = $content->getEmailAlertContent($oNotification);
  531 + $emailSubject = $content->getEmailAlertSubject($oNotification);
  532 + $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
  533 + $oEmail->send();
  534 + }
  535 + }
534 536  
535 537 $aUsers = $this->_getSubscribers($oToFolder->getId(), $this->subscriptionTypes["Folder"]);
536   - $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
537   - foreach ($aUsers as $oSubscriber) {
538   -
539   - // notification object first.
540   - $aNotificationOptions = array();
541   - $aNotificationOptions['target_user'] = $oSubscriber->getID();
542   - $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
543   - $aNotificationOptions['target_name'] = $oMovedDocument->getName();
544   - $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oParentFolder->getId());
545   - $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
546   - $aNotificationOptions['event_type'] = "MovedDocument";
547   - $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
548   -
549   - // now the email content.
550   - // FIXME this needs to be handled entirely within notifications from now on.
551   - if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
552   - $emailContent = $content->getEmailAlertContent($oNotification);
553   - $emailSubject = $content->getEmailAlertSubject($oNotification);
554   - $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
555   - $oEmail->send();
556   - }
557   - }
  538 + $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
  539 + foreach ($aUsers as $oSubscriber) {
  540 +
  541 + // notification object first.
  542 + $aNotificationOptions = array();
  543 + $aNotificationOptions['target_user'] = $oSubscriber->getID();
  544 + $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
  545 + $aNotificationOptions['target_name'] = $oMovedDocument->getName();
  546 + $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oToFolder->getId());
  547 + $aNotificationOptions['object_id'] = $oToFolder->getId(); // parent folder_id, in this case.
  548 + $aNotificationOptions['event_type'] = $moveOrCopy;
  549 + $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
  550 +
  551 + // now the email content.
  552 + // FIXME this needs to be handled entirely within notifications from now on.
  553 + if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
  554 + $emailContent = $content->getEmailAlertContent($oNotification);
  555 + $emailSubject = $content->getEmailAlertSubject($oNotification);
  556 + $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
  557 + $oEmail->send();
  558 + }
  559 + }
558 560 }
  561 +
559 562 function ArchivedDocument($oModifiedDocument, $oParentFolder) {
560 563 $content = new SubscriptionContent(); // needed for i18n
561 564 // OK: two actions: document registrants, folder registrants.
... ... @@ -662,6 +665,59 @@ class SubscriptionEvent {
662 665 }
663 666 }
664 667  
  668 + function DownloadDocument($oDocument, $oParentFolder) {
  669 + $content = new SubscriptionContent(); // needed for i18n
  670 + // OK: two actions: document registrants, folder registrants.
  671 + $aUsers = $this->_getSubscribers($oDocument->getId(), $this->subscriptionTypes["Document"]);
  672 + $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
  673 + foreach ($aUsers as $oSubscriber) {
  674 +
  675 + // notification object first.
  676 + $aNotificationOptions = array();
  677 + $aNotificationOptions['target_user'] = $oSubscriber->getID();
  678 + $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
  679 + $aNotificationOptions['target_name'] = $oDocument->getName();
  680 + $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oParentFolder->getId());
  681 + $aNotificationOptions['object_id'] = $oDocument->getId(); // parent folder_id, in this case.
  682 + $aNotificationOptions['event_type'] = "DownloadDocument";
  683 + $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
  684 +
  685 + // now the email content.
  686 + // FIXME this needs to be handled entirely within notifications from now on.
  687 + if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
  688 + $emailContent = $content->getEmailAlertContent($oNotification);
  689 + $emailSubject = $content->getEmailAlertSubject($oNotification);
  690 + $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
  691 + $oEmail->send();
  692 + }
  693 + }
  694 +
  695 +
  696 + $aUsers = $this->_getSubscribers($oParentFolder->getId(), $this->subscriptionTypes["Folder"]);
  697 + $aUsers = $this->_pruneAlertedUsers($aUsers); // setup the alerted users. _might_ be a singleton.
  698 + foreach ($aUsers as $oSubscriber) {
  699 +
  700 + // notification object first.
  701 + $aNotificationOptions = array();
  702 + $aNotificationOptions['target_user'] = $oSubscriber->getID();
  703 + $aNotificationOptions['actor_id'] = KTUtil::arrayGet($_SESSION,"userID", null); // _won't_ be null.
  704 + $aNotificationOptions['target_name'] = $oDocument->getName();
  705 + $aNotificationOptions['location_name'] = Folder::generateFullFolderPath($oParentFolder->getId());
  706 + $aNotificationOptions['object_id'] = $oDocument->getId(); // parent folder_id, in this case.
  707 + $aNotificationOptions['event_type'] = "DownloadDocument";
  708 + $oNotification =& KTSubscriptionNotification::generateSubscriptionNotification($aNotificationOptions);
  709 +
  710 + // now the email content.
  711 + // FIXME this needs to be handled entirely within notifications from now on.
  712 + if ($oSubscriber->getEmailNotification() && (strlen($oSubscriber->getEmail()) > 0)) {
  713 + $emailContent = $content->getEmailAlertContent($oNotification);
  714 + $emailSubject = $content->getEmailAlertSubject($oNotification);
  715 + $oEmail = new EmailAlert($oSubscriber->getEmail(), $emailSubject, $emailContent);
  716 + $oEmail->send();
  717 + }
  718 + }
  719 + }
  720 +
665 721 // small helper function to assist in identifying the numeric id.
666 722 function _getKeyForType($sEventType) {
667 723 foreach ($this->eventTypes as $key => $val) {
... ... @@ -733,7 +789,9 @@ class SubscriptionContent {
733 789 "CheckInDocument" => _kt('Document checked in'),
734 790 "CheckOutDocument" => _kt('Document checked out'),
735 791 "MovedDocument" => _kt('Document moved'),
  792 + "CopiedDocument" => _kt('Document copied'),
736 793 "ArchivedDocument" => _kt('Document archived'), // can go through and request un-archival (?)
  794 + "DownloadDocument" => _kt('Document downloaded'),
737 795 "RestoredArchivedDocument" => _kt('Document restored'),
738 796 "DiscussDocument" => _kt('Document Discussions updated'),
739 797 );
... ... @@ -786,7 +844,9 @@ class SubscriptionContent {
786 844 "CheckInDocument" => 'document',
787 845 "CheckOutDocument" => 'document',
788 846 "MovedDocument" => 'document',
  847 + "CopiedDocument" => 'document',
789 848 "ArchivedDocument" => 'document', // can go through and request un-archival (?)
  849 + "DownloadDocument" => 'document',
790 850 "RestoredArchivedDocument" => 'document',
791 851 "DiscussDocument" => 'document');
792 852  
... ...
plugins/ktcore/KTBulkActions.php
... ... @@ -32,6 +32,7 @@
32 32 require_once(KT_LIB_DIR . '/actions/bulkaction.php');
33 33 require_once(KT_LIB_DIR . '/widgets/forms.inc.php');
34 34 require_once(KT_LIB_DIR . '/foldermanagement/compressionArchiveUtil.inc.php');
  35 +require_once(KT_LIB_DIR . '/subscriptions/Subscription.inc');
35 36  
36 37  
37 38 class KTBulkDeleteAction extends KTBulkAction {
... ... @@ -477,25 +478,14 @@ class KTBulkArchiveAction extends KTBulkAction {
477 478  
478 479 function perform_action($oEntity) {
479 480 if(is_a($oEntity, 'Document')) {
480   - DBUtil::startTransaction();
481   -
482   - $document = $oEntity;
483   -
484   - $document->setStatusID(ARCHIVED);
485   - $res = $document->update();
486   - if (($res === false) || PEAR::isError($res)) {
487   - DBUtil::rollback();
488   - return false;
  481 +
  482 + $res = KTDocumentUtil::archive($oEntity, $this->sReason);
  483 +
  484 + if(PEAR::isError($res)){
  485 + return $res;
489 486 }
490   -
491   - $oDocumentTransaction = & new DocumentTransaction($document, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update');
492   - $oDocumentTransaction->create();
493   -
494   - DBUtil::commit();
495 487 return true;
496 488 }else if(is_a($oEntity, 'Folder')) {
497   - DBUtil::startTransaction();
498   -
499 489 $aDocuments = array();
500 490 $aChildFolders = array();
501 491 $oFolder = $oEntity;
... ... @@ -520,7 +510,6 @@ class KTBulkArchiveAction extends KTBulkAction {
520 510 $sChildId = $oChild->getID();
521 511 $sChildDocs = $oChild->getDocumentIDs($sChildId);
522 512 if (PEAR::isError($res)) {
523   - DBUtil::rollback();
524 513 return false;
525 514 }
526 515  
... ... @@ -535,19 +524,14 @@ class KTBulkArchiveAction extends KTBulkAction {
535 524 if(!empty($aDocuments)){
536 525 foreach($aDocuments as $sDocumentId){
537 526 $oDocument = Document::get($sDocumentId);
538   -
539   - $oDocument->setStatusID(ARCHIVED);
540   - $res = $oDocument->update();
541   - if (($res === false) || PEAR::isError($res)) {
542   - DBUtil::rollback();
543   - return false;
  527 +
  528 + $res = KTDocumentUtil::archive($oEntity, $this->sReason);
  529 +
  530 + if(PEAR::isError($res)){
  531 + return $res;
544 532 }
545   -
546   - $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update');
547   - $oDocumentTransaction->create();
548 533 }
549 534 }
550   - DBUtil::commit();
551 535 return true;
552 536 }
553 537 }
... ... @@ -557,7 +541,8 @@ class KTBrowseBulkExportAction extends KTBulkAction {
557 541 var $sName = 'ktcore.actions.bulk.export';
558 542 var $_sPermission = 'ktcore.permissions.read';
559 543 var $_bMutator = true;
560   -
  544 + var $bNotifications = true;
  545 +
561 546 function getDisplayName() {
562 547 return _kt('Export');
563 548 }
... ... @@ -589,6 +574,8 @@ class KTBrowseBulkExportAction extends KTBulkAction {
589 574 $this->startTransaction();
590 575 $oKTConfig =& KTConfig::getSingleton();
591 576 $this->bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations");
  577 +
  578 + $this->bNotifications = ($oKTConfig->get('export/enablenotifications', 'on') == 'on') ? true : false;
592 579  
593 580 $result = parent::do_performaction();
594 581 $sExportCode = $this->oZip->createZipFile();
... ... @@ -634,6 +621,14 @@ class KTBrowseBulkExportAction extends KTBulkAction {
634 621 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array());
635 622 $oDocumentTransaction->create();
636 623 }
  624 +
  625 + // fire subscription alerts for the downloaded document - if global config is set
  626 + if($this->bNotifications){
  627 + $oSubscriptionEvent = new SubscriptionEvent();
  628 + $oFolder = Folder::get($oDocument->getFolderID());
  629 + $oSubscriptionEvent->DownloadDocument($oDocument, $oFolder);
  630 + }
  631 +
637 632 $this->oZip->addDocumentToZip($oDocument);
638 633  
639 634 }else if(is_a($oEntity, 'Folder')) {
... ... @@ -677,6 +672,14 @@ class KTBrowseBulkExportAction extends KTBulkAction {
677 672 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array());
678 673 $oDocumentTransaction->create();
679 674 }
  675 +
  676 + // fire subscription alerts for the downloaded document
  677 + if($this->bNotifications){
  678 + $oSubscriptionEvent = new SubscriptionEvent();
  679 + $oFolder = Folder::get($oDocument->getFolderID());
  680 + $oSubscriptionEvent->DownloadDocument($oDocument, $oFolder);
  681 + }
  682 +
680 683 $this->oZip->addDocumentToZip($oDocument);
681 684 }
682 685 }
... ...
plugins/ktcore/KTDocumentActions.php
... ... @@ -296,6 +296,16 @@ class KTDocumentViewAction extends KTDocumentAction {
296 296  
297 297 $oDocumentTransaction = & new DocumentTransaction($this->oDocument, _kt('Document downloaded'), 'ktcore.transactions.download', $aOptions);
298 298 $oDocumentTransaction->create();
  299 +
  300 + // fire subscription alerts for the downloaded document
  301 + $oKTConfig =& KTConfig::getSingleton();
  302 + $bNotifications = ($oKTConfig->get('export/enablenotifications', 'on') == 'on') ? true : false;
  303 + if($bNotifications){
  304 + $oSubscriptionEvent = new SubscriptionEvent();
  305 + $oFolder = Folder::get($this->oDocument->getFolderID());
  306 + $oSubscriptionEvent->DownloadDocument($this->oDocument, $oFolder);
  307 + }
  308 +
299 309 exit(0);
300 310 }
301 311 }
... ... @@ -1319,34 +1329,13 @@ class KTDocumentArchiveAction extends KTDocumentAction {
1319 1329  
1320 1330 $sReason = $data['reason'];
1321 1331  
1322   - $this->startTransaction();
1323   - $this->oDocument->setStatusID(ARCHIVED);
1324   - $res = $this->oDocument->update();
1325   - if (PEAR::isError($res) || ($res === false)) {
1326   - $_SESSION['KTErrorMessage'][] = _kt('There was a database error while trying to archive this file');
  1332 + $res = KTDocumentUtil::archive($this->oDocument, $sReason);
  1333 +
  1334 + if(PEAR::isError($res)){
  1335 + $_SESSION['KTErrorMessage'][] = $res->getMessage();
1327 1336 controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
1328 1337 exit(0);
1329 1338 }
1330   - $oDocumentTransaction = & new DocumentTransaction($this->oDocument, sprintf(_kt('Document archived: %s'), $sReason), 'ktcore.transactions.update');
1331   - $oDocumentTransaction->create();
1332   -
1333   - $this->commitTransaction();
1334   -
1335   - $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
1336   - $aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
1337   - foreach ($aTriggers as $aTrigger) {
1338   - $sTrigger = $aTrigger[0];
1339   - $oTrigger = new $sTrigger;
1340   - $aInfo = array(
1341   - 'document' => $this->oDocument,
1342   - );
1343   - $oTrigger->setInfo($aInfo);
1344   - $ret = $oTrigger->postValidate();
1345   - if (PEAR::isError($ret)) {
1346   - $this->oDocument->delete();
1347   - return $ret;
1348   - }
1349   - }
1350 1339  
1351 1340 $_SESSION['KTInfoMessage'][] = _kt('Document archived.');
1352 1341 controllerRedirect('browse', 'fFolderId=' . $this->oDocument->getFolderID());
... ...
plugins/ktcore/folder/BulkUpload.php
... ... @@ -46,7 +46,7 @@ class KTBulkUploadFolderAction extends KTFolderAction {
46 46 var $bAutomaticTransaction = true;
47 47  
48 48 function getDisplayName() {
49   - return _kt('Bulk upload');
  49 + return _kt('Bulk Upload');
50 50 }
51 51  
52 52 function check() {
... ... @@ -70,7 +70,7 @@ class KTBulkUploadFolderAction extends KTFolderAction {
70 70 $this->oPage->setBreadcrumbDetails(_kt("bulk upload"));
71 71 $oTemplate =& $this->oValidator->validateTemplate('ktcore/folder/bulkUpload');
72 72 $add_fields = array();
73   - $add_fields[] = new KTFileUploadWidget(_kt('Archive file'), _kt('The archive file containing the documents you wish to add to the document management system.'), 'file', "", $this->oPage, true);
  73 + $add_fields[] = new KTFileUploadWidget(_kt('Archive file'), _kt('The archive file containing the documents you wish to add to the document management system.'), 'file', "", $this->oPage, true, "file");
74 74  
75 75 $aVocab = array('' => _kt('- Please select a document type -'));
76 76 foreach (DocumentType::getListForUserAndFolder($this->oUser, $this->oFolder) as $oDocumentType) {
... ... @@ -126,10 +126,10 @@ class KTBulkUploadFolderAction extends KTFolderAction {
126 126 $bm =& new KTBulkImportManager($this->oFolder, $fs, $this->oUser, $aOptions);
127 127 $this->startTransaction();
128 128 $res = $bm->import();
129   - $aErrorOptions['message'] = _kt("Bulk upload failed");
  129 + $aErrorOptions['message'] = _kt("Bulk Upload failed");
130 130 $this->oValidator->notError($res, $aErrorOptions);
131 131  
132   - $this->addInfoMessage(_kt("Bulk upload successful"));
  132 + $this->addInfoMessage(_kt("Bulk Upload successful"));
133 133 $this->commitTransaction();
134 134 controllerRedirect("browse", 'fFolderId=' . $this->oFolder->getID());
135 135 exit(0);
... ...
plugins/ktstandard/KTBulkExportPlugin.php
... ... @@ -32,6 +32,7 @@
32 32 require_once(KT_LIB_DIR . '/plugins/plugin.inc.php');
33 33 require_once(KT_LIB_DIR . '/plugins/pluginregistry.inc.php');
34 34 require_once(KT_LIB_DIR . '/browse/browseutil.inc.php');
  35 +require_once(KT_LIB_DIR . '/subscriptions/Subscription.inc');
35 36  
36 37 require_once(KT_LIB_DIR . '/config/config.inc.php');
37 38 require_once(KT_LIB_DIR . '/foldermanagement/compressionArchiveUtil.inc.php');
... ... @@ -90,6 +91,7 @@ class KTBulkExportAction extends KTFolderAction {
90 91  
91 92 $oKTConfig =& KTConfig::getSingleton();
92 93 $bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations");
  94 + $bNotifications = ($oKTConfig->get('export/enablenotifications', 'on') == 'on') ? true : false;
93 95  
94 96 // Redirect if there are no documents and no folders to export
95 97 if (empty($aDocumentIds) && empty($aFolderList)) {
... ... @@ -112,6 +114,13 @@ class KTBulkExportAction extends KTFolderAction {
112 114 $oDocumentTransaction->create();
113 115 }
114 116  
  117 + // fire subscription alerts for the downloaded document
  118 + if($bNotifications){
  119 + $oSubscriptionEvent = new SubscriptionEvent();
  120 + $oFolder = Folder::get($oDocument->getFolderID());
  121 + $oSubscriptionEvent->DownloadDocument($oDocument, $oFolder);
  122 + }
  123 +
115 124 $this->oZip->addDocumentToZip($oDocument);
116 125 }
117 126 }
... ...
search2/indexing/extractorCore.inc.php
... ... @@ -408,7 +408,7 @@ abstract class ApplicationExtractor extends ExternalDocumentExtractor
408 408 {
409 409 $sources = array('{source}','{target}');
410 410 $target = array($this->sourcefile, $this->targetfile);
411   - $cmdline = $this->command . ' ' . str_replace($sources,$target, $params);
  411 + $cmdline = $this->command . ' ' . str_replace($sources,$target, $this->params);
412 412  
413 413 return $cmdline;
414 414 }
... ...
search2/indexing/indexerCore.inc.php
... ... @@ -252,6 +252,8 @@ abstract class Indexer
252 252 */
253 253 private $hookPath;
254 254  
  255 + private $enabledExtractors;
  256 +
255 257 /**
256 258 * Initialise the indexer
257 259 *
... ... @@ -267,6 +269,29 @@ abstract class Indexer
267 269  
268 270 $this->extractorPath = $config->get('indexer/extractorPath', 'extractors');
269 271 $this->hookPath = $config->get('indexer/extractorHookPath','extractorHooks');
  272 +
  273 +
  274 + $this->loadExtractorStatus();
  275 + }
  276 +
  277 + /**
  278 + * Get the list if enabled extractors
  279 + *
  280 + */
  281 + private function loadExtractorStatus()
  282 + {
  283 + $sql = "SELECT id, name FROM mime_extractors WHERE active=1";
  284 + $rs = DBUtil::getResultArray($sql);
  285 + $this->enabledExtractors = array();
  286 + foreach($rs as $item)
  287 + {
  288 + $this->enabledExtractors[] = $item['name'];
  289 + }
  290 + }
  291 +
  292 + private function isExtractorEnabled($extractor)
  293 + {
  294 + return in_array($extractor, $this->enabledExtractors);
270 295 }
271 296  
272 297 /**
... ... @@ -599,6 +624,7 @@ abstract class Indexer
599 624 {
600 625 global $default;
601 626  
  627 + $default->log->info('indexDocuments: start');
602 628 if (!$this->doesDiagnosticsPass())
603 629 {
604 630 return;
... ... @@ -618,13 +644,14 @@ abstract class Indexer
618 644 // identify the indexers that must run
619 645 // mysql specific limit!
620 646 $sql = "SELECT
621   - iff.document_id, mt.filetypes, mt.mimetypes, mt.extractor, iff.what
  647 + iff.document_id, mt.filetypes, mt.mimetypes, me.name as extractor, iff.what
622 648 FROM
623 649 index_files iff
624 650 INNER JOIN documents d ON iff.document_id=d.id
625 651 INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id
626 652 INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id
627 653 INNER JOIN mime_types mt ON dcv.mime_id=mt.id
  654 + INNER JOIN mime_extractors me ON mt.extractor_id=me.id
628 655 WHERE
629 656 (iff.processdate IS NULL or iff.processdate < cast(cast('$date' as date) -1 as date)) AND dmv.status_id=1
630 657 ORDER BY indexdate
... ... @@ -674,6 +701,12 @@ abstract class Indexer
674 701 $default->log->debug(sprintf(_kt("Indexing docid: %d extension: '%s' mimetype: '%s' extractor: '%s'"), $docId, $extension,$mimeType,$extractorClass));
675 702 }
676 703  
  704 + if (!$this->isExtractorEnabled($extractorClass))
  705 + {
  706 + $default->log->info(sprintf(_kt("diagnose: Not indexing docid: %d because extractor '%s' is disabled."), $docId, $extractorClass));
  707 + continue;
  708 + }
  709 +
677 710 if (empty($extractorClass))
678 711 {
679 712 if ($this->debug)
... ... @@ -835,10 +868,7 @@ abstract class Indexer
835 868 }
836 869  
837 870 }
838   - if ($this->debug)
839   - {
840   - $default->log->debug(_kt("Done."));
841   - }
  871 + $default->log->info('indexDocuments: done');
842 872 }
843 873  
844 874 public function migrateDocuments($max=null)
... ... @@ -1032,6 +1062,12 @@ abstract class Indexer
1032 1062 continue;
1033 1063 }
1034 1064  
  1065 + if (!$this->isExtractorEnabled($class))
  1066 + {
  1067 + $default->log->info(sprintf(_kt("diagnose: extractor '%s' is disabled."), $class));
  1068 + continue;
  1069 + }
  1070 +
1035 1071 $extractor = new $class();
1036 1072 if (!is_a($extractor, $baseclass))
1037 1073 {
... ...
templates/ktcore/search2/adv_query_builder.smarty
... ... @@ -3,7 +3,6 @@
3 3 {$context->oPage->requireJSResource("thirdpartyjs/extjs/adapter/ext/ext-base.js")}
4 4 {$context->oPage->requireJSResource("thirdpartyjs/extjs/ext-all.js")}
5 5  
6   -<h2>{i18n}Advanced Search{/i18n}</h2>
7 6  
8 7 {literal}
9 8 <style>
... ... @@ -765,7 +764,7 @@ function butSearchClick()
765 764 {/literal}
766 765  
767 766 <fieldset>
768   - <legend>{i18n}Metadata Query{/i18n}</legend>
  767 + <legend>{i18n}Advanced Search{/i18n}</legend>
769 768  
770 769  
771 770 {capture assign=options}
... ... @@ -800,7 +799,7 @@ function butSearchClick()
800 799 <tr>
801 800 <td width="50%" valign="top">
802 801 <br>
803   - <div id="criteria_nofields0" style="color: brown">{i18n}No fields have been selected for the criteria group.{/i18n}
  802 + <div id="criteria_nofields0" style="color: brown">{i18n}No criteria have been selected for the criteria group.{/i18n}
804 803 <p>
805 804 <input type=button value="{i18n}Remove Criteria Group{/i18n}" onclick="removeCriteriaGroup(0)" id="removeCriteriaGroup0" style="display: none">
806 805 </div>
... ... @@ -813,14 +812,14 @@ function butSearchClick()
813 812 <tr>
814 813 <td valign=top>
815 814 <select id="selector0" style="width: 200px" onchange="selectorChange(0)">
816   - <option value="0">{i18n}Available Fields{/i18n}
  815 + <option value="0">{i18n}Available Criteria{/i18n}
817 816 <option value="1">{i18n}Available Fieldsets{/i18n}
818 817 <option value="2">{i18n}Available Workflows{/i18n}
819 818 </select>
820 819 <br>
821 820 <div>
822 821 <select id="fields0" size="5" style="width: 200px; height: 100px; display: block" onclick="fieldChange(0)">
823   - <option value="" selected>--- {i18n}Select a field{/i18n} ---
  822 + <option value="" selected>--- {i18n}Select some criteria{/i18n} ---
824 823 {foreach from=$metainfo.fields item=field}
825 824 <option>{$field.display}
826 825 {/foreach}
... ...
templates/ktcore/search2/manage_saved_search.smarty
1   -<h2>{i18n}Manage Saved Searches{/i18n}</h2>
  1 +<h2>{i18n}Manage Saved Search Criteria{/i18n}</h2>
2 2  
3   -<p class="descriptiveText">{i18n}Saved searches are searches which are particular to your location
4   -For example, you could define a search which returns all documents in a particular workflow state,
  3 +<p class="descriptiveText">{i18n}Saved search criteria are criteria that are particular to your location.
  4 +For example, you could define criteria that returns all documents in a particular workflow state,
5 5 or all documents which are considered "common" within your organisation (leave policy,
6 6 newsletters, etc.) based on a category or fieldset value.{/i18n}</p>
7 7  
8 8  
9 9 <p class="descriptiveText">
10 10 {capture assign=options}
11   -<a href="{addQS}action=guiBuilder{/addQS}">{i18n}Advanced Search{/i18n}</a> {i18n}or{/i18n} <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Query Editor{/i18n}</a>
  11 +<a href="{addQS}action=guiBuilder{/addQS}">{i18n}Advanced Search{/i18n}</a> {i18n}or{/i18n} <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Search Critiera Editor{/i18n}</a>
12 12 {/capture}
13 13  
14 14  
... ... @@ -18,12 +18,12 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}&lt;/p&gt;
18 18  
19 19  
20 20 {if $saved}
21   -<h2>{i18n}Existing Searches{/i18n}</h2>
  21 +<h2>{i18n}Existing Saved Search Criteria{/i18n}</h2>
22 22  
23 23 <table class="listing">
24 24 <thead>
25 25 <tr>
26   - <th>{i18n}Search Name{/i18n}</th>
  26 + <th>{i18n}Name{/i18n}</th>
27 27 <th>{i18n}User{/i18n}</th>
28 28 <th>{i18n}Edit{/i18n}</th>
29 29 <th>{i18n}Delete{/i18n}</th>
... ...
templates/ktcore/search2/search_portlet.smarty
... ... @@ -10,7 +10,8 @@
10 10 </div>
11 11 <ul class="actionlist">
12 12 <li><a href="{$rootUrl}/search2.php?action=guiBuilder">{i18n}Advanced Search{/i18n}</a></li>
13   -<li><a href="{$rootUrl}/search2.php?action=manage">{i18n}Manage Saved Search{/i18n}</a></li>
  13 +<li><a href="{$rootUrl}/search2.php?action=queryBuilder">{i18n}Search Criteria Editor{/i18n}</a></li>
  14 +<li><a href="{$rootUrl}/search2.php?action=manage"><nobr>{i18n}Manage Saved Search Criteria{/i18n}</a></li>
14 15 </ul>
15 16  
16 17 {if (count($savedSearches) > 0)}
... ...
templates/ktcore/search2/search_results.smarty
... ... @@ -2,35 +2,35 @@
2 2 {$context->oPage->requireJSResource('resources/js/toggleselect.js')}
3 3  
4 4 <div class="collapsible">
5   -<h4 onclick="toggleElementClass('expanded', this.parentNode)">{i18n}Search Expression{/i18n}</h4>
  5 +<h4 onclick="toggleElementClass('expanded', this.parentNode)">{i18n}Search Criteria{/i18n}</h4>
6 6 <div class="collapsiblebody">
7 7 <fieldset>
8   - <legend>{i18n}Search Expression{/i18n}</legend>
  8 + <legend>{i18n}Search Criteria{/i18n}</legend>
9 9 {$txtQuery}
10 10 <br>
11 11 {if empty($iSavedID)}
12 12 {capture assign=options}
13   - <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Query Editor{/i18n}</a>
  13 + <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Search Critieria Editor{/i18n}</a>
14 14 {/capture}
15   - {i18n arg_options=$options}Use the #options# to extend this query.{/i18n}
  15 + {i18n arg_options=$options}Use the #options# to extend your search criteria.{/i18n}
16 16 {/if}
17 17 {if !empty($iSavedID)}
18 18 {capture assign=options}
19 19 <a href="{addQS}action=queryBuilder&fSavedSearchId={$iSavedID}{/addQS}">Query Editor</a>
20 20 {/capture}
21   - {i18n arg_options=$options}To edit the search expression, use the #options#.{/i18n}
  21 + {i18n arg_options=$options}To edit the search criteria, use the #options#.{/i18n}
22 22 {/if}
23   - <font color=brown><div id="savedSearch" style="display: none">{i18n}The search has been saved.{/i18n}</div></font>
  23 + <font color=brown><div id="savedSearch" style="display: none">{i18n}The search criteria has been saved.{/i18n}</div></font>
24 24 </fieldset>
25 25 <br>
26 26 {if !empty($iSavedID)}
27 27 <fieldset>
28 28 <legend>{i18n}Saved Search{/i18n}</legend>
29   - {i18n}This is the saved search:{/i18n} {$txtSavedName}. <br/>
  29 + {i18n}This is the saved search criteria:{/i18n} {$txtSavedName}. <br/>
30 30 {capture assign=options}
31   - <a href="{addQS}action=manage{/addQS}">{i18n}Manage Saved Searches{/i18n}</a>
  31 + <a href="{addQS}action=manage{/addQS}">{i18n}Manage Saved Search Criteria{/i18n}</a>
32 32 {/capture}
33   - {i18n arg_options=$options}To delete this saved search or edit other saved search expressions, #options#.{/i18n}
  33 + {i18n arg_options=$options}To delete this saved search criteria or to edit other saved search criteria, #options#.{/i18n}
34 34 </fieldset>
35 35 {/if}
36 36 {literal}
... ... @@ -117,11 +117,11 @@ function onShowAll(showall)
117 117  
118 118 {if $numResults == 0}
119 119  
120   - {i18n}There are no search results matching your search query.{/i18n}
  120 + {i18n}There are no search results matching your search criteria.{/i18n}
121 121  
122 122 <p>
123 123 {capture assign=options}
124   - <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Query Editor{/i18n}</a>
  124 + <a href="{addQS}action=queryBuilder{/addQS}">{i18n}Search Criteria Editor{/i18n}</a>
125 125 {/capture}
126 126  
127 127 {i18n arg_options=$options}Use the #options# to extend this query.{/i18n}
... ...