Skip to content

Add URI factory (fix #3) #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ HttpAdapterDiscovery::register('my_adapter', 'My\Adapter\Class');
$adapter = HttpAdapterDiscovery::find();
```


### Message Factory discovery

Two common message factories are bundled with this package. ([Guzzle](https://github.com/guzzle/psr7), [Diactoros](https://github.com/zendframework/zend-diactoros))
Expand All @@ -52,9 +51,23 @@ use Http\Discovery\MessageFactoryDiscovery;

MessageFactoryDiscovery::register('my_factory', 'Psr\Request\Implementation\Class', 'My\Factory\Class');

$adapter = MessageFactoryDiscovery::find();
$factory = MessageFactoryDiscovery::find();
```

### URI Factory discovery

Two common URI factories are bundled with this package: ([Guzzle](https://github.com/guzzle/psr7)
and [Diactoros](https://github.com/zendframework/zend-diactoros)).

``` php
use Http\Discovery\UriFactoryDiscovery;

MessageFactoryDiscovery::register('my_factory', 'Psr\Uri\Implementation\Class', 'My\Factory\Class');

$factory = UriFactoryDiscovery::find();
```



## Testing

Expand Down
2 changes: 2 additions & 0 deletions spec/HttpAdapterDiscoverySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace spec\Http\Discovery;

use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\UriFactoryDiscovery;
use PhpSpec\ObjectBehavior;

class HttpAdapterDiscoverySpec extends ObjectBehavior
Expand Down
8 changes: 4 additions & 4 deletions spec/MessageFactoryDiscoverySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function it_registers_a_factory()
{
$this->reset();

$this->register('guzzle', 'spec\Http\Discovery\TestClass', 'spec\Http\Discovery\Factory');
$this->register('guzzle', 'spec\Http\Discovery\Factory', 'spec\Http\Discovery\TestClass');

$this->find()->shouldHaveType('spec\Http\Discovery\Factory');
}
Expand All @@ -26,7 +26,7 @@ function it_resets_cache_when_a_factory_is_registered()

$firstGuess = $this->find();

$this->register('guzzle', 'spec\Http\Discovery\TestClass', 'spec\Http\Discovery\Factory');
$this->register('guzzle', 'spec\Http\Discovery\Factory', 'spec\Http\Discovery\TestClass');

$this->find()->shouldNotBe($firstGuess);
}
Expand Down Expand Up @@ -65,8 +65,8 @@ function it_throws_an_exception_when_no_message_factory_is_found()

function reset()
{
$this->register('guzzle', 'GuzzleHttp\Psr7\Request', 'Http\Discovery\MessageFactory\GuzzleFactory');
$this->register('diactoros', 'Zend\Diactoros\Request', 'Http\Discovery\MessageFactory\DiactorosFactory');
$this->register('guzzle', 'Http\Discovery\MessageFactory\GuzzleFactory', 'GuzzleHttp\Psr7\Request');
$this->register('diactoros', 'Http\Discovery\MessageFactory\DiactorosFactory', 'Zend\Diactoros\Request');
}
}

Expand Down
25 changes: 25 additions & 0 deletions spec/UriFactoryDiscoverySpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace spec\Http\Discovery;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class UriFactoryDiscoverySpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Http\Discovery\UriFactoryDiscovery');
}

function it_finds_guzzle_then_zend_by_default()
{
$this->find()->shouldHaveType('Http\Discovery\UriFactory\GuzzleFactory');

$this->register('guzzle', 'invalid', '');

if (class_exists('Zend\Diactoros\Request')) {
$this->find()->shouldHaveType('Http\Discovery\UriFactory\DiactorosFactory');
}
}
}
51 changes: 51 additions & 0 deletions src/ClassDiscovery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Http\Discovery;

/**
* Registry that based find results on class existence
*
* @author David de Boer <[email protected]>
*/
abstract class ClassDiscovery
{
/**
* Add a condition (and class) to the discovery registry
*
* @param string $name
* @param string $class Class that will be instantiated if found
* @param string $condition Optional other class to check for existence
*/
public static function register($name, $class, $condition = null)
{
static::$cache = null;

static::$classes[$name] = [
'class' => $class,
'condition' => $condition ?: $class,
];
}

/**
* Finds a Factory
*
* @return object
*
* @throws NotFoundException
*/
public static function find()
{
// We have a cache
if (isset(static::$cache)) {
return static::$cache;
}

foreach (static::$classes as $name => $definition) {
if (class_exists($definition['condition'])) {
return static::$cache = new $definition['class'];
}
}

throw new NotFoundException('Not found');
}
}
54 changes: 21 additions & 33 deletions src/HttpAdapterDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,59 +11,47 @@

namespace Http\Discovery;

use Http\Adapter\HttpAdapter;

/**
* Finds an HTTP Adapter
*
* @author Márk Sági-Kazár <[email protected]>
*/
class HttpAdapterDiscovery
class HttpAdapterDiscovery extends ClassDiscovery
{
/**
* @var array
*/
protected static $adapters = [
'guzzle6' => 'Http\Adapter\Guzzle6HttpAdapter',
'guzzle5' => 'Http\Adapter\Guzzle5HttpAdapter',
];

/**
* @var string
* Cached adapter
*
* @var HttpAdapter
*/
protected static $cache;

/**
* Register an HTTP Adapter
*
* @param string $name
* @param string $class
* @var array
*/
public static function register($name, $class)
{
static::$cache = null;

static::$adapters[$name] = $class;
}
protected static $classes = [
'guzzle6' => [
'class' => 'Http\Adapter\Guzzle6HttpAdapter',
'condition' => 'Http\Adapter\Guzzle6HttpAdapter'

],
'guzzle5' => [
'class' => 'Http\Adapter\Guzzle5HttpAdapter',
'condition' => 'Http\Adapter\Guzzle6HttpAdapter'
],
];

/**
* Finds an HTTP Adapter
*
* @return object
* @return HttpAdapter
*
* @throws NotFoundException
*/
public static function find()
{
// We have a cache
if (isset(static::$cache)) {
return static::$cache;
}

foreach (static::$adapters as $name => $class) {
if (class_exists($class)) {
return static::$cache = new $class;
}
}

throw new NotFoundException('No HTTP Adapter found');
// Override only used for return type declaration
return parent::find();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these methods necessary? For the sake of return type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Necessary, no. But (as you may have noticed elsewhere) I value IDE auto-completion very much. Previously they had a @return object which stops your auto-complete chain.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine. 😃 But in that case, add a comment so that I dont remove it as auto optimalization. 😃

}
}
61 changes: 19 additions & 42 deletions src/MessageFactoryDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,69 +11,46 @@

namespace Http\Discovery;

use Http\Message\MessageFactory;

/**
* Finds a Message Factory
*
* @author Márk Sági-Kazár <[email protected]>
*/
class MessageFactoryDiscovery
class MessageFactoryDiscovery extends ClassDiscovery
{
/**
* Cached factory
*
* @var MessageFactory
*/
protected static $cache;

/**
* @var array
*/
protected static $messageFactories = [
protected static $classes = [
'guzzle' => [
'class' => 'GuzzleHttp\Psr7\Request',
'factory' => 'Http\Discovery\MessageFactory\GuzzleFactory',
'class' => 'Http\Discovery\MessageFactory\GuzzleFactory',
'condition'=> 'GuzzleHttp\Psr7\Request',
],
'diactoros' => [
'class' => 'Zend\Diactoros\Request',
'factory' => 'Http\Discovery\MessageFactory\DiactorosFactory',
'class' => 'Http\Discovery\MessageFactory\DiactorosFactory',
'condition' => 'Zend\Diactoros\Request',
],
];

/**
* @var string
*/
protected static $cache;

/**
* Register a Message Factory
* Find Message Factory
*
* @param string $name
* @param string $class
* @param string $factory
*/
public static function register($name, $class, $factory)
{
static::$cache = null;

static::$messageFactories[$name] = [
'class' => $class,
'factory' => $factory,
];
}

/**
* Finds a Message Factory
*
* @return object
* @return MessageFactory
*
* @throws NotFoundException
*/
public static function find()
{
// We have a cache
if (isset(static::$cache)) {
return static::$cache;
}

foreach (static::$messageFactories as $name => $definition) {
if (class_exists($definition['class'])) {
return static::$cache = new $definition['factory'];
}
}

throw new NotFoundException('No Message Factory found');
// Override only used for return type declaration
return parent::find();
}
}
22 changes: 22 additions & 0 deletions src/UriFactory/DiactorosFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Http\Discovery\UriFactory;

use Zend\Diactoros\Uri;
use Http\Message\UriFactory;

/**
* Creates a zend/diactoros URI object
*
* @author David de Boer <[email protected]>
*/
class DiactorosFactory implements UriFactory
{
/**
* {@inheritdoc}
*/
public function createUri($uri)
{
return new Uri($uri);
}
}
22 changes: 22 additions & 0 deletions src/UriFactory/GuzzleFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Http\Discovery\UriFactory;

use GuzzleHttp\Psr7;
use Http\Message\UriFactory;

/**
* Creates a guzzlehttp/psr7 URI object
*
* @author David de Boer <[email protected]>
*/
class GuzzleFactory implements UriFactory
{
/**
* {@inheritdoc}
*/
public function createUri($uri)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC there is a uri_for function in guzzle. Maybe it worth to use that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So as to support passing UriInterface objects as $uri?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. The reason why UriInterface is accepted in the factory interface is that you can accept both string and uri implementation in your library and you can leave the check to the factory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. (By the way, if you comment on the line itself, the discussion will be cleaned up if that line changes.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, my bad

return Psr7\uri_for($uri);
}
}
Loading