ALF-10109 Convert the last two wiki webscripts to be Java backed, using the new Service

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30144 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Nick Burch
2011-08-31 16:08:58 +00:00
parent ec600def09
commit 2fbd91d3f9
9 changed files with 362 additions and 351 deletions

View File

@@ -1,80 +0,0 @@
/**
* A collection of general functions used across most wiki scripts.
*/
const DEFAULT_PAGE_CONTENT = "This is a new page. It has no content";
/**
* Takes an array of template parameter arguments
* and returns an object keyed on parameter name.
*/
function getTemplateArgs(params)
{
var p = {};
var param;
for (var i=0; i < params.length; i++)
{
param = params[i];
p[param] = url.templateArgs[param];
}
return p;
}
/* Format and return error object */
function jsonError(errorString)
{
status.setCode(status.STATUS_BAD_REQUEST, errorString);
}
// NOTE: may need a custom content type for a wiki entry
function createWikiPage(name, folder, options)
{
var page = folder.createFile(name);
if (options)
{
if (options.content)
{
page.content = options.content;
page.mimetype = "text/html";
}
if (options.versionable)
{
page.addAspect("cm:versionable");
}
}
// Initialise tags to empty array
page.tags = [];
// Set cm:title
page.properties["cm:title"] = new String(name).replace(/_/g, " ");
page.save();
return page;
}
function getWikiContainer(site)
{
var wiki;
if (site.hasContainer("wiki"))
{
wiki = site.getContainer("wiki");
}
else
{
wiki = site.createContainer("wiki");
}
if(wiki != null)
{
if (!wiki.isTagScope)
{
wiki.isTagScope = true;
}
}
return wiki;
}

View File

@@ -1,77 +0,0 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/lib/wiki.lib.js">
/**
* Renames a wiki page. Updates the name of the current page
* and creates a link with the previous name that points to the page;
* this is done so that all references to the old page will still work.
*
* @method POST
* @param uri {string} /slingshot/wiki/page/{siteid}/{pageTitle}
*/
model.result = main();
function main()
{
if (json.isNull("name"))
{
return jsonError("No new name property specified");
}
// Remove any whitespace and replace with "_"
var newName = new String(json.get("name"));
newName = newName.replace(/\s+/g, "_");
var params = getTemplateArgs(["siteId", "pageTitle"]);
// Get the site
var site = siteService.getSite(params.siteId);
if (site === null)
{
return jsonError("Could not find site: " + params.siteId);
}
var wiki = getWikiContainer(site);
if (wiki === null)
{
return jsonError("Could not locate wiki");
}
var page = wiki.childByNamePath(params.pageTitle);
if (!page)
{
return jsonError("Could not find specified page.");
}
var existing = wiki.childByNamePath(newName);
{
if (existing)
{
status.setCode(status.STATUS_CONFLICT, "Duplicate name.");
return;
}
}
// Finally, now we can do what we are supposed to do
var currentName = new String(page.name);
page.name = newName;
page.properties["cm:title"] = new String(newName).replace(/_/g, " ");
page.save();
var placeholder = createWikiPage(currentName, wiki,
{
content: msg.get("page-moved") + " [[" + newName + "|" + msg.get("page-moved-here") + "]]."
});
var data =
{
title: newName.replace(/_/g, " "),
page: json.get("page") + "?title=" + newName,
custom0: currentName.replace(/_/g, " ")
}
activities.postActivity("org.alfresco.wiki.page-renamed", params.siteId, "wiki", jsonUtils.toJSONString(data));
return (
{
name: newName // Return the new name to the client
});
}

View File

@@ -1,10 +1,10 @@
<#assign page = result.page>
<#escape x as jsonUtils.encodeJSONString(x)>
{
"name": "${page.name}",
"title": "<#if page.properties.title?exists>${page.properties.title}<#else>${page.name?replace("_", " ")}</#if>",
"pagetext": "${page.content}",
<#assign tags><#list result.tags as tag>"${tag}"<#if tag_has_next>,</#if></#list></#assign>
"name": "${page.systemName}",
"title": "${page.title}",
"pagetext": "${page.contents}",
<#assign tags><#list page.tags as tag>"${tag}"<#if tag_has_next>,</#if></#list></#assign>
"tags": <#noescape>[${tags}]</#noescape>
}
</#escape>

View File

@@ -1,189 +0,0 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/lib/wiki.lib.js">
/**
* Update specified wiki page.
*
* @method PUT
* @param uri {string} /slingshot/wiki/page/{siteid}/{pageTitle}
*/
function getTemplateParams()
{
// Grab the URI parameters
var siteId = "" + url.templateArgs.siteId;
var pageTitle = "" + url.templateArgs.pageTitle;
if (siteId === null || siteId.length === 0)
{
return null;
}
if (pageTitle === null || pageTitle.length === 0)
{
return null;
}
return (
{
"siteId": siteId,
"pageTitle": pageTitle
});
}
function update()
{
var params = getTemplateArgs(["siteId", "pageTitle"]);
if (params === null)
{
return jsonError("No parameters supplied");
}
// Get the site
var site = siteService.getSite(params.siteId);
if (site === null)
{
return jsonError("Could not find site: " + siteId);
}
var wiki = getWikiContainer(site);
if (wiki === null)
{
return jsonError("Could not locate wiki container");
}
var page = wiki.childByNamePath(params.pageTitle), activityType;
// Create the page if it doesn't exist
if (page === null)
{
page = createWikiPage(params.pageTitle, wiki,
{
content: json.get("pagecontent"),
versionable: true
});
activityType = "org.alfresco.wiki.page-created";
}
else
{
// Check the version of the page being submitted against the version now in the repo, or a forced save
if (pageVersionMatchesSubmitted(page) || json.has("forceSave"))
{
// Create a new revision of the page
var workingCopy = page.checkout();
workingCopy.content = json.get("pagecontent");
workingCopy.checkin();
page.save();
activityType = "org.alfresco.wiki.page-edited";
}
else
{
status.setCode(status.STATUS_CONFLICT, "Repository version is newer.");
return;
}
}
var data =
{
title: params.pageTitle.replace(/_/g, " "),
page: json.get("page") + "?title=" + params.pageTitle
}
// Log activity
activities.postActivity(activityType, params.siteId, "wiki", jsonUtils.toJSONString(data));
if (!json.isNull("tags"))
{
var tags = Array(json.get("tags"));
if (tags)
{
// This is so unnecessary!
// A much cleaner approach would be to just pass in the tags as a space separated
// string and call the (native) method split
var tags = [];
var tmp = json.get("tags");
for (var x = 0, xx = tmp.length(); x < xx; x++)
{
tags.push(tmp.get(x));
}
page.tags = tags;
}
else
{
page.tags = []; // reset
}
page.save();
}
// NOTE: for now we return the raw page content and do the transformation
// of any wiki markup on the client. This is because the edit view needs to display
// the raw content (for editing) whereas the page view needs to display the rendered content.
return (
{
page: page,
tags: page.tags
});
}
/**
* Checks whether the current repository version is newer than a submitted version number.
* Returns:
* false if currentVersion is older than repoVersion
* true otherwise
*/
function pageVersionMatchesSubmitted(page)
{
var currentVersion = "0",
repoVersion = "0";
if (json.has("currentVersion"))
{
currentVersion = json.get("currentVersion");
}
if (page.hasAspect("cm:versionable"))
{
repoVersion = getLatestVersion(page.versionHistory);
}
else
{
page.addAspect("cm:versionable");
page.save();
return 0;
}
return (sortByLabel(
{
label: repoVersion
},
{
label: currentVersion
}) != -1);
}
function sortByLabel(version1, version2)
{
if ((version1.label.indexOf(".") == -1) || (version2.label.indexOf(".") == -1))
{
return -1;
}
var major1 = new Number(version1.label.substring(0, version1.label.indexOf(".")));
var major2 = new Number(version2.label.substring(0, version2.label.indexOf(".")));
if (major1 - 0 == major2 - 0)
{
var minor1 = new Number(version1.label.substring(version1.label.indexOf(".")+1));
var minor2 = new Number(version2.label.substring(version2.label.indexOf(".")+1));
return (minor1 < minor2) ? 1 : (minor1 > minor2) ? -1 : 0;
}
else
{
return (major1 < major2) ? 1 : -1;
}
}
function getLatestVersion(versionHistory)
{
versionHistory.sort(sortByLabel);
return versionHistory[0].label;
}
model.result = update();

View File

@@ -1585,6 +1585,19 @@
<property name="versionService" ref="VersionService" />
</bean>
<!-- Creates and Edits wiki pages -->
<bean id="webscript.org.alfresco.slingshot.wiki.page.put"
class="org.alfresco.repo.web.scripts.wiki.WikiPagePut"
parent="abstractWikiWebScript">
<property name="versionService" ref="VersionService" />
</bean>
<!-- Renames a wiki page (changing the title and name) -->
<bean id="webscript.org.alfresco.slingshot.wiki.move.post"
class="org.alfresco.repo.web.scripts.wiki.WikiPageMovePost"
parent="abstractWikiWebScript">
</bean>
<!-- Deletes a wiki page -->
<bean id="webscript.org.alfresco.slingshot.wiki.page.delete"
class="org.alfresco.repo.web.scripts.wiki.WikiPageDelete"

View File

@@ -25,7 +25,6 @@ import java.util.Map;
import org.alfresco.query.PagingRequest;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.activities.ActivityService;
import org.alfresco.service.cmr.links.LinkInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService;

View File

@@ -0,0 +1,118 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.wiki;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.wiki.WikiPageInfo;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* This class is the controller for the wiki page renaming move.post webscript.
*
* TODO Track links to pages, so we can avoid creating the "This page has been moved"
* stubs as now, for cases where nothing links to the page being renamed. (ALF-3844)
*
* @author Nick Burch
* @since 4.0
*/
public class WikiPageMovePost extends AbstractWikiWebScript
{
private static final String MSG_MOVED = "page-moved";
private static final String MSG_MOVED_HERE = "page-moved-here";
@Override
protected Map<String, Object> executeImpl(SiteInfo site, String pageName,
WebScriptRequest req, JSONObject json, Status status, Cache cache) {
final Map<String, Object> model = new HashMap<String, Object>();
final ResourceBundle rb = getResources();
// Try to find the page we're renaming
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageName);
if(page == null)
{
String message = "The Wiki Page could not be found";
status.setCode(Status.STATUS_NOT_FOUND);
status.setMessage(message);
// Wrap and bail
model.put("error", message);
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", model);
return result;
}
// Grab the new Title
String newTitle;
try
{
// The "name" in the JSON is actually the title!
newTitle = json.getString("name");
}
catch(JSONException e)
{
throw new WebScriptException("Invalid JSON: " + e.getMessage());
}
// Have the page re-named, if possible
String oldTitle = page.getTitle();
try
{
page.setTitle(newTitle);
page = wikiService.updateWikiPage(page);
}
catch(FileExistsException e)
{
throw new WebScriptException(Status.STATUS_CONFLICT, "Duplicate page name");
}
// Create the "This page has been moved" entry for the old page
String movedContent = rb.getString(MSG_MOVED) + " [[" + page.getSystemName() +
"|" + rb.getString(MSG_MOVED_HERE) + "]].";
wikiService.createWikiPage(site.getShortName(), oldTitle, movedContent);
// Add an activity entry for the rename
addActivityEntry("renamed", page, site, req, json);
// All done
model.put("name", page.getSystemName());
model.put("page", page);
model.put("siteId", site.getShortName());
model.put("site", site);
// Double wrap
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", model);
return result;
}
}

View File

@@ -0,0 +1,210 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.wiki;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.wiki.WikiPageInfo;
import org.alfresco.service.namespace.QName;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* This class is the controller for the wiki page creating/editing page.put webscript.
*
* @author Nick Burch
* @since 4.0
*/
public class WikiPagePut extends AbstractWikiWebScript
{
private static final String DEFAULT_PAGE_CONTENT = "This is a new page. It has no content";
private VersionService versionService;
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
@Override
protected Map<String, Object> executeImpl(SiteInfo site, String pageName,
WebScriptRequest req, JSONObject json, Status status, Cache cache) {
Map<String, Object> model = new HashMap<String, Object>();
// Grab the details of the change
List<String> tags = null;
String currentVersion = null;
boolean forceSave;
String contents;
String title;
try
{
// Fetch the contents
contents = json.getString("pagecontent");
// Fetch the title, used only when creating
if(json.has("title"))
{
title = json.getString("title");
}
else
{
title = pageName;
}
// Fetch the versioning details
forceSave = json.has("forceSave");
if(json.has("currentVersion"))
{
currentVersion = json.getString("currentVersion");
}
// Fetch the tags, if given
if(json.has("tags"))
{
tags = new ArrayList<String>();
if(json.get("tags").equals(""))
{
// Empty list given as a string, eg "tags":""
}
else
{
// Array of tags
JSONArray tagsA = json.getJSONArray("tags");
for(int i=0; i<tagsA.length(); i++)
{
tags.add(tagsA.getString(i));
}
}
}
}
catch(JSONException e)
{
throw new WebScriptException("Invalid JSON: " + e.getMessage());
}
// Are we creating or editing?
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageName);
if(page == null)
{
// Create the page
page = wikiService.createWikiPage(site.getShortName(), title, contents);
// Add tags if given
if(tags != null && tags.size() > 0)
{
page.getTags().addAll(tags);
wikiService.updateWikiPage(page);
}
// Make it versioned
makeVersioned(page);
// Generate the activity
addActivityEntry("created", page, site, req, json);
}
else
{
// Updating, check about versioning first
if(forceSave || pageVersionMatchesSubmitted(page, currentVersion))
{
// Update the page
page.setContents(contents);
if(tags != null && tags.size() > 0)
{
page.getTags().clear();
page.getTags().addAll(tags);
}
wikiService.updateWikiPage(page);
}
else
{
// Editing the wrong version
String message = "Repository version is newer.";
throw new WebScriptException(Status.STATUS_CONFLICT, message);
}
// Generate the activity
addActivityEntry("edited", page, site, req, json);
}
// All done
model.put("page", page);
model.put("site", site);
model.put("siteId", site.getShortName());
// Double wrap
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", model);
return result;
}
private boolean pageVersionMatchesSubmitted(WikiPageInfo page, String currentVersion)
{
// If they didn't give version, it can't be right
if(currentVersion == null)
{
return false;
}
// Grab the current version
Version version = versionService.getCurrentVersion(page.getNodeRef());
if(version == null)
{
// It should be versioned already, fix that
makeVersioned(page);
// Wasn't versioned before, so can't detect conflict
return true;
}
// Check the label
if(version.getVersionLabel().equals(currentVersion))
{
// Match, no changes
return true;
}
else
{
// Someone else has edited it
return false;
}
}
private void makeVersioned(WikiPageInfo page)
{
Map<QName,Serializable> versionProps = new HashMap<QName, Serializable>();
versionProps.put(ContentModel.PROP_AUTO_VERSION, true);
versionProps.put(ContentModel.PROP_AUTO_VERSION_PROPS, true);
versionService.ensureVersioningEnabled(page.getNodeRef(), versionProps);
}
}

View File

@@ -523,6 +523,23 @@ public class WikiRestApiTest extends BaseWebScriptTest
assertEquals(name, page.getString("name"));
assertEquals(PAGE_TITLE_TWO, page.getString("title"));
assertEquals("This page has been moved [["+name2+"|here]].", page.getString("pagetext"));
// Ensure you can't rename onto an existing page
page = createOrUpdatePage(PAGE_TITLE_ONE, PAGE_CONTENTS_THREE, null, Status.STATUS_OK);
String name1 = PAGE_TITLE_ONE.replace(' ', '_');
// Check the rename won't work
renamePage(PAGE_TITLE_THREE, PAGE_TITLE_ONE, Status.STATUS_CONFLICT);
// Check that the pages weren't changed
page = getPage(name2, Status.STATUS_OK);
assertEquals(name2, page.getString("name"));
assertEquals(PAGE_TITLE_THREE, page.getString("title"));
page = getPage(name1, Status.STATUS_OK);
assertEquals(name1, page.getString("name"));
assertEquals(PAGE_TITLE_ONE, page.getString("title"));
}
public void testVersioning() throws Exception