From 6dfd44b731a3b1547351c80805100e6b540b35bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Espi=C3=A9?= Date: Thu, 12 Apr 2018 09:51:32 +0000 Subject: [PATCH] Advanced Search: Small bug fixes and enhancements SVN:trunk[5636] --- application/displayblock.class.inc.php | 12 ++++- core/attributedef.class.inc.php | 27 +++++----- core/oql/expression.class.inc.php | 1 - pages/ajax.searchform.php | 9 ++++ .../criteriontooql.class.inc.php | 11 +++++ .../criterionconversionabstract.class.inc.php | 1 + .../search/searchform.class.inc.php | 49 +++++++++++++------ 7 files changed, 81 insertions(+), 29 deletions(-) diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 1574966de..eac1dd655 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -272,7 +272,17 @@ class DisplayBlock return $sHtml; } - + + /** + * @param \WebPage $oPage + * @param array $aExtraParams + * + * @throws \ApplicationException + * @throws \CoreException + * @throws \CoreWarning + * @throws \DictExceptionMissingString + * @throws \MySQLException + */ public function RenderContent(WebPage $oPage, $aExtraParams = array()) { if (!isset($aExtraParams['currentId'])) diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index fa60d0fe8..03179137d 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -2290,7 +2290,7 @@ class AttributeString extends AttributeDBField */ class AttributeClass extends AttributeString { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_ENUM; static public function ListExpectedParams() { @@ -2344,7 +2344,7 @@ class AttributeClass extends AttributeString */ class AttributeApplicationLanguage extends AttributeString { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; static public function ListExpectedParams() { @@ -2382,7 +2382,7 @@ class AttributeApplicationLanguage extends AttributeString */ class AttributeFinalClass extends AttributeString { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; public function __construct($sCode, $aParams) { @@ -3036,7 +3036,7 @@ class AttributeLongText extends AttributeText */ class AttributeCaseLog extends AttributeLongText { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; public function GetNullValue() { @@ -3457,7 +3457,7 @@ class AttributeIPAddress extends AttributeString */ class AttributeOQL extends AttributeText { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; public function GetEditClass() {return "OQLExpression";} } @@ -3469,7 +3469,7 @@ class AttributeOQL extends AttributeText */ class AttributeTemplateString extends AttributeString { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; } /** @@ -3479,7 +3479,7 @@ class AttributeTemplateString extends AttributeString */ class AttributeTemplateText extends AttributeText { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; } /** @@ -3489,7 +3489,7 @@ class AttributeTemplateText extends AttributeText */ class AttributeTemplateHTML extends AttributeText { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; public function GetSQLColumns($bFullSpec = false) { @@ -5003,10 +5003,13 @@ class AttributeExternalField extends AttributeDefinition try { - $oRemoteAtt = $this->GetExtAttDef(); - if ($oRemoteAtt instanceof AttributeString) + $oRemoteAtt = $this->GetFinalAttDef(); + switch (true) { - return self::SEARCH_WIDGET_TYPE_EXTERNAL_FIELD; + case ($oRemoteAtt instanceof AttributeString): + return self::SEARCH_WIDGET_TYPE_EXTERNAL_FIELD; + case ($oRemoteAtt instanceof AttributeExternalKey): + return self::SEARCH_WIDGET_TYPE_EXTERNAL_KEY; } } catch (CoreException $e) @@ -7528,7 +7531,7 @@ class AttributeRedundancySettings extends AttributeDBField */ class AttributeCustomFields extends AttributeDefinition { - const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING; + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; static public function ListExpectedParams() { diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php index deae190c4..a9d3fa5df 100644 --- a/core/oql/expression.class.inc.php +++ b/core/oql/expression.class.inc.php @@ -1039,7 +1039,6 @@ class FieldExpression extends UnaryExpression { if ($sSearchType == AttributeDefinition::SEARCH_WIDGET_TYPE_EXTERNAL_KEY) { - // TODO Check the type of external key ? (EXTKEY_ABSOLUTE or EXTKEY_RELATIVE) if (MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass())) { $sSearchType = AttributeDefinition::SEARCH_WIDGET_TYPE_HIERARCHICAL_KEY; diff --git a/pages/ajax.searchform.php b/pages/ajax.searchform.php index ec161ae48..dc2d58567 100644 --- a/pages/ajax.searchform.php +++ b/pages/ajax.searchform.php @@ -131,6 +131,15 @@ try // note: transform to cope with XSS attacks echo '
' . htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8') . '
'; IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString()); +} catch (MySQLException $e) +{ + http_response_code(500); + // Sanytize error: + $sMsg = $e->GetMessage(); + $sMsg = preg_replace("@^.* mysql_error = @", '', $sMsg); + // note: transform to cope with XSS attacks + echo '
'.htmlentities($sMsg, ENT_QUOTES, 'utf-8').'
'; + IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString()); } catch (Exception $e) { http_response_code(500); diff --git a/sources/application/search/criterionconversion/criteriontooql.class.inc.php b/sources/application/search/criterionconversion/criteriontooql.class.inc.php index 2da91a4fa..bcf1f7c2f 100644 --- a/sources/application/search/criterionconversion/criteriontooql.class.inc.php +++ b/sources/application/search/criterionconversion/criteriontooql.class.inc.php @@ -68,6 +68,7 @@ class CriterionToOQL extends CriterionConversionAbstract self::OP_NOT_EMPTY => 'NotEmptyToOql', self::OP_BETWEEN_DATES => 'BetweenDatesToOql', self::OP_BETWEEN => 'BetweenToOql', + self::OP_REGEXP => 'RegexpToOql', self::OP_IN => 'InToOql', self::OP_ALL => 'AllToOql', ); @@ -148,6 +149,16 @@ class CriterionToOQL extends CriterionConversionAbstract return "({$sRef} = '{$sValue}')"; } + protected static function RegexpToOql($sRef, $aCriteria) + { + $aValues = self::GetValues($aCriteria); + $sValue = self::GetValue($aValues, 0); + + if (empty($sValue)) return "1"; + + return "({$sRef} REGEXP '{$sValue}')"; + } + protected static function EmptyToOql($sRef, $aCriteria) { if (isset($aCriteria['widget'])) diff --git a/sources/application/search/criterionconversionabstract.class.inc.php b/sources/application/search/criterionconversionabstract.class.inc.php index 8a5b83284..d4296edbf 100644 --- a/sources/application/search/criterionconversionabstract.class.inc.php +++ b/sources/application/search/criterionconversionabstract.class.inc.php @@ -35,6 +35,7 @@ abstract class CriterionConversionAbstract const OP_IN = 'IN'; const OP_BETWEEN_DATES = 'between_dates'; const OP_BETWEEN = 'between'; + const OP_REGEXP = 'REGEXP'; const OP_ALL = 'all'; } diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php index 34f947905..d016c4132 100644 --- a/sources/application/search/searchform.class.inc.php +++ b/sources/application/search/searchform.class.inc.php @@ -25,6 +25,7 @@ namespace Combodo\iTop\Application\Search; use ApplicationContext; use AttributeDefinition; +use AttributeExternalField; use CMDBObjectSet; use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm; use CoreException; @@ -144,7 +145,7 @@ class SearchForm } else { - // Serach for child classes + // Search for child classes foreach($mSubmitParam as $sConfigClass => $bFlag) { $aChildClasses = MetaModel::EnumChildClasses($sConfigClass); @@ -230,13 +231,6 @@ class SearchForm $aMonthsShort = array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'), Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short')); - -// $sDateTimeFormat = \AttributeDateTime::GetFormat()->ToMomentJS('%s'); -// $iDateTimeSeparatorPos = strpos($sDateTimeFormat, ' '); -// $sDateFormat = substr($sDateTimeFormat, 0, $iDateTimeSeparatorPos); -// $sTimeFormat = substr($sDateTimeFormat, $iDateTimeSeparatorPos + 1); - - $sDateTimeFormat = \AttributeDateTime::GetFormat()->ToDatePicker(); $iDateTimeSeparatorPos = strpos($sDateTimeFormat, ' '); $sDateFormat = substr($sDateTimeFormat, 0, $iDateTimeSeparatorPos); @@ -264,7 +258,6 @@ class SearchForm 'dayNamesMin' => $aDaysMin, 'monthNamesShort' => $aMonthsShort, 'firstDay' => (int) Dict::S('Calendar-FirstDayOfWeek'), -// 'format' => \AttributeDateTime::GetFormat()->ToDatePicker() 'dateFormat' => $sDateFormat, 'timeFormat' => $sTimeFormat, ), @@ -334,6 +327,15 @@ class SearchForm */ protected function PopulateFieldList($sClass, $sAlias, &$aZList, &$aOthers) { + $aDBIndexes = MetaModel::DBGetIndexes($sClass); + $aIndexes = array(); + foreach($aDBIndexes as $aIndexGroup) + { + foreach($aIndexGroup as $sIndex) + { + $aIndexes[$sIndex] = true; + } + } $aAttributeDefs = MetaModel::ListAttributeDefs($sClass); $aList = MetaModel::GetZListItems($sClass, 'standard_search'); $bHasFriendlyname = false; @@ -341,8 +343,13 @@ class SearchForm { if (array_key_exists($sAttCode, $aAttributeDefs)) { + $bHasIndex = false; + if (isset($aIndexes[$sAttCode])) + { + $bHasIndex = true; + } $oAttDef = $aAttributeDefs[$sAttCode]; - $aZList = $this->AppendField($sClass, $sAlias, $sAttCode, $oAttDef, $aZList); + $aZList = $this->AppendField($sClass, $sAlias, $sAttCode, $oAttDef, $aZList, $bHasIndex); unset($aAttributeDefs[$sAttCode]); } if ($sAttCode == 'friendlyname') @@ -499,16 +506,18 @@ class SearchForm $aFields = array_merge($aNewFields, $aFields); return $aFields; } + /** * @param $sClass * @param $sClassAlias * @param $sAttCode * @param $oAttDef * @param $aFields + * @param bool $bHasIndex * * @return mixed */ - private function AppendField($sClass, $sClassAlias, $sAttCode, $oAttDef, $aFields) + private function AppendField($sClass, $sClassAlias, $sAttCode, $oAttDef, $aFields, $bHasIndex = false) { if (!is_null($oAttDef) && ($oAttDef->GetSearchType() != AttributeDefinition::SEARCH_WIDGET_TYPE_RAW)) { @@ -534,14 +543,23 @@ class SearchForm $sLabel = $oAttDef->GetLabel(); } } - - if (method_exists($oAttDef, 'GetTargetClass')) + + if ($oAttDef instanceof AttributeExternalField) { - $sTargetClass = $oAttDef->GetTargetClass(); + $oTargetAttDef = $oAttDef->GetFinalAttDef(); } else { - $sTargetClass = $oAttDef->GetHostClass(); + $oTargetAttDef = $oAttDef; + } + + if (method_exists($oTargetAttDef, 'GetTargetClass')) + { + $sTargetClass = $oTargetAttDef->GetTargetClass(); + } + else + { + $sTargetClass = $oTargetAttDef->GetHostClass(); } $aField = array(); @@ -553,6 +571,7 @@ class SearchForm $aField['widget'] = $oAttDef->GetSearchType(); $aField['allowed_values'] = self::GetFieldAllowedValues($oAttDef); $aField['is_null_allowed'] = $oAttDef->IsNullAllowed(); + $aField['has_index'] = $bHasIndex; $aFields[$sClassAlias.'.'.$sAttCode] = $aField; // Sub items