Commit 47e20abac975dfcb787251a6eb720e504989899b
1 parent
102db588
Per-User saved searches. Please test.
git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5439 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
7 changed files
with
217 additions
and
5 deletions
lib/search/savedsearch.inc.php
| @@ -146,6 +146,15 @@ class KTSavedSearch extends KTEntity { | @@ -146,6 +146,15 @@ class KTSavedSearch extends KTEntity { | ||
| 146 | )); | 146 | )); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | + function &getUserSearches($iUserId, $bNoSystem = false) { | ||
| 150 | + $sQuery = sprintf('user_id = %d', $iUserId); | ||
| 151 | + if(!$bNoSystem) { | ||
| 152 | + $sQuery .= ' OR user_id IS NULL'; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + return KTEntityUtil::getList2('KTSavedSearch', $sQuery, array('orderby' => 'user_id, name')); | ||
| 156 | + } | ||
| 157 | + | ||
| 149 | function &getConditions() { | 158 | function &getConditions() { |
| 150 | return KTEntityUtil::getByDict('KTSavedSearch', array( | 159 | return KTEntityUtil::getByDict('KTSavedSearch', array( |
| 151 | 'is_condition' => true, | 160 | 'is_condition' => true, |
plugins/ktcore/KTPortlets.php
| @@ -40,15 +40,26 @@ class KTSearchPortlet extends KTPortlet { | @@ -40,15 +40,26 @@ class KTSearchPortlet extends KTPortlet { | ||
| 40 | $oTemplating =& KTTemplating::getSingleton(); | 40 | $oTemplating =& KTTemplating::getSingleton(); |
| 41 | $oTemplate = $oTemplating->loadTemplate("kt3/portlets/search_portlet"); | 41 | $oTemplate = $oTemplating->loadTemplate("kt3/portlets/search_portlet"); |
| 42 | 42 | ||
| 43 | - $aSearches = KTSavedSearch::getSearches(); | 43 | + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', 1); |
| 44 | + $iDocumentId = KTUtil::arrayGet($_REQUEST, 'fDocumentId'); | ||
| 45 | + if (!$iFolderId && !$iDocumentId) { | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + $iUserId = $_SESSION['userID']; | ||
| 50 | + $aSearches = KTSavedSearch::getUserSearches($iUserId); | ||
| 51 | + | ||
| 44 | // empty on error. | 52 | // empty on error. |
| 45 | if (PEAR::isError($aSearches)) { | 53 | if (PEAR::isError($aSearches)) { |
| 46 | $aSearches = array(); | 54 | $aSearches = array(); |
| 47 | } | 55 | } |
| 48 | 56 | ||
| 57 | + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', 1); | ||
| 49 | $aTemplateData = array( | 58 | $aTemplateData = array( |
| 50 | "context" => $this, | 59 | "context" => $this, |
| 51 | "saved_searches" => $aSearches, | 60 | "saved_searches" => $aSearches, |
| 61 | + "folder_id" => $iFolderId, | ||
| 62 | + "document_id" => $iDocumentId, | ||
| 52 | ); | 63 | ); |
| 53 | 64 | ||
| 54 | return $oTemplate->render($aTemplateData); | 65 | return $oTemplate->render($aTemplateData); |
plugins/ktcore/admin/savedSearch.php
| @@ -149,7 +149,7 @@ class KTSavedSearchDispatcher extends KTAdminDispatcher { | @@ -149,7 +149,7 @@ class KTSavedSearchDispatcher extends KTAdminDispatcher { | ||
| 149 | $oSearch = KTSavedSearch::get($id); | 149 | $oSearch = KTSavedSearch::get($id); |
| 150 | 150 | ||
| 151 | if (PEAR::isError($oSearch) || ($oSearch == false)) { | 151 | if (PEAR::isError($oSearch) || ($oSearch == false)) { |
| 152 | - $this->errorRedirectToMain('No Such search'); | 152 | + $this->errorRedirectToMain('No such search'); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | 155 | ||
| @@ -212,6 +212,16 @@ class KTSavedSearchDispatcher extends KTAdminDispatcher { | @@ -212,6 +212,16 @@ class KTSavedSearchDispatcher extends KTAdminDispatcher { | ||
| 212 | )); | 212 | )); |
| 213 | $this->successRedirectToMain(_kt('Search saved')); | 213 | $this->successRedirectToMain(_kt('Search saved')); |
| 214 | } | 214 | } |
| 215 | + | ||
| 216 | + // helper for the template | ||
| 217 | + function _getUserName($iUserId) { | ||
| 218 | + $oUser = User::get($iUserId); | ||
| 219 | + if(PEAR::isError($oUser)) { | ||
| 220 | + return _kt('Error retrieving username'); | ||
| 221 | + } | ||
| 222 | + return $oUser->getUserName(); | ||
| 223 | + } | ||
| 224 | + | ||
| 215 | } | 225 | } |
| 216 | 226 | ||
| 217 | //$oDispatcher = new KTSavedSearchDispatcher(); | 227 | //$oDispatcher = new KTSavedSearchDispatcher(); |
search/booleanSearch.php
| @@ -84,7 +84,7 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | @@ -84,7 +84,7 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | ||
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | if (is_null(KTUtil::arrayGet($datavars["subgroup"][0], "values"))) { | 86 | if (is_null(KTUtil::arrayGet($datavars["subgroup"][0], "values"))) { |
| 87 | - $this->errorRedirectToMain("No search parameters given"); | 87 | + $this->errorRedirectToMain(_kt("No search parameters given")); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | if (empty($datavars)) { | 90 | if (empty($datavars)) { |
| @@ -96,6 +96,132 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | @@ -96,6 +96,132 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | ||
| 96 | return $res; | 96 | return $res; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | + function do_saveSearch() { | ||
| 100 | + $this->startTransaction(); | ||
| 101 | + | ||
| 102 | + $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSearchId', false); | ||
| 103 | + $sName = KTUtil::arrayGet($_REQUEST, 'name', false); | ||
| 104 | + $sSearch = KTUtil::arrayGet($_REQUEST, 'boolean_search'); | ||
| 105 | + | ||
| 106 | + if($iSearchId === false && $sName === false) { | ||
| 107 | + $this->errorRedirectTo('performSearch', _kt('Please either enter a name, or select a search to save over'), sprintf('boolean_search_id=%s', $sSearch)); | ||
| 108 | + exit(0); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + $datavars = $_SESSION['boolean_search'][$sSearch]; | ||
| 112 | + if (!is_array($datavars)) { | ||
| 113 | + $datavars = unserialize($datavars); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + if (empty($datavars)) { | ||
| 117 | + $this->errorRedirectToMain(_kt('You need to have at least 1 condition.')); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + if($iSearchId) { | ||
| 121 | + $oSearch = KTSavedSearch::get($iSearchId); | ||
| 122 | + if(PEAR::isError($oSearch) || $oSearch == false) { | ||
| 123 | + $this->errorRedirectToMain(_kt('No such search')); | ||
| 124 | + exit(0); | ||
| 125 | + } | ||
| 126 | + $oSearch->setSearch($datavars); | ||
| 127 | + $oSearch = $oSearch->update(); | ||
| 128 | + | ||
| 129 | + } else { | ||
| 130 | + $sName = $this->oValidator->validateEntityName('KTSavedSearch', | ||
| 131 | + KTUtil::arrayGet($_REQUEST, 'name'), | ||
| 132 | + array('extra_condition' => 'not is_condition', 'redirect_to' => array('new'))); | ||
| 133 | + | ||
| 134 | + $sNamespace = KTUtil::nameToLocalNamespace('Saved searches', $sName); | ||
| 135 | + | ||
| 136 | + $oSearch = KTSavedSearch::createFromArray(array('name' => $sName, | ||
| 137 | + 'namespace' => $sNamespace, | ||
| 138 | + 'iscondition' => false, | ||
| 139 | + 'iscomplete' => true, | ||
| 140 | + 'userid' => $this->oUser->getId(), | ||
| 141 | + 'search' => $datavars,)); | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + $this->oValidator->notError($oSearch, array( | ||
| 145 | + 'redirect_to' => 'main', | ||
| 146 | + 'message' => _kt('Search not saved'), | ||
| 147 | + )); | ||
| 148 | + | ||
| 149 | + $this->commitTransaction(); | ||
| 150 | + $this->successRedirectTo('performSearch', _kt('Search saved'), sprintf('boolean_search_id=%s', $sSearch)); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + | ||
| 154 | + function do_deleteSearch() { | ||
| 155 | + $this->startTransaction(); | ||
| 156 | + | ||
| 157 | + $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSavedSearchId', false); | ||
| 158 | + $oSearch = KTSavedSearch::get($iSearchId); | ||
| 159 | + if(PEAR::isError($oSearch) || $oSearch == false) { | ||
| 160 | + $this->errorRedirectToMain(_kt('No such search')); | ||
| 161 | + exit(0); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + $res = $oSearch->delete(); | ||
| 165 | + $this->oValidator->notError($res, array( | ||
| 166 | + 'redirect_to' => 'main', | ||
| 167 | + 'message' => _kt('Error deleting search'), | ||
| 168 | + )); | ||
| 169 | + | ||
| 170 | + $this->commitTransaction(); | ||
| 171 | + | ||
| 172 | + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false); | ||
| 173 | + $iDocumentId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false); | ||
| 174 | + | ||
| 175 | + if($iFolderId) { | ||
| 176 | + controllerRedirect('browse', 'fFolderId=' . $iFolderId); | ||
| 177 | + } else { | ||
| 178 | + controllerRedirect('viewDocument', 'fDocumentId=' . $iDocumentId); | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + function do_editSearch() { | ||
| 183 | + $sSearch = KTUtil::arrayGet($_REQUEST, 'boolean_search'); | ||
| 184 | + $aSearch = $_SESSION['boolean_search'][$sSearch]; | ||
| 185 | + if (!is_array($aSearch)) { | ||
| 186 | + $aSearch = unserialize($aSearch); | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + if (empty($aSearch)) { | ||
| 190 | + $this->errorRedirectToMain(_kt('You need to have at least 1 condition.')); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + $oTemplating =& KTTemplating::getSingleton(); | ||
| 194 | + $oTemplate = $oTemplating->loadTemplate("ktcore/boolean_search_change"); | ||
| 195 | + | ||
| 196 | + $aCriteria = Criteria::getAllCriteria(); | ||
| 197 | + | ||
| 198 | + // we need to help out here, since it gets unpleasant inside the template. | ||
| 199 | + | ||
| 200 | + foreach ($aSearch['subgroup'] as $isg => $as) { | ||
| 201 | + $aSubgroup =& $aSearch['subgroup'][$isg]; | ||
| 202 | + if (is_array($aSubgroup['values'])) { | ||
| 203 | + foreach ($aSubgroup['values'] as $iv => $t) { | ||
| 204 | + $datavars =& $aSubgroup['values'][$iv]; | ||
| 205 | + $datavars['typename'] = $aCriteria[$datavars['type']]->sDisplay; | ||
| 206 | + $datavars['widgetval'] = $aCriteria[$datavars['type']]->searchWidget(null, $datavars['data']); | ||
| 207 | + } | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + $aTemplateData = array( | ||
| 212 | + "title" => _kt("Edit an existing condition"), | ||
| 213 | + "aCriteria" => $aCriteria, | ||
| 214 | + "searchButton" => _kt("Search"), | ||
| 215 | + 'aSearch' => $aSearch, | ||
| 216 | + 'context' => $this, | ||
| 217 | + // 'iSearchId' => $oSearch->getId(), | ||
| 218 | + // 'old_name' => $oSearch->getName(), | ||
| 219 | + 'sNameTitle' => _kt('Edit Search'), | ||
| 220 | + ); | ||
| 221 | + return $oTemplate->render($aTemplateData); | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + | ||
| 99 | function handleCriteriaSet($aCriteriaSet, $iStartIndex, $sTitle=null) { | 225 | function handleCriteriaSet($aCriteriaSet, $iStartIndex, $sTitle=null) { |
| 100 | 226 | ||
| 101 | if ($sTitle == null) { | 227 | if ($sTitle == null) { |
| @@ -142,6 +268,22 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | @@ -142,6 +268,22 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | ||
| 142 | $qObj = new BooleanSearchQuery($aCriteriaSet); | 268 | $qObj = new BooleanSearchQuery($aCriteriaSet); |
| 143 | $collection->setQueryObject($qObj); | 269 | $collection->setQueryObject($qObj); |
| 144 | 270 | ||
| 271 | + | ||
| 272 | + // form fields for saving the search | ||
| 273 | + $save_fields = array(); | ||
| 274 | + $save_fields[] = new KTStringWidget(_kt('New search'), _kt('The name to save this search as'), 'name', null, $this->oPage, true); | ||
| 275 | + | ||
| 276 | + $aUserSearches = KTSavedSearch::getUserSearches($this->oUser->getId(), true); | ||
| 277 | + if(count($aUserSearches)) { | ||
| 278 | + $aVocab = array('' => ' ---- '); | ||
| 279 | + foreach($aUserSearches as $oSearch) { | ||
| 280 | + $aVocab[$oSearch->getId()] = $oSearch->getName(); | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + $aSelectOptions = array('vocab' => $aVocab); | ||
| 284 | + $save_fields[] = new KTLookupWidget(_kt('Existing search'), _kt('To save over one of your existing searches, select it here.'), 'fSearchId', null, $this->oPage, true, null, null, $aSelectOptions); | ||
| 285 | + } | ||
| 286 | + | ||
| 145 | $collection->getResults(); | 287 | $collection->getResults(); |
| 146 | $oTemplating =& KTTemplating::getSingleton(); | 288 | $oTemplating =& KTTemplating::getSingleton(); |
| 147 | $oTemplate = $oTemplating->loadTemplate("kt3/browse"); | 289 | $oTemplate = $oTemplating->loadTemplate("kt3/browse"); |
| @@ -149,6 +291,8 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | @@ -149,6 +291,8 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { | ||
| 149 | "context" => $this, | 291 | "context" => $this, |
| 150 | "collection" => $collection, | 292 | "collection" => $collection, |
| 151 | "custom_title" => $sTitle, | 293 | "custom_title" => $sTitle, |
| 294 | + "save_fields" => $save_fields, | ||
| 295 | + "boolean_search" => $sSearch, | ||
| 152 | ); | 296 | ); |
| 153 | return $oTemplate->render($aTemplateData); | 297 | return $oTemplate->render($aTemplateData); |
| 154 | } | 298 | } |
templates/kt3/browse.smarty
| @@ -8,7 +8,8 @@ | @@ -8,7 +8,8 @@ | ||
| 8 | <h2>{$custom_title}</h2> | 8 | <h2>{$custom_title}</h2> |
| 9 | {/if} | 9 | {/if} |
| 10 | 10 | ||
| 11 | -<form action="{$smarty.server.PHP_SELF}" METHOD="POST"> | 11 | + |
| 12 | +<form action="{$smarty.server.PHP_SELF}" method="post"> | ||
| 12 | <input type="hidden" name="action" value="massaction" /> | 13 | <input type="hidden" name="action" value="massaction" /> |
| 13 | {if ($isEditable)} | 14 | {if ($isEditable)} |
| 14 | <input type="hidden" name="fFolderId" value="{$context->oFolder->getId()}" /> | 15 | <input type="hidden" name="fFolderId" value="{$context->oFolder->getId()}" /> |
| @@ -21,4 +22,36 @@ | @@ -21,4 +22,36 @@ | ||
| 21 | </div> | 22 | </div> |
| 22 | {/if} | 23 | {/if} |
| 23 | </form> | 24 | </form> |
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +{if ($save_fields)} | ||
| 29 | +<form action="{$smarty.server.PHP_SELF}" method="post"> | ||
| 30 | +<fieldset> | ||
| 31 | +<legend>Edit search</legend> | ||
| 32 | +<p class="descriptiveText">{i18n}To modify this search, press the 'Edit' button.{/i18n}</p> | ||
| 33 | +<input type="hidden" name="action" value="editSearch" /> | ||
| 34 | +<input type="hidden" name="boolean_search" value="{$boolean_search}" /> | ||
| 35 | +<div class="form_actions"> | ||
| 36 | +<input type="submit" name="submit" value="{i18n}Edit{/i18n}" /> | ||
| 37 | +</div> | ||
| 38 | +</fieldset> | ||
| 39 | +</form> | ||
| 40 | + | ||
| 41 | +<form action="{$smarty.server.PHP_SELF}" method="post"> | ||
| 42 | +<fieldset> | ||
| 43 | +<legend>{i18n}Save this search{/i18n}</legend> | ||
| 44 | +<p class="descriptiveText">{i18n}To save this search permanently, so that you can run it again at any time, fill in a name below and click 'Save'.{/i18n}</p> | ||
| 45 | +<input type="hidden" name="action" value="saveSearch" /> | ||
| 46 | +<input type="hidden" name="boolean_search" value="{$boolean_search}" /> | ||
| 47 | +{foreach item=oWidget from=$save_fields} | ||
| 48 | + {$oWidget->render()} | ||
| 49 | +{/foreach} | ||
| 50 | +<div class="form_actions"> | ||
| 51 | +<input type="submit" name="submit" value="{i18n}Save{/i18n}" /> | ||
| 52 | +</div> | ||
| 53 | +</fieldset> | ||
| 54 | +</form> | ||
| 55 | +{/if} | ||
| 56 | + | ||
| 24 | {* we break encapsulation pretty badly here. *} | 57 | {* we break encapsulation pretty badly here. *} |
| 25 | \ No newline at end of file | 58 | \ No newline at end of file |
templates/kt3/portlets/search_portlet.smarty
| @@ -8,7 +8,9 @@ | @@ -8,7 +8,9 @@ | ||
| 8 | <h4>{i18n}Saved Searches{/i18n}</h4> | 8 | <h4>{i18n}Saved Searches{/i18n}</h4> |
| 9 | <ul class="actionlist"> | 9 | <ul class="actionlist"> |
| 10 | {foreach item=oSearch from=$saved_searches} | 10 | {foreach item=oSearch from=$saved_searches} |
| 11 | -<li><a href="{"booleanSearch"|generateControllerUrl}&qs[action]=performSearch&qs[fSavedSearchId]={$oSearch->getId()}">{$oSearch->getName()}</a></li> | 11 | +<li> |
| 12 | +{if ($oSearch->getUserId())}<a class="ktInline ktAction ktDelete" href="{"booleanSearch"|generateControllerUrl}&qs[action]=deleteSearch&qs[fSavedSearchId]={$oSearch->getId()}&qs[fFolderId]={$folder_id}&qs[fDocumentId]={$document_id}">{i18n}Delete{/i18n}</a>{/if}<a href="{"booleanSearch"|generateControllerUrl}&qs[action]=performSearch&qs[fSavedSearchId]={$oSearch->getId()}">{$oSearch->getName()}</a> | ||
| 13 | +</li> | ||
| 12 | {/foreach} | 14 | {/foreach} |
| 13 | </ul> | 15 | </ul> |
| 14 | <hr /> | 16 | <hr /> |
templates/ktcore/search/administration/savedsearches.smarty
| @@ -22,6 +22,7 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> | @@ -22,6 +22,7 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> | ||
| 22 | <thead> | 22 | <thead> |
| 23 | <tr> | 23 | <tr> |
| 24 | <th>{i18n}Search Name{/i18n}</th> | 24 | <th>{i18n}Search Name{/i18n}</th> |
| 25 | + <th>{i18n}User{/i18n}</th> | ||
| 25 | <th>{i18n}Edit{/i18n}</th> | 26 | <th>{i18n}Edit{/i18n}</th> |
| 26 | <th>{i18n}Delete{/i18n}</th> | 27 | <th>{i18n}Delete{/i18n}</th> |
| 27 | <th>{i18n}View Results{/i18n}</th> | 28 | <th>{i18n}View Results{/i18n}</th> |
| @@ -31,6 +32,8 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> | @@ -31,6 +32,8 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> | ||
| 31 | {foreach item=oSearch from=$saved_searches} | 32 | {foreach item=oSearch from=$saved_searches} |
| 32 | <tr> | 33 | <tr> |
| 33 | <td>{$oSearch->getName()}</td> | 34 | <td>{$oSearch->getName()}</td> |
| 35 | + {capture assign=iUserId}{$oSearch->getUserId()}{/capture} | ||
| 36 | + <td>{if ($iUserId === '')}Global{else}{$context->_getUserName($iUserId)}{/if}</td> | ||
| 34 | <td><a href="{addQS}action=edit&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktEdit">{i18n}Edit{/i18n}</a></td> | 37 | <td><a href="{addQS}action=edit&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktEdit">{i18n}Edit{/i18n}</a></td> |
| 35 | <td><a href="{addQS}action=delete&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td> | 38 | <td><a href="{addQS}action=delete&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td> |
| 36 | <td><a href="{"booleanSearch"|generateControllerUrl}&qs[action]=performSearch&qs[fSavedSearchId]={$oSearch->getId()}">Run Search</a></td> | 39 | <td><a href="{"booleanSearch"|generateControllerUrl}&qs[action]=performSearch&qs[fSavedSearchId]={$oSearch->getId()}">Run Search</a></td> |