public function save() { if (!$this->libraryID) { trigger_error("Library ID must be set before saving", E_USER_ERROR); } Zotero_Collections::editCheck($this); if (!$this->changed) { Z_Core::debug("Collection {$this->id} has not changed"); return false; } Zotero_DB::beginTransaction(); try { $collectionID = $this->id ? $this->id : Zotero_ID::get('collections'); Z_Core::debug("Saving collection {$this->id}"); $key = $this->key ? $this->key : $this->generateKey(); $timestamp = Zotero_DB::getTransactionTimestamp(); $dateAdded = $this->dateAdded ? $this->dateAdded : $timestamp; $dateModified = $this->dateModified ? $this->dateModified : $timestamp; // Verify parent if ($this->_parent) { if (is_int($this->_parent)) { $newParentCollection = Zotero_Collections::get($this->libraryID, $this->_parent); } else { $newParentCollection = Zotero_Collections::getByLibraryAndKey($this->libraryID, $this->_parent); } if (!$newParentCollection) { // TODO: clear caches throw new Exception("Cannot set parent to invalid collection {$this->_parent}"); } if ($newParentCollection->id == $this->id) { trigger_error("Cannot move collection {$this->id} into itself!", E_USER_ERROR); } // If the designated parent collection is already within this // collection (which shouldn't happen), move it to the root if ($this->id && $this->hasDescendent('collection', $newParentCollection->id)) { $newParentCollection->parent = null; $newParentCollection->save(); } $parent = $newParentCollection->id; } else { $parent = null; } $fields = "collectionName=?, parentCollectionID=?, libraryID=?, `key`=?,\n\t\t\t\t\t\tdateAdded=?, dateModified=?, serverDateModified=?"; $params = array($this->name, $parent, $this->libraryID, $key, $dateAdded, $dateModified, $timestamp); $params = array_merge(array($collectionID), $params, $params); $shardID = Zotero_Shards::getByLibraryID($this->libraryID); $sql = "INSERT INTO collections SET collectionID=?, {$fields}\n\t\t\t\t\tON DUPLICATE KEY UPDATE {$fields}"; $insertID = Zotero_DB::query($sql, $params, $shardID); if (!$this->id) { if (!$insertID) { throw new Exception("Collection id not available after INSERT"); } $collectionID = $insertID; Zotero_Collections::cacheLibraryKeyID($this->libraryID, $key, $insertID); } // Remove from delete log if it's there $sql = "DELETE FROM syncDeleteLogKeys WHERE libraryID=? AND objectType='collection' AND `key`=?"; Zotero_DB::query($sql, array($this->libraryID, $key), $shardID); Zotero_DB::commit(); Zotero_Collections::cachePrimaryData(array('id' => $collectionID, 'libraryID' => $this->libraryID, 'key' => $key, 'name' => $this->name, 'dateAdded' => $dateAdded, 'dateModified' => $dateModified, 'parent' => $parent)); } catch (Exception $e) { Zotero_DB::rollback(); throw $e; } // If successful, set values in object if (!$this->id) { $this->_id = $collectionID; } if (!$this->key) { $this->_key = $key; } return $this->id; }