diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/links/links.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/links/links.get.js deleted file mode 100644 index 3669912f5a..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/links/links.get.js +++ /dev/null @@ -1,69 +0,0 @@ - - - - - -const DEFAULT_NUM_DAYS = 7; - -/** - * Fetches all links added to the site - */ -function getLinksList(node, filter, tag, numdays, index, count) -{ - // query information - var luceneQuery = " +TYPE:\"{http://www.alfresco.org/model/linksmodel/1.0}link\" +PATH:\"" + node.qnamePath + "/*\""; - - if (filter == "recent") - { - var fromDate = getTodayMinusXDays(DEFAULT_NUM_DAYS); - var toDate = new Date(); - - luceneQuery += getCreationDateRangeQuery(fromDate, toDate); - } - else if (filter == "user") - { - luceneQuery += " +@cm\\:creator:\"" + person.properties.userName + '"'; - } - - if (tag !== null) - { - luceneQuery += " +PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(tag) + "/member\" "; - } - - var sortAttribute = "@{http://www.alfresco.org/model/content/1.0}created"; - - // get the data - return getPagedResultsDataByLuceneQuery(node, luceneQuery, sortAttribute, false, index, count, getLinksData); -} - -function main() -{ - // get requested node - var node = getRequestNode(); - if (status.getCode() != status.STATUS_OK) - { - return; - } - model.links = node; - - // Grab the paging and filtering details - var pNumber = parseInt(args.page, 10); - var pSize = parseInt(args.pageSize, 10); - var filter = args.filter; - var tag = (args.tag != undefined && args.tag.length > 0) ? args.tag : null; - - // Paging is required, ensure the parameters were given - if ((pNumber === undefined) || (pSize === undefined) || - isNaN(pNumber) || isNaN(pSize)) - { - var message = "Page sizing parameters missing!"; - status.code = 400; // Bad Request - status.message = message; - model.message = message; - return; - } - - model.data = getLinksList(node,filter,tag,7,(pNumber - 1) * pSize,pSize); -} - -main(); diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index b7aae0254c..1ee60453e8 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -1505,6 +1505,28 @@ + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/web/scripts/links/AbstractLinksWebScript.java b/source/java/org/alfresco/repo/web/scripts/links/AbstractLinksWebScript.java new file mode 100644 index 0000000000..dad97f2127 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/links/AbstractLinksWebScript.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2005-2011 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 . + */ +package org.alfresco.repo.web.scripts.links; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.query.PagingRequest; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.jscript.ScriptNode; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.links.LinkInfo; +import org.alfresco.service.cmr.links.LinksService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author Nick Burch + * @since 4.0 + */ +public abstract class AbstractLinksWebScript extends DeclarativeWebScript +{ + public static final String LINKS_SERVICE_ACTIVITY_APP_NAME = "links"; + + private static Log logger = LogFactory.getLog(AbstractLinksWebScript.class); + + // Injected services + protected NodeService nodeService; + protected SiteService siteService; + protected LinksService linksService; + protected ActivityService activityService; + protected ServiceRegistry serviceRegistry; + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setLinksService(LinksService linksService) + { + this.linksService = linksService; + } + + public void setActivityService(ActivityService activityService) + { + this.activityService = activityService; + } + + public void setServiceRegistry(ServiceRegistry serviceRegistry) + { + this.serviceRegistry = serviceRegistry; + } + + + protected String getOrNull(JSONObject json, String key) throws JSONException + { + if(json.has(key)) + { + return json.getString(key); + } + return null; + } + + /** + * Builds up a listing Paging request, based on the arguments + * specified in the URL + */ + protected PagingRequest buildPagingRequest(WebScriptRequest req) + { + String pageNumberS = req.getParameter("page"); + String pageSizeS = req.getParameter("pageSize"); + if(pageNumberS == null || pageSizeS == null) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Paging size parameters missing"); + } + + int pageNumber; + int pageSize; + try + { + pageNumber = Integer.parseInt(pageNumberS); + pageSize = Integer.parseInt(pageSizeS); + } + catch(NumberFormatException e) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Paging size parameters invalid"); + } + + PagingRequest paging = new PagingRequest( (pageNumber-1) * pageSize, pageSize ); + paging.setRequestTotalCountMax( Math.max(10, pageNumber) * pageSize ); + return paging; + } + + /** + * Generates an activity entry for the link + */ + protected void addActivityEntry(String event, LinkInfo link, SiteInfo site, + WebScriptRequest req, JSONObject json) + { + // What page is this for? + String page = req.getParameter("page"); + if(page == null && json != null) + { + if(json.has("page")) + { + try + { + page = json.getString("page"); + } + catch(JSONException e) {} + } + } + if(page == null) + { + // Default + page = "links"; + } + + try + { + JSONObject activity = new JSONObject(); + activity.put("title", link.getTitle()); + activity.put("page", page + "?linkId=" + link.getSystemName()); + + activityService.postActivity( + "org.alfresco.links.link-" + event, + site.getShortName(), + LINKS_SERVICE_ACTIVITY_APP_NAME, + activity.toString() + ); + } + catch(Exception e) + { + // Warn, but carry on + logger.warn("Error adding link " + event + " to activities feed", e); + } + } + + protected Map renderLink(LinkInfo link) + { + Map res = new HashMap(); + res.put("node", link.getNodeRef()); + res.put("name", link.getSystemName()); + res.put("title", link.getTitle()); + res.put("description", link.getDescription()); + res.put("url", link.getURL()); + res.put("createdOn", link.getCreatedAt()); + res.put("modifiedOn", link.getModifiedAt()); + res.put("tags", link.getTags()); + res.put("internal", link.isInternal()); + + // FTL needs a script node of the person + String creator = link.getCreator(); + Object creatorO; + if(creator == null) + { + creatorO = ""; + } + else + { + NodeRef person = serviceRegistry.getPersonService().getPerson(creator); + creatorO = new ScriptNode(person, serviceRegistry); + } + res.put("creator", creatorO); + + // We want blank instead of null + for(String key : res.keySet()) + { + if(res.get(key) == null) + { + res.put(key, ""); + } + } + + return res; + } + + @Override + protected Map executeImpl(WebScriptRequest req, + Status status, Cache cache) + { + Map templateVars = req.getServiceMatch().getTemplateVars(); + if(templateVars == null) + { + String error = "No parameters supplied"; + throw new WebScriptException(Status.STATUS_BAD_REQUEST, error); + } + + + // Parse the JSON, if supplied + JSONObject json = null; + String contentType = req.getContentType(); + if(contentType != null && contentType.indexOf(';') != -1) + { + contentType = contentType.substring(0, contentType.indexOf(';')); + } + if(MimetypeMap.MIMETYPE_JSON.equals(contentType)) + { + try + { + json = new JSONObject(new JSONTokener(req.getContent().getContent())); + } + catch(IOException io) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage()); + } + catch(JSONException je) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + je.getMessage()); + } + } + + + // Get the site short name. Try quite hard to do so... + String siteName = templateVars.get("site"); + if(siteName == null) + { + siteName = req.getParameter("site"); + } + if(siteName == null && json != null) + { + try + { + if(json.has("siteid")) + { + siteName = json.getString("siteid"); + } + else if(json.has("site")) + { + siteName = json.getString("site"); + } + } + catch(JSONException e) {} + } + if(siteName == null) + { + String error = "No site given"; + throw new WebScriptException(Status.STATUS_BAD_REQUEST, error); + } + + // Grab the requested site + SiteInfo site = siteService.getSite(siteName); + if(site == null) + { + String error = "Could not find site: " + siteName; + throw new WebScriptException(Status.STATUS_NOT_FOUND, error); + } + + // Link name is optional + String linkName = templateVars.get("path"); + + // Have the real work done + return executeImpl(site, linkName, req, json, status, cache); + } + + protected abstract Map executeImpl(SiteInfo site, + String linkName, WebScriptRequest req, JSONObject json, + Status status, Cache cache); + +} diff --git a/source/java/org/alfresco/repo/web/scripts/links/LinksListGet.java b/source/java/org/alfresco/repo/web/scripts/links/LinksListGet.java new file mode 100644 index 0000000000..2a21f605c3 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/links/LinksListGet.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2005-2011 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 . + */ +package org.alfresco.repo.web.scripts.links; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.jscript.ScriptNode; +import org.alfresco.repo.links.LinksServiceImpl; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.links.LinkInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.util.ScriptPagingDetails; +import org.json.JSONObject; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * This class is the controller for the links listing links.get webscript. + * + * @author Nick Burch + * @since 4.0 + */ +public class LinksListGet extends AbstractLinksWebScript +{ + protected static final int RECENT_SEARCH_PERIOD_DAYS = 7; + protected static final long ONE_DAY_MS = 24*60*60*1000; + + @Override + protected Map executeImpl(SiteInfo site, String linkName, + WebScriptRequest req, JSONObject json, Status status, Cache cache) { + // Decide on what kind of request they wanted + String filter = req.getParameter("filter"); + + // Tagging? + boolean tagFiltering = true; + String tag = req.getParameter("tag"); + if(tag == null || tag.length() == 0) + { + tagFiltering = false; + } + + // User? + boolean userFiltering = false; + String user = null; + if("user".equals(filter)) + { + userFiltering = true; + user = AuthenticationUtil.getFullyAuthenticatedUser(); + } + + // Date? + boolean dateFiltering = false; + Date from = null; + Date to = null; + if("recent".equals(filter)) + { + dateFiltering = true; + Date now = new Date(); + from = new Date(now.getTime() - RECENT_SEARCH_PERIOD_DAYS*ONE_DAY_MS); + to = new Date(now.getTime() + ONE_DAY_MS); + } + + + // Get the links for the list + PagingRequest paging = buildPagingRequest(req); + PagingResults links; + if(tagFiltering) + { + links = linksService.findLinks(site.getShortName(), user, from, to, tag, paging); + } + else + { + if(userFiltering) + { + links = linksService.listLinks(site.getShortName(), user, paging); + } + else if(dateFiltering) + { + links = linksService.listLinks(site.getShortName(), from, to, paging); + } + else + { + links = linksService.listLinks(site.getShortName(), paging); + } + } + + + // For each one in our page, grab details of any ignored instances + List> items = new ArrayList>(); + for (LinkInfo link : links.getPage()) + { + Map result = renderLink(link); + items.add(result); + } + Map data = new HashMap(); + data.put("items", items); + data.put("pageSize", paging.getMaxItems()); + data.put("startIndex", paging.getSkipCount()); + data.put("itemCount", items.size()); + + int total = items.size(); + if(links.getTotalResultCount() != null && links.getTotalResultCount().getFirst() != null) + { + total = links.getTotalResultCount().getFirst(); + } + data.put("total", total); + + // We need the container node for permissions checking + NodeRef container; + if(links.getPage().size() > 0) + { + container = links.getPage().get(0).getContainerNodeRef(); + } + else + { + container = siteService.getContainer( + site.getShortName(), LinksServiceImpl.LINKS_COMPONENT + ); + } + + // All done + Map model = new HashMap(); + model.put("data", data); + model.put("links", new ScriptNode(container, serviceRegistry)); + model.put("siteId", site.getShortName()); + model.put("site", site); + return model; + } +}