From 13fdd8baafc0c809bae72661dc5b8990cc3f4084 Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 15:07:54 +0300 Subject: [PATCH 01/22] add Symfony 5 requirement --- DependencyInjection/Configuration.php | 4 ++-- composer.json | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 43c2cf3..038831d 100755 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -18,8 +18,8 @@ class Configuration implements ConfigurationInterface */ public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('tmdb_symfony'); + $treeBuilder = new TreeBuilder('tmdb_symfony'); + $rootNode = $treeBuilder->getRootNode(); $rootNode ->children() diff --git a/composer.json b/composer.json index 4872be3..35d67d9 100755 --- a/composer.json +++ b/composer.json @@ -14,17 +14,17 @@ ], "require": { "php": ">=5.5.0", - "symfony/config": ">=2.7,<5", - "symfony/dependency-injection": ">=2.7,<5", - "symfony/event-dispatcher": ">=2.7,<5", - "symfony/http-kernel": ">=2.7,<5", + "symfony/config": "^4.3.7 || ^5.0", + "symfony/dependency-injection": "^4.3.7 || ^5.0", + "symfony/event-dispatcher": "^4.3.7 || ^5.0", + "symfony/http-kernel": "^4.3.7 || ^5.0", "doctrine/doctrine-cache-bundle": "^1.0", "php-tmdb/api": "^2.1", "twig/twig": "^1.11|^2.0" }, "require-dev": { "phpunit/phpunit": "^4.8||^5.0,<5.4", - "symfony/framework-bundle": ">=2.7,<5" + "symfony/framework-bundle": "^4.3.7 || ^5.0" }, "autoload": { "psr-4": { "Tmdb\\SymfonyBundle\\": "" } From aa159d6df72a8499814802ba02e56db248415b49 Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 15:10:28 +0300 Subject: [PATCH 02/22] update travis config --- .travis.yml | 52 +++++++++++----------------------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8bd74f..519f6a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,8 @@ sudo: false language: php php: - - 5.5 + - 7.3 + - 7.4 - nightly - hhvm @@ -20,46 +21,15 @@ script: vendor/bin/phpunit --verbose matrix: include: - - php: 5.6 - env: [SYMFONY_VERSION="2.7.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.7.*"] - - php: 5.6 - env: [SYMFONY_VERSION="2.8.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.8.*"] - - php: 5.6 - env: [SYMFONY_VERSION="3.0.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.0.*"] - - php: 5.6 - env: [SYMFONY_VERSION="3.1.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.1.*"] - - php: 5.6 - env: [SYMFONY_VERSION="3.2.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.2.*"] - - php: 5.6 - env: [SYMFONY_VERSION="^3.3", SYMFONY_EVENT_DISPATCHER_VERSION="^3.3"] - - - php: 7.0 - env: [SYMFONY_VERSION="2.7.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.7.*"] - - php: 7.0 - env: [SYMFONY_VERSION="2.8.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.8.*"] - - php: 7.0 - env: [SYMFONY_VERSION="3.0.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.0.*"] - - php: 7.0 - env: [SYMFONY_VERSION="3.1.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.1.*"] - - php: 7.0 - env: [SYMFONY_VERSION="3.2.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.2.*"] - - php: 7.0 - env: [SYMFONY_VERSION="^3.3", SYMFONY_EVENT_DISPATCHER_VERSION="^3.3"] - - - php: 7.1 - env: [SYMFONY_VERSION="2.7.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.7.*"] - - php: 7.1 - env: [SYMFONY_VERSION="2.8.*", SYMFONY_EVENT_DISPATCHER_VERSION="2.8.*"] - - php: 7.1 - env: [SYMFONY_VERSION="3.0.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.0.*"] - - php: 7.1 - env: [SYMFONY_VERSION="3.1.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.1.*"] - - php: 7.1 - env: [SYMFONY_VERSION="3.2.*", SYMFONY_EVENT_DISPATCHER_VERSION="3.2.*"] - - php: 7.1 - env: [SYMFONY_VERSION="^3.3", SYMFONY_EVENT_DISPATCHER_VERSION="^3.3"] - - php: 7.1 - env: [SYMFONY_VERSION="^4.0", SYMFONY_EVENT_DISPATCHER_VERSION="^4.0"] + - php: 7.3 + env: [SYMFONY_VERSION="^4.4", SYMFONY_EVENT_DISPATCHER_VERSION="^4.4"] + - php: 7.3 + env: [SYMFONY_VERSION="^5.0", SYMFONY_EVENT_DISPATCHER_VERSION="^5.0"] + + - php: 7.4 + env: [SYMFONY_VERSION="^4.4", SYMFONY_EVENT_DISPATCHER_VERSION="^4.4"] + - php: 7.4 + env: [SYMFONY_VERSION="^5.0", SYMFONY_EVENT_DISPATCHER_VERSION="^5.0"] allow_failures: - php: nightly From 92f4ef60fa49684ad877ba82bbf3408409187be6 Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 15:22:18 +0300 Subject: [PATCH 03/22] update api --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 35d67d9..522f3c0 100755 --- a/composer.json +++ b/composer.json @@ -19,11 +19,11 @@ "symfony/event-dispatcher": "^4.3.7 || ^5.0", "symfony/http-kernel": "^4.3.7 || ^5.0", "doctrine/doctrine-cache-bundle": "^1.0", - "php-tmdb/api": "^2.1", + "php-tmdb/api": "^3.0", "twig/twig": "^1.11|^2.0" }, "require-dev": { - "phpunit/phpunit": "^4.8||^5.0,<5.4", + "phpunit/phpunit": ">=5.7", "symfony/framework-bundle": "^4.3.7 || ^5.0" }, "autoload": { From 13070de2bdf91bfc1c4efa6386969bfde47723dc Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 15:38:05 +0300 Subject: [PATCH 04/22] phpunit update test --- Tests/DependencyInjection/TmdbSymfonyExtensionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php b/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php index 7bebff5..9182d92 100644 --- a/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php +++ b/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php @@ -2,7 +2,7 @@ namespace Tmdb\SymfonyBundle\Tests\DependencyInjection; -use PHPUnit_Framework_TestCase as TestCase; +use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; use Tmdb\SymfonyBundle\Tests\TestKernel; From 929b7a526377c5768037943ffc42652a01a232a1 Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 16:03:15 +0300 Subject: [PATCH 05/22] doctrine cache --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 522f3c0..ecc5644 100755 --- a/composer.json +++ b/composer.json @@ -18,7 +18,6 @@ "symfony/dependency-injection": "^4.3.7 || ^5.0", "symfony/event-dispatcher": "^4.3.7 || ^5.0", "symfony/http-kernel": "^4.3.7 || ^5.0", - "doctrine/doctrine-cache-bundle": "^1.0", "php-tmdb/api": "^3.0", "twig/twig": "^1.11|^2.0" }, From 6fa07ff3efab7298852a37067d8455683dff75ad Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Fri, 10 Apr 2020 16:07:05 +0300 Subject: [PATCH 06/22] symf yaml --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index ecc5644..1e80b28 100755 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "symfony/dependency-injection": "^4.3.7 || ^5.0", "symfony/event-dispatcher": "^4.3.7 || ^5.0", "symfony/http-kernel": "^4.3.7 || ^5.0", + "symfony/yaml": "^4.3.7 || ^5.0", "php-tmdb/api": "^3.0", "twig/twig": "^1.11|^2.0" }, From 46afa5c64a72c09a558626b5ec7b29044f95fd16 Mon Sep 17 00:00:00 2001 From: Ivan Borzenkov Date: Sun, 12 Apr 2020 15:06:06 +0300 Subject: [PATCH 07/22] update twig extenion --- Twig/TmdbExtension.php | 9 +++++---- composer.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Twig/TmdbExtension.php b/Twig/TmdbExtension.php index 8b9e0ed..6de674e 100644 --- a/Twig/TmdbExtension.php +++ b/Twig/TmdbExtension.php @@ -3,10 +3,11 @@ use Tmdb\Client; use Tmdb\Helper\ImageHelper; -use Tmdb\Model\Image; use Tmdb\Repository\ConfigurationRepository; +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; -class TmdbExtension extends \Twig_Extension +class TmdbExtension extends AbstractExtension { /** * @var ImageHelper|null @@ -26,8 +27,8 @@ public function __construct(Client $client) public function getFilters() { return array( - new \Twig_SimpleFilter('tmdb_image_html', array($this, 'getHtml')), - new \Twig_SimpleFilter('tmdb_image_url', array($this, 'getUrl')), + new TwigFilter('tmdb_image_html', array($this, 'getHtml')), + new TwigFilter('tmdb_image_url', array($this, 'getUrl')), ); } diff --git a/composer.json b/composer.json index 1e80b28..bd56246 100755 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "symfony/http-kernel": "^4.3.7 || ^5.0", "symfony/yaml": "^4.3.7 || ^5.0", "php-tmdb/api": "^3.0", - "twig/twig": "^1.11|^2.0" + "twig/twig": "^2.0|^3.0" }, "require-dev": { "phpunit/phpunit": ">=5.7", From 765876fdfe7e3c4c4fc6660ab3d11e2cb53dcd01 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 21:44:27 +0100 Subject: [PATCH 08/22] Release 4.0.0 (#29) Massive changes that implement many PSR standards, and now only supports PHP7.3+, and Symfony 4 and 5. --- .gitattributes | 7 + .github/workflows/coding-standards.yml | 45 +++ .github/workflows/continuous-integration.yml | 89 +++++ .github/workflows/static-analysis.yml.bak | 56 +++ .gitignore | 5 +- .travis.yml | 37 -- ClientConfiguration.php | 54 ++- .../CompilerPass/ConfigurationPass.php | 170 +++++++++ .../CompilerPass/EventDispatchingPass.php | 279 ++++++++++++++ DependencyInjection/Configuration.php | 209 +++++++++-- DependencyInjection/TmdbSymfonyExtension.php | 169 +++++++-- README.md | 246 +++++++++---- Resources/config/repositories.xml | 113 +++--- Resources/config/services.xml | 103 ++++-- Resources/config/twig.xml | 8 +- Resources/test/configuration.json | 97 +++++ .../CompilerPass/ConfigurationPassTest.php | 197 ++++++++++ .../CompilerPass/EventDispatchingPassTest.php | 341 ++++++++++++++++++ Tests/DependencyInjection/TestCase.php | 212 +++++++++++ .../TmdbSymfonyExtensionTest.php | 119 +++++- Tests/TestKernel.php | 39 -- Tests/Twig/TmdbExtensionTest.php | 105 ++++++ Tests/config.yml | 4 - TmdbSymfonyBundle.php | 48 +++ Twig/TmdbExtension.php | 52 ++- composer.json | 38 +- phpcs.xml.dist | 13 + phpstan.neon | 10 + phpunit.xml.dist | 39 +- psalm.xml | 16 + 30 files changed, 2565 insertions(+), 355 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/coding-standards.yml create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .github/workflows/static-analysis.yml.bak delete mode 100644 .travis.yml create mode 100644 DependencyInjection/CompilerPass/ConfigurationPass.php create mode 100644 DependencyInjection/CompilerPass/EventDispatchingPass.php create mode 100644 Resources/test/configuration.json create mode 100644 Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php create mode 100644 Tests/DependencyInjection/CompilerPass/EventDispatchingPassTest.php create mode 100644 Tests/DependencyInjection/TestCase.php delete mode 100644 Tests/TestKernel.php create mode 100644 Tests/Twig/TmdbExtensionTest.php delete mode 100644 Tests/config.yml create mode 100644 phpcs.xml.dist create mode 100644 phpstan.neon create mode 100644 psalm.xml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..22c1526 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +.editorconfig export-ignore +.gitattributes export-ignore +.github export-ignore +.gitignore export-ignore +.php_cs export-ignore +phpstan.neon.dist export-ignore +Tests export-ignore diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml new file mode 100644 index 0000000..8c69385 --- /dev/null +++ b/.github/workflows/coding-standards.yml @@ -0,0 +1,45 @@ +name: "Coding Standards" + +on: ["pull_request"] + +jobs: + coding-standards: + name: "Coding Standards" + runs-on: "ubuntu-20.04" + + strategy: + matrix: + php-version: + - "7.4" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 10 + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + tools: "cs2pr" + + - name: "Cache dependencies installed with Composer" + uses: "actions/cache@v2" + with: + path: "~/.composer/cache" + key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" + restore-keys: "php-${{ matrix.php-version }}-composer-locked-" + + - name: "Install dependencies with Composer" + run: "composer update --no-interaction --no-progress --prefer-dist --prefer-stable" + + - name: "Install git-phpcs" + run: "wget https://github.com/diff-sniffer/git/releases/download/0.3.2/git-phpcs.phar" + + - name: "Fetch head branch" + run: "git remote set-branches --add origin $GITHUB_BASE_REF && git fetch origin $GITHUB_BASE_REF" + + - name: "Run git-phpcs" + run: "php git-phpcs.phar origin/$GITHUB_BASE_REF...$GITHUB_SHA --report=checkstyle | cs2pr" diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000..18be910 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,89 @@ +name: "Continuous Integration" + +on: ["pull_request", "push"] + +env: + fail-fast: true + +jobs: + phpunit: + name: "PHPUnit" + runs-on: "ubuntu-20.04" + env: + SYMFONY_REQUIRE: ${{matrix.symfony-require}} + SYMFONY_DEPRECATIONS_HELPER: ${{matrix.symfony-deprecations-helper}} + + strategy: + matrix: + php-version: + - "7.3" + - "7.4" + deps: + - "normal" + symfony-require: + - "" + symfony-deprecations-helper: + - "" + include: + # Test against latest Symfony 4.3 stable + - symfony-require: "4.3.*" + php-version: "7.3" + deps: "normal" + + # Test against latest Symfony 4.4 dev + - symfony-require: "4.4.*" + php-version: "7.3" + deps: "dev" + + # Test against latest Symfony 5.2 dev + - symfony-require: "5.2.*" + php-version: "7.3" + deps: "dev" + + - php-version: "8.0" + deps: "dev" + symfony-deprecations-helper: "weak" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 2 + + - name: "Install PHP with PCOV" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + coverage: "pcov" + + - name: "Cache dependencies installed with composer" + uses: "actions/cache@v2" + with: + path: "~/.composer/cache" + key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" + restore-keys: "php-${{ matrix.php-version }}-composer-locked-" + + - name: "Install stable dependencies with composer" + run: "composer update --no-interaction --prefer-dist --prefer-stable" + if: "${{ matrix.deps == 'normal' }}" + + - name: "Install dev dependencies with composer" + run: "composer update --no-interaction --prefer-dist" + if: "${{ matrix.deps == 'dev' }}" + + - name: "Install lowest possible dependencies with composer" + run: "composer update --no-interaction --prefer-dist --prefer-stable --prefer-lowest" + if: "${{ matrix.deps == 'low' }}" + + - name: "Run PHPUnit" + run: "vendor/bin/phpunit --coverage-clover=coverage.xml" + + - name: "Upload coverage file" + uses: "actions/upload-artifact@v2" + with: + name: "phpunit-${{ matrix.php-version }}-${{ matrix.deps }}-${{ hashFiles('composer.lock') }}.coverage" + path: "coverage.xml" + + - uses: codecov/codecov-action@v1 + with: + verbose: true diff --git a/.github/workflows/static-analysis.yml.bak b/.github/workflows/static-analysis.yml.bak new file mode 100644 index 0000000..1fd3f32 --- /dev/null +++ b/.github/workflows/static-analysis.yml.bak @@ -0,0 +1,56 @@ +name: Static Analysis + +on: + pull_request: + +jobs: + static-analysis-phpstan: + name: "PHPStan" + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "7.4" + + steps: + - name: "Checkout code" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + tools: cs2pr + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v1" + + - name: "Run PHPStan" + run: "vendor/bin/phpstan analyse --error-format=checkstyle --no-progress -c phpstan.neon | cs2pr" + + static-analysis-psalm: + name: "Psalm" + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "7.4" + + steps: + - name: "Checkout code" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v1" + + - name: "Run a static analysis with vimeo/psalm" + run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)" diff --git a/.gitignore b/.gitignore index 63c79b6..6ae778b 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ composer.lock .idea/ vendor/ - +coverage/ +phpcs.cache +.phpunit.result.cache +.phpcs-cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 519f6a7..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -sudo: false -language: php - -php: - - 7.3 - - 7.4 - - nightly - - hhvm - -cache: - directories: - - ~/.composer/cache - -before_script: - - composer self-update - - if [ "$SYMFONY_VERSION" != "" ]; then composer require --no-update symfony/config:${SYMFONY_VERSION} symfony/dependency-injection:${SYMFONY_VERSION} symfony/event-dispatcher:${SYMFONY_VERSION} symfony/http-kernel:${SYMFONY_VERSION} symfony/framework-bundle:${SYMFONY_VERSION}; fi; - - if [ "$SYMFONY_EVENT_DISPATCHER_VERSION" != "" ]; then composer require --no-update symfony/event-dispatcher:${SYMFONY_EVENT_DISPATCHER_VERSION}; fi; - - composer install --no-interaction --prefer-source --dev - -script: vendor/bin/phpunit --verbose - -matrix: - include: - - php: 7.3 - env: [SYMFONY_VERSION="^4.4", SYMFONY_EVENT_DISPATCHER_VERSION="^4.4"] - - php: 7.3 - env: [SYMFONY_VERSION="^5.0", SYMFONY_EVENT_DISPATCHER_VERSION="^5.0"] - - - php: 7.4 - env: [SYMFONY_VERSION="^4.4", SYMFONY_EVENT_DISPATCHER_VERSION="^4.4"] - - php: 7.4 - env: [SYMFONY_VERSION="^5.0", SYMFONY_EVENT_DISPATCHER_VERSION="^5.0"] - - allow_failures: - - php: nightly - - php: hhvm - fast_finish: true diff --git a/ClientConfiguration.php b/ClientConfiguration.php index f509d19..6ddf0ba 100644 --- a/ClientConfiguration.php +++ b/ClientConfiguration.php @@ -1,35 +1,55 @@ parameters = $options; - - $this->parameters['event_dispatcher'] = $eventDispatcher; - } + ) { + $options['api_token'] = $apiToken; + $options['event_dispatcher']['adapter'] = $eventDispatcher; + $options['http']['client'] = $client; + $options['http']['request_factory'] = $requestFactory; + $options['http']['response_factory'] = $responseFactory; + $options['http']['stream_factory'] = $streamFactory; + $options['http']['uri_factory'] = $uriFactory; - public function setCacheHandler(Cache $handler = null) - { - $this->parameters['cache']['handler'] = $handler; - } + // Library handles it as an api_token + unset($options['bearer_token']); - /** - * @return array - */ - public function all() - { - return $this->parameters; + parent::__construct($options); } } diff --git a/DependencyInjection/CompilerPass/ConfigurationPass.php b/DependencyInjection/CompilerPass/ConfigurationPass.php new file mode 100644 index 0000000..842bdde --- /dev/null +++ b/DependencyInjection/CompilerPass/ConfigurationPass.php @@ -0,0 +1,170 @@ +getParameter('tmdb.options'); + $configDefinition = $container->getDefinition(ClientConfiguration::class); + + // By default the first argument is always referenced to the ApiToken. + if (null !== $bearerToken = $parameters['options']['bearer_token']) { + $configDefinition->replaceArgument(0, new Reference(BearerToken::class)); + } + + $this->setupEventDispatcher($container, $configDefinition, $parameters); + $this->setupHttpClient($container, $configDefinition, $parameters); + } + + /** + * @param ContainerBuilder $container + * @param Definition $configDefinition + * @param array $parameters + * + * @return void + */ + private function setupEventDispatcher( + ContainerBuilder $container, + Definition $configDefinition, + array $parameters + ): void { + if (!$container->hasDefinition($parameters['options']['event_dispatcher']['adapter'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['event_dispatcher']['adapter'], + TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS, + 'tmdb_symfony.options.event_dispatcher.adapter' + ); + } + + $configDefinition->replaceArgument(1, new Reference($parameters['options']['event_dispatcher']['adapter'])); + } + + /** + * @param ContainerBuilder $container + * @param Definition $configDefinition + * @param array $parameters + * + * @return void + */ + private function setupHttpClient( + ContainerBuilder $container, + Definition $configDefinition, + array $parameters + ): void { + if (!$container->hasDefinition($parameters['options']['http']['client'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['http']['client'], + TmdbSymfonyBundle::PSR18_CLIENTS, + 'tmdb_symfony.options.http.client' + ); + } + + if (!$container->hasDefinition($parameters['options']['http']['request_factory'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['http']['request_factory'], + TmdbSymfonyBundle::PSR17_REQUEST_FACTORIES, + 'tmdb_symfony.options.http.request_factory' + ); + } + + if (!$container->hasDefinition($parameters['options']['http']['response_factory'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['http']['response_factory'], + TmdbSymfonyBundle::PSR17_RESPONSE_FACTORIES, + 'tmdb_symfony.options.http.response_factory' + ); + } + + if (!$container->hasDefinition($parameters['options']['http']['stream_factory'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['http']['stream_factory'], + TmdbSymfonyBundle::PSR17_STREAM_FACTORIES, + 'tmdb_symfony.options.http.stream_factory' + ); + } + + if (!$container->hasDefinition($parameters['options']['http']['uri_factory'])) { + $this->tryToAliasAutowiredInterfacesIfPossible( + $container, + $parameters['options']['http']['uri_factory'], + TmdbSymfonyBundle::PSR17_URI_FACTORIES, + 'tmdb_symfony.options.http.uri_factory' + ); + } + + $configDefinition->replaceArgument(2, new Reference($parameters['options']['http']['client'])); + $configDefinition->replaceArgument(3, new Reference($parameters['options']['http']['request_factory'])); + $configDefinition->replaceArgument(4, new Reference($parameters['options']['http']['response_factory'])); + $configDefinition->replaceArgument(5, new Reference($parameters['options']['http']['stream_factory'])); + $configDefinition->replaceArgument(6, new Reference($parameters['options']['http']['uri_factory'])); + } + + /** + * @param ContainerBuilder $container + * @param string $alias + * @param string $tag + * @param string $configurationPath + * @return void + * @throws \RuntimeException + */ + protected function tryToAliasAutowiredInterfacesIfPossible( + ContainerBuilder $container, + string $alias, + string $tag, + string $configurationPath + ): void { + $services = $container->findTaggedServiceIds($tag); + + if (!empty($services)) { + if (count($services) > 1) { + throw new RuntimeException( + sprintf( + 'Trying to automatically configure tmdb symfony bundle, however we found %d applicable services' + . ' ( %s ) for tag "%s", please set one of these explicitly in your configuration under "%s".', + count($services), + implode(', ', array_keys($services)), + $tag, + $configurationPath + ) + ); + } + + $serviceIds = array_keys($services); + $serviceId = array_shift($serviceIds); + + $container->setAlias($alias, $serviceId); + return; + } + + throw new RuntimeException( + sprintf( + 'Unable to find any services tagged with "%s", ' . + 'please set it in the configuration explicitly under "%s".', + $tag, + $configurationPath + ) + ); + } +} diff --git a/DependencyInjection/CompilerPass/EventDispatchingPass.php b/DependencyInjection/CompilerPass/EventDispatchingPass.php new file mode 100644 index 0000000..9a3c1e6 --- /dev/null +++ b/DependencyInjection/CompilerPass/EventDispatchingPass.php @@ -0,0 +1,279 @@ +getParameter('tmdb.options'); + $clientOptions = $parameters['options']; + + if ($container->hasAlias($clientOptions['event_dispatcher']['adapter'])) { + $definition = $container->getDefinition( + $container->getAlias($clientOptions['event_dispatcher']['adapter']) + ); + } else { + $definition = $container->getDefinition($clientOptions['event_dispatcher']['adapter']); + } + + if ($definition->getClass() === EventDispatcher::class) { + $this->handleSymfonyEventDispatcherRegistration($container, $definition, $parameters); + } + } + + /** + * @param ContainerBuilder $container + * @param Definition $eventDispatcher + * @param array $parameters + * + * @return void + */ + private function handleSymfonyEventDispatcherRegistration( + ContainerBuilder $container, + Definition $eventDispatcher, + array $parameters + ): void { + $cacheEnabled = $parameters['cache']['enabled']; + $logEnabled = $parameters['log']['enabled']; + + $requestListener = $cacheEnabled ? + $this->getPsr6CacheRequestListener($container, $parameters) : + $this->getRequestListener($container, $parameters); + + if ($logEnabled) { + $this->handleLoggerListeners($container, $eventDispatcher, $parameters); + } + + $this->registerEventListener( + $eventDispatcher, + RequestEvent::class, + $requestListener->getClass() + ); + + if (null !== $bearerToken = $parameters['options']['bearer_token']) { + $definition = $container->getDefinition(ApiTokenRequestListener::class); + $definition->replaceArgument(0, new Reference(BearerToken::class)); + } + + $this->registerEventListener( + $eventDispatcher, + BeforeRequestEvent::class, + ApiTokenRequestListener::class + ); + + $this->registerEventListener( + $eventDispatcher, + BeforeRequestEvent::class, + ContentTypeJsonRequestListener::class + ); + + $this->registerEventListener( + $eventDispatcher, + BeforeRequestEvent::class, + AcceptJsonRequestListener::class + ); + + $definition = $container->getDefinition(UserAgentRequestListener::class); + $definition->replaceArgument( + 0, + sprintf( + 'php-tmdb/symfony/%s php-tmdb/api/%s', + TmdbSymfonyBundle::VERSION, + Client::VERSION + ) + ); + + $this->registerEventListener( + $eventDispatcher, + BeforeRequestEvent::class, + UserAgentRequestListener::class + ); + } + + /** + * @param ContainerBuilder $container + * @param array $parameters + * @return Definition + */ + private function getRequestListener( + ContainerBuilder $container, + array $parameters + ): Definition { + return $container->getDefinition(RequestListener::class) + ->replaceArgument( + 1, + new Reference($parameters['options']['event_dispatcher']['adapter']) + ); + } + + /** + * @param ContainerBuilder $container + * @param array $parameters + * @return Definition + */ + private function getPsr6CacheRequestListener( + ContainerBuilder $container, + array $parameters + ): Definition { + return $container->getDefinition(Psr6CachedRequestListener::class) + ->replaceArgument(1, new Reference($parameters['options']['event_dispatcher']['adapter'])) + ->replaceArgument(2, new Reference($parameters['cache']['adapter'])) + ->replaceArgument(3, new Reference($parameters['options']['http']['stream_factory'])); + } + + /** + * @param string $event + * @param string $listener + * @param Definition $eventDispatcher + * @param ContainerBuilder $container + * @param array $parameters + * + * @return void + */ + private function handleLogging( + string $event, + string $listener, + Definition $eventDispatcher, + ContainerBuilder $container, + array $parameters + ) { + $options = $parameters[$listener]; + $configEntry = sprintf('tmdb_symfony.log.%s', $listener); + + if (!$options['enabled']) { + return; + } + + if (!$options['adapter']) { + $options['adapter'] = $parameters['adapter']; + } + + if (!$container->hasDefinition($options['adapter']) && !$container->hasAlias($options['adapter'])) { + throw new \RuntimeException(sprintf( + 'Unable to find a definition for the adapter to provide tmdb request logging, you gave "%s" for "%s".', + $options['adapter'], + sprintf('%s.%s', $configEntry, 'adapter') + )); + } + + if (!$container->hasDefinition($options['listener']) && !$container->hasAlias($options['listener'])) { + throw new \RuntimeException(sprintf( + 'Unable to find a definition for the listener to provide tmdb request logging, you gave "%s" for "%s".', + $options['listener'], + sprintf('%s.%s', $configEntry, 'listener') + )); + } + + if (!$container->hasDefinition($options['formatter']) && !$container->hasAlias($options['formatter'])) { + throw new \RuntimeException(sprintf( + 'Unable to find a definition for the formatter to provide tmdb request logging, ' . + 'you gave "%s" for "%s".', + $options['formatter'], + sprintf('%s.%s', $configEntry, 'formatter') + )); + } + + $adapter = $container->hasAlias($options['adapter']) ? + $container->getAlias($options['adapter']) : + $options['adapter']; + + $listenerDefinition = $container->getDefinition($options['listener']); + $listenerDefinition->replaceArgument(0, new Reference($adapter)); + $listenerDefinition->replaceArgument(1, new Reference($options['formatter'])); + + // Cannot assume if this was replaced this parameter will be kept. + if ($listenerDefinition->getClass() === LogHydrationListener::class) { + $listenerDefinition->replaceArgument( + 2, + $parameters['hydration']['with_hydration_data'] + ); + } + + $this->registerEventListener( + $eventDispatcher, + $event, + $listenerDefinition->getClass() + ); + } + + /** + * Register listeners for logging. + * + * @param ContainerBuilder $container + * @param Definition $eventDispatcher + * @param array $parameters + * + * @return void + */ + private function handleLoggerListeners(ContainerBuilder $container, Definition $eventDispatcher, array $parameters): void + { + $listeners = [ + BeforeRequestEvent::class => 'request_logging', + ResponseEvent::class => 'response_logging', + HttpClientExceptionEvent::class => 'client_exception_logging', + TmdbExceptionEvent::class => 'api_exception_logging', + BeforeHydrationEvent::class => 'hydration' + ]; + + foreach ($listeners as $event => $listener) { + $this->handleLogging( + $event, + $listener, + $eventDispatcher, + $container, + $parameters['log'] + ); + } + } + + /** + * @param Definition $eventDispatcher + * @param string $event + * @param string $reference + */ + private function registerEventListener( + Definition $eventDispatcher, + string $event, + string $reference + ): void { + $eventDispatcher->addMethodCall( + 'addListener', + [ + $event, + new Reference($reference) + ] + ); + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 038831d..4397a8f 100755 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1,16 +1,18 @@ getRootNode(); + $this->addRootChildren($rootNode); + $this->addOptionsSection($rootNode); + $this->addLogSection($rootNode); + $this->addCacheSection($rootNode); + + return $treeBuilder; + } + + /** + * @param ArrayNodeDefinition $rootNode + * + * @return void + */ + private function addRootChildren(ArrayNodeDefinition $rootNode): void + { $rootNode + ->beforeNormalization() + ->ifTrue(function ($v) { + return isset($v['api_key']) && !empty($v['api_key']); + }) + ->then(function ($v) { + $v['options']['api_token'] = $v['api_key']; + + return $v; + }) + ->end() + ->addDefaultsIfNotSet() ->children() ->scalarNode('api_key')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('session_token')->defaultValue(null)->end() ->arrayNode('repositories')->canBeDisabled()->end() ->arrayNode('twig_extension')->canBeDisabled()->end() + ->booleanNode('disable_legacy_aliases')->defaultFalse()->end() + ->end() + ; + } + + /** + * @param ArrayNodeDefinition $rootNode + * + * @return void + */ + private function addOptionsSection(ArrayNodeDefinition $rootNode): void + { + $rootNode + ->children() ->arrayNode('options') ->addDefaultsIfNotSet() ->children() - ->scalarNode('adapter')->defaultValue(null)->end() - ->scalarNode('secure')->defaultValue(true)->end() + ->scalarNode('api_token') + ->defaultValue(null) + ->info('Will be set by root api_key') + ->end() + ->scalarNode('bearer_token') + ->defaultValue(null) + ->info('If set will be used instead of api token') + ->end() + ->scalarNode('secure')->defaultTrue()->end() ->scalarNode('host')->defaultValue(Client::TMDB_URI)->end() - ->scalarNode('session_token')->defaultValue(null)->end() - ->arrayNode('cache') - ->canBeDisabled() + ->scalarNode('guest_session_token')->defaultValue(null)->end() + ->arrayNode('event_dispatcher') + ->info('Reference to a service which implements PSR-14 Event Dispatcher') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('adapter') + ->isRequired()->cannotBeEmpty() + ->defaultValue('Psr\EventDispatcher\EventDispatcherInterface') + ->end() + ->end() + ->end() + ->arrayNode('http') + ->addDefaultsIfNotSet() ->children() - ->scalarNode('path')->defaultValue('%kernel.cache_dir%/themoviedb')->end() - ->scalarNode('handler')->defaultValue(null)->end() - ->scalarNode('subscriber')->defaultValue(null)->end() + ->scalarNode('client') + ->defaultValue('Psr\Http\Client\ClientInterface') + ->info('Reference to a service which implements PSR-18 HTTP Client') + ->end() + ->scalarNode('request_factory') + ->defaultValue('Psr\Http\Message\RequestFactoryInterface') + ->info('Reference to a service which implements PSR-17 HTTP Factories') + ->end() + ->scalarNode('response_factory') + ->defaultValue('Psr\Http\Message\ResponseFactoryInterface') + ->info('Reference to a service which implements PSR-17 HTTP Factories') + ->end() + ->scalarNode('stream_factory') + ->defaultValue('Psr\Http\Message\StreamFactoryInterface') + ->info('Reference to a service which implements PSR-17 HTTP Factories') + ->end() + ->scalarNode('uri_factory') + ->defaultValue('Psr\Http\Message\UriFactoryInterface') + ->info('Reference to a service which implements PSR-17 HTTP Factories') + ->end() ->end() ->end() - ->arrayNode('log') - ->canBeEnabled() + ->arrayNode('hydration') + ->addDefaultsIfNotSet() ->children() - ->scalarNode('level')->defaultValue('DEBUG')->end() - ->scalarNode('path')->defaultValue('%kernel.logs_dir%/themoviedb.log')->end() - ->scalarNode('handler')->defaultValue(null)->end() - ->scalarNode('subscriber')->defaultValue(null)->end() + ->booleanNode('event_listener_handles_hydration')->defaultFalse()->end() + ->arrayNode('only_for_specified_models') + ->scalarPrototype()->end() + ->end() ->end() ->end() ->end() ->end() - ->end(); + ->end() + ; + } - return $treeBuilder; + /** + * @param ArrayNodeDefinition $rootNode + * + * @return void + */ + private function addLogSection(ArrayNodeDefinition $rootNode): void + { + $rootNode + ->children() + ->arrayNode('log') + ->addDefaultsIfNotSet() + ->canBeEnabled() + ->children() + ->scalarNode('adapter') + ->defaultValue('Psr\Log\LoggerInterface') + ->info('When registering a channel in monolog as "tmdb" for example, monolog.logger.tmdb') + ->end() + ->arrayNode('request_logging') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('enabled')->defaultValue('%kernel.debug%')->end() + ->scalarNode('listener')->defaultValue(LogHttpMessageListener::class)->end() + ->scalarNode('adapter')->defaultValue(null)->end() + ->scalarNode('formatter')->defaultValue(SimpleHttpMessageFormatter::class)->end() + ->end() + ->end() + ->arrayNode('response_logging') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('enabled')->defaultValue('%kernel.debug%')->end() + ->scalarNode('listener')->defaultValue(LogHttpMessageListener::class)->end() + ->scalarNode('adapter')->defaultValue(null)->end() + ->scalarNode('formatter')->defaultValue(SimpleHttpMessageFormatter::class)->end() + ->end() + ->end() + ->arrayNode('api_exception_logging') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('enabled')->defaultValue('%kernel.debug%')->end() + ->scalarNode('listener')->defaultValue(LogApiErrorListener::class)->end() + ->scalarNode('adapter')->defaultValue(null)->end() + ->scalarNode('formatter')->defaultValue(SimpleTmdbApiExceptionFormatter::class)->end() + ->end() + ->end() + ->arrayNode('client_exception_logging') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('enabled')->defaultValue('%kernel.debug%')->end() + ->scalarNode('listener')->defaultValue(LogHttpMessageListener::class)->end() + ->scalarNode('adapter')->defaultValue(null)->end() + ->scalarNode('formatter')->defaultValue(SimpleHttpMessageFormatter::class)->end() + ->end() + ->end() + ->arrayNode('hydration') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('enabled')->defaultValue('%kernel.debug%')->end() + ->scalarNode('listener')->defaultValue(LogHydrationListener::class)->end() + ->scalarNode('adapter')->defaultValue(null)->end() + ->scalarNode('formatter')->defaultValue(SimpleHydrationFormatter::class)->end() + ->booleanNode('with_hydration_data')->defaultFalse()->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + /** + * @param ArrayNodeDefinition $rootNode + * + * @return void + */ + private function addCacheSection(ArrayNodeDefinition $rootNode): void + { + $rootNode + ->children() + ->arrayNode('cache') + ->addDefaultsIfNotSet() + ->canBeEnabled() + ->children() + ->scalarNode('adapter')->defaultValue('Psr\Cache\CacheItemPoolInterface')->end() + ->end() + ->end() + ->end() + ; } } diff --git a/DependencyInjection/TmdbSymfonyExtension.php b/DependencyInjection/TmdbSymfonyExtension.php index 6194347..c295250 100644 --- a/DependencyInjection/TmdbSymfonyExtension.php +++ b/DependencyInjection/TmdbSymfonyExtension.php @@ -2,70 +2,183 @@ namespace Tmdb\SymfonyBundle\DependencyInjection; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Tmdb\Token\Api\ApiToken; +use Tmdb\Client; +use Tmdb\Repository\AccountRepository; +use Tmdb\Repository\AuthenticationRepository; +use Tmdb\Repository\CertificationRepository; +use Tmdb\Repository\ChangesRepository; +use Tmdb\Repository\CollectionRepository; +use Tmdb\Repository\CompanyRepository; +use Tmdb\Repository\ConfigurationRepository; +use Tmdb\Repository\CreditsRepository; +use Tmdb\Repository\DiscoverRepository; +use Tmdb\Repository\FindRepository; +use Tmdb\Repository\GenreRepository; +use Tmdb\Repository\JobsRepository; +use Tmdb\Repository\KeywordRepository; +use Tmdb\Repository\ListRepository; +use Tmdb\Repository\MovieRepository; +use Tmdb\Repository\NetworkRepository; +use Tmdb\Repository\PeopleRepository; +use Tmdb\Repository\ReviewRepository; +use Tmdb\Repository\SearchRepository; +use Tmdb\Repository\TvEpisodeRepository; +use Tmdb\Repository\TvRepository; +use Tmdb\Repository\TvSeasonRepository; +use Tmdb\SymfonyBundle\ClientConfiguration; +use Tmdb\SymfonyBundle\Twig\TmdbExtension; /** - * This is the class that loads and manages your bundle configuration - * - * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} + * Class TmdbSymfonyExtension + * @package Tmdb\SymfonyBundle\DependencyInjection */ class TmdbSymfonyExtension extends Extension { /** - * {@inheritDoc} + * @param array $configs + * @param ContainerBuilder $container + * @return void */ public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); - $container->setParameter('tmdb.api_key', $config['api_key']); + $container->setParameter('tmdb.api_token', $config['options']['api_token']); + $container->setParameter('tmdb.bearer_token', $config['options']['bearer_token']); + + if (!$config['disable_legacy_aliases']) { + $this->handleLegacyGeneralAliases($container); + } if ($config['repositories']['enabled']) { $loader->load('repositories.xml'); + + if (!$config['disable_legacy_aliases']) { + $this->handleLegacyRepositoryAliases($container); + } } if ($config['twig_extension']['enabled']) { $loader->load('twig.xml'); - } - - $options = $config['options']; - - if ($options['cache']['enabled']) { - $options = $this->handleCache($container, $options); - } - if ($options['log']['enabled']) { - $options = $this->handleLog($options); + if (!$config['disable_legacy_aliases']) { + $this->handleLegacyTwigExtensionAlias($container); + } } - $container->setParameter('tmdb.options', $options); + $container->setParameter('tmdb.options', $config); + $container->setParameter('tmdb.client.options', $config['options']); } - protected function handleCache(ContainerBuilder $container, $options) + /** + * Alias mapping for legacy constructs; public to abuse within test suite. + * + * @return array + */ + public function getLegacyAliasMapping() { - if (null !== $handler = $options['cache']['handler']) { - $serviceId = sprintf('doctrine_cache.providers.%s', $options['cache']['handler']); + return [ + 'repositories' => [ + 'tmdb.authentication_repository' => AuthenticationRepository::class, + 'tmdb.account_repository' => AccountRepository::class, + 'tmdb.certification_repository' => CertificationRepository::class, + 'tmdb.changes_repository' => ChangesRepository::class, + 'tmdb.collection_repository' => CollectionRepository::class, + 'tmdb.company_repository' => CompanyRepository::class, + 'tmdb.configuration_repository' => ConfigurationRepository::class, + 'tmdb.credits_repository' => CreditsRepository::class, + 'tmdb.discover_repository' => DiscoverRepository::class, + 'tmdb.find_repository' => FindRepository::class, + 'tmdb.genre_repository' => GenreRepository::class, + 'tmdb.jobs_repository' => JobsRepository::class, + 'tmdb.keyword_repository' => KeywordRepository::class, + 'tmdb.list_repository' => ListRepository::class, + 'tmdb.movie_repository' => MovieRepository::class, + 'tmdb.network_repository' => NetworkRepository::class, + 'tmdb.people_repository' => PeopleRepository::class, + 'tmdb.review_repository' => ReviewRepository::class, + 'tmdb.search_repository' => SearchRepository::class, + 'tmdb.tv_repository' => TvRepository::class, + 'tmdb.tv_episode_repository' => TvEpisodeRepository::class, + 'tmdb.tv_season_repository' => TvSeasonRepository::class, + ], + 'general' => [ + 'tmdb.client' => Client::class, + 'tmdb.api_token' => ApiToken::class, + 'tmdb.configuration' => ClientConfiguration::class + ], + 'twig' => [ + 'tmdb.twig.image_extension' => TmdbExtension::class + ] + ]; + } - $container->setAlias('tmdb.cache_handler', new Alias($serviceId, false)); + /** + * Performs mapping of legacy aliases to their new service identifiers. + * + * @todo major release remove alias mapping of legacy muck :-) + * + * @param ContainerBuilder $container + * @param array $mapping + * + * @return void + */ + protected function performAliasMapping(ContainerBuilder $container, array $mapping = []): void + { + foreach ($mapping as $legacyAlias => $newAlias) { + // @todo fix alias with public/private properties + $container + ->setAlias($legacyAlias, new Alias($newAlias)) + ; } + } - return $options; + /** + * Handle general lgeacy aliases. + * + * @param ContainerBuilder $container + * + * @return void + */ + protected function handleLegacyGeneralAliases(ContainerBuilder $container): void + { + $mapping = $this->getLegacyAliasMapping(); + $this->performAliasMapping($container, $mapping['general']); } - protected function handleLog($options) + /** + * Map repository legacy aliases + * + * @param ContainerBuilder $container + * + * @return void + */ + protected function handleLegacyRepositoryAliases(ContainerBuilder $container): void { - if (null !== $handler = $options['log']['handler']) { - $options['log']['handler'] = !is_string($handler) ? $handler: new $handler(); - } + $mapping = $this->getLegacyAliasMapping(); + $this->performAliasMapping($container, $mapping['repositories']); + } - return $options; + /** + * Map twig legacy aliases + * + * @param ContainerBuilder $container + * + * @return void + */ + protected function handleLegacyTwigExtensionAlias(ContainerBuilder $container): void + { + $mapping = $this->getLegacyAliasMapping(); + $this->performAliasMapping($container, $mapping['twig']); } } diff --git a/README.md b/README.md index b2847b7..3f3e142 100755 --- a/README.md +++ b/README.md @@ -1,87 +1,155 @@ -Description ----------------- +# A Symfony Bundle for use together with the [php-tmdb/api](https://github.com/php-tmdb/api) TMDB API Wrapper. + +[![License](https://poser.pugx.org/php-tmdb/symfony/license.png)](https://packagist.org/packages/php-tmdb/symfony) +[![License](https://img.shields.io/github/v/tag/php-tmdb/symfony)](https://github.com/php-tmdb/symfony/releases) +[![Build Status](https://img.shields.io/github/workflow/status/php-tmdb/symfony/Continuous%20Integration?label=phpunit)](https://github.com/php-tmdb/symfony/actions?query=workflow%3A%22Continuous+Integration%22) +[![Build Status](https://img.shields.io/github/workflow/status/php-tmdb/symfony/Coding%20Standards?label=phpcs)](https://github.com/php-tmdb/symfony/actions?query=workflow%3A%22Coding+Standards%22) +[![codecov](https://img.shields.io/codecov/c/github/php-tmdb/symfony?token=gTM9AiO5vH)](https://codecov.io/gh/php-tmdb/symfony) +[![PHP](https://img.shields.io/badge/php->=7.3,%20>=8.0-8892BF.svg)](https://packagist.org/packages/php-tmdb/symfony) +[![Total Downloads](https://poser.pugx.org/php-tmdb/symfony/downloads.svg)](https://packagist.org/packages/php-tmdb/symfony) -A Symfony Bundle for use together with the [php-tmdb/api](https://github.com/php-tmdb/api) TMDB API Wrapper. +Compatible with Symfony 4 and 5, PHP 7.3 and up. Installation ------------ -[Install Composer](https://getcomposer.org/doc/00-intro.md) +- [Install Composer](https://getcomposer.org/doc/00-intro.md) +- [Install php-tmdb/api dependencies](https://github.com/php-tmdb/api/tree/release/4.0.0#installation) + - For development within Symfony we recommend making use of Symfony's PSR-18 HTTP Client _`Symfony\Component\HttpClient\Psr18Client`_, + as when non-cached results pass your profiler will be filled with data. -Then require the package: +Then require the bundle: ``` -composer require php-tmdb/symfony +composer require php-tmdb/symfony:^4 ``` Configuration ---------------- -Register the bundle in `app/AppKernel.php`: +Register the bundle in `app/bundles.php`: ```php - public function registerBundles() - { - ... - new Tmdb\SymfonyBundle\TmdbSymfonyBundle() - ... - } -``` + ['all' => true], +]; ``` - -Add to your `app/config/config.yml` the following: +Add to your `app/config/config.yml` the following, or replace values with services of your choice ( PSR-18 Http Client / PSR-17 Factories ): ```yaml tmdb_symfony: api_key: YOUR_API_KEY_HERE + options: + http: + client: Symfony\Component\HttpClient\Psr18Client + request_factory: Nyholm\Psr7\Factory\Psr17Factory + response_factory: Nyholm\Psr7\Factory\Psr17Factory + stream_factory: Nyholm\Psr7\Factory\Psr17Factory + uri_factory: Nyholm\Psr7\Factory\Psr17Factory +``` + +`services.yaml`: + +```yaml +services: + Symfony\Component\HttpClient\Psr18Client: + class: Symfony\Component\HttpClient\Psr18Client + + Nyholm\Psr7\Factory\Psr17Factory: + class: Nyholm\Psr7\Factory\Psr17Factory ``` __Configure caching__ -First create a new doctrine_cache provider with a caching provider of your preference. +You can use any PSR-6 cache you wish to use, we will simply use symfony's cache. + +When making use of caching, make sure to also include `php-http/cache-plugin` in composer, this plugin handles the logic for us, +so we don't have to re-invent the wheel. + +You are however also free to choose to implement your own cache listener, or add the caching logic inside the http client of your choice. + +```shell script +composer require php-http/cache-plugin:^1.7 +``` + +First off configure the cache pool in symfony `config/cache.yaml`: ```yaml -doctrine_cache: - providers: - tmdb_cache: - file_system: - directory: %kernel.cache_dir%/tmdb +framework: + cache: + pools: + cache.tmdb: + adapter: cache.adapter.filesystem + default_lifetime: 86400 ``` -Then update the tmdb configuration with the alias: +Then in your `tmdb_symfony.yaml` configuration enable the cache and reference this cache pool: ```yaml tmdb_symfony: - options: - cache: - enabled: true - handler: tmdb_cache + api_key: YOUR_API_KEY_HERE + cache: + enabled: true + adapter: cache.tmdb ``` -This caching system will adhere to the TMDB API max-age values, if you have different needs like long TTL's -you'd have to make your own implementation. We would be happy to integrate more options, so please contribute. - __Want to make use of logging?__ +Logging capabilities as of `4.0` allow you to make a fine-grained configuration. + +You can use any PSR-3 logger you wish to use, we will simply use monolog. + +First off configure the monolog and add a channel and handler: + +```yaml +monolog: + channels: + - tmdb + handlers: + tmdb: + type: stream + path: "%kernel.logs_dir%/php-tmdb--symfony.%kernel.environment%.log" + level: info + channels: ["tmdb"] +``` + +Then in your `tmdb_symfony.yaml` configuration: + ```yaml tmdb_symfony: - api_key: YOUR_API_KEY_HERE - options: - cache: - enabled: true - log: - enabled: true - #path: "%kernel.logs_dir%/tmdb.log" + api_key: YOUR_API_KEY_HERE + log: + enabled: true + adapter: monolog.logger.tmdb + hydration: + enabled: true + with_hydration_data: false # We would only recommend to enable this with an in-memory logger, so you have access to the hydration data within the profiler. + adapter: null # you can set different adapters for different logs, leave null to use the main adapter. + listener: Tmdb\Event\Listener\Logger\LogHydrationListener + formatter: Tmdb\Formatter\Hydration\SimpleHydrationFormatter + request_logging: + enabled: true + adapter: null # you can set different adapters for different logs, leave null to use the main adapter. + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter + response_logging: + enabled: true + adapter: null # you can set different adapters for different logs, leave null to use the main adapter. + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter + api_exception_logging: + enabled: true + adapter: null # you can set different adapters for different logs, leave null to use the main adapter. + listener: Tmdb\Event\Listener\Logger\LogApiErrorListener + formatter: Tmdb\Formatter\TmdbApiException\SimpleTmdbApiExceptionFormatter + client_exception_logging: + enabled: true + adapter: null # you can set different adapters for different logs, leave null to use the main adapter. + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter ``` __Disable repositories :__ @@ -111,30 +179,75 @@ tmdb_symfony: enabled: false ``` +__Disable legacy aliases :__ + +_Set to true to remove all legacy alises ( e.g. `tmdb.client` or `tmdb.movie_repository` )._ + +```yaml +tmdb_symfony: + api_key: YOUR_API_KEY_HERE + disable_legacy_aliases: true +``` + __Full configuration with defaults :__ ```yaml tmdb_symfony: api_key: YOUR_API_KEY_HERE + cache: + enabled: true + adapter: cache.tmdb + log: + enabled: true + adapter: monolog.logger.tmdb + hydration: + enabled: true + with_hydration_data: false + adapter: null + listener: Tmdb\Event\Listener\Logger\LogHydrationListener + formatter: Tmdb\Formatter\Hydration\SimpleHydrationFormatter + request_logging: + enabled: true + adapter: null + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter + response_logging: + enabled: true + adapter: null + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter + api_exception_logging: + enabled: true + adapter: null + listener: Tmdb\Event\Listener\Logger\LogApiErrorListener + formatter: Tmdb\Formatter\TmdbApiException\SimpleTmdbApiExceptionFormatter + client_exception_logging: + enabled: true + adapter: null + listener: Tmdb\Event\Listener\Logger\LogHttpMessageListener + formatter: Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter + options: + bearer_token: YOUR_BEARER_TOKEN_HERE + http: + client: Symfony\Component\HttpClient\Psr18Client + request_factory: Nyholm\Psr7\Factory\Psr17Factory + response_factory: Nyholm\Psr7\Factory\Psr17Factory + stream_factory: Nyholm\Psr7\Factory\Psr17Factory + uri_factory: Nyholm\Psr7\Factory\Psr17Factory + secure: true + host: api.themoviedb.org/3 + guest_session_token: null + event_dispatcher: + adapter: event_dispatcher + hydration: + event_listener_handles_hydration: false + only_for_specified_models: { } + api_token: YOUR_API_KEY_HERE # you don't have to set this if you set it at the root level + session_token: null repositories: - enabled: true # Set to false to disable repositories + enabled: true twig_extension: - enabled: true # Set to false to disable twig extensions - options: - adapter: null - secure: true # Set to false to disable https - host: "api.themoviedb.org/3/" - session_token: null - cache: - enabled: true # Set to false to disable cache - path: "%kernel.cache_dir%/themoviedb" - handler: null - subscriber: null - log: - enabled: false # Set to true to enable log - path: "%kernel.logs_dir%/themoviedb.log" - level: DEBUG - handler: null - subscriber: null + enabled: true + disable_legacy_aliases: false ``` Usage @@ -143,13 +256,13 @@ Usage Obtaining the client ```php -$client = $this->get('tmdb.client'); +$client = $this->get(Tmdb\Client::class); ``` Obtaining repositories ```php -$movie = $this->get('tmdb.movie_repository')->load(13); +$movie = $this->get(\Tmdb\Repository\MovieRepository::class)->load(13); ``` An overview of all the repositories can be found in the services configuration [repositories.xml](https://github.com/php-tmdb/symfony/blob/master/Resources/config/repositories.xml). @@ -163,3 +276,4 @@ There is also a Twig helper that makes use of the `Tmdb\Helper\ImageHelper` to o ``` **For all all other interactions take a look at [php-tmdb/api](https://github.com/php-tmdb/api).** + diff --git a/Resources/config/repositories.xml b/Resources/config/repositories.xml index c1390e5..d1848eb 100755 --- a/Resources/config/repositories.xml +++ b/Resources/config/repositories.xml @@ -4,110 +4,93 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - Tmdb\Repository\AuthenticationRepository - Tmdb\Repository\AccountRepository - Tmdb\Repository\CertificationRepository - Tmdb\Repository\ChangesRepository - Tmdb\Repository\CollectionRepository - Tmdb\Repository\CompanyRepository - Tmdb\Repository\ConfigurationRepository - Tmdb\Repository\CreditsRepository - Tmdb\Repository\DiscoverRepository - Tmdb\Repository\FindRepository - Tmdb\Repository\GenreRepository - Tmdb\Repository\JobsRepository - Tmdb\Repository\KeywordRepository - Tmdb\Repository\ListRepository - Tmdb\Repository\MovieRepository - Tmdb\Repository\NetworkRepository - Tmdb\Repository\PeopleRepository - Tmdb\Repository\ReviewRepository - Tmdb\Repository\SearchRepository - Tmdb\Repository\TvRepository - Tmdb\Repository\TvEpisodeRepository - Tmdb\Repository\TvSeasonRepository - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index a32e439..e6777ca 100755 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -4,34 +4,93 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - - Tmdb\Client - Tmdb\SymfonyBundle\ClientConfiguration - Tmdb\ApiToken - Tmdb\RequestToken - Tmdb\SessionToken - - - - - + + + + + + %tmdb.api_token% + + + + %tmdb.bearer_token% - - %tmdb.api_key% + + - - - %tmdb.options% + + + + + + + + + + + + + + + - - - + + + + + + + + + + %tmdb.client.options% + + + + + + + + %tmdb.client.options% + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/config/twig.xml b/Resources/config/twig.xml index 13a908c..9c9a039 100755 --- a/Resources/config/twig.xml +++ b/Resources/config/twig.xml @@ -4,13 +4,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - Tmdb\SymfonyBundle\Twig\TmdbExtension - - - - + + diff --git a/Resources/test/configuration.json b/Resources/test/configuration.json new file mode 100644 index 0000000..cda945d --- /dev/null +++ b/Resources/test/configuration.json @@ -0,0 +1,97 @@ +{ + "images": { + "base_url": "http://image.tmdb.org/t/p/", + "secure_base_url": "https://image.tmdb.org/t/p/", + "backdrop_sizes": [ + "w300", + "w780", + "w1280", + "original" + ], + "logo_sizes": [ + "w45", + "w92", + "w154", + "w185", + "w300", + "w500", + "original" + ], + "poster_sizes": [ + "w92", + "w154", + "w185", + "w342", + "w500", + "w780", + "original" + ], + "profile_sizes": [ + "w45", + "w185", + "h632", + "original" + ], + "still_sizes": [ + "w92", + "w185", + "w300", + "original" + ] + }, + "change_keys": [ + "adult", + "air_date", + "also_known_as", + "alternative_titles", + "biography", + "birthday", + "budget", + "cast", + "certifications", + "character_names", + "created_by", + "crew", + "deathday", + "episode", + "episode_number", + "episode_run_time", + "freebase_id", + "freebase_mid", + "general", + "genres", + "guest_stars", + "homepage", + "images", + "imdb_id", + "languages", + "name", + "network", + "origin_country", + "original_name", + "original_title", + "overview", + "parts", + "place_of_birth", + "plot_keywords", + "production_code", + "production_companies", + "production_countries", + "releases", + "revenue", + "runtime", + "season", + "season_number", + "season_regular", + "spoken_languages", + "status", + "tagline", + "title", + "translations", + "tvdb_id", + "tvrage_id", + "type", + "video", + "videos" + ] +} \ No newline at end of file diff --git a/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php b/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php new file mode 100644 index 0000000..f523a0e --- /dev/null +++ b/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php @@ -0,0 +1,197 @@ +createFullConfiguration(); + $this->registerBasicServices($container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $this->doBasicAssertionsBasedOnFullOrMinimalConfig($container); + } + + /** + * @test + * @group DependencyInjection + */ + public function testProcessMinimalConfiguration() + { + $container = $this->createMinimalConfiguration(); + $this->registerBasicServices($container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $this->doBasicAssertionsBasedOnFullOrMinimalConfig($container); + } + + /** + * @test + * @group DependencyInjection + */ + public function testAutowiring() + { + $container = new ContainerBuilder(); + + $eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + $container->register(get_class($eventDispatcherMock))->addTag(TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS); + + $httpClientMock = $this->createMock(ClientInterface::class); + $container->register(get_class($httpClientMock))->addTag(TmdbSymfonyBundle::PSR18_CLIENTS); + + $requestFactoryMock = $this->createMock(RequestFactoryInterface::class); + $container->register(get_class($requestFactoryMock))->addTag(TmdbSymfonyBundle::PSR17_REQUEST_FACTORIES); + + $responseFactoryMock = $this->createMock(ResponseFactoryInterface::class); + $container->register(get_class($responseFactoryMock))->addTag(TmdbSymfonyBundle::PSR17_RESPONSE_FACTORIES); + + $streamFactoryMock = $this->createMock(StreamFactoryInterface::class); + $container->register(get_class($streamFactoryMock))->addTag(TmdbSymfonyBundle::PSR17_STREAM_FACTORIES); + + $uriFactoryMock = $this->createMock(UriFactoryInterface::class); + $container->register(get_class($uriFactoryMock))->addTag(TmdbSymfonyBundle::PSR17_URI_FACTORIES); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $this->assertAlias($container, get_class($eventDispatcherMock), EventDispatcherInterface::class); + $this->assertAlias($container, get_class($httpClientMock), ClientInterface::class); + $this->assertAlias($container, get_class($requestFactoryMock), RequestFactoryInterface::class); + $this->assertAlias($container, get_class($responseFactoryMock), ResponseFactoryInterface::class); + $this->assertAlias($container, get_class($streamFactoryMock), StreamFactoryInterface::class); + $this->assertAlias($container, get_class($uriFactoryMock), UriFactoryInterface::class); + } + + /** + * @test + * @group DependencyInjection + */ + public function testAutowiringFailsWithUndiscoveredServices() + { + $this->expectException(\RuntimeException::class); + $container = new ContainerBuilder(); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + } + + /** + * @test + * @group DependencyInjection + */ + public function testAutowiringFailsWithSeveralDiscoveredServices() + { + $this->expectException(\RuntimeException::class); + + $container = new ContainerBuilder(); + + $eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + // mocking the same interface results in the same object? Doesn't matter for test though. + $eventDispatcherMockTwo = $this->createMock(ClientInterface::class); + + $container->register(get_class($eventDispatcherMock))->addTag(TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS); + $container->register(get_class($eventDispatcherMockTwo))->addTag(TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + } + + /** + * @test + * @group DependencyInjection + */ + public function testProcessBearerToken() + { + $config = $this->getFullConfig(); + $config['options']['bearer_token'] = 'bearer_token'; + + $container = $this->createManualConfiguration($config); + $this->registerBasicServices($container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $this->assertEquals( + BearerToken::class, + $container->getDefinition('Tmdb\SymfonyBundle\ClientConfiguration')->getArgument(0)->__toString() + ); + } + + /** + * @param ContainerBuilder $container + */ + protected function registerBasicServices(ContainerBuilder $container) + { + $container->register(EventDispatcherInterface::class); + $container->register(ClientInterface::class); + $container->register(RequestFactoryInterface::class); + $container->register(ResponseFactoryInterface::class); + $container->register(StreamFactoryInterface::class); + $container->register(UriFactoryInterface::class); + } + + /** + * @param ContainerBuilder $container + */ + protected function doBasicAssertionsBasedOnFullOrMinimalConfig(ContainerBuilder $container) + { + $this->assertClientConfigurationEquals($container, ApiToken::class, 0); + $this->assertClientConfigurationEquals($container, EventDispatcherInterface::class, 1); + $this->assertClientConfigurationEquals($container, ClientInterface::class, 2); + $this->assertClientConfigurationEquals($container, RequestFactoryInterface::class, 3); + $this->assertClientConfigurationEquals($container, ResponseFactoryInterface::class, 4); + $this->assertClientConfigurationEquals($container, StreamFactoryInterface::class, 5); + $this->assertClientConfigurationEquals($container, UriFactoryInterface::class, 6); + } + + /** + * @param ContainerBuilder $container + * @param string $expectedServiceId + * @param int $argument + */ + protected function assertClientConfigurationEquals( + ContainerBuilder $container, + string $expectedServiceId, + int $argument + ) { + $this->assertEquals( + $expectedServiceId, + $container->getDefinition('Tmdb\SymfonyBundle\ClientConfiguration')->getArgument($argument)->__toString() + ); + } +} diff --git a/Tests/DependencyInjection/CompilerPass/EventDispatchingPassTest.php b/Tests/DependencyInjection/CompilerPass/EventDispatchingPassTest.php new file mode 100644 index 0000000..b472e5b --- /dev/null +++ b/Tests/DependencyInjection/CompilerPass/EventDispatchingPassTest.php @@ -0,0 +1,341 @@ +setParameter('kernel.debug', true); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getFullConfig(); + + $this->registerBasicServices($container); + $this->registerListenerServices($container); + $config['options']['event_dispatcher']['adapter'] = EventDispatcher::class; + + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $pass = new EventDispatchingPass(); + $pass->process($container); + + $container->compile(); + $this->doAssertCountListenersRegistered( + $container, + 5, + 1, + 1, + 1, + 1 + ); + } + + /** + * @test + * @group DependencyInjection + */ + public function testProcessFullConfigurationWithSingleLogItemDisabled() + { + $container = $this->containerWithConfig([ + 'log' => [ + 'request_logging' => [ + 'enabled' => false + ] + ] + ]); + + $container->compile(); + $this->doAssertCountListenersRegistered( + $container, + 4, + 1, + 1, + 1, + 1 + ); + } + + /** + * @test + * @group DependencyInjection + */ + public function testProcessMinimalConfiguration() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + + $this->registerBasicServices($container); + $this->registerListenerServices($container); + + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $pass = new EventDispatchingPass(); + $pass->process($container); + + $container->compile(); + $this->doAssertCountListenersRegistered( + $container, + 4 + ); + } + + /** + * @test + * @group DependencyInjection + */ + public function testBearerToken() + { + $container = $this->containerWithConfig(['options' => ['bearer_token' => 'foobar']]); + + $definition = $container->getDefinition(ApiTokenRequestListener::class); + $this->assertEquals(BearerToken::class, $definition->getArgument(0)->__toString()); + } + + /** + * @test + * @group DependencyInjection + */ + public function testWithFaultyAdapter() + { + $this->expectException(\RuntimeException::class); + + $this->containerWithConfig(['log' => ['request_logging' => ['adapter' => 'foobar']]]); + } + + /** + * @test + * @group DependencyInjection + */ + public function testWithFaultyFormatter() + { + $this->expectException(\RuntimeException::class); + + $this->containerWithConfig(['log' => ['request_logging' => ['formatter' => 'foobar']]]); + } + + /** + * @test + * @group DependencyInjection + */ + public function testWithFaultyListener() + { + $this->expectException(\RuntimeException::class); + + $this->containerWithConfig(['log' => ['request_logging' => ['listener' => 'foobar']]]); + } + + /** + * @test + * @group DependencyInjection + */ + public function testWithLogItemAliases() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getFullConfig(); + + $this->registerBasicServices($container); + $this->registerListenerServices($container); + $config['options']['event_dispatcher']['adapter'] = EventDispatcher::class; + + $loader->load([$config], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $pass = new EventDispatchingPass(); + $pass->process($container); + + $container->compile(); + $this->doAssertCountListenersRegistered( + $container, + 5, + 1, + 1, + 1, + 1 + ); + } + + /** + * @param array $faulty + * @return ContainerBuilder + */ + private function containerWithConfig(array $faulty = []) + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + $loader = new TmdbSymfonyExtension(); + $config = $this->getFullConfig(); + + $this->registerBasicServices($container); + $this->registerListenerServices($container); + $config['options']['event_dispatcher']['adapter'] = EventDispatcher::class; + + $loader->load([array_merge($config, $faulty)], $container); + + $pass = new ConfigurationPass(); + $pass->process($container); + + $pass = new EventDispatchingPass(); + $pass->process($container); + + return $container; + } + + /** + * @param ContainerBuilder $container + */ + protected function registerBasicServices(ContainerBuilder $container) + { + $container->register(EventDispatcher::class, EventDispatcher::class)->addTag( + TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS + ); + $container->setAlias(EventDispatcherInterface::class, EventDispatcher::class); + + $httpClientMock = $this->createMock(ClientInterface::class); + $container->register(get_class($httpClientMock), get_class($httpClientMock))->addTag( + TmdbSymfonyBundle::PSR18_CLIENTS + ); + + $requestFactoryMock = $this->createMock(RequestFactoryInterface::class); + $container->register(get_class($requestFactoryMock), get_class($requestFactoryMock))->addTag( + TmdbSymfonyBundle::PSR17_REQUEST_FACTORIES + ); + + $responseFactoryMock = $this->createMock(ResponseFactoryInterface::class); + $container->register(get_class($responseFactoryMock), get_class($responseFactoryMock))->addTag( + TmdbSymfonyBundle::PSR17_RESPONSE_FACTORIES + ); + + $streamFactoryMock = $this->createMock(StreamFactoryInterface::class); + $container->register(get_class($streamFactoryMock), get_class($streamFactoryMock))->addTag( + TmdbSymfonyBundle::PSR17_STREAM_FACTORIES + ); + + $uriFactoryMock = $this->createMock(UriFactoryInterface::class); + $container->register(get_class($uriFactoryMock), get_class($uriFactoryMock))->addTag( + TmdbSymfonyBundle::PSR17_URI_FACTORIES + ); + + $cacheItemPoolMock = $this->createMock(CacheItemPoolInterface::class); + $container->register(get_class($cacheItemPoolMock), get_class($cacheItemPoolMock)); + $container->setAlias(CacheItemPoolInterface::class, get_class($cacheItemPoolMock)); + + $loggerMock = $this->createMock(LoggerInterface::class); + $container->register(get_class($loggerMock), get_class($loggerMock)); + $container->setAlias(LoggerInterface::class, get_class($loggerMock)); + } + + /** + * @param ContainerBuilder $container + */ + protected function registerListenerServices(ContainerBuilder $container) + { + $container->register(RequestListener::class, RequestListener::class); + $container->register(Psr6CachedRequestListener::class, Psr6CachedRequestListener::class); + $container->register(HydrationListener::class, HydrationListener::class); + $container->register(AcceptJsonRequestListener::class, AcceptJsonRequestListener::class); + $container->register(ContentTypeJsonRequestListener::class, ContentTypeJsonRequestListener::class); + $container->register(ApiTokenRequestListener::class, ApiTokenRequestListener::class); + $container->register(SessionTokenRequestListener::class, SessionTokenRequestListener::class); + } + + /** + * @param ContainerBuilder $container + * @param int $beforeRequestEventCount + * @param int $responseEventCount + * @param int $httpClientExceptionEventCount + * @param int $tmdbExceptionEventCount + * @param int $beforeHydrationEventCount + * @throws Exception + */ + protected function doAssertCountListenersRegistered( + ContainerBuilder $container, + int $beforeRequestEventCount = 0, + int $responseEventCount = 0, + int $httpClientExceptionEventCount = 0, + int $tmdbExceptionEventCount = 0, + int $beforeHydrationEventCount = 0 + ) { + /** @var Client $client */ + $client = $container->get(Client::class); + + /** @var EventDispatcher $eventDispatcher */ + $eventDispatcher = $client->getEventDispatcher(); + + $this->assertEquals( + $beforeRequestEventCount, + count($eventDispatcher->getListeners(BeforeRequestEvent::class)) + ); + + $this->assertEquals( + $responseEventCount, + count($eventDispatcher->getListeners(ResponseEvent::class)) + ); + + $this->assertEquals( + $httpClientExceptionEventCount, + count($eventDispatcher->getListeners(HttpClientExceptionEvent::class)) + ); + + $this->assertEquals( + $tmdbExceptionEventCount, + count($eventDispatcher->getListeners(TmdbExceptionEvent::class)) + ); + + $this->assertEquals( + $beforeHydrationEventCount, + count($eventDispatcher->getListeners(BeforeHydrationEvent::class)) + ); + } +} diff --git a/Tests/DependencyInjection/TestCase.php b/Tests/DependencyInjection/TestCase.php new file mode 100644 index 0000000..d093b2a --- /dev/null +++ b/Tests/DependencyInjection/TestCase.php @@ -0,0 +1,212 @@ +assertTrue(($this->container->hasDefinition($id) ?: $this->container->hasAlias($id))); + } + + /** + * @param ContainerBuilder $container + * @param string $value + * @param string $key + */ + protected function assertAlias(ContainerBuilder $container, $value, $key): void + { + $this->assertSame($value, (string)$container->getAlias($key), sprintf('%s alias is correct', $key)); + } + + /** + * @param string $key + */ + protected function assertNotAlias($key): void + { + $this->assertFalse( + $this->container->hasAlias($key), + sprintf('%s alias is expected not to be registered', $key) + ); + } + + /** + * @param string $id + */ + protected function assertNotHasDefinition($id): void + { + $this->assertFalse(($this->container->hasDefinition($id) ?: $this->container->hasAlias($id))); + } + + protected function tearDown(): void + { + $this->container = null; + } + + /** + * @param mixed $value + * @param string $key + */ + protected function assertParameter($value, $key): void + { + $this->assertSame($value, $this->container->getParameter($key), sprintf('%s parameter is correct', $key)); + } + + /** + * @return ContainerBuilder + */ + protected function createEmptyConfiguration(): ContainerBuilder + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getEmptyConfig(); + $loader->load([$config], $this->container); + + return $this->container; + } + + /** + * getEmptyConfig. + * + * @return array + */ + protected function getEmptyConfig(): array + { + return []; + } + + /** + * @param array $config + * @return ContainerBuilder + */ + protected function createManualConfiguration(array $config = array()): ContainerBuilder + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $loader->load([$config], $this->container); + + return $this->container; + } + + /** + * @return ContainerBuilder + */ + protected function createMinimalConfiguration(): ContainerBuilder + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $this->container); + + return $this->container; + } + + /** + * getEmptyConfig. + * + * @return array + */ + protected function getMinimalConfig(): array + { + $yaml = <<parse($yaml); + } + + /** + * @return ContainerBuilder + */ + protected function createFullConfiguration(): ContainerBuilder + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getFullConfig(); + $loader->load([$config], $this->container); + + return $this->container; + } + + /** + * @return mixed + */ + protected function getFullConfig(): array + { + $yaml = <<parse($yaml); + } +} diff --git a/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php b/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php index 9182d92..d731d69 100644 --- a/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php +++ b/Tests/DependencyInjection/TmdbSymfonyExtensionTest.php @@ -2,9 +2,9 @@ namespace Tmdb\SymfonyBundle\Tests\DependencyInjection; -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Container; -use Tmdb\SymfonyBundle\Tests\TestKernel; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Tmdb\SymfonyBundle\DependencyInjection\TmdbSymfonyExtension; final class TmdbSymfonyExtensionTest extends TestCase { @@ -12,14 +12,113 @@ final class TmdbSymfonyExtensionTest extends TestCase * @test * @group DependencyInjection */ - public function all_tmdb_services_can_be_loaded() + public function testDefaultConfigurationWithoutApiKeyThrowsException(): void { - $kernel = new TestKernel('test', true); - $kernel->boot(); + $this->expectException(InvalidConfigurationException::class); + $loader = new TmdbSymfonyExtension(); + $config = $this->getEmptyConfig(); + $loader->load([$config], new ContainerBuilder()); + } + + /** + * @test + * @group DependencyInjection + */ + public function testDefaultConfigurationWithApiKey(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $this->container); + + $this->assertHasDefinition('Tmdb\Client'); + $this->assertHasDefinition('Tmdb\Repository\MovieRepository'); + $this->assertHasDefinition('Tmdb\SymfonyBundle\Twig\TmdbExtension'); + } + + /** + * @test + * @group DependencyInjection + */ + public function testDefaultConfigurationHasLegacyAliases(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $this->container); + + $this->assertAlias($this->container, 'Tmdb\Client', 'tmdb.client'); + $this->assertAlias($this->container, 'Tmdb\Repository\MovieRepository', 'tmdb.movie_repository'); + $this->assertAlias($this->container, 'Tmdb\SymfonyBundle\Twig\TmdbExtension', 'tmdb.twig.image_extension'); + } + + /** + * @test + * @group DependencyInjection + */ + public function testDisablingRepositories(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $config['repositories']['enabled'] = false; + $loader->load([$config], $this->container); + + $this->assertAlias($this->container, 'Tmdb\Client', 'tmdb.client'); + $this->assertNotAlias('tmdb.movie_repository'); + $this->assertNotHasDefinition('Tmdb\Repository\MovieRepository'); + } + + /** + * @test + * @group DependencyInjection + */ + public function testDisablingTwig(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $config['twig_extension']['enabled'] = false; + $loader->load([$config], $this->container); + + $this->assertAlias($this->container, 'Tmdb\Client', 'tmdb.client'); + $this->assertHasDefinition('Tmdb\Repository\MovieRepository'); + $this->assertNotHasDefinition('Tmdb\SymfonyBundle\Twig\TmdbExtension'); + } + + /** + * @test + * @group DependencyInjection + */ + public function testDisablingLegacyAliasesRemovesLegacyAliases(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $config['disable_legacy_aliases'] = true; + $loader->load([$config], $this->container); + + $this->assertNotAlias('tmdb.client'); + $this->assertNotAlias('tmdb.movie_repository'); + $this->assertNotAlias('tmdb.twig.image_extension'); + } + + /** + * @test + * @group DependencyInjection + */ + public function testLegacyMappingMapsCorrectly(): void + { + $this->container = new ContainerBuilder(); + $loader = new TmdbSymfonyExtension(); + $config = $this->getMinimalConfig(); + $loader->load([$config], $this->container); - /** @var Container $container */ - $container = $kernel->getContainer(); - $this->assertInstanceOf('Tmdb\Client', $container->get('tmdb.client')); - $this->assertInstanceOf('Tmdb\Repository\MovieRepository', $container->get('tmdb.movie_repository')); + foreach ($loader->getLegacyAliasMapping() as $group => $mapping) { + foreach ($mapping as $alias => $serviceIdentifier) { + $this->assertHasDefinition($serviceIdentifier); + $this->assertAlias($this->container, $serviceIdentifier, $alias); + } + } } } diff --git a/Tests/TestKernel.php b/Tests/TestKernel.php deleted file mode 100644 index 0249a58..0000000 --- a/Tests/TestKernel.php +++ /dev/null @@ -1,39 +0,0 @@ -load(__DIR__ . '/config.yml'); - } - - public function getRootDir() - { - return sys_get_temp_dir() . '/php-tmdb-symfony-test'; - } - - public function getCacheDir() - { - return $this->getRootDir() . '/cache'; - } - - public function getLogDir() - { - return $this->getRootDir() . '/logs'; - } -} diff --git a/Tests/Twig/TmdbExtensionTest.php b/Tests/Twig/TmdbExtensionTest.php new file mode 100644 index 0000000..4124a0d --- /dev/null +++ b/Tests/Twig/TmdbExtensionTest.php @@ -0,0 +1,105 @@ +createMock(Client::class); + $responseData = json_decode( + file_get_contents(__DIR__ . '/../../Resources/test/configuration.json'), + true + ); + + $configuration = new Configuration(); + $configuration->setImages($responseData['images']); + + $helper = new ImageHelper($configuration); + + $extension = new TmdbExtension($client); + $this->assertEquals($client, $extension->getClient()); + + $extension->setHelper($helper); + $extension->setClient($client); + $this->assertEquals($client, $extension->getClient()); + + $image = new Image(); + $image + ->setAspectRatio(1) + ->setFilePath('/foo.jpg') + ->setHeight(null) + ->setWidth(null) + ->setIso6391('foobar') + ->setMedia('dunno') + ->setVoteAverage(4.7) + ->setVoteCount(666); + + $this->assertEquals('//image.tmdb.org/t/p/original/foo.jpg', $extension->getUrl($image)); + $this->assertEquals( + '', + $extension->getHtml($image) + ); + $this->assertEquals('tmdb_extension', $extension->getName()); + $this->assertEquals(2, count($extension->getFilters())); + } + + /** + * @test + * @group Twig + */ + public function testRepository() + { + $client = $this->createMock(Client::class); + $responseData = json_decode( + file_get_contents(__DIR__ . '/../../Resources/test/configuration.json'), + true + ); + + $configuration = new Configuration(); + $configuration->setImages($responseData['images']); + + $helper = new ImageHelper($configuration); + + $repository = $this->getMockBuilder(AbstractRepository::class) + ->disableOriginalConstructor() + ->setMethods(['load', 'getApi', 'getFactory']) + ->getMock() + ; + + $repository->method('load')->willReturn($configuration); + + $extension = new TmdbExtension($client, $repository); + $this->assertEquals($client, $extension->getClient()); + + $image = new Image(); + $image + ->setAspectRatio(1) + ->setFilePath('/foo.jpg') + ->setHeight(null) + ->setWidth(null) + ->setIso6391('foobar') + ->setMedia('dunno') + ->setVoteAverage(4.7) + ->setVoteCount(666); + + $this->assertEquals('//image.tmdb.org/t/p/original/foo.jpg', $extension->getUrl($image)); + $this->assertEquals( + '', + $extension->getHtml($image) + ); + $this->assertEquals('tmdb_extension', $extension->getName()); + $this->assertEquals(2, count($extension->getFilters())); + } +} diff --git a/Tests/config.yml b/Tests/config.yml deleted file mode 100644 index 8d8d68c..0000000 --- a/Tests/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -framework: - secret: NopeChuckTesta -tmdb_symfony: - api_key: invalidapikey diff --git a/TmdbSymfonyBundle.php b/TmdbSymfonyBundle.php index 7bcec9c..cf29829 100644 --- a/TmdbSymfonyBundle.php +++ b/TmdbSymfonyBundle.php @@ -2,8 +2,56 @@ namespace Tmdb\SymfonyBundle; +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UriFactoryInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Tmdb\SymfonyBundle\DependencyInjection\CompilerPass\ConfigurationPass; +use Tmdb\SymfonyBundle\DependencyInjection\CompilerPass\EventDispatchingPass; +/** + * Class TmdbSymfonyBundle + * @package Tmdb\SymfonyBundle + * @codeCoverageIgnore + */ class TmdbSymfonyBundle extends Bundle { + public const VERSION = '4.0.0'; + public const PSR18_CLIENTS = 'tmdb_symfony.psr18.clients'; + public const PSR17_REQUEST_FACTORIES = 'tmdb_symfony.psr17.request_factories'; + public const PSR17_RESPONSE_FACTORIES = 'tmdb_symfony.psr17.response_factories'; + public const PSR17_STREAM_FACTORIES = 'tmdb_symfony.psr17.stream_factories'; + public const PSR17_URI_FACTORIES = 'tmdb_symfony.psr17.uri_factories'; + public const PSR14_EVENT_DISPATCHERS = 'tmdb_symfony.psr17.event_dispatchers'; + + /** + * @param ContainerBuilder $container + */ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new ConfigurationPass()); + $container->addCompilerPass(new EventDispatchingPass()); + + $targets = [ + ClientInterface::class => self::PSR18_CLIENTS, + RequestFactoryInterface::class => self::PSR17_REQUEST_FACTORIES, + ResponseFactoryInterface::class => self::PSR17_RESPONSE_FACTORIES, + StreamFactoryInterface::class => self::PSR17_STREAM_FACTORIES, + UriFactoryInterface::class => self::PSR17_URI_FACTORIES, + EventDispatcherInterface::class => self::PSR14_EVENT_DISPATCHERS + ]; + + foreach ($targets as $interface => $tag) { + $container + ->registerForAutoconfiguration($interface) + ->addTag($tag) + ; + } + } } diff --git a/Twig/TmdbExtension.php b/Twig/TmdbExtension.php index 6de674e..673ac8d 100644 --- a/Twig/TmdbExtension.php +++ b/Twig/TmdbExtension.php @@ -1,8 +1,10 @@ client = $client; + $this->repository = $repository ?? new ConfigurationRepository($client); } + /** + * @return array|TwigFilter[] + */ public function getFilters() { return array( @@ -32,26 +48,41 @@ public function getFilters() ); } - public function getHtml($image, $size = 'original', $width = null, $height = null) + /** + * @param string $image + * @param string $size + * @param int|null $width + * @param int|null $height + * @return string + */ + public function getHtml(string $image, string $size = 'original', int $width = null, int $height = null): string { return $this->getHelper()->getHtml($image, $size, $width, $height); } - public function getUrl($image, $size = 'original') + /** + * @param string $image + * @param string $size + * @return string + */ + public function getUrl(string $image, string $size = 'original'): string { return $this->getHelper()->getUrl($image, $size); } - public function getName() + /** + * @return string + */ + public function getName(): string { return 'tmdb_extension'; } /** - * @param null $client + * @param Client $client * @return $this */ - public function setClient($client) + public function setClient(Client $client) { $this->client = $client; @@ -59,9 +90,9 @@ public function setClient($client) } /** - * @return null + * @return Client|null */ - public function getClient() + public function getClient(): ?Client { return $this->client; } @@ -86,10 +117,7 @@ public function getHelper() return $this->helper; } - $repository = new ConfigurationRepository($this->client); - $config = $repository->load(); - - $this->helper = new ImageHelper($config); + $this->helper = new ImageHelper($this->repository->load()); return $this->helper; } diff --git a/composer.json b/composer.json index bd56246..eab7454 100755 --- a/composer.json +++ b/composer.json @@ -3,8 +3,8 @@ "license": "MIT", "type": "symfony-bundle", "description": "Symfony Bundle for TMDB (The Movie Database) API. Provides easy access to the php-tmdb/api library.", - "homepage": "https://github.com/wtfzdotnet/php-tmdb-api", - "keywords": ["tmdb", "api", "php","wrapper", "movie", "cinema", "tv", "tv show", "tvdb", "symfony", "symfony2", "symfony3"], + "homepage": "https://github.com/php-tmdb/symfony", + "keywords": ["tmdb", "api", "php","wrapper", "movie", "cinema", "tv", "tv show", "tvdb", "symfony", "symfony4", "symfony5"], "authors": [ { "name": "Michael Roterman", @@ -13,18 +13,34 @@ } ], "require": { - "php": ">=5.5.0", - "symfony/config": "^4.3.7 || ^5.0", - "symfony/dependency-injection": "^4.3.7 || ^5.0", - "symfony/event-dispatcher": "^4.3.7 || ^5.0", - "symfony/http-kernel": "^4.3.7 || ^5.0", + "php": "^7.3 || ^8.0", + "php-tmdb/api": "^4", + "symfony/config": "^4.3.7 || <6", + "symfony/dependency-injection": "^4.3.7 || <6", + "symfony/event-dispatcher": "^4.3.7 || <6", + "symfony/http-kernel": "^4.3.7 || >=5.1.5", + "symfony/phpunit-bridge": "^4.2", "symfony/yaml": "^4.3.7 || ^5.0", - "php-tmdb/api": "^3.0", - "twig/twig": "^2.0|^3.0" + "twig/twig": "^2.0 || ^3.0" + }, + "scripts": { + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml coverage", + "test-coverage": "php -d xdebug.mode=coverage vendor/bin/phpunit --coverage-html build/coverage", + "test-cs": "vendor/bin/phpcs", + "test-phpstan": "vendor/bin/phpstan analyse -c phpstan.neon . --level 7 --no-progress", + "test-psalm": "vendor/bin/psalm --show-info=true ." }, "require-dev": { - "phpunit/phpunit": ">=5.7", - "symfony/framework-bundle": "^4.3.7 || ^5.0" + "nyholm/psr7": "^1.2", + "slevomat/coding-standard": "^6.4.1", + "squizlabs/php_codesniffer": "^3.5.8", + "php-http/guzzle7-adapter": "^0.1", + "phpstan/phpstan": "^0.12.18", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3", + "symfony/framework-bundle": "^4.3.7 || ^5.0", + "vimeo/psalm": "^4", + "php-http/cache-plugin": "^1.7" }, "autoload": { "psr-4": { "Tmdb\\SymfonyBundle\\": "" } diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..c851d73 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,13 @@ + + + + + + + + + + . + vendor/* + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..7450740 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,10 @@ +parameters: + level: 2 + inferPrivatePropertyTypeFromConstructor: true + ignoreErrors: + - '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::children\(\)\.#' + paths: + - . + excludes_analyse: + - Tests + - vendor diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 133e76d..5d6685c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,25 @@ - - - - ./Tests/ - - + + + + + ./ + + + ./Resources + ./Tests + ./vendor + + + + + + + + + + + + ./Tests/ + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..d1fc7bf --- /dev/null +++ b/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + From 06c46aec90b9651c2e6907803203633fc846c96e Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:08:39 +0100 Subject: [PATCH 09/22] Bump for codecov --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3f3e142..7801ba1 100755 --- a/README.md +++ b/README.md @@ -276,4 +276,3 @@ There is also a Twig helper that makes use of the `Tmdb\Helper\ImageHelper` to o ``` **For all all other interactions take a look at [php-tmdb/api](https://github.com/php-tmdb/api).** - From cee35053ed97e6c54f5019c75217b625c6e1a0ea Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:12:23 +0100 Subject: [PATCH 10/22] Bump for php badge --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index eab7454..7e7d4ed 100755 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "^7.3 || ^8.0", + "php": "^7.3 || ^7.4 || ^8.0", "php-tmdb/api": "^4", "symfony/config": "^4.3.7 || <6", "symfony/dependency-injection": "^4.3.7 || <6", From 7d11f810678a3f62c6ff67ee877eb36d9d3ef89f Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:24:55 +0100 Subject: [PATCH 11/22] Add donation badge --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 7801ba1..61668ff 100755 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ Compatible with Symfony 4 and 5, PHP 7.3 and up. +## Buy me a coffee, or a beer :-) + + + +My stomach will appreciate your donation! + Installation ------------ From 461eb2e137e8f56d8f3a39a0606723279c2e6041 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:25:45 +0100 Subject: [PATCH 12/22] Fix link to php-tmdb api docs for installation. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61668ff..692c9db 100755 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Installation ------------ - [Install Composer](https://getcomposer.org/doc/00-intro.md) -- [Install php-tmdb/api dependencies](https://github.com/php-tmdb/api/tree/release/4.0.0#installation) +- [Install php-tmdb/api dependencies](https://github.com/php-tmdb/api#installation) - For development within Symfony we recommend making use of Symfony's PSR-18 HTTP Client _`Symfony\Component\HttpClient\Psr18Client`_, as when non-cached results pass your profiler will be filled with data. From c7838ccbf0b2dec2ad4f991c389733f5f4d13500 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:30:51 +0100 Subject: [PATCH 13/22] Update http-kernel to at least 4.4.13 which includes https://github.com/symfony/symfony/commit/d9910e0b33a2e0f993abff41c6fbc86951b66d78 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7e7d4ed..af78ba2 100755 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "symfony/config": "^4.3.7 || <6", "symfony/dependency-injection": "^4.3.7 || <6", "symfony/event-dispatcher": "^4.3.7 || <6", - "symfony/http-kernel": "^4.3.7 || >=5.1.5", + "symfony/http-kernel": "^4.4.13 || >=5.1.5", "symfony/phpunit-bridge": "^4.2", "symfony/yaml": "^4.3.7 || ^5.0", "twig/twig": "^2.0 || ^3.0" From fcb783f82898076ffe4690d30d23ce7cde5b5968 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Mon, 4 Jan 2021 23:48:17 +0100 Subject: [PATCH 14/22] Update the CI matrix (#31) --- .github/workflows/continuous-integration.yml | 53 +++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 18be910..d5b9d47 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -25,21 +25,62 @@ jobs: symfony-deprecations-helper: - "" include: - # Test against latest Symfony 4.3 stable - - symfony-require: "4.3.*" + # Test against latest Symfony 4.4 stable on 7.3 + - symfony-require: "4.4.*" php-version: "7.3" - deps: "normal" + deps: "dev" - # Test against latest Symfony 4.4 dev - - symfony-require: "4.4.*" + # Test against latest Symfony 5.1 dev on 7.3 + - symfony-require: "5.1.*" php-version: "7.3" deps: "dev" - # Test against latest Symfony 5.2 dev + # Test against latest Symfony 5.2 stable on 7.3 - symfony-require: "5.2.*" php-version: "7.3" deps: "dev" + # Test against latest Symfony 5.3 stable on 7.3 + - symfony-require: "5.3.*" + php-version: "7.3" + deps: "dev" + + # Test against latest Symfony 4.4 stable on 7.4 + - symfony-require: "4.4.*" + php-version: "7.4" + deps: "normal" + + # Test against latest Symfony 5.1 stable on 7.4 + - symfony-require: "5.1.*" + php-version: "7.4" + deps: "dev" + + # Test against latest Symfony 5.2 stable on 7.4 + - symfony-require: "5.2.*" + php-version: "7.4" + deps: "dev" + + # Test against latest Symfony 4.4 stable on 8.0 + - symfony-require: "4.4.*" + php-version: "8.0" + deps: "normal" + + # Test against latest Symfony 5.3 dev on 8.0 + - symfony-require: "5.1.*" + php-version: "8.0" + deps: "dev" + + # Test against latest Symfony 5.2 stable on 8.0 + - symfony-require: "5.2.*" + php-version: "8.0" + deps: "dev" + + # Test against latest Symfony 5.3 dev on 8.0 + - symfony-require: "5.3.*" + php-version: "8.0" + deps: "dev" + + # Test bleeding edge - php-version: "8.0" deps: "dev" symfony-deprecations-helper: "weak" From 238b41968c1521a68ff8684857b62fcb55376d12 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Tue, 5 Jan 2021 00:23:54 +0100 Subject: [PATCH 15/22] Tighten up the test matrix even further (#32) Improvements for github actions --- .github/workflows/continuous-integration.yml | 113 ++++++++++++++++--- composer.json | 12 +- 2 files changed, 103 insertions(+), 22 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index d5b9d47..942ca40 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -18,6 +18,7 @@ jobs: php-version: - "7.3" - "7.4" + - "8.0" deps: - "normal" symfony-require: @@ -30,49 +31,129 @@ jobs: php-version: "7.3" deps: "dev" - # Test against latest Symfony 5.1 dev on 7.3 - - symfony-require: "5.1.*" + # Test against latest Symfony 4.4 stable on 7.3 deps low + - symfony-require: "4.4.*" php-version: "7.3" - deps: "dev" + deps: "low" - # Test against latest Symfony 5.2 stable on 7.3 - - symfony-require: "5.2.*" + # Test against latest Symfony 4.4 stable on 7.3 deps normal + - symfony-require: "4.4.*" php-version: "7.3" - deps: "dev" + deps: "normal" - # Test against latest Symfony 5.3 stable on 7.3 - - symfony-require: "5.3.*" - php-version: "7.3" + # Test against latest Symfony 4.4 stable on 7.4 + - symfony-require: "4.4.*" + php-version: "7.4" deps: "dev" - # Test against latest Symfony 4.4 stable on 7.4 + # Test against latest Symfony 4.4 stable on 7.4 deps low + - symfony-require: "4.4.*" + php-version: "7.4" + deps: "low" + + # Test against latest Symfony 4.4 stable on 7.4 deps normal - symfony-require: "4.4.*" php-version: "7.4" deps: "normal" + # Test against latest Symfony 4.4 stable on 8.0 + - symfony-require: "4.4.*" + php-version: "8.0" + deps: "dev" + + # Test against latest Symfony 4.4 stable on 7.4 deps normal + - symfony-require: "4.4.*" + php-version: "8.0" + deps: "normal" + + # Test against latest Symfony 5.1 stable on 7.3 + - symfony-require: "5.1.*" + php-version: "7.3" + deps: "dev" + + # Test against latest Symfony 5.1 stable on 7.3 deps low + - symfony-require: "5.1.*" + php-version: "7.3" + deps: "low" + + # Test against latest Symfony 5.1 stable on 7.3 deps normal + - symfony-require: "5.1.*" + php-version: "7.3" + deps: "normal" + # Test against latest Symfony 5.1 stable on 7.4 - symfony-require: "5.1.*" php-version: "7.4" deps: "dev" + # Test against latest Symfony 5.1 stable on 7.4 deps low + - symfony-require: "5.1.*" + php-version: "7.4" + deps: "low" + + # Test against latest Symfony 5.1 stable on 7.4 deps normal + - symfony-require: "5.1.*" + php-version: "7.4" + deps: "normal" + + # Test against latest Symfony 5.1 stable on 8.0 + - symfony-require: "5.1.*" + php-version: "8.0" + deps: "dev" + + # Test against latest Symfony 5.1 stable on 7.4 deps normal + - symfony-require: "5.1.*" + php-version: "8.0" + deps: "normal" + + # Test against latest Symfony 5.2 stable on 7.3 + - symfony-require: "5.2.*" + php-version: "7.3" + deps: "dev" + + # Test against latest Symfony 5.2 stable on 7.3 deps low + - symfony-require: "5.2.*" + php-version: "7.3" + deps: "low" + + # Test against latest Symfony 5.2 stable on 7.3 deps normal + - symfony-require: "5.2.*" + php-version: "7.3" + deps: "normal" + # Test against latest Symfony 5.2 stable on 7.4 - symfony-require: "5.2.*" php-version: "7.4" deps: "dev" - # Test against latest Symfony 4.4 stable on 8.0 - - symfony-require: "4.4.*" - php-version: "8.0" + # Test against latest Symfony 5.2 stable on 7.4 deps low + - symfony-require: "5.2.*" + php-version: "7.4" + deps: "low" + + # Test against latest Symfony 5.2 stable on 7.4 deps normal + - symfony-require: "5.2.*" + php-version: "7.4" deps: "normal" - # Test against latest Symfony 5.3 dev on 8.0 - - symfony-require: "5.1.*" + # Test against latest Symfony 5.2 stable on 8.0 + - symfony-require: "5.2.*" php-version: "8.0" deps: "dev" - # Test against latest Symfony 5.2 stable on 8.0 + # Test against latest Symfony 5.2 stable on 7.4 deps normal - symfony-require: "5.2.*" php-version: "8.0" + deps: "normal" + + # Test against latest Symfony 5.3 dev on 7.3 + - symfony-require: "5.3.*" + php-version: "7.3" + deps: "dev" + + # Test against latest Symfony 5.3 dev on 7.4 + - symfony-require: "5.3.*" + php-version: "7.4" deps: "dev" # Test against latest Symfony 5.3 dev on 8.0 diff --git a/composer.json b/composer.json index af78ba2..09c5850 100755 --- a/composer.json +++ b/composer.json @@ -15,12 +15,12 @@ "require": { "php": "^7.3 || ^7.4 || ^8.0", "php-tmdb/api": "^4", - "symfony/config": "^4.3.7 || <6", - "symfony/dependency-injection": "^4.3.7 || <6", - "symfony/event-dispatcher": "^4.3.7 || <6", + "symfony/config": "^4.4 || <6", + "symfony/dependency-injection": "^4.4 || <6", + "symfony/event-dispatcher": "^4.4 || <6", "symfony/http-kernel": "^4.4.13 || >=5.1.5", - "symfony/phpunit-bridge": "^4.2", - "symfony/yaml": "^4.3.7 || ^5.0", + "symfony/phpunit-bridge": "^4.4", + "symfony/yaml": "^4.4 || ^5.0", "twig/twig": "^2.0 || ^3.0" }, "scripts": { @@ -38,7 +38,7 @@ "php-http/guzzle7-adapter": "^0.1", "phpstan/phpstan": "^0.12.18", "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3", - "symfony/framework-bundle": "^4.3.7 || ^5.0", + "symfony/framework-bundle": "^4.4 || ^5.0", "vimeo/psalm": "^4", "php-http/cache-plugin": "^1.7" }, From 6e856c529d313f5cd0b194f93a6e35d7213db91f Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Tue, 5 Jan 2021 00:29:15 +0100 Subject: [PATCH 16/22] Php badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 692c9db..77706b3 100755 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Build Status](https://img.shields.io/github/workflow/status/php-tmdb/symfony/Continuous%20Integration?label=phpunit)](https://github.com/php-tmdb/symfony/actions?query=workflow%3A%22Continuous+Integration%22) [![Build Status](https://img.shields.io/github/workflow/status/php-tmdb/symfony/Coding%20Standards?label=phpcs)](https://github.com/php-tmdb/symfony/actions?query=workflow%3A%22Coding+Standards%22) [![codecov](https://img.shields.io/codecov/c/github/php-tmdb/symfony?token=gTM9AiO5vH)](https://codecov.io/gh/php-tmdb/symfony) -[![PHP](https://img.shields.io/badge/php->=7.3,%20>=8.0-8892BF.svg)](https://packagist.org/packages/php-tmdb/symfony) +[![PHP](https://img.shields.io/badge/php->=7.3,%20>=7.4,%20>=8.0-8892BF.svg)](https://packagist.org/packages/php-tmdb/api) [![Total Downloads](https://poser.pugx.org/php-tmdb/symfony/downloads.svg)](https://packagist.org/packages/php-tmdb/symfony) Compatible with Symfony 4 and 5, PHP 7.3 and up. From 5c53d8e098005c0362b59ea1cfd5272a23e1f413 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Sun, 7 Mar 2021 15:45:51 +0100 Subject: [PATCH 17/22] Resolve issue with phpunit-bridge of symfony (#35) Resolves #33, phpunit bridge was in the wrong composer section and had a wrong dependency. --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 09c5850..8cc87cd 100755 --- a/composer.json +++ b/composer.json @@ -18,9 +18,8 @@ "symfony/config": "^4.4 || <6", "symfony/dependency-injection": "^4.4 || <6", "symfony/event-dispatcher": "^4.4 || <6", - "symfony/http-kernel": "^4.4.13 || >=5.1.5", - "symfony/phpunit-bridge": "^4.4", - "symfony/yaml": "^4.4 || ^5.0", + "symfony/http-kernel": "^4.4.13 || ^5.1.5", + "symfony/yaml": "^4.4 || <6", "twig/twig": "^2.0 || ^3.0" }, "scripts": { @@ -39,6 +38,7 @@ "phpstan/phpstan": "^0.12.18", "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3", "symfony/framework-bundle": "^4.4 || ^5.0", + "symfony/phpunit-bridge": "^4.4 || ^5", "vimeo/psalm": "^4", "php-http/cache-plugin": "^1.7" }, From 671434d0a78d753aa6f23e5806443265bf1c471f Mon Sep 17 00:00:00 2001 From: Romain Monteil Date: Thu, 3 Nov 2022 20:09:38 +0100 Subject: [PATCH 18/22] Allow Symfony 6, drop Symfony < 5.4 and PHP < 7.4 (#42) --- .github/workflows/continuous-integration.yml | 148 ++++-------------- ClientConfiguration.php | 10 +- .../CompilerPass/ConfigurationPass.php | 27 +--- .../CompilerPass/EventDispatchingPass.php | 43 +---- DependencyInjection/Configuration.php | 45 ++---- DependencyInjection/TmdbSymfonyExtension.php | 25 +-- Tests/Twig/TmdbExtensionTest.php | 34 ++-- TmdbSymfonyBundle.php | 5 +- Twig/TmdbExtension.php | 93 ++--------- composer.json | 29 ++-- phpstan.neon | 4 +- 11 files changed, 110 insertions(+), 353 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 942ca40..041c386 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -16,9 +16,9 @@ jobs: strategy: matrix: php-version: - - "7.3" - "7.4" - "8.0" + - "8.1" deps: - "normal" symfony-require: @@ -26,149 +26,69 @@ jobs: symfony-deprecations-helper: - "" include: - # Test against latest Symfony 4.4 stable on 7.3 - - symfony-require: "4.4.*" - php-version: "7.3" - deps: "dev" - - # Test against latest Symfony 4.4 stable on 7.3 deps low - - symfony-require: "4.4.*" - php-version: "7.3" - deps: "low" - - # Test against latest Symfony 4.4 stable on 7.3 deps normal - - symfony-require: "4.4.*" - php-version: "7.3" - deps: "normal" - - # Test against latest Symfony 4.4 stable on 7.4 - - symfony-require: "4.4.*" + # Test against latest Symfony 5.4 stable on 7.4 + - symfony-require: "5.4.*" php-version: "7.4" deps: "dev" - # Test against latest Symfony 4.4 stable on 7.4 deps low - - symfony-require: "4.4.*" - php-version: "7.4" - deps: "low" - - # Test against latest Symfony 4.4 stable on 7.4 deps normal - - symfony-require: "4.4.*" + # Test against latest Symfony 5.4 stable on 7.4 deps normal + - symfony-require: "5.4.*" php-version: "7.4" deps: "normal" - # Test against latest Symfony 4.4 stable on 8.0 - - symfony-require: "4.4.*" + # Test against latest Symfony 5.4 stable on 8.0 + - symfony-require: "5.4.*" php-version: "8.0" deps: "dev" - # Test against latest Symfony 4.4 stable on 7.4 deps normal - - symfony-require: "4.4.*" + # Test against latest Symfony 5.4 stable on 8.0 deps normal + - symfony-require: "5.4.*" php-version: "8.0" deps: "normal" - - # Test against latest Symfony 5.1 stable on 7.3 - - symfony-require: "5.1.*" - php-version: "7.3" - deps: "dev" - - # Test against latest Symfony 5.1 stable on 7.3 deps low - - symfony-require: "5.1.*" - php-version: "7.3" - deps: "low" - - # Test against latest Symfony 5.1 stable on 7.3 deps normal - - symfony-require: "5.1.*" - php-version: "7.3" - deps: "normal" - # Test against latest Symfony 5.1 stable on 7.4 - - symfony-require: "5.1.*" - php-version: "7.4" + # Test against latest Symfony 5.4 stable on 8.1 + - symfony-require: "5.4.*" + php-version: "8.1" deps: "dev" - # Test against latest Symfony 5.1 stable on 7.4 deps low - - symfony-require: "5.1.*" - php-version: "7.4" - deps: "low" - - # Test against latest Symfony 5.1 stable on 7.4 deps normal - - symfony-require: "5.1.*" - php-version: "7.4" + # Test against latest Symfony 5.4 stable on 8.1 deps normal + - symfony-require: "5.4.*" + php-version: "8.1" deps: "normal" - # Test against latest Symfony 5.1 stable on 8.0 - - symfony-require: "5.1.*" + # Test against latest Symfony 6.0 stable on 8.0 + - symfony-require: "6.0.*" php-version: "8.0" deps: "dev" - # Test against latest Symfony 5.1 stable on 7.4 deps normal - - symfony-require: "5.1.*" + # Test against latest Symfony 6.0 stable on 8.0 deps normal + - symfony-require: "6.0.*" php-version: "8.0" - deps: "normal" - - # Test against latest Symfony 5.2 stable on 7.3 - - symfony-require: "5.2.*" - php-version: "7.3" - deps: "dev" - - # Test against latest Symfony 5.2 stable on 7.3 deps low - - symfony-require: "5.2.*" - php-version: "7.3" - deps: "low" - - # Test against latest Symfony 5.2 stable on 7.3 deps normal - - symfony-require: "5.2.*" - php-version: "7.3" deps: "normal" - # Test against latest Symfony 5.2 stable on 7.4 - - symfony-require: "5.2.*" - php-version: "7.4" + # Test against latest Symfony 6.0 stable on 8.1 + - symfony-require: "6.0.*" + php-version: "8.1" deps: "dev" - # Test against latest Symfony 5.2 stable on 7.4 deps low - - symfony-require: "5.2.*" - php-version: "7.4" - deps: "low" - - # Test against latest Symfony 5.2 stable on 7.4 deps normal - - symfony-require: "5.2.*" - php-version: "7.4" + # Test against latest Symfony 6.0 stable on 8.1 deps normal + - symfony-require: "6.0.*" + php-version: "8.1" deps: "normal" - # Test against latest Symfony 5.2 stable on 8.0 - - symfony-require: "5.2.*" - php-version: "8.0" + # Test against latest Symfony 6.1 stable on 8.1 + - symfony-require: "6.1.*" + php-version: "8.1" deps: "dev" - # Test against latest Symfony 5.2 stable on 7.4 deps normal - - symfony-require: "5.2.*" - php-version: "8.0" + # Test against latest Symfony 6.1 stable on 8.1 deps normal + - symfony-require: "6.1.*" + php-version: "8.1" deps: "normal" - # Test against latest Symfony 5.3 dev on 7.3 - - symfony-require: "5.3.*" - php-version: "7.3" - deps: "dev" - - # Test against latest Symfony 5.3 dev on 7.4 - - symfony-require: "5.3.*" - php-version: "7.4" - deps: "dev" - - # Test against latest Symfony 5.3 dev on 8.0 - - symfony-require: "5.3.*" - php-version: "8.0" - deps: "dev" - - # Test bleeding edge - - php-version: "8.0" - deps: "dev" - symfony-deprecations-helper: "weak" - steps: - name: "Checkout" - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" with: fetch-depth: 2 @@ -179,7 +99,7 @@ jobs: coverage: "pcov" - name: "Cache dependencies installed with composer" - uses: "actions/cache@v2" + uses: "actions/cache@v3" with: path: "~/.composer/cache" key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" @@ -205,7 +125,7 @@ jobs: with: name: "phpunit-${{ matrix.php-version }}-${{ matrix.deps }}-${{ hashFiles('composer.lock') }}.coverage" path: "coverage.xml" - + - uses: codecov/codecov-action@v1 with: verbose: true diff --git a/ClientConfiguration.php b/ClientConfiguration.php index 6ddf0ba..19e0e9e 100644 --- a/ClientConfiguration.php +++ b/ClientConfiguration.php @@ -20,14 +20,8 @@ class ClientConfiguration extends ParameterBag implements ConfigurationInterface { /** * ClientConfiguration constructor. - * @param ApiToken $apiToken - * @param EventDispatcherInterface $eventDispatcher - * @param ClientInterface $client - * @param RequestFactoryInterface $requestFactory - * @param ResponseFactoryInterface $responseFactory - * @param StreamFactoryInterface $streamFactory - * @param UriFactoryInterface $uriFactory - * @param array $options + * + * @param array $options */ public function __construct( ApiToken $apiToken, diff --git a/DependencyInjection/CompilerPass/ConfigurationPass.php b/DependencyInjection/CompilerPass/ConfigurationPass.php index 842bdde..d9dc55b 100644 --- a/DependencyInjection/CompilerPass/ConfigurationPass.php +++ b/DependencyInjection/CompilerPass/ConfigurationPass.php @@ -14,17 +14,13 @@ class ConfigurationPass implements CompilerPassInterface { - /** - * @param ContainerBuilder $container - * - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { + /** @var array $parameters */ $parameters = $container->getParameter('tmdb.options'); $configDefinition = $container->getDefinition(ClientConfiguration::class); - // By default the first argument is always referenced to the ApiToken. + // By default, the first argument is always referenced to the ApiToken. if (null !== $bearerToken = $parameters['options']['bearer_token']) { $configDefinition->replaceArgument(0, new Reference(BearerToken::class)); } @@ -34,11 +30,7 @@ public function process(ContainerBuilder $container) } /** - * @param ContainerBuilder $container - * @param Definition $configDefinition - * @param array $parameters - * - * @return void + * @param array $parameters */ private function setupEventDispatcher( ContainerBuilder $container, @@ -58,11 +50,7 @@ private function setupEventDispatcher( } /** - * @param ContainerBuilder $container - * @param Definition $configDefinition - * @param array $parameters - * - * @return void + * @param array $parameters */ private function setupHttpClient( ContainerBuilder $container, @@ -122,11 +110,6 @@ private function setupHttpClient( } /** - * @param ContainerBuilder $container - * @param string $alias - * @param string $tag - * @param string $configurationPath - * @return void * @throws \RuntimeException */ protected function tryToAliasAutowiredInterfacesIfPossible( diff --git a/DependencyInjection/CompilerPass/EventDispatchingPass.php b/DependencyInjection/CompilerPass/EventDispatchingPass.php index 9a3c1e6..b4c7a3a 100644 --- a/DependencyInjection/CompilerPass/EventDispatchingPass.php +++ b/DependencyInjection/CompilerPass/EventDispatchingPass.php @@ -30,13 +30,9 @@ */ class EventDispatchingPass implements CompilerPassInterface { - /** - * @param ContainerBuilder $container - * - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { + /** @var array $parameters */ $parameters = $container->getParameter('tmdb.options'); $clientOptions = $parameters['options']; @@ -54,11 +50,7 @@ public function process(ContainerBuilder $container) } /** - * @param ContainerBuilder $container - * @param Definition $eventDispatcher - * @param array $parameters - * - * @return void + * @param array $parameters */ private function handleSymfonyEventDispatcherRegistration( ContainerBuilder $container, @@ -123,9 +115,7 @@ private function handleSymfonyEventDispatcherRegistration( } /** - * @param ContainerBuilder $container - * @param array $parameters - * @return Definition + * @param array $parameters */ private function getRequestListener( ContainerBuilder $container, @@ -139,9 +129,7 @@ private function getRequestListener( } /** - * @param ContainerBuilder $container - * @param array $parameters - * @return Definition + * @param array $parameters */ private function getPsr6CacheRequestListener( ContainerBuilder $container, @@ -154,13 +142,7 @@ private function getPsr6CacheRequestListener( } /** - * @param string $event - * @param string $listener - * @param Definition $eventDispatcher - * @param ContainerBuilder $container - * @param array $parameters - * - * @return void + * @param array $parameters */ private function handleLogging( string $event, @@ -168,7 +150,7 @@ private function handleLogging( Definition $eventDispatcher, ContainerBuilder $container, array $parameters - ) { + ): void { $options = $parameters[$listener]; $configEntry = sprintf('tmdb_symfony.log.%s', $listener); @@ -231,11 +213,7 @@ private function handleLogging( /** * Register listeners for logging. * - * @param ContainerBuilder $container - * @param Definition $eventDispatcher - * @param array $parameters - * - * @return void + * @param array $parameters */ private function handleLoggerListeners(ContainerBuilder $container, Definition $eventDispatcher, array $parameters): void { @@ -258,11 +236,6 @@ private function handleLoggerListeners(ContainerBuilder $container, Definition $ } } - /** - * @param Definition $eventDispatcher - * @param string $event - * @param string $reference - */ private function registerEventListener( Definition $eventDispatcher, string $event, diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 4397a8f..a865751 100755 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -2,6 +2,13 @@ namespace Tmdb\SymfonyBundle\DependencyInjection; +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UriFactoryInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -13,14 +20,16 @@ use Tmdb\Formatter\Hydration\SimpleHydrationFormatter; use Tmdb\Formatter\TmdbApiException\SimpleTmdbApiExceptionFormatter; + class Configuration implements ConfigurationInterface { /** * {@inheritDoc} */ - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('tmdb_symfony'); + /** @var ArrayNodeDefinition $rootNode */ $rootNode = $treeBuilder->getRootNode(); $this->addRootChildren($rootNode); @@ -31,11 +40,6 @@ public function getConfigTreeBuilder() return $treeBuilder; } - /** - * @param ArrayNodeDefinition $rootNode - * - * @return void - */ private function addRootChildren(ArrayNodeDefinition $rootNode): void { $rootNode @@ -60,11 +64,6 @@ private function addRootChildren(ArrayNodeDefinition $rootNode): void ; } - /** - * @param ArrayNodeDefinition $rootNode - * - * @return void - */ private function addOptionsSection(ArrayNodeDefinition $rootNode): void { $rootNode @@ -89,7 +88,7 @@ private function addOptionsSection(ArrayNodeDefinition $rootNode): void ->children() ->scalarNode('adapter') ->isRequired()->cannotBeEmpty() - ->defaultValue('Psr\EventDispatcher\EventDispatcherInterface') + ->defaultValue(EventDispatcherInterface::class) ->end() ->end() ->end() @@ -97,23 +96,23 @@ private function addOptionsSection(ArrayNodeDefinition $rootNode): void ->addDefaultsIfNotSet() ->children() ->scalarNode('client') - ->defaultValue('Psr\Http\Client\ClientInterface') + ->defaultValue(ClientInterface::class) ->info('Reference to a service which implements PSR-18 HTTP Client') ->end() ->scalarNode('request_factory') - ->defaultValue('Psr\Http\Message\RequestFactoryInterface') + ->defaultValue(RequestFactoryInterface::class) ->info('Reference to a service which implements PSR-17 HTTP Factories') ->end() ->scalarNode('response_factory') - ->defaultValue('Psr\Http\Message\ResponseFactoryInterface') + ->defaultValue(ResponseFactoryInterface::class) ->info('Reference to a service which implements PSR-17 HTTP Factories') ->end() ->scalarNode('stream_factory') - ->defaultValue('Psr\Http\Message\StreamFactoryInterface') + ->defaultValue(StreamFactoryInterface::class) ->info('Reference to a service which implements PSR-17 HTTP Factories') ->end() ->scalarNode('uri_factory') - ->defaultValue('Psr\Http\Message\UriFactoryInterface') + ->defaultValue(UriFactoryInterface::class) ->info('Reference to a service which implements PSR-17 HTTP Factories') ->end() ->end() @@ -133,11 +132,6 @@ private function addOptionsSection(ArrayNodeDefinition $rootNode): void ; } - /** - * @param ArrayNodeDefinition $rootNode - * - * @return void - */ private function addLogSection(ArrayNodeDefinition $rootNode): void { $rootNode @@ -147,7 +141,7 @@ private function addLogSection(ArrayNodeDefinition $rootNode): void ->canBeEnabled() ->children() ->scalarNode('adapter') - ->defaultValue('Psr\Log\LoggerInterface') + ->defaultValue(LoggerInterface::class) ->info('When registering a channel in monolog as "tmdb" for example, monolog.logger.tmdb') ->end() ->arrayNode('request_logging') @@ -202,11 +196,6 @@ private function addLogSection(ArrayNodeDefinition $rootNode): void ; } - /** - * @param ArrayNodeDefinition $rootNode - * - * @return void - */ private function addCacheSection(ArrayNodeDefinition $rootNode): void { $rootNode diff --git a/DependencyInjection/TmdbSymfonyExtension.php b/DependencyInjection/TmdbSymfonyExtension.php index c295250..00659a3 100644 --- a/DependencyInjection/TmdbSymfonyExtension.php +++ b/DependencyInjection/TmdbSymfonyExtension.php @@ -41,11 +41,9 @@ class TmdbSymfonyExtension extends Extension { /** - * @param array $configs - * @param ContainerBuilder $container - * @return void + * @param array $configs */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); @@ -83,9 +81,9 @@ public function load(array $configs, ContainerBuilder $container) /** * Alias mapping for legacy constructs; public to abuse within test suite. * - * @return array + * @return array */ - public function getLegacyAliasMapping() + public function getLegacyAliasMapping(): array { return [ 'repositories' => [ @@ -128,10 +126,7 @@ public function getLegacyAliasMapping() * * @todo major release remove alias mapping of legacy muck :-) * - * @param ContainerBuilder $container * @param array $mapping - * - * @return void */ protected function performAliasMapping(ContainerBuilder $container, array $mapping = []): void { @@ -145,10 +140,6 @@ protected function performAliasMapping(ContainerBuilder $container, array $mappi /** * Handle general lgeacy aliases. - * - * @param ContainerBuilder $container - * - * @return void */ protected function handleLegacyGeneralAliases(ContainerBuilder $container): void { @@ -158,10 +149,6 @@ protected function handleLegacyGeneralAliases(ContainerBuilder $container): void /** * Map repository legacy aliases - * - * @param ContainerBuilder $container - * - * @return void */ protected function handleLegacyRepositoryAliases(ContainerBuilder $container): void { @@ -171,10 +158,6 @@ protected function handleLegacyRepositoryAliases(ContainerBuilder $container): v /** * Map twig legacy aliases - * - * @param ContainerBuilder $container - * - * @return void */ protected function handleLegacyTwigExtensionAlias(ContainerBuilder $container): void { diff --git a/Tests/Twig/TmdbExtensionTest.php b/Tests/Twig/TmdbExtensionTest.php index 4124a0d..8001f12 100644 --- a/Tests/Twig/TmdbExtensionTest.php +++ b/Tests/Twig/TmdbExtensionTest.php @@ -1,18 +1,17 @@ setImages($responseData['images']); - $helper = new ImageHelper($configuration); - - $extension = new TmdbExtension($client); - $this->assertEquals($client, $extension->getClient()); - - $extension->setHelper($helper); - $extension->setClient($client); - $this->assertEquals($client, $extension->getClient()); + $extension = new TmdbExtension($client, $configuration); $image = new Image(); $image @@ -48,15 +40,14 @@ public function testTwigExtension() $this->assertEquals('//image.tmdb.org/t/p/original/foo.jpg', $extension->getUrl($image)); $this->assertEquals( - '', + '', $extension->getHtml($image) ); $this->assertEquals('tmdb_extension', $extension->getName()); - $this->assertEquals(2, count($extension->getFilters())); + $this->assertCount(2, $extension->getFilters()); } /** - * @test * @group Twig */ public function testRepository() @@ -70,18 +61,15 @@ public function testRepository() $configuration = new Configuration(); $configuration->setImages($responseData['images']); - $helper = new ImageHelper($configuration); - - $repository = $this->getMockBuilder(AbstractRepository::class) + $repository = $this->getMockBuilder(ConfigurationRepository::class) ->disableOriginalConstructor() - ->setMethods(['load', 'getApi', 'getFactory']) + ->onlyMethods(['load', 'getApi', 'getFactory']) ->getMock() ; $repository->method('load')->willReturn($configuration); - $extension = new TmdbExtension($client, $repository); - $this->assertEquals($client, $extension->getClient()); + $extension = new TmdbExtension($client, $repository->load()); $image = new Image(); $image @@ -96,10 +84,10 @@ public function testRepository() $this->assertEquals('//image.tmdb.org/t/p/original/foo.jpg', $extension->getUrl($image)); $this->assertEquals( - '', + '', $extension->getHtml($image) ); $this->assertEquals('tmdb_extension', $extension->getName()); - $this->assertEquals(2, count($extension->getFilters())); + $this->assertCount(2, $extension->getFilters()); } } diff --git a/TmdbSymfonyBundle.php b/TmdbSymfonyBundle.php index cf29829..6bd9d5e 100644 --- a/TmdbSymfonyBundle.php +++ b/TmdbSymfonyBundle.php @@ -28,10 +28,7 @@ class TmdbSymfonyBundle extends Bundle public const PSR17_URI_FACTORIES = 'tmdb_symfony.psr17.uri_factories'; public const PSR14_EVENT_DISPATCHERS = 'tmdb_symfony.psr17.event_dispatchers'; - /** - * @param ContainerBuilder $container - */ - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { parent::build($container); diff --git a/Twig/TmdbExtension.php b/Twig/TmdbExtension.php index 673ac8d..72994fb 100644 --- a/Twig/TmdbExtension.php +++ b/Twig/TmdbExtension.php @@ -4,43 +4,29 @@ use Tmdb\Client; use Tmdb\Helper\ImageHelper; -use Tmdb\Repository\AbstractRepository; +use Tmdb\Model\Configuration; use Tmdb\Repository\ConfigurationRepository; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; class TmdbExtension extends AbstractExtension { - /** - * @var ImageHelper|null - */ - private $helper; - - /** - * @var Client - */ - private $client; - - /** - * @var AbstractRepository|ConfigurationRepository - */ - private $repository; + private ImageHelper $helper; /** * TmdbExtension constructor. - * @param Client $client - * @param AbstractRepository $repository */ - public function __construct(Client $client, AbstractRepository $repository = null) + public function __construct(Client $client, Configuration $configuration = null) { - $this->client = $client; - $this->repository = $repository ?? new ConfigurationRepository($client); + $configuration ??= (new ConfigurationRepository($client))->load(); + + $this->helper = new ImageHelper($configuration); } /** - * @return array|TwigFilter[] + * @return array */ - public function getFilters() + public function getFilters(): array { return array( new TwigFilter('tmdb_image_html', array($this, 'getHtml')), @@ -48,77 +34,18 @@ public function getFilters() ); } - /** - * @param string $image - * @param string $size - * @param int|null $width - * @param int|null $height - * @return string - */ public function getHtml(string $image, string $size = 'original', int $width = null, int $height = null): string { - return $this->getHelper()->getHtml($image, $size, $width, $height); + return $this->helper->getHtml($image, $size, $width, $height); } - /** - * @param string $image - * @param string $size - * @return string - */ public function getUrl(string $image, string $size = 'original'): string { - return $this->getHelper()->getUrl($image, $size); + return $this->helper->getUrl($image, $size); } - /** - * @return string - */ public function getName(): string { return 'tmdb_extension'; } - - /** - * @param Client $client - * @return $this - */ - public function setClient(Client $client) - { - $this->client = $client; - - return $this; - } - - /** - * @return Client|null - */ - public function getClient(): ?Client - { - return $this->client; - } - - /** - * @param ImageHelper $helper - * @return $this - */ - public function setHelper($helper) - { - $this->helper = $helper; - - return $this; - } - - /** - * @return ImageHelper - */ - public function getHelper() - { - if ($this->helper) { - return $this->helper; - } - - $this->helper = new ImageHelper($this->repository->load()); - - return $this->helper; - } } diff --git a/composer.json b/composer.json index 8cc87cd..15e506e 100755 --- a/composer.json +++ b/composer.json @@ -13,14 +13,14 @@ } ], "require": { - "php": "^7.3 || ^7.4 || ^8.0", - "php-tmdb/api": "^4", - "symfony/config": "^4.4 || <6", - "symfony/dependency-injection": "^4.4 || <6", - "symfony/event-dispatcher": "^4.4 || <6", - "symfony/http-kernel": "^4.4.13 || ^5.1.5", - "symfony/yaml": "^4.4 || <6", - "twig/twig": "^2.0 || ^3.0" + "php": "^7.4 || ^8.0", + "php-tmdb/api": "^4.0", + "symfony/config": "^5.4 || ^6.0", + "symfony/dependency-injection": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/http-kernel": "^5.4 || ^6.0", + "symfony/yaml": "^5.4 || ^6.0", + "twig/twig": "^3.0" }, "scripts": { "test": "vendor/bin/phpunit", @@ -35,14 +35,19 @@ "slevomat/coding-standard": "^6.4.1", "squizlabs/php_codesniffer": "^3.5.8", "php-http/guzzle7-adapter": "^0.1", - "phpstan/phpstan": "^0.12.18", + "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3", - "symfony/framework-bundle": "^4.4 || ^5.0", - "symfony/phpunit-bridge": "^4.4 || ^5", - "vimeo/psalm": "^4", + "symfony/framework-bundle": "^5.4 || ^6.0", + "symfony/phpunit-bridge": "^5.4 || ^6.0", + "vimeo/psalm": "^4.0", "php-http/cache-plugin": "^1.7" }, "autoload": { "psr-4": { "Tmdb\\SymfonyBundle\\": "" } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/phpstan.neon b/phpstan.neon index 7450740..ac7ebae 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,10 +1,8 @@ parameters: level: 2 inferPrivatePropertyTypeFromConstructor: true - ignoreErrors: - - '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::children\(\)\.#' paths: - . - excludes_analyse: + excludePaths: - Tests - vendor From 0c40031d19e809db7a5eb9ed7bc9247cf4c1735e Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Thu, 3 Nov 2022 20:11:50 +0100 Subject: [PATCH 19/22] Update README.md to reflect new release with major version changes. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77706b3..d6ca286 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![PHP](https://img.shields.io/badge/php->=7.3,%20>=7.4,%20>=8.0-8892BF.svg)](https://packagist.org/packages/php-tmdb/api) [![Total Downloads](https://poser.pugx.org/php-tmdb/symfony/downloads.svg)](https://packagist.org/packages/php-tmdb/symfony) -Compatible with Symfony 4 and 5, PHP 7.3 and up. +Compatible with Symfony 5 and 6, PHP 7.4 and up. ## Buy me a coffee, or a beer :-) From 4a017c337215c1eeae3db66431a1791696c252c3 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Sun, 19 Mar 2023 21:19:17 +0100 Subject: [PATCH 20/22] Got word of a probable bug, lead to me figuring out the test was dirty, fixing test and see what might come up from CI. --- .../CompilerPass/ConfigurationPassTest.php | 12 ++++++------ Tests/DependencyInjection/TestCase.php | 10 ++++++++++ composer.json | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php b/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php index f523a0e..207d00a 100644 --- a/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php +++ b/Tests/DependencyInjection/CompilerPass/ConfigurationPassTest.php @@ -81,12 +81,12 @@ public function testAutowiring() $pass = new ConfigurationPass(); $pass->process($container); - $this->assertAlias($container, get_class($eventDispatcherMock), EventDispatcherInterface::class); - $this->assertAlias($container, get_class($httpClientMock), ClientInterface::class); - $this->assertAlias($container, get_class($requestFactoryMock), RequestFactoryInterface::class); - $this->assertAlias($container, get_class($responseFactoryMock), ResponseFactoryInterface::class); - $this->assertAlias($container, get_class($streamFactoryMock), StreamFactoryInterface::class); - $this->assertAlias($container, get_class($uriFactoryMock), UriFactoryInterface::class); + $this->assertTag($container, get_class($eventDispatcherMock), TmdbSymfonyBundle::PSR14_EVENT_DISPATCHERS); + $this->assertTag($container, get_class($httpClientMock), TmdbSymfonyBundle::PSR18_CLIENTS); + $this->assertTag($container, get_class($requestFactoryMock), TmdbSymfonyBundle::PSR17_REQUEST_FACTORIES); + $this->assertTag($container, get_class($responseFactoryMock), TmdbSymfonyBundle::PSR17_RESPONSE_FACTORIES); + $this->assertTag($container, get_class($streamFactoryMock), TmdbSymfonyBundle::PSR17_STREAM_FACTORIES); + $this->assertTag($container, get_class($uriFactoryMock), TmdbSymfonyBundle::PSR17_URI_FACTORIES); } /** diff --git a/Tests/DependencyInjection/TestCase.php b/Tests/DependencyInjection/TestCase.php index d093b2a..394e001 100644 --- a/Tests/DependencyInjection/TestCase.php +++ b/Tests/DependencyInjection/TestCase.php @@ -30,6 +30,16 @@ protected function assertAlias(ContainerBuilder $container, $value, $key): void $this->assertSame($value, (string)$container->getAlias($key), sprintf('%s alias is correct', $key)); } + /** + * @param ContainerBuilder $container + * @param string $class + * @param string $tag + */ + protected function assertTag(ContainerBuilder $container, string $class, string $tag): void + { + $this->assertArrayHasKey($class, $container->findTaggedServiceIds($tag)); + } + /** * @param string $key */ diff --git a/composer.json b/composer.json index 15e506e..0ee83bb 100755 --- a/composer.json +++ b/composer.json @@ -47,7 +47,8 @@ }, "config": { "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "php-http/discovery": true } } } From d46c7f1d9c5a0bcfefda7b76c2d823e4254d9bf2 Mon Sep 17 00:00:00 2001 From: Michael Roterman Date: Sun, 19 Mar 2023 21:23:47 +0100 Subject: [PATCH 21/22] Adding php 8.2 and symfony 6.2 to figure out if we got an issue at hand. --- .github/workflows/continuous-integration.yml | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 041c386..f827328 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -19,6 +19,7 @@ jobs: - "7.4" - "8.0" - "8.1" + - "8.2" deps: - "normal" symfony-require: @@ -56,6 +57,16 @@ jobs: php-version: "8.1" deps: "normal" + # Test against latest Symfony 5.4 stable on 8.2 + - symfony-require: "5.4.*" + php-version: "8.2" + deps: "dev" + + # Test against latest Symfony 5.4 stable on 8.2 deps normal + - symfony-require: "5.4.*" + php-version: "8.2" + deps: "normal" + # Test against latest Symfony 6.0 stable on 8.0 - symfony-require: "6.0.*" php-version: "8.0" @@ -76,6 +87,16 @@ jobs: php-version: "8.1" deps: "normal" + # Test against latest Symfony 6.0 stable on 8.2 + - symfony-require: "6.0.*" + php-version: "8.2" + deps: "dev" + + # Test against latest Symfony 6.0 stable on 8.2 deps normal + - symfony-require: "6.0.*" + php-version: "8.2" + deps: "normal" + # Test against latest Symfony 6.1 stable on 8.1 - symfony-require: "6.1.*" php-version: "8.1" @@ -86,6 +107,35 @@ jobs: php-version: "8.1" deps: "normal" + # Test against latest Symfony 6.1 stable on 8.2 + - symfony-require: "6.1.*" + php-version: "8.2" + deps: "dev" + + # Test against latest Symfony 6.1 stable on 8.2 deps normal + - symfony-require: "6.1.*" + php-version: "8.2" + deps: "normal" + + # Test against latest Symfony 6.2 stable on 8.1 + - symfony-require: "6.2.*" + php-version: "8.1" + deps: "dev" + + # Test against latest Symfony 6.2 stable on 8.1 deps normal + - symfony-require: "6.2.*" + php-version: "8.1" + deps: "normal" + + # Test against latest Symfony 6.2 stable on 8.2 + - symfony-require: "6.2.*" + php-version: "8.2" + deps: "dev" + + # Test against latest Symfony 6.2 stable on 8.2 deps normal + - symfony-require: "6.2.*" + php-version: "8.2" + deps: "normal" steps: - name: "Checkout" uses: "actions/checkout@v3" From 596f33e0e1ca47dcba8312527a50480cecaffcc6 Mon Sep 17 00:00:00 2001 From: Kevin Jansen Date: Sun, 19 Mar 2023 21:44:46 +0100 Subject: [PATCH 22/22] Update README.md to use the Symfony 5.4+ autowiring syntax --- README.md | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6ca286..1f19b35 100755 --- a/README.md +++ b/README.md @@ -262,13 +262,50 @@ Usage Obtaining the client ```php -$client = $this->get(Tmdb\Client::class); +client = $client; + } +} ``` Obtaining repositories ```php -$movie = $this->get(\Tmdb\Repository\MovieRepository::class)->load(13); +movieRepository = $movieRepository; + } + + public function findMovie(string $id): AbstractModel + { + // Use the auto-wired repository in any of your methods + return $this->movieRepository->load($id); + } +} ``` An overview of all the repositories can be found in the services configuration [repositories.xml](https://github.com/php-tmdb/symfony/blob/master/Resources/config/repositories.xml).