Beispiel #1
0
 public function testExportFormatMultiple()
 {
     foreach (self::$formats as $format) {
         $response = API::userGet(self::$config['userID'], "items?format={$format}");
         $this->assert200($response);
         $this->assertContentType(self::$multiResponses[$format]['contentType'], $response);
         $this->assertEquals(self::$multiResponses[$format]['content'], $response->getBody());
     }
 }
Beispiel #2
0
 /**
  * An object type's primary data cache for a library has to be created before
  * 
  */
 public function testCacheCreatorPrimaryData()
 {
     $data = array("title" => "Title", "creators" => array(array("creatorType" => "author", "firstName" => "First", "lastName" => "Last"), array("creatorType" => "editor", "firstName" => "Ed", "lastName" => "McEditor")));
     $key = API::createItem("book", $data, $this, 'key');
     $response = API::userGet(self::$config['userID'], "items/{$key}?content=csljson");
     $json = json_decode(API::getContentFromResponse($response));
     $this->assertEquals("First", $json->author[0]->given);
     $this->assertEquals("Last", $json->author[0]->family);
     $this->assertEquals("Ed", $json->editor[0]->given);
     $this->assertEquals("McEditor", $json->editor[0]->family);
 }
Beispiel #3
0
 public function testCreateItemAndAnonymousRead()
 {
     // Create item
     API::useAPIKey(self::$config['apiKey']);
     $json = API::getItemTemplate("book");
     $response = API::userPost(self::$config['userID'], "publications/items", json_encode([$json]));
     $this->assert200ForObject($response);
     // Test notifications (which we do here instead of in NotificationsTest.php because
     // we want to test library creation above (though we could delete the publications
     // library explicitly first))
     $this->assertCountNotifications(1, $response);
     $this->assertHasNotification(['event' => 'topicUpdated', 'topic' => '/users/' . self::$config['userID'] . '/publications'], $response);
     $json = API::getJSONFromResponse($response);
     $itemKey = $json['success'][0];
     // Read item anonymously
     API::useAPIKey("");
     $libraryName = self::$config['username'] . '’s Publications';
     // JSON
     $response = API::userGet(self::$config['userID'], "publications/items/{$itemKey}");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($libraryName, $json['library']['name']);
     $this->assertEquals("publications", $json['library']['type']);
     // Atom
     $response = API::userGet(self::$config['userID'], "publications/items/{$itemKey}?format=atom");
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $this->assertEquals($libraryName, (string) $xml->author->name);
 }
Beispiel #4
0
 public function testAuthorization()
 {
     $apiKey = self::$config['apiKey'];
     API::useAPIKey(false);
     // Zotero-API-Key header
     $response = API::userGet(self::$config['userID'], "items", ["Zotero-API-Key: {$apiKey}"]);
     $this->assertHTTPStatus(200, $response);
     // Authorization header
     $response = API::userGet(self::$config['userID'], "items", ["Authorization: Bearer {$apiKey}"]);
     $this->assertHTTPStatus(200, $response);
     // Query parameter
     $response = API::userGet(self::$config['userID'], "items?key={$apiKey}");
     $this->assertHTTPStatus(200, $response);
     // Zotero-API-Key header and query parameter
     $response = API::userGet(self::$config['userID'], "items?key={$apiKey}", ["Zotero-API-Key: {$apiKey}"]);
     $this->assertHTTPStatus(200, $response);
     // No key
     $response = API::userGet(self::$config['userID'], "items");
     $this->assertHTTPStatus(403, $response);
     // Zotero-API-Key header and empty key (which is still an error)
     $response = API::userGet(self::$config['userID'], "items?key=", ["Zotero-API-Key: {$apiKey}"]);
     $this->assertHTTPStatus(400, $response);
     // Zotero-API-Key header and incorrect Authorization key (which is ignored)
     $response = API::userGet(self::$config['userID'], "items", ["Zotero-API-Key: {$apiKey}", "Authorization: Bearer invalidkey"]);
     $this->assertHTTPStatus(200, $response);
     // Zotero-API-Key header and key mismatch
     $response = API::userGet(self::$config['userID'], "items?key=invalidkey", ["Zotero-API-Key: {$apiKey}"]);
     $this->assertHTTPStatus(400, $response);
     // Invalid Bearer format
     $response = API::userGet(self::$config['userID'], "items", ["Authorization: Bearer key={$apiKey}"]);
     $this->assertHTTPStatus(400, $response);
     // Ignored OAuth 1.0 header, with key query parameter
     $response = API::userGet(self::$config['userID'], "items?key={$apiKey}", ['Authorization: OAuth oauth_consumer_key="aaaaaaaaaaaaaaaaaaaa"']);
     $this->assertHTTPStatus(200, $response);
     // Ignored OAuth 1.0 header, with no key query parameter
     $response = API::userGet(self::$config['userID'], "items", ['Authorization: OAuth oauth_consumer_key="aaaaaaaaaaaaaaaaaaaa"']);
     $this->assertHTTPStatus(403, $response);
 }
Beispiel #5
0
 private function _testSinceContent($param)
 {
     API::userClear(self::$config['userID']);
     // Store content for one item
     $key = API::createItem("book", false, $this, 'key');
     $json = API::createAttachmentItem("imported_url", [], $key, $this, 'jsonData');
     $key1 = $json['key'];
     $content = "Here is some full-text content";
     $response = API::userPut(self::$config['userID'], "items/{$key1}/fulltext", json_encode(["content" => $content]), array("Content-Type: application/json"));
     $this->assert204($response);
     $contentVersion1 = $response->getHeader("Last-Modified-Version");
     $this->assertGreaterThan(0, $contentVersion1);
     // And another
     $key = API::createItem("book", false, $this, 'key');
     $json = API::createAttachmentItem("imported_url", [], $key, $this, 'jsonData');
     $key2 = $json['key'];
     $response = API::userPut(self::$config['userID'], "items/{$key2}/fulltext", json_encode(["content" => $content]), array("Content-Type: application/json"));
     $this->assert204($response);
     $contentVersion2 = $response->getHeader("Last-Modified-Version");
     $this->assertGreaterThan(0, $contentVersion2);
     // Get newer one
     $response = API::userGet(self::$config['userID'], "fulltext?{$param}={$contentVersion1}");
     $this->assert200($response);
     $this->assertContentType("application/json", $response);
     $this->assertEquals($contentVersion2, $response->getHeader("Last-Modified-Version"));
     $json = API::getJSONFromResponse($response);
     $this->assertCount(1, $json);
     $this->assertArrayHasKey($key2, $json);
     $this->assertEquals($contentVersion2, $json[$key2]);
     // Get both with since=0
     $response = API::userGet(self::$config['userID'], "fulltext?{$param}=0");
     $this->assert200($response);
     $this->assertContentType("application/json", $response);
     $json = API::getJSONFromResponse($response);
     $this->assertCount(2, $json);
     $this->assertArrayHasKey($key1, $json);
     $this->assertEquals($contentVersion1, $json[$key1]);
     $this->assertArrayHasKey($key1, $json);
     $this->assertEquals($contentVersion2, $json[$key2]);
 }
Beispiel #6
0
 public function testCollectionItems()
 {
     $collectionKey = API::createCollection('Test', false, $this, 'key');
     $json = API::createItem("book", ['collections' => [$collectionKey]], $this, 'jsonData');
     $itemKey1 = $json['key'];
     $itemVersion1 = $json['version'];
     $this->assertEquals([$collectionKey], $json['collections']);
     $json = API::createItem("journalArticle", ['collections' => [$collectionKey]], $this, 'jsonData');
     $itemKey2 = $json['key'];
     $itemVersion2 = $json['version'];
     $this->assertEquals([$collectionKey], $json['collections']);
     $childItemKey1 = API::createAttachmentItem("linked_url", [], $itemKey1, $this, 'key');
     $childItemKey2 = API::createAttachmentItem("linked_url", [], $itemKey2, $this, 'key');
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items?format=keys");
     $this->assert200($response);
     $keys = explode("\n", trim($response->getBody()));
     $this->assertCount(4, $keys);
     $this->assertContains($itemKey1, $keys);
     $this->assertContains($itemKey2, $keys);
     $this->assertContains($childItemKey1, $keys);
     $this->assertContains($childItemKey2, $keys);
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items/top?format=keys");
     $this->assert200($response);
     $keys = explode("\n", trim($response->getBody()));
     $this->assertCount(2, $keys);
     $this->assertContains($itemKey1, $keys);
     $this->assertContains($itemKey2, $keys);
 }
Beispiel #7
0
 public function testAcceptHeader()
 {
     $response = API::userGet(self::$config['userID'], "items", ["Accept: application/atom+xml,application/rdf+xml,application/rss+xml,application/xml,text/xml,*/*"]);
     $this->assertContentType('application/atom+xml', $response);
     // But format= should still override
     $response = API::userGet(self::$config['userID'], "items?format=json", ["Accept: application/atom+xml,application/rdf+xml,application/rss+xml,application/xml,text/xml,*/*"]);
     $this->assertContentType('application/json', $response);
 }
Beispiel #8
0
	public function testUnicodeTitle() {
		$title = "Tést";
		
		$key = API::createItem("book", array("title" => $title), $this, 'key');
		
		// Test entry (JSON)
		$response = API::userGet(
			self::$config['userID'],
			"items/$key"
		);
		$this->assertContains('"title": "Tést"', $response->getBody());
		
		// Test feed (JSON)
		$response = API::userGet(
			self::$config['userID'],
			"items"
		);
		$this->assertContains('"title": "Tést"', $response->getBody());
		
		// Test entry (Atom)
		$response = API::userGet(
			self::$config['userID'],
			"items/$key?content=json"
		);
		$this->assertContains('"title": "Tést"', $response->getBody());
		
		// Test feed (Atom)
		$response = API::userGet(
			self::$config['userID'],
			"items?content=json"
		);
		$this->assertContains('"title": "Tést"', $response->getBody());
	}
Beispiel #9
0
 public function testAddFileClientZip()
 {
     API::userClear(self::$config['userID']);
     $auth = array('username' => self::$config['username'], 'password' => self::$config['password']);
     // Get last storage sync
     $response = API::userGet(self::$config['userID'], "laststoragesync?auth=1", array(), $auth);
     $this->assert404($response);
     $json = API::createItem("book", false, $this, 'jsonData');
     $key = $json['key'];
     $fileContentType = "text/html";
     $fileCharset = "UTF-8";
     $fileFilename = "file.html";
     $fileModtime = time();
     $json = API::createAttachmentItem("imported_url", [], $key, $this, 'jsonData');
     $key = $json['key'];
     $version = $json['version'];
     $json['contentType'] = $fileContentType;
     $json['charset'] = $fileCharset;
     $json['filename'] = $fileFilename;
     $response = API::userPut(self::$config['userID'], "items/{$key}", json_encode($json), array("Content-Type: application/json"));
     $this->assert204($response);
     // Get a sync timestamp from before the file is updated
     sleep(1);
     require_once 'include/sync.inc.php';
     $sessionID = Sync::login();
     $xml = Sync::updated($sessionID);
     $lastsync = (int) $xml['timestamp'];
     Sync::logout($sessionID);
     // Get file info
     $response = API::userGet(self::$config['userID'], "items/{$json['key']}/file?auth=1&iskey=1&version=1&info=1", array(), $auth);
     $this->assert404($response);
     $zip = new \ZipArchive();
     $file = "work/{$key}.zip";
     if ($zip->open($file, \ZIPARCHIVE::CREATE) !== TRUE) {
         throw new Exception("Cannot open ZIP file");
     }
     $zip->addFromString($fileFilename, self::getRandomUnicodeString());
     $zip->addFromString("file.css", self::getRandomUnicodeString());
     $zip->close();
     $hash = md5_file($file);
     $filename = $key . ".zip";
     $size = filesize($file);
     $fileContents = file_get_contents($file);
     // Get upload authorization
     $response = API::userPost(self::$config['userID'], "items/{$json['key']}/file?auth=1&iskey=1&version=1", $this->implodeParams(array("md5" => $hash, "filename" => $filename, "filesize" => $size, "mtime" => $fileModtime, "zip" => 1)), array("Content-Type: application/x-www-form-urlencoded"), $auth);
     $this->assert200($response);
     $this->assertContentType("application/xml", $response);
     $xml = new SimpleXMLElement($response->getBody());
     self::$toDelete[] = "{$hash}";
     $boundary = "---------------------------" . rand();
     $postData = "";
     foreach ($xml->params->children() as $key => $val) {
         $postData .= "--" . $boundary . "\r\nContent-Disposition: form-data; " . "name=\"{$key}\"\r\n\r\n{$val}\r\n";
     }
     $postData .= "--" . $boundary . "\r\nContent-Disposition: form-data; " . "name=\"file\"\r\n\r\n" . $fileContents . "\r\n";
     $postData .= "--" . $boundary . "--";
     // Upload to S3
     $response = HTTP::post((string) $xml->url, $postData, array("Content-Type: multipart/form-data; boundary=" . $boundary));
     $this->assert201($response);
     //
     // Register upload
     //
     $response = API::userPost(self::$config['userID'], "items/{$json['key']}/file?auth=1&iskey=1&version=1", "update=" . $xml->key . "&mtime=" . $fileModtime, array("Content-Type: application/x-www-form-urlencoded"), $auth);
     $this->assert204($response);
     // Verify attachment item metadata
     $response = API::userGet(self::$config['userID'], "items/{$json['key']}");
     $json = API::getJSONFromResponse($response)['data'];
     $this->assertEquals($hash, $json['md5']);
     $this->assertEquals($fileFilename, $json['filename']);
     $this->assertEquals($fileModtime, $json['mtime']);
     // Make sure attachment item wasn't updated (or else the client
     // will get a conflict when it tries to update the metadata)
     $sessionID = Sync::login();
     $xml = Sync::updated($sessionID, $lastsync);
     Sync::logout($sessionID);
     $this->assertEquals(0, $xml->updated[0]->count());
     $response = API::userGet(self::$config['userID'], "laststoragesync?auth=1", array(), array('username' => self::$config['username'], 'password' => self::$config['password']));
     $this->assert200($response);
     $mtime = $response->getBody();
     $this->assertRegExp('/^[0-9]{10}$/', $mtime);
     // File exists
     $response = API::userPost(self::$config['userID'], "items/{$json['key']}/file?auth=1&iskey=1&version=1", $this->implodeParams(array("md5" => $hash, "filename" => $filename, "filesize" => $size, "mtime" => $fileModtime + 1000, "zip" => 1)), array("Content-Type: application/x-www-form-urlencoded"), $auth);
     $this->assert200($response);
     $this->assertContentType("application/xml", $response);
     $this->assertEquals("<exists/>", $response->getBody());
     // Make sure attachment item still wasn't updated
     $sessionID = Sync::login();
     $xml = Sync::updated($sessionID, $lastsync);
     Sync::logout($sessionID);
     $this->assertEquals(0, $xml->updated[0]->count());
 }
Beispiel #10
0
 public function testFormatBibMultiple()
 {
     foreach (self::$styles as $style) {
         $response = API::userGet(self::$config['userID'], "items?format=bib" . ($style == "default" ? "" : "&style=" . urlencode($style)));
         $this->assert200($response);
         $this->assertXmlStringEqualsXmlString(self::$multiResponses[$style], $response->getBody());
     }
 }
Beispiel #11
0
 private function _testPartialWriteFailureWithUnchanged($objectType)
 {
     API::userClear(self::$config['userID']);
     $objectTypePlural = API::getPluralObjectType($objectType);
     switch ($objectType) {
         case 'collection':
             $json1 = API::createCollection("Test", false, $this, 'jsonData');
             $json2 = array("name" => str_repeat("1234567890", 6554));
             $json3 = array("name" => "Test");
             break;
         case 'item':
             $json1 = API::createItem("book", array("title" => "Title"), $this, 'jsonData');
             $json2 = API::getItemTemplate('book');
             $json3 = clone $json2;
             $json2->title = str_repeat("1234567890", 6554);
             break;
         case 'search':
             $conditions = array(array('condition' => 'title', 'operator' => 'contains', 'value' => 'value'));
             $json1 = API::createSearch("Name", $conditions, $this, 'jsonData');
             $json2 = array("name" => str_repeat("1234567890", 6554), "conditions" => $conditions);
             $json3 = array("name" => "Test", "conditions" => $conditions);
             break;
     }
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}", json_encode([$json1, $json2, $json3]), array("Content-Type: application/json"));
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $this->assertUnchangedForObject($response, 0);
     $this->assert400ForObject($response, false, 1);
     $this->assert200ForObject($response, false, 2);
     $json = API::getJSONFromResponse($response);
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}?format=keys&key=" . self::$config['apiKey']);
     $this->assert200($response);
     $keys = explode("\n", trim($response->getBody()));
     $this->assertCount(2, $keys);
     foreach ($json['success'] as $key) {
         $this->assertContains($key, $keys);
     }
 }
Beispiel #12
0
 public function testUnsupportedSettingMultiple()
 {
     $settingKey = "unsupportedSetting";
     $json = array("tagColors" => array("value" => array("name" => "_READ", "color" => "#990000"), "version" => 0), $settingKey => array("value" => false, "version" => 0));
     $libraryVersion = API::getLibraryVersion();
     $response = API::userPut(self::$config['userID'], "settings/{$settingKey}", json_encode($json), array("Content-Type: application/json"));
     $this->assert400($response, "Invalid setting '{$settingKey}'");
     // Valid setting shouldn't exist, and library version should be unchanged
     $response = API::userGet(self::$config['userID'], "settings/{$settingKey}");
     $this->assert404($response);
     $this->assertEquals($libraryVersion, API::getLibraryVersion());
 }
Beispiel #13
0
 public function testKeyNoteAccess()
 {
     API::userClear(self::$config['userID']);
     API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryNotes', 1);
     $keys = array();
     $topLevelKeys = array();
     $bookKeys = array();
     $key = API::createItem('book', array("title" => "A"), $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $bookKeys[] = $key;
     $key = API::createNoteItem("B", false, $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $key = API::createNoteItem("C", false, $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $key = API::createNoteItem("D", false, $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $key = API::createNoteItem("E", false, $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $key = API::createItem('book', array("title" => "F"), $this, 'key');
     $keys[] = $key;
     $topKeys[] = $key;
     $bookKeys[] = $key;
     $key = API::createNoteItem("G", $key, $this, 'key');
     $keys[] = $key;
     // Create collection and add items to it
     $response = API::userPost(self::$config['userID'], "collections", json_encode([["name" => "Test", "parentCollection" => false]]), array("Content-Type: application/json"));
     $this->assert200ForObject($response);
     $collectionKey = API::getFirstSuccessKeyFromResponse($response);
     $response = API::userPost(self::$config['userID'], "collections/{$collectionKey}/items", implode(" ", $topKeys));
     $this->assert204($response);
     //
     // format=atom
     //
     // Root
     $response = API::userGet(self::$config['userID'], "items");
     $this->assertNumResults(sizeOf($keys), $response);
     $this->assertTotalResults(sizeOf($keys), $response);
     // Top
     $response = API::userGet(self::$config['userID'], "items/top");
     $this->assertNumResults(sizeOf($topKeys), $response);
     $this->assertTotalResults(sizeOf($topKeys), $response);
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items/top");
     $this->assertNumResults(sizeOf($topKeys), $response);
     $this->assertTotalResults(sizeOf($topKeys), $response);
     //
     // format=keys
     //
     // Root
     $response = API::userGet(self::$config['userID'], "items?format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($keys), explode("\n", trim($response->getBody())));
     // Top
     $response = API::userGet(self::$config['userID'], "items/top?format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($topKeys), explode("\n", trim($response->getBody())));
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items/top?format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($topKeys), explode("\n", trim($response->getBody())));
     // Remove notes privilege from key
     API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryNotes', 0);
     //
     // format=json
     //
     // totalResults with limit
     $response = API::userGet(self::$config['userID'], "items?limit=1");
     $this->assertNumResults(1, $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // And without limit
     $response = API::userGet(self::$config['userID'], "items");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Top
     $response = API::userGet(self::$config['userID'], "items/top");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     //
     // format=atom
     //
     // totalResults with limit
     $response = API::userGet(self::$config['userID'], "items?format=atom&limit=1");
     $this->assertNumResults(1, $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // And without limit
     $response = API::userGet(self::$config['userID'], "items?format=atom");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Top
     $response = API::userGet(self::$config['userID'], "items/top?format=atom");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items?format=atom");
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     //
     // format=keys
     //
     $response = API::userGet(self::$config['userID'], "items?format=keys");
     $keys = explode("\n", trim($response->getBody()));
     sort($keys);
     $this->assertEmpty(array_merge(array_diff($bookKeys, $keys), array_diff($keys, $bookKeys)));
 }
Beispiel #14
0
 public function testSortDirection()
 {
     API::userClear(self::$config['userID']);
     // Setup
     $dataArray = [];
     $dataArray[] = API::createItem("book", ['title' => "B", 'creators' => [["creatorType" => "author", "name" => "B"]], 'dateAdded' => '2014-02-05T00:00:00Z', 'dateModified' => '2014-04-05T01:00:00Z'], $this, 'jsonData');
     $dataArray[] = API::createItem("journalArticle", ['title' => "A", 'creators' => [["creatorType" => "author", "name" => "A"]], 'dateAdded' => '2014-02-04T00:00:00Z', 'dateModified' => '2014-01-04T01:00:00Z'], $this, 'jsonData');
     $dataArray[] = API::createItem("newspaperArticle", ['title' => "F", 'creators' => [["creatorType" => "author", "name" => "F"]], 'dateAdded' => '2014-02-03T00:00:00Z', 'dateModified' => '2014-02-03T01:00:00Z'], $this, 'jsonData');
     $dataArray[] = API::createItem("book", ['title' => "C", 'creators' => [["creatorType" => "author", "name" => "C"]], 'dateAdded' => '2014-02-02T00:00:00Z', 'dateModified' => '2014-03-02T01:00:00Z'], $this, 'jsonData');
     // Get sorted keys
     usort($dataArray, function ($a, $b) {
         return strcmp($a['dateAdded'], $b['dateAdded']);
     });
     $keysByDateAddedAscending = array_map(function ($data) {
         return $data['key'];
     }, $dataArray);
     $keysByDateAddedDescending = array_reverse($keysByDateAddedAscending);
     // Ascending
     $response = API::userGet(self::$config['userID'], "items?format=keys&sort=dateAdded&direction=asc");
     $this->assert200($response);
     $this->assertEquals($keysByDateAddedAscending, explode("\n", trim($response->getBody())));
     $response = API::userGet(self::$config['userID'], "items?format=json&sort=dateAdded&direction=asc");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $keys = array_map(function ($val) {
         return $val['key'];
     }, $json);
     $this->assertEquals($keysByDateAddedAscending, $keys);
     $response = API::userGet(self::$config['userID'], "items?format=atom&sort=dateAdded&direction=asc");
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $keys = array_map(function ($val) {
         return (string) $val;
     }, $xml->xpath('//atom:entry/zapi:key'));
     $this->assertEquals($keysByDateAddedAscending, $keys);
     // Ascending using old 'order'/'sort' instead of 'sort'/'direction'
     $response = API::userGet(self::$config['userID'], "items?format=keys&order=dateAdded&sort=asc");
     $this->assert200($response);
     $this->assertEquals($keysByDateAddedAscending, explode("\n", trim($response->getBody())));
     $response = API::userGet(self::$config['userID'], "items?format=json&order=dateAdded&sort=asc");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $keys = array_map(function ($val) {
         return $val['key'];
     }, $json);
     $this->assertEquals($keysByDateAddedAscending, $keys);
     $response = API::userGet(self::$config['userID'], "items?format=atom&order=dateAdded&sort=asc");
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $keys = array_map(function ($val) {
         return (string) $val;
     }, $xml->xpath('//atom:entry/zapi:key'));
     $this->assertEquals($keysByDateAddedAscending, $keys);
     // Deprecated 'order'/'sort', but the wrong way
     $response = API::userGet(self::$config['userID'], "items?format=keys&sort=dateAdded&order=asc");
     $this->assert200($response);
     $this->assertEquals($keysByDateAddedAscending, explode("\n", trim($response->getBody())));
     // Descending
     $response = API::userGet(self::$config['userID'], "items?format=keys&sort=dateAdded&direction=desc");
     $this->assert200($response);
     $this->assertEquals($keysByDateAddedDescending, explode("\n", trim($response->getBody())));
     $response = API::userGet(self::$config['userID'], "items?format=json&sort=dateAdded&direction=desc");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $keys = array_map(function ($val) {
         return $val['key'];
     }, $json);
     $this->assertEquals($keysByDateAddedDescending, $keys);
     $response = API::userGet(self::$config['userID'], "items?format=atom&sort=dateAdded&direction=desc");
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $keys = array_map(function ($val) {
         return (string) $val;
     }, $xml->xpath('//atom:entry/zapi:key'));
     $this->assertEquals($keysByDateAddedDescending, $keys);
     // Descending
     $response = API::userGet(self::$config['userID'], "items?format=keys&order=dateAdded&sort=desc");
     $this->assert200($response);
     $this->assertEquals($keysByDateAddedDescending, explode("\n", trim($response->getBody())));
     $response = API::userGet(self::$config['userID'], "items?format=json&order=dateAdded&sort=desc");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $keys = array_map(function ($val) {
         return $val['key'];
     }, $json);
     $this->assertEquals($keysByDateAddedDescending, $keys);
     $response = API::userGet(self::$config['userID'], "items?format=atom&order=dateAdded&sort=desc");
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $keys = array_map(function ($val) {
         return (string) $val;
     }, $xml->xpath('//atom:entry/zapi:key'));
     $this->assertEquals($keysByDateAddedDescending, $keys);
 }
Beispiel #15
0
	public function testLastStorageSyncNoAuthorization() {
		API::useAPIKey(false);
		$response = API::userGet(
			self::$config['userID'],
			"laststoragesync"
		);
		$this->assert401($response);
	}
Beispiel #16
0
 public function testMultiTagDelete()
 {
     $tags1 = array("a", "aa", "b");
     $tags2 = array("b", "c", "cc");
     $tags3 = array("Foo");
     API::createItem("book", array("tags" => array_map(function ($tag) {
         return array("tag" => $tag);
     }, $tags1)), $this, 'key');
     API::createItem("book", array("tags" => array_map(function ($tag) {
         return array("tag" => $tag, "type" => 1);
     }, $tags2)), $this, 'key');
     API::createItem("book", array("tags" => array_map(function ($tag) {
         return array("tag" => $tag);
     }, $tags3)), $this, 'key');
     $libraryVersion = API::getLibraryVersion();
     // Missing version header
     $response = API::userDelete(self::$config['userID'], "tags?tag=" . implode("%20||%20", array_merge($tags1, $tags2)));
     $this->assert428($response);
     // Outdated version header
     $response = API::userDelete(self::$config['userID'], "tags?tag=" . implode("%20||%20", array_merge($tags1, $tags2)), array("If-Unmodified-Since-Version: " . ($libraryVersion - 1)));
     $this->assert412($response);
     // Delete
     $response = API::userDelete(self::$config['userID'], "tags?tag=" . implode("%20||%20", array_merge($tags1, $tags2)), array("If-Unmodified-Since-Version: {$libraryVersion}"));
     $this->assert204($response);
     // Make sure they're gone
     $response = API::userGet(self::$config['userID'], "tags?tag=" . implode("%20||%20", array_merge($tags1, $tags2, $tags3)));
     $this->assert200($response);
     $this->assertNumResults(1, $response);
 }
Beispiel #17
0
 public function testItemQuickSearchOrderByDate()
 {
     $title1 = "Test Title";
     $title2 = "Another Title";
     $keys = [];
     $keys[] = API::createItem("book", ['title' => $title1, 'date' => "February 12, 2013"], $this, 'key');
     $keys[] = API::createItem("journalArticle", ['title' => $title2, 'date' => "November 25, 2012"], $this, 'key');
     // Search for one by title
     $response = API::userGet(self::$config['userID'], "items?q=" . urlencode($title1));
     $this->assert200($response);
     $this->assertNumResults(1, $response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($keys[0], $json[0]['key']);
     // Search by both by title, date asc
     $response = API::userGet(self::$config['userID'], "items?q=title&sort=date&direction=asc");
     $this->assert200($response);
     $this->assertNumResults(2, $response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($keys[1], $json[0]['key']);
     $this->assertEquals($keys[0], $json[1]['key']);
     // Search by both by title, date asc, with old-style parameters
     $response = API::userGet(self::$config['userID'], "items?q=title&order=date&sort=asc");
     $this->assert200($response);
     $this->assertNumResults(2, $response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($keys[1], $json[0]['key']);
     $this->assertEquals($keys[0], $json[1]['key']);
     // Search by both by title, date desc
     $response = API::userGet(self::$config['userID'], "items?q=title&sort=date&direction=desc");
     $this->assert200($response);
     $this->assertNumResults(2, $response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($keys[0], $json[0]['key']);
     $this->assertEquals($keys[1], $json[1]['key']);
     // Search by both by title, date desc, with old-style parameters
     $response = API::userGet(self::$config['userID'], "items?q=title&order=date&sort=desc");
     $this->assert200($response);
     $this->assertNumResults(2, $response);
     $json = API::getJSONFromResponse($response);
     $this->assertEquals($keys[0], $json[0]['key']);
     $this->assertEquals($keys[1], $json[1]['key']);
 }
Beispiel #18
0
 public function testKeyCreateAndDelete()
 {
     API::useAPIKey("");
     $name = "Test " . uniqid();
     // Can't create as user
     $response = API::userPost(self::$config['userID'], 'keys', json_encode(['name' => $name, 'access' => ['user' => ['library' => true]]]));
     $this->assert403($response);
     // Create as root
     $response = API::userPost(self::$config['userID'], 'keys', json_encode(['name' => $name, 'access' => ['user' => ['library' => true]]]), [], ["username" => self::$config['rootUsername'], "password" => self::$config['rootPassword']]);
     $this->assert201($response);
     $json = API::getJSONFromResponse($response);
     $key = $json['key'];
     $this->assertEquals($json['name'], $name);
     $this->assertEquals(['user' => ['library' => true, 'files' => true]], $json['access']);
     // Delete anonymously (with embedded key)
     $response = API::userDelete(self::$config['userID'], "keys/{$key}");
     $this->assert204($response);
     $response = API::userGet(self::$config['userID'], "keys/{$key}");
     $this->assert404($response);
 }
Beispiel #19
0
 /**
  * Changing a group's metadata should change its ETag
  */
 public function testUpdateMetadataAtom()
 {
     $response = API::userGet(self::$config['userID'], "groups?content=json&key=" . self::$config['apiKey']);
     $this->assert200($response);
     // Get group API URI and version
     $xml = API::getXMLFromResponse($response);
     $xml->registerXPathNamespace('atom', 'http://www.w3.org/2005/Atom');
     $xml->registerXPathNamespace('zapi', 'http://zotero.org/ns/api');
     $groupID = (string) array_shift($xml->xpath("//atom:entry/zapi:groupID"));
     $url = (string) array_shift($xml->xpath("//atom:entry/atom:link[@rel='self']/@href"));
     $url = str_replace(self::$config['apiURLPrefix'], '', $url);
     $version = json_decode(API::parseDataFromAtomEntry($xml)['content'], true)['version'];
     // Make sure format=versions returns the same ETag
     $response = API::userGet(self::$config['userID'], "groups?format=versions&key=" . self::$config['apiKey']);
     $this->assert200($response);
     $json = json_decode($response->getBody());
     $this->assertEquals($version, $json->{$groupID});
     // Update group metadata
     $json = json_decode(array_shift($xml->xpath("//atom:entry/atom:content")));
     $xml = new SimpleXMLElement("<group/>");
     foreach ($json as $key => $val) {
         switch ($key) {
             case 'id':
             case 'members':
                 continue;
             case 'name':
                 $name = "My Test Group " . uniqid();
                 $xml['name'] = $name;
                 break;
             case 'description':
                 $description = "This is a test description " . uniqid();
                 $xml->{$key} = $description;
                 break;
             case 'url':
                 $urlField = "http://example.com/" . uniqid();
                 $xml->{$key} = $urlField;
                 break;
             default:
                 $xml[$key] = $val;
         }
     }
     $xml = trim(preg_replace('/^<\\?xml.+\\n/', "", $xml->asXML()));
     $response = API::put($url, $xml, array("Content-Type: text/xml"), array("username" => self::$config['rootUsername'], "password" => self::$config['rootPassword']));
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $xml->registerXPathNamespace('zxfer', 'http://zotero.org/ns/transfer');
     $group = $xml->xpath('//atom:entry/atom:content/zxfer:group');
     $this->assertCount(1, $group);
     $this->assertEquals($name, $group[0]['name']);
     $response = API::userGet(self::$config['userID'], "groups?format=versions&key=" . self::$config['apiKey']);
     $this->assert200($response);
     $json = json_decode($response->getBody());
     $newVersion = $json->{$groupID};
     $this->assertNotEquals($version, $newVersion);
     // Check ETag header on individual group request
     $response = API::groupGet($groupID, "?content=json&key=" . self::$config['apiKey']);
     $this->assert200($response);
     $this->assertEquals($newVersion, $response->getHeader('Last-Modified-Version'));
     $json = json_decode(API::getContentFromResponse($response));
     $this->assertEquals($name, $json->name);
     $this->assertEquals($description, $json->description);
     $this->assertEquals($urlField, $json->url);
 }
Beispiel #20
0
 private function _testTagsSince($param)
 {
     $tags1 = array("a", "aa", "b");
     $tags2 = array("b", "c", "cc");
     $data1 = API::createItem("book", array("tags" => array_map(function ($tag) {
         return array("tag" => $tag);
     }, $tags1)), $this, 'jsonData');
     $data2 = API::createItem("book", array("tags" => array_map(function ($tag) {
         return array("tag" => $tag);
     }, $tags2)), $this, 'jsonData');
     // Only newly added tags should be included in 'since',
     // not previously added tags or tags added to items
     $response = API::userGet(self::$config['userID'], "tags?{$param}=" . $data1['version']);
     $this->assertNumResults(2, $response);
     // Deleting an item shouldn't update associated tag versions
     $response = API::userDelete(self::$config['userID'], "items/{$data1['key']}", array("If-Unmodified-Since-Version: " . $data1['version']));
     $this->assert204($response);
     $response = API::userGet(self::$config['userID'], "tags?{$param}=" . $data1['version']);
     $this->assertNumResults(2, $response);
     $libraryVersion = $response->getHeader("Last-Modified-Version");
     $response = API::userGet(self::$config['userID'], "tags?{$param}=" . $libraryVersion);
     $this->assertNumResults(0, $response);
 }
 /**
  * Revoke access for a group from an API key that has access to all groups
  */
 public function testKeyRemoveLibraryFromAllGroupsNotification()
 {
     API::useAPIKey("");
     $removedGroup = self::$config['ownedPrivateGroupID'];
     $json = $this->createKeyWithAllGroupAccess(self::$config['userID']);
     $apiKey = $json['key'];
     try {
         // Get list of available groups
         API::useAPIKey($apiKey);
         $response = API::userGet(self::$config['userID'], 'groups');
         $groupIDs = array_map(function ($group) {
             return $group['id'];
         }, API::getJSONFromResponse($response));
         // Remove one group, and replace access array with new set
         $groupIDs = array_diff($groupIDs, [$removedGroup]);
         unset($json['access']['groups']['all']);
         foreach ($groupIDs as $groupID) {
             $json['access']['groups'][$groupID]['library'] = true;
         }
         // Post new JSON, which should trigger topicRemoved for the removed group
         API::useAPIKey("");
         $response = API::superPut("keys/{$apiKey}", json_encode($json));
         $this->assert200($response);
         $this->assertCountNotifications(1, $response);
         foreach ($groupIDs as $groupID) {
             $this->assertHasNotification(['event' => 'topicRemoved', 'apiKey' => $apiKey, 'topic' => '/groups/' . $removedGroup], $response);
         }
     } finally {
         $response = API::superDelete("keys/{$apiKey}");
     }
 }