/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This service is intended to be used for performing searches. It was written specifically to
* service requests that can be rendered by the [AlfSearchList]{@link module:alfresco/search/AlfSearchList}
* widget.
*
* @module alfresco/services/SearchService
* @extends module:alfresco/services/BaseService
* @author Dave Draper
*/
define(["dojo/_base/declare",
"alfresco/services/BaseService",
"alfresco/core/CoreXhr",
"service/constants/Default",
"alfresco/core/PathUtils",
"alfresco/core/NodeUtils",
"alfresco/core/topics",
"dojo/_base/lang",
"dojo/json"],
function(declare, BaseService, CoreXhr, AlfConstants, PathUtils, NodeUtils, topics, lang, dojoJson) {
return declare([BaseService, CoreXhr, PathUtils], {
/**
* Sets up the subscriptions for the SearchService.
*
* @instance
* @since 1.0.32
*/
registerSubscriptions: function alfresco_services_SearchService__registerSubscriptions() {
this.alfSubscribe(topics.SEARCH_REQUEST, lang.hitch(this, this.onSearchRequest));
this.alfSubscribe("ALF_STOP_SEARCH_REQUEST", lang.hitch(this, this.onStopRequest));
this.alfSubscribe("ALF_AUTO_SUGGEST_SEARCH", lang.hitch(this, this.onAutoSuggest));
},
/**
* The URL to call to fetch auto suggest results
*
* @instance
* @type {string}
* @default
*/
autoSuggestAPI: AlfConstants.PROXY_URI + "slingshot/auto-suggest",
/**
* A comma-delimited string of the properties to apply search term highlighting to.
*
* @instance
* @type {string}
* @default
* @since 1.0.99
*/
highlightFields: "cm:name,cm:description,cm:title,content,ia:descriptionEvent,ia:whatEvent,lnk:title",
/**
* The number of characters to include in a highlight fragment of the content
*
* @instance
* @type {number}
* @default
* @since 1.0.99
*/
highlightFragmentSize: 255,
/**
* The number of characters to search into the content for the search term.
*
* @instance
* @type {number}
* @default
* @since 1.0.99
*/
highlightMaxAnalyzedChars: null,
/**
* The number of characters to include in a highlight snippet.
*
* @instance
* @type {number}
* @default
* @since 1.0.99
*/
highlightSnippetCount: 100,
/**
* Whether to use SpanScorer to highlight phrase terms only when they appear within the query phrase in
* the document.
*
* @instance
* @type {number}
* @default
* @since 1.0.99
*/
highlightUsePhraseHighlighter: true,
/**
* Collapse contiguous fragments into a single fragment. If the value is true it indicates that contiguous
* fragments will be collapsed into single fragment.
*
* @instance
* @type {boolean}
* @default
* @since 1.0.99
*/
highlightMergeContiguous: false,
/**
* This is the default number of items to return as a single page of result data. This value will be used if
* a specific value isn't supplied in a search request.
*
* @instance
* @type {number}
* @default
*/
pageSize: 25,
/**
* This is the default query to use if one isn't supplied in a search request.
*
* @instance
* @type {string}
* @default
*/
query: "",
/**
* This boolean indicates whether the entire repository should be searched. This value will be used if a specific
* value isn't supplied in a search request.
*
* @instance
* @type {boolean}
* @default
*/
repo: true,
/**
* This is the default node to use as the root of the search. This value will be used if a specific value isn't
* supplied in the search request.
*
* @instance
* @type {string}
* @default
*/
rootNode: "alfresco://company/home",
/**
* The URL to send a search request to
*
* @instance
* @type {string}
* @default
*/
searchAPI: AlfConstants.PROXY_URI + "slingshot/search/",
/**
* The URL to send the
*/
/**
* This is the default site to use. This value will be used if a specific value isn't supplied in the search request.
*
* @instance
* @type {string}
* @default
*/
site: "",
/**
* This is the default sort to use. This value will be used if a specific value isn't supplied in the search request.
*
* @instance
* @type {string}
* @default
*/
sort: "",
/**
* This is the default sort direction to use. This value will be used if a specific value isn't supplied in the search request.
*
* @instance
* @type {boolean}
* @default
*/
sortAscending: true,
/**
* This is the default page index to use for multiple pages of search results. This value will be used if
* a specific value isn't supplied in a search request.
*
* @instance
* @type {number}
* @default
*/
startIndex: 0,
/**
* This is the default tag to use. This value will be used if a specific value isn't supplied in the search request.
*
* @instance
* @type {string}
* @default
*/
tag: "",
/**
*
* @instance
* @param {object} payload The payload defining the document to retrieve the details for.
*/
onSearchRequest: function alfresco_services_SearchService__onSearchRequest(payload) {
// jshint maxlen:300, maxcomplexity:false
if (!payload)
{
this.alfLog("warn", "A request was made to perform a search but no payload was provided", payload, this);
this.alfPublish(payload.alfResponseTopic + "_FAILURE", {}, false, false, payload.alfResponseScope);
}
else
{
// Check to see whether or not a success topic has been provided...
var alfTopic = (payload.alfResponseTopic) ? payload.alfResponseTopic : topics.SEARCH_REQUEST;
var url = this.searchAPI;
// Use any unexpected attributes as a query attribute...
var query = this.query;
if (!payload.query)
{
var queryAttributes = {};
for (var key in payload)
{
if (payload.hasOwnProperty(key)) {
switch(key) {
case "alfTopic":
case "alfResponseScope":
case "alfResponseTopic":
case "alfPublishScope":
case "alfCallerName":
case "term":
case "tag":
case "startIndex":
case "sort":
case "site":
case "rootNode":
case "repo":
case "pageSize":
case "maxResults":
case "facetFields":
case "filters":
case "sortAscending":
case "sortField":
case "requestId":
case "spellcheck":
break;
default:
queryAttributes[key] = payload[key];
}
}
}
query = dojoJson.stringify(queryAttributes);
if (query === "{}")
{
query = "";
}
}
else
{
query = payload.query;
}
var sort = "";
if (payload.sortField === "null" || payload.sortField === "Relevance" || payload.sortField === "")
{
// No action required - leave as the empty string which is relevance - no direction can be applied
}
else
{
var sortAscending = (payload.sortAscending !== null && typeof payload.sortAscending !== "undefined") ? payload.sortAscending : this.sortAscending;
sort = (payload.sortField || this.sort) + "|" + sortAscending;
}
var data = {
facetFields: payload.facetFields || "",
filters: decodeURIComponent(payload.filters) || "",
encodedFilters: payload.filters || "",term: payload.term,
tag: payload.tag || this.tag,
startIndex: (payload.startIndex || payload.startIndex === 0) ? payload.startIndex : this.startIndex,
sort: sort,
site: payload.site || this.site,
rootNode: payload.rootNode || this.rootNode,
repo: (payload.repo || payload.repo === false) ? payload.repo : this.repo,
query: query,
pageSize: payload.pageSize || this.pageSize, // It makes no sense for page size to ever be 0
maxResults: payload.maxResults || 0,
noCache: new Date().getTime(),
spellcheck: payload.spellcheck || false,
highlightPrefix: "\u0002",
highlightPostfix: "\u0003",
highlightFields: this.highlightFields,
highlightFragmentSize: this.highlightFragmentSize,
highlightSnippetCount: this.highlightSnippetCount,
highlightMergeContiguous: this.highlightMergeContiguous,
highlightMaxAnalyzedChars: this.highlightMaxAnalyzedChars,
highlightUsePhraseHighlighter: this.highlightUsePhraseHighlighter
};
var config = {
requestId: payload.requestId,
alfTopic: alfTopic,
url: url,
query: data,
method: "GET",
callbackScope: this
};
this.serviceXhr(config);
}
},
/**
* Retrieves a list of suggested search terms based on the supplied search term.
*
* @instance
* @param {object} payload The auto-suggest payload. Should contain the current search term
*/
onAutoSuggest: function alfresco_services_SearchService__onAutoSuggest(payload) {
// Create the root URL...
var url = this.autoSuggestAPI;
var options = {
t: ""
};
if (payload.query)
{
options.t = payload.query;
}
if (url !== null)
{
this.serviceXhr({url: url,
query: options,
alfTopic: (payload.alfResponseTopic ? payload.alfResponseTopic : null),
alfResponseScope: payload.alfResponseScope,
method: "GET"});
}
}
});
});