www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

group.js (7890B)


      1 /*
      2     ***** BEGIN LICENSE BLOCK *****
      3     
      4     Copyright © 2009 Center for History and New Media
      5                      George Mason University, Fairfax, Virginia, USA
      6                      http://zotero.org
      7     
      8     This file is part of Zotero.
      9     
     10     Zotero is free software: you can redistribute it and/or modify
     11     it under the terms of the GNU Affero General Public License as published by
     12     the Free Software Foundation, either version 3 of the License, or
     13     (at your option) any later version.
     14     
     15     Zotero is distributed in the hope that it will be useful,
     16     but WITHOUT ANY WARRANTY; without even the implied warranty of
     17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18     GNU Affero General Public License for more details.
     19     
     20     You should have received a copy of the GNU Affero General Public License
     21     along with Zotero.  If not, see <http://www.gnu.org/licenses/>.
     22     
     23     ***** END LICENSE BLOCK *****
     24 */
     25 
     26 "use strict";
     27 
     28 Zotero.Group = function (params = {}) {
     29 	params.libraryType = 'group';
     30 	Zotero.Group._super.call(this, params);
     31 	
     32 	Zotero.Utilities.assignProps(this, params, ['groupID', 'name', 'description',
     33 		'version']);
     34 	
     35 	// Return a proxy so that we can disable the object once it's deleted
     36 	return new Proxy(this, {
     37 		get: function(obj, prop) {
     38 			if (obj._disabled && !(prop == 'libraryID' || prop == 'id')) {
     39 				throw new Error("Group (" + obj.libraryID + ") has been disabled");
     40 			}
     41 			return obj[prop];
     42 		}
     43 	});
     44 }
     45 
     46 
     47 /**
     48  * Non-prototype properties
     49  */
     50 
     51 Zotero.defineProperty(Zotero.Group, '_dbColumns', {
     52 	value: Object.freeze(['name', 'description', 'version'])
     53 });
     54 
     55 Zotero.Group._colToProp = function(c) {
     56 	return "_group" + Zotero.Utilities.capitalize(c);
     57 }
     58 
     59 Zotero.defineProperty(Zotero.Group, '_rowSQLSelect', {
     60 	value: Zotero.Library._rowSQLSelect + ", G.groupID, "
     61 		+ Zotero.Group._dbColumns.map(c => "G." + c + " AS " + Zotero.Group._colToProp(c)).join(", ")
     62 });
     63 
     64 Zotero.defineProperty(Zotero.Group, '_rowSQL', {
     65 	value: "SELECT " + Zotero.Group._rowSQLSelect
     66 		+ " FROM groups G JOIN libraries L USING (libraryID)"
     67 });
     68 
     69 Zotero.extendClass(Zotero.Library, Zotero.Group);
     70 
     71 Zotero.defineProperty(Zotero.Group.prototype, '_objectType', {
     72 	value: 'group'
     73 });
     74 
     75 Zotero.defineProperty(Zotero.Group.prototype, 'libraryTypes', {
     76 	value: Object.freeze(Zotero.Group._super.prototype.libraryTypes.concat(['group']))
     77 });
     78 
     79 Zotero.defineProperty(Zotero.Group.prototype, 'groupID', {
     80 	get: function() { return this._groupID; },
     81 	set: function(v) { return this._groupID = v; }
     82 });
     83 
     84 Zotero.defineProperty(Zotero.Group.prototype, 'id', {
     85 	get: function() { return this.groupID; },
     86 	set: function(v) { return this.groupID = v; }
     87 });
     88 
     89 Zotero.defineProperty(Zotero.Group.prototype, 'allowsLinkedFiles', {
     90 	value: false
     91 });
     92 
     93 // Create accessors
     94 (function() {
     95 let accessors = ['name', 'description', 'version'];
     96 for (let i=0; i<accessors.length; i++) {
     97 	let name = accessors[i];
     98 	let prop = Zotero.Group._colToProp(name);
     99 	Zotero.defineProperty(Zotero.Group.prototype, name, {
    100 		get: function() { return this._get(prop); },
    101 		set: function(v) { return this._set(prop, v); }
    102 	})
    103 }
    104 })();
    105 
    106 Zotero.Group.prototype._isValidGroupProp = function(prop) {
    107 	let preffix = '_group';
    108 	if (prop.indexOf(preffix) !== 0 || prop.length == preffix.length) {
    109 		return false;
    110 	}
    111 	
    112 	let col = prop.substr(preffix.length);
    113 	col =  col.charAt(0).toLowerCase() + col.substr(1);
    114 	
    115 	return Zotero.Group._dbColumns.indexOf(col) != -1;
    116 }
    117 
    118 Zotero.Group.prototype._isValidProp = function(prop) {
    119 	return this._isValidGroupProp(prop)
    120 		|| Zotero.Group._super.prototype._isValidProp.call(this, prop);
    121 }
    122 
    123 /*
    124  * Populate group data from a database row
    125  */
    126 Zotero.Group.prototype._loadDataFromRow = function(row) {
    127 	Zotero.Group._super.prototype._loadDataFromRow.call(this, row);
    128 	
    129 	this._groupID = row.groupID;
    130 	this._groupName = row._groupName;
    131 	this._groupDescription = row._groupDescription;
    132 	this._groupVersion = row._groupVersion;
    133 }
    134 
    135 Zotero.Group.prototype._set = function(prop, val) {
    136 	switch(prop) {
    137 		case '_groupVersion':
    138 			let newVal = Number.parseInt(val, 10);
    139 			if (newVal != val) {
    140 				throw new Error(prop + ' must be an integer');
    141 			}
    142 			val = newVal
    143 			
    144 			if (val < 0) {
    145 				throw new Error(prop + ' must be non-negative');
    146 			}
    147 			
    148 			// Ensure that it is never decreasing
    149 			if (val < this._groupVersion) {
    150 				throw new Error(prop + ' cannot decrease');
    151 			}
    152 			
    153 			break;
    154 		case '_groupName':
    155 		case '_groupDescription':
    156 			if (typeof val != 'string') {
    157 				throw new Error(prop + ' must be a string');
    158 			}
    159 			break;
    160 	}
    161 	
    162 	return Zotero.Group._super.prototype._set.call(this, prop, val);
    163 }
    164 
    165 Zotero.Group.prototype._reloadFromDB = Zotero.Promise.coroutine(function* () {
    166 	let sql = Zotero.Group._rowSQL + " WHERE G.groupID=?";
    167 	let row = yield Zotero.DB.rowQueryAsync(sql, [this.groupID]);
    168 	this._loadDataFromRow(row);
    169 });
    170 
    171 Zotero.Group.prototype._initSave = Zotero.Promise.coroutine(function* (env) {
    172 	let proceed = yield Zotero.Group._super.prototype._initSave.call(this, env);
    173 	if (!proceed) return false;
    174 	
    175 	if (!this._groupName) throw new Error("Group name not set");
    176 	if (typeof this._groupDescription != 'string') throw new Error("Group description not set");
    177 	if (!(this._groupVersion >= 0)) throw new Error("Group version not set");
    178 	if (!this._groupID) throw new Error("Group ID not set");
    179 	
    180 	return true;
    181 });
    182 
    183 Zotero.Group.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
    184 	yield Zotero.Group._super.prototype._saveData.call(this, env);
    185 	
    186 	let changedCols = [], params = [];
    187 	for (let i=0; i<Zotero.Group._dbColumns.length; i++) {
    188 		let col = Zotero.Group._dbColumns[i];
    189 		let prop = Zotero.Group._colToProp(col);
    190 		
    191 		if (!this._changed[prop]) continue;
    192 		
    193 		changedCols.push(col);
    194 		params.push(this[prop]);
    195 	}
    196 	
    197 	if (env.isNew) {
    198 		changedCols.push('groupID', 'libraryID');
    199 		params.push(this.groupID, this.libraryID);
    200 		
    201 		let sql = "INSERT INTO groups (" + changedCols.join(', ') + ") "
    202 			+ "VALUES (" + Array(params.length).fill('?').join(', ') + ")";
    203 		yield Zotero.DB.queryAsync(sql, params);
    204 		
    205 		Zotero.Notifier.queue('add', 'group', this.groupID, env.notifierData);
    206 	}
    207 	else if (changedCols.length) {
    208 		let sql = "UPDATE groups SET " + changedCols.map(v => v + '=?').join(', ')
    209 			+ " WHERE groupID=?";
    210 		params.push(this.groupID);
    211 		yield Zotero.DB.queryAsync(sql, params);
    212 		
    213 		if (!env.options.skipNotifier) {
    214 			Zotero.Notifier.queue('modify', 'group', this.groupID, env.notifierData);
    215 		}
    216 	}
    217 	else {
    218 		Zotero.debug("Group data did not change for group " + this.groupID, 5);
    219 	}
    220 });
    221 
    222 Zotero.Group.prototype._finalizeSave = Zotero.Promise.coroutine(function* (env) {
    223 	yield Zotero.Group._super.prototype._finalizeSave.call(this, env);
    224 	
    225 	if (env.isNew) {
    226 		Zotero.Groups.register(this);
    227 	}
    228 });
    229 
    230 Zotero.Group.prototype._finalizeErase = Zotero.Promise.coroutine(function* (env) {
    231 	let notifierData = {};
    232 	notifierData[this.groupID] = {
    233 		libraryID: this.libraryID
    234 	};
    235 	Zotero.Notifier.queue('delete', 'group', this.groupID, notifierData);
    236 	
    237 	Zotero.Groups.unregister(this.groupID);
    238 	
    239 	yield Zotero.Group._super.prototype._finalizeErase.call(this, env);
    240 });
    241 
    242 Zotero.Group.prototype.fromJSON = function (json, userID) {
    243 	if (json.name !== undefined) this.name = json.name;
    244 	if (json.description !== undefined) this.description = json.description;
    245 	
    246 	var editable = false;
    247 	var filesEditable = false;
    248 	if (userID) {
    249 		({ editable, filesEditable } = Zotero.Groups.getPermissionsFromJSON(json, userID));
    250 	}
    251 	this.editable = editable;
    252 	this.filesEditable = filesEditable;
    253 }
    254 
    255 Zotero.Group.prototype._prepFieldChange = function (field) {
    256 	if (!this._changed) {
    257 		this._changed = {};
    258 	}
    259 	this._changed[field] = true;
    260 	
    261 	// Save a copy of the data before changing
    262 	// TODO: only save previous data if group exists
    263 	if (this.id && this.exists() && !this._previousData) {
    264 		//this._previousData = this.serialize();
    265 	}
    266 }