Skip to content

Commit

Permalink
[FEATURE] Let ProviderFactory manage template providers
Browse files Browse the repository at this point in the history
  • Loading branch information
eliashaeussler committed Mar 22, 2023
1 parent a5eb5c4 commit 8589ad5
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 93 deletions.
4 changes: 0 additions & 4 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
use Cocur\Slugify;
use CPSIT\ProjectBuilder\Builder;
use CPSIT\ProjectBuilder\IO;
use CPSIT\ProjectBuilder\Template;
use CPSIT\ProjectBuilder\Twig;
use GuzzleHttp\Client as GuzzleClient;
use Nyholm\Psr7;
Expand Down Expand Up @@ -55,9 +54,6 @@
$container->registerForAutoconfiguration(IO\Validator\ValidatorInterface::class)
->addTag('io.validator')
;
$container->registerForAutoconfiguration(Template\Provider\ProviderInterface::class)
->addTag('template.provider')
;
$container->registerForAutoconfiguration(Twig\Filter\TwigFilterInterface::class)
->addTag('twig.filter')
;
Expand Down
4 changes: 0 additions & 4 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ services:
CPSIT\ProjectBuilder\IO\Messenger:
alias: 'app.messenger'

CPSIT\ProjectBuilder\Template\Provider\ProviderFactory:
arguments:
$providers: !tagged_iterator template.provider

CPSIT\ProjectBuilder\Twig\Extension\ProjectBuilderExtension:
arguments:
$filters: !tagged_iterator twig.filter
Expand Down
6 changes: 5 additions & 1 deletion src/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,16 @@ public static function simulateCreateProject(Script\Event $event): never

private static function createApplication(IO\Messenger $messenger, string $targetDirectory): Console\Application
{
$filesystem = new Filesystem\Filesystem();
$providerFactory = Template\Provider\ProviderFactory::create($messenger, $filesystem);

return new Console\Application(
$messenger,
Builder\Config\ConfigReader::create(),
new Error\ErrorHandler($messenger),
new Filesystem\Filesystem(),
$filesystem,
$targetDirectory,
$providerFactory->getAll(),
);
}

Expand Down
26 changes: 2 additions & 24 deletions src/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,16 @@ final class Application
private const ABORTED = 2;

/**
* @var non-empty-list<Template\Provider\ProviderInterface>
*/
private array $templateProviders;

/**
* @param list<Template\Provider\ProviderInterface> $templateProviders
* @param non-empty-list<Template\Provider\ProviderInterface> $templateProviders
*/
public function __construct(
private readonly IO\Messenger $messenger,
private readonly Builder\Config\ConfigReader $configReader,
private readonly Error\ErrorHandler $errorHandler,
private readonly Filesystem\Filesystem $filesystem,
private readonly string $targetDirectory,
array $templateProviders = [],
private array $templateProviders,
) {
if ([] === $templateProviders) {
$templateProviders = $this->createDefaultTemplateProviders();
}

$this->templateProviders = $templateProviders;
}

public function run(): int
Expand Down Expand Up @@ -170,16 +160,4 @@ private function buildContainer(Builder\Config\Config $config): \Symfony\Compone

return $container;
}

/**
* @return non-empty-list<Template\Provider\ProviderInterface>
*/
private function createDefaultTemplateProviders(): array
{
return [
new Template\Provider\PackagistProvider($this->messenger, $this->filesystem),
new Template\Provider\ComposerProvider($this->messenger, $this->filesystem),
new Template\Provider\VcsProvider($this->messenger, $this->filesystem),
];
}
}
43 changes: 43 additions & 0 deletions src/Exception/UnknownTemplateProviderException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Composer package "cpsit/project-builder".
*
* Copyright (C) 2023 Elias Häußler <e.haeussler@familie-redlich.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace CPSIT\ProjectBuilder\Exception;

use function sprintf;

/**
* UnknownTemplateProviderException.
*
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @license GPL-3.0-or-later
*/
final class UnknownTemplateProviderException extends Exception
{
public static function create(string $identifier): self
{
return new self(
sprintf('The template provider "%s" does not exist or is not available.', $identifier),
1677140774,
);
}
}
5 changes: 0 additions & 5 deletions src/Template/Provider/ComposerProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,4 @@ public static function getType(): string
{
return self::TYPE;
}

public static function supports(string $type): bool
{
return self::TYPE === $type;
}
}
5 changes: 0 additions & 5 deletions src/Template/Provider/PackagistProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,4 @@ public static function getType(): string
{
return self::TYPE;
}

public static function supports(string $type): bool
{
return self::TYPE === $type;
}
}
33 changes: 28 additions & 5 deletions src/Template/Provider/ProviderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
namespace CPSIT\ProjectBuilder\Template\Provider;

use CPSIT\ProjectBuilder\Exception;
use CPSIT\ProjectBuilder\IO;
use Symfony\Component\Filesystem;

/**
* ProviderFactory.
Expand All @@ -34,21 +36,42 @@
final class ProviderFactory
{
/**
* @param iterable<ProviderInterface> $providers
* @param non-empty-list<ProviderInterface> $providers
*/
public function __construct(
private readonly iterable $providers,
private function __construct(
private readonly array $providers,
) {
}

public static function create(IO\Messenger $messenger, Filesystem\Filesystem $filesystem): self
{
return new self([
// sorted by priority
new PackagistProvider($messenger, $filesystem),
new ComposerProvider($messenger, $filesystem),
new VcsProvider($messenger, $filesystem),
]);
}

/**
* @throws Exception\UnknownTemplateProviderException
*/
public function get(string $type): ProviderInterface
{
foreach ($this->providers as $provider) {
if ($provider::supports($type)) {
if ($type === $provider::getType()) {
return $provider;
}
}

throw Exception\UnsupportedTypeException::create($type);
throw Exception\UnknownTemplateProviderException::create($type);
}

/**
* @return non-empty-list<ProviderInterface>
*/
public function getAll(): array
{
return $this->providers;
}
}
2 changes: 0 additions & 2 deletions src/Template/Provider/ProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,4 @@ public function installTemplateSource(Template\TemplateSource $templateSource):
public static function getName(): string;

public static function getType(): string;

public static function supports(string $type): bool;
}
5 changes: 0 additions & 5 deletions src/Template/Provider/VcsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,4 @@ public static function getType(): string
{
return self::TYPE;
}

public static function supports(string $type): bool
{
return self::TYPE === $type;
}
}
24 changes: 0 additions & 24 deletions tests/src/Console/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,30 +199,6 @@ public function runGeneratesNewProjectFromSelectedTemplate(): void
);
}

/**
* @test
*/
public function runUsesDefaultTemplateProvidersIfNoProvidersAreConfigured(): void
{
$subject = new Src\Console\Application(
$this->messenger,
$this->configReader,
new Src\Error\ErrorHandler($this->messenger),
$this->filesystem,
$this->targetDirectory,
);

self::$io->setUserInputs(['Try another template provider.']);

$subject->run();

$output = self::$io->getOutput();

self::assertStringContainsString(Src\Template\Provider\PackagistProvider::getName(), $output);
self::assertStringContainsString(Src\Template\Provider\ComposerProvider::getName(), $output);
self::assertStringContainsString(Src\Template\Provider\VcsProvider::getName(), $output);
}

private function createTemplateSource(): Src\Template\TemplateSource
{
$sourcePath = dirname(__DIR__).'/Fixtures/Templates/json-template';
Expand Down
47 changes: 47 additions & 0 deletions tests/src/Exception/UnknownTemplateProviderExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Composer package "cpsit/project-builder".
*
* Copyright (C) 2023 Elias Häußler <e.haeussler@familie-redlich.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace CPSIT\ProjectBuilder\Tests\Exception;

use CPSIT\ProjectBuilder as Src;
use PHPUnit\Framework\TestCase;

/**
* UnknownTemplateProviderExceptionTest.
*
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @license GPL-3.0-or-later
*/
final class UnknownTemplateProviderExceptionTest extends TestCase
{
/**
* @test
*/
public function createReturnsExceptionForUnknownTemplateProvider(): void
{
$actual = Src\Exception\UnknownTemplateProviderException::create('foo');

self::assertSame('The template provider "foo" does not exist or is not available.', $actual->getMessage());
self::assertSame(1677140774, $actual->getCode());
}
}
5 changes: 0 additions & 5 deletions tests/src/Fixtures/DummyComposerProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,4 @@ public static function getType(): string
{
return self::TYPE;
}

public static function supports(string $type): bool
{
return self::TYPE === $type;
}
}
5 changes: 0 additions & 5 deletions tests/src/Fixtures/DummyProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,4 @@ public static function getType(): string
{
return self::TYPE;
}

public static function supports(string $type): bool
{
return self::TYPE === $type;
}
}
23 changes: 19 additions & 4 deletions tests/src/Template/Provider/ProviderFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

use CPSIT\ProjectBuilder as Src;
use CPSIT\ProjectBuilder\Tests;
use Symfony\Component\Filesystem;

/**
* ProviderFactoryTest.
Expand All @@ -38,17 +39,18 @@ final class ProviderFactoryTest extends Tests\ContainerAwareTestCase

protected function setUp(): void
{
$this->subject = self::$container->get(Src\Template\Provider\ProviderFactory::class);
$this->subject = Src\Template\Provider\ProviderFactory::create(
self::$container->get(Src\IO\Messenger::class),
self::$container->get(Filesystem\Filesystem::class),
);
}

/**
* @test
*/
public function getThrowsExceptionIfNoProviderOfGivenTypeIsAvailable(): void
{
$this->expectException(Src\Exception\UnsupportedTypeException::class);
$this->expectExceptionCode(1652800199);
$this->expectExceptionMessage('The type "foo" is not supported.');
$this->expectExceptionObject(Src\Exception\UnknownTemplateProviderException::create('foo'));

$this->subject->get('foo');
}
Expand All @@ -71,4 +73,17 @@ public function getReturnsProviderOfGivenType(): void
$this->subject->get('vcs'),
);
}

/**
* @test
*/
public function getAllReturnsAllProviders(): void
{
$actual = $this->subject->getAll();

self::assertCount(3, $actual);
self::assertInstanceOf(Src\Template\Provider\PackagistProvider::class, $actual[0]);
self::assertInstanceOf(Src\Template\Provider\ComposerProvider::class, $actual[1]);
self::assertInstanceOf(Src\Template\Provider\VcsProvider::class, $actual[2]);
}
}

0 comments on commit 8589ad5

Please sign in to comment.