Skip to content

Allow for a candidate to have a Closure as a class parameter #66

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 3 commits into from
Jul 5, 2016
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
27 changes: 26 additions & 1 deletion src/ClassDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Http\Discovery;

use Http\Discovery\Exception\ClassinstantiationFailedException;
use Http\Discovery\Exception\DiscoveryFailedException;
use Http\Discovery\Exception\StrategyUnavailableException;

Expand Down Expand Up @@ -36,7 +37,7 @@ abstract class ClassDiscovery
*
* @param string $type
*
* @return string
* @return string|\Closure
*
* @throws DiscoveryFailedException
*/
Expand Down Expand Up @@ -177,4 +178,28 @@ protected static function evaluateCondition($condition)

return false;
}

/**
* Get an instance of the $class.
*
* @param string|\Closure $class A FQN of a class or a closure that instantiate the class.
Copy link
Member

Choose a reason for hiding this comment

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

FQCN

*
* @return object
*/
protected static function instantiateClass($class)
{
try {
if (is_string($class)) {
return new $class();
}

if (is_callable($class)) {
return $class();
}
} catch (\Exception $e) {
throw new ClassinstantiationFailedException('Unexcepced exception when instantiating class.', 0, $e);
}

throw new ClassinstantiationFailedException('Could not instantiate class becuase parameter is neitehr a callable or a string');
Copy link
Member

Choose a reason for hiding this comment

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

s/neitehr/neither

Copy link
Member

Choose a reason for hiding this comment

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

neither ... nor ...

}
}
14 changes: 14 additions & 0 deletions src/Exception/ClassinstantiationFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Http\Discovery\Exception;

use Http\Discovery\Exception;

/**
* Thrown when a class fails to instantiate.
*
* @author Tobias Nyholm <[email protected]>
*/
class ClassinstantiationFailedException extends \RuntimeException implements Exception
Copy link
Member

Choose a reason for hiding this comment

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

Should this be final?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, and also a capital "I" in Instantiation

{
}
2 changes: 1 addition & 1 deletion src/HttpAsyncClientDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function find()
try {
$asyncClient = static::findOneByType(HttpAsyncClient::class);

return new $asyncClient();
return static::instantiateClass($asyncClient);
Copy link
Member

Choose a reason for hiding this comment

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

Do we need the instantiation within the try? Is it possible that a closure throws a DiscoveryFailedException?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, we do not need a try-catch here. We know that instantiateClass could only throw a ClassInstantiationFailedException

Copy link
Member

Choose a reason for hiding this comment

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

Then maybe we should move the instantiation out of the try-catch block. Makes the code easier to read IMO.

Copy link
Member Author

@Nyholm Nyholm Jul 7, 2016

Choose a reason for hiding this comment

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

Sorry, I think I miss-read your comment. I meant that we do not need an additional try-catch here (at this line).

Do we need the instantiation within the try? Is it possible that a closure throws a DiscoveryFailedException?

Yes, we need the instantiation within a try-catch. Any weird exception could happen both with a FQCN (Class not found) and with the closure. The closure may throw a "VeryRandomException" that is not part of our code.

Our strategies does not behave weirdly (of course) but the application developer may inject a strategy of their own.

Copy link
Contributor

@dbu dbu Jul 7, 2016 via email

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I am wrong, but this try-catch only handles DiscoveryFailedExceptions, which mean we cannot (and we don't want to) catch VeryRandomExceptions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you propose that we should rewrite it like:

        try {
            $asyncClient = static::findOneByType(HttpAsyncClient::class);
        } catch (DiscoveryFailedException $e) {
            throw new NotFoundException(
                'No HTTPlug async clients found. Make sure to install a package providing "php-http/async-client-implementation". Example: "php-http/guzzle6-adapter".',
                0,
                $e
            );
        }
        return static::instantiateClass($asyncClient);

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand how the linked method is relevant: the exceptions there would still not be caught by this catch block.

Yes, I propose exactly that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Now I understand you. You got a PR.

} catch (DiscoveryFailedException $e) {
throw new NotFoundException(
'No HTTPlug async clients found. Make sure to install a package providing "php-http/async-client-implementation". Example: "php-http/guzzle6-adapter".',
Expand Down
2 changes: 1 addition & 1 deletion src/HttpClientDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function find()
try {
$client = static::findOneByType(HttpClient::class);

return new $client();
return static::instantiateClass($client);
} catch (DiscoveryFailedException $e) {
throw new NotFoundException(
'No HTTPlug clients found. Make sure to install a package providing "php-http/client-implementation". Example: "php-http/guzzle6-adapter".',
Expand Down
2 changes: 1 addition & 1 deletion src/MessageFactoryDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function find()
try {
$messageFactory = static::findOneByType(MessageFactory::class);

return new $messageFactory();
return static::instantiateClass($messageFactory);
} catch (DiscoveryFailedException $e) {
throw new NotFoundException(
'No message factories found. To use Guzzle or Diactoros factories install php-http/message and the chosen message implementation.',
Expand Down
2 changes: 1 addition & 1 deletion src/StreamFactoryDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function find()
try {
$streamFactory = static::findOneByType(StreamFactory::class);

return new $streamFactory();
return static::instantiateClass($streamFactory);
} catch (DiscoveryFailedException $e) {
throw new NotFoundException(
'No stream factories found. To use Guzzle or Diactoros factories install php-http/message and the chosen message implementation.',
Expand Down
2 changes: 1 addition & 1 deletion src/UriFactoryDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function find()
try {
$uriFactory = static::findOneByType(UriFactory::class);

return new $uriFactory();
return static::instantiateClass($uriFactory);
} catch (DiscoveryFailedException $e) {
throw new NotFoundException(
'No uri factories found. To use Guzzle or Diactoros factories install php-http/message and the chosen message implementation.',
Expand Down