Skip to content

Commit

Permalink
Add Webdav specific models and collections
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Petry committed Mar 1, 2017
1 parent 7efbb5e commit f17e391
Show file tree
Hide file tree
Showing 2 changed files with 496 additions and 19 deletions.
160 changes: 141 additions & 19 deletions core/js/oc-backbone-webdav.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit f17e391

Please sign in to comment.