From fac375a371ca26cc0f80be6ff07c18ecfb6f1c1c Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 7 Jul 2022 16:47:21 +0200 Subject: [PATCH 1/5] do not use callHook() because the return value of the last hook must be passed to the next hook --- views/bootstrap/class.Bootstrap.php | 65 ++++++++++++++++++++------- views/bootstrap4/class.Bootstrap4.php | 65 ++++++++++++++++++++------- 2 files changed, 100 insertions(+), 30 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 363ae17b9..399af883a 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -693,9 +693,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['index_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php?folderid=". $folderID."&showtree=".showtree(), 'label'=>getMLText('index_folder')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('folderNavigationBar')) - $menuitems = $this->callHook('folderNavigationBar', $folder, $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'folderNavigationBar')) { + $menuitems = $hookObj->folderNavigationBar($this, $folder, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -789,9 +796,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['groups'] = array('link'=>$this->params['settings']->_httpRoot."out/out.GroupView.php", 'label'=>getMLText('groups')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('accountNavigationBar')) - $menuitems = $this->callHook('accountNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'accountNavigationBar')) { + $menuitems = $hookObj->accountNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -819,9 +833,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['workflow_summary'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowSummary.php", 'label'=>getMLText('workflow_summary')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('mydocumentsNavigationBar')) - $menuitems = $this->callHook('mydocumentsNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'mydocumentsNavigationBar')) { + $menuitems = $hookObj->mydocumentsNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -908,9 +929,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['misc']['children']['version_info'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Info.php", 'label'=>getMLText('version_info')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('admintoolsNavigationBar')) - $menuitems = $this->callHook('admintoolsNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'admintoolsNavigationBar')) { + $menuitems = $hookObj->admintoolsNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -944,9 +972,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; if (!$this->params['user']->isGuest()) $menuitems['addevent'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddEvent.php", 'label'=>getMLText('add_event')); - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('calendarNavigationBar')) - $menuitems = $this->callHook('calendarNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'calendarNavigationBar')) { + $menuitems = $hookObj->calendarNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 5c2bb7e54..689494a29 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -694,9 +694,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['index_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php?folderid=". $folderID."&showtree=".showtree(), 'label'=>getMLText('index_folder')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('folderNavigationBar')) - $menuitems = $this->callHook('folderNavigationBar', $folder, $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'folderNavigationBar')) { + $menuitems = $hookObj->folderNavigationBar($this, $folder, $menuitems); + } + } self::showNavigationBar($menuitems); } /* }}} */ @@ -782,9 +789,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['groups'] = array('link'=>$this->params['settings']->_httpRoot."out/out.GroupView.php", 'label'=>getMLText('groups')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('accountNavigationBar')) - $menuitems = $this->callHook('accountNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'accountNavigationBar')) { + $menuitems = $hookObj->accountNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -808,9 +822,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['workflow_summary'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowSummary.php", 'label'=>getMLText('workflow_summary')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('mydocumentsNavigationBar')) - $menuitems = $this->callHook('mydocumentsNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'mydocumentsNavigationBar')) { + $menuitems = $hookObj->mydocumentsNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -894,9 +915,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['misc']['children']['version_info'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Info.php", 'label'=>getMLText('version_info')); } - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('admintoolsNavigationBar')) - $menuitems = $this->callHook('admintoolsNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'admintoolsNavigationBar')) { + $menuitems = $hookObj->admintoolsNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); @@ -927,9 +955,16 @@ background-image: linear-gradient(to bottom, #882222, #111111);; if (!$this->params['user']->isGuest()) $menuitems['addevent'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddEvent.php", 'label'=>getMLText('add_event')); - /* Check if hook exists because otherwise callHook() will override $menuitems */ - if($this->hasHook('calendarNavigationBar')) - $menuitems = $this->callHook('calendarNavigationBar', $menuitems); + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'calendarNavigationBar')) { + $menuitems = $hookObj->calendarNavigationBar($this, $menuitems); + } + } self::showNavigationBar($menuitems); From ca2739b96ee49340313e96af4606784bc236a47b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 7 Jul 2022 16:47:42 +0200 Subject: [PATCH 2/5] add hooks folderRowAction and documentRowAction --- views/bootstrap/class.Bootstrap.php | 45 ++++++++++++++++++++++----- views/bootstrap4/class.Bootstrap4.php | 42 +++++++++++++++++++++---- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 399af883a..4a1f5b549 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -3038,10 +3038,23 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) } if($onepage) $actions['view_document'] = ''; + + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'documentRowAction')) { + $actions = $hookObj->documentRowAction($this, $document, $actions); + } + } + foreach($actions as $action) { if(is_string($action)) $content .= $action; } + if(!empty($extracontent['end_action_list'])) $content .= $extracontent['end_action_list']; $content .= ""; @@ -3206,29 +3219,47 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $content = ''; $content .= "
"; + $actions = array(); if(!empty($extracontent['begin_action_list'])) $content .= $extracontent['begin_action_list']; $subFolderAccessMode = $subFolder->getAccessMode($user); if ($accessop->check_view_access('RemoveFolder')) { if($subFolderAccessMode >= M_ALL) { - $content .= $this->printDeleteFolderButton($subFolder, 'splash_rm_folder', true); + $actions['remove_folder'] = $this->printDeleteFolderButton($subFolder, 'splash_rm_folder', true); } else { - $content .= ''; + $actions['remove_folder'] = ''; } } if($subFolderAccessMode >= M_READWRITE) { - $content .= ''; + $actions['edit_folder'] = ''; } else { - $content .= ''; + $actions['edit_folder'] = ''; } if($subFolderAccessMode >= M_READWRITE) { - $content .= $this->printAccessButton($subFolder, true); + $actions['folder_access'] = $this->printAccessButton($subFolder, true); } if($enableClipboard) { - $content .= ''; + $actions['add_to_clipboard'] = ''; } if($onepage) - $content .= ''; + $actions['view_folder'] = ''; + + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'folderRowAction')) { + $actions = $hookObj->folderRowAction($this, $folder, $actions); + } + } + + foreach($actions as $action) { + if(is_string($action)) + $content .= $action; + } + if(!empty($extracontent['end_action_list'])) $content .= $extracontent['end_action_list']; $content .= "
"; diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 689494a29..7e84e82e4 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -3113,6 +3113,18 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) } if($onepage) $actions['view_document'] = ''; + + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'documentRowAction')) { + $actions = $hookObj->documentRowAction($this, $document, $actions); + } + } + foreach($actions as $action) { if(is_string($action)) $content .= $action; @@ -3328,29 +3340,47 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $content = ''; $content .= "
"; + $actions = array(); if(!empty($extracontent['begin_action_list'])) $content .= $extracontent['begin_action_list']; $subFolderAccessMode = $subFolder->getAccessMode($user); if ($accessop->check_view_access('RemoveFolder')) { if($subFolderAccessMode >= M_ALL) { - $content .= $this->printDeleteFolderButton($subFolder, 'splash_rm_folder', true); + $actions['remove_folder'] = $this->printDeleteFolderButton($subFolder, 'splash_rm_folder', true); } else { - $content .= ''; + $actions['remove_folder'] = ''; } } if($subFolderAccessMode >= M_READWRITE) { - $content .= ''; + $actions['edit_folder'] = ''; } else { $content .= ''; } if($subFolderAccessMode >= M_READWRITE) { - $content .= $this->printAccessButton($subFolder, true); + $actions['folder_access'] = $this->printAccessButton($subFolder, true); } if($enableClipboard) { - $content .= ''; + $actions['add_to_clipboard'] = ''; } if($onepage) - $content .= ''; + $actions['view_folder'] = ''; + + /* Do not use $this->callHook() because $menuitems must be returned by the the + * first hook and passed to next hook. $this->callHook() will just pass + * the menuitems to each single hook. Hence, the last hook will win. + */ + $hookObjs = $this->getHookObjects(); + foreach($hookObjs as $hookObj) { + if (method_exists($hookObj, 'folderRowAction')) { + $actions = $hookObj->folderRowAction($this, $folder, $actions); + } + } + + foreach($actions as $action) { + if(is_string($action)) + $content .= $action; + } + if(!empty($extracontent['end_action_list'])) $content .= $extracontent['end_action_list']; $content .= "
"; From be2ed2f061b4d56ba682f1b891d8b1582f2cabac Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 8 Jul 2022 13:16:40 +0200 Subject: [PATCH 3/5] fix some comments and variable names --- controllers/class.RemoveFolder.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/controllers/class.RemoveFolder.php b/controllers/class.RemoveFolder.php index a0633d093..ac64f246a 100644 --- a/controllers/class.RemoveFolder.php +++ b/controllers/class.RemoveFolder.php @@ -22,17 +22,17 @@ */ class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common { - /* Register a callback which removes each document from the fulltext index + /* Register a callback which removes each document/folder from the fulltext index * The callback must return null otherwise the removal will be canceled. */ - static function removeFromIndex($arr, $document) { /* {{{ */ + static function removeFromIndex($arr, $object) { /* {{{ */ $fulltextservice = $arr[0]; $lucenesearch = $fulltextservice->Search(); $hit = null; - if($document->isType('document')) - $hit = $lucenesearch->getDocument($document->getID()); - elseif($document->isType('folder')) - $hit = $lucenesearch->getFolder($document->getID()); + if($object->isType('document')) + $hit = $lucenesearch->getDocument($object->getID()); + elseif($object->isType('folder')) + $hit = $lucenesearch->getFolder($object->getID()); if($hit) { $index = $fulltextservice->Indexer(); $index->delete($hit->id); @@ -55,7 +55,7 @@ class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common { $folder = $this->params['folder']; $fulltextservice = $this->params['fulltextservice']; - /* Get the document id and name before removing the document */ + /* Get the folder id and name before removing the folder */ $foldername = $folder->getName(); $folderid = $folder->getID(); From 5c4ae08b4acea80c2f6bf693f050b3e2d9307b8b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 8 Jul 2022 13:17:02 +0200 Subject: [PATCH 4/5] sync with RemoveFolder --- controllers/class.EmptyFolder.php | 63 +++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/controllers/class.EmptyFolder.php b/controllers/class.EmptyFolder.php index a6629923c..eb1c5a629 100644 --- a/controllers/class.EmptyFolder.php +++ b/controllers/class.EmptyFolder.php @@ -22,41 +22,64 @@ */ class SeedDMS_Controller_EmptyFolder extends SeedDMS_Controller_Common { - public function run() { + /* Register a callback which removes each document/folder from the fulltext index + * The callback must return null otherwise the removal will be canceled. + */ + static function removeFromIndex($arr, $object) { /* {{{ */ + $fulltextservice = $arr[0]; + $lucenesearch = $fulltextservice->Search(); + $hit = null; + if($object->isType('document')) + $hit = $lucenesearch->getDocument($object->getID()); + elseif($object->isType('folder')) + $hit = $lucenesearch->getFolder($object->getID()); + if($hit) { + $index = $fulltextservice->Indexer(); + $index->delete($hit->id); + $index->commit(); + } + return null; + } /* }}} */ + + static function removePreviews($arr, $document) { /* {{{ */ + $previewer = $arr[0]; + + $previewer->deleteDocumentPreviews($document); + return null; + } /* }}} */ + + public function run() { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; $settings = $this->params['settings']; $folder = $this->params['folder']; - $index = $this->params['index']; - $indexconf = $this->params['indexconf']; + $fulltextservice = $this->params['fulltextservice']; - /* Get the document id and name before removing the document */ + /* Get the folder id and name before removing the folder */ $foldername = $folder->getName(); $folderid = $folder->getID(); if(false === $this->callHook('preEmptyFolder')) { if(empty($this->errormsg)) $this->errormsg = 'hook_preEmptyFolder_failed'; - return null; + return false; } $result = $this->callHook('emptyFolder', $folder); if($result === null) { - /* Register a callback which removes each document from the fulltext index - * The callback must return null other the removal will be canceled. - */ - function removeFromIndex($arr, $document) { - $index = $arr[0]; - $indexconf = $arr[1]; - $lucenesearch = new $indexconf['Search']($index); - if($hit = $lucenesearch->getDocument($document->getID())) { - $index->delete($hit->id); - $index->commit(); - } - return null; + if($fulltextservice && ($index = $fulltextservice->Indexer())) { + /* Register a callback which is called by SeedDMS_Core when a folder + * or document is removed. The second parameter passed to this callback + * is the document or folder to be removed. + */ + $dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice)); + $dms->addCallback('onPreRemoveFolder', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice)); } - if($index) - $dms->setCallback('onPreEmptyDocument', 'removeFromIndex', array($index, $indexconf)); + + /* Register another callback which removes the preview images of the document */ + require_once("SeedDMS/Preview.php"); + $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir); + $dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removePreviews', array($previewer)); if (!$folder->emptyFolder()) { $this->errormsg = 'error_occured'; @@ -72,5 +95,5 @@ class SeedDMS_Controller_EmptyFolder extends SeedDMS_Controller_Common { } return true; - } + } /* }}} */ } From c31d12b44cf832a13222e7a7c5ae3d54e22eca0e Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 8 Jul 2022 13:17:27 +0200 Subject: [PATCH 5/5] set splash message --- op/op.RemoveFolder.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/op/op.RemoveFolder.php b/op/op.RemoveFolder.php index 5d0e09b64..92744b27d 100644 --- a/op/op.RemoveFolder.php +++ b/op/op.RemoveFolder.php @@ -88,6 +88,8 @@ if ($notifier) { $notifier->sendDeleteFolderMail($folder, $user); } +$session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_rm_folder'))); + add_log_line("?folderid=".$folderid."&name=".$foldername); header("Location:../out/out.ViewFolder.php?folderid=".$parent->getID()."&showtree=".$_POST["showtree"]);