From 6e771156a081f86070d8f2ef10f9cbca1b5678fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Nikolaou?= Date: Mon, 2 Sep 2019 21:03:47 +0300 Subject: [PATCH] Add support for Laravel 6.0 --- .travis.yml | 3 - CHANGELOG.md | 5 ++ composer.json | 10 ++-- src/Client.php | 66 ++++++++++++++-------- src/Commands/Cache/Purge.php | 104 +++++++++++++++++------------------ src/ServiceProvider.php | 9 +-- src/Zone.php | 39 +++++++++++++ tests/ClientTest.php | 36 +++++++----- tests/CollectionTest.php | 22 ++++---- tests/ConsoleHelpers.php | 4 +- tests/GuzzleHelpers.php | 13 +++-- tests/PurgeCommandTest.php | 2 +- 12 files changed, 188 insertions(+), 125 deletions(-) create mode 100644 src/Zone.php diff --git a/.travis.yml b/.travis.yml index 5bfc711..115f07b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: php php: - - 5.5.9 - - 5.6 - - 7.0 - 7.1 - 7.2 - 7.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ddd001..42b6364 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to `artisan-cloudflare` will be documented in this file. +## 2.0.0 - 2019-09-02 + +- Add support for Laravel 6.0 +- Drop support for Laravel <5.5 and PHP <7.1 + ## 1.3.0 - 2019-02-15 - Add support for Laravel 5.8 diff --git a/composer.json b/composer.json index 50e5d23..29430ed 100644 --- a/composer.json +++ b/composer.json @@ -18,15 +18,15 @@ } ], "require": { - "php": "^5.5.9|^7.0", + "php": "^7.1", "guzzlehttp/guzzle": "^6.0", - "illuminate/console": "5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*|5.8.*|^6.0", - "illuminate/support": "5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*|5.8.*|^6.0" + "illuminate/console": "^5.5|^6.0", + "illuminate/support": "^5.5|^6.0" }, "require-dev": { "mockery/mockery": "^0.9|^1.0", - "orchestra/testbench": "3.1.*|3.2.*|3.3.*|3.4.*|3.5.*|3.6.*|3.7.*|3.8.*|3.9.*", - "phpunit/phpunit": "^4.8|^5.0|^6.0|^7.0" + "orchestra/testbench": "^3.5", + "phpunit/phpunit": "^7.0|^8.0" }, "autoload": { "psr-4": { diff --git a/src/Client.php b/src/Client.php index 6e69fd8..195d75e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -47,18 +47,28 @@ public function __construct(GuzzleClient $client, LoggerInterface $logger) * The promise waits until all the promises have been resolved or rejected * and returns the results of each request. * - * @param \Illuminate\Support\Collection|array[] $parameters - * @return \Illuminate\Support\Collection|\stdClass[] + * @param \Illuminate\Support\Collection $zones + * @return \Illuminate\Support\Collection */ - public function purge(Collection $parameters) + public function purge($zones) { - $promises = $parameters->map(function ($parameters, $identifier) { - return $this->client->deleteAsync("zones/{$identifier}/purge_cache", [ - \GuzzleHttp\RequestOptions::JSON => $parameters, - ]); - }); + return $zones->map(function (Zone $zone, $identifier) { + return $this->delete($identifier, $zone); + })->pipe(function ($promises) { + return $this->settle($promises); + })->wait(); + } - return $this->settle($promises)->wait(); + /** + * @param string $identifier + * @param \Sebdesign\ArtisanCloudflare\Zone $zone + * @return \GuzzleHttp\Promise\PromiseInterface + */ + protected function delete($identifier, Zone $zone) + { + return $this->client->deleteAsync("zones/{$identifier}/purge_cache", [ + \GuzzleHttp\RequestOptions::JSON => $zone, + ]); } /** @@ -67,15 +77,15 @@ public function purge(Collection $parameters) * * The returned promise is fulfilled with a collection of results. * - * @param \Illuminate\Support\Collection|\GuzzleHttp\Promise\PromiseInterface[] $promises + * @param \Illuminate\Support\Collection $promises * @return \GuzzleHttp\Promise\PromiseInterface */ protected function settle(Collection $promises) { - $results = collect(); + $results = new Collection(); return Promise\each( - $promises->toArray(), + $promises->getIterator(), $this->onFulfilled($results), $this->onRejected($results) )->then(function () use ($results) { @@ -86,11 +96,16 @@ protected function settle(Collection $promises) /** * Put the body of the fulfilled promise into the results. * - * @param \Illuminate\Support\Collection|object[] $results + * @param \Illuminate\Support\Collection $results * @return \Closure */ - protected function onFulfilled(Collection $results) + protected function onFulfilled($results) { + /** + * @param \Psr\Http\Message\ResponseInterface $response + * @param string $identifier + * @return \Illuminate\Support\Collection + */ return function ($response, $identifier) use ($results) { return $results->put($identifier, $this->getBody($response)); }; @@ -99,11 +114,16 @@ protected function onFulfilled(Collection $results) /** * Handle the rejected promise and put the errors into the results. * - * @param \Illuminate\Support\Collection|object[] $results + * @param \Illuminate\Support\Collection $results * @return \Closure */ - protected function onRejected(Collection $results) + protected function onRejected($results) { + /** + * @param \GuzzleHttp\Exception\RequestException $reason + * @param string $identifier + * @return \Illuminate\Support\Collection + */ return function ($reason, $identifier) use ($results) { $this->logger->error($reason->getMessage(), [ 'zone' => $identifier, @@ -118,7 +138,7 @@ protected function onRejected(Collection $results) * Transform a request exception into a result object. * * @param \GuzzleHttp\Exception\RequestException $e - * @return \stdClass + * @return \Sebdesign\ArtisanCloudflare\Zone */ protected function handleException(RequestException $e) { @@ -135,28 +155,26 @@ protected function handleException(RequestException $e) $message = $e->getMessage(); } - $result = [ + return new Zone([ 'success' => false, 'errors' => [ - (object) [ + [ 'code' => $e->getCode(), 'message' => $message, ], ], - ]; - - return (object) $result; + ]); } /** * Transform the response body into a result object. * * @param \Psr\Http\Message\ResponseInterface $response - * @return \stdClass + * @return \Sebdesign\ArtisanCloudflare\Zone */ protected function getBody(ResponseInterface $response) { - return json_decode($response->getBody(), false); + return new Zone(json_decode($response->getBody(), true)); } /** diff --git a/src/Commands/Cache/Purge.php b/src/Commands/Cache/Purge.php index 8483560..47f5c5c 100644 --- a/src/Commands/Cache/Purge.php +++ b/src/Commands/Cache/Purge.php @@ -5,8 +5,8 @@ use Illuminate\Console\Command; use Illuminate\Support\Collection; use Sebdesign\ArtisanCloudflare\Client; +use Sebdesign\ArtisanCloudflare\Zone; use Symfony\Component\Console\Helper\TableCell; -use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\Console\Helper\TableSeparator; class Purge extends Command @@ -45,34 +45,34 @@ class Purge extends Command /** * API item identifier tags. * - * @var \Illuminate\Support\Collection + * @var \Illuminate\Support\Collection */ private $zones; /** * Purge constructor. * - * @param \Sebdesign\ArtisanCloudflare\Client $client - * @param array $zones + * @param array $zones */ - public function __construct(Client $client, array $zones) + public function __construct(array $zones) { parent::__construct(); - $this->client = $client; - - $this->zones = collect($zones)->map(function ($zone) { - return new ParameterBag(array_filter($zone)); + $this->zones = Collection::make($zones)->map(function (array $zone) { + return new Zone(array_filter($zone)); }); } /** * Execute the console command. * + * @param \Sebdesign\ArtisanCloudflare\Client $client * @return int */ - public function handle() + public function handle(Client $client) { + $this->client = $client; + $zones = $this->getZones(); if ($zones->isEmpty()) { @@ -95,10 +95,10 @@ public function handle() * * Use the config for each zone, unless options are passed in the command. * - * @param \Illuminate\Support\Collection|\Symfony\Component\HttpFoundation\ParameterBag[] $zones - * @return \Illuminate\Support\Collection|\Symfony\Component\HttpFoundation\ParameterBag[] + * @param \Illuminate\Support\Collection $zones + * @return \Illuminate\Support\Collection */ - private function applyParameters(Collection $zones) + private function applyParameters($zones) { $defaults = array_filter([ 'files' => $this->option('file'), @@ -110,7 +110,7 @@ private function applyParameters(Collection $zones) return $zones; } - return $zones->each(function ($zone) use ($defaults) { + return $zones->each(function (Zone $zone) use ($defaults) { $zone->replace($defaults); }); } @@ -118,20 +118,12 @@ private function applyParameters(Collection $zones) /** * Execute the purging operations and return each result. * - * @param \Illuminate\Support\Collection|\Symfony\Component\HttpFoundation\ParameterBag[] $zones - * @return \Illuminate\Support\Collection|\stdClass[] + * @param \Illuminate\Support\Collection $zones + * @return \Illuminate\Support\Collection */ - private function purge(Collection $zones) + private function purge($zones) { - $parameters = $zones->map(function ($zone) { - if ($zone->count()) { - return $zone->all(); - } - - return ['purge_everything' => true]; - }); - - $results = $this->client->purge($parameters); + $results = $this->client->purge($zones); return $results->reorder($zones->keys()); } @@ -139,11 +131,11 @@ private function purge(Collection $zones) /** * Display a table with the results. * - * @param \Illuminate\Support\Collection|\Symfony\Component\HttpFoundation\ParameterBag[] $zones - * @param \Illuminate\Support\Collection|\stdClass[] $results + * @param \Illuminate\Support\Collection $zones + * @param \Illuminate\Support\Collection $results * @return void */ - private function displayResults(Collection $zones, Collection $results) + private function displayResults($zones, $results) { $headers = ['Status', 'Zone', 'Files', 'Tags', 'Hosts', 'Errors']; @@ -155,36 +147,36 @@ private function displayResults(Collection $zones, Collection $results) ]; // Get the status emoji - $emoji = $results->pluck('success')->map(function ($success) { - return $success ? '✅' : '❌'; + $emoji = $results->map(function (Zone $zone) { + return $zone->get('success') ? '✅' : '❌'; }); // Get the zone identifiers $identifiers = $zones->keys(); // Get the files as multiline strings - $files = $zones->map(function ($zones) { - return $this->formatItems($zones->get('files')); + $files = $zones->map(function (Zone $zone) { + return $this->formatItems($zone->get('files', [])); }); // Get the tags as multiline strings - $tags = $zones->map(function ($zones) { - return $this->formatItems($zones->get('tags')); + $tags = $zones->map(function (Zone $zone) { + return $this->formatItems($zone->get('tags', [])); }); // Get the hosts as multiline strings - $hosts = $zones->map(function ($zones) { - return $this->formatItems($zones->get('hosts')); + $hosts = $zones->map(function (Zone $zone) { + return $this->formatItems($zone->get('hosts', [])); }); // Get the errors as red multiline strings - $errors = $results->map(function ($result) { - return $this->formatErrors($result->errors); - })->map(function ($errors) { + $errors = $results->map(function (Zone $result) { + return $this->formatErrors($result->get('errors', [])); + })->map(function (array $errors) { return $this->formatItems($errors); }); - $columns = collect([ + $columns = Collection::make([ 'status' => $emoji, 'identifier' => $identifiers, 'files' => $files, @@ -201,35 +193,35 @@ private function displayResults(Collection $zones, Collection $results) /** * Format an array into a multiline string. * - * @param array|null $items + * @param array $items * @return string */ - private function formatItems(array $items = null) + private function formatItems(array $items) { - return implode("\n", (array) $items); + return implode("\n", $items); } /** * Format the errors. * - * @param \stdClass[] $errors + * @param array[] $errors * @return string[] */ private function formatErrors(array $errors) { - return array_map(function ($error) { - if (isset($error->code)) { - return "{$error->code}: {$error->message}"; + return array_map(function (array $error) { + if (isset($error['code'])) { + return "{$error['code']}: {$error['message']}"; } - return "{$error->message}"; + return "{$error['message']}"; }, $errors); } /** * Get the zone identifier from the input argument or the configuration. * - * @return \Illuminate\Support\Collection|\Symfony\Component\HttpFoundation\ParameterBag[] + * @return \Illuminate\Support\Collection */ private function getZones() { @@ -243,19 +235,21 @@ private function getZones() return $zones; } - return collect([ - $zone => new ParameterBag(), + return new Collection([ + $zone => new Zone(), ]); } /** * Return 1 if all successes are false, otherwise return 0. * - * @param \Illuminate\Support\Collection $results + * @param \Illuminate\Support\Collection $results * @return int */ - private function getExitCode(Collection $results) + private function getExitCode($results) { - return (int) $results->pluck('success')->filter()->isEmpty(); + return (int) $results->filter(function (Zone $zone) { + return $zone->get('success'); + })->isEmpty(); } } diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 4aaff97..fe64f58 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -20,9 +20,11 @@ class ServiceProvider extends IlluminateServiceProvider */ public function boot() { - $this->publishes([ - __DIR__.'/../config/cloudflare.php' => config_path('cloudflare.php'), - ], 'config'); + if ($this->app->runningInConsole()) { + $this->publishes([ + __DIR__.'/../config/cloudflare.php' => config_path('cloudflare.php'), + ], 'config'); + } } public function register() @@ -61,7 +63,6 @@ protected function registerCommands() { $this->app->bind(Commands\Cache\Purge::class, function () { return new Commands\Cache\Purge( - $this->app[Client::class], $this->app['config']['cloudflare.zones'] ); }); diff --git a/src/Zone.php b/src/Zone.php new file mode 100644 index 0000000..23c41a2 --- /dev/null +++ b/src/Zone.php @@ -0,0 +1,39 @@ +parameters = $parameters; + } + + public function replace(array $parameters) + { + $this->parameters = $parameters; + } + + public function jsonSerialize() + { + if (empty($this->parameters)) { + return ['purge_everything' => true]; + } + + return $this->parameters; + } + + public function get($key, $default = null) + { + if (isset($this->parameters[$key])) { + return $this->parameters[$key]; + } + + return $default; + } +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 8628c8a..d6e94a2 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,7 +2,9 @@ namespace Sebdesign\ArtisanCloudflare\Test; +use Illuminate\Support\Collection; use Sebdesign\ArtisanCloudflare\Client; +use Sebdesign\ArtisanCloudflare\Zone; class ClientTest extends TestCase { @@ -13,7 +15,7 @@ class ClientTest extends TestCase * * @return void */ - public function setUp() + public function setUp() : void { parent::setUp(); @@ -32,7 +34,9 @@ public function it_purges_a_zone_with_success() // Act - $results = $client->purge(collect(['foo' => ['bar' => 'baz']])); + $results = $client->purge(Collection::make([ + 'foo' => new Zone(['bar' => 'baz']), + ])); // Assert @@ -40,7 +44,7 @@ public function it_purges_a_zone_with_success() $this->assertCount(1, $results); $this->seeRequestWithBody($this->transactions->first(), ['bar' => 'baz']); $this->seeRequestContainsPath($this->transactions->first(), 'foo'); - $this->assertEquals((object) ['success' => true], $results->get('foo')); + $this->assertEquals(new Zone(['success' => true]), $results->get('foo')); } /** @@ -55,7 +59,9 @@ public function it_handles_client_errors() // Act - $results = $client->purge(collect(['foo' => ['bar' => 'baz']])); + $results = $client->purge(Collection::make([ + 'foo' => new Zone(['bar' => 'baz']), + ])); // Assert @@ -63,10 +69,10 @@ public function it_handles_client_errors() $this->assertCount(1, $results); $this->seeRequestWithBody($this->transactions->first(), ['bar' => 'baz']); $this->seeRequestContainsPath($this->transactions->first(), 'foo'); - $this->assertEquals((object) [ + $this->assertEquals(new Zone([ 'success' => false, 'errors' => ['error'], - ], $results->get('foo')); + ]), $results->get('foo')); } /** @@ -82,9 +88,9 @@ public function it_handles_server_errors() // Act - $results = $client->purge(collect([ - 'foo' => ['bar' => 'baz'], - 'bar' => ['baz' => 'qux'], + $results = $client->purge(Collection::make([ + 'foo' => new Zone(['bar' => 'baz']), + 'bar' => new Zone(['baz' => 'qux']), ])); // Assert @@ -93,26 +99,26 @@ public function it_handles_server_errors() $this->assertCount(2, $results); $this->seeRequestWithBody($this->transactions->get(0), ['bar' => 'baz']); $this->seeRequestContainsPath($this->transactions->get(0), 'foo'); - $this->assertEquals((object) [ + $this->assertEquals(new Zone([ 'success' => false, 'errors' => [ - (object) [ + [ 'code' => 0, 'message' => 'Connection error', ], ], - ], $results->get('foo')); + ]), $results->get('foo')); $this->seeRequestWithBody($this->transactions->get(1), ['baz' => 'qux']); $this->seeRequestContainsPath($this->transactions->get(1), 'bar'); - $this->assertEquals((object) [ + $this->assertEquals(new Zone([ 'success' => false, 'errors' => [ - (object) [ + [ 'code' => 500, 'message' => 'Fatal error', ], ], - ], $results->get('bar')); + ]), $results->get('bar')); } } diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php index 7b2c522..a6965ae 100644 --- a/tests/CollectionTest.php +++ b/tests/CollectionTest.php @@ -2,9 +2,11 @@ namespace Sebdesign\ArtisanCloudflare\Test; +use Illuminate\Support\Collection; + class CollectionTest extends TestCase { - public function setUp() + public function setUp() : void { parent::setUp(); @@ -37,17 +39,17 @@ public function it_transposes_a_collection() ]; $expected = [ - collect([ + Collection::make([ 'identifiers' => 'zone-a', 'files' => ['app.css', 'app.js'], 'tags' => ['styles', 'scripts'], ]), - collect([ + Collection::make([ 'identifiers' => 'zone-b', 'files' => ['main.css', 'main.js'], 'tags' => ['images', 'icons'], ]), - collect([ + Collection::make([ 'identifiers' => 'zone-c', 'files' => ['style.css', 'scripts.css'], 'tags' => ['fonts', 'media'], @@ -56,11 +58,11 @@ public function it_transposes_a_collection() // Act - $actual = collect($zones)->_transpose(); + $actual = Collection::make($zones)->_transpose(); // Assert - $this->assertEquals(collect($expected), $actual); + $this->assertEquals(Collection::make($expected), $actual); } /** @@ -86,11 +88,11 @@ public function it_inserts_a_value_between_items() // Act - $actual = collect($table)->insertBetween('-----'); + $actual = Collection::make($table)->insertBetween('-----'); // Assert - $this->assertEquals(collect($expected), $actual); + $this->assertEquals(Collection::make($expected), $actual); } /** @@ -116,10 +118,10 @@ public function it_reorders_a_collection() // Act - $actual = collect($items)->reorder($keys); + $actual = Collection::make($items)->reorder($keys); // Assert - $this->assertEquals(collect($expected), $actual); + $this->assertEquals(Collection::make($expected), $actual); } } diff --git a/tests/ConsoleHelpers.php b/tests/ConsoleHelpers.php index 6422ae1..e3f13c2 100644 --- a/tests/ConsoleHelpers.php +++ b/tests/ConsoleHelpers.php @@ -43,7 +43,7 @@ public function artisan($command, $parameters = []) */ protected function seeInConsole($text) { - $this->assertContains($text, $this->output); + $this->assertStringContainsString($text, $this->output); return $this; } @@ -56,7 +56,7 @@ protected function seeInConsole($text) */ protected function dontSeeInConsole($text) { - $this->assertNotContains($text, $this->output); + $this->assertStringNotContainsString($text, $this->output); return $this; } diff --git a/tests/GuzzleHelpers.php b/tests/GuzzleHelpers.php index 3e765aa..d9901f8 100644 --- a/tests/GuzzleHelpers.php +++ b/tests/GuzzleHelpers.php @@ -2,14 +2,15 @@ namespace Sebdesign\ArtisanCloudflare\Test; -use GuzzleHttp\Middleware; +use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; +use GuzzleHttp\Middleware; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Handler\MockHandler; -use GuzzleHttp\Client as GuzzleClient; +use Illuminate\Support\Collection; use Sebdesign\ArtisanCloudflare\Client; -use GuzzleHttp\Exception\RequestException; trait GuzzleHelpers { @@ -34,7 +35,7 @@ trait GuzzleHelpers */ protected function seeRequestContainsPath(array $transaction, $path) { - $this->assertContains($path, $transaction['request']->getUri()->getPath()); + $this->assertStringContainsString($path, $transaction['request']->getUri()->getPath()); return $this; } @@ -65,7 +66,7 @@ protected function mockClient() $stack = HandlerStack::create($this->handler); // Attach the transaction history to the handler stack. - $this->transactions = collect(); + $this->transactions = Collection::make(); $stack->push(Middleware::history($this->transactions)); // Initialize the mocked guzzle client diff --git a/tests/PurgeCommandTest.php b/tests/PurgeCommandTest.php index f19034d..453973d 100644 --- a/tests/PurgeCommandTest.php +++ b/tests/PurgeCommandTest.php @@ -11,7 +11,7 @@ class PurgeCommandTest extends TestCase * * @return void */ - public function setUp() + public function setUp() : void { parent::setUp();