1
0
mirror of https://github.com/guzzle/guzzle.git synced 2025-02-25 02:22:57 +01:00

[Service] Adding Model classes that can be used to make it easier to consume the models generated by service description powered OperationCommands.

This commit is contained in:
Michael Dowling 2012-09-29 23:53:43 -07:00
parent 32080ea36d
commit 0f57d6ac22
6 changed files with 140 additions and 2 deletions

View File

@ -29,6 +29,8 @@ abstract class AbstractCommand extends Collection implements CommandInterface
const DISABLE_VALIDATION = 'command.disable_validation';
// Option used to override how a command result will be formatted
const RESPONSE_PROCESSING = 'command.response_processing';
// Options to specify that response models should be a raw array rather than a model object
const RESPONSE_MODEL_ARRAY = 'command.response_model_array';
// Different response types that commands can use
const TYPE_RAW = 'raw';
const TYPE_NATIVE = 'native';

View File

@ -10,6 +10,7 @@ use Guzzle\Service\Command\LocationVisitor\Response\BodyVisitor;
use Guzzle\Service\Command\LocationVisitor\Response\JsonVisitor;
use Guzzle\Service\Command\LocationVisitor\Response\XmlVisitor;
use Guzzle\Service\Command\LocationVisitor\Response\ResponseVisitorInterface;
use Guzzle\Service\Resource\Model;
/**
* Response parser that attempts to marshal responses into an associative array based on models in a service description
@ -112,6 +113,11 @@ class OperationResponseParser extends DefaultResponseParser
$visitor->after($command);
}
// Use a model object if it is not disabled on the command
if (!$command->get(AbstractCommand::RESPONSE_MODEL_ARRAY)) {
$result = new Model($result, $model);
}
return $result;
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Guzzle\Service\Resource;
use Guzzle\Common\Collection;
use Guzzle\Service\Description\Parameter;
/**
* Default model created when commands create service description model responses
*/
class Model extends Collection
{
/**
* @var Parameter Structure of the model
*/
protected $structure;
/**
* @param array $data Data contained by the model
* @param Parameter $structure The structure of the model
*/
public function __construct(array $data, Parameter $structure)
{
$this->data = $data;
$this->structure = $structure;
}
/**
* Get the structure of the model
*
* @return Parameter
*/
public function getStructure()
{
return $this->structure;
}
/**
* Gets a value from the model using an array path (e.g. foo/baz/bar would retrieve bar from two nested arrays)
*
* @param string $path Path to traverse and retrieve a value from
* @param string $separator Character used to add depth to the search
*
* @return mixed|null
*/
public function getPath($path, $separator = '/')
{
$parts = explode($separator, $path);
$data = &$this->data;
// Using an iterative approach rather than recursion for speed
while ($part = array_shift($parts)) {
// Return null if this path doesn't exist or if there's more depth and the value is not an array
if (!isset($data[$part]) || ($parts && !is_array($data[$part]))) {
return null;
}
$data = &$data[$part];
}
return $data;
}
/**
* Convert the model to an array
*
* @return array
*/
public function toArray()
{
return $this->data;
}
}

View File

@ -9,6 +9,7 @@ use Guzzle\Service\Command\OperationCommand;
use Guzzle\Service\Description\Operation;
use Guzzle\Service\Description\ServiceDescription;
use Guzzle\Service\Command\DefaultRequestSerializer;
use Guzzle\Service\Resource\Model;
/**
* @covers Guzzle\Service\Command\OperationCommand
@ -66,9 +67,9 @@ class OperationCommandTest extends \Guzzle\Tests\GuzzleTestCase
$request->setResponse(new Response(200, array(
'Content-Type' => 'application/xml'
), '<Foo><Baz>Bar</Baz></Foo>'), true);
$this->assertEquals(array(
$this->assertEquals(new Model(array(
'Baz' => 'Bar'
), $op->execute());
), $description->getModel('bar')), $op->execute());
}
public function testAllowsRawResponses()

View File

@ -4,13 +4,16 @@ namespace Guzzle\Tests\Service\Command;
use Guzzle\Http\Message\Response;
use Guzzle\Service\Client;
use Guzzle\Service\Command\AbstractCommand;
use Guzzle\Service\Command\OperationResponseParser;
use Guzzle\Service\Command\OperationCommand;
use Guzzle\Service\Description\Operation;
use Guzzle\Service\Description\Parameter;
use Guzzle\Service\Description\ServiceDescription;
use Guzzle\Service\Command\LocationVisitor\Response\StatusCodeVisitor;
use Guzzle\Service\Command\LocationVisitor\Response\ReasonPhraseVisitor;
use Guzzle\Service\Command\LocationVisitor\Response\BodyVisitor;
use Guzzle\Service\Resource\Model;
/**
* @covers Guzzle\Service\Command\OperationResponseParser
@ -42,7 +45,20 @@ class OperationResponseParserTest extends \Guzzle\Tests\GuzzleTestCase
$op = new OperationCommand(array(), $this->getDescription()->getOperation('test'));
$op->setResponseParser($parser)->setClient(new Client());
$op->prepare()->setResponse(new Response(200, array('Content-Type' => 'application/xml'), '<F><B>C</B></F>'), true);
$this->assertInstanceOf('Guzzle\Service\Resource\Model', $op->execute());
$this->assertEquals('C', $op->getResult()->get('B'));
}
public function testUsesRawArraysWhenInstructed()
{
$parser = new OperationResponseParser();
$op = new OperationCommand(array(), $this->getDescription()->getOperation('test'));
$op->setResponseParser($parser)->setClient(new Client());
$op->prepare()->setResponse(new Response(200, array('Content-Type' => 'application/xml'), '<F><B>C</B></F>'), true);
$op->set(AbstractCommand::RESPONSE_MODEL_ARRAY, true);
$this->assertInternalType('array', $op->execute());
$result = $op->getResult();
$this->assertEquals('C', $result['B']);
}
public function testVisitsLocations()

View File

@ -0,0 +1,41 @@
<?php
namespace Guzzle\Tests\Service\Resource;
use Guzzle\Service\Resource\Model;
use Guzzle\Service\Description\Parameter;
/**
* @covers Guzzle\Service\Resource\Model
*/
class ModelTest extends \Guzzle\Tests\GuzzleTestCase
{
public function testOwnsStructure()
{
$param = new Parameter(array('type' => 'object'));
$model = new Model(array('foo' => 'bar'), $param);
$this->assertSame($param, $model->getStructure());
$this->assertEquals('bar', $model->get('foo'));
$this->assertEquals('bar', $model['foo']);
}
public function testRetrievesNestedKeysUsingPath()
{
$data = array(
'foo' => 'bar',
'baz' => array(
'mesa' => array(
'jar' => 'jar'
)
)
);
$param = new Parameter(array('type' => 'object'));
$model = new Model($data, $param);
$this->assertSame($param, $model->getStructure());
$this->assertEquals('bar', $model->getPath('foo'));
$this->assertEquals('jar', $model->getPath('baz/mesa/jar'));
$this->assertNull($model->getPath('wewewf'));
$this->assertNull($model->getPath('baz/mesa/jar/jar'));
$this->assertSame($data, $model->toArray());
}
}