Commit 53fec10811a1ff05c01a96c787e616138d961e47

Authored by kevin_fourie
1 parent ec35c4fa

Merged in...

KTC-621
"Deleting a folder causes the error: PEAR_Error::getSymbolicLinks()"
Fixed. Moved the loop to get the symbolic links above the code to delete the folder.

KTS-3774
"Although 'Action Restrictions' for 'Archive' is set the user can still 'Archive' the document via the bulk actions when in folder view."
Fixed. Added a check for workflow before doing the archive.

KTS-3758
"When attempting to Archive a folder that contains no documents the Status is given as being 'Non-numeric identifier'"
Fixed. Added a check around explode($sDocuments) to create an empty array if $sDocuments is empty otherwise it creates an array containing an empty array which is not seen as empty.

KTS-3780
"When cancelling / returning from a bulk action in the tag cloud search the user is taken to the browse page"
Fixed. Changed the return action to contain the full link. Added a default in getReturnUrl() in bulk action to use the full url.

KTS-3757
"After a Bulk action was performed on folders in the Search results pane/view the user is returned to the original view where the folders search is shown in its previous state."
Fixed. On completing the bulk action the return url calls refresh which repeats the search.

KTS-3759
"When the user does not select a folder or documenton the search result view and uses any of the Bulk Actions he is returned to the Root fodler view."
Fixed. It now builds the return url based on the request parameters.

KTS-3764
"Items in admin section registered more than once."
Fixed. Added a lock around the plugin registration (reread) to prevent a race condition.

Committed by: Megan Watson
Reviewed by: Conrad Vermeulen



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/STABLE/branches/3.5.4-Release-Branch@9476 c91229c3-7414-0410-bfa2-8a42b809f60b
action.php
... ... @@ -6,31 +6,31 @@
6 6 * Document Management Made Simple
7 7 * Copyright (C) 2008 KnowledgeTree Inc.
8 8 * Portions copyright The Jam Warehouse Software (Pty) Limited
9   - *
  9 + *
10 10 * This program is free software; you can redistribute it and/or modify it under
11 11 * the terms of the GNU General Public License version 3 as published by the
12 12 * Free Software Foundation.
13   - *
  13 + *
14 14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 17 * details.
18   - *
  18 + *
19 19 * You should have received a copy of the GNU General Public License
20 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21   - *
22   - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
  21 + *
  22 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
23 23 * California 94120-7775, or email info@knowledgetree.com.
24   - *
  24 + *
25 25 * The interactive user interfaces in modified source and object code versions
26 26 * of this program must display Appropriate Legal Notices, as required under
27 27 * Section 5 of the GNU General Public License version 3.
28   - *
  28 + *
29 29 * In accordance with Section 7(b) of the GNU General Public License version 3,
30 30 * these Appropriate Legal Notices must retain the display of the "Powered by
31   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  31 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
32 32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
33   - * must display the words "Powered by KnowledgeTree" and retain the original
  33 + * must display the words "Powered by KnowledgeTree" and retain the original
34 34 * copyright notice.
35 35 * Contributor( s): ______________________________________
36 36 *
... ... @@ -85,6 +85,42 @@ class KTActionDispatcher extends KTStandardDispatcher {
85 85 return $this->do_main();
86 86 }
87 87  
  88 + function getBulkReturnUrl(){
  89 + $sReturnAction = $_REQUEST['fReturnAction'];
  90 + $sReturnData = $_REQUEST['fReturnData'];
  91 + $sAction = 'main';
  92 + $qs = '';
  93 +
  94 + switch ($sReturnAction){
  95 + case 'browse':
  96 + $sReturnData = (empty($sReturnData)) ? $_REQUEST['fFolderId'] : $sReturnData;
  97 + $sTargetUrl = KTBrowseUtil::getUrlForFolder(Folder::get($sReturnData));
  98 + break;
  99 + case 'simpleSearch':
  100 + $sTargetUrl = KTBrowseUtil::getSimpleSearchBaseUrl();
  101 + $extra = 'fSearchableText='.$sReturnData;
  102 + break;
  103 + case 'booleanSearch':
  104 + $sTargetUrl = KTBrowseUtil::getBooleanSearchBaseUrl();
  105 + $sAction = 'performSearch';
  106 + $extra = 'boolean_search_id='.$sReturnData;
  107 + break;
  108 + case 'search2':
  109 + $sTargetUrl = KTBrowseUtil::getSearchResultURL();
  110 + $sAction = 'searchResults';
  111 + break;
  112 + default:
  113 + $sTargetUrl = $sReturnAction;
  114 + $sAction = '';
  115 + }
  116 +
  117 + $qs = (!empty($sAction))? 'action='.$sAction : '';
  118 + $qs .= (!empty($extra))? '&'.$extra : '';
  119 + $sTargetUrl = KTUtil::addQueryString($sTargetUrl, $qs);
  120 +
  121 + return $sTargetUrl;
  122 + }
  123 +
88 124 function do_bulkaction() {
89 125 $act = (array) KTUtil::arrayGet($_REQUEST, 'submit',null);
90 126  
... ... @@ -101,11 +137,23 @@ class KTActionDispatcher extends KTStandardDispatcher {
101 137  
102 138 $oFolder = Folder::get(KTUtil::arrayGet($_REQUEST, 'fFolderId', 1));
103 139 if (PEAR::isError($oFolder)) {
  140 + $redirectUrl = $this->getBulkReturnUrl();
  141 + if(!empty($redirectUrl)){
  142 + $this->addErrorMessage(_kt('Invalid folder selected.'));
  143 + redirect($redirectUrl);
  144 + exit(0);
  145 + }
104 146 $this->errorRedirectToBrowse(_kt('Invalid folder selected.'));
105 147 exit(0);
106 148 }
107 149  
108 150 if (empty($aFolderSelection) && empty($aDocumentSelection)) {
  151 + $redirectUrl = $this->getBulkReturnUrl();
  152 + if(!empty($redirectUrl)){
  153 + $this->addErrorMessage(_kt('Please select documents or folders first.'));
  154 + redirect($redirectUrl);
  155 + exit(0);
  156 + }
109 157 $this->errorRedirectToBrowse(_kt('Please select documents or folders first.'), sprintf('fFolderId=%d', $oFolder->getId()));
110 158 exit(0);
111 159 }
... ...
lib/actions/bulkaction.php
... ... @@ -430,9 +430,12 @@ class KTBulkAction extends KTStandardDispatcher {
430 430 $sTargetUrl = KTBrowseUtil::getSearchResultURL();
431 431 $sAction = 'searchResults';
432 432 break;
  433 + default:
  434 + $sTargetUrl = $sReturnAction;
  435 + $sAction = '';
433 436 }
434 437  
435   - $qs = 'action='.$sAction;
  438 + $qs = (!empty($sAction))? 'action='.$sAction : '';
436 439 $qs .= (!empty($extra))? '&'.$extra : '';
437 440 $sTargetUrl = KTUtil::addQueryString($sTargetUrl, $qs);
438 441  
... ... @@ -489,7 +492,7 @@ class KTBulkAction extends KTStandardDispatcher {
489 492 break;
490 493 case 'search2':
491 494 $sTargetUrl = KTBrowseUtil::getSearchResultURL();
492   - $sAction = 'searchResults';
  495 + $sAction = 'refresh';
493 496 break;
494 497 }
495 498  
... ...
lib/documentmanagement/documentutil.inc.php
... ... @@ -194,6 +194,11 @@ class KTDocumentUtil {
194 194 return PEAR::raiseError(_kt('There was a database error while trying to archive this file'));
195 195 }
196 196  
  197 + // Ensure the action is not blocked
  198 + if(!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.archive')){
  199 + return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.'));
  200 + }
  201 +
197 202 //delete all shortcuts linking to this document
198 203 $aSymlinks = $oDocument->getSymbolicLinks();
199 204 foreach($aSymlinks as $aSymlink){
... ...
lib/foldermanagement/folderutil.inc.php
... ... @@ -8,31 +8,31 @@
8 8 * Document Management Made Simple
9 9 * Copyright (C) 2008 KnowledgeTree Inc.
10 10 * Portions copyright The Jam Warehouse Software (Pty) Limited
11   - *
  11 + *
12 12 * This program is free software; you can redistribute it and/or modify it under
13 13 * the terms of the GNU General Public License version 3 as published by the
14 14 * Free Software Foundation.
15   - *
  15 + *
16 16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 19 * details.
20   - *
  20 + *
21 21 * You should have received a copy of the GNU General Public License
22 22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23   - *
24   - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
  23 + *
  24 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
25 25 * California 94120-7775, or email info@knowledgetree.com.
26   - *
  26 + *
27 27 * The interactive user interfaces in modified source and object code versions
28 28 * of this program must display Appropriate Legal Notices, as required under
29 29 * Section 5 of the GNU General Public License version 3.
30   - *
  30 + *
31 31 * In accordance with Section 7(b) of the GNU General Public License version 3,
32 32 * these Appropriate Legal Notices must retain the display of the "Powered by
33   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  33 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
34 34 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
35   - * must display the words "Powered by KnowledgeTree" and retain the original
  35 + * must display the words "Powered by KnowledgeTree" and retain the original
36 36 * copyright notice.
37 37 * Contributor( s): ______________________________________
38 38 */
... ... @@ -392,6 +392,14 @@ class KTFolderUtil {
392 392 $oStorage =& KTStorageManagerUtil::getSingleton();
393 393 $oStorage->removeFolderTree($oStartFolder);
394 394  
  395 + // Check for symbolic links to the folder and its sub folders
  396 + $aSymlinks = array();
  397 + foreach($aFolderIds as $iFolder){
  398 + $oFolder = Folder::get($iFolder);
  399 + $aLinks = $oFolder->getSymbolicLinks();
  400 + array_merge($aSymlinks, $aLinks);
  401 + }
  402 +
395 403 // documents all cleared.
396 404 $sQuery = 'DELETE FROM ' . KTUtil::getTableName('folders') . ' WHERE id IN (' . DBUtil::paramArray($aFolderIds) . ')';
397 405 $aParams = $aFolderIds;
... ... @@ -402,17 +410,22 @@ class KTFolderUtil {
402 410 DBUtil::rollback();
403 411 return PEAR::raiseError(_kt('Failure deleting folders.'));
404 412 }
405   -
406   - //delete all folder shortcuts
407   - foreach($aFolderIds as $iFolder){
408   - $oFolder = Folder::get($iFolder);
409   - $aSymlinks = $oFolder->getSymbolicLinks();
410   -
411   - foreach($aSymlinks as $aSymlink){
412   - KTFolderUtil::deleteSymbolicLink($aSymlink['id']);
413   - }
  413 +
  414 + // now that the folder has been deleted we delete all the shortcuts
  415 + if(!empty($aSymlinks)){
  416 + $links = array();
  417 + foreach($aSymlinks as $link){
  418 + $links[] = $link['id'];
  419 + }
  420 + $linkIds = implode(',', $links);
  421 +
  422 + $query = "DELETE FROM folders WHERE id IN ($linkIds)";
  423 + }
  424 +
  425 + foreach($aSymlinks as $aSymlink){
  426 + KTFolderUtil::deleteSymbolicLink($aSymlink['id']);
414 427 }
415   -
  428 +
416 429 // purge caches
417 430 KTEntityUtil::clearAllCaches('Folder');
418 431  
... ... @@ -584,7 +597,7 @@ class KTFolderUtil {
584 597  
585 598 return true;
586 599 }
587   -
  600 +
588 601 /**
589 602 * Create a symbolic link in the target folder
590 603 *
... ... @@ -634,7 +647,7 @@ class KTFolderUtil {
634 647 return PEAR::raiseError(_kt('You\'re not authorized to create a shortcut to this folder'));
635 648 }
636 649 }
637   -
  650 +
638 651 //check if the shortcut doesn't already exists in the target folder
639 652 $aSymlinks = $sourceFolder->getSymbolicLinks();
640 653 foreach($aSymlinks as $iSymlink){
... ... @@ -643,7 +656,7 @@ class KTFolderUtil {
643 656 return PEAR::raiseError(_kt('There already is a shortcut to this folder in the target folder.'));
644 657 }
645 658 }
646   -
  659 +
647 660 //Create the link
648 661 $oSymlink = Folder::createFromArray(array(
649 662 'iParentID' => $targetFolder->getId(),
... ... @@ -677,7 +690,7 @@ class KTFolderUtil {
677 690 }
678 691 if (!$folder->isSymbolicLink())
679 692 {
680   - return PEAR::raiseError(_kt('Focument must be a symbolic link entity'));
  693 + return PEAR::raiseError(_kt('Folder must be a symbolic link entity'));
681 694 }
682 695 if (is_null($user))
683 696 {
... ... @@ -692,17 +705,17 @@ class KTFolderUtil {
692 705 $oPerm = KTPermission::getByName('ktcore.permissions.delete');
693 706 if (!KTBrowseUtil::inAdminMode($user, $folder)) {
694 707 if(!KTPermissionUtil::userHasPermissionOnItem($user, $oPerm, $folder)){
695   - return PEAR::raiseError(_kt('You\'re not authorized to create shortcuts'));
  708 + return PEAR::raiseError(_kt('You\'re not authorized to delete shortcuts'));
696 709 }
697 710 }
698   -
  711 +
699 712 // we only need to delete the folder entry for the link
700 713 $sql = "DELETE FROM folders WHERE id=?";
701 714 DBUtil::runQuery(array($sql, array($folder->getId())));
702 715  
703 716 }
704   -
705   -
  717 +
  718 +
706 719 }
707 720  
708 721 ?>
... ...
lib/plugins/pluginutil.inc.php
... ... @@ -475,6 +475,64 @@ class KTPluginUtil {
475 475 * This is called by the 'Re-read plugins' action in the web interface.
476 476 */
477 477 function registerPlugins () {
  478 + global $default;
  479 +
  480 + // Path to lock file
  481 + $cacheDir = $default->cacheDirectory . DIRECTORY_SEPARATOR;
  482 + $lockFile = $cacheDir.'plugin_register.lock';
  483 +
  484 + // Check if the lock file exists
  485 + if(KTPluginUtil::doCheck($lockFile)){
  486 + return true;
  487 + }
  488 +
  489 + // Create the lock file, run through the plugin registration and then delete the lock file
  490 + touch($lockFile);
  491 + KTPluginUtil::doPluginRegistration();
  492 + @unlink($lockFile);
  493 + }
  494 +
  495 + /**
  496 + * Check the lockfile
  497 + */
  498 + function doCheck($lockFile)
  499 + {
  500 + if(file_exists($lockFile)){
  501 + // If it does exist, do a stat on it to check when it was created.
  502 + // if it was accessed more than 5 minutes ago then delete it and proceed with the plugin registration
  503 + // otherwise wait till lock file is deleted signalling that the registration is complete and return.
  504 +
  505 + $stat = stat($lockFile);
  506 +
  507 + $time = time() - (60 * 5);
  508 + if($stat['mtime'] > $time){
  509 +
  510 + $cnt = 0;
  511 +
  512 + while(file_exists($lockFile)){
  513 + $cnt++;
  514 + sleep(2);
  515 +
  516 + // if we've been waiting too long - typically it should only take a few seconds so 2 mins is too much time.
  517 + if($cnt > 60){
  518 + @unlink($lockFile);
  519 + return false;
  520 + }
  521 + }
  522 + return true;
  523 + }
  524 + @unlink($lockFile);
  525 + }
  526 + return false;
  527 + }
  528 +
  529 + /**
  530 + * Read the plugins directory and register all plugins in the database.
  531 + */
  532 + function doPluginRegistration()
  533 + {
  534 + global $default;
  535 +
478 536 KTPluginUtil::_deleteSmartyFiles();
479 537 require_once(KT_LIB_DIR . '/cache/cache.inc.php');
480 538 $oCache =& KTCache::getSingleton();
... ... @@ -493,7 +551,6 @@ class KTPluginUtil {
493 551 }
494 552 }
495 553  
496   - global $default;
497 554 $oRegistry =& KTPluginRegistry::getSingleton();
498 555 $aRegistryList = $oRegistry->getPlugins();
499 556 foreach ($aRegistryList as $oPlugin) {
... ...
plugins/ktcore/KTBulkActions.php
... ... @@ -103,13 +103,15 @@ class KTBulkDeleteAction extends KTBulkAction {
103 103 * @return KTForm the form
104 104 */
105 105 function form_confirm() {
  106 + $cancelUrl = $this->getReturnUrl();
  107 +
106 108 $oForm = new KTForm;
107 109 $oForm->setOptions(array(
108 110 'label' => _kt('Are you sure?'),
109 111 'description' => _kt('There are shortcuts linking to some of the documents or folders in your selection; continuing will automatically delete the shortcuts. Would you like to continue?'),
110 112 'action' => 'collectinfo',
111 113 'fail_action' => 'main',
112   - 'cancel_url' => KTBrowseUtil::getUrlForFolder($this->oFolder),
  114 + 'cancel_url' => $cancelUrl,
113 115 'submit_label' => _kt('Continue'),
114 116 'context' => $this,
115 117 ));
... ... @@ -539,6 +541,11 @@ class KTBulkArchiveAction extends KTBulkAction {
539 541 if($oEntity->isSymbolicLink()){
540 542 return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document or folder instead."));
541 543 }
  544 + if(is_a($oEntity, 'Document')){
  545 + if(!KTWorkflowUtil::actionEnabledForDocument($oEntity, 'ktcore.actions.document.archive')){
  546 + return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.'));
  547 + }
  548 + }
542 549 return parent::check_entity($oEntity);
543 550 }
544 551  
... ... @@ -548,13 +555,15 @@ class KTBulkArchiveAction extends KTBulkAction {
548 555 * @return KTForm the form
549 556 */
550 557 function form_confirm() {
  558 + $cancelUrl = $this->getReturnUrl();
  559 +
551 560 $oForm = new KTForm;
552 561 $oForm->setOptions(array(
553 562 'label' => _kt('Are you sure?'),
554 563 'description' => _kt('There are shortcuts linking to some of the documents or folders in your selection; continuing will automatically delete the shortcuts. Would you like to continue?'),
555 564 'action' => 'collectinfo',
556 565 'fail_action' => 'main',
557   - 'cancel_url' => KTBrowseUtil::getUrlForFolder($this->oFolder),
  566 + 'cancel_url' => $cancelUrl,
558 567 'submit_label' => _kt('Continue'),
559 568 'context' => $this,
560 569 ));
... ... @@ -640,7 +649,7 @@ class KTBulkArchiveAction extends KTBulkAction {
640 649  
641 650 // Get documents in folder
642 651 $sDocuments = $oFolder->getDocumentIDs($sFolderId);
643   - $aDocuments = explode(',', $sDocuments);
  652 + $aDocuments = (!empty($sDocuments)) ? explode(',', $sDocuments) : array();
644 653  
645 654 // Get all the folders within the folder
646 655 $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR
... ... @@ -680,6 +689,8 @@ class KTBulkArchiveAction extends KTBulkAction {
680 689 return $res;
681 690 }
682 691 }
  692 + }else {
  693 + return PEAR::raiseError(_kt('The folder contains no documents to archive.'));
683 694 }
684 695 return true;
685 696 }
... ...
plugins/tagcloud/TagCloudRedirectPage.php
... ... @@ -142,7 +142,8 @@ class TagCloudRedirectPage extends KTStandardDispatcher {
142 142  
143 143 $aOptions = $collection->getEnvironOptions(); // extract data from the environment
144 144  
145   - $aOptions['return_url'] = KTUtil::addQueryString('TagCloudRedirection&action=search&tag='. urlencode($tag), false );
  145 + $returnUrl = KTUtil::addQueryString('TagCloudRedirection&action=search&tag='. urlencode($tag), false);
  146 + $aOptions['return_url'] = $returnUrl;
146 147 $aOptions['empty_message'] = _kt('No documents or folders match this query.');
147 148 $aOptions['is_browse'] = true;
148 149  
... ... @@ -159,8 +160,7 @@ class TagCloudRedirectPage extends KTStandardDispatcher {
159 160 'boolean_search' => $sSearch,
160 161 'bulkactions' => KTBulkActionUtil::getAllBulkActions(),
161 162 'browseutil' => new KTBrowseUtil(),
162   - 'returnaction' => 'booleanSearch',
163   - 'returndata' => $sSearch,
  163 + 'returnaction' => $returnUrl,
164 164 );
165 165 return $oTemplate->render($aTemplateData);
166 166 }
... ...
search2.php
... ... @@ -274,6 +274,14 @@ class SearchDispatcher extends KTStandardDispatcher {
274 274 redirect(KTUtil::kt_url().'/dashboard.php');
275 275 }
276 276  
  277 + function do_refresh(){
  278 + // Get query from session
  279 + $query = $_SESSION['search2_query'];
  280 +
  281 + $this->processQuery($query);
  282 + $this->redirectTo('searchResults');
  283 + }
  284 +
277 285 /**
278 286 * Processes a query sent by HTTP POST in searchQuery.
279 287 *
... ...