public function testSetItemContent() { $key = API::createItem("book", false, $this, 'key'); $xml = API::createAttachmentItem("imported_url", [], $key, $this, 'atom'); $data = API::parseDataFromAtomEntry($xml); $response = API::userGet(self::$config['userID'], "items/{$data['key']}/fulltext?key=" . self::$config['apiKey']); $this->assert404($response); $this->assertNull($response->getHeader("Last-Modified-Version")); $libraryVersion = API::getLibraryVersion(); $content = "Here is some full-text content"; $pages = 50; // No Content-Type $response = API::userPut(self::$config['userID'], "items/{$data['key']}/fulltext?key=" . self::$config['apiKey'], $content); $this->assert400($response, "Content-Type must be application/json"); // Store content $response = API::userPut(self::$config['userID'], "items/{$data['key']}/fulltext?key=" . self::$config['apiKey'], json_encode(["content" => $content, "indexedPages" => $pages, "totalPages" => $pages, "invalidParam" => "shouldBeIgnored"]), array("Content-Type: application/json")); $this->assert204($response); $contentVersion = $response->getHeader("Last-Modified-Version"); $this->assertGreaterThan($libraryVersion, $contentVersion); // Retrieve it $response = API::userGet(self::$config['userID'], "items/{$data['key']}/fulltext?key=" . self::$config['apiKey']); $this->assert200($response); $this->assertContentType("application/json", $response); $json = json_decode($response->getBody(), true); $this->assertEquals($content, $json['content']); $this->assertArrayHasKey('indexedPages', $json); $this->assertArrayHasKey('totalPages', $json); $this->assertEquals($pages, $json['indexedPages']); $this->assertEquals($pages, $json['totalPages']); $this->assertArrayNotHasKey("indexedChars", $json); $this->assertArrayNotHasKey("invalidParam", $json); $this->assertEquals($contentVersion, $response->getHeader("Last-Modified-Version")); }
public function testSettings() { $settingKey = 'tagColors'; $value = array(array("name" => "_READ", "color" => "#990000")); $xml = Sync::updated(self::$sessionID); $updateKey = (string) $xml['updateKey']; $lastSyncTimestamp = (int) $xml['timestamp']; $libraryVersion = API::getLibraryVersion(); // Create item via sync $data = '<data version="9"><settings><setting libraryID="' . self::$config['libraryID'] . '" name="' . $settingKey . '">' . htmlspecialchars(json_encode($value)) . '</setting></settings></data>'; $response = Sync::upload(self::$sessionID, $updateKey, $data); Sync::waitForUpload(self::$sessionID, $response, $this); // Check via sync $xml = Sync::updated(self::$sessionID, $lastSyncTimestamp); $updateKey = (string) $xml['updateKey']; $lastSyncTimestamp = $xml['timestamp']; $settingXML = $xml->updated[0]->settings[0]->setting[0]; $this->assertEquals(self::$config['libraryID'], (int) $settingXML['libraryID']); $this->assertEquals($settingKey, (string) $settingXML['name']); $this->assertEquals($value, json_decode((string) $settingXML, true)); // Get setting via API and check value $response = API::userGet(self::$config['userID'], "settings/{$settingKey}?key=" . self::$config['apiKey']); $this->assertEquals(200, $response->getStatus()); $json = json_decode($response->getBody(), true); $this->assertNotNull($json); $this->assertEquals($value, $json['value']); $this->assertEquals($libraryVersion + 1, $json['version']); // Delete via sync $xmlstr = '<data version="9">' . '<deleted>' . '<settings>' . '<setting libraryID="' . self::$config['libraryID'] . '" key="' . $settingKey . '"/>' . '</settings>' . '</deleted>' . '</data>'; $response = Sync::upload(self::$sessionID, $updateKey, $xmlstr); $xml = Sync::waitForUpload(self::$sessionID, $response, $this); // Get setting via API and check value $response = API::userGet(self::$config['userID'], "settings/{$settingKey}?key=" . self::$config['apiKey']); $this->assertEquals(404, $response->getStatus()); // Check for missing via sync $xml = Sync::updated(self::$sessionID); $updateKey = (string) $xml['updateKey']; $lastSyncTimestamp = $xml['timestamp']; $this->assertEquals(0, $xml->updated[0]->settings->count()); $this->assertEquals(1, $xml->updated[0]->deleted[0]->settings[0]->setting->count()); $this->assertEquals(self::$config['libraryID'], (int) $xml->updated[0]->deleted[0]->settings[0]->setting[0]['libraryID']); $this->assertEquals($settingKey, (string) $xml->updated[0]->deleted[0]->settings[0]->setting[0]['key']); }
public function testTagDeletePermissions() { API::userClear(self::$config['userID']); $xml = API::createItem('book', array("tags" => array(array("tag" => "A"))), $this); $libraryVersion = API::getLibraryVersion(); API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryWrite', 0); $response = API::userDelete(self::$config['userID'], "tags?tag=A&key=" . self::$config['apiKey']); $this->assert403($response); API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryWrite', 1); $response = API::userDelete(self::$config['userID'], "tags?tag=A&key=" . self::$config['apiKey'], array("If-Unmodified-Since-Version: {$libraryVersion}")); $this->assert204($response); }
public function testRelatedItems() { $itemKey1 = API::createItem("audioRecording", array("relations" => array('owl:sameAs' => 'http://zotero.org/groups/1/items/AAAAAAAA')), null, 'key'); $itemURI1 = 'http://zotero.org/users/' . self::$config['userID'] . '/items/' . $itemKey1; $itemKey2 = API::createItem("interview", array("relations" => array('dc:relation' => $itemURI1)), null, 'key'); $itemURI2 = 'http://zotero.org/users/' . self::$config['userID'] . '/items/' . $itemKey2; $itemKey3 = API::createItem("book", null, null, 'key'); $itemURI3 = 'http://zotero.org/users/' . self::$config['userID'] . '/items/' . $itemKey3; $libraryVersion = API::getLibraryVersion(); // Add related items via sync $xml = Sync::updated(self::$sessionID); $updateKey = $xml['updateKey']; $lastSyncTimestamp = $xml['timestamp']; $itemXML1 = array_shift($xml->updated[0]->items[0]->xpath("item[@key='{$itemKey1}']")); $itemXML2 = array_shift($xml->updated[0]->items[0]->xpath("item[@key='{$itemKey2}']")); $itemXML3 = array_shift($xml->updated[0]->items[0]->xpath("item[@key='{$itemKey3}']")); $itemXML1['libraryID'] = self::$config['libraryID']; $itemXML2['libraryID'] = self::$config['libraryID']; $itemXML3['libraryID'] = self::$config['libraryID']; $itemXML1->related = $itemKey2 . ' ' . $itemKey3; $itemXML2->related = $itemKey1; $itemXML3->related = $itemKey1; $xmlstr = '<data version="9">' . '<items>' . $itemXML1->asXML() . $itemXML2->asXML() . $itemXML3->asXML() . '</items>' . '</data>'; $response = Sync::upload(self::$sessionID, $updateKey, $xmlstr); Sync::waitForUpload(self::$sessionID, $response, $this); // Check via API $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey'] . "&content=json&newer={$libraryVersion}"); $xml = API::getXMLFromResponse($response); // Item 2 already had the relation and shouldn't have been updated $this->assertEquals(2, (int) array_shift($xml->xpath('/atom:feed/zapi:totalResults'))); $itemJSON1 = json_decode(array_shift($xml->xpath("//atom:entry[atom:id='{$itemURI1}']"))->content, 1); $itemJSON3 = json_decode(array_shift($xml->xpath("//atom:entry[atom:id='{$itemURI3}']"))->content, 1); $this->assertInternalType('array', $itemJSON1['relations']['dc:relation']); $this->assertInternalType('string', $itemJSON3['relations']['dc:relation']); $this->assertCount(2, $itemJSON1['relations']['dc:relation']); $this->assertTrue(in_array($itemURI2, $itemJSON1['relations']['dc:relation'])); $this->assertTrue(in_array($itemURI3, $itemJSON1['relations']['dc:relation'])); $this->assertEquals($itemURI1, $itemJSON3['relations']['dc:relation']); }
public function testCollectionChildItemError() { $collectionKey = API::createCollection('Test', false, $this, 'key'); $key = API::createItem("book", array(), $this, 'key'); $xml = API::createNoteItem("Test Note", $key, $this, 'atom'); $data = API::parseDataFromAtomEntry($xml); $json = json_decode($data['content'], true); $json['collections'] = array($collectionKey); $json['relations'] = new stdClass(); $libraryVersion = API::getLibraryVersion(); $response = API::userPut(self::$config['userID'], "items/{$data['key']}?key=" . self::$config['apiKey'], json_encode($json), ["Content-Type: application/json"]); $this->assert400($response); $this->assertEquals("Child items cannot be assigned to collections", $response->getBody()); }
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?key=" . self::$config['apiKey'] . "&content=json&tag=" . implode("%20||%20", array_merge($tags1, $tags2))); $this->assert428($response); // Outdated version header $response = API::userDelete(self::$config['userID'], "tags?key=" . self::$config['apiKey'] . "&content=json&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?key=" . self::$config['apiKey'] . "&content=json&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?key=" . self::$config['apiKey'] . "&content=json&tag=" . implode("%20||%20", array_merge($tags1, $tags2, $tags3))); $this->assert200($response); $this->assertNumResults(1, $response); }
public function testTagDeleteUnmodifiedItemChange() { $key = 'AAAAAAAA'; $xml = Sync::updated(self::$sessionID); $updateKey = (string) $xml['updateKey']; // Create item via sync $data = '<data version="9"><items><item libraryID="' . self::$config['libraryID'] . '" itemType="book" ' . 'dateAdded="2009-03-07 04:53:20" ' . 'dateModified="2009-03-07 04:54:09" ' . 'key="' . $key . '"/></items>' . '<tags><tag libraryID="' . self::$config['libraryID'] . '" name="Test" ' . 'dateAdded="2009-03-07 04:54:56" ' . 'dateModified="2009-03-07 04:54:56" ' . 'key="BBBBBBBB">' . '<items>' . $key . '</items>' . '</tag></tags></data>'; $response = Sync::upload(self::$sessionID, $updateKey, $data); Sync::waitForUpload(self::$sessionID, $response, $this); // Get item via API $response = API::userGet(self::$config['userID'], "items/{$key}?key=" . self::$config['apiKey'] . "&content=json"); $xml = API::getXMLFromResponse($response); $data = API::parseDataFromAtomEntry($xml); $json = json_decode($data['content']); $originalVersion = $data['version']; $this->assertCount(1, $json->tags); $this->assertTrue(isset($json->tags[0]->tag)); $this->assertEquals("Test", $json->tags[0]->tag); // Get item via sync $xml = Sync::updated(self::$sessionID); $this->assertEquals(1, sizeOf($xml->updated->items->item)); $this->assertEquals(1, sizeOf($xml->updated->tags->tag)); $this->assertEquals(1, sizeOf($xml->updated->tags->tag[0]->items)); $lastsync = (int) $xml['timestamp']; usleep(1500000); // Increment the library version, since we're testing the // version below API::createItem('newspaperArticle', false, false, 'key'); $libraryVersion = API::getLibraryVersion(); $xml = Sync::updated(self::$sessionID); $updateKey = (string) $xml['updateKey']; // Delete tag via sync, with unmodified item $data = '<data version="9"><items><item libraryID="' . self::$config['libraryID'] . '" itemType="book" ' . 'dateAdded="2009-03-07 04:53:20" ' . 'dateModified="2009-03-07 04:54:09" ' . 'key="' . $key . '"/></items>' . '<deleted><tags><tag libraryID="' . self::$config['libraryID'] . '" key="BBBBBBBB"/>' . '</tags></deleted></data>'; $response = Sync::upload(self::$sessionID, $updateKey, $data); Sync::waitForUpload(self::$sessionID, $response, $this); // Get item via sync $xml = Sync::updated(self::$sessionID); $this->assertEquals(1, sizeOf(isset($xml->updated->tags->tag))); $this->assertFalse(isset($xml->updated->tags->tag[0]->items)); // Get item version via API $response = API::userGet(self::$config['userID'], "items/{$key}?key=" . self::$config['apiKey'] . "&content=json"); $xml = API::getXMLFromResponse($response); $data = API::parseDataFromAtomEntry($xml); $json = json_decode($data['content']); $this->assertEquals(0, (int) array_shift($xml->xpath('/atom:entry/zapi:numTags'))); $this->assertCount(0, $json->tags); // New item version should be greater than before $this->assertGreaterThan($originalVersion, $data['version']); // And should be one more than previous version $this->assertEquals($libraryVersion + 1, $data['version']); // Only the newspaperArticle should be updated $xml = Sync::updated(self::$sessionID, $lastsync); $this->assertEquals(1, $xml->updated[0]->items[0]->count()); }
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}?key=" . self::$config['apiKey'], 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}?key=" . self::$config['apiKey']); $this->assert404($response); $this->assertEquals($libraryVersion, API::getLibraryVersion()); }