Index: main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl (working copy)
@@ -39,7 +39,10 @@
hit page
-
+
+
+
+
@@ -56,7 +59,14 @@
Index: main/plugin-odf-web/pages/services/search/search-bydomain_1.3.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search-bydomain_1.3.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search-bydomain_1.3.xsl (working copy)
@@ -41,12 +41,24 @@
hit page
-
+
+
+
+
Index: main/plugin-odf-web/pages/services/search/search-criteria/search-criteria-multiple.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search-criteria/search-criteria-multiple.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search-criteria/search-criteria-multiple.xsl (working copy)
@@ -70,6 +70,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/pages/services/search/search-criteria/search-criteria.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search-criteria/search-criteria.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search-criteria/search-criteria.xsl (working copy)
@@ -128,6 +128,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/pages/services/search/search-criteria/search-criteria_1.2.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search-criteria/search-criteria_1.2.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search-criteria/search-criteria_1.2.xsl (working copy)
@@ -155,6 +155,15 @@
+
+
+
+
+
+
+
+
+
@@ -206,6 +215,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/pages/services/search/search-map.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search-map.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search-map.xsl (working copy)
@@ -168,12 +168,7 @@
-
-
- /
-
- .html
-
+
@@ -186,7 +181,10 @@
-
+
+
+
+
Index: main/plugin-odf-web/pages/services/search/search.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search.xsl (working copy)
@@ -20,7 +20,9 @@
xmlns:math="java.lang.Math"
xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- extension-element-prefixes="math">
+ xmlns:url-encode="java.net.URLEncoder"
+ xmlns:str="http://exslt.org/strings"
+ extension-element-prefixes="math str url-encode">
@@ -69,7 +71,10 @@
hit even
-
+
+
+
+
hit even
@@ -126,6 +131,15 @@
+
+
+
+
+
+
+
+
+
@@ -218,6 +232,15 @@
+
+
+
+
+
+
+
+
+
@@ -228,5 +251,29 @@
-
+
+
+
+
+ /.html
+
+
+ &
+ ?
+
+ search-keywords=
+
+
+ ,
+
+ ,
+
+
+
+
+ ,
+
+
+
+
\ No newline at end of file
Index: main/plugin-odf-web/pages/services/search/search_1.2.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/search_1.2.xsl (revision 36748)
+++ main/plugin-odf-web/pages/services/search/search_1.2.xsl (working copy)
@@ -20,7 +20,9 @@
xmlns:math="java.lang.Math"
xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- extension-element-prefixes="math">
+ xmlns:url-encode="java.net.URLEncoder"
+ xmlns:str="http://exslt.org/strings"
+ extension-element-prefixes="math str url-encode">
@@ -111,7 +113,10 @@
hit page
-
+
+
+
+
@@ -138,7 +143,16 @@
@@ -262,6 +276,30 @@
-
-
+
+
+
+
+
+ /.html
+
+
+ &
+ ?
+
+ search-keywords=
+
+
+ ,
+
+ ,
+
+
+
+
+ ,
+
+
+
+
Index: main/plugin-odf-web/plugin.xml
===================================================================
--- main/plugin-odf-web/plugin.xml (revision 36748)
+++ main/plugin-odf-web/plugin.xml (working copy)
@@ -392,6 +392,10 @@
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_ADVANCED_SEARCH_DESC
+
PLUGINS_ODFWEB_SERVICE_SEARCH_FACET_DESC
@@ -510,6 +514,10 @@
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_ADVANCED_SEARCH_DESC
+
PLUGINS_ODFWEB_SERVICE_SEARCH_FACET_DESC
Index: main/plugin-odf-web/resources/js/search/facet-checkboxes-multi.i18n.js
===================================================================
--- main/plugin-odf-web/resources/js/search/facet-checkboxes-multi.i18n.js (revision 36748)
+++ main/plugin-odf-web/resources/js/search/facet-checkboxes-multi.i18n.js (working copy)
@@ -46,7 +46,7 @@
// Add a 'onchange' listener on each checkbox when DOM is ready
// Used to update the facets when an item is selected or deselected;
- // Same for the title and textfield input fields
+ // Same for the title, textfield and advanced search input fields
AOMF.onReady = function()
{
$j.each(_formsData, function(formId, formData) {
@@ -56,8 +56,11 @@
AOMF.handleFacetsVisibility($form);
$form.find('.field .input .checkbox input').change(AOMF.onFieldChange);
- $form.find('#' + 'search-title-' + formData.uniqueId).change(AOMF.onFieldChange);
- $form.find('#' + 'search-textfield-' + formData.uniqueId).change(AOMF.onFieldChange);
+ $form.find('#search-title-' + formData.uniqueId).change(AOMF.onFieldChange);
+ $form.find('#search-textfield-' + formData.uniqueId).change(AOMF.onFieldChange);
+ $form.find('#search-all-words-' + formData.uniqueId).change(AOMF.onFieldChange);
+ $form.find('#search-exact-wording-' + formData.uniqueId).change(AOMF.onFieldChange);
+ $form.find('#search-no-words-' + formData.uniqueId).change(AOMF.onFieldChange);
});
}
$j(function() {
Index: main/plugin-odf-web/sitemap.xmap
===================================================================
--- main/plugin-odf-web/sitemap.xmap (revision 36748)
+++ main/plugin-odf-web/sitemap.xmap (working copy)
@@ -111,6 +111,7 @@
+
@@ -130,6 +131,7 @@
+
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java (revision 36748)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java (working copy)
@@ -21,10 +21,12 @@
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.regex.Matcher;
import org.apache.avalon.framework.configuration.Configuration;
@@ -47,9 +49,11 @@
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.QueryParser.Operator;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Searcher;
@@ -59,7 +63,6 @@
import org.apache.lucene.store.FSDirectory;
import org.apache.tika.io.IOUtils;
import org.xml.sax.SAXException;
-
import org.ametys.cms.contenttype.ContentType;
import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
import org.ametys.cms.contenttype.MetadataDefinition;
@@ -119,6 +122,9 @@
/** The inputs as a Map fieldName -> metadataPath. */
protected Map _searchFields;
+ /** The search fields to be excluded from some operations. */
+ protected Set _excludedFields;
+
@Override
public void service(ServiceManager smanager) throws ServiceException
{
@@ -139,6 +145,7 @@
public void generate() throws IOException, SAXException, ProcessingException
{
_searchFields = getSearchFields();
+ _excludedFields = getExcludedFields();
super.generate();
}
@@ -159,9 +166,32 @@
searchFields.put(fieldName, metadataPath);
}
+
+ boolean advancedSearch = parameters.getParameterAsBoolean("advanced-search", false);
+ if (advancedSearch)
+ {
+ searchFields.put("all-words", "all-words");
+ searchFields.put("exact-wording", "exact-wording");
+ searchFields.put("no-words", "no-words");
+ }
return searchFields;
}
+
+ /**
+ * Get the search fields to exclude from some operations
+ * @return The excluded search fields
+ */
+ protected Set getExcludedFields()
+ {
+ Set excluded = new HashSet();
+ excluded.add("textfield");
+ excluded.add("title");
+ excluded.add("all-words");
+ excluded.add("exact-wording");
+ excluded.add("no-words");
+ return excluded;
+ }
@Override
protected Query getQuery (Request request) throws ParseException, IllegalArgumentException
@@ -274,9 +304,12 @@
// Keywords
_addTextFieldQuery(query, params.get("textfield"), getBoost("title", serviceId));
+ // Advanced search
+ _addAdvancedSearchQuery(query, params.get("all-words"), params.get("exact-wording"), params.get("no-words"));
+
for (String fieldName : _searchFields.keySet())
{
- if (!fieldName.equals("title") && !fieldName.equals("textfield") && !fieldName.equals("catalog"))
+ if (!fieldName.equals("catalog") && !_excludedFields.contains(fieldName))
{
String value = params.get(fieldName);
if (StringUtils.isNotEmpty(value))
@@ -342,7 +375,14 @@
// Keywords
String textfield = params.containsKey("textfield") ? params.get("textfield").get(0) : null;
_addTextFieldQuery(query, textfield, getBoost("title", serviceId));
+
+ // Advanced search
+ String allWords = params.containsKey("all-words") ? params.get("all-words").get(0) : null;
+ String exactWording = params.containsKey("exact-wording") ? params.get("exact-wording").get(0) : null;
+ String noWords = params.containsKey("no-words") ? params.get("no-words").get(0) : null;
+ _addAdvancedSearchQuery(query, allWords, exactWording, noWords);
+ // WARNING !!
// Setting base query for facet data (ie. the query part without the selected criteria)
if (facetData != null)
{
@@ -352,7 +392,7 @@
for (String fieldName : _searchFields.keySet())
{
- if (!fieldName.equals("title") && !fieldName.equals("textfield") && !fieldName.equals("catalog"))
+ if (!fieldName.equals("catalog") && !_excludedFields.contains(fieldName))
{
// Real values are expected here (non-empty)
List values = params.get(fieldName);
@@ -420,7 +460,7 @@
for (String fieldName : _searchFields.keySet())
{
- if (!fieldName.equals("title") && !fieldName.equals("textfield"))
+ if (!_excludedFields.contains(fieldName))
{
String metadataPath = _searchFields.get(fieldName);
@@ -428,11 +468,10 @@
if (StringUtils.isNotEmpty(metadataPath))
{
criterion = getCriterion(fieldName, metadataPath);
- }
-
- if (criterion != null)
- {
- criteria.put(fieldName, criterion);
+ if (criterion != null)
+ {
+ criteria.put(fieldName, criterion);
+ }
}
}
}
@@ -538,14 +577,12 @@
@Override
protected void saxFormFields (Request request, String siteName, String lang) throws SAXException
{
- if (_searchFields.containsKey("title"))
- {
- XMLUtils.createElement(contentHandler, "title");
- }
-
- if (_searchFields.containsKey("textfield"))
+ for (String excludedField : _excludedFields)
{
- XMLUtils.createElement(contentHandler, "textfield");
+ if (_searchFields.containsKey(excludedField))
+ {
+ XMLUtils.createElement(contentHandler, excludedField);
+ }
}
}
@@ -748,6 +785,54 @@
}
}
+ private void _addAdvancedSearchQuery(BooleanQuery query, String allWords, String exactWording, String noWords) throws ParseException, IllegalArgumentException
+ {
+ if (!StringUtils.isBlank(allWords))
+ {
+ Matcher m = _TEXTFIELD_PATTERN.matcher(allWords);
+ if (!m.matches())
+ {
+ throw new IllegalArgumentException(allWords + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
+ }
+
+ MultiFieldQueryParser parser = new MultiFieldQueryParser(LuceneConstants.LUCENE_VERSION, _fields, _analyser);
+ parser.setDefaultOperator(Operator.AND);
+ Query multiQuery = parser.parse(QueryParser.escape(allWords));
+ query.add(multiQuery, BooleanClause.Occur.MUST);
+ }
+
+ if (!StringUtils.isBlank(exactWording))
+ {
+ Matcher m = _TEXTFIELD_PATTERN.matcher(exactWording);
+ if (!m.matches())
+ {
+ throw new IllegalArgumentException(exactWording + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
+ }
+
+ PhraseQuery phraseQuery = new PhraseQuery();
+ String[] fields = exactWording.split(" ");
+ for (String field : fields)
+ {
+ phraseQuery.add(new Term(FieldNames.ALL_NOT_ANALYZED, StringUtils.strip(field, ",?!:()[].{}=").toLowerCase()));
+ }
+ query.add(phraseQuery, BooleanClause.Occur.MUST);
+ }
+
+ if (!StringUtils.isBlank(noWords))
+ {
+ Matcher m = _TEXTFIELD_PATTERN.matcher(noWords);
+ if (!m.matches())
+ {
+ throw new IllegalArgumentException(noWords + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
+ }
+
+ MultiFieldQueryParser parser = new MultiFieldQueryParser(LuceneConstants.LUCENE_VERSION, _fields, _analyser);
+ parser.setDefaultOperator(Operator.AND);
+ Query multiQuery = parser.parse(QueryParser.escape(noWords));
+ query.add(multiQuery, BooleanClause.Occur.MUST_NOT);
+ }
+ }
+
/**
* Get the service search configuration
* @param serviceId The id of service