/**
* 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/>.
*/
/**
* Handles requests retrieve documents from the repository and publishes the details of them when they're
* retrieved.
*
* @module alfresco/services/DocumentService
* @extends module:alfresco/services/BaseService
* @author Dave Draper
* @author David Webster
*/
define(["dojo/_base/declare",
"alfresco/services/BaseService",
"alfresco/core/CoreXhr",
"alfresco/core/topics",
"service/constants/Default",
"alfresco/core/PathUtils",
"alfresco/core/NodeUtils",
"alfresco/enums/urlTypes",
"dojo/_base/lang",
"dojo/dom-construct",
"dojo/_base/array"],
function(declare, BaseService, CoreXhr, topics, AlfConstants, PathUtils, NodeUtils, urlTypes, lang, domConstruct, array) {
return declare([BaseService, CoreXhr, PathUtils], {
/**
* An array of the i18n files to use with this widget.
*
* @instance
* @type {object[]}
* @default [{i18nFile: "./i18n/DocumentService.properties"}]
*/
i18nRequirements: [{i18nFile: "./i18n/DocumentService.properties"}],
/**
* How long should we wait before triggering a request on a failed progress update?
*
* @instance
* @type {int}
* @default
*/
archiveProgressUpdateFailureInterval: 5000,
/**
* How often should we request an update on an Archive's progress?
*
* @instance
* @type {int}
* @default
*/
archiveProgressUpdateInterval: 250,
/**
* The URL used to cancel document editing
*
* @instance
* @type {String}
* @default [AlfConstants.PROXY_URI + "cancel-checkout/node/"]
* @todo should this be parameterised?
*/
cancelEditAPI: AlfConstants.PROXY_URI + "slingshot/doclib/action/cancel-checkout/node/",
/**
* The URL to the download API
*
* @instance
* @type {String}
* @default [AlfConstants.PROXY_URI + "api/internal/downloads"]
* @todo should this be parameterised?
*/
downloadAPI: AlfConstants.PROXY_URI + "api/internal/downloads",
/**
* This is a reference to an IFrame that gets created to handle download requests. An IFrame is required because
* it is possible that the full metadata for the node to download may need to be requested over an XHR request
* and the use of an IFrame prevents browser popup blocking occuring in this scenario. See AKU-757.
*
* @instance
* @type {element}
* @default
* @since 1.0.61
*/
downloadIFrame: null,
/**
* Overrides the default setting for encoding URIs
*
* @instance
* @type {boolean}
* @default
*/
encodeURIs: false,
/**
* How many times should we retry a failed archive progress request?
*
* @instance
* @type {int}
* @default
*/
maxArchiveProgressRetryCount: 6,
/**
* Indicates whether or not XHR requests should be rooted directly to the Alfresco Repository
* and bypass the Share web-tier.
*
* @instance
* @type {boolean}
* @default
* @since 1.0.33
*/
rawData: false,
/**
*
* @instance
* @since 1.0.32
* @listens module:alfresco/core/topics#GET_DOCUMENT
* @listens module:alfresco/core/topics#GET_DOCUMENT_LIST
* @listens module:alfresco/core/topics#REQUEST_ARCHIVE
* @listens module:alfresco/core/topics#REQUEST_ARCHIVE_PROGRESS
* @listens module:alfresco/core/topics#DELETE_ARCHIVE
* @listens module:alfresco/core/topics#DOWNLOAD
* @listens module:alfresco/core/topics#DOWNLOAD_AS_ZIP
* @listens module:alfresco/core/topics#DOWNLOAD_GENERATED_ARCHIVE
* @listens module:alfresco/core/topics#CANCEL_EDIT
* @listens module:alfresco/core/topics#GET_PARENT_NODEREF
* @listens module:alfresco/core/topics#SMART_DOWNLOAD
* @listens module:alfresco/core/topics#DOWNLOAD_ON_NODE_RETRIEVAL_SUCCESS
*/
registerSubscriptions: function alfresco_services_DocumentService__registerSubscriptions() {
// Bind to document topics:
this.alfSubscribe(topics.GET_DOCUMENT, lang.hitch(this, this.onRetrieveSingleDocumentRequest));
this.alfSubscribe(topics.GET_DOCUMENT_LIST, lang.hitch(this, this.onRetrieveDocumentsRequest));
// Bind to archive topics:
this.alfSubscribe(topics.REQUEST_ARCHIVE, lang.hitch(this, this.onRequestArchive));
this.alfSubscribe(topics.REQUEST_ARCHIVE_PROGRESS, lang.hitch(this, this.onRequestArchiveProgress));
this.alfSubscribe(topics.REQUEST_DELAYED_ARCHIVE_PROGRESS, lang.hitch(this, this.onRequestDelayedArchiveProgress));
this.alfSubscribe(topics.DELETE_ARCHIVE, lang.hitch(this, this.onDeleteDownloadArchive));
// Bind to download topics:
this.alfSubscribe(topics.DOWNLOAD, lang.hitch(this, this.onDownload));
this.alfSubscribe(topics.DOWNLOAD_AS_ZIP, lang.hitch(this, this.onDownloadAsZip));
this.alfSubscribe(topics.DOWNLOAD_NODE, lang.hitch(this, this.onDownloadFile));
this.alfSubscribe(topics.CANCEL_EDIT, lang.hitch(this, this.onCancelEdit));
this.alfSubscribe(topics.GET_PARENT_NODEREF, lang.hitch(this, this.onGetParentNodeRef));
this.alfSubscribe(topics.SMART_DOWNLOAD, lang.hitch(this, this.onSmartDownload));
this.alfSubscribe(topics.DOWNLOAD_ON_NODE_RETRIEVAL_SUCCESS, lang.hitch(this, this.onDocumentRetrievedForDownload));
},
/**
* Retrieves the details for a single document. This currently uses the Repository API and therefore won't collect any Share specific
* information such as actions, etc. However this could be updated to use a new WebScript in the future.
*
* @instance
* @param {object} payload The payload defining the document to retrieve the details for.
*/
onRetrieveSingleDocumentRequest: function alfresco_services_DocumentService__onRetrieveSingleDocumentRequest(payload) {
if (!payload || !payload.nodeRef)
{
this.alfLog("warn", "A request was made to retrieve the details of a document but no 'nodeRef' attribute was provided", payload, this);
}
else
{
var nodeRef = NodeUtils.processNodeRef(payload.nodeRef),
targetNodeUri = nodeRef.uri;
// View mode and No-cache
var params = "?view=";
params += encodeURIComponent(payload.view || "browse");
params += "&noCache=" + new Date().getTime() + "&includeThumbnails=true";
var alfTopic = payload.alfResponseTopic || topics.GET_DOCUMENT;
var url;
if (payload.rawData === true || this.rawData === true)
{
url = AlfConstants.PROXY_URI + "slingshot/doclib2/node/" + targetNodeUri + params;
}
else
{
url = AlfConstants.URL_SERVICECONTEXT + "components/documentlibrary/data/";
if (payload.site)
{
url += "site/" + encodeURIComponent(payload.site) + "/";
}
url += "node/" + targetNodeUri + params;
}
var config = {
alfTopic: alfTopic,
url: url,
method: "GET",
callbackScope: this,
originalPayload: payload
};
this.serviceXhr(config);
}
},
/**
* Handles requests to retrieve documents. The payload should contain the following properties:
*
* path
* type
* site
* container
* filter
* page
* pageSize
* sortAscending
* sortField
* rootNode
*
* @instance
* @param {object} payload The payload published on the topic
*/
onRetrieveDocumentsRequest: function alfresco_services_DocumentService__onRetrieveDocumentsRequest(payload) {
// jshint maxcomplexity:false, maxstatements:false
var targetNode = "alfresco://company/home",
targetNodeUri = "alfresco/company/home";
if (payload.nodeRef)
{
var nodeRef = NodeUtils.processNodeRef(payload.nodeRef);
targetNode = payload.nodeRef;
targetNodeUri = nodeRef.uri;
}
// Construct the URI for the request...
var uriPart = payload.site ? "{type}/site/{site}/{container}" : "{type}/node/" + targetNodeUri;
if (payload.filter && payload.filter.path)
{
// If a path has been provided in the filter then it is necessary to perform some special
// encoding. We need to ensure that the data is URI encoded, but we want to preserve the
// forward slashes. We also need to "double encode" all % characters because FireFox has
// a nasty habit of decoding them *before* they've actually been posted back... this
// guarantees that the user will be able to bookmark valid URLs...
var encodedPath = encodeURIComponent(payload.filter.path).replace(/%2F/g, "/").replace(/%25/g,"%2525");
uriPart += this.combinePaths("/", encodedPath);
}
// Unbelievably it is necessary to remove any trailing forward slashes otherwise the location
// data set for each item will duplicate first element in the path !!!
if (uriPart.lastIndexOf("/") === uriPart.length-1)
{
uriPart = uriPart.substring(0, uriPart.length-1);
}
// Build the URI stem
var params = lang.replace(uriPart, {
type: encodeURIComponent(payload.type || "all"),
site: encodeURIComponent(payload.site),
container: encodeURIComponent(payload.container)
});
if (payload.filter)
{
if (payload.filter.filter)
{
params += "?filter=" + payload.filter.filter;
}
else if (payload.filter.tag)
{
params += "?filter=tag&filterData=" + payload.filter.tag;
}
else if (payload.filter.category)
{
params += "?filter=category&filterData=" + payload.filter.category;
}
else
{
params += "?filter=path";
}
}
// NOTE: It makes no sense for pageSize or page to be zero here in this if statement!
if (payload.pageSize && payload.page)
{
params += "&size=" + payload.pageSize + "&pos=" + payload.page;
}
// Sort parameters
params += "&sortAsc=" + payload.sortAscending + "&sortField=" + encodeURIComponent(payload.sortField);
if (!payload.site)
{
if (payload.libraryRoot)
{
params += "&libraryRoot=" + encodeURIComponent(payload.libraryRoot);
}
else
{
// Repository mode (don't resolve Site-based folders)
params += "&libraryRoot=" + encodeURIComponent(targetNode);
}
}
// View mode and No-cache
params += "&view=";
params += encodeURIComponent(payload.view || "browse");
params += "&noCache=" + new Date().getTime();
var alfTopic = payload.alfResponseTopic || topics.GET_DOCUMENT_LIST;
var url;
if (payload.rawData === true || this.rawData === true)
{
url = AlfConstants.PROXY_URI + "slingshot/doclib2/doclist/" + params;
}
else
{
url = AlfConstants.URL_SERVICECONTEXT + "components/documentlibrary/data/";
if (payload.site)
{
url += "site/" + encodeURIComponent(payload.site) + "/";
}
url += "doclist/" + params;
}
var config = {
requestId: payload.requestId,
alfTopic: alfTopic,
url: url,
method: "GET",
callbackScope: this
};
this.serviceXhr(config);
},
/**
* Handles requests to download a single document.
*
* @instance
* @param {object} payload The published payload that should contain a node.contentURL attribute.
* @since 1.0.43
* @fires module:alfresco/core/topics#NAVIGATE_TO_PAGE
*/
onDownload: function alfresco_services_DocumentService__onDownload(payload) {
var contentURL = lang.getObject("node.contentURL", false, payload);
if (contentURL)
{
// Strip off any superfluous forward slash at the beginning of the URL, this is required
// because the PROXY_URI has a trailing slash included...
if (contentURL[0] === "/")
{
contentURL = contentURL.substring(1);
}
if (this.downloadIFrame)
{
this.downloadIFrame.src = AlfConstants.PROXY_URI + contentURL + "?a=true";
}
else
{
this.downloadIFrame = domConstruct.create("iframe", {
id: "ALF_DOCUMENT_SERVICE_DOWNLOAD_IFRAME",
src: AlfConstants.PROXY_URI + contentURL + "?a=true",
style: "display:none"
}, document.body);
}
}
else
{
this.alfLog("warn", "A request was made to download a document but no 'node.contentURL' attribute was found in the payload provided", payload, this);
}
},
/**
* This function is provided to handle downloads of selected items with some intelligence. If a single
* document is selected then it will be downloaded
* (via the [onDownload]{@link module:alfresco/services/DocumentService#onDownload}), but if multiple items
* are selected then they will be downloaded as an archive
* (via the [onDownloadAsZip]{@link module:alfresco/services/DocumentService#onDownloadAsZip}) function.
* If a single folder is selected then it will be downloaded as an archive. This function is also able to cope
* with data provided by either the Document Library or Search APIs.
*
* @instance
* @param {object} payload An object containing the items to download.
* @since 1.0.43
*/
onSmartDownload: function alfresco_servicews_DocumentService__onSmartDownload(payload) {
if (payload.nodes)
{
if (payload.nodes.length === 1)
{
// For single items perform a single download...
// However, we still need to check the item type (i.e. whether it is a document or folder)...
var node = payload.nodes[0];
if (node.node)
{
// Document Library style API
if (node.node.isContainer === true)
{
this.onDownloadAsZip(payload);
}
else
{
this.onDownload(node);
}
}
else if (node.type === "document" && node.nodeRef)
{
// Search style API document, it is necessary to request the full metadata of the node...
this.onRetrieveSingleDocumentRequest({
nodeRef: node.nodeRef,
alfResponseTopic: "ALF_DOWNLOAD_ON_NODE_RETRIEVAL"
});
}
else if (node.type === "folder")
{
// Search style API folder...
this.onDownloadAsZip(payload);
}
else
{
this.alfLog("warn", "A request was made to perform a smart download on a single item but it was not able to determine if the item was a document or a folder", payload, this);
}
}
else
{
// Always download multiple files as a zip...
this.onDownloadAsZip(payload);
}
}
else
{
this.alfLog("warn", "A request was made to perform a smart download but no 'nodes' attribute was provided in the payload", payload, this);
}
},
/**
* This is the callback function from requests to retrieve the metadata for a node defined by the
* Search API called from the [onSmartDownload]{@link module:alfresco/services/DocumentService#onSmartDownload}
* function.
*
* @instance
* @param {object} payload The full metadata of a node to download.
* @since 1.0.43
*/
onDocumentRetrievedForDownload: function alfresco_services_DocumentService__onDocumentRetrievedForDownload(payload) {
var node = lang.getObject("response.item", false, payload);
if (node)
{
this.onDownload(node);
}
},
/**
* Handles requests to download one or more documents and/or folders as a ZIP archive.
*
* @instance
* @param {object} payload The payload containing the nodes to archive and download
* @since 1.0.33
*/
onDownloadAsZip: function alfresco_services_DocumentService__onDownloadAsZip(payload) {
// Make sure that the nodeRef is an attribute at the root of each document, this is
// required to support clients using "raw" data retrieved directly from the Repository...
if (payload.documents)
{
array.forEach(payload.documents, function(item) {
item.nodeRef = item.nodeRef || item.node.nodeRef;
});
}
else if (payload.document)
{
payload.document.nodeRef = payload.document.nodeRef || payload.document.node.nodeRef;
}
this.alfPublish(topics.CREATE_DIALOG, {
generatePubSubScope: true,
dialogId: "ARCHIVING_DIALOG",
dialogTitle: this.message("services.ActionService.ActionFolderDownload.title"),
hideTopic: "ALF_CLOSE_DIALOG",
widgetsContent: [
{
name: "alfresco/renderers/Progress",
config: {
requestProgressTopic: topics.REQUEST_ARCHIVE,
progressFinishedTopic: [topics.DOWNLOAD_NODE, topics.DELETE_ARCHIVE],
nodes: payload.documents || [payload.document]
}
}
],
widgetsButtons: [
{
name: "alfresco/buttons/AlfButton",
config: {
label: this.message("services.ActionService.button.cancel"),
additionalCssClasses: "alfresco-dialogs-AlfProgress cancellation call-to-action",
publishTopic: "ALF_PROGRESS_CANCELLED"
}
}
],
handleOverflow: false
}, true);
},
/**
*
* @instance
* @param {object} payload
*/
onRequestArchive: function alfresco_services_DocumentService__onRequestArchive(payload) {
var nodes = payload.nodes,
responseTopic = this.generateUuid();
if (!nodes)
{
this.alfLog("error", "No Nodes to generate Archive from");
}
else
{
var subscriptionHandle = this.alfSubscribe(responseTopic + "_SUCCESS", lang.hitch(this, this.onRequestArchiveSuccess));
this.serviceXhr({
alfTopic: responseTopic,
subscriptionHandle: subscriptionHandle,
url: this.downloadAPI,
method: "POST",
data: nodes,
payload: payload
});
}
},
/**
* Called when the initial request to create the Download Archive Succeeds.
*
* @instance
* @param payload
*/
onRequestArchiveSuccess: function alfresco_services_DocumentService__onRequestArchiveSuccess(payload) {
this.alfLog("info", "Archive successfully requested");
// Clean up listeners
if (payload.subscriptionHandle)
{
this.alfUnsubscribe(payload.subscriptionHandle);
}
var publishPayload = lang.getObject("requestConfig.payload", false, payload);
if (!publishPayload)
{
this.alfLog("error", "Unable to retrieve passed in payload from requestConfig.");
}
else
{
publishPayload.archiveNodeRef= lang.getObject("response.nodeRef", false, payload);
if (!publishPayload.archiveNodeRef)
{
this.alfLog("error", "archiveNodeRef missing from response object.");
}
else
{
// The archiving has started - now check the progress:
this.alfPublish(topics.REQUEST_ARCHIVE_PROGRESS, publishPayload);
}
}
},
/**
* Called when the initial request to create the Download Archive Fails.
*
* @instance
* @param payload
*/
onRequestArchiveFailure: function alfresco_services_DocumentService__onRequestArchiveFailure(payload) {
// jshint unused:false
this.alfLog("error", "Unable to request archive");
},
/**
* Are we nearly there yet? Can we download the Archive yet?
*
* @instance
* @param payload
*/
onRequestArchiveProgress: function alfresco_services_DocumentService__onRequestArchiveProgress(payload) {
// Payload varies depending on
var progressRequestPayload = (payload.requestConfig) ? lang.getObject("requestConfig.progressRequestPayload", false, payload) : payload;
// Check payload has archiveNodeRef in.
if (!progressRequestPayload.archiveNodeRef)
{
this.alfLog("error", "Unable to retrieve nodeRef from payload: " + progressRequestPayload);
}
else
{
var responseTopic = this.generateUuid();
// Remove old listeners before creating new ones.
if (progressRequestPayload.subscriptionHandles)
{
this.alfUnsubscribe(progressRequestPayload.subscriptionHandles);
}
var subscriptionHandles = [
this.alfSubscribe(responseTopic + "_SUCCESS", lang.hitch(this, this.onActionRequestArchiveProgressSuccess)),
this.alfSubscribe(responseTopic + "_FAILURE", lang.hitch(this, this.onActionRequestArchiveProgressFailure))
];
this.serviceXhr({
alfTopic: responseTopic,
subscriptionHandles: subscriptionHandles,
progressRequestPayload: progressRequestPayload,
url: this.downloadAPI + "/" + progressRequestPayload.archiveNodeRef.replace("://", "/") + "/status",
method: "GET"
});
}
},
/**
* @instance
* @param {object} payload
*/
onRequestDelayedArchiveProgress: function alfresco_services_DocumentService__onRequestDelayedArchiveProgress(payload) {
this.alfPublishDelayed(topics.REQUEST_ARCHIVE_PROGRESS, payload, this.archiveProgressUpdateInterval);
},
/**
* Handles the Archive progress response.
*
* @instance
* @param payload
*/
onActionRequestArchiveProgressSuccess: function alfresco_services_DocumentService__onActionRequestArchiveProgressSuccess(payload) {
// Remove subscriptionListeners
if (payload.subscriptionHandles)
{
this.alfUnsubscribe(payload.subscriptionHandles);
}
if (!(payload && payload.response && payload.response.status))
{
this.alfLog("error", "Archive Progress Response Status missing");
}
else
{
var status = payload.response.status;
var progressRequestPayload = payload.requestConfig.progressRequestPayload;
// Clean up the payload a little:
payload.nodeRef = payload.requestConfig.progressRequestPayload.archiveNodeRef;
switch (status)
{
case "PENDING":
// Check again in a little bit.
this.alfPublish(topics.REQUEST_DELAYED_ARCHIVE_PROGRESS, payload);
break;
case "IN_PROGRESS":
// ok, we've got progress. Check again soon.
this.alfPublish(topics.REQUEST_DELAYED_ARCHIVE_PROGRESS, payload);
// Use the topic from the payload to notify the dialog of an update.
this.alfPublish(progressRequestPayload.progressUpdateTopic, payload);
break;
case "DONE":
// Now we're ready to download.
this.alfPublish(progressRequestPayload.progressCompleteTopic, payload);
break;
case "CANCELLED":
this.alfLog("info", "Archive cancelled");
this.alfPublish(progressRequestPayload.progressCancelledTopic, payload);
break;
default:
// Pass on error status:
// e.g. status = "MAX_CONTENT_SIZE_EXCEEDED"
progressRequestPayload.errorMessage = status;
this.alfPublish(progressRequestPayload.progressErrorTopic, payload);
break;
}
}
},
/**
*
* Handles the Archive progress failure.
*
* @instance
* @param payload
*/
onActionRequestArchiveProgressFailure: function alfresco_services_DocumentService__onActionRequestArchiveProgressFailure(payload) {
this.alfLog("warn", "Error getting archive progress: " + payload);
// Remove subscriptionListeners
if (payload.subscriptonHandles)
{
this.alfUnsubscribe(payload.subscriptionHandles);
}
var failureCount = payload.requestConfig.progressRequestPayload.failureCount || 0;
if (failureCount < this.maxArchiveProgressRetryCount)
{
payload.requestConfig.progressRequestPayload.failureCount = ++failureCount;
this.alfPublish(topics.REQUEST_DELAYED_ARCHIVE_PROGRESS, payload);
}
else
{
this.alfLog("warn", "Failed to get archive progress");
this.alfPublish(topics.ARCHIVE_PROGRESS_FAILURE, payload);
}
},
/**
* Called to Delete a Download Archive, to clean up the server.
*
* @instance
* @param payload
*/
onDeleteDownloadArchive: function alfresco_services_DocumentService__onDeleteDownloadArchive(payload) {
// TODO: Error handling? Handle Success?
this.serviceXhr({
url: this.downloadAPI + "/" + payload.nodeRef.replace("://", "/"),
method: "delete"
});
},
/**
* Called to trigger an async file download.
*
* @instance
* @param payload Payload supplied to the event
*/
onDownloadFile: function alfresco_services_DocumentService__onDownloadFile(payload) {
var nodeRefObj = NodeUtils.processNodeRef(payload.nodeRef);
var fileName = payload.fileName || this.message("services.DocumentService.archiveName") + ".zip";
var form = domConstruct.create("form");
form.method = "GET";
form.action = AlfConstants.PROXY_URI + "api/node/content/" + nodeRefObj.uri + "/" + encodeURIComponent(fileName);
domConstruct.place(form, document.body);
var iframe = domConstruct.create("iframe");
iframe.style.display = "none";
iframe.name = iframe.id = "downloadArchive_" + this.generateUuid();
domConstruct.place(iframe, document.body);
// makes it possible to target the frame properly in IE.
window.frames[iframe.name].name = iframe.name;
form.target = iframe.name;
form.submit();
},
/**
* Called to cancel the editing of a checked out file.
*
* @instance
* @param {object} payload The payload supplied when the event was triggered.
*/
onCancelEdit: function alfresco_services_DocumentService__onCancelEdit(payload) {
if (payload.documents)
{
var nodes = NodeUtils.nodeRefArray(payload.documents);
array.forEach(nodes, lang.hitch(this, this.onCancelEditNode, payload));
}
else if (payload.document)
{
this.onCancelEditNode(payload, payload.document);
}
else
{
this.alfLog("error", "Unable to cancel editing: 'documents' or 'document' missing from payload", payload, this);
}
},
/**
* Call the Alfresco Repository API to cancel the editing the node provided.
*
* @instance
* @param {object} payload The original payload from the request.
* @param {string} node The node to cancel the editing on.
*/
onCancelEditNode: function alfresco_services_DocumentService__onCancelEditNode(payload, node) {
if (node && node.nodeRef)
{
var nodeRefObj = NodeUtils.processNodeRef(node.nodeRef);
var responseTopic = this.generateUuid();
var subscriptionHandle = this.alfSubscribe(responseTopic + "_SUCCESS", lang.hitch(this, this.onCancelEditNodeSuccess));
this.serviceXhr({
alfTopic: responseTopic,
responseScope: payload.alfResponseScope,
subscriptionHandles: subscriptionHandle,
url: this.cancelEditAPI + nodeRefObj.uri,
method: "POST",
data: {}
});
}
},
/**
* Triggered when the cancel edit call succeeds.
*
* @instance
* @param payload The payload from the request to cancel editing
*/
onCancelEditNodeSuccess: function alfresco_services_DocumentService__onCancelEditNodeSuccess(payload) {
this.alfPublish(topics.RELOAD_DATA_TOPIC, {}, false, false, payload.requestConfig.responseScope);
},
/**
* Retrieve the nodeRef for a given node's parent, by requesting the details for that node.
*
* @instance
* @param payload {Object} The publish event payload.
*/
onGetParentNodeRef: function alfresco_services_DocumentService__onGetParentNodeRef(payload) {
var responseTopic = this.generateUuid(),
subscriptionHandle = this.alfSubscribe(responseTopic + "_SUCCESS", lang.hitch(this, this.onGetParentNodeRefSuccess));
if (lang.isArray(payload.subscriptionHandles))
{
payload.subscriptionHandles.push(subscriptionHandle);
}
payload.alfResponseTopic = responseTopic;
this.alfPublish(topics.GET_DOCUMENT, payload);
},
/**
* Triggered by onGetParentNodeRef when the request returns successfully.
* This method processes the response to pull out the parent node, then triggers the originalResponseTopic
* that was passed into the request to get the parent nodeRef.
*
* @instance
* @param payload {Object} The publish event payload.
*/
onGetParentNodeRefSuccess: function alfresco_services_DocumentService__onGetParentNodeRefSuccess(payload) {
var responseTopic = lang.getObject("requestConfig.originalPayload.originalResponseTopic", false, payload);
if (responseTopic)
{
var parent = lang.getObject("response.item.parent", false, payload);
if (!parent)
{
parent = lang.getObject("response.metadata.parent", false, payload);
}
if (parent)
{
var publishPayload = {
node: parent
};
this.alfPublish(responseTopic, publishPayload);
}
else
{
this.alfLog("error", "Could not retrieve parent node from response data.", payload, this);
}
}
else
{
this.alfLog("error", "Unable to retrieve originalResponseTopic, so can't let the original caller know we have the parentNode Ref.", payload, this);
}
}
});
});