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