From 0875c783eab82d00181ad79d727cd0c2cc4e41d9 Mon Sep 17 00:00:00 2001
From: Valentin Clavreul <valentin.clavreul@bedrockstreaming.com>
Date: Fri, 13 Oct 2023 11:06:25 +0200
Subject: [PATCH] feat: setup and applied rector

---
 .github/workflows/ci.yml                      | 25 ++++++++++-
 composer.json                                 |  3 +-
 rector.php                                    | 29 +++++++++++++
 src/DataCollector/GuzzleHttpDataCollector.php |  2 +-
 src/DependencyInjection/Configuration.php     | 36 ++++------------
 src/DependencyInjection/GuzzleHttpPass.php    |  6 +--
 .../M6WebGuzzleHttpExtension.php              |  8 ++--
 .../AbstractGuzzleCacheEvent.php              |  4 +-
 .../AbstractGuzzleHttpEvent.php               |  4 +-
 src/Handler/CacheTrait.php                    |  9 ++--
 src/Middleware/EventDispatcherMiddleware.php  | 41 ++++++++-----------
 src/Middleware/HostForwarderMiddleware.php    | 27 +++++-------
 12 files changed, 103 insertions(+), 91 deletions(-)
 create mode 100644 rector.php

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0eaa5b1..e1a298a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,5 +1,5 @@
 name: Continuous Integration
-on: [push, pull_request]
+on: [ push, pull_request ]
 
 jobs:
   linter:
@@ -65,4 +65,25 @@ jobs:
           key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
           restore-keys: ${{ runner.os }}-composer-
       - run: composer update --prefer-dist --no-interaction ${{ matrix.flags }}
-      - run: bin/phpstan
\ No newline at end of file
+      - run: bin/phpstan
+
+  rector:
+    name: Rector checks
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@master
+      - uses: shivammathur/setup-php@v2
+        with:
+          php-version: 8.1
+          coverage: xdebug2
+      - name: Get composer cache directory
+        id: composer-cache
+        run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+      - name: Cache dependencies
+        uses: actions/cache@v3
+        with:
+          path: ${{ steps.composer-cache.outputs.dir }}
+          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
+          restore-keys: ${{ runner.os }}-composer-
+      - run: composer update --prefer-dist --no-interaction
+      - run: bin/rector --dry-run
diff --git a/composer.json b/composer.json
index f5fe759..e5e59ba 100644
--- a/composer.json
+++ b/composer.json
@@ -28,7 +28,8 @@
     "friendsofphp/php-cs-fixer": "3.35.1",
     "guzzlehttp/promises": "^2",
     "phpstan/phpstan": "1.10.38",
-    "phpstan/phpstan-symfony": "1.3.4"
+    "phpstan/phpstan-symfony": "1.3.4",
+    "rector/rector": "0.18.5"
   },
   "autoload": {
     "psr-4": {"M6Web\\Bundle\\GuzzleHttpBundle\\": "src/"}
diff --git a/rector.php b/rector.php
new file mode 100644
index 0000000..3be9423
--- /dev/null
+++ b/rector.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
+use Rector\Config\RectorConfig;
+use Rector\Set\ValueObject\LevelSetList;
+use Rector\Symfony\Set\SymfonySetList;
+use Rector\Doctrine\Set\DoctrineSetList;
+use Rector\Symfony\Set\SensiolabsSetList;
+
+return static function (RectorConfig $rectorConfig): void {
+    $rectorConfig->paths([
+        __DIR__ . '/src'
+    ]);
+
+    // register a single rule
+    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
+
+    // define sets of rules
+    $rectorConfig->sets([
+        LevelSetList::UP_TO_PHP_81,
+        SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES,
+        SymfonySetList::SYMFONY_54,
+        SymfonySetList::SYMFONY_CODE_QUALITY,
+        DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
+        SensiolabsSetList::ANNOTATIONS_TO_ATTRIBUTES,
+    ]);
+};
diff --git a/src/DataCollector/GuzzleHttpDataCollector.php b/src/DataCollector/GuzzleHttpDataCollector.php
index 0fc1d2c..bd2c47c 100644
--- a/src/DataCollector/GuzzleHttpDataCollector.php
+++ b/src/DataCollector/GuzzleHttpDataCollector.php
@@ -16,7 +16,7 @@
 class GuzzleHttpDataCollector extends DataCollector
 {
     /** @var GuzzleHttpClient[] */
-    private $clients = [];
+    private array $clients = [];
 
     public function __construct()
     {
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index 272480f..56a8832 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -52,34 +52,26 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->scalarNode('body')->end()
                             ->variableNode('cert')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_string($v) && (!\is_array($v) || \count($v) != 2);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_string($v) && (!\is_array($v) || \count($v) != 2))
                                     ->theninvalid('Requires a string or a two entries array')
                                 ->end()
                             ->end()
                             ->variableNode('debug')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_string($v) && !\is_bool($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_string($v) && !\is_bool($v))
                                     ->theninvalid('Requires an invokable service id or a bolean value')
                                 ->end()
                             ->end()
                             ->variableNode('decode_content')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_string($v) && !\is_bool($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_string($v) && !\is_bool($v))
                                     ->theninvalid('Requires a string or a boolean')
                                 ->end()
                             ->end()
                             ->floatNode('delay')->end()
                             ->variableNode('expect')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_int($v) && !\is_bool($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_int($v) && !\is_bool($v))
                                     ->theninvalid('Requires an integer or a boolean')
                                 ->end()
                             ->end()
@@ -91,9 +83,7 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->end()
                             ->variableNode('cookies')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_array($v) && !\is_bool($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_array($v) && !\is_bool($v))
                                     ->theninvalid('Requires an array or a boolean')
                                 ->end()
                             ->end()
@@ -114,9 +104,7 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->scalarNode('on_stats')->end()
                             ->variableNode('proxy')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_array($v) && !\is_string($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_array($v) && !\is_string($v))
                                     ->theninvalid('Requires an array or a string')
                                 ->end()
                             ->end()
@@ -127,9 +115,7 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->scalarNode('sink')->end()
                             ->variableNode('ssl_key')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_string($v) && (!\is_array($v) || \count($v) != 2);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_string($v) && (!\is_array($v) || \count($v) != 2))
                                     ->theninvalid('Requires a string or a two entries array')
                                 ->end()
                             ->end()
@@ -137,9 +123,7 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->booleanNode('synchronous')->end()
                             ->variableNode('verify')
                                 ->validate()
-                                    ->ifTrue(function ($v) {
-                                        return !\is_string($v) && !\is_bool($v);
-                                    })
+                                    ->ifTrue(fn($v) => !\is_string($v) && !\is_bool($v))
                                     ->theninvalid('Requires a string or a boolean')
                                 ->end()
                             ->end()
@@ -147,9 +131,7 @@ public function getConfigTreeBuilder(): TreeBuilder
                             ->arrayNode('allow_redirects')
                                 ->beforeNormalization()
                                     ->ifInArray([true, false])
-                                    ->then(function ($v) {
-                                        return ['max' => 0];
-                                    })
+                                    ->then(fn($v) => ['max' => 0])
                                 ->end()
                                 ->addDefaultsIfNotSet()
                                 ->children()
diff --git a/src/DependencyInjection/GuzzleHttpPass.php b/src/DependencyInjection/GuzzleHttpPass.php
index fae8f8d..19551a5 100644
--- a/src/DependencyInjection/GuzzleHttpPass.php
+++ b/src/DependencyInjection/GuzzleHttpPass.php
@@ -10,12 +10,8 @@
 
 class GuzzleHttpPass implements CompilerPassInterface
 {
-    /** @var string */
-    private $clientTag;
-
-    public function __construct(string $clientTag = 'm6web_guzzlehttp.client')
+    public function __construct(private readonly string $clientTag = 'm6web_guzzlehttp.client')
     {
-        $this->clientTag = $clientTag;
     }
 
     public function process(ContainerBuilder $container)
diff --git a/src/DependencyInjection/M6WebGuzzleHttpExtension.php b/src/DependencyInjection/M6WebGuzzleHttpExtension.php
index c720743..b2758e0 100644
--- a/src/DependencyInjection/M6WebGuzzleHttpExtension.php
+++ b/src/DependencyInjection/M6WebGuzzleHttpExtension.php
@@ -226,7 +226,7 @@ protected function getCurlConfig(array $config)
 
     protected function getServiceReference(string $id)
     {
-        if (substr($id, 0, 1) == '@') {
+        if (str_starts_with($id, '@')) {
             return new Reference(substr($id, 1));
         }
 
@@ -238,9 +238,7 @@ protected function getCookiesJarServiceReference(ContainerBuilder $container, ar
         array_walk($cookies, function (&$item) {
             $item = array_combine(
                 array_map(
-                    function ($key) {
-                        return ucwords($key, ' -');
-                    },
+                    fn($key) => ucwords($key, ' -'),
                     array_keys($item)
                 ),
                 array_values($item)
@@ -249,7 +247,7 @@ function ($key) {
 
         $container->register(
             $id = sprintf('m6web_guzzlehttp.guzzle.cookies_jar.%s', $clientId),
-            'GuzzleHttp\Cookie\CookieJar'
+            \GuzzleHttp\Cookie\CookieJar::class
         )
         ->setArguments([false, $cookies])
         ->setPublic(true);
diff --git a/src/EventDispatcher/AbstractGuzzleCacheEvent.php b/src/EventDispatcher/AbstractGuzzleCacheEvent.php
index 5c8bcfb..4d6d833 100644
--- a/src/EventDispatcher/AbstractGuzzleCacheEvent.php
+++ b/src/EventDispatcher/AbstractGuzzleCacheEvent.php
@@ -13,10 +13,10 @@
 abstract class AbstractGuzzleCacheEvent extends Event
 {
     /** @const string Name of standard event */
-    public const NAME = 'm6web.guzzlecache';
+    final public const NAME = 'm6web.guzzlecache';
 
     /** @const string Name of Error event */
-    public const NAME_ERROR = 'm6web.guzzlecache.error';
+    final public const NAME_ERROR = 'm6web.guzzlecache.error';
 
     /** @var RequestInterface */
     protected $request;
diff --git a/src/EventDispatcher/AbstractGuzzleHttpEvent.php b/src/EventDispatcher/AbstractGuzzleHttpEvent.php
index 7843ae9..631a1aa 100644
--- a/src/EventDispatcher/AbstractGuzzleHttpEvent.php
+++ b/src/EventDispatcher/AbstractGuzzleHttpEvent.php
@@ -15,8 +15,8 @@
  */
 abstract class AbstractGuzzleHttpEvent extends Event
 {
-    public const EVENT_NAME = 'm6web.guzzlehttp';
-    public const EVENT_ERROR_NAME = 'm6web.guzzlehttp.error';
+    final public const EVENT_NAME = 'm6web.guzzlehttp';
+    final public const EVENT_ERROR_NAME = 'm6web.guzzlehttp.error';
 
     /** @var float Command start time */
     protected $executionStart;
diff --git a/src/Handler/CacheTrait.php b/src/Handler/CacheTrait.php
index 9a7c466..83b51e4 100644
--- a/src/Handler/CacheTrait.php
+++ b/src/Handler/CacheTrait.php
@@ -72,14 +72,11 @@ protected static function getKey(RequestInterface $request)
         // Generate headerline for the cache key. X- headers are ignored except those included in the Vary
         $vary = array_flip($request->getHeader('Vary'));
         $headerLine = implode('', array_map(
-            [$request, 'getHeaderLine'],
+            $request->getHeaderLine(...),
             array_filter(
                 array_keys($request->getHeaders()),
-                function ($header) use ($vary) {
-                    return 0 !== stripos($header, 'x-')
-                        || \array_key_exists($header, $vary)
-                    ;
-                }
+                fn($header) => 0 !== stripos((string) $header, 'x-')
+                    || \array_key_exists($header, $vary)
             )
         ));
 
diff --git a/src/Middleware/EventDispatcherMiddleware.php b/src/Middleware/EventDispatcherMiddleware.php
index d759361..c3ce7de 100644
--- a/src/Middleware/EventDispatcherMiddleware.php
+++ b/src/Middleware/EventDispatcherMiddleware.php
@@ -20,21 +20,16 @@ class EventDispatcherMiddleware implements MiddlewareInterface
     protected $eventDispatcher;
 
     /** @var array */
-    protected $events;
-
-    /** @var string */
-    protected $clientId;
+    protected $events = [];
 
     /**
      * Constructor
      *
      * @param string $clientId
      */
-    public function __construct(EventDispatcherInterface $eventDispatcher, $clientId)
+    public function __construct(EventDispatcherInterface $eventDispatcher, protected $clientId)
     {
         $this->eventDispatcher = $eventDispatcher;
-        $this->events = [];
-        $this->clientId = $clientId;
     }
 
     /**
@@ -44,26 +39,24 @@ public function __construct(EventDispatcherInterface $eventDispatcher, $clientId
      */
     public function push(HandlerStack $stack)
     {
-        $stack->push(function (callable $handler) {
-            return function (
-                RequestInterface $request,
-                array $options
-            ) use ($handler) {
-                $promise = $handler($request, $options);
+        $stack->push(fn(callable $handler) => function (
+            RequestInterface $request,
+            array $options
+        ) use ($handler) {
+            $promise = $handler($request, $options);
 
-                return $promise->then(
-                    function (ResponseInterface $response) use ($request) {
-                        $this->sendEvent($request, $response);
+            return $promise->then(
+                function (ResponseInterface $response) use ($request) {
+                    $this->sendEvent($request, $response);
 
-                        return $response;
-                    },
-                    function (\Exception $reason) use ($request) {
-                        $this->sendErrorEvent($request, $reason);
+                    return $response;
+                },
+                function (\Exception $reason) use ($request): never {
+                    $this->sendErrorEvent($request, $reason);
 
-                        throw $reason;
-                    }
-                );
-            };
+                    throw $reason;
+                }
+            );
         }, 'eventDispatcher_dispatch');
 
         return $stack;
diff --git a/src/Middleware/HostForwarderMiddleware.php b/src/Middleware/HostForwarderMiddleware.php
index 5ef022b..92a19d4 100644
--- a/src/Middleware/HostForwarderMiddleware.php
+++ b/src/Middleware/HostForwarderMiddleware.php
@@ -12,11 +12,8 @@
  */
 class HostForwarderMiddleware implements MiddlewareInterface
 {
-    protected array $config;
-
-    public function __construct(array $config)
+    public function __construct(protected array $config)
     {
-        $this->config = $config;
     }
 
     /**
@@ -24,20 +21,18 @@ public function __construct(array $config)
      */
     public function push(HandlerStack $stack): HandlerStack
     {
-        $stack->push(function (callable $handler) {
-            return function (
-                RequestInterface $request,
-                array $options
-            ) use ($handler) {
-                if (isset($this->config['headers'])) {
-                    $lowercaseHeaders = array_change_key_case($this->config['headers']);
-                    if (isset($lowercaseHeaders['host'])) {
-                        $request = $request->withHeader('host', $lowercaseHeaders['host']);
-                    }
+        $stack->push(fn(callable $handler) => function (
+            RequestInterface $request,
+            array $options
+        ) use ($handler) {
+            if (isset($this->config['headers'])) {
+                $lowercaseHeaders = array_change_key_case($this->config['headers']);
+                if (isset($lowercaseHeaders['host'])) {
+                    $request = $request->withHeader('host', $lowercaseHeaders['host']);
                 }
+            }
 
-                return $handler($request, $options);
-            };
+            return $handler($request, $options);
         }, 'hostForwarder_forward');
 
         return $stack;