diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/lib/wiki.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/lib/wiki.lib.js deleted file mode 100644 index 9177d9979d..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/lib/wiki.lib.js +++ /dev/null @@ -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; -} diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/move.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/move.post.json.js deleted file mode 100644 index d47b1e6b65..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/move.post.json.js +++ /dev/null @@ -1,77 +0,0 @@ - -/** - * 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 - }); -} \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.ftl index 587af9d9eb..57c6a00648 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.ftl @@ -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("_", " ")}", - "pagetext": "${page.content}", - <#assign tags><#list result.tags as tag>"${tag}"<#if tag_has_next>, + "name": "${page.systemName}", + "title": "${page.title}", + "pagetext": "${page.contents}", + <#assign tags><#list page.tags as tag>"${tag}"<#if tag_has_next>, "tags": <#noescape>[${tags}] } diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.js deleted file mode 100644 index c8ff8cafe1..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/wiki/page.put.json.js +++ /dev/null @@ -1,189 +0,0 @@ - - -/** - * 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(); \ No newline at end of file diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index 816f9bea85..61284b0c68 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -1585,6 +1585,19 @@ + + + + + + + + + . + */ +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 executeImpl(SiteInfo site, String pageName, + WebScriptRequest req, JSONObject json, Status status, Cache cache) { + final Map model = new HashMap(); + 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 result = new HashMap(); + 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 result = new HashMap(); + result.put("result", model); + return result; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/wiki/WikiPagePut.java b/source/java/org/alfresco/repo/web/scripts/wiki/WikiPagePut.java new file mode 100644 index 0000000000..bf79cb0626 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/wiki/WikiPagePut.java @@ -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 . + */ +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 executeImpl(SiteInfo site, String pageName, + WebScriptRequest req, JSONObject json, Status status, Cache cache) { + Map model = new HashMap(); + + // Grab the details of the change + List 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(); + 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 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 result = new HashMap(); + 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 versionProps = new HashMap(); + versionProps.put(ContentModel.PROP_AUTO_VERSION, true); + versionProps.put(ContentModel.PROP_AUTO_VERSION_PROPS, true); + versionService.ensureVersioningEnabled(page.getNodeRef(), versionProps); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/wiki/WikiRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/wiki/WikiRestApiTest.java index b8a618085f..47d107f763 100644 --- a/source/java/org/alfresco/repo/web/scripts/wiki/WikiRestApiTest.java +++ b/source/java/org/alfresco/repo/web/scripts/wiki/WikiRestApiTest.java @@ -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