public function collections() { if (($this->method == 'POST' || $this->method == 'PUT') && !$this->body) { $this->e400("{$this->method} data not provided"); } $collections = array(); // Single collection if (($this->objectID || $this->objectKey) && $this->subset != 'collections') { $this->allowMethods(array('GET', 'PUT', 'DELETE')); // If id, redirect to key URL if ($this->objectID) { $this->allowMethods(array('GET')); $collection = Zotero_Collections::get($this->objectLibraryID, $this->objectID); if (!$collection) { $this->e404("Collection not found"); } $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; header("Location: " . Zotero_API::getCollectionURI($collection) . $qs); exit; } $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); if (!$collection) { $this->e404("Collection not found"); } // In single-collection mode, require public pref to be enabled if (!$this->permissions->canAccess($this->objectLibraryID)) { $this->e403(); } 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 ($collection->etag != $matches[1]) { $this->e412("ETag does not match current version of collection"); } } if ($this->method == 'PUT') { $obj = $this->jsonDecode($this->body); Zotero_Collections::updateFromJSON($collection, $obj); $this->queryParams['format'] = 'atom'; $this->queryParams['content'] = array('json'); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } } else { Zotero_Collections::delete($this->objectLibraryID, $this->objectKey, true); $this->e204(); } } $this->responseXML = Zotero_Collections::convertCollectionToAtom($collection, $this->queryParams['content']); } else { $this->allowMethods(array('GET', 'POST')); if (!$this->permissions->canAccess($this->objectLibraryID)) { $this->e403(); } if ($this->scopeObject) { $this->allowMethods(array('GET')); switch ($this->scopeObject) { case 'collections': // If id, redirect to key URL if ($this->scopeObjectID) { $collection = Zotero_Collections::get($this->objectLibraryID, $this->scopeObjectID); if (!$collection) { $this->e404("Collection not found"); } $qs = !empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''; header("Location: " . Zotero_API::getCollectionURI($collection) . $qs); exit; } $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); if (!$collection) { $this->e404("Collection not found"); } $title = "Child Collections of ‘{$collection->name}'’"; $collectionIDs = $collection->getChildCollections(); break; default: throw new Exception("Invalid collections scope object '{$this->scopeObject}'"); } } else { // Top-level items if ($this->subset == 'top') { $this->allowMethods(array('GET')); $title = "Top-Level Collections"; $results = Zotero_Collections::getAllAdvanced($this->objectLibraryID, true, $this->queryParams); } else { // Create a collection if ($this->method == 'POST') { if (!$this->permissions->canWrite($this->objectLibraryID)) { $this->e403("Write access denied"); } $obj = $this->jsonDecode($this->body); $collection = Zotero_Collections::addFromJSON($obj, $this->objectLibraryID); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } $uri = Zotero_API::getCollectionURI($collection); $queryString = "content=json"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, true); } $title = "Collections"; $results = Zotero_Collections::getAllAdvanced($this->objectLibraryID, false, $this->queryParams); } $collections = $results['collections']; $totalResults = $results['total']; } if (!empty($collectionIDs)) { foreach ($collectionIDs as $collectionID) { $collections[] = Zotero_Collections::get($this->objectLibraryID, $collectionID); } // Fake sorting and limiting $totalResults = sizeOf($collections); $key = $this->queryParams['order']; if ($key == 'title') { $key = 'name'; } $dir = $this->queryParams['sort']; usort($collections, function ($a, $b) use($key, $dir) { $dir = $dir == "asc" ? 1 : -1; if ($a->{$key} == $b->{$key}) { return 0; } else { return $a->{$key} > $b->{$key} ? $dir : $dir * -1; } }); $collections = array_slice($collections, $this->queryParams['start'], $this->queryParams['limit']); } $this->responseXML = Zotero_Atom::createAtomFeed($this->getFeedNamePrefix($this->objectLibraryID) . $title, $this->uri, $collections, $totalResults, $this->queryParams, $this->apiVersion, $this->permissions); } $this->end(); }
public function collections() { // 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(); } Zotero_Libraries::updateVersionAndTimestamp($this->objectLibraryID); } $collectionIDs = array(); $collectionKeys = array(); $results = array(); // Single collection if ($this->singleObject) { $this->allowMethods(['HEAD', 'GET', 'PUT', 'PATCH', 'DELETE']); if (!Zotero_ID::isValidKey($this->objectKey)) { $this->e404(); } $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->objectKey); if ($this->isWriteMethod()) { $collection = $this->handleObjectWrite('collection', $collection ? $collection : null); $this->queryParams['content'] = ['json']; } if (!$collection) { $this->e404("Collection not found"); } $this->libraryVersion = $collection->version; if ($this->method == 'HEAD') { $this->end(); } switch ($this->queryParams['format']) { case 'atom': $this->responseXML = Zotero_Collections::convertCollectionToAtom($collection, $this->queryParams); break; case 'json': $json = $collection->toResponseJSON($this->queryParams, $this->permissions); echo Zotero_Utilities::formatJSON($json); break; default: throw new Exception("Unexpected format '" . $this->queryParams['format'] . "'"); } } else { $this->allowMethods(['HEAD', 'GET', 'POST', 'DELETE']); $this->libraryVersion = Zotero_Libraries::getUpdatedVersion($this->objectLibraryID); if ($this->scopeObject) { $this->allowMethods(array('GET')); switch ($this->scopeObject) { case 'collections': $collection = Zotero_Collections::getByLibraryAndKey($this->objectLibraryID, $this->scopeObjectKey); if (!$collection) { $this->e404("Collection not found"); } $title = "Child Collections of ‘{$collection->name}'’"; $collectionIDs = $collection->getChildCollections(); break; default: throw new Exception("Invalid collections scope object '{$this->scopeObject}'"); } } else { // Top-level items if ($this->subset == 'top') { $this->allowMethods(array('GET')); $title = "Top-Level Collections"; $results = Zotero_Collections::search($this->objectLibraryID, true, $this->queryParams); } else { // Create a collection if ($this->method == 'POST') { $this->queryParams['format'] = 'writereport'; $obj = $this->jsonDecode($this->body); $results = Zotero_Collections::updateMultipleFromJSON($obj, $this->queryParams, $this->objectLibraryID, $this->userID, $this->permissions, $libraryTimestampChecked ? 0 : 1, null); if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } if ($this->apiVersion < 2) { $uri = Zotero_API::getCollectionsURI($this->objectLibraryID); $keys = array_merge(get_object_vars($results['success']), get_object_vars($results['unchanged'])); $queryString = "collectionKey=" . urlencode(implode(",", $keys)) . "&format=atom&content=json&order=collectionKeyList&sort=asc"; if ($this->apiKey) { $queryString .= "&key=" . $this->apiKey; } $uri .= "?" . $queryString; $this->queryParams = Zotero_API::parseQueryParams($queryString, $this->action, true, $this->apiVersion); $title = "Collections"; $results = Zotero_Collections::search($this->objectLibraryID, false, $this->queryParams); } } else { if ($this->method == 'DELETE') { Zotero_DB::beginTransaction(); foreach ($this->queryParams['collectionKey'] as $collectionKey) { Zotero_Collections::delete($this->objectLibraryID, $collectionKey); } Zotero_DB::commit(); $this->e204(); } else { $title = "Collections"; $results = Zotero_Collections::search($this->objectLibraryID, false, $this->queryParams); } } } } if ($collectionIDs) { $this->queryParams['collectionIDs'] = $collectionIDs; $results = Zotero_Collections::search($this->objectLibraryID, false, $this->queryParams); } $options = ['action' => $this->action, 'uri' => $this->uri, 'results' => $results, 'requestParams' => $this->queryParams, 'permissions' => $this->permissions, 'head' => $this->method == 'HEAD']; switch ($this->queryParams['format']) { case 'atom': $this->responseXML = Zotero_API::multiResponse(array_merge($options, ['title' => $this->getFeedNamePrefix($this->objectLibraryID) . $title])); break; case 'json': case 'keys': case 'versions': case 'writereport': Zotero_API::multiResponse($options); break; default: throw new Exception("Unexpected format '" . $this->queryParams['format'] . "'"); } } $this->end(); }