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 | 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 | 158 | function &getConditions() { |
| 150 | 159 | return KTEntityUtil::getByDict('KTSavedSearch', array( |
| 151 | 160 | 'is_condition' => true, | ... | ... |
plugins/ktcore/KTPortlets.php
| ... | ... | @@ -40,15 +40,26 @@ class KTSearchPortlet extends KTPortlet { |
| 40 | 40 | $oTemplating =& KTTemplating::getSingleton(); |
| 41 | 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 | 52 | // empty on error. |
| 45 | 53 | if (PEAR::isError($aSearches)) { |
| 46 | 54 | $aSearches = array(); |
| 47 | 55 | } |
| 48 | 56 | |
| 57 | + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', 1); | |
| 49 | 58 | $aTemplateData = array( |
| 50 | 59 | "context" => $this, |
| 51 | 60 | "saved_searches" => $aSearches, |
| 61 | + "folder_id" => $iFolderId, | |
| 62 | + "document_id" => $iDocumentId, | |
| 52 | 63 | ); |
| 53 | 64 | |
| 54 | 65 | return $oTemplate->render($aTemplateData); | ... | ... |
plugins/ktcore/admin/savedSearch.php
| ... | ... | @@ -149,7 +149,7 @@ class KTSavedSearchDispatcher extends KTAdminDispatcher { |
| 149 | 149 | $oSearch = KTSavedSearch::get($id); |
| 150 | 150 | |
| 151 | 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 | 212 | )); |
| 213 | 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 | 227 | //$oDispatcher = new KTSavedSearchDispatcher(); | ... | ... |
search/booleanSearch.php
| ... | ... | @@ -84,7 +84,7 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 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 | 90 | if (empty($datavars)) { |
| ... | ... | @@ -96,6 +96,132 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { |
| 96 | 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 | 225 | function handleCriteriaSet($aCriteriaSet, $iStartIndex, $sTitle=null) { |
| 100 | 226 | |
| 101 | 227 | if ($sTitle == null) { |
| ... | ... | @@ -142,6 +268,22 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { |
| 142 | 268 | $qObj = new BooleanSearchQuery($aCriteriaSet); |
| 143 | 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 | 287 | $collection->getResults(); |
| 146 | 288 | $oTemplating =& KTTemplating::getSingleton(); |
| 147 | 289 | $oTemplate = $oTemplating->loadTemplate("kt3/browse"); |
| ... | ... | @@ -149,6 +291,8 @@ class BooleanSearchDispatcher extends KTStandardDispatcher { |
| 149 | 291 | "context" => $this, |
| 150 | 292 | "collection" => $collection, |
| 151 | 293 | "custom_title" => $sTitle, |
| 294 | + "save_fields" => $save_fields, | |
| 295 | + "boolean_search" => $sSearch, | |
| 152 | 296 | ); |
| 153 | 297 | return $oTemplate->render($aTemplateData); |
| 154 | 298 | } | ... | ... |
templates/kt3/browse.smarty
| ... | ... | @@ -8,7 +8,8 @@ |
| 8 | 8 | <h2>{$custom_title}</h2> |
| 9 | 9 | {/if} |
| 10 | 10 | |
| 11 | -<form action="{$smarty.server.PHP_SELF}" METHOD="POST"> | |
| 11 | + | |
| 12 | +<form action="{$smarty.server.PHP_SELF}" method="post"> | |
| 12 | 13 | <input type="hidden" name="action" value="massaction" /> |
| 13 | 14 | {if ($isEditable)} |
| 14 | 15 | <input type="hidden" name="fFolderId" value="{$context->oFolder->getId()}" /> |
| ... | ... | @@ -21,4 +22,36 @@ |
| 21 | 22 | </div> |
| 22 | 23 | {/if} |
| 23 | 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 | 57 | {* we break encapsulation pretty badly here. *} |
| 25 | 58 | \ No newline at end of file | ... | ... |
templates/kt3/portlets/search_portlet.smarty
| ... | ... | @@ -8,7 +8,9 @@ |
| 8 | 8 | <h4>{i18n}Saved Searches{/i18n}</h4> |
| 9 | 9 | <ul class="actionlist"> |
| 10 | 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 | 14 | {/foreach} |
| 13 | 15 | </ul> |
| 14 | 16 | <hr /> | ... | ... |
templates/ktcore/search/administration/savedsearches.smarty
| ... | ... | @@ -22,6 +22,7 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> |
| 22 | 22 | <thead> |
| 23 | 23 | <tr> |
| 24 | 24 | <th>{i18n}Search Name{/i18n}</th> |
| 25 | + <th>{i18n}User{/i18n}</th> | |
| 25 | 26 | <th>{i18n}Edit{/i18n}</th> |
| 26 | 27 | <th>{i18n}Delete{/i18n}</th> |
| 27 | 28 | <th>{i18n}View Results{/i18n}</th> |
| ... | ... | @@ -31,6 +32,8 @@ newsletters, etc.) based on a category or fieldset value.{/i18n}</p> |
| 31 | 32 | {foreach item=oSearch from=$saved_searches} |
| 32 | 33 | <tr> |
| 33 | 34 | <td>{$oSearch->getName()}</td> |
| 35 | + {capture assign=iUserId}{$oSearch->getUserId()}{/capture} | |
| 36 | + <td>{if ($iUserId === '')}Global{else}{$context->_getUserName($iUserId)}{/if}</td> | |
| 34 | 37 | <td><a href="{addQS}action=edit&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktEdit">{i18n}Edit{/i18n}</a></td> |
| 35 | 38 | <td><a href="{addQS}action=delete&fSavedSearchId={$oSearch->getId()}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td> |
| 36 | 39 | <td><a href="{"booleanSearch"|generateControllerUrl}&qs[action]=performSearch&qs[fSavedSearchId]={$oSearch->getId()}">Run Search</a></td> | ... | ... |