kenken999/php
0
1<?php2 3require_once(getabspath('classes/searchclause_base.php'));4 5class SearchClause extends SearchClauseBase6{7 /**8 * Array with all session data9 * @var array10 */11 public $_where = array(); //?12 13 /**14 * Name of current table, for which instance of class was created15 * @var string16 */17 public $tName = "";18 19 /**20 * Name of current page21 * @var string22 */23 public $pageName = "";24 25 26 /**27 * Array of fields for basic search28 * @var array29 */30 public $searchFieldsArr = array();31 32 protected $googleLikeFields = array();33 34 /**35 * Type of search36 * @var string37 */38 protected $srchType = 'integrated';39 40 /**41 * Session vars pref42 * @var string43 */44 protected $sessionPrefix = "";45 46 /**47 * Indicator, if used search it will be true48 * @deprecated49 * @var Boolean50 */51 protected $bIsUsedSrch = false;52 53 /**54 * An indicator showing if filters functionality is activated55 * @var Boolean56 */57 public $filtersActivated = false;58 59 /**60 * Indicator, if started simple or google-like search"61 * @var Boolean62 */63 public $simpleSearchActive = false;64 65 /**66 * Indicator, if started search is Advanced or from Search Panel67 * @var Boolean68 */69 protected $advancedSearchActive = false;70 71 /**72 * Indicator, if request have agregate fields it will be true73 * @type Boolean74 */75 protected $haveAggregateFields = false;76 77 protected $panelSearchFields = array(); //?78 79 public $cipherer = null;80 public $pSetSearch;81 82 protected $searchOptions = array();83 84 protected $fieldDelimiterLeft = ')';85 protected $fieldDelimiterRight = '(';86 protected $valueDelimiter = '~';87 88 protected $fieldsUsedForSearch = array();89 90 /**91 * Local instance of EditControlsContainer. Use only for compatibility with business templates92 * @var object93 */94 protected $localEditControls = null;95 96 /**97 * Indicator, if used "show basic search options" field it will be true98 * @var boolean99 */100 protected $isShowSimpleSrchOpt = false;101 102 /**103 * The array to store search params ('q', 'qs', 'f')104 * extracted from REQUEST to use them for search saving105 * @type Array106 */107 protected $searchParams = array();108 109 public $savedSearchIsRun = false;110 111 /**112 * The associative array containing the filtered fields data113 * @var array114 */115 protected $filteredFields = array();116 117 /**118 * @type Boolean119 */120 protected $searchSavingEnabled = false;121 122 protected $dashTName = "";123 124 125 /**126 * If the whole Dashboard (combined) search is in effect127 * @type bool128 */129 protected $wholeDashboardSearch = false;130 131 protected $dashboardSearchClause = null;132 133 134 /**135 * @type Array136 */137 protected $customFieldSQLConditions;138 139 /**140 * @constructor141 */142 function __construct(&$params)143 {144 $this->setSearchOptions();145 146 $this->tName = $params['tName'];147 $this->sessionPrefix = $params['sessionPrefix'] ? $params['sessionPrefix'] : $this->tName;148 $this->cipherer = $params['cipherer'];149 $this->pageName = $params['pageName'];150 151 $this->pSetSearch = new ProjectSettings($this->tName, PAGE_SEARCH, $this->pageName);152 if( !$this->cipherer )153 $this->cipherer = new RunnerCipherer( $this->tName, $this->pSetSearch );154 155 $this->searchFieldsArr = ( $params['searchFieldsArr'] ? $params['searchFieldsArr'] : $this->pSetSearch->getSearchableFields() ); // searchable field (could be added to the search panel)156 $this->panelSearchFields = ($params['panelSearchFields'] ? $params['panelSearchFields'] : $this->pSetSearch->getPanelSearchFields()); // fields that are always on the search panel157 $this->googleLikeFields = ($params['googleLikeFields'] ? $params['googleLikeFields'] : $this->pSetSearch->getGoogleLikeFields()); // simple search fields158 159 $this->isShowSimpleSrchOpt = $this->pSetSearch->showSimpleSearchOptions();160 $this->searchSavingEnabled = $params['searchSavingEnabled'] ? $params['searchSavingEnabled'] : false;161 162 $this->dashTName = $params['dashTName'] ? $params['dashTName'] : "";163 164 if( $params['haveAggregateFields'] )165 $this->haveAggregateFields = true;166 167 $this->customFieldSQLConditions = array();168 }169 170 /**171 * set searchOptions array172 */173 protected function setSearchOptions()174 {175 $this->searchOptions["contains"] = array("option" => "Contains", "not" => false);176 $this->searchOptions["equals"] = array("option" => "Equals", "not" => false);177 $this->searchOptions["startswith"] = array("option" => "Starts with", "not" => false);178 $this->searchOptions["morethan"] = array("option" => "More than", "not" => false);179 $this->searchOptions["lessthan"] = array("option" => "Less than", "not" => false);180 $this->searchOptions["between"] = array("option" => "Between", "not" => false);181 $this->searchOptions["empty"] = array("option" => "Empty", "not" => false);182 183 $this->searchOptions["lessequal"] = array("option" => "More than", "not" => true);184 $this->searchOptions["moreequal"] = array("option" => "Less than", "not" => true);185 186 $this->searchOptions["notcontain"] = array("option" => "Contains", "not" => true);187 $this->searchOptions["notequal"] = array("option" => "Equals", "not" => true);188 $this->searchOptions["notstartwith"] = array("option" => "Starts with", "not" => true);189 $this->searchOptions["notmorethan"] = array("option" => "More than", "not" => true);190 $this->searchOptions["notlessthan"] = array("option" => "Less than", "not" => true);191 $this->searchOptions["notbetween"] = array("option" => "Between", "not" => true);192 $this->searchOptions["notempty"] = array("option" => "Empty", "not" => true);193 }194 195 /**196 *197 */198 protected function getLocalEditControls()199 {200 include_once getabspath("classes/controls/EditControlsContainer.php");201 return new EditControlsContainer(null, $this->pSetSearch, PAGE_SEARCH, $this->cipherer);202 }203 204 /**205 * In case the filter value contains the added partent filters values ("|"-separeated)206 * it returns an array of filter's and its parent filters values.207 * Otherwise the returning array contains at most the own filter's value208 * @param String fValue209 * @return Array210 */211 protected function getUnescapedFValues($fValue)212 {213 $start = 0;214 $unescapedValues = array();215 $valueLength = strlen($fValue);216 217 if( !$valueLength )218 return $unescapedValues;219 220 for($i = 0; $i < $valueLength; $i++)221 {222 if( $fValue[$i] != "|" )223 continue;224 if( $i > 0 )225 {226 if( $fValue[$i - 1] == "\\" )227 continue;228 }229 $unescapedValues[] = str_replace( '\\|', '|', substr($fValue, $start, $i - $start) );230 $start = $i + 1;231 }232 233 if( $start < $valueLength )234 $unescapedValues[] = str_replace( '\\|', '|', substr($fValue, $start, $valueLength - $start) );235 236 return $unescapedValues;237 }238 239 /**240 * Parse form with union search REQUEST (for new versions: 6.2 and newest)241 * Params are common for advanced search and search panel on list242 * Use in new projects243 *244 * @protected245 * @return string246 */247 function parseItegratedRequest()248 {249 global $suggestAllContent;250 251 $this->setStorage( "qs", postvalue('qs') );252 $this->setStorage( "q", postvalue('q') );253 254 255 $this->fieldsUsedForSearch = array();256 257 $this->_where["simpleSrchTypeComboOpt"] = $suggestAllContent ? "Contains" : "Starts with";258 $this->_where["simpleSrchTypeComboNot"] = false;259 $this->_where["simpleSrchFieldsComboOpt"] = '';260 261 $tempArr = $this->parseStringToArray( postvalue('qs') );262 $simpleQueryArr = $tempArr[0];263 if( $this->wholeDashboardSearch )264 $simpleQueryArr = $this->getSimpleSearchFromDashboard();265 266 $this->_where["_simpleSrch" ] = $this->searchUnEscape( $simpleQueryArr[0] );267 $this->simpleSearchActive = $simpleQueryArr[0] != '';268 269 if($this->simpleSearchActive && $this->wholeDashboardSearch)270 {271 $this->googleLikeFields = $this->getGoogleLikeFieldsFromDashboard();272 }273 274 if(isset($this->searchOptions[$this->getArrayValueByIndex($simpleQueryArr, 2, true)]))275 {276 $simpleSrchTypeComboNot = $this->searchOptions[$simpleQueryArr[2]]["not"];277 $this->_where["simpleSrchTypeComboOpt"] = $this->searchOptions[$simpleQueryArr[2]]["option"];278 if (!strlen($this->_where["simpleSrchTypeComboOpt"]))279 {280 $this->_where["simpleSrchTypeComboOpt"] = $suggestAllContent ? "Contains" : "Starts with";281 }282 }283 284 $fieldName = trim($this->getArrayValueByIndex($simpleQueryArr, 1, true));285 $this->_where["simpleSrchFieldsComboOpt"] = $fieldName;286 if($fieldName)287 {288 $this->fieldsUsedForSearch[$fieldName] = true;289 }290 291 $srchCriteriaCombineType = postvalue("criteria");292 if( $this->wholeDashboardSearch )293 $srchCriteriaCombineType = $this->getCriteriaFromDashboard();294 295 if( !$srchCriteriaCombineType )296 $srchCriteriaCombineType = "and";297 298 $this->_where["_srchCriteriaCombineType"] = $srchCriteriaCombineType;299 300 $this->setStorage( "criteriaSearch", $this->getCriteriaCombineType() );301 302 $this->_where["_srchFields"] = array();303 304 $this->advancedSearchActive = false;305 306 $searchFieldsArr = $this->parseStringToArray(postvalue('q'), true);307 if( $this->wholeDashboardSearch )308 $searchFieldsArr = $this->getSearchFieldsFromDashboard();309 310 foreach ($searchFieldsArr as $searchItemArr)311 {312 if( count($searchItemArr) < 2 )313 continue;314 315 $fName = $this->searchUnEscape($searchItemArr[0]);316 if (false == in_array($fName, $this->searchFieldsArr))317 continue;318 319 $this->advancedSearchActive = true;320 321 $srchF = array();322 $srchF['fName'] = $fName;323 $srchF['eType'] = $this->getArrayValueByIndex($searchItemArr, 3);324 $srchF['value1'] = $this->getArrayValueByIndex($searchItemArr, 2, true);325 $opt = $this->getArrayValueByIndex($searchItemArr, 1);326 $srchF['not'] = false;327 328 if(isset($this->searchOptions[$opt]))329 {330 $srchF['not'] = $this->searchOptions[$opt]["not"];331 $srchF['opt'] = $this->searchOptions[$opt]["option"];332 }333 else334 {335 $srchF['opt'] = $this->getDefaultSearchTypeOption($fName, $this->pSetSearch);336 }337 338 if( $this->wholeDashboardSearch )339 {340 $srchF['not'] = $this->getArrayValueByIndex($searchItemArr, 5);341 }342 343 $srchF['value2'] = $this->getArrayValueByIndex($searchItemArr, 4, true);344 345 $this->_where["_srchFields"][] = $srchF;346 $this->fieldsUsedForSearch[$fName] = true;347 }348 349 // process srch panel attrs, better then use coockies.350 $this->_where["_srchOptShowStatus"]= postvalue('srchOptShowStatus')==='1';351 $this->_where["_ctrlTypeComboStatus"]= postvalue('ctrlTypeComboStatus')==='1';352 $this->_where["srchWinShowStatus"]= postvalue('srchWinShowStatus')==='1';353 }354 355 /**356 * Get criteria from dashboard search clause357 * @return String358 */359 protected function getCriteriaFromDashboard()360 {361 if( $this->dashboardSearchClause )362 return $this->dashboardSearchClause->_where['_srchCriteriaCombineType' ];363 364 return "";365 }366 367 /**368 * Get simple search from dashboard search clause369 * @return Array370 */371 function getSimpleSearchFromDashboard()372 {373 if($this->dashboardSearchClause)374 return array(0 => $this->dashboardSearchClause->_where['_simpleSrch']);375 else376 return array(0 => null);377 }378 379 /**380 * Get search fields from dashboard search clause381 * @return Array382 */383 function getSearchFieldsFromDashboard()384 {385 $result = array();386 if($this->dashboardSearchClause)387 $dashSearchFieldsSession = $this->dashboardSearchClause->_where['_srchFields'];388 else389 $dashSearchFieldsSession = null;390 391 if ($dashSearchFieldsSession)392 {393 $dashSettings = new ProjectSettings($this->dashTName, PAGE_DASHBOARD);394 $dashSearchFields = $dashSettings->getDashboardSearchFields();395 396 foreach ($dashSearchFieldsSession as $i => $data)397 {398 foreach ($dashSearchFields[ $data['fName'] ] as $j => $fData)399 {400 if ($fData['table'] != $this->tName)401 continue;402 403 $resutlData = array();404 $resutlData[0] = $fData['field'];405 406 foreach ($this->searchOptions as $opt => $optData)407 {408 if ($data['opt'] == $optData['option'])409 {410 $resutlData[1] = $opt;411 break;412 }413 }414 415 $resutlData[2] = $data['value1'];416 if ($data['eType'])417 $resutlData[3] = $data['eType'];418 419 if ($data['value2'])420 $resutlData[4] = $data['value2'];421 422 $resutlData[5] = $data['not'];423 424 $result[] = $resutlData;425 }426 }427 }428 429 return $result;430 }431 432 /**433 * Get google like fields from dashboard434 * @return Array435 */436 function getGoogleLikeFieldsFromDashboard()437 {438 $result = array();439 $dashSettings = new ProjectSettings($this->dashTName, PAGE_DASHBOARD);440 $dashGoogleLikeFields = $dashSettings->getGoogleLikeFields();441 $dashSearchFields = $dashSettings->getDashboardSearchFields();442 443 foreach ($dashGoogleLikeFields as $i => $field)444 {445 foreach ($dashSearchFields[$field] as $j => $data)446 {447 if( $data['table'] == $this->tName )448 $result[] = $data['field'];449 }450 }451 452 return $result;453 }454 455 /**456 * @param String inputString457 * @return String458 */459 function searchUnEscape($inputString)460 {461 return str_replace("\\\\", "\\",462 str_replace("\\".$this->valueDelimiter, $this->valueDelimiter,463 str_replace("\\".$this->fieldDelimiterLeft.$this->fieldDelimiterRight,464 $this->fieldDelimiterLeft.$this->fieldDelimiterRight, $inputString)));465 }466 467 /**468 * @param String inputString469 * @param Boolean advanced470 * @return Array471 */472 function parseStringToArray($inputString, $advanced = false)473 {474 if(0 == strlen($inputString))475 return array();476 $result = array();477 $valuesArray = array();478 $startPos = 0;479 if($advanced)480 $inputString = substr($inputString, 1, strlen($inputString) - 2);481 $strLength = strlen($inputString);482 for($i = 0; $i < $strLength; $i++)483 {484 if($inputString[$i] == $this->valueDelimiter)485 if($this->isDelimiter($inputString, $startPos, $i))486 {487 $valuesArray[] = trim( substr($inputString, $startPos, $i - $startPos) );488 $startPos = $i + 1;489 }490 if($i == $strLength - 1 || $inputString[$i] == $this->fieldDelimiterLeft)491 if($i == $strLength - 1 || $this->isDelimiter($inputString, $startPos, $i, true))492 {493 $valuesArray[] = trim( substr($inputString, $startPos, $i - $startPos + ($i == $strLength - 1 ? 1 : 0)) );494 $result[] = $valuesArray;495 $valuesArray = array();496 $startPos = $i + 2;497 $i++;498 }499 }500 return $result;501 }502 503 /**504 * @param &String inputString505 * @param Number startPos506 * @param Number currentPos507 * @param Boolean isFieldDelimiter (optional)508 * @return Boolean509 */510 function isDelimiter(&$inputString, $startPos, $currentPos, $isFieldDelimiter = false)511 {512 $backSlahesCount = 0;513 for($i = $currentPos - 1; $i >= $startPos; $i--)514 {515 if($inputString[$i] != '\\')516 break;517 $backSlahesCount++;518 }519 $result = $backSlahesCount == 0 || $backSlahesCount % 2 == 0;520 if($result && $isFieldDelimiter && strlen($inputString) > $currentPos + 1)521 {522 return $inputString[$currentPos + 1] == $this->fieldDelimiterRight;523 }524 return $result;525 }526 527 /**528 *529 */530 function getArrayValueByIndex(&$arr, $index, $isEncoded = false)531 {532 $result = "";533 if(isset($arr[$index]))534 {535 $result = $arr[$index];536 if($isEncoded)537 $result = $this->searchUnEscape($result);538 }539 return $result;540 }541 542 /**543 *544 */545 function getDefaultSearchTypeOption($fName, $pSet)546 {547 $fType = $pSet->getEditFormat($fName);548 $option = "Equals";549 if($fType == EDIT_FORMAT_LOOKUP_WIZARD)550 {551 if ($pSet->multiSelect($fName))552 $option = "Contains";553 }554 elseif ($fType == EDIT_FORMAT_TEXT_FIELD || $fType == EDIT_FORMAT_TEXT_AREA || $fType == EDIT_FORMAT_PASSWORD555 || $fType == EDIT_FORMAT_HIDDEN || $fType == EDIT_FORMAT_READONLY)556 {557 if(!$this->cipherer->isFieldPHPEncrypted($fName))558 $option = "Contains";559 }560 561 return $option;562 }563 564 /**565 *566 */567 protected function removeSessionSearchVariables()568 {569 if ( $this->getStorage( "qs" ) ) {570 $this->deleteStorage( "qs" );571 }572 if ( $this->getStorage( "q" ) ) {573 $this->deleteStorage( "q" );574 }575 if ( $this->getStorage( "criteriaSearch" ) ) {576 $this->deleteStorage( "criteriaSearch" );577 }578 }579 580 /**581 * Parse REQUEST582 */583 public function parseRequest()584 {585 global $requestTable, $requestPage;586 $this->wholeDashboardSearch = false;587 588 //set session if show all records589 if(@$_REQUEST["a"] == "showall" || $requestTable == $this->tName590 && ( $requestPage == "list" || $requestPage == "chart" || $requestPage == "report" || $requestPage == "dashboard" )591 && IsEmptyRequest() )592 {593 $this->resetSearch();594 }595 else if( isset($_REQUEST["q"]) || isset($_REQUEST["qs"]) || @$_REQUEST["f"] )596 {597 $this->srchType = 'integrated';598 $this->parseItegratedRequest();599 $this->bIsUsedSrch = isset($_REQUEST["q"]) && $_REQUEST["q"] !== "" || isset($_REQUEST["qs"]) && $_REQUEST["qs"] !== "";600 601 // !! move it to RunnerPage602 $this->setStorage( "pagenumber", 1 );603 }604 else if( $this->dashTName && $this->existsStorage( "advsearch", true ) )605 {606 $this->dashboardSearchClause = SearchClause::UnserializeObject( $this->getStorage( 'advsearch', true ) );607 $this->wholeDashboardSearch = $this->dashboardSearchClause->searchStarted();608 if( $this->wholeDashboardSearch )609 {610 $this->srchType = 'integrated';611 $this->parseItegratedRequest();612 $this->bIsUsedSrch = true;613 }614 else if( $this->dashboardSearchClause->srchType == 'showall' )615 {616 $this->_where["_search"] = 0;617 $this->srchType = 'showall';618 $this->bIsUsedSrch = false;619 $this->clearSearch();620 $this->simpleSearchActive = false;621 622 $this->removeSessionSearchVariables();623 }624 }625 626 //set session for filters627 if( @$_REQUEST["f"] ) {628 $this->setStorage( "filters", $_REQUEST["f"] );629 $this->filteredFields = array();630 }631 $this->filtersActivated = $this->existsStorage( "filters" ) && $this->getStorage( "filters" ) != 'all';632 633 if( $this->searchSavingEnabled )634 {635 if( isset($_REQUEST["savedSearch"]) )636 $this->savedSearchIsRun = true;637 else if( $this->isSearchFunctionalityActivated() && !$this->searchHasTheSameSearchParams() || $this->srchType == 'showall' )638 $this->savedSearchIsRun = false;639 }640 }641 642 /**643 * Fill the 'searchParams' array with extracted from REQUEST's 'q', 'qs'644 * and 'f' params to use them then for a search saving process.645 */646 public function storeSearchParamsForLogging()647 {648 if( !$this->searchSavingEnabled )649 return;650 651 if( !isset($_REQUEST["saveSearch"]) && !isset($_REQUEST["deleteSearch"]) )652 {653 if( $this->srchType == 'showall' )654 // reset the simple search and search panel params655 $this->searchParams = array( "f" => $this->searchParams["f"] );656 else if( !@$_REQUEST["goto"] && !@$_REQUEST["orderby"] && !@$_REQUEST["pagesize"] )657 // reset all stored params658 $this->searchParams = array();659 }660 661 if( isset( $_REQUEST["q"] ) )662 {663 $this->searchParams["q"] = $_REQUEST["q"];664 $this->searchParams["criteria"] = @$_REQUEST["criteria"];665 }666 667 if( isset( $_REQUEST["qs"] ) )668 $this->searchParams["qs"] = $_REQUEST["qs"];669 670 if( isset( $_REQUEST["f"] ) )671 $this->searchParams["f"] = $_REQUEST["f"];672 }673 674 /**675 * Check if the current REQUEST search params are equal to stored save search params.676 * When the pagination or sorting is activated and there are some stored search params677 * the current and stored search params are deemed the same678 * @return Boolean679 */680 public function searchHasTheSameSearchParams()681 {682 if( @$_REQUEST["goto"] || @$_REQUEST["orderby"] || @$_REQUEST["pagesize"] )683 return true;684 685 if( !$this->searchParams )686 return false;687 688 if( @$_REQUEST["q"] != $this->searchParams["q"] || @$_REQUEST["qs"] != $this->searchParams["qs"] || @$_REQUEST["f"] != $this->searchParams["f"])689 return false;690 691 return true;692 }693 694 /**695 * @return Array696 */697 public function getSearchParamsForSaving()698 {699 return $this->searchParams;700 }701 702 /**703 * Clears search params704 */705 function clearSearch()706 {707 $this->_where["_simpleSrch"] = '';708 $this->_where["_srchCriteriaCombineType"] = "and";709 $this->_where["simpleSrchTypeComboOpt"] = "Contains";710 $this->_where["simpleSrchTypeComboNot"] = false;711 $this->_where["simpleSrchFieldsComboOpt"] = '';712 // prepare vars713 $this->_where["_srchFields"] = array();714 // process srch panel attrs, better then use coockies.715 $this->_where["_srchOptShowStatus"]= false;716 $this->_where["_ctrlTypeComboStatus"]= false;717 $this->_where["srchWinShowStatus"]= false;718 719 $this->fieldsUsedForSearch = array();720 }721 722 /**723 * @param String fName724 * @return Array725 */726 public function getSearchCtrlParams($fName)727 {728 $resArr = array();729 $editControls = $this->getLocalEditControls();730 731 if( $this->_where["_srchFields"] )732 {733 foreach( $this->_where["_srchFields"] as $srchField )734 {735 if( strtolower( $srchField['fName'] ) == strtolower( $fName ) )736 {737 $tField = $srchField;738 $ctrl = $editControls->getControl( $fName );739 740 $eType = $tField["eType"];741 if( $ctrl->checkIfDisplayFieldSearch( $tField["opt"] ) )742 $eType = "display";743 744 $tField["value1"] = prepare_for_db( $tField["fName"], $tField["value1"], $eType, "", $this->tName );745 $tField["value2"] = prepare_for_db( $tField["fName"], $tField["value2"], $eType, "", $this->tName );746 747 $resArr[] = $tField;748 }749 }750 }751 752 return $resArr;753 }754 755 /**756 * @return Number757 */758 public function getUsedCtrlsCount()759 {760 if( $this->_where["_srchFields" ] )761 return count( $this->_where["_srchFields" ] );762 763 return 0;764 }765 /**766 * Global search params: use and|or, srchType panel|adv and simple search value767 * @return array768 */769 public function getSearchGlobalParams()770 {771 return array('simpleSrch' => $this->_where["_simpleSrch" ],772 'srchTypeRadio' => $this->getCriteriaCombineType(),773 'srchType'=> $this->srchType,774 'simpleSrchTypeComboOpt' => $this->_where["simpleSrchTypeComboOpt" ],775 'simpleSrchTypeComboNot' => $this->_where["simpleSrchTypeComboNot" ],776 'simpleSrchFieldsComboOpt' => $this->_where["simpleSrchFieldsComboOpt" ]777 );778 }779 780 /**781 * Search panel status indicators array. Open|closed etc782 * @return array783 */784 public function getSrchPanelAttrs()785 {786 return array('srchOptShowStatus' => ($this->_where["_srchOptShowStatus"] || $this->panelSearchFields ),787 'ctrlTypeComboStatus' => $this->_where["_ctrlTypeComboStatus"],788 'srchWinShowStatus' => $this->_where["srchWinShowStatus"]789 );790 }791 792 /**793 * Returns indicator is search was init794 * @deprecated795 * @return Boolean796 */797 public function isUsedSrch()798 {799 return $this->bIsUsedSrch;800 }801 802 /**803 * Returns indicator is show button 'Show All'804 * @return Boolean805 */806 public function isShowAll()807 {808 return $this->searchStarted();809 }810 811 /**812 * Check if search functionality is activated813 * @return Boolean814 */815 public function isSearchFunctionalityActivated() {816 //return $this->bIsUsedSrch || $this->filtersActivated || !!$this->getSearchFields();817 return $this->searchStarted() || $this->filtersActivated;818 }819 820 /**821 * Checks whether required search fields are used for the searching or not822 * @return Boolean823 */824 public function isRequiredSearchRunning()825 {826 if( !$this->searchStarted() ) {827 //the search isn't run828 return false;829 }830 831 if( $this->pSetSearch ) {832 $requiredSearchFields = $this->pSetSearch->getSearchRequiredFields();833 foreach($requiredSearchFields as $fName) {834 if( !$this->fieldsUsedForSearch[$fName] ) {835 //a required search field isn't involved in the current search836 return false;837 }838 }839 }840 return true;841 }842 843 /**844 * Forms an array containing the search words and options845 *846 * @param String fname847 * @param Array lookupParams848 * @return array | false849 */850 public function getSearchToHighlight($fname, $lookupParams = array())851 {852 // if not in search fields array853 if (!in_array($fname, $this->searchFieldsArr))854 return false;855 856 $options = array();857 858 //simple search processing859 $simpleSearch['fname'] = $this->_where["simpleSrchFieldsComboOpt"];860 $opt = $this->_where["simpleSrchTypeComboOpt"];861 862 if($this->isShowSimpleSrchOpt)863 $simpleSearch['value'] = array($this->_where["_simpleSrch"]);864 else865 $simpleSearch['value'] = $this->googleLikeParseString($this->_where["_simpleSrch"]);866 867 if( isset($simpleSearch['value']) && !!$simpleSearch['value'] && (!$simpleSearch['fname'] || $simpleSearch['fname'] == $fname) )868 {869 foreach($simpleSearch['value'] as $simpleSearchValue)870 {871 if( strlen( trim($simpleSearchValue) ) )872 $options[$opt][$fname][] = $simpleSearchValue;873 }874 }875 876 //integrated search processing877 $srchFields = $this->_where["_srchFields"];878 if( !$srchFields )879 $srchFields = array();880 881 $multiselect = $lookupParams["multiselect"];882 $needLookupProcessing = $lookupParams["needLookupProcessing"];883 884 foreach($srchFields as $srchFieldData)885 {886 if($srchFieldData['fName'] != $fname || $srchFieldData['not'])887 {888 continue;889 }890 891 $opt = $srchFieldData['opt'];892 if($opt != "Contains" && $opt != "Equals" && $opt != "Starts with")893 {894 continue;895 }896 897 898 if($needLookupProcessing && $opt == "Equals")899 {900 $options[$opt][$srchFieldData['fName']][] = implode(",", splitLookupValues( $srchFieldData['value1'] ));901 continue;902 }903 904 if(!$multiselect || $opt != "Contains")905 {906 $options[$opt][$srchFieldData['fName']][] = $srchFieldData['value1'];907 continue;908 }909 910 $values = splitLookupValues( $srchFieldData['value1'] );911 foreach($values as $value)912 {913 $options[$opt][$srchFieldData['fName']][] = $value;914 }915 }916 917 if($options['Equals'][$fname])918 return array("searchWords" => $options['Equals'][$fname], "option" => 'Equals');919 920 if($options['Starts with'][$fname])921 return array("searchWords" => $options['Starts with'][$fname], "option" => 'Starts with');922 923 if($options['Contains'][$fname])924 return array("searchWords" => $options['Contains'][$fname], "option" => 'Contains');925 926 return false;927 }928 929 /**930 * Forms an array containing the actual search word and option, if there is at least one word to highlight.931 *932 * @param String fname933 * @param String value934 * @param Boolean encoded It indicates if runner_htmlspecialchars should be applied to the search words935 * @param Array lookupParams It contains the following propeties:936 * String linkFieldValue The value of the link field if the link field differs from the displayed field937 * Boolean multiselect An indicator showing if the lookup is multiselect938 * Boolean needLookupProcessing An indicator showing if the lookup is tablebased, multiselect, with939 * the same link and displayed fields940 * @param Boolean numberFormat941 * @return Array | false942 */943 public function getSearchHighlightingData($fname, $value, $encoded, $lookupParams, $numberFormat = false )944 {945 global $useUTF8;946 947 $searchData = $this->getSearchToHighlight($fname, $lookupParams);948 if(!$searchData)949 {950 return false;951 }952 953 $searchWordArr = array();954 $searchOpt = $searchData['option'];955 956 957 foreach($searchData['searchWords'] as $searchWord)958 {959 $curSearchWord = $searchWord;960 961 //linkFieldValue and linkFieldValue params are set for lookup contols with distinct Link and Displayed fields only962 //originLinkValue param is set for multiselet lookups only963 if($searchOpt == 'Contains' && $lookupParams["originLinkValue"] == $searchWord || $searchOpt == 'Equals' && $lookupParams["linkFieldValue"] == $searchWord )964 {965 return array("searchWords" => array($value), "searchOpt" => $searchData['option']);966 }967 968 if($encoded)969 {970 $curSearchWord = runner_htmlspecialchars($curSearchWord);971 }972 973 $foundWord = $this->doHighlightMatch( $curSearchWord, $value, $searchOpt );974 if( $foundWord === "" && $numberFormat ) {975 // try correcting decimal separator976 $curSearchWord = str_replace( ',', '.', $curSearchWord );977 $foundWord = $this->doHighlightMatch( $curSearchWord, $value, $searchOpt );978 }979 if( $foundWord !== "" ) {980 $searchWordArr[] = $foundWord;981 }982 }983 984 if( !!$searchWordArr )985 {986 return array("searchWords" => $searchWordArr, "searchOpt" => $searchOpt);987 }988 989 return false;990 }991 992 /**993 * @param String994 * @param String995 * @param Boolean996 */997 protected function doHighlightMatch( $searchWord, $fieldValue, $searchOpt ) {998 global $useUTF8;999 $flags = $useUTF8 ? "iu" : "i";1000 1001 $pattern = '/'.preg_quote($searchWord,"/").'/'.$flags;1002 if($searchOpt == 'Starts with')1003 {1004 $pattern = '/^'.preg_quote($searchWord,"/").'/'.$flags;1005 }1006 1007 $isMatched = preg_match($pattern, $fieldValue, $matches);1008 if( $isMatched && ( $searchOpt != 'Equals' || $fieldValue == $matches[0] ) )1009 {1010 //get the actual search word contained in the $value string1011 $searchWord = $matches[0];1012 return $searchWord;1013 }1014 return "";1015 1016 }1017 1018 /**1019 * Google-like parse search string1020 * Input: "a b" c d "e f"1021 * Output: array("a b", "c", "d", "e f")1022 *1023 * @param string $str search string1024 * @return array1025 */1026 protected function googleLikeParseString($str)1027 {1028 $ret = array();1029 $matches = array();1030 if(preg_match_all('/(\"[^"]+\")|([^\s]+)/', $str, $matches))1031 {1032 foreach($matches[0] as $match)1033 {1034 $ret[] = ($match[0] == '"') ? substr($match, 1, -1) : $match;1035 }1036 }1037 return array_unique($ret);1038 }1039 1040 /**1041 * Informs how search criterions are combined.1042 * Returns "and" or "or";1043 *1044 * @return string1045 */1046 public function getCriteriaCombineType()1047 {1048 if( $this->_where["_srchCriteriaCombineType"] == "or" )1049 return "or";1050 1051 if( $this->simpleSearchActive && !$this->_where["_srchFields"] )1052 return "or";1053 1054 return "and";1055 }1056 1057 /**1058 *1059 */1060 public static function UnserializeObject($str)1061 {1062 if(!$str)1063 return null;1064 1065 include_once getabspath("classes/controls/EditControlsContainer.php");1066 $obj = unserialize($str);1067 1068 $obj->pSetSearch = new ProjectSettings($obj->tName, PAGE_SEARCH);1069 1070 $obj->cipherer = new RunnerCipherer($obj->tName, $obj->pSetSearch );1071 1072 return $obj;1073 }1074/*1075 public function Serialize()1076 {1077 return serialize($this);1078 // PHP7 can't serialize connection object which is linked through one of the objects1079 $_pset = $this->pSetSearch;1080 $_cipherer = $obj->cipherer;1081 $this->pSetSearch = null;1082 $obj->cipherer = null;1083 1084 $ret = serialize($this);1085 1086 $this->pSetSearch = $_pset;1087 $obj->cipherer = $_cipherer;1088 1089 return $ret;1090 1091 }1092 1093 */1094 /**1095 * User Search API1096 * @return Array1097 */1098 public function getSearchFields()1099 {1100 $fieldsData = array();1101 1102 if( $this->_where["_srchFields" ] ) { //for asp1103 foreach( $this->_where["_srchFields" ] as $ind => $sfData )1104 {1105 if( !$fieldsData[ $sfData['fName'] ] )1106 $fieldsData[ $sfData['fName'] ] = array();1107 1108 $fieldsData[ $sfData['fName'] ][] = SEARCHID_PANEL + $ind;1109 }1110 }1111 1112 if( $this->haveAggregateFields && $this->advancedSearchActive )1113 return $fieldsData;1114 1115 $simpleSrch = $this->_where["_simpleSrch" ];1116 $simpleSrchOption = $this->_where["simpleSrchTypeComboOpt" ];1117 1118 if( ( $simpleSrch == null || !strlen($simpleSrch) ) && $simpleSrchOption != "Empty" )1119 return $fieldsData;1120 1121 $simpleSrchField = $this->_where["simpleSrchFieldsComboOpt" ];1122 if( $simpleSrch != null && strlen($simpleSrchField) && in_array($simpleSrchField, $this->googleLikeFields) )1123 {1124 if( !$fieldsData[ $simpleSrchField ] )1125 $fieldsData[ $simpleSrchField ] = array();1126 1127 $fieldsData[ $simpleSrchField ][] = SEARCHID_SIMPLE;1128 }1129 1130 if( $this->isShowSimpleSrchOpt )1131 $simpleSrchArr = array( $simpleSrch );1132 else1133 $simpleSrchArr = $this->googleLikeParseString( $simpleSrch );1134 1135 foreach($simpleSrchArr as $ind => $simpleSrchItem)1136 {1137 for($i = 0; $i < count($this->searchFieldsArr); $i++)1138 {1139 if ( in_array($this->searchFieldsArr[$i], $this->googleLikeFields) )1140 {1141 if( !$fieldsData[ $this->searchFieldsArr[$i] ] )1142 $fieldsData[ $this->searchFieldsArr[$i] ] = array();1143 1144 $fieldsData[ $this->searchFieldsArr[$i] ][] = SEARCHID_ALL + $ind;1145 }1146 }1147 }1148 1149 return $fieldsData;1150 }1151 1152 /**1153 * @return Boolean1154 */1155 public function isSearchPanelByUserApiRun()1156 {1157 if ( !$this->_where["_srchFields" ] )1158 return false;1159 1160 foreach( $this->_where["_srchFields" ] as $ind => $sfData )1161 {1162 if( $sfData['byUserApi'] )1163 return true;1164 }1165 1166 return false;1167 }1168 1169 /**1170 * User Search API1171 * @param String field1172 * @param Number id1173 * @param Boolean - don't include Search for all fields value. Only individual field search1174 * @return mixed ( String | null )1175 */1176 public function getFieldValue( $field, $id = null, $returnAllFieldSearch = true )1177 {1178 return $this->_getFieldValue( $field, $id, $returnAllFieldSearch, false );1179 }1180 1181 /**1182 * @param Boolean reduce - when true convert to database value like "2000-01-1" from "1/1/2000"1183 */1184 public function _getFieldValue( $field, $id = null, $returnAllFieldSearch = true, $reduce = false ) {1185 $srchFields = &$this->_where["_srchFields" ];1186 foreach($srchFields as $ind => $srchF)1187 {1188 if( $srchF['fName'] == $field && ( $id == SEARCHID_PANEL + $ind || is_null($id) ) ) {1189 if( $reduce ) {1190 $controls = $this->getLocalEditControls();1191 $fieldControl = $controls->getControl( $field );1192 return $fieldControl->processControlValue( $srchF['value1'], $srchF['eType']);1193 } 1194 else {1195 return $srchF['value1'];1196 }1197 }1198 }1199 1200 if( $this->haveAggregateFields && $this->advancedSearchActive )