Permalink
Browse files

[Service] Fixing headers set using an array on commands via the const…

…ructor

Removing special handling of ClosureCommand
Throwing an exception when required parameters are missing from a dynamic command
Pass ApiCommand objects to a ClosureCommand in the second argument of the constructor, not in the api_command parameter key
Adding Guzzle\Service\Command\DynamicCommand that will prepare HTTP requests based on an API command. Extend this class for advanced response processing for API commands.
Making DynamicCommand the default command for ApiCommands
Removing the old DynamicCommandFactory and replacing with a simpler ApiCommandFactory
  • Loading branch information...
1 parent 466c28e commit 2986444944ae769e967c6b7c3666fdd6e4d35346 @mtdowling mtdowling committed Jan 22, 2012
@@ -51,12 +51,12 @@ public function __construct($parameters = null, ApiCommand $apiCommand = null)
if ($apiCommand) {
$this->apiCommand = $apiCommand;
Inspector::getInstance()->validateConfig($apiCommand->getParams(), $this, false);
- } else if (!($this instanceof ClosureCommand)) {
+ } else {
Inspector::getInstance()->validateClass(get_class($this), $this, false);
}
if (!$this->get('headers') instanceof Collection) {
- $this->set('headers', new Collection());
+ $this->set('headers', new Collection((array) $this->get('headers')));
}
$this->init();
@@ -216,13 +216,11 @@ public function prepare()
throw new \RuntimeException('A Client object must be associated with the command before it can be prepared.');
}
- // Fail on missing required arguments when it is not a ClosureCommand
- if (!($this instanceof ClosureCommand)) {
- if ($this->apiCommand) {
- Inspector::getInstance()->validateConfig($this->apiCommand->getParams(), $this);
- } else {
- Inspector::getInstance()->validateClass(get_class($this), $this, true);
- }
+ // Fail on missing required arguments
+ if ($this->apiCommand) {
+ Inspector::getInstance()->validateConfig($this->apiCommand->getParams(), $this, true);
+ } else {
+ Inspector::getInstance()->validateClass(get_class($this), $this, true);
}
$this->build();
@@ -22,10 +22,6 @@ protected function init()
if (!$this->get('closure')) {
throw new \InvalidArgumentException('A closure must be passed in the parameters array');
}
-
- if (!$this->get('closure_api')) {
- throw new \InvalidArgumentException('A closure_api value must be passed in the parameters array');
- }
}
/**
@@ -36,7 +32,7 @@ protected function init()
protected function build()
{
$closure = $this->get('closure');
- $this->request = $closure($this, $this->get('closure_api'));
+ $this->request = $closure($this, $this->apiCommand);
if (!$this->request || !$this->request instanceof RequestInterface) {
throw new \UnexpectedValueException('Closure command did not return a RequestInterface object');
@@ -0,0 +1,98 @@
+<?php
+
+namespace Guzzle\Service\Command;
+
+use Guzzle\Guzzle;
+use Guzzle\Http\EntityBody;
+use Guzzle\Http\Url;
+use Guzzle\Service\Inspector;
+
+/**
+ * A command that creates requests based on ApiCommands
+ */
+class DynamicCommand extends AbstractCommand
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function init()
+ {
+ if (!$this->apiCommand) {
+ throw new \InvalidArgumentException('An API command must be passed');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function build()
+ {
+ // Get the path values and use the client config settings
+ $pathValues = $this->getClient()->getConfig();
+ $foundPath = false;
+ foreach ($this->apiCommand->getParams() as $name => $arg) {
+ if ($arg->get('location') == 'path') {
+ $pathValues->set($name, $arg->get('prepend') . $this->get($name) . $arg->get('append'));
+ $foundPath = true;
+ }
+ }
+
+ // Build a custom URL if there are path values
+ if ($foundPath) {
+ $path = str_replace('//', '', Guzzle::inject($this->apiCommand->getPath(), $pathValues));
+ } else {
+ $path = $this->apiCommand->getPath();
+ }
+
+ if (!$path) {
+ $url = $this->getClient()->getBaseUrl();
+ } else {
+ $url = Url::factory($this->getClient()->getBaseUrl());
+ $url->combine($path);
+ $url = (string) $url;
+ }
+
+ // Inject path and base_url values into the URL
+ $this->request = $this->getClient()->createRequest($this->apiCommand->getMethod(), $url);
+
+ // Add arguments to the request using the location attribute
+ foreach ($this->apiCommand->getParams() as $name => $arg) {
+
+ if ($this->get($name)) {
+
+ // Check that a location is set
+ $location = $arg->get('location') ?: 'query';
+
+ if ($location == 'path' || $location == 'data') {
+ continue;
+ }
+
+ if ($location) {
+
+ // Create the value based on prepend and append settings
+ $value = $arg->get('prepend') . $this->get($name) . $arg->get('append');
+
+ // Determine the location and key setting location[:key]
+ $parts = explode(':', $location);
+ $place = $parts[0];
+
+ // If a key is specified (using location:key), use it
+ $key = isset($parts[1]) ? $parts[1] : $name;
+
+ // Add the parameter to the request
+ switch ($place) {
+ case 'body':
+ $this->request->setBody(EntityBody::factory($value));
+ break;
+ case 'header':
+ $this->request->setHeader($key, $value);
+ break;
+ case 'query':
+ $this->request->getQuery()->set($key, $value);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
@@ -24,7 +24,7 @@ class ApiCommand
*
* @param array $config Array of configuration data using the following keys
* string name Name of the command
- * tring doc Method documentation
+ * string doc Method documentation
* string method HTTP method of the command
* string path (optional) Path routing information of the command to include in the path
* string class (optional) Concrete class that implements this command
@@ -52,7 +52,7 @@ public function __construct(array $config)
$this->config['doc'] = isset($config['doc']) ? trim($config['doc']) : '';
$this->config['method'] = isset($config['method']) ? trim($config['method']) : '';
$this->config['path'] = isset($config['path']) ? trim($config['path']) : '';
- $this->config['class'] = isset($config['class']) ? trim($config['class']) : 'Guzzle\\Service\\Command\\ClosureCommand';
+ $this->config['class'] = isset($config['class']) ? trim($config['class']) : 'Guzzle\\Service\\Command\\DynamicCommand';
if (isset($config['params']) && is_array($config['params'])) {
foreach ($config['params'] as $paramName => $param) {
@@ -0,0 +1,19 @@
+<?php
+
+namespace Guzzle\Service\Description;
+
+/**
+ * Build Guzzle commands based on an ApiCommand object
+ */
+class ApiCommandFactory implements CommandFactoryInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function createCommand(ApiCommand $command, array $args)
+ {
+ $class = $command->getConcreteClass();
+
+ return new $class($args, $command);
+ }
+}
@@ -1,113 +0,0 @@
-<?php
-
-namespace Guzzle\Service\Description;
-
-use Guzzle\Guzzle;
-use Guzzle\Common\Collection;
-use Guzzle\Service\Inspector;
-use Guzzle\Http\Message\RequestFactory;
-use Guzzle\Http\EntityBody;
-use Guzzle\Http\Url;
-use Guzzle\Service\Command\ClosureCommand;
-
-/**
- * Build Guzzle commands based on a service document using dynamically created
- * commands to implement a service document's specifications.
- */
-class DynamicCommandFactory implements CommandFactoryInterface
-{
- /**
- * {@inheritdoc}
- */
- public function createCommand(ApiCommand $command, array $args)
- {
- if ($command->getConcreteClass() != 'Guzzle\\Service\\Command\\ClosureCommand') {
- $class = $command->getConcreteClass();
-
- return new $class($args, $command);
- }
-
- // Build the command based on the service doc and supplied arguments
- return new ClosureCommand(array_merge($args, array(
-
- // Generate a dynamically created command using a closure to
- // prepare the command
- 'closure' => function(ClosureCommand $that, ApiCommand $api) {
-
- // Validate the command with the config options
- Inspector::getInstance()->validateConfig($api->getParams(), $that);
-
- // Get the path values and use the client config settings
- $pathValues = $that->getClient()->getConfig();
- $foundPath = false;
- foreach ($api->getParams() as $name => $arg) {
- if ($arg->get('location') == 'path') {
- $pathValues->set($name, $arg->get('prepend') . $that->get($name) . $arg->get('append'));
- $foundPath = true;
- }
- }
-
- // Build a custom URL if there are path values
- if ($foundPath) {
- $path = str_replace('//', '', Guzzle::inject($api->getPath(), $pathValues));
- } else {
- $path = $api->getPath();
- }
-
- if (!$path) {
- $url = $that->getClient()->getBaseUrl();
- } else {
- $url = Url::factory($that->getClient()->getBaseUrl());
- $url->combine($path);
- $url = (string) $url;
- }
-
- // Inject path and base_url values into the URL
- $request = $that->getClient()->createRequest($api->getMethod(), $url);
-
- // Add arguments to the request using the location attribute
- foreach ($api->getParams() as $name => $arg) {
-
- if ($that->get($name)) {
-
- // Check that a location is set
- $location = $arg->get('location') ?: 'query';
-
- if ($location == 'path' || $location == 'data') {
- continue;
- }
-
- if ($location) {
-
- // Create the value based on prepend and append settings
- $value = $arg->get('prepend') . $that->get($name) . $arg->get('append');
-
- // Determine the location and key setting location[:key]
- $parts = explode(':', $location);
- $place = $parts[0];
-
- // If a key is specified (using location:key), use it
- $key = isset($parts[1]) ? $parts[1] : $name;
-
- // Add the parameter to the request
- switch ($place) {
- case 'body':
- $request->setBody(EntityBody::factory($value));
- break;
- case 'header':
- $request->setHeader($key, $value);
- break;
- case 'query':
- $request->getQuery()->set($key, $value);
- break;
- }
- }
- }
- }
-
- return $request;
- },
- 'closure_api' => $command
- )));
- }
-}
@@ -10,7 +10,7 @@
*/
class ServiceDescription
{
- const DEFAULT_COMMAND_CLASS = 'Guzzle\\Service\\Command\\ClosureCommand';
+ const DEFAULT_COMMAND_CLASS = 'Guzzle\\Service\\Command\\DynamicCommand';
/**
* @var array Array of ApiCommand objects
@@ -73,12 +73,12 @@ public static function factory(array $data)
*
* @param array $commands (optional) Array of {@see ApiCommand} objects
* @param CommandFactoryInterface (optional) Command factory to build
- * dynamic commands. Uses the DynamicCommandFactory by default.
+ * dynamic commands. Uses the ApiCommandFactory by default.
*/
public function __construct(array $commands = array(), CommandFactoryInterface $commandFactory = null)
{
$this->commands = $commands;
- $this->commandFactory = $commandFactory ?: new DynamicCommandFactory();
+ $this->commandFactory = $commandFactory ?: new ApiCommandFactory();
}
/**
@@ -18,18 +18,6 @@ public function testConstructorValidatesClosure()
$c = new ClosureCommand();
}
- /**
- * @covers Guzzle\Service\Command\ClosureCommand
- * @expectedException InvalidArgumentException
- * @expectedExceptionMessage A closure_api value must be passed in the parameters array
- */
- public function testConstructorValidatesClosureApi()
- {
- $c = new ClosureCommand(array(
- 'closure' => function() {}
- ));
- }
-
/**
* @covers Guzzle\Service\Command\ClosureCommand::prepare
* @covers Guzzle\Service\Command\ClosureCommand::build
@@ -41,8 +29,7 @@ public function testExecutesClosure()
$command->set('testing', '123');
$request = RequestFactory::create('GET', 'http://www.test.com/');
return $request;
- },
- 'closure_api' => true
+ }
));
$client = $this->getServiceBuilder()->get('mock');
@@ -61,8 +48,7 @@ public function testMustReturnRequest()
$c = new ClosureCommand(array(
'closure' => function($command, $api) {
return false;
- },
- 'closure_api' => true
+ }
));
$client = $this->getServiceBuilder()->get('mock');
@@ -213,6 +213,20 @@ public function testCommandsAllowsCustomRequestHeaders()
$this->assertEquals('123', $command->getRequest()->getHeaders()->get('test'));
}
+ /**
+ * @covers Guzzle\Service\Command\AbstractCommand::__construct
+ */
+ public function testCommandsAllowsCustomRequestHeadersAsArray()
+ {
+ $command = new MockCommand(array(
+ 'headers' => array(
+ 'Foo' => 'Bar'
+ )
+ ));
+ $this->assertInstanceOf('Guzzle\Common\Collection', $command->getRequestHeaders());
+ $this->assertEquals('Bar', $command->getRequestHeaders()->get('Foo'));
+ }
+
/**
* @covers Guzzle\Service\Command\AbstractCommand
*/
Oops, something went wrong.

0 comments on commit 2986444

Please sign in to comment.