Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 142 additions & 20 deletions core/js/oc-backbone-webdav.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
// so we take the part before that
} while (!result && parts.length > 0);

return result;
return decodeURIComponent(result);
}

function isSuccessStatus(status) {
Expand All @@ -142,8 +142,8 @@
var changedProp = davProperties[key];
var value = attrs[key];
if (!changedProp) {
console.warn('No matching DAV property for property "' + key);
changedProp = key;
// no matching DAV property for property, skip
continue;
}
if (_.isBoolean(value) || _.isNumber(value)) {
// convert to string
Expand Down Expand Up @@ -179,10 +179,10 @@
});
}

function callPropPatch(client, options, model, headers) {
function callPropPatch(client, options, model, headers, changed) {
return client.propPatch(
options.url,
convertModelAttributesToDavProperties(model.changed, options.davProperties),
convertModelAttributesToDavProperties(changed || model.changed, options.davProperties),
headers
).then(function(result) {
if (isSuccessStatus(result.status)) {
Expand Down Expand Up @@ -213,7 +213,7 @@
return;
}

callPropPatch(client, options, model, headers);
callPropPatch(client, options, model, headers, model.attributes);
});
}

Expand Down Expand Up @@ -282,24 +282,57 @@
}

/**
* DAV transport
*
*/
function davSync(method, model, options) {
var params = {type: methodMap[method] || method};
var isCollection = (model instanceof Backbone.Collection);
function getTypeForMethod(method, model) {
var type = methodMap[method];

if (!type) {
// return method directly
return method;
}

// TODO: use special attribute "resourceType" instead
var isWebdavCollection = model instanceof WebdavCollectionNode;

if (method === 'update') {
// if a model has an inner collection, it must define an
// attribute "hasInnerCollection" that evaluates to true
if (model.hasInnerCollection) {
// if the model itself is a Webdav collection, use MKCOL
params.type = 'MKCOL';
} else if (model.usePUT || (model.collection && model.collection.usePUT)) {
// use PUT instead of PROPPATCH
params.type = 'PUT';
// need to override default behavior and decide what to do
if (method === 'create') {
if (isWebdavCollection) {
if (!_.isUndefined(model.id)) {
// create new collection with known id
type = 'MKCOL';
} else {
// unsupported
throw 'Cannot create Webdav collection without id';
}
} else {
if (!_.isUndefined(model.id)) {
// need to create it first
type = 'PUT';
} else {
// creating without known id, will receive it after creation
type = 'POST';
}
}
} else if (method === 'update') {
// it exists, only update properties
type = 'PROPPATCH';
// force PUT usage ?
if (model.usePUT || (model.collection && model.collection.usePUT)) {
type = 'PUT';
}
}

return type;
}

/**
* DAV transport
*/
function davSync(method, model, options) {
var params = {type: getTypeForMethod(method, model)};
var isCollection = (model instanceof Backbone.Collection);

// Ensure that we have a URL.
if (!options.url) {
params.url = _.result(model, 'url') || urlError();
Expand All @@ -315,7 +348,7 @@
params.processData = false;
}

if (params.type === 'PROPFIND' || params.type === 'PROPPATCH') {
if (params.type === 'PROPFIND' || params.type === 'PROPPATCH' || params.type === 'MKCOL') {
var davProperties = model.davProperties;
if (!davProperties && model.model) {
// use dav properties from model in case of collection
Expand Down Expand Up @@ -356,9 +389,98 @@
return xhr;
}


/**
* Regular Webdav leaf node
*/
var WebdavNode = Backbone.Model.extend({
sync: davSync,

constructor: function() {
this.on('sync', this._onSync, this);
this._isNew = true;
Backbone.Model.prototype.constructor.apply(this, arguments);
},

_onSync: function() {
this._isNew = false;
},

isNew: function() {
// we can't rely on the id so use a dummy attribute
return !!this._isNew;
}
});

/**
* Children collection for a Webdav collection node
*/
var WebdavChildrenCollection = Backbone.Collection.extend({
sync: davSync,

collectionNode: null,
model: WebdavNode,

constructor: function() {
this.on('sync', this._onSync, this);
Backbone.Collection.prototype.constructor.apply(this, arguments);
},

initialize: function(models, options) {
options = options || {};

this.collectionNode = options.collectionNode;

return Backbone.Collection.prototype.initialize.apply(this, arguments);
},

_onSync: function(model) {
if (model instanceof Backbone.Model) {
// since we saved, mark as non-new
if (!_.isUndefined(model._isNew)) {
model._isNew = false;
}
} else {
// since we fetched, mark models as non-new
model.each(function(model) {
if (!_.isUndefined(model._isNew)) {
model._isNew = false;
}
});
}
},

url: function() {
return this.collectionNode.url();
}
});

/**
* Webdav collection which is a special node, represented by a backbone model
* and a sub-collection for its children.
*/
var WebdavCollectionNode = WebdavNode.extend({
sync: davSync,

childrenCollectionClass: WebdavChildrenCollection,

_childrenCollection: null,

getChildrenCollection: function() {
if (!this._childrenCollection) {
this._childrenCollection = new this.childrenCollectionClass([], {collectionNode: this});
}
return this._childrenCollection;
}
});

// exports
Backbone.davCall = davCall;
Backbone.davSync = davSync;

Backbone.WebdavNode = WebdavNode;
Backbone.WebdavChildrenCollection = WebdavChildrenCollection;
Backbone.WebdavCollectionNode = WebdavCollectionNode;

})(OC.Backbone);

Loading