public function testModifyItemNotification()
 {
     $json = API::createItem("book", false, $this, 'jsonData');
     $json['title'] = 'test';
     $response = API::userPut(self::$config['userID'], "items/{$json['key']}", json_encode($json));
     $this->assertCountNotifications(1, $response);
     $this->assertHasNotification(['event' => 'topicUpdated', 'topic' => '/users/' . self::$config['userID']], $response);
 }
Beispiel #2
0
 /**
  * @depends testNewSearch
  */
 public function testModifySearch($data)
 {
     $key = $data['key'];
     $version = $data['version'];
     // Remove one search condition
     array_shift($data['conditions']);
     $name = $data['name'];
     $conditions = $data['conditions'];
     $response = API::userPut(self::$config['userID'], "searches/{$key}", json_encode($data), array("Content-Type: application/json", "If-Unmodified-Since-Version: {$version}"));
     $this->assert204($response);
     $data = API::getSearch($key, $this, 'json')['data'];
     $this->assertEquals($name, (string) $data['name']);
     $this->assertInternalType('array', $data['conditions']);
     $this->assertCount(sizeOf($conditions), $data['conditions']);
     foreach ($conditions as $i => $condition) {
         foreach ($condition as $key => $val) {
             $this->assertEquals($val, $data['conditions'][$i][$key]);
         }
     }
 }
Beispiel #3
0
 public function testCreatorSummaryAtom()
 {
     $xml = API::createItem("book", array("creators" => array(array("creatorType" => "author", "name" => "Test"))), $this, 'atom');
     $data = API::parseDataFromAtomEntry($xml);
     $itemKey = $data['key'];
     $json = json_decode($data['content'], true);
     $creatorSummary = (string) array_shift($xml->xpath('//atom:entry/zapi:creatorSummary'));
     $this->assertEquals("Test", $creatorSummary);
     $json['creators'][] = array("creatorType" => "author", "firstName" => "Alice", "lastName" => "Foo");
     $response = API::userPut(self::$config['userID'], "items/{$itemKey}", json_encode($json));
     $this->assert204($response);
     $xml = API::getItemXML($itemKey);
     $creatorSummary = (string) array_shift($xml->xpath('//atom:entry/zapi:creatorSummary'));
     $this->assertEquals("Test and Foo", $creatorSummary);
     $data = API::parseDataFromAtomEntry($xml);
     $json = json_decode($data['content'], true);
     $json['creators'][] = array("creatorType" => "author", "firstName" => "Bob", "lastName" => "Bar");
     $response = API::userPut(self::$config['userID'], "items/{$itemKey}", json_encode($json));
     $this->assert204($response);
     $xml = API::getItemXML($itemKey);
     $creatorSummary = (string) array_shift($xml->xpath('//atom:entry/zapi:creatorSummary'));
     $this->assertEquals("Test et al.", $creatorSummary);
 }
Beispiel #4
0
 private function _testUploadUnmodified($objectType)
 {
     $objectTypePlural = API::getPluralObjectType($objectType);
     switch ($objectType) {
         case 'collection':
             $data = API::createCollection("Name", false, $this, 'jsonData');
             break;
         case 'item':
             $data = API::createItem("book", array("title" => "Title"), $this, 'jsonData');
             break;
         case 'search':
             $data = API::createSearch("Name", 'default', $this, 'jsonData');
             break;
     }
     $version = $data['version'];
     $this->assertNotEquals(0, $version);
     $response = API::userPut(self::$config['userID'], "{$objectTypePlural}/{$data['key']}", json_encode($data));
     $this->assert204($response);
     $this->assertEquals($version, $response->getHeader("Last-Modified-Version"));
     switch ($objectType) {
         case 'collection':
             $json = API::getCollection($data['key'], $this, 'json');
             break;
         case 'item':
             $json = API::getItem($data['key'], $this, 'json');
             break;
         case 'search':
             $json = API::getSearch($data['key'], $this, 'json');
             break;
     }
     $this->assertEquals($version, $json['version']);
 }
Beispiel #5
0
	public function testParentItem() {
		$json = API::createItem("book", false, $this, 'jsonData');
		$parentKey = $json['key'];
		$parentVersion = $json['version'];
		
		$json = API::createAttachmentItem("linked_url", [], $parentKey, $this, 'jsonData');
		$childKey = $json['key'];
		$childVersion = $json['version'];
		
		$this->assertArrayHasKey('parentItem', $json);
		$this->assertEquals($parentKey, $json['parentItem']);
		
		// Remove the parent, making the child a standalone attachment
		unset($json['parentItem']);
		
		$response = API::userPut(
			self::$config['userID'],
			"items/$childKey",
			json_encode($json),
			array("If-Unmodified-Since-Version: " . $childVersion)
		);
		$this->assert204($response);
		
		$json = API::getItem($childKey, $this, 'json')['data'];
		$this->assertArrayNotHasKey('parentItem', $json);
	}
Beispiel #6
0
	public function testAddFileClientV4Zip() {
		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 #7
0
 public function testDeleteCollectionRelation()
 {
     $relations = array("owl:sameAs" => "http://zotero.org/groups/1/collections/AAAAAAAA");
     $data = API::createCollection("Test", array("relations" => $relations), $this, 'jsonData');
     // Remove all relations
     $data['relations'] = new \stdClass();
     unset($relations['owl:sameAs']);
     $response = API::userPut(self::$config['userID'], "collections/{$data['key']}", json_encode($data));
     $this->assert204($response);
     // Make sure it's gone
     $data = API::getCollection($data['key'], $this, 'json')['data'];
     $this->assertCount(sizeOf($relations), $data['relations']);
     foreach ($relations as $predicate => $object) {
         $this->assertEquals($object, $data['relations'][$predicate]);
     }
 }
Beispiel #8
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 #9
0
 public function testCollectionChildItemError()
 {
     $collectionKey = API::createCollection('Test', false, $this, 'key');
     $key = API::createItem("book", array(), $this, 'key');
     $json = API::createNoteItem("Test Note", $key, $this, 'jsonData');
     $json['collections'] = [$collectionKey];
     $response = API::userPut(self::$config['userID'], "items/{$json['key']}", json_encode($json), array("Content-Type: application/json"));
     $this->assert400($response);
     $this->assertEquals("Child items cannot be assigned to collections", $response->getBody());
 }
Beispiel #10
0
 private function _testResponseJSONPut($objectType)
 {
     API::userClear(self::$config['userID']);
     $objectTypePlural = API::getPluralObjectType($objectType);
     switch ($objectType) {
         case 'collection':
             $json1 = ["name" => "Test 1"];
             break;
         case 'item':
             $json1 = API::getItemTemplate('book');
             $json1->title = "Test 1";
             break;
         case 'search':
             $conditions = array(array('condition' => 'title', 'operator' => 'contains', 'value' => 'value'));
             $json1 = ["name" => "Test 1", "conditions" => $conditions];
             break;
     }
     $response = API::userPost(self::$config['userID'], $objectTypePlural, json_encode([$json1]), array("Content-Type: application/json"));
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $this->assert200ForObject($response, false, 0);
     $objectKey = $json['success'][0];
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}/{$objectKey}");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     switch ($objectType) {
         case 'item':
             $json['data']['title'] = "Test 2";
             break;
         case 'collection':
         case 'search':
             $json['data']['name'] = "Test 2";
             break;
     }
     $response = API::userPut(self::$config['userID'], "{$objectTypePlural}/{$objectKey}", json_encode($json), array("Content-Type: application/json"));
     $this->assert204($response);
     // Check
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}/{$objectKey}");
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     switch ($objectTypePlural) {
         case 'item':
             $this->assertEquals("Test 2", $json['data']['title']);
             break;
         case 'collection':
         case 'search':
             $this->assertEquals("Test 2", $json['data']['name']);
             break;
     }
 }
Beispiel #11
0
 public function testOverlongSetting()
 {
     $settingKey = "tagColors";
     $value = array(array("name" => $this->content = str_repeat("abcdefghij", 1001), "color" => "#990000"));
     $json = array("value" => $value, "version" => 0);
     $response = API::userPut(self::$config['userID'], "settings/{$settingKey}", json_encode($json), array("Content-Type: application/json"));
     $this->assert400($response, "'value' cannot be longer than 1000 characters");
 }
Beispiel #12
0
 public function testKeyCreateAndModifyWithCredentials()
 {
     API::useAPIKey("");
     $name = "Test " . uniqid();
     // Can't create on /users/:userID/keys with credentials
     $response = API::userPost(self::$config['userID'], 'keys', json_encode(['username' => self::$config['username'], 'password' => self::$config['password'], 'name' => $name, 'access' => ['user' => ['library' => true]]]));
     $this->assert403($response);
     // Create with credentials
     $response = API::post('keys', json_encode(['username' => self::$config['username'], 'password' => self::$config['password'], 'name' => $name, 'access' => ['user' => ['library' => true]]]), [], []);
     $this->assert201($response);
     $json = API::getJSONFromResponse($response);
     $key = $json['key'];
     $this->assertEquals($json['userID'], self::$config['userID']);
     $this->assertEquals($json['name'], $name);
     $this->assertEquals(['user' => ['library' => true, 'files' => true]], $json['access']);
     $name = "Test " . uniqid();
     // Can't modify on /users/:userID/keys/:key with credentials
     $response = API::userPut(self::$config['userID'], "keys/{$key}", json_encode(['username' => self::$config['username'], 'password' => self::$config['password'], 'name' => $name, 'access' => ['user' => ['library' => true]]]));
     $this->assert403($response);
     // Modify with credentials
     $response = API::put("keys/{$key}", json_encode(['username' => self::$config['username'], 'password' => self::$config['password'], 'name' => $name, 'access' => ['user' => ['library' => true]]]));
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $key = $json['key'];
     $this->assertEquals($json['name'], $name);
     $response = API::userDelete(self::$config['userID'], "keys/{$key}");
     $this->assert204($response);
 }