diff --git a/.idea/inspectionProfiles/iTop.xml b/.idea/inspectionProfiles/iTop.xml
deleted file mode 100644
index b7028562f..000000000
--- a/.idea/inspectionProfiles/iTop.xml
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index ef816746c..000000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/application/nicewebpage.class.inc.php b/application/nicewebpage.class.inc.php
index 61c2bdcaf..b3c023aaf 100644
--- a/application/nicewebpage.class.inc.php
+++ b/application/nicewebpage.class.inc.php
@@ -52,6 +52,7 @@ class NiceWebPage extends WebPage
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.popupmenu.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/searchformforeignkeys.js');
+ $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/latinise/latinise.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_handler.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_handler_history.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria.js');
diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php
index 5b84748eb..fa60d0fe8 100644
--- a/core/attributedef.class.inc.php
+++ b/core/attributedef.class.inc.php
@@ -3957,7 +3957,11 @@ class AttributeDateTime extends AttributeDBField
const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_DATE_TIME;
static $oFormat = null;
-
+
+ /**
+ *
+ * @return DateTimeFormat
+ */
static public function GetFormat()
{
if (self::$oFormat == null)
diff --git a/core/config.class.inc.php b/core/config.class.inc.php
index 3413f05b7..9ef9935af 100644
--- a/core/config.class.inc.php
+++ b/core/config.class.inc.php
@@ -1085,6 +1085,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
+ 'search_manual_submit' => array(
+ 'type' => 'array',
+ 'description' => 'Force manual submit of search requests (class => true)',
+ 'default' => false,
+ 'value' => true,
+ 'source_of_value' => '',
+ 'show_in_conf_sample' => true,
+ ),
);
public function IsProperty($sPropCode)
diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php
index 0a36c106a..8d49afdfe 100644
--- a/core/oql/expression.class.inc.php
+++ b/core/oql/expression.class.inc.php
@@ -733,12 +733,19 @@ class ScalarExpression extends UnaryExpression
case $oAttDef->IsExternalKey():
try
{
- /** @var AttributeExternalKey $oAttDef */
- $sTarget = $oAttDef->GetTargetClass();
- $oObj = MetaModel::GetObject($sTarget, $this->GetValue());
- $aValue['label'] = $oObj->Get("friendlyname");
+ if ($this->GetValue() == 0)
+ {
+ $aValue['label'] = Dict::S('UI:UndefinedObject');
+ }
+ else
+ {
+ /** @var AttributeExternalKey $oAttDef */
+ $sTarget = $oAttDef->GetTargetClass();
+ $oObj = MetaModel::GetObject($sTarget, $this->GetValue());
+ $aValue['label'] = $oObj->Get("friendlyname");
+ }
}
catch (Exception $e)
{
diff --git a/datamodels/2.x/itop-portal-base/portal/src/views/layout.html.twig b/datamodels/2.x/itop-portal-base/portal/src/views/layout.html.twig
index 920c70d54..869dadc32 100644
--- a/datamodels/2.x/itop-portal-base/portal/src/views/layout.html.twig
+++ b/datamodels/2.x/itop-portal-base/portal/src/views/layout.html.twig
@@ -85,7 +85,7 @@
-
+
{# Visible.js to check if an element is visible on screen #}
{# Base64.js #}
diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php
index 7aa344ff8..9bfbdbe52 100644
--- a/dictionaries/en.dictionary.itop.ui.php
+++ b/dictionaries/en.dictionary.itop.ui.php
@@ -1430,13 +1430,13 @@ When associated with a trigger, each action is given an "order" number, specifyi
'UI:Search:Criteria:Title:Default:LessThanOrEquals' => '%1$s <= %2$s',
'UI:Search:Criteria:Title:Default:Different' => '%1$s ≠ %2$s',
'UI:Search:Criteria:Title:Default:Between' => '%1$s between [%2$s]',
+ 'UI:Search:Criteria:Title:Default:BetweenDates' => '%1$s [%2$s]',
'UI:Search:Criteria:Title:Default:BetweenDates:All' => '%1$s: Any',
'UI:Search:Criteria:Title:Default:BetweenDates:From' => '%1$s from %2$s',
'UI:Search:Criteria:Title:Default:BetweenDates:Until' => '%1$s until %2$s',
'UI:Search:Criteria:Title:Default:Between:All' => '%1$s: Any',
'UI:Search:Criteria:Title:Default:Between:From' => '%1$s from %2$s',
- 'UI:Search:Criteria:Title:Default:Between:Until' => '%1$s until %2$s',
- 'UI:Search:Criteria:Title:Default:BetweenDays' => '%1$s [%2$s]',
+ 'UI:Search:Criteria:Title:Default:Between:Until' => '%1$s up to %2$s',
// - Numeric widget
// None yet
// - DateTime widget
@@ -1483,7 +1483,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
// - Widget other translations
'UI:Search:Criteria:Numeric:From' => 'From',
- 'UI:Search:Criteria:Numeric:Until' => 'Until',
+ 'UI:Search:Criteria:Numeric:Until' => 'To',
'UI:Search:Criteria:Numeric:PlaceholderFrom' => 'Any',
'UI:Search:Criteria:Numeric:PlaceholderUntil' => 'Any',
'UI:Search:Criteria:DateTime:From' => 'From',
diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php
index d6a852266..362019ea3 100644
--- a/dictionaries/fr.dictionary.itop.ui.php
+++ b/dictionaries/fr.dictionary.itop.ui.php
@@ -1247,13 +1247,13 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
'UI:Search:Criteria:Title:Default:LessThanOrEquals' => '%1$s <= %2$s',
'UI:Search:Criteria:Title:Default:Different' => '%1$s ≠ %2$s',
'UI:Search:Criteria:Title:Default:Between' => '%1$s entre [%2$s]',
+ 'UI:Search:Criteria:Title:Default:BetweenDates' => '%1$s [%2$s]',
'UI:Search:Criteria:Title:Default:BetweenDates:All' => '%1$s : Indifférent',
'UI:Search:Criteria:Title:Default:BetweenDates:From' => '%1$s depuis %2$s',
'UI:Search:Criteria:Title:Default:BetweenDates:Until' => '%1$s jusqu\'à %2$s',
'UI:Search:Criteria:Title:Default:Between:All' => '%1$s : Indifférent',
'UI:Search:Criteria:Title:Default:Between:From' => '%1$s à partir de %2$s',
'UI:Search:Criteria:Title:Default:Between:Until' => '%1$s jusqu\'à %2$s',
- 'UI:Search:Criteria:Title:Default:BetweenDays' => '%1$s [%2$s]',
// - Numeric widget
// None yet
// - DateTime widget
diff --git a/datamodels/2.x/itop-portal-base/portal/web/lib/latinise/latinise.min.js b/js/latinise/latinise.min.js
similarity index 100%
rename from datamodels/2.x/itop-portal-base/portal/web/lib/latinise/latinise.min.js
rename to js/latinise/latinise.min.js
diff --git a/js/search/search_form_criteria.js b/js/search/search_form_criteria.js
index 3fcc07f57..de6875596 100644
--- a/js/search/search_form_criteria.js
+++ b/js/search/search_form_criteria.js
@@ -487,28 +487,64 @@ $(function()
});
},
// - Compute the title string
+
+ _computeEmptyOperatorTitle: function(sTitle) {
+ if (sTitle !== undefined) {
+ return sTitle;
+ }
+
+ sTitle = Dict.Format('UI:Search:Criteria:Title:Default:Any:Empty', this.options.field.label);
+
+ return sTitle;
+ },
+ _computeNotEmptyOperatorTitle: function(sTitle) {
+ if (sTitle !== undefined) {
+ return sTitle;
+ }
+
+ sTitle = Dict.Format('UI:Search:Criteria:Title:Default:Any:NotEmpty', this.options.field.label);
+
+ return sTitle;
+ },
+
_computeTitle: function(sTitle)
{
- if(sTitle === undefined)
+ if(sTitle !== undefined)
{
- var sValueAsText = this._getValuesAsText();
- var sOperator = (sValueAsText !== '') ? this.operators[this.options.operator].code : 'Any';
- var sDictEntry = 'UI:Search:Criteria:Title:' + this._toCamelCase(this.options.field.widget) + ':' + this._toCamelCase(sOperator);
+ return sTitle;
+ }
- // Fallback to default widget dict entry if none exists for the current widget
- if(Dict.S(sDictEntry) === sDictEntry)
+
+ var sCallback = '_compute' + this._toCamelCase(this.operators[this.options.operator].code) + 'OperatorTitle';
+ if(this[sCallback] !== undefined)
+ {
+ var sCallbackTitle = this[sCallback](sTitle);
+ if (sCallbackTitle !== undefined)
{
- sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(sOperator);
- }
-
- sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
-
- // Last chande fallback
- if(sTitle === sDictEntry)
- {
- sTitle = this.options.label;
+ sTitle = sCallbackTitle;
+ return sTitle;
}
}
+
+
+ var sValueAsText = this._getValuesAsText();
+ var sOperator = (sValueAsText !== '') ? this.operators[this.options.operator].code : 'Any';
+ var sDictEntry = 'UI:Search:Criteria:Title:' + this._toCamelCase(this.options.field.widget) + ':' + this._toCamelCase(sOperator);
+
+ // Fallback to default widget dict entry if none exists for the current widget
+ if(Dict.S(sDictEntry) === sDictEntry)
+ {
+ sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(sOperator);
+ }
+
+ sTitle = Dict.Format(sDictEntry, this.options.field.label, sValueAsText);
+
+ // Last chande fallback
+ if(sTitle === sDictEntry)
+ {
+ sTitle = this.options.label;
+ }
+
return sTitle;
},
// - Set the title element
diff --git a/js/search/search_form_criteria_date_abstract.js b/js/search/search_form_criteria_date_abstract.js
index d3bba1cf6..28db826e0 100644
--- a/js/search/search_form_criteria_date_abstract.js
+++ b/js/search/search_form_criteria_date_abstract.js
@@ -175,8 +175,9 @@ $(function()
};
var odatetimepickerOptionsDefault = {
- dateFormat: 'yy-mm-dd',
- timeFormat: 'HH:mm:ss',
+ // dateFormat: 'yy-mm-dd',
+ // timeFormat: 'HH:mm:ss',
+ showSecond: true,
buttonImage: GetAbsoluteUrlAppRoot()+"/images/calendar.png",
// buttonImageOnly: true,
buttonText: "",
@@ -294,10 +295,10 @@ $(function()
//------------------
// Inherited methods
//------------------
- _computeTitle: function(sTitle)
+ _computeBetweenDaysOperatorTitle: function(sTitle)
{
var me = this;
- if (sTitle === undefined && me.options.operator == 'between_dates')
+ if (sTitle === undefined)
{
var aValues = me._getValues();
switch (true)
@@ -318,24 +319,23 @@ $(function()
var sDictEntrySuffix = ':From';
break;
default:
- var sDictEntrySuffix = undefined;
+ var sDictEntrySuffix = '';
break;
}
- if (sDictEntrySuffix != undefined)
+ var sDictEntry = 'UI:Search:Criteria:Title:' + this._toCamelCase(this.options.field.widget) + ':' + this._toCamelCase(me.options.operator) + sDictEntrySuffix ;
+ // Fallback to default widget dict entry if none exists for the current widget
+ if(Dict.S(sDictEntry) === sDictEntry)
{
- var sDictEntry = 'UI:Search:Criteria:Title:' + this._toCamelCase(this.options.field.widget) + ':' + this._toCamelCase(me.options.operator) + sDictEntrySuffix ;
- // Fallback to default widget dict entry if none exists for the current widget
- if(Dict.S(sDictEntry) === sDictEntry)
- {
- sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(me.options.operator) + sDictEntrySuffix;
- }
-
- sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
+ sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(me.options.operator) + sDictEntrySuffix;
}
+
+ sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
+ return sTitle;
+
}
- return me._super(sTitle);
+ return undefined;
},
@@ -358,7 +358,8 @@ $(function()
}
else
{
- aRawValues[1].label = aRawValues[1].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
+ // aRawValues[1].label = aRawValues[1].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
+ aRawValues[1].label = aRawValues[1].label.replace('23:59:59', '');
}
if (typeof aRawValues[0] == 'undefined' || typeof aRawValues[0].label == 'undefined' || aRawValues[0].label == '')
{
@@ -366,7 +367,8 @@ $(function()
}
else
{
- aRawValues[0].label = aRawValues[0].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
+ // aRawValues[0].label = aRawValues[0].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
+ aRawValues[0].label = aRawValues[0].label.replace('00:00:00', '');
}
}
return me._super(aRawValues);
diff --git a/js/search/search_form_criteria_enum.js b/js/search/search_form_criteria_enum.js
index 79374ac76..baccd0101 100644
--- a/js/search/search_form_criteria_enum.js
+++ b/js/search/search_form_criteria_enum.js
@@ -238,11 +238,11 @@ $(function()
else
{
oOpContentElem.find('.sfc_opc_mc_item').each(function(){
- var oRegExp = new RegExp(sQuery, 'ig');
+ var oRegExp = new RegExp(sQuery.latinise(), 'ig');
var sValue = $(this).find('input').val();
var sLabel = $(this).text();
- if( (sValue.match(oRegExp) !== null) || (sLabel.match(oRegExp) !== null) )
+ if( (sValue.latinise().match(oRegExp) !== null) || (sLabel.latinise().match(oRegExp) !== null) )
{
$(this).show();
}
diff --git a/js/search/search_form_criteria_numeric.js b/js/search/search_form_criteria_numeric.js
index 364b7a944..e50552134 100644
--- a/js/search/search_form_criteria_numeric.js
+++ b/js/search/search_form_criteria_numeric.js
@@ -186,7 +186,7 @@ $(function()
//------------------
// Inherited methods
//------------------
- _computeTitle: function(sTitle)
+ _computeBetweenOperatorTitle: function(sTitle)
{
var me = this;
if (sTitle === undefined && me.options.operator == 'between')
@@ -222,7 +222,7 @@ $(function()
var sDictEntrySuffix = ':From';
break;
default:
- var sDictEntrySuffix = undefined;
+ var sDictEntrySuffix = '';
break;
}
@@ -236,11 +236,12 @@ $(function()
}
sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
+ return sTitle;
}
}
- return me._super(sTitle);
+ return undefined;
},
// - Convert values to a standard string
diff --git a/js/search/search_form_handler.js b/js/search/search_form_handler.js
index 276cc452a..db7ddbdee 100644
--- a/js/search/search_form_handler.js
+++ b/js/search/search_form_handler.js
@@ -209,7 +209,7 @@ $(function()
for (var j = 0; j < prefix.length; j++) {
var pos = pars[i].lastIndexOf(prefix[j], 0);
if (pos !== -1) {
- return pars[i].substring(pos);
+ return pars[i].substring(pos + prefix[j].length);
}
}
}
@@ -524,12 +524,12 @@ $(function()
else
{
oListsElem.find('.sfl_items > li:not(.sfl_i_placeholder)').each(function(){
- var oRegExp = new RegExp(sFilter, 'ig');
+ var oRegExp = new RegExp(sFilter.latinize(), 'ig');
var sValue = $(this).find('input').val();
var sLabel = $(this).text();
// We don't check the sValue as it contains the class alias.
- if(sLabel.match(oRegExp) !== null)
+ if(sLabel.latinise().match(oRegExp) !== null)
{
$(this).show();
}
diff --git a/sources/application/search/criterionconversion/criteriontooql.class.inc.php b/sources/application/search/criterionconversion/criteriontooql.class.inc.php
index ebd852b3c..27a8292b3 100644
--- a/sources/application/search/criterionconversion/criteriontooql.class.inc.php
+++ b/sources/application/search/criterionconversion/criteriontooql.class.inc.php
@@ -30,6 +30,8 @@ use AttributeEnum;
use Combodo\iTop\Application\Search\AjaxSearchException;
use Combodo\iTop\Application\Search\CriterionConversionAbstract;
use Combodo\iTop\Application\Search\SearchForm;
+use Exception;
+use MetaModel;
class CriterionToOQL extends CriterionConversionAbstract
{
@@ -59,6 +61,7 @@ class CriterionToOQL extends CriterionConversionAbstract
$aMappedOperators = array(
self::OP_CONTAINS => 'ContainsToOql',
+ self::OP_EQUALS => 'EqualsToOql',
self::OP_STARTS_WITH => 'StartsWithToOql',
self::OP_ENDS_WITH => 'EndsWithToOql',
self::OP_EMPTY => 'EmptyToOql',
@@ -110,6 +113,8 @@ class CriterionToOQL extends CriterionConversionAbstract
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
+ if (empty($sValue)) return "1";
+
return "({$sRef} LIKE '%{$sValue}%')";
}
@@ -118,6 +123,8 @@ class CriterionToOQL extends CriterionConversionAbstract
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
+ if (empty($sValue)) return "1";
+
return "({$sRef} LIKE '{$sValue}%')";
}
@@ -126,9 +133,21 @@ class CriterionToOQL extends CriterionConversionAbstract
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
+ if (empty($sValue)) return "1";
+
return "({$sRef} LIKE '%{$sValue}')";
}
+ protected static function EqualsToOql($sRef, $aCriteria)
+ {
+ $aValues = self::GetValues($aCriteria);
+ $sValue = self::GetValue($aValues, 0);
+
+ if (empty($sValue)) return "1";
+
+ return "({$sRef} = '{$sValue}')";
+ }
+
protected static function EmptyToOql($sRef, $aCriteria)
{
if (isset($aCriteria['widget']))
@@ -164,7 +183,7 @@ class CriterionToOQL extends CriterionConversionAbstract
$bFilterOnUndefined = false;
try
{
- $aAttributeDefs = \MetaModel::ListAttributeDefs($sClass);
+ $aAttributeDefs = MetaModel::ListAttributeDefs($sClass);
if (array_key_exists($sAttCode, $aAttributeDefs))
{
$oAttDef = $aAttributeDefs[$sAttCode];
@@ -272,17 +291,29 @@ class CriterionToOQL extends CriterionConversionAbstract
$sStartDate = $aValues[0]['value'];
if (!empty($sStartDate))
{
- $oDate = $oFormat->parse($sStartDate);
- $sStartDate = $oDate->format($sAttributeClass::GetSQLFormat());
- $aOQL[] = "({$sRef} >= '$sStartDate')";
+ try
+ {
+ $oDate = $oFormat->parse($sStartDate);
+ $sStartDate = $oDate->format($sAttributeClass::GetSQLFormat());
+ $aOQL[] = "({$sRef} >= '$sStartDate')";
+ }
+ catch (Exception $e)
+ {
+ }
}
$sEndDate = $aValues[1]['value'];
if (!empty($sEndDate))
{
- $oDate = $oFormat->parse($sEndDate);
- $sEndDate = $oDate->format($sAttributeClass::GetSQLFormat());
- $aOQL[] = "({$sRef} <= '$sEndDate')";
+ try
+ {
+ $oDate = $oFormat->parse($sEndDate);
+ $sEndDate = $oDate->format($sAttributeClass::GetSQLFormat());
+ $aOQL[] = "({$sRef} <= '$sEndDate')";
+ }
+ catch (Exception $e)
+ {
+ }
}
$sOQL = implode(' AND ', $aOQL);
diff --git a/sources/application/search/criterionconversion/criteriontosearchform.class.inc.php b/sources/application/search/criterionconversion/criteriontosearchform.class.inc.php
index f85dcf9c3..6daa18b55 100644
--- a/sources/application/search/criterionconversion/criteriontosearchform.class.inc.php
+++ b/sources/application/search/criterionconversion/criteriontosearchform.class.inc.php
@@ -197,6 +197,8 @@ class CriterionToSearchForm extends CriterionConversionAbstract
if (($a['widget'] === AttributeDefinition::SEARCH_WIDGET_TYPE_RAW) &&
($b['widget'] === AttributeDefinition::SEARCH_WIDGET_TYPE_RAW))
{
+ if (!isset($a['label'])) return -1;
+ if (!isset($b['label'])) return 1;
return strcmp($a['label'], $b['label']);
}
if ($a['widget'] === AttributeDefinition::SEARCH_WIDGET_TYPE_RAW)
@@ -207,6 +209,8 @@ class CriterionToSearchForm extends CriterionConversionAbstract
return 1;
}
+ if (!isset($a['label'])) return -1;
+ if (!isset($b['label'])) return 1;
return strcmp($a['label'], $b['label']);
});
@@ -564,7 +568,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
$aCriteria['values'] = array();
}
// Convention for 'undefined' enums
- $aCriteria['values'][] = array('value' => 'null', 'label' => 'null');
+ $aCriteria['values'][] = array('value' => 'null', 'label' => Dict::S('Enum:Undefined'));
}
break;
default:
diff --git a/sources/application/search/criterionconversionabstract.class.inc.php b/sources/application/search/criterionconversionabstract.class.inc.php
index 041d840e8..8a5b83284 100644
--- a/sources/application/search/criterionconversionabstract.class.inc.php
+++ b/sources/application/search/criterionconversionabstract.class.inc.php
@@ -27,6 +27,7 @@ abstract class CriterionConversionAbstract
{
const OP_CONTAINS = 'contains';
+ const OP_EQUALS = '=';
const OP_STARTS_WITH = 'starts_with';
const OP_ENDS_WITH = 'ends_with';
const OP_EMPTY = 'empty';
diff --git a/sources/application/search/criterionparser.class.inc.php b/sources/application/search/criterionparser.class.inc.php
index 903bb7b71..097e02b5c 100644
--- a/sources/application/search/criterionparser.class.inc.php
+++ b/sources/application/search/criterionparser.class.inc.php
@@ -90,12 +90,17 @@ class CriterionParser
$aExpression = array();
foreach($aAnd as $aCriteria)
{
- $aExpression[] = CriterionToOQL::Convert($aCriteria);
+
+ $sExpression = CriterionToOQL::Convert($aCriteria);
+ if ($sExpression !== '1')
+ {
+ $aExpression[] = $sExpression;
+ }
}
if (empty($aExpression))
{
- return '';
+ return '1';
}
return '('.implode(" AND ", $aExpression).')';
diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php
index f24d61860..9e99fd6b0 100644
--- a/sources/application/search/searchform.class.inc.php
+++ b/sources/application/search/searchform.class.inc.php
@@ -131,8 +131,39 @@ class SearchForm
{
$sClassesCombo = MetaModel::GetName($sClassName);
}
+
+ $bAutoSubmit = true;
+ $mSubmitParam = utils::GetConfig()->Get('search_manual_submit');
+ if (is_array($mSubmitParam))
+ {
+ // List of classes
+ if (isset($mSubmitParam[$sClassName]))
+ {
+ $bAutoSubmit = !$mSubmitParam[$sClassName];
+ }
+ else
+ {
+ // Serach for child classes
+ foreach($mSubmitParam as $sConfigClass => $bFlag)
+ {
+ $aChildClasses = MetaModel::EnumChildClasses($sConfigClass);
+ if (in_array($sClassName, $aChildClasses))
+ {
+ $bAutoSubmit = !$bFlag;
+ break;
+ }
+ }
+
+ }
+ }
+ else if ($mSubmitParam !== false)
+ {
+ $bAutoSubmit = false;
+ }
+
$sAction = (isset($aExtraParams['action'])) ? $aExtraParams['action'] : utils::GetAbsoluteUrlAppRoot().'pages/UI.php';
$sStyle = ($bOpen == 'true') ? '' : 'closed';
+ $sStyle .= ($bAutoSubmit === true) ? '' : ' no_auto_submit';
$sHtml .= "