Commit 98ead1851c7f44bd50ef8c4dc809038c2567e55d

Authored by Brad Shuttleworth
1 parent ae92e7ca

KTS-721: Criteria should be invertable.

Also made it explicit that date widgets are ranged.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5304 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing 1 changed file with 163 additions and 29 deletions
lib/browse/Criteria.inc
... ... @@ -36,6 +36,8 @@ require_once(KT_LIB_DIR . '/workflow/workflow.inc.php');
36 36 * @package lib.browse
37 37 */
38 38  
  39 +$RESTRICTING_SEARCH = true;
  40 +
39 41 class BrowseCriterion {
40 42 var $sDisplay;
41 43 var $sDocumentField;
... ... @@ -47,6 +49,7 @@ class BrowseCriterion {
47 49 var $bString = false;
48 50 var $sSearchTable = "D";
49 51 var $bVisible = true;
  52 + var $bContains = false;
50 53  
51 54 function BrowseCriterion ($sDisplay, $sDocumentField, $sSortField, $iID) {
52 55 $this->sDisplay =& $sDisplay;
... ... @@ -160,14 +163,28 @@ class BrowseCriterion {
160 163  
161 164 function searchWidget ($aRequest, $aPreValue = null) {
162 165 if ($aPreValue != null) {
163   - // !#@&)*( (*&!@# *(&@!(*&!@#
  166 + // !#@&)*( (*&!@# *(&@NOT (*&!@#
164 167 $k = array_keys($aPreValue);
165 168 $k = $k[0];
166 169 $preval = $aPreValue[$k];
167   - return "<input type=\"text\" size=\"50\" name=\"" . $this->getWidgetBase() . "\" value=\"" . $preval . "\"/>";
  170 + return $this->getNotWidget() . "<input type=\"text\" size=\"50\" name=\"" . $this->getWidgetBase() . "\" value=\"" . $preval . "\"/>";
  171 + } else {
  172 + return $this->getNotWidget() . "<input type=\"text\" size=\"50\" name=\"" . $this->getWidgetBase() . "\" />";
  173 + }
  174 + }
  175 +
  176 + function getNotWidget() {
  177 + // not perfect, but acceptable.
  178 + $form_name = $this->getWidgetBase() . '_not';
  179 + if (!$this->bContains) {
  180 + $not_string = _kt('is not');
  181 + $is_string = _kt('is');
168 182 } else {
169   - return "<input type=\"text\" size=\"50\" name=\"" . $this->getWidgetBase() . "\" />";
  183 + $not_string = _kt('does not contain');
  184 + $is_string = _kt('contains');
170 185 }
  186 + $widget = sprintf('<select name="%s"><option value="0">%s</option><option value="1">%s</option></select>&nbsp;', $form_name, $is_string, $not_string);
  187 + return $widget;
171 188 }
172 189  
173 190 function getWidgetBase () {
... ... @@ -178,12 +195,26 @@ class BrowseCriterion {
178 195 return $this->sSearchTable;
179 196 }
180 197  
181   - function searchSQL ($aRequest) {
  198 + function searchSQL ($aRequest, $handle_not = true) {
  199 + $val = null;
182 200 if ($this->bString) {
183   - return array($this->getSearchTable() . "." . $this->getSearchField() . " LIKE '%" . DBUtil::escapeSimple($aRequest[$this->getWidgetBase()]) . "%'", array());
  201 + $val = array($this->getSearchTable() . "." . $this->getSearchField() . " LIKE '%" . DBUtil::escapeSimple($aRequest[$this->getWidgetBase()]) . "%'", array());
184 202 } else {
185   - return array($this->getSearchTable() . "." . $this->getSearchField() . " = ?", array($aRequest[$this->getWidgetBase()]));
  203 + $val = array($this->getSearchTable() . "." . $this->getSearchField() . " = ?", array($aRequest[$this->getWidgetBase()]));
  204 + }
  205 +
  206 + // handle the boolean "not" stuff UNLESS our caller is doing so already.
  207 + if ($handle_not) {
  208 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  209 +
  210 + if (is_null($want_invert)) {
  211 + return $val;
  212 + } else {
  213 + $val[0] = '(NOT (' . $val[0] . '))';
  214 + }
186 215 }
  216 +
  217 + return $val;
187 218 }
188 219  
189 220 function searchJoinSQL () {
... ... @@ -195,6 +226,8 @@ class NameCriterion extends BrowseCriterion {
195 226 var $bFolderCriterion = true;
196 227 var $bString = true;
197 228 var $sSearchTable = "DC";
  229 + var $bContains = true;
  230 +
198 231 function documentDisplay ($oDocument) {
199 232 $aOptions = $this->aOptions;
200 233 if (array_key_exists('displayFullPath', $aOptions)) {
... ... @@ -238,6 +271,8 @@ class TitleCriterion extends BrowseCriterion {
238 271 var $bFolderCriterion = true;
239 272 var $bString = true;
240 273 var $sSearchTable = "DM";
  274 + var $bContains = true;
  275 +
241 276 function documentDisplay ($oDocument) {
242 277 return $oDocument->getName();
243 278 }
... ... @@ -257,6 +292,7 @@ class CreatorCriterion extends BrowseCriterion {
257 292 "table" => "users",
258 293 "field" => "name",
259 294 );
  295 +
260 296 function documentDisplay ($oDocument) {
261 297 $oCreator = User::get($oDocument->getCreatorID());
262 298 if ($oCreator) {
... ... @@ -270,12 +306,12 @@ class CreatorCriterion extends BrowseCriterion {
270 306 function searchWidget ($aRequest, $aPreValue = null) {
271 307 $preval = null;
272 308 if ($aPreValue != null) {
273   - // !#@&)*( (*&!@# *(&@!(*&!@#
  309 + // !#@&)*( (*&!@# *(&@NOT (*&!@#
274 310 $k = array_keys($aPreValue);
275 311 $k = $k[0];
276 312 $preval = $aPreValue[$k];
277 313 }
278   - $sRet = "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
  314 + $sRet = $this->getNotWidget() . "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
279 315 $aUsers = User::getList();/*ok*/
280 316 $sRet .= "<option value=\"-1\">None</option>\n";
281 317 foreach ($aUsers as $oUser) {
... ... @@ -309,7 +345,8 @@ class DateCreatedCriterion extends BrowseCriterion {
309 345 $sToRender .= " &nbsp; Before date: <input type=\"text\" size=\"10\" name=\"" . $sEndWidget . "\" />";
310 346 $sToRender .= "&nbsp;&nbsp;<a href=\"javascript:show_calendar('MainForm." . $sEndWidget . "',null,null,'YYYY-MM-DD', false);\" onmouseover=\"window.status='Date Picker';return true;\" onmouseout=\"window.status='';return true;\"><img src=\"$default->graphicsUrl/calendar/calendar.gif\" name=\"imgCalendar\" width=\"34\" height=\"21\" border=\"0\" alt=\"\"></a>";
311 347 */
312   - $sToRender = 'After Date: <span class="kt_calendar_holder"><strong class="kt_calendar_datetext">' . $aPreValue[$sStartWidget] . '</strong><input type="hidden" name="' . $sStartWidget . '" class="kt_calendar_value" value="' . $aPreValue[$sStartWidget] . '"/> <input type="button" onclick="init_kt_calendar(this);" value="select"></span> &mdash; ';
  348 + $sToRender = $this->getNotWidget();
  349 + $sToRender .= 'After Date: <span class="kt_calendar_holder"><strong class="kt_calendar_datetext">' . $aPreValue[$sStartWidget] . '</strong><input type="hidden" name="' . $sStartWidget . '" class="kt_calendar_value" value="' . $aPreValue[$sStartWidget] . '"/> <input type="button" onclick="init_kt_calendar(this);" value="select"></span> and ';
313 350 $sToRender .= 'Before Date: <span class="kt_calendar_holder"><strong class="kt_calendar_datetext">' . $aPreValue[$sStartWidget] . '</strong><input type="hidden" name="' . $sEndWidget . '" class="kt_calendar_value" value="' . $aPreValue[$sEndWidget] . '"/> <input type="button" onclick="init_kt_calendar(this);" value="select"></span><br />';
314 351 return $sToRender;
315 352 }
... ... @@ -328,16 +365,30 @@ class DateCreatedCriterion extends BrowseCriterion {
328 365 } else {
329 366 $sEnd = $aRequest[$this->getWidgetBase() . "_end"];
330 367 }
  368 +
  369 +
  370 + $val = null;
331 371 if ($sStart && $sEnd) {
332   - return array($this->getSearchTable() . "." . $this->getSearchField() . " BETWEEN ? AND ?", array($sStart, $sEnd));
333   - }
334   - if ($sStart) {
335   - return array($this->getSearchTable() . "." . $this->getSearchField() . " > ?", array($sStart));
336   - }
337   - if ($sEnd) {
338   - return array($this->getSearchTable() . "." . $this->getSearchField() . " < ?", array($sEnd));
  372 + $val = array($this->getSearchTable() . "." . $this->getSearchField() . " BETWEEN ? AND ?", array($sStart, $sEnd));
  373 + } else if ($sStart) {
  374 + $val = array($this->getSearchTable() . "." . $this->getSearchField() . " > ?", array($sStart));
  375 + } else if ($sEnd) {
  376 + $val = array($this->getSearchTable() . "." . $this->getSearchField() . " < ?", array($sEnd));
  377 + } else {
  378 + return null;
  379 + }
  380 +
  381 + // handle the boolean "not" stuff.
  382 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  383 +
  384 + if (is_null($want_invert)) {
  385 + return $val;
  386 + } else {
  387 + $val[0] = '(NOT (' . $val[0] . '))';
339 388 }
340   - return null;
  389 +
  390 + // finally
  391 + return $val;
341 392 }
342 393  
343 394 }
... ... @@ -359,12 +410,13 @@ class DocumentTypeCriterion extends BrowseCriterion {
359 410 function searchWidget ($aRequest, $aPreValue = null) {
360 411 $preval = null;
361 412 if ($aPreValue != null) {
362   - // !#@&)*( (*&!@# *(&@!(*&!@#
  413 + // !#@&)*( (*&!@# *(&@NOT (*&!@#
363 414 $k = array_keys($aPreValue);
364 415 $k = $k[0];
365 416 $preval = $aPreValue[$k];
366 417 }
367   - $sRet = "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
  418 + $sRet = $this->getNotWidget();
  419 + $sRet .= "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
368 420 $aUsers = DocumentType::getList();/*ok*/
369 421 $sRet .= "<option value=\"-1\">None</option>\n";
370 422 foreach ($aUsers as $oUser) {
... ... @@ -422,17 +474,19 @@ class GenericMetadataCriterion extends BrowseCriterion {
422 474 function searchWidget ($aRequest, $aPreValue = null) {
423 475 $preval = null;
424 476 if ($aPreValue != null) {
425   - // !#@&)*( (*&!@# *(&@!(*&!@#
  477 + // !#@&)*( (*&!@# *(&@NOT (*&!@#
426 478 $k = array_keys($aPreValue);
427 479 $k = $k[0];
428 480 $preval = $aPreValue[$k];
429 481 }
430 482 // If there's no lookup, just use the standard text input
431 483 if ($this->oField->getHasLookup() == false) {
  484 + $this->bContains = true; // contains
432 485 return parent::searchWidget($aRequest, $aPreValue);
433 486 }
434   -
435   - $sRet = "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
  487 + $this->bContains = false; // is
  488 + $sRet = $this->getNotWidget();
  489 + $sRet .= "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
436 490 $aSearch = array('document_field_id = ?', $this->getID());
437 491 $aMetaData = MetaData::getByDocumentField(DocumentField::get($this->getID()));/*ok*/
438 492 $sRet .= "<option value=\"-1\">None</option>\n";
... ... @@ -446,9 +500,18 @@ class GenericMetadataCriterion extends BrowseCriterion {
446 500 }
447 501  
448 502 function searchSQL ($aRequest) {
449   - $p = parent::searchSQL($aRequest);
  503 + $p = parent::searchSQL($aRequest, false); // handle not ourselves.
450 504 $p[0] = join(' AND ', array($p[0], "$this->sSearchTable.document_field_id = ?"));
451 505 $p[1] = array_merge($p[1], array($this->iID));
  506 +
  507 + // handle the boolean "not" stuff.
  508 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  509 + if (is_null($want_invert)) {
  510 + return $p;
  511 + } else {
  512 + $p[0] = '(NOT (' . $p[0] . '))';
  513 + }
  514 +
452 515 return $p;
453 516 }
454 517  
... ... @@ -483,6 +546,7 @@ class SizeCriterion extends BrowseCriterion {
483 546 }
484 547  
485 548 class ContentCriterion extends BrowseCriterion {
  549 + var $bContains = true;
486 550 function documentDisplay ($oDocument) {
487 551 return "Content";
488 552 }
... ... @@ -501,7 +565,32 @@ class ContentCriterion extends BrowseCriterion {
501 565  
502 566 $p = array();
503 567 $p[0] = "MATCH(DT.document_text) AGAINST (? $boolean_mode)";
504   - $p[1] = $aRequest[$this->getWidgetBase()];
  568 +
  569 +
  570 +
  571 + if ($RESTRICTING_SEARCH) {
  572 + $q_set = KTUtil::phraseSplit($aRequest[$this->getWidgetBase()]);
  573 + $temp = $q_set;
  574 + foreach ($temp as $k => $v) {
  575 + $t = array();
  576 + foreach ($v as $part) {
  577 + $t[] = sprintf('+"%s"', $part);
  578 + }
  579 + $q_set[$k] = join(' ', $t);
  580 + }
  581 + $p[1] = implode(' ',$q_set);
  582 + } else {
  583 + $p[1] = $aRequest[$this->getWidgetBase()];
  584 + }
  585 +
  586 + // handle the boolean "not" stuff.
  587 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  588 + if (is_null($want_invert)) {
  589 + return $p;
  590 + } else {
  591 + $p[0] = '(NOT (' . $p[0] . '))';
  592 + }
  593 +
505 594 return $p;
506 595 }
507 596  
... ... @@ -530,19 +619,27 @@ class WorkflowStateCriterion extends BrowseCriterion {
530 619 $p = array();
531 620 $p[0] = "D.workflow_state_id = ?";
532 621 $p[1] = $aRequest[$this->getWidgetBase()];
  622 +
  623 + // handle the boolean "not" stuff.
  624 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  625 + if (is_null($want_invert)) {
  626 + return $p;
  627 + } else {
  628 + $p[0] = '(NOT (' . $p[0] . '))';
  629 + }
533 630 return $p;
534 631 }
535 632  
536 633 function searchWidget ($aRequest, $aPreValue = null) {
537 634 $preval = null;
538 635 if ($aPreValue != null) {
539   - // !#@&)*( (*&!@# *(&@!(*&!@#
  636 + // !#@&)*( (*&!@# *(&@NOT (*&!@#
540 637 $k = array_keys($aPreValue);
541 638 $k = $k[0];
542 639 $preval = $aPreValue[$k];
543 640 }
544   -
545   - $sRet = "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
  641 + $sRet = $this->getNotWidget();
  642 + $sRet .= "<select size=\"1\" name=\"" . $this->getWidgetBase() . "\">\n";
546 643 $aStates = KTWorkflowState::getList("ORDER BY workflow_id");
547 644 $sRet .= "<option value=\"-1\">None</option>\n";
548 645 foreach ($aStates as $oState) {
... ... @@ -557,6 +654,7 @@ class WorkflowStateCriterion extends BrowseCriterion {
557 654 }
558 655  
559 656 class TransactionTextCriterion extends BrowseCriterion {
  657 + var $bContains = true;
560 658 function documentDisplay ($oDocument) {
561 659 return "Transaction text";
562 660 }
... ... @@ -575,7 +673,32 @@ class TransactionTextCriterion extends BrowseCriterion {
575 673  
576 674 $p = array();
577 675 $p[0] = "MATCH(DTT.document_text) AGAINST (? $boolean_mode)";
578   - $p[1] = $aRequest[$this->getWidgetBase()];
  676 +
  677 +
  678 +
  679 + if ($RESTRICTING_SEARCH) {
  680 + $q_set = KTUtil::phraseSplit($aRequest[$this->getWidgetBase()]);
  681 + $temp = $q_set;
  682 + foreach ($temp as $k => $v) {
  683 + $t = array();
  684 + foreach ($v as $part) {
  685 + $t[] = sprintf('+"%s"', $part);
  686 + }
  687 + $q_set[$k] = join(' ', $t);
  688 + }
  689 + $p[1] = implode(' ',$q_set);
  690 + } else {
  691 + $p[1] = $aRequest[$this->getWidgetBase()];
  692 + }
  693 +
  694 + // handle the boolean "not" stuff.
  695 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  696 + if (is_null($want_invert)) {
  697 + return $p;
  698 + } else {
  699 + $p[0] = '(NOT (' . $p[0] . '))';
  700 + }
  701 +
579 702 return $p;
580 703 }
581 704  
... ... @@ -586,6 +709,7 @@ class TransactionTextCriterion extends BrowseCriterion {
586 709 }
587 710  
588 711 class SearchableTextCriterion extends BrowseCriterion {
  712 + var $bContains = true;
589 713 function documentDisplay ($oDocument) {
590 714 return "Searchable text";
591 715 }
... ... @@ -605,7 +729,7 @@ class SearchableTextCriterion extends BrowseCriterion {
605 729 $p = array();
606 730 $p[0] = "MATCH(DST.document_text) AGAINST (? $boolean_mode)";
607 731  
608   - $RESTRICTING_SEARCH = true;
  732 +
609 733  
610 734 if ($RESTRICTING_SEARCH) {
611 735 $q_set = KTUtil::phraseSplit($aRequest[$this->getWidgetBase()]);
... ... @@ -621,6 +745,15 @@ class SearchableTextCriterion extends BrowseCriterion {
621 745 } else {
622 746 $p[1] = $aRequest[$this->getWidgetBase()];
623 747 }
  748 +
  749 + // handle the boolean "not" stuff.
  750 + $want_invert = KTUtil::arrayGet($aRequest, $this->getWidgetBase() . '_not');
  751 + if (is_null($want_invert)) {
  752 + return $p;
  753 + } else {
  754 + $p[0] = '(NOT (' . $p[0] . '))';
  755 + }
  756 +
624 757 return $p;
625 758 }
626 759  
... ... @@ -631,6 +764,7 @@ class SearchableTextCriterion extends BrowseCriterion {
631 764 }
632 765  
633 766 class Criteria {
  767 +
634 768 function &_getBaseCriterionByNumber($iID) {
635 769 global $default;
636 770 switch ($iID) {
... ...