Search tool

  1. How to override the default search tool ?
    1. Criteria declaration
      1. Samples
        1. Simple string criteria
        2. Date interval criteria
        3. Workflow step criteria
        4. Content type criteria
        5. Criteria using a specific widget
        6. Hidden criteria
    2. Result columns
      1. Sample
      2. Renderer function
      3. Default sorting and grouping
    3. Property mapping
    4. Number of result per page
    5. Search URL
  2. Advanced
    1. Override the JS tool
    2. Override the search generator class (org.ametys.cms.repository.SearchGenerator.java)

The CMS provides a default search tool on contents. This tool allows to search contents among 5 criterium :

  • content type,
  • content title,
  • last contributor's login,
  • workflow step,
  • last modified date

The results are displayed in a grid with 5 columns :

  • the content title with its content type's icon
  • the last contributor
  • the last modified date
  • the workflow step as an icon
  • the content type (hidden by default)

How to override the default search tool ?

The search tool is configurable in the plugin.xml file so you can easily override it.

The following elements are defined, and so configurables, in the plugin.xml file:

  • the criterium
  • the result columns
  • the mapping between content properties and columns
  • the search URL
  • the number of result per page
Criteria declaration

To declare a criteria (ie. form field), you must defines at least :

  • the field name
  • the column index in which it will be displayed : 1,2,3 or 4
  • the field label
  • the test operator for the search : wd (wildcard), eq (equals), ne (not equals), lt (less than), le (less than or equals), ge (greater than or equals) or gt (greater than)
  • the type : string, long, double, date or boolean

You can also define :

  • if it is a hidden field. Default to false
  • a specific widget to use.
  • if it is a metadata or not. Default to true.
  • a enumerator
Samples
Simple string criteria
<criteria name="document-title" type="string" column="1">
      <label i18n="true">UITOOL_SEARCH_CONTENT_TITLE</label>
      <test-operator>wd</test-operator>
 </criteria>
Date interval criteria
<criteria name="lastModified" type="date" column="2">
      <label i18n="true">UITOOL_SEARCH_CONTENT_LASTMODIFIED_AFTER</label>
      <test-operator>ge</test-operator>
</criteria>
<criteria name="lastModified" type="date" column="2">
      <label i18n="true">UITOOL_SEARCH_CONTENT_LASTMODIFIED_BEFORE</label>
      <test-operator>le</test-operator>
</criteria>
Workflow step criteria
<criteria name="workflow-step" type="string" column="2" metadata="false">
     <label i18n="true">UITOOL_SEARCH_CONTENT_WORKFLOW_STEP</label>
     <test-operator>eq</test-operator>
     <enumeration>
	  <custom-enumerator class="org.ametys.cms.workflow.DefaultWorkflowStepEnumerator"/>
     </enumeration>
</criteria>

This criteria use a custom enumerator.
The workflow step is not a metadata : add  metadata="false"

Content type criteria
<criteria name="content-type" type="string" column="1" metadata="false">
      <label i18n="true">UITOOL_SEARCH_CONTENT_CONTENTTYPE</label>
      <test-operator>eq</test-operator>
      <enumeration>
	   <custom-enumerator class="org.ametys.cms.contenttype.ContentTypeEnumerator"/>
      </enumeration>
</criteria>

This criteria use a custom enumerator.
The content type is not a metadata : add metadata="false"

Criteria using a specific widget
<criteria name="num_bulletin" type="long" column="3" metadata="false">
     <label i18n="true">UITOOL_SEARCH_BULLETIN</label>
     <test-operator>eq</test-operator>
     <widget>bulletin</widget>
     <width>30</width>
</criteria>

This field uses a widget which must be declared :

org.ametys.utils.Widgets.registerWidget ('long', 'bulletin', 'org.ametys.waldec.widget.BulletinWidget');

This field defines is own width (<width>30</width>). By default, it will take 95% of the available space.

Hidden criteria
<criteria name="isPublished" type="boolean" column="3" hidden="true">
     <label i18n="false"></label>
     <test-operator>eq</test-operator>
</criteria>
Result columns

A column is defined by :

  • a label
  • a property id
  • a width
  • a JS renderer function (optional)
  • hidden property. Defaults to false
  • hiddeable property. Defaults to true
  • sortable property. Defaults to true
Sample
<column id="document-title" hideable="false|true" sortable="false|true" hidden="false|true" >
     <label i18n="true">UITOOL_SEARCH_CONTENT_TITLE</label>
     <width>350</width>
     <renderer>org.ametys.cms.tool.search.SearchTool.renderTitle</renderer>
</column>
Renderer function

The renderer function is a ExtJS function to be used to process the raw data and return HTML markup to display it in the cell. The render function is called with the following parameters:

  • value : the data value for the cell,
  • p : an object in which you may set the following attributes:
    • css : StringA CSS class name to add to the cell's TD element.
    • attr : StringAn HTML attribute definition string to apply to the data container element within the table cell (e.g. 'style="color:red;"').
  • record : The Ext.data.Record from which the data was extracted
  • rowIndex: the row index
  • colIndex: the column index

The CMS search tool provides 4 renderer functions you can use :

  • org.ametys.cms.tool.search.SearchTool.renderTitle

To render the "document-title" property with the content type's icon

org.ametys.cms.tool.search.SearchTool.renderTitle = function (value, p, record)
{
	var title = '';
	if (record.data['icon-small'])
	{
		title += '&lt;img src="' + context.contextPath + record.data['icon-small'] + '" style="float:left; margin-right: 5px"/&gt;';
	}
	title += record.data['document-title'];

	return title;
}
  • org.ametys.cms.tool.search.SearchTool.renderDateTime

To render a raw date time on the format "D d/m/Y at H:m" (Mon 25/01/2009 at 10:52)

org.ametys.cms.tool.search.SearchTool.renderDateTime = function (value, p, record)
{
	var dateFormat = "D d/m/Y at H:m";
	return Ext.util.Format.date(value, dateFormat);
}
  • org.ametys.cms.tool.search.SearchTool.renderDate

To render a raw date on the format "d/m/Y"

org.ametys.cms.tool.search.SearchTool.renderDate = function (value, p, record)
{
	var dateFormat = "d/m/Y";
	return Ext.util.Format.date(value, dateFormat);
}
  • org.ametys.cms.tool.search.SearchTool.renderWorlflowStep

To render the workflow step by its icon if available

org.ametys.cms.tool.search.SearchTool.renderWorlflowStep = function (value, p, record)
{
	var step;
	if (record.data['workflow-icon-small'])
	{
		step = '&lt;img src="' + context.contextPath + record.data['workflow-icon-small'] + '" style="float:left; margin-right: 5px" title="' + record.data['workflow-step'] + '"/&gt;';
	}
	else
	{
		step = record.data['workflow-step'];
	}
	return step;
}
Default sorting and grouping

The default sorting and grouping columns can be specified :

<columns>
  <column ...>
  ...
  <sort-by>document-title</sort-by>
  <group-by>workflow-step</group-by>
</columns>
Property mapping

The property mapping is used to link the column property to the XML received after a search. This is a very important part, if your result values are not well displayed, first check the mapping.

In the mapping, you defines :

  • the column property id
  • the matching XPath where to find the property value
  • the property type. Default to string
    <property-mapping>
         <property id="id" path="@id"/>
         <property id="document-title" path="metadata/document-title"/>
         <property id="contributor" path="metadata/contributor"/>
         <property id="icon-small" path="@smallIcon"/>
         <property id="icon-medium" path="@mediumIcon"/>
         <property id="content-type" path="content-type"/>
         <property id="lastModified" path="metadata/lastModified" type="date"/>
         <property id="workflow-step" path="workflow-step"/>
         <property id="workflow-icon-small" path="workflow-icon-small"/>
         <property id="workflow-icon-medium" path="workflow-icon-medium"/>
    </property-mapping>
    
    To do this correctly you must know the XML stream send by the search generator. By default it is composed by the requested properties defined in mapping as following :
    <contents>
    
        <content smallIcon="/plugins/cms/resources/img/content/page_16.gif"
             mediumIcon="/plugins/cms/resources/img/content/page_32.gif"
             largeIcon="/plugins/cms/resources/img/content/page_50.gif"
             id="defaultWebContent://7eb9b55b-f859-4827-abca-ae1432f6056a"
             name="universite-article">
    	     <content-type>Article</content-type>
    	     <workflow-step id="3">Validé</workflow-step>
    	     <workflow-icon-small>/plugins/web/resources/img/workflow/WORKFLOW_STATE_VALIDATED-small.png</workflow-icon-small>
    	     <workflow-icon-medium>/plugins/web/resources/img/workflow/WORKFLOW_STATE_VALIDATED-medium.png</workflow-icon-medium>
    	     <workflow-icon-large>/plugins/web/resources/img/workflow/WORKFLOW_STATE_VALIDATED-large.png</workflow-icon-large>
    	     <metadata>
    		    <lastModified>2010-01-04T16:56:39.238+01:00</lastModified>
    		    <contributor login="anonymous">Anonymous user</contributor>
    		    <document-title>Titre de mon article</document-title>
    
    		    <!-- Other metadata properties -->
    	    </metadata>
         </content>
         <content>
           [...]
         </content>
         [...]
    </contents>
    
Number of result per page

By default it is 50. If you want to override this value, do as follow in the plugin.xml file

<nb-result-per-page>100</nb-result-per-page>
Search URL

The search URL is the called URL to launch search. If you want to override it (if you changed the default search generator for example), do as follow in the plugin.xml file

<search-url plugin="myplugin">search/list.xml</search-url>

Advanced

Override the JS tool

If you need to do more specific actions that the tool declaration does not allow you, you can override the JS tool (org.ametys.cms.tool.search.SearchTool). Take a look to the original JS file to see which function(s) you need to override.

The following sample shows you how to override the search tool to add a listener on a criteria field :

Ext.namespace('org.ametys.waldec.tool');

org.ametys.waldec.tool.SearchTool = function(id, pluginName)
{
    org.ametys.waldec.tool.SearchTool.superclass.constructor.call(this, id, pluginName);
};

Ext.extend(org.ametys.waldec.tool.SearchTool,org.ametys.cms.tool.search.SearchTool, {});

org.ametys.waldec.tool.SearchTool.prototype._drawFormPanel = function ()
{
	var panel = org.ametys.waldec.tool.SearchTool.superclass._drawFormPanel.call(this);

	var queryField = panel.getForm().findField('string-eq-query');
	queryField.addListener ('select', this._selectQuery, this);

	return panel;
}

org.ametys.waldec.tool.SearchTool.prototype._selectQuery = function(combo, record, index)
{
    ....
}
Override the search generator class (org.ametys.cms.repository.SearchGenerator.java)

You may need to override the search generator JAVA class to do specific treatments. The search generator provides a lot of protected methods to do this easily. Take a look on API.

To use it you must add your own pipeline in your plugin and change the default url (see "Search Url" above)

<map:match pattern="search/list.xml">
	<map:generate type="search"/>
	<map:transform type="i18n">
		<map:parameter name="locale" value="{locale:locale}"/>
	</map:transform>
	<map:serialize type="xml"/>
</map:match>

This class provides the following abstract method to SAX more informations :

/**
     * SAX additional content data
     * @param content The content
     * @throws SAXException if an error occurs while SAXing
     * @throws RepositoryException if an error occurs
     */
    protected void saxAdditionalContentData (Content content) throws SAXException, RepositoryException
    {
        // Nothing
    }

    /**
     * SAX additional content metadata
     * @param content The content
     * @throws SAXException if an error occurs while SAXing
     * @throws RepositoryException if an error occurs
     */
    protected void saxAdditionalContentMetadata (Content content) throws SAXException, RepositoryException
    {
        // Nothing
    }

    /**
     * SAX additional data
     * @param request The request
     * @throws SAXException if an error occurs while SAXing
     */
    protected void saxAdditionalData (Request request) throws SAXException
    {
        // Nothing
    }

This class has also protected methods to construct JCR query.