<commit_before>/*
    ***** 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 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 General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.
    
    ***** END LICENSE BLOCK *****
*/


/*
 * Primary interface for accessing Zotero items
 */
Zotero.Items = new function() {
	Zotero.DataObjects.apply(this, ['item']);
	this.constructor.prototype = new Zotero.DataObjects();
	
	// Privileged methods
	this.get = get;
	this.exist = exist;
	this.getAll = getAll;
	this.add = add;
	this.cacheFields = cacheFields;
	this.erase = erase;
	this.getFirstCreatorSQL = getFirstCreatorSQL;
	this.getSortTitle = getSortTitle;
	
	this.__defineGetter__('primaryFields', function () {
		if (!_primaryFields.length) {
			_primaryFields = Zotero.DB.getColumns('items');
			_primaryFields.splice(_primaryFields.indexOf('clientDateModified'), 1);
			_primaryFields = _primaryFields.concat(
				['firstCreator', 'numNotes', 'numAttachments']
			);
		}
		return _primaryFields;
	});
	
	this.__defineGetter__('linkedItemPredicate', function () "owl:sameAs");
	
	// Private members
	var _cachedFields = [];
	var _firstCreatorSQL = '';
	var _primaryFields = [];
	
	
	/*
	 * Retrieves (and loads, if necessary) an arbitrary number of items
	 *
	 * Can be passed ids as individual parameters or as an array of ids, or both
	 *
	 * If only one argument and it's an id, return object directly;
	 * otherwise, return array
	 */
	function get() {
		var toLoad = [];
		var loaded = [];
		
		if (!arguments[0]) {
			Zotero.debug('No arguments provided to Items.get()');
			return false;
		}
		
		var ids = Zotero.flattenArguments(arguments);
		
		for (var i=0; i<ids.length; i++) {
			// Check if already loaded
			if (!this._objectCache[ids[i]]) {
				toLoad.push(ids[i]);
			}
		}
		
		// New items to load
		if (toLoad.length) {
			this._load(toLoad);
		}
		
		// If single id, return the object directly
		if (arguments[0] && typeof arguments[0]!='object'
				&& typeof arguments[1]=='undefined') {
			if (!this._objectCache[arguments[0]]) {
				Zotero.debug("Item " + arguments[0] + " doesn't exist", 2);
				return false;
			}
			return this._objectCache[arguments[0]];
		}
		
		// Otherwise, build return array
		for (i=0; i<ids.length; i++) {
			if (!this._objectCache[ids[i]]) {
				Zotero.debug("Item " + ids[i] + " doesn't exist", 2);
				continue;
			}
			loaded.push(this._objectCache[ids[i]]);
		}
		
		return loaded;
	}
	
	
	function exist(itemIDs) {
		var sql = "SELECT itemID FROM items WHERE itemID IN ("
			+ itemIDs.map(function () '?').join() + ")";
		var exist = Zotero.DB.columnQuery(sql, itemIDs);
		return exist ? exist : [];
	}
	
	
	
	/**
	 * Return items marked as deleted
	 *
	 * @param	{Boolean}	asIDs			Return itemIDs instead of
	 *											Zotero.Item objects
	 * @return	{Zotero.Item[]|Integer[]}
	 */
	this.getDeleted = function (asIDs, days) {
		var sql = "SELECT itemID FROM deletedItems";
		if (days) {
			sql += " WHERE dateDeleted<=DATE('NOW', '-" + parseInt(days) + " DAYS')";
		}
		var ids = Zotero.DB.columnQuery(sql);
		if (asIDs) {
			return ids;
		}
		return this.get(ids);
	}
	
	
	/*
	 * Returns all items in the database
	 *
	 * If |onlyTopLevel|, don't include child items
	 */
	function getAll(onlyTopLevel, libraryID) {
		var sql = 'SELECT A.itemID FROM items A';
		if (onlyTopLevel) {
			sql += ' LEFT JOIN itemNotes B USING (itemID) '
			+ 'LEFT JOIN itemAttachments C ON (C.itemID=A.itemID) '
			+ 'WHERE B.sourceItemID IS NULL AND C.sourceItemID IS NULL';
		}
		else {
			sql += " WHERE 1";
		}
		if (libraryID) {
			sql += " AND libraryID=?";
			var ids = Zotero.DB.columnQuery(sql, libraryID);
		}
		else {
			sql += " AND libraryID IS NULL";
			var ids = Zotero.DB.columnQuery(sql);
		}
		
		return this.get(ids);
	}
	
	
	/*
	 * Create a new item with optional metadata and pass back the primary reference
	 *<commit_msg>Don't include deleted items in "Export Library" output<commit_after>/*
    ***** 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 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 General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.
    
    ***** END LICENSE BLOCK *****
*/


/*
 * Primary interface for accessing Zotero items
 */
Zotero.Items = new function() {
	Zotero.DataObjects.apply(this, ['item']);
	this.constructor.prototype = new Zotero.DataObjects();
	
	// Privileged methods
	this.get = get;
	this.exist = exist;
	this.getAll = getAll;
	this.add = add;
	this.cacheFields = cacheFields;
	this.erase = erase;
	this.getFirstCreatorSQL = getFirstCreatorSQL;
	this.getSortTitle = getSortTitle;
	
	this.__defineGetter__('primaryFields', function () {
		if (!_primaryFields.length) {
			_primaryFields = Zotero.DB.getColumns('items');
			_primaryFields.splice(_primaryFields.indexOf('clientDateModified'), 1);
			_primaryFields = _primaryFields.concat(
				['firstCreator', 'numNotes', 'numAttachments']
			);
		}
		return _primaryFields;
	});
	
	this.__defineGetter__('linkedItemPredicate', function () "owl:sameAs");
	
	// Private members
	var _cachedFields = [];
	var _firstCreatorSQL = '';
	var _primaryFields = [];
	
	
	/*
	 * Retrieves (and loads, if necessary) an arbitrary number of items
	 *
	 * Can be passed ids as individual parameters or as an array of ids, or both
	 *
	 * If only one argument and it's an id, return object directly;
	 * otherwise, return array
	 */
	function get() {
		var toLoad = [];
		var loaded = [];
		
		if (!arguments[0]) {
			Zotero.debug('No arguments provided to Items.get()');
			return false;
		}
		
		var ids = Zotero.flattenArguments(arguments);
		
		for (var i=0; i<ids.length; i++) {
			// Check if already loaded
			if (!this._objectCache[ids[i]]) {
				toLoad.push(ids[i]);
			}
		}
		
		// New items to load
		if (toLoad.length) {
			this._load(toLoad);
		}
		
		// If single id, return the object directly
		if (arguments[0] && typeof arguments[0]!='object'
				&& typeof arguments[1]=='undefined') {
			if (!this._objectCache[arguments[0]]) {
				Zotero.debug("Item " + arguments[0] + " doesn't exist", 2);
				return false;
			}
			return this._objectCache[arguments[0]];
		}
		
		// Otherwise, build return array
		for (i=0; i<ids.length; i++) {
			if (!this._objectCache[ids[i]]) {
				Zotero.debug("Item " + ids[i] + " doesn't exist", 2);
				continue;
			}
			loaded.push(this._objectCache[ids[i]]);
		}
		
		return loaded;
	}
	
	
	function exist(itemIDs) {
		var sql = "SELECT itemID FROM items WHERE itemID IN ("
			+ itemIDs.map(function () '?').join() + ")";
		var exist = Zotero.DB.columnQuery(sql, itemIDs);
		return exist ? exist : [];
	}
	
	
	
	/**
	 * Return items marked as deleted
	 *
	 * @param	{Boolean}	asIDs			Return itemIDs instead of
	 *											Zotero.Item objects
	 * @return	{Zotero.Item[]|Integer[]}
	 */
	this.getDeleted = function (asIDs, days) {
		var sql = "SELECT itemID FROM deletedItems";
		if (days) {
			sql += " WHERE dateDeleted<=DATE('NOW', '-" + parseInt(days) + " DAYS')";
		}
		var ids = Zotero.DB.columnQuery(sql);
		if (asIDs) {
			return ids;
		}
		return this.get(ids);
	}
	
	
	/*
	 * Returns all items in the database
	 *
	 * If |onlyTopLevel|, don't include child items
	 */
	function getAll(onlyTopLevel, libraryID, includeDeleted) {
		var sql = 'SELECT A.itemID FROM items A';
		if (onlyTopLevel) {
			sql += ' LEFT JOIN itemNotes B USING (itemID) '
			+ 'LEFT JOIN itemAttachments C ON (C.itemID=A.itemID) '
			+ 'WHERE B.sourceItemID IS NULL AND C.sourceItemID IS NULL';
		}
		else {
			sql += " WHERE 1";
		}
		if (!includeDeleted) {
			sql += " AND A.itemID NOT IN (SELECT itemID FROM deletedItems)";
		}
		if (libraryID) {
			sql += " AND libraryID=?";
			var ids = Zotero.DB.columnQuery(sql, libraryID);
		}
		else {
			sql += " AND libraryID IS NULL";
			var ids = Zotero.DB.columnQuery(sql);
		}
		return this.get(ids);
	}
	
	
	/*
	 * Create a new item with optional metadata and pass back the primary reference
	 *
{'fraction_non_alphanumeric': 0.12736201558663393, 'fraction_numerical': 0.0038432795985907974, 'mean_word_length': 3.029247311827957, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2545372', 'n_tokens_mistral': 3408, 'n_tokens_neox': 2969, 'n_words': 911}