Skip to content

Commit

Permalink
Merge pull request #34 from veewee/optional-deps
Browse files Browse the repository at this point in the history
Improve error handling of optional dependencies
  • Loading branch information
veewee authored Nov 9, 2023
2 parents 1f2eb53 + 497941c commit dbefcf3
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 13 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"psr/http-message": "^1.0 || ^2.0",
"psr/http-message-implementation": "^1.0",
"psr/log": "^3",
"symfony/mime": "^6.3",
"webmozart/assert": "^1.11"
},
"require-dev": {
Expand All @@ -42,13 +41,15 @@
"php-http/vcr-plugin": "^1.2",
"phpro/grumphp-shim": "^2.1",
"symfony/http-client": "^5.4.26 || ^6.0",
"symfony/mime": "^6.0",
"symfony/property-access": "^5.4 || ^6.0",
"symfony/options-resolver": "^5.4 || ^6.0",
"symfony/serializer": "^5.4 || ^6.0"
},
"suggest": {
"symfony/http-client": "If you want to use the built-in symfony/http-client tools.",
"symfony/serializer": "If you want to use symfony serializer to handle request serialization and response deserialization.",
"symfony/mime": "If you want to use symfony/mime to upload or download binary files.",
"guzzlehttp/guzzle": "If you want to use the built-in guzzlehttp/guzzle tools.",
"php-http/mock-client": "For testing HTTP clients through mocking Requests and responses.",
"php-http/vcr-plugin": "For testing HTTP clients through storing and replaying requests and responses."
Expand Down
6 changes: 2 additions & 4 deletions src/Client/Factory/GuzzleClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Phpro\HttpTools\Dependency\GuzzleDependency;
use Psr\Http\Client\ClientInterface;
use Webmozart\Assert\Assert;

Expand All @@ -19,10 +20,7 @@ final class GuzzleClientFactory implements FactoryInterface
public static function create(iterable $middlewares, array $options = []): ClientInterface
{
Assert::allIsCallable($middlewares);
Assert::classExists(
Client::class,
'Could not find guzzle client. Please run: "composer require guzzlehttp/guzzle:^7.0"'
);
GuzzleDependency::guard();

$stack = HandlerStack::create();

Expand Down
7 changes: 2 additions & 5 deletions src/Client/Factory/SymfonyClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

use Http\Client\Common\Plugin;
use Phpro\HttpTools\Client\Configurator\PluginsConfigurator;
use Phpro\HttpTools\Dependency\SymfonyClientDependency;
use Psr\Http\Client\ClientInterface;
use Symfony\Component\HttpClient\CurlHttpClient;
use Symfony\Component\HttpClient\HttplugClient;
use Webmozart\Assert\Assert;

final class SymfonyClientFactory implements FactoryInterface
{
Expand All @@ -20,10 +20,7 @@ final class SymfonyClientFactory implements FactoryInterface
*/
public static function create(iterable $middlewares, array $options = []): ClientInterface
{
Assert::classExists(
CurlHttpClient::class,
'Could not find symfony HTTP client. Please run: "composer require symfony/http-client:^5.4"'
);
SymfonyClientDependency::guard();

return PluginsConfigurator::configure(
new HttplugClient(
Expand Down
19 changes: 19 additions & 0 deletions src/Dependency/GuzzleDependency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Phpro\HttpTools\Dependency;

use GuzzleHttp\Client;
use Webmozart\Assert\Assert;

final class GuzzleDependency
{
public static function guard(): void
{
Assert::classExists(
Client::class,
'Could not find guzzle client. Please run: "composer require guzzlehttp/guzzle" and make sure the version >7.'
);
}
}
18 changes: 18 additions & 0 deletions src/Dependency/MockClientDependency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Phpro\HttpTools\Dependency;

use Webmozart\Assert\Assert;

final class MockClientDependency
{
public static function guard(): void
{
Assert::classExists(
\Http\Mock\Client::class,
'Could not find a mock client. Please run: "composer require --dev php-http/mock-client"'
);
}
}
19 changes: 19 additions & 0 deletions src/Dependency/SymfonyClientDependency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Phpro\HttpTools\Dependency;

use Symfony\Component\HttpClient\CurlHttpClient;
use Webmozart\Assert\Assert;

final class SymfonyClientDependency
{
public static function guard(): void
{
Assert::classExists(
CurlHttpClient::class,
'Could not find symfony HTTP client. Please run: "composer require symfony/http-client" and make sure the version >5.4'
);
}
}
19 changes: 19 additions & 0 deletions src/Dependency/SymfonyMimeDependency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Phpro\HttpTools\Dependency;

use Symfony\Component\Mime\MimeTypes;
use Webmozart\Assert\Assert;

final class SymfonyMimeDependency
{
public static function guard(): void
{
Assert::classExists(
MimeTypes::class,
'Could not find symfony HTTP client. Please run: "composer require symfony/mime" and make sure the version >6.0'
);
}
}
19 changes: 19 additions & 0 deletions src/Dependency/VcrPluginDependency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Phpro\HttpTools\Dependency;

use Http\Client\Plugin\Vcr\RecordPlugin;
use Webmozart\Assert\Assert;

final class VcrPluginDependency
{
public static function guard(): void
{
Assert::classExists(
RecordPlugin::class,
'Could not find the VCR plugin. Please run: "composer require --dev php-http/vcr-plugin"'
);
}
}
3 changes: 3 additions & 0 deletions src/Encoding/Binary/Extractor/ExtensionExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Phpro\HttpTools\Encoding\Binary\Extractor;

use Phpro\HttpTools\Dependency\SymfonyMimeDependency;

use function Psl\Iter\first;

use Psr\Http\Message\ResponseInterface;
Expand All @@ -14,6 +16,7 @@ final class ExtensionExtractor
public function __invoke(ResponseInterface $response): ?string
{
if ($mimeType = (new MimeTypeExtractor())($response)) {
SymfonyMimeDependency::guard();
$extensions = MimeTypes::getDefault()->getExtensions($mimeType);
if ($extensions) {
return first($extensions);
Expand Down
3 changes: 3 additions & 0 deletions src/Encoding/Binary/Extractor/MimeTypeExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Phpro\HttpTools\Encoding\Binary\Extractor;

use Phpro\HttpTools\Dependency\SymfonyMimeDependency;

use function Psl\Iter\first;

use Psr\Http\Message\ResponseInterface;
Expand All @@ -19,6 +21,7 @@ public function __invoke(ResponseInterface $response): ?string

if ($originalName = (new FilenameExtractor())($response)) {
if ($extension = pathinfo($originalName, PATHINFO_EXTENSION)) {
SymfonyMimeDependency::guard();
$mimeTypes = MimeTypes::getDefault()->getMimeTypes($extension);

return first($mimeTypes);
Expand Down
3 changes: 3 additions & 0 deletions src/Encoding/Mime/MultiPartEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Phpro\HttpTools\Encoding\Mime;

use Http\Discovery\Psr17FactoryDiscovery;
use Phpro\HttpTools\Dependency\SymfonyMimeDependency;
use Phpro\HttpTools\Encoding\EncoderInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
Expand All @@ -19,6 +20,8 @@ final class MultiPartEncoder implements EncoderInterface

public function __construct(StreamFactoryInterface $streamFactory)
{
SymfonyMimeDependency::guard();

$this->streamFactory = $streamFactory;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Test/UseMockClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Phpro\HttpTools\Test;

use Http\Mock\Client;
use Webmozart\Assert\Assert;
use Phpro\HttpTools\Dependency\MockClientDependency;

trait UseMockClient
{
Expand All @@ -16,7 +16,7 @@ trait UseMockClient
*/
private function mockClient(callable $configurator = null): Client
{
Assert::classExists(Client::class, 'Could not find a mock client. Please run: "composer require --dev php-http/mock-client"');
MockClientDependency::guard();
$configurator ??= fn (Client $client) => $client;

return $configurator(new Client());
Expand Down
3 changes: 2 additions & 1 deletion src/Test/UseVcrClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Http\Client\Plugin\Vcr\Recorder\FilesystemRecorder;
use Http\Client\Plugin\Vcr\RecordPlugin;
use Http\Client\Plugin\Vcr\ReplayPlugin;
use Phpro\HttpTools\Dependency\VcrPluginDependency;
use Webmozart\Assert\Assert;

trait UseVcrClient
Expand All @@ -20,7 +21,7 @@ trait UseVcrClient
*/
private function useRecording(string $path, NamingStrategyInterface $namingStrategy = null): array
{
Assert::classExists(RecordPlugin::class, 'Could not find the VCR plugin. Please run: "composer require --dev php-http/vcr-plugin"');
VcrPluginDependency::guard();

Assert::directory($path);
$recorder = new FilesystemRecorder($path);
Expand Down

0 comments on commit dbefcf3

Please sign in to comment.