public function testExistsByLibraryAndKey() { $this->assertFalse(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], "AAAAAAAA")); $item = new Zotero_Item(); $item->libraryID = self::$config['userLibraryID']; $item->itemTypeID = Zotero_ItemTypes::getID("book"); $item->save(); $key = $item->key; $this->assertTrue(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], $key)); Zotero_Items::delete(self::$config['userLibraryID'], $key); $this->assertFalse(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], $key)); }
/** * Import an item by URL using the translation server * * Initial request: * * { * "url": "http://..." * } * * Item selection for multi-item results: * * { * "url": "http://...", * "token": "<token>" * "items": { * "0": "Item 1 Title", * "3": "Item 2 Title" * } * } * * Returns an array of keys of added items (like updateMultipleFromJSON) or an object * with a 'select' property containing an array of titles for multi-item results */ public static function addFromURL($json, $requestParams, $libraryID, $userID, Zotero_Permissions $permissions, $translationToken) { if (!$translationToken) { throw new Exception("Translation token not provided"); } self::validateJSONURL($json, $requestParams); $cacheKey = 'addFromURLKeyMappings_' . md5($json->url . $translationToken); // Replace numeric keys with URLs for selected items if (isset($json->items) && $requestParams['v'] >= 2) { $keyMappings = Z_Core::$MC->get($cacheKey); $newItems = []; foreach ($json->items as $number => $title) { if (!isset($keyMappings[$number])) { throw new Exception("Index '{$number}' not found for URL and token", Z_ERROR_INVALID_INPUT); } $url = $keyMappings[$number]; $newItems[$url] = $title; } $json->items = $newItems; } $response = Zotero_Translate::doWeb($json->url, $translationToken, isset($json->items) ? $json->items : null); if (!$response || is_int($response)) { return $response; } if (isset($response->items)) { if ($requestParams['v'] >= 2) { $response = $response->items; for ($i = 0, $len = sizeOf($response); $i < $len; $i++) { // Assign key here so that we can add notes if necessary do { $itemKey = Zotero_ID::getKey(); } while (Zotero_Items::existsByLibraryAndKey($libraryID, $itemKey)); $response[$i]->key = $itemKey; // Pull out notes and stick in separate items if (isset($response[$i]->notes)) { foreach ($response[$i]->notes as $note) { $newNote = (object) ["itemType" => "note", "note" => $note->note, "parentItem" => $itemKey]; $response[] = $newNote; } unset($response[$i]->notes); } // TODO: link attachments, or not possible from translation-server? } } try { self::validateMultiObjectJSON($response, $requestParams); } catch (Exception $e) { error_log($e); error_log(json_encode($response)); throw new Exception("Invalid JSON from doWeb()"); } } else { if (isset($response->select)) { // Replace URLs with numeric keys for found items if ($requestParams['v'] >= 2) { $keyMappings = []; $newItems = new stdClass(); $number = 0; foreach ($response->select as $url => $title) { $keyMappings[$number] = $url; $newItems->{$number} = $title; $number++; } Z_Core::$MC->set($cacheKey, $keyMappings, 600); $response->select = $newItems; } return $response; } else { throw new Exception("Invalid return value from doWeb()"); } } return self::updateMultipleFromJSON($response, $requestParams, $libraryID, $userID, $permissions, false, null); }
private function loadPrimaryData($allowFail = false) { Z_Core::debug("Loading primary data for item {$this->libraryID}/{$this->key}"); if ($this->loaded['primaryData']) { throw new Exception("Primary data already loaded for item {$this->libraryID}/{$this->key}"); } $libraryID = $this->libraryID; $id = $this->id; $key = $this->key; if (!$libraryID) { throw new Exception("Library ID not set"); } if (!$id && !$key) { throw new Exception("ID or key not set"); } // Use cached check for existence if possible if ($libraryID && $key) { if (!Zotero_Items::existsByLibraryAndKey($libraryID, $key)) { $this->loaded['primaryData'] = true; if ($allowFail) { return false; } throw new Exception("Item " . ($id ? $id : "{$libraryID}/{$key}") . " not found"); } } $columns = array(); foreach (Zotero_Items::$primaryFields as $field) { $colSQL = ''; if (is_null($field == 'itemID' ? $this->id : $this->{$field})) { switch ($field) { case 'itemID': case 'itemTypeID': case 'dateAdded': case 'dateModified': case 'libraryID': case 'key': case 'serverDateModified': $colSQL = 'I.' . $field; break; case 'itemVersion': $colSQL = 'I.version AS itemVersion'; break; case 'numNotes': $colSQL = '(SELECT COUNT(*) FROM itemNotes INo WHERE sourceItemID=I.itemID AND INo.itemID NOT IN (SELECT itemID FROM deletedItems)) AS numNotes'; break; case 'numAttachments': $colSQL = '(SELECT COUNT(*) FROM itemAttachments IA WHERE sourceItemID=I.itemID AND IA.itemID NOT IN (SELECT itemID FROM deletedItems)) AS numAttachments'; break; case 'numNotes': $colSQL = '(SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=I.itemID) AS numNotes'; break; case 'numAttachments': $colSQL = '(SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID=I.itemID) AS numAttachments'; break; } if ($colSQL) { $columns[] = $colSQL; } } } if (!$columns) { Z_Core::debug("No primary columns to load"); return; } $sql = 'SELECT ' . implode(', ', $columns) . " FROM items I WHERE "; if ($id) { if (!is_numeric($id)) { trigger_error("Invalid itemID '{$id}'", E_USER_ERROR); } $sql .= "itemID=?"; $stmt = Zotero_DB::getStatement($sql, 'loadPrimaryData_id', Zotero_Shards::getByLibraryID($libraryID)); $row = Zotero_DB::rowQueryFromStatement($stmt, array($id)); } else { if (!is_numeric($libraryID)) { trigger_error("Invalid libraryID '{$libraryID}'", E_USER_ERROR); } if (!preg_match('/[A-Z0-9]{8}/', $key)) { trigger_error("Invalid key '{$key}'!", E_USER_ERROR); } $sql .= "libraryID=? AND `key`=?"; $stmt = Zotero_DB::getStatement($sql, 'loadPrimaryData_key', Zotero_Shards::getByLibraryID($libraryID)); $row = Zotero_DB::rowQueryFromStatement($stmt, array($libraryID, $key)); } $this->loaded['primaryData'] = true; if (!$row) { if ($allowFail) { return false; } throw new Exception("Item " . ($id ? $id : "{$libraryID}/{$key}") . " not found"); } $this->loadFromRow($row); return true; }
public function setLinkedItems($newKeys) { if (!$this->linkedItemsLoaded) { $this->loadLinkedItems(); } if (!is_array($newKeys)) { throw new Exception('$newKeys must be an array'); } $oldKeys = $this->getLinkedItems(true); if (!$newKeys && !$oldKeys) { Z_Core::debug("No linked items added", 4); return false; } $addKeys = array_diff($newKeys, $oldKeys); $removeKeys = array_diff($oldKeys, $newKeys); // Make sure all new keys exist foreach ($addKeys as $key) { if (!Zotero_Items::existsByLibraryAndKey($this->libraryID, $key)) { // Return a specific error for a wrong-library tag issue // that I can't reproduce throw new Exception("Linked item {$key} of tag " . "{$this->libraryID}/{$this->key} not found", Z_ERROR_TAG_LINKED_ITEM_NOT_FOUND); } } if ($addKeys || $removeKeys) { $this->prepFieldChange('linkedItems'); } else { Z_Core::debug('Linked items not changed', 4); return false; } $this->linkedItems = $newKeys; return true; }