Skip to content

Commit

Permalink
First full implementation of WindowsAzureTableStorage. No functional …
Browse files Browse the repository at this point in the history
…tests yet and implementations for the authentication schema are missing.
  • Loading branch information
beberlei committed Mar 26, 2012
1 parent 6dbed9c commit aaa8d93
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 1 deletion.
66 changes: 65 additions & 1 deletion lib/Doctrine/KeyValueStore/Storage/WindowsAzureTableStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private function request($method, $url, $xml, $headers)
$authorizationParts = explode(":" , $authorizationHeader, 2);
$headers['Content-Length'] = strlen($xml);
$headers[$authorizationParts[0]] = ltrim($authorizationParts[1]);
$response = $this->client->request($method, $url, $xml, $headers);
return $this->client->request($method, $url, $xml, $headers);
}

private function serializeProperties($propertiesNode, array $data)
Expand Down Expand Up @@ -249,13 +249,77 @@ public function update($className, $key, array $data)

public function delete($className, $key)
{
$headers = array(
'Content-Type' => 'application/atom+xml',
'x-ms-date' => $this->now(),
'Content-Length' => 0,
'If-Match' => '*',
);

// TODO: This sucks
$tableName = $className;
$keys = array_values($key);
$url = $this->baseUrl . '/' . $tableName ."(PartitionKey='" . $keys[0] . "', RowKey='" . $keys[1] . "')";

$this->request('DELETE', $url, '', $headers);
}

public function find($className, $key)
{
$headers = array(
'Content-Type' => 'application/atom+xml',
'x-ms-date' => $this->now(),
'Content-Length' => 0,
);

// TODO: This sucks
$tableName = $className;
$keys = array_values($key);
$url = $this->baseUrl . '/' . $tableName ."(PartitionKey='" . $keys[0] . "', RowKey='" . $keys[1] . "')";

$response = $this->request('GET', $url, '', $headers);

if ($response->getStatusCode() != 200) {
// Todo: do stuff
}

$dom = new \DomDocument('1.0', 'UTF-8');
$dom->loadXML($response->getBody());

$xpath = new \DOMXpath($dom);
$xpath->registerNamespace('d', 'http://schemas.microsoft.com/ado/2007/08/dataservices');
$xpath->registerNamespace('m', 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$properties = $xpath->evaluate('/atom:entry/atom:content/m:properties/d:*');

$data = array();
list($partitionKey, $rowKey) = array_keys($key);
foreach ($properties as $property) {
$name = substr($property->tagName, 2);
if ($name == "PartitionKey") {
$name = $partitionKey;
} else if ($name == "RowKey") {
$name = $rowKey;
}

$value = $property->nodeValue;
if ($property->hasAttributeNS(self::METADATA_NS, 'null')) {
$value = null;
} else if ($property->hasAttributeNS(self::METADATA_NS, 'type')) {
$type = $property->getAttributeNS(self::METADATA_NS, 'type');
switch ($type) {
case self::TYPE_BOOLEAN:
$value = ($value == 1);
break;
case self::TYPE_DATETIME:
$value = new \DateTime(substr($value, 0, 19), new \DateTimeZone('UTC'));
break;
}
}
$data[$name] = $value;
}

return $data;
}

public function getName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,43 @@ public function testUpdateCompositeKey()
$this->storage->update('stdClass', $key, $data);
}

public function testDeleteCompositeKey()
{
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
$this->markTestSkipped("Composite keys need to be supported for this test to run.");
}

$key = array('dist' => 'foo', 'range' => 100);

$this->mockDeleteCompositeKey($key);
$this->storage->delete('stdClass', $key);
}

public function testFindCompositeKey()
{
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
$this->markTestSkipped("Composite keys need to be supported for this test to run.");
}

$key = array('dist' => 'foo', 'range' => 100);

$this->mockFindCompositeKey($key);
$data = $this->storage->find('stdClass', $key);

$this->assertEquals(array(
'dist' => 'foo',
'range' => '100',
'timestamp' => new \DateTime('2008-09-18 23:46:19', new \DateTimeZone("UTC")),
'name' => 'Test',
'value' => 23,
'amount' => 200.23,
'bool' => true,
), $data);
}

abstract function mockInsertCompositeKey($key, $data);
abstract function mockUpdateCompositeKey($key, $data);
abstract function mockDeleteCompositeKey($key);
abstract function mockFindCompositeKey($key);
}

Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,73 @@ public function mockUpdateCompositeKey($key, $data)
);

}

public function mockDeleteCompositeKey($key)
{
$expectedHeaders = array(
'Content-Type' => 'application/atom+xml',
'Content-Length' => 0,
'x-ms-date' => '2012-03-26T10:10:10.0000000Z',
'If-Match' => '*',
'Authorization' => 'SharedKeyLite testaccount1:uay+rilMVayH/SVI8X+a3fL8k/NxCnIePdyZSkqvydM=',
);

$this->client->expects($this->at(0))
->method('request')
->with(
$this->equalTo('DELETE'),
$this->equalTo("https://teststore.table.core.windows.net/stdClass(PartitionKey='foo', RowKey='100')"),
$this->equalTo(''),
$this->equalTo($expectedHeaders)
)->will($this->returnValue(new Response(204, "", array())));
}

public function mockFindCompositeKey($key)
{
$expectedHeaders = array(
'Content-Type' => 'application/atom+xml',
'Content-Length' => 0,
'x-ms-date' => '2012-03-26T10:10:10.0000000Z',
'Authorization' => 'SharedKeyLite testaccount1:uay+rilMVayH/SVI8X+a3fL8k/NxCnIePdyZSkqvydM=',
);

$this->client->expects($this->at(0))
->method('request')
->with(
$this->equalTo('GET'),
$this->equalTo("https://teststore.table.core.windows.net/stdClass(PartitionKey='foo', RowKey='100')"),
$this->equalTo(''),
$this->equalTo($expectedHeaders)
)->will($this->returnValue(
new Response(201, <<<XML
<?xml version="1.0" ?>
<entry xml:base="http://myaccount.table.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2008-09-18T23%3A46%3A19.4277424Z'&quot;" xmlns="http://www.w3.org/2005/Atom">
<id>http://myaccount.table.core.windows.net/mytable(PartitionKey='foo',RowKey='100')</id>
<title type="text"></title>
<updated>2008-09-18T23:46:19.3857256Z</updated>
<author>
<name />
</author>
<link rel="edit" title="stdClass" href="stdClass(PartitionKey='foo',RowKey='100')" />
<category term="myaccount.Tables" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:PartitionKey>foo</d:PartitionKey>
<d:RowKey>100</d:RowKey>
<d:timestamp m:type="Edm.DateTime">2008-09-18T23:46:19.000000Z</d:timestamp>
<d:name>Test</d:name>
<d:value m:type="Edm.Int32">23</d:value>
<d:amount m:type="Edm.Double">200.23</d:amount>
<d:bool m:type="Edm.Boolean">1</d:bool>
</m:properties>
</content>
</entry>
XML
, array()

))
);

}
}

0 comments on commit aaa8d93

Please sign in to comment.