diff --git a/chrome/content/zotero/bindings/zoterosearch.xml b/chrome/content/zotero/bindings/zoterosearch.xml index a2244b8f5..4b34ca102 100644 --- a/chrome/content/zotero/bindings/zoterosearch.xml +++ b/chrome/content/zotero/bindings/zoterosearch.xml @@ -440,7 +440,7 @@ var rows = []; var libraryID = this.parent.search.libraryID; - var cols = Zotero.getCollections(false, true, libraryID); + var cols = Zotero.getCollections(false, true, libraryID); // TODO: Replace with Zotero.Collections.getByLibrary() for (var i in cols) { // Indent subcollections var indent = ''; diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js index b493d3b39..fd06984f2 100644 --- a/chrome/content/zotero/fileInterface.js +++ b/chrome/content/zotero/fileInterface.js @@ -285,7 +285,7 @@ var Zotero_File_Interface = new function() { var leafName = translation.location.leafName; var collectionName = (translation.location.isDirectory() || leafName.indexOf(".") === -1 ? leafName : leafName.substr(0, leafName.lastIndexOf("."))); - var allCollections = Zotero.getCollections(); + var allCollections = Zotero.getCollections(); // TODO: Replace with Zotero.Collections.getBy* for(var i=0; i} - A promise for an array of objects with 'id', 'key', + * 'type' ('item' or 'collection'), 'parent', and, if collection, 'name' and the nesting 'level' */ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (recursive, nested, type, includeDeletedItems, level) { if (!this.id) { - throw ('Zotero.Collection.getChildren() cannot be called on an unsaved item'); + throw new Error('Cannot be called on an unsaved item'); } var toReturn = []; diff --git a/chrome/content/zotero/xpcom/data/collections.js b/chrome/content/zotero/xpcom/data/collections.js index 30bcc43db..8f7776bd9 100644 --- a/chrome/content/zotero/xpcom/data/collections.js +++ b/chrome/content/zotero/xpcom/data/collections.js @@ -53,43 +53,47 @@ Zotero.Collections = function() { this._primaryDataSQLFrom = "FROM collections O " + "LEFT JOIN collections CP ON (O.parentCollectionID=CP.collectionID)"; + /** - * Add new collection to DB and return Collection object - * - * _name_ is non-empty string - * _parent_ is optional collectionID -- creates root collection by default - * - * Returns true on success; false on error - **/ - this.add = function (name, parent) { - var col = new Zotero.Collection; - col.name = name; - col.parent = parent; - var id = col.save(); - return this.getAsync(id); + * Get collections within a library + * + * Either libraryID or parentID must be provided + * + * @param {Integer} libraryID + * @param {Boolean} [recursive=false] + * @return {Promise} + */ + this.getByLibrary = function (libraryID, recursive) { + return _getByContainer(libraryID, null, recursive); } - /* - * Zotero.getCollections(parent) + /** + * Get collections that are subcollection of a given collection * - * Returns an array of all collections are children of a collection - * as Zotero.Collection instances - * - * Takes parent collectionID as optional parameter; - * by default, returns root collections + * @param {Integer} parentCollectionID + * @param {Boolean} [recursive=false] + * @return {Promise} */ - this.getByParent = Zotero.Promise.coroutine(function* (libraryID, parentID, recursive) { + this.getByParent = function (parentCollectionID, recursive) { + return _getByContainer(null, parentCollectionID, recursive); + } + + + var _getByContainer = Zotero.Promise.coroutine(function* (libraryID, parentID, recursive) { let children; if (parentID) { - let parent = yield this.getAsync(parentID); + let parent = yield Zotero.Collections.getAsync(parentID); yield parent.loadChildCollections(); children = parent.getChildCollections(); } else if (libraryID) { - children = yield this.getCollectionsInLibrary(libraryID); + let sql = "SELECT collectionID AS id FROM collections " + + "WHERE libraryID=? AND parentCollectionID IS NULL"; + let ids = yield Zotero.DB.columnQueryAsync(sql, [libraryID]); + children = yield this.getAsync(ids); } else { - throw new Error("Either library ID or parent collection ID must be provided to getNumCollectionsByParent"); + throw new Error("Either library ID or parent collection ID must be provided"); } if (!children.length) { @@ -106,7 +110,7 @@ Zotero.Collections = function() { var obj = children[i]; toReturn.push(obj); - var desc = obj.getDescendents(false, 'collection'); + var desc = yield obj.getDescendents(false, 'collection'); for (var j in desc) { var obj2 = yield this.getAsync(desc[j]['id']); if (!obj2) { @@ -126,18 +130,7 @@ Zotero.Collections = function() { } return toReturn; - }); - - - this.getCollectionsInLibrary = Zotero.Promise.coroutine(function* (libraryID) { - let sql = "SELECT collectionID AS id FROM collections C " - + "WHERE libraryID=? AND parentCollectionId IS NULL"; - let ids = yield Zotero.DB.queryAsync(sql, [libraryID]); - let collections = yield this.getAsync(ids.map(function(row) row.id)); - if (!collections.length) return collections; - - return collections.sort(function (a, b) Zotero.localeCompare(a.name, b.name)); - }); + }.bind(this)); this.getCollectionsContainingItems = function (itemIDs, asIDs) { diff --git a/chrome/content/zotero/xpcom/data/group.js b/chrome/content/zotero/xpcom/data/group.js index a0cfaf9c5..166cfdc9d 100644 --- a/chrome/content/zotero/xpcom/data/group.js +++ b/chrome/content/zotero/xpcom/data/group.js @@ -182,34 +182,6 @@ Zotero.Group.prototype.clearSearchCache = function () { this._hasSearches = null; } -/** - * Returns collections of this group - * - * @param {Boolean} asIDs Return as collectionIDs - * @return {Zotero.Collection[]} Array of Zotero.Collection instances - */ -Zotero.Group.prototype.getCollections = Zotero.Promise.coroutine(function* (parent) { - var sql = "SELECT collectionID FROM collections WHERE libraryID=? AND " - + "parentCollectionID " + (parent ? '=' + parent : 'IS NULL'); - var ids = yield Zotero.DB.columnQueryAsync(sql, this.libraryID); - - // Return Zotero.Collection objects - var objs = []; - for each(var id in ids) { - var col = yield Zotero.Collections.getAsync(id); - objs.push(col); - } - - // Do proper collation sort - var collation = Zotero.getLocaleCollation(); - objs.sort(function (a, b) { - return collation.compareString(1, a.name, b.name); - }); - - return objs; -}); - - Zotero.Group.prototype.hasItem = function (item) { if (!(item instanceof Zotero.Item)) { throw new Error("item must be a Zotero.Item"); diff --git a/chrome/content/zotero/xpcom/data_access.js b/chrome/content/zotero/xpcom/data_access.js deleted file mode 100644 index 81da997b8..000000000 --- a/chrome/content/zotero/xpcom/data_access.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - - Copyright © 2009 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - http://zotero.org - - This file is part of Zotero. - - Zotero is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Zotero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Zotero. If not, see . - - ***** END LICENSE BLOCK ***** -*/ - - -/* - * Zotero.getCollections(parent) - * - * Returns an array of all collections are children of a collection - * as Zotero.Collection instances - * - * Takes parent collectionID as optional parameter; - * by default, returns root collections - */ -Zotero.getCollections = function(parent, recursive, libraryID) { - var toReturn = new Array(); - - if (!parent) { - parent = null; - } - - var sql = "SELECT collectionID AS id, collectionName AS name FROM collections C " - + "WHERE libraryID=? AND parentCollectionID " + (parent ? '=' + parent : 'IS NULL'); - var children = Zotero.DB.query(sql, [libraryID ? libraryID : Zotero.Libraries.userLibraryID]); - - if (!children) { - Zotero.debug('No child collections of collection ' + parent, 5); - return toReturn; - } - - // Do proper collation sort - var collation = Zotero.getLocaleCollation(); - children.sort(function (a, b) { - return collation.compareString(1, a.name, b.name); - }); - - for (var i=0, len=children.length; i col.id), [col1.id, col2.id]); + assert.ok(cols.every(col => + col.libraryID == Zotero.Libraries.userLibraryID && !col.parentID + )); + }) + + it("should get all collections in a library in recursive mode", function* () { + var col1 = yield createDataObject('collection'); + var col2 = yield createDataObject('collection'); + var col3 = yield createDataObject('collection', { parentID: col2.id }); + var cols = yield Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID, true); + assert.isAbove(cols.length, 2); + assert.includeMembers(cols.map(col => col.id), [col1.id, col2.id, col3.id]); + assert.ok(cols.every(col => col.libraryID == Zotero.Libraries.userLibraryID)); + }) + }) + + describe("#getByParent()", function () { + it("should get all direct subcollections of a library", function* () { + var col1 = yield createDataObject('collection'); + var col2 = yield createDataObject('collection'); + var col3 = yield createDataObject('collection', { parentID: col2.id }); + assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0); + var cols = yield Zotero.Collections.getByParent(col2.id); + assert.lengthOf(cols, 1); + assert.sameMembers(cols.map(col => col.id), [col3.id]); + }) + + it("should get all collections underneath a collection in recursive mode", function* () { + var col1 = yield createDataObject('collection'); + var col2 = yield createDataObject('collection'); + var col3 = yield createDataObject('collection', { parentID: col2.id }); + var col4 = yield createDataObject('collection', { parentID: col3.id }); + assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0); + var cols = yield Zotero.Collections.getByParent(col2.id, true); + assert.lengthOf(cols, 2); + assert.includeMembers(cols.map(col => col.id), [col3.id, col4.id]); + }) + }) +})