public function items() { if (($this->method == 'POST' || $this->method == 'PUT') && !$this->body) { $this->e400("{$this->method} data not provided"); } $itemIDs = array(); $responseItems = array(); $responseKeys = array(); $totalResults = null; // // Single item // if (($this->objectID || $this->objectKey) && !$this->subset) { if ($this->fileMode) { if ($this->fileView) { $this->allowMethods(array('GET', 'HEAD', 'POST')); } else { $this->allowMethods(array('GET', 'PUT', 'POST', 'HEAD', 'PATCH')); } } else { $this->allowMethods(array('GET', 'PUT', 'DELETE')); } // Check for general library access if (!$this->permissions->canAccess($this->objectLibraryID)) { //var_dump($this->objectLibraryID); //var_dump($this->permissions); $this->e403(); } if ($this->objectKey) { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); } else { try { $item = Zotero_Items::get($this->objectLibraryID, $this->objectID); } catch (Exception $e) { if ($e->getCode() == Z_ERROR_OBJECT_LIBRARY_MISMATCH) { $item = false; } else { throw $e; } } } if (!$item) { // Possibly temporary workaround to block unnecessary full syncs if ($this->fileMode && $this->method == 'POST') { // If > 2 requests for missing file, trigger a full sync via 404 $cacheKey = "apiMissingFile_" . $this->objectLibraryID . "_" . ($this->objectKey ? $this->objectKey : $this->objectID); $set = Z_Core::$MC->get($cacheKey); if (!$set) { Z_Core::$MC->set($cacheKey, 1, 86400); } else { if ($set < 2) { Z_Core::$MC->increment($cacheKey); } else { Z_Core::$MC->delete($cacheKey); $this->e404("A file sync error occurred. Please sync again."); } } $this->e500("A file sync error occurred. Please sync again."); } // If we have an id, make sure this isn't really an all-numeric key if ($this->objectID && strlen($this->objectID) == 8 && preg_match('/[0-9]{8}/', $this->objectID)) { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectID); if ($item) { $this->objectKey = $this->objectID; unset($this->objectID); } } if (!$item) { $this->e404("Item does not exist"); } } if ($item->isNote() && !$this->permissions->canAccess($this->objectLibraryID, 'notes')) { $this->e403(); } // Make sure URL libraryID matches item libraryID if ($this->objectLibraryID != $item->libraryID) { $this->e404("Item does not exist"); } // File access mode if ($this->fileMode) { $this->_handleFileRequest($item); } // If id, redirect to key URL if ($this->objectID) { $this->allowMethods(array('GET')); $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; header("Location: " . Zotero_API::getItemURI($item) . $qs); exit; } if ($this->scopeObject) { switch ($this->scopeObject) { // Remove item from collection case 'collections': $this->allowMethods(array('DELETE')); if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); if (!$collection) { $this->e404("Collection not found"); } if (!$collection->hasItem($item->id)) { $this->e404("Item not found in collection"); } Zotero_DB::beginTransaction(); $timestamp = Zotero_Libraries::updateTimestamps($this->objectLibraryID); Zotero_DB::registerTransactionTimestamp($timestamp); $collection->removeItem($item->id); Zotero_DB::commit(); $this->e204(); default: $this->e400(); } } if ($this->method == 'PUT' || $this->method == 'DELETE') { if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } if (!Z_CONFIG::$TESTING_SITE || empty($_GET['skipetag'])) { if (empty($_SERVER['HTTP_IF_MATCH'])) { $this->e400("If-Match header not provided"); } if (!preg_match('/^"?([a-f0-9]{32})"?$/', $_SERVER['HTTP_IF_MATCH'], $matches)) { $this->e400("Invalid ETag in If-Match header"); } if ($item->etag != $matches[1]) { $this->e412("ETag does not match current version of item"); } } // Update existing item if ($this->method == 'PUT') { $obj = $this->jsonDecode($this->body); Zotero_Items::updateFromJSON($item, $obj, false, null, $this->userID); $this->queryParams['format'] = 'atom'; $this->queryParams['content'] = array('json'); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } } else { Zotero_Items::delete($this->objectLibraryID, $this->objectKey, true); try { Zotero_Processors::notifyProcessors('index'); } catch (Exception $e) { Z_Core::logError($e); } $this->e204(); } } // Display item switch ($this->queryParams['format']) { case 'atom': $this->responseXML = Zotero_Items::convertItemToAtom($item, $this->queryParams, $this->apiVersion, $this->permissions); break; case 'bib': echo Zotero_Cite::getBibliographyFromCitationServer(array($item), $this->queryParams['style'], $this->queryParams['css']); exit; case 'csljson': $json = Zotero_Cite::getJSONFromItems(array($item), true); if ($this->queryParams['pprint']) { header("Content-Type: text/plain"); $json = Zotero_Utilities::json_encode_pretty($json); } else { header("Content-Type: application/vnd.citationstyles.csl+json"); $json = json_encode($json); } echo $json; exit; default: $export = Zotero_Translate::doExport(array($item), $this->queryParams['format']); if ($this->queryParams['pprint']) { header("Content-Type: text/plain"); } else { header("Content-Type: " . $export['mimeType']); } echo $export['body']; exit; } } else { $this->allowMethods(array('GET', 'POST')); if (!$this->permissions->canAccess($this->objectLibraryID)) { $this->e403(); } $includeTrashed = false; $formatAsKeys = $this->queryParams['format'] == 'keys'; if ($this->scopeObject) { $this->allowMethods(array('GET', 'POST')); // If id, redirect to key URL if ($this->scopeObjectID) { $this->allowMethods(array('GET')); if (!in_array($this->scopeObject, array("collections", "tags"))) { $this->e400(); } $className = 'Zotero_' . ucwords($this->scopeObject); $obj = call_user_func(array($className, 'get'), $this->objectLibraryID, $this->scopeObjectID); if (!$obj) { $this->e404("Scope " . substr($this->scopeObject, 0, -1) . " not found"); } $base = call_user_func(array('Zotero_API', 'get' . substr(ucwords($this->scopeObject), 0, -1) . 'URI'), $obj); $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; header("Location: " . $base . "/items" . $qs); exit; } switch ($this->scopeObject) { case 'collections': $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); if (!$collection) { $this->e404("Collection not found"); } // Add items to collection if ($this->method == 'POST') { if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } Zotero_DB::beginTransaction(); $timestamp = Zotero_Libraries::updateTimestamps($this->objectLibraryID); Zotero_DB::registerTransactionTimestamp($timestamp); $itemKeys = explode(' ', $this->body); $itemIDs = array(); foreach ($itemKeys as $key) { try { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $key); } catch (Exception $e) { if ($e->getCode() == Z_ERROR_OBJECT_LIBRARY_MISMATCH) { $item = false; } else { throw $e; } } if (!$item) { throw new Exception("Item '{$key}' not found in library", Z_ERROR_INVALID_INPUT); } if ($item->getSource()) { throw new Exception("Child items cannot be added to collections directly", Z_ERROR_INVALID_INPUT); } $itemIDs[] = $item->id; } $collection->addItems($itemIDs); Zotero_DB::commit(); $this->e204(); } $title = "Items in Collection ‘" . $collection->name . "’"; $itemIDs = $collection->getChildItems(); break; case 'tags': $this->allowMethods(array('GET')); $tagIDs = Zotero_Tags::getIDs($this->objectLibraryID, $this->scopeObjectName); if (!$tagIDs) { $this->e404("Tag not found"); } $itemIDs = array(); $title = ''; foreach ($tagIDs as $tagID) { $tag = new Zotero_Tag(); $tag->libraryID = $this->objectLibraryID; $tag->id = $tagID; // Use a real tag name, in case case differs if (!$title) { $title = "Items of Tag ‘" . $tag->name . "’"; } $itemIDs = array_merge($itemIDs, $tag->getLinkedItems(true)); } $itemIDs = array_unique($itemIDs); break; default: throw new Exception("Invalid items scope object '{$this->scopeObject}'"); } } else { // Top-level items if ($this->subset == 'top') { $this->allowMethods(array('GET')); $title = "Top-Level Items"; $results = Zotero_Items::search($this->objectLibraryID, true, $this->queryParams, false, $formatAsKeys); } else { if ($this->subset == 'trash') { $this->allowMethods(array('GET')); $title = "Deleted Items"; $itemIDs = Zotero_Items::getDeleted($this->objectLibraryID, true); $includeTrashed = true; } else { if ($this->subset == 'children') { // If we have an id, make sure this isn't really an all-numeric key if ($this->objectID && strlen($this->objectID) == 8 && preg_match('/[0-9]{8}/', $this->objectID)) { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectID); if ($item) { $this->objectKey = $this->objectID; unset($this->objectID); } } // If id, redirect to key URL if ($this->objectID) { $this->allowMethods(array('GET')); $item = Zotero_Items::get($this->objectLibraryID, $this->objectID); if (!$item) { $this->e404("Item not found"); } $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; header("Location: " . Zotero_API::getItemURI($item) . '/children' . $qs); exit; } $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); if (!$item) { $this->e404("Item not found"); } // Create new child items if ($this->method == 'POST') { if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } $obj = $this->jsonDecode($this->body); $keys = Zotero_Items::addFromJSON($obj, $this->objectLibraryID, $item, $this->userID); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } $uri = Zotero_API::getItemURI($item) . "/children"; $queryString = "itemKey=" . urlencode(implode(",", $keys)) . "&content=json"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->responseCode = 201; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, false); } // Display items $title = "Child Items of ‘" . $item->getDisplayTitle() . "’"; $notes = $item->getNotes(); $attachments = $item->getAttachments(); $itemIDs = array_merge($notes, $attachments); } else { // Create new items if ($this->method == 'POST') { if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } $obj = $this->jsonDecode($this->body); if (isset($obj->url)) { $response = Zotero_Items::addFromURL($obj, $this->objectLibraryID, $this->userID, $this->getTranslationToken()); if ($response instanceof stdClass) { header("Content-Type: application/json"); echo json_encode($response->select); $this->e300(); } else { if (is_int($response)) { switch ($response) { case 501: $this->e501("No translators found for URL"); break; default: $this->e500("Error translating URL"); } } else { $keys = $response; } } } else { $keys = Zotero_Items::addFromJSON($obj, $this->objectLibraryID, null, $this->userID); } if (!$keys) { throw new Exception("No items added"); } if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } $uri = Zotero_API::getItemsURI($this->objectLibraryID); $queryString = "itemKey=" . urlencode(implode(",", $keys)) . "&content=json"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->responseCode = 201; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, false); } $title = "Items"; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, false, $formatAsKeys); } } } if (!empty($results)) { if ($formatAsKeys) { $responseKeys = $results['keys']; } else { $responseItems = $results['items']; } $totalResults = $results['total']; } } if ($this->queryParams['format'] == 'bib') { if (($itemIDs ? sizeOf($itemIDs) : $results['total']) > Zotero_API::$maxBibliographyItems) { $this->e413("Cannot generate bibliography with more than " . Zotero_API::$maxBibliographyItems . " items"); } } if ($itemIDs) { $this->queryParams['itemIDs'] = $itemIDs; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $formatAsKeys); if ($formatAsKeys) { $responseKeys = $results['keys']; } else { $responseItems = $results['items']; } $totalResults = $results['total']; } else { if (!isset($results)) { if ($formatAsKeys) { $responseKeys = array(); } else { $responseItems = array(); } $totalResults = 0; } } // Remove notes if not user and not public for ($i = 0; $i < sizeOf($responseItems); $i++) { if ($responseItems[$i]->isNote() && !$this->permissions->canAccess($responseItems[$i]->libraryID, 'notes')) { array_splice($responseItems, $i, 1); $totalResults--; $i--; } } switch ($this->queryParams['format']) { case 'atom': $this->responseXML = Zotero_Atom::createAtomFeed($this->getFeedNamePrefix($this->objectLibraryID) . $title, $this->uri, $responseItems, $totalResults, $this->queryParams, $this->apiVersion, $this->permissions); break; case 'bib': echo Zotero_Cite::getBibliographyFromCitationServer($responseItems, $this->queryParams['style'], $this->queryParams['css']); exit; case 'csljson': $json = Zotero_Cite::getJSONFromItems($responseItems, true); if ($this->queryParams['pprint']) { header("Content-Type: text/plain"); $json = Zotero_Utilities::json_encode_pretty($json); } else { header("Content-Type: application/vnd.citationstyles.csl+json"); $json = json_encode($json); } echo $json; exit; case 'keys': if (!$formatAsKeys) { $responseKeys = array(); foreach ($responseItems as $item) { $responseKeys[] = $item->key; } } header("Content-Type: text/plain"); echo implode("\n", $responseKeys) . "\n"; exit; default: $export = Zotero_Translate::doExport($responseItems, $this->queryParams['format']); if ($this->queryParams['pprint']) { header("Content-Type: text/plain"); } else { header("Content-Type: " . $export['mimeType']); } echo $export['body']; exit; } } $this->end(); }
public function items() { // Check for general library access if (!$this->permissions->canAccess($this->objectLibraryID)) { $this->e403(); } if ($this->isWriteMethod()) { // Check for library write access if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } // Make sure library hasn't been modified if (!$this->singleObject) { $libraryTimestampChecked = $this->checkLibraryIfUnmodifiedSinceVersion(); } // We don't update the library version in file mode, because currently // to avoid conflicts in the client the timestamp can't change // when the client updates file metadata if (!$this->fileMode) { Zotero_Libraries::updateVersionAndTimestamp($this->objectLibraryID); } } $itemIDs = array(); $itemKeys = array(); $results = array(); $title = ""; // // Single item // if ($this->singleObject) { if ($this->fileMode) { if ($this->fileView) { $this->allowMethods(array('HEAD', 'GET', 'POST')); } else { $this->allowMethods(array('HEAD', 'GET', 'PUT', 'POST', 'PATCH')); } } else { $this->allowMethods(array('HEAD', 'GET', 'PUT', 'PATCH', 'DELETE')); } if (!$this->objectLibraryID || !Zotero_ID::isValidKey($this->objectKey)) { $this->e404(); } $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); if ($item) { // If no access to the note, don't show that it exists if ($item->isNote() && !$this->permissions->canAccess($this->objectLibraryID, 'notes')) { $this->e404(); } // Make sure URL libraryID matches item libraryID if ($this->objectLibraryID != $item->libraryID) { $this->e404("Item does not exist"); } // File access mode if ($this->fileMode) { $this->_handleFileRequest($item); } if ($this->scopeObject) { switch ($this->scopeObject) { // Remove item from collection case 'collections': $this->allowMethods(array('DELETE')); $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); if (!$collection) { $this->e404("Collection not found"); } if (!$collection->hasItem($item->id)) { $this->e404("Item not found in collection"); } $collection->removeItem($item->id); $this->e204(); default: $this->e400(); } } } else { // Possibly temporary workaround to block unnecessary full syncs if ($this->fileMode && $this->httpAuth && $this->method == 'POST') { // If > 2 requests for missing file, trigger a full sync via 404 $cacheKey = "apiMissingFile_" . $this->objectLibraryID . "_" . $this->objectKey; $set = Z_Core::$MC->get($cacheKey); if (!$set) { Z_Core::$MC->set($cacheKey, 1, 86400); } else { if ($set < 2) { Z_Core::$MC->increment($cacheKey); } else { Z_Core::$MC->delete($cacheKey); $this->e404("A file sync error occurred. Please sync again."); } } $this->e500("A file sync error occurred. Please sync again."); } } if ($this->isWriteMethod()) { $item = $this->handleObjectWrite('item', $item ? $item : null); if ($this->apiVersion < 2 && ($this->method == 'PUT' || $this->method == 'PATCH')) { $this->queryParams['format'] = 'atom'; $this->queryParams['content'] = ['json']; } } if (!$item) { $this->e404("Item does not exist"); } $this->libraryVersion = $item->version; if ($this->method == 'HEAD') { $this->end(); } // Display item switch ($this->queryParams['format']) { case 'atom': $this->responseXML = Zotero_Items::convertItemToAtom($item, $this->queryParams, $this->permissions); break; case 'bib': echo Zotero_Cite::getBibliographyFromCitationServer(array($item), $this->queryParams); break; case 'csljson': $json = Zotero_Cite::getJSONFromItems(array($item), true); echo Zotero_Utilities::formatJSON($json); break; case 'json': $json = $item->toResponseJSON($this->queryParams, $this->permissions); echo Zotero_Utilities::formatJSON($json); break; default: $export = Zotero_Translate::doExport(array($item), $this->queryParams['format']); $this->queryParams['format'] = null; header("Content-Type: " . $export['mimeType']); echo $export['body']; break; } } else { $this->allowMethods(array('HEAD', 'GET', 'POST', 'DELETE')); $this->libraryVersion = Zotero_Libraries::getUpdatedVersion($this->objectLibraryID); $includeTrashed = $this->queryParams['includeTrashed']; if ($this->scopeObject) { $this->allowMethods(array('GET', 'POST')); switch ($this->scopeObject) { case 'collections': // TEMP if (Zotero_ID::isValidKey($this->scopeObjectKey)) { $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); } else { $collection = false; } if (!$collection) { // If old collectionID, redirect if ($this->method == 'GET' && Zotero_Utilities::isPosInt($this->scopeObjectKey)) { $collection = Zotero_Collections::get($this->objectLibraryID, $this->scopeObjectKey); if ($collection) { $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; $base = Zotero_API::getCollectionURI($collection); $this->redirect($base . "/items" . $qs, 301); } } $this->e404("Collection not found"); } // Add items to collection if ($this->method == 'POST') { $itemKeys = explode(' ', $this->body); $itemIDs = array(); foreach ($itemKeys as $key) { try { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $key); } catch (Exception $e) { if ($e->getCode() == Z_ERROR_OBJECT_LIBRARY_MISMATCH) { $item = false; } else { throw $e; } } if (!$item) { throw new Exception("Item '{$key}' not found in library", Z_ERROR_INVALID_INPUT); } if ($item->getSource()) { throw new Exception("Child items cannot be added to collections directly", Z_ERROR_INVALID_INPUT); } $itemIDs[] = $item->id; } $collection->addItems($itemIDs); $this->e204(); } if ($this->subset == 'top' || $this->apiVersion < 2) { $title = "Top-Level Items in Collection ‘" . $collection->name . "’"; $itemIDs = $collection->getItems(); } else { $title = "Items in Collection ‘" . $collection->name . "’"; $itemIDs = $collection->getItems(true); } break; case 'tags': if ($this->apiVersion >= 2) { $this->e404(); } $this->allowMethods(array('GET')); $tagIDs = Zotero_Tags::getIDs($this->objectLibraryID, $this->scopeObjectName); if (!$tagIDs) { $this->e404("Tag not found"); } foreach ($tagIDs as $tagID) { $tag = new Zotero_Tag(); $tag->libraryID = $this->objectLibraryID; $tag->id = $tagID; // Use a real tag name, in case case differs if (!$title) { $title = "Items of Tag ‘" . $tag->name . "’"; } $itemKeys = array_merge($itemKeys, $tag->getLinkedItems(true)); } $itemKeys = array_unique($itemKeys); break; default: $this->e404(); } } else { // Top-level items if ($this->subset == 'top') { $this->allowMethods(array('GET')); $title = "Top-Level Items"; $results = Zotero_Items::search($this->objectLibraryID, true, $this->queryParams, $includeTrashed, $this->permissions); } else { if ($this->subset == 'trash') { $this->allowMethods(array('GET')); $title = "Deleted Items"; $this->queryParams['trashedItemsOnly'] = true; $includeTrashed = true; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } else { if ($this->subset == 'children') { $item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); if (!$item) { $this->e404("Item not found"); } if ($item->isAttachment()) { $this->e400("/children cannot be called on attachment items"); } if ($item->isNote()) { $this->e400("/children cannot be called on note items"); } if ($item->getSource()) { $this->e400("/children cannot be called on child items"); } // Create new child items if ($this->method == 'POST') { if ($this->apiVersion >= 2) { $this->allowMethods(array('GET')); } Zotero_DB::beginTransaction(); $obj = $this->jsonDecode($this->body); $results = Zotero_Items::updateMultipleFromJSON($obj, $this->queryParams, $this->objectLibraryID, $this->userID, $this->permissions, $libraryTimestampChecked ? 0 : 1, $item); Zotero_DB::commit(); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } $uri = Zotero_API::getItemsURI($this->objectLibraryID); $keys = array_merge(get_object_vars($results['success']), get_object_vars($results['unchanged'])); $queryString = "itemKey=" . urlencode(implode(",", $keys)) . "&format=atom&content=json&order=itemKeyList&sort=asc"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, false); $this->responseCode = 201; $title = "Items"; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } else { $title = "Child Items of ‘" . $item->getDisplayTitle() . "’"; $notes = $item->getNotes(); $attachments = $item->getAttachments(); $itemIDs = array_merge($notes, $attachments); } } else { // Create new items if ($this->method == 'POST') { $this->queryParams['format'] = 'writereport'; $obj = $this->jsonDecode($this->body); // Server-side translation if (isset($obj->url)) { if ($this->apiVersion == 1) { Zotero_DB::beginTransaction(); } $token = $this->getTranslationToken($obj); $results = Zotero_Items::addFromURL($obj, $this->queryParams, $this->objectLibraryID, $this->userID, $this->permissions, $token); if ($this->apiVersion == 1) { Zotero_DB::commit(); } // Multiple choices if ($results instanceof stdClass) { $this->queryParams['format'] = null; header("Content-Type: application/json"); if ($this->queryParams['v'] >= 2) { echo Zotero_Utilities::formatJSON(['url' => $obj->url, 'token' => $token, 'items' => $results->select]); } else { echo Zotero_Utilities::formatJSON($results->select); } $this->e300(); } else { if (is_int($results)) { switch ($results) { case 501: $this->e501("No translators found for URL"); break; default: $this->e500("Error translating URL"); } } else { if ($this->apiVersion == 1) { $uri = Zotero_API::getItemsURI($this->objectLibraryID); $keys = array_merge(get_object_vars($results['success']), get_object_vars($results['unchanged'])); $queryString = "itemKey=" . urlencode(implode(",", $keys)) . "&format=atom&content=json&order=itemKeyList&sort=asc"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, false); $this->responseCode = 201; $title = "Items"; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } } } // Otherwise return write status report } else { if ($this->apiVersion < 2) { Zotero_DB::beginTransaction(); } $results = Zotero_Items::updateMultipleFromJSON($obj, $this->queryParams, $this->objectLibraryID, $this->userID, $this->permissions, $libraryTimestampChecked ? 0 : 1, null); if ($this->apiVersion < 2) { Zotero_DB::commit(); $uri = Zotero_API::getItemsURI($this->objectLibraryID); $keys = array_merge(get_object_vars($results['success']), get_object_vars($results['unchanged'])); $queryString = "itemKey=" . urlencode(implode(",", $keys)) . "&format=atom&content=json&order=itemKeyList&sort=asc"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, false); $this->responseCode = 201; $title = "Items"; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } } if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } } else { if ($this->method == 'DELETE') { Zotero_DB::beginTransaction(); foreach ($this->queryParams['itemKey'] as $itemKey) { Zotero_Items::delete($this->objectLibraryID, $itemKey); } Zotero_DB::commit(); $this->e204(); } else { $title = "Items"; $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } } } } } } if ($itemIDs || $itemKeys) { if ($itemIDs) { $this->queryParams['itemIDs'] = $itemIDs; } if ($itemKeys) { $this->queryParams['itemKey'] = $itemKeys; } $results = Zotero_Items::search($this->objectLibraryID, false, $this->queryParams, $includeTrashed, $this->permissions); } if ($this->queryParams['format'] == 'bib') { $maxBibItems = Zotero_API::MAX_BIBLIOGRAPHY_ITEMS; if ($results['total'] > $maxBibItems) { $this->e413("Cannot generate bibliography with more than {$maxBibItems} items"); } } $this->generateMultiResponse($results, $title); } $this->end(); }