Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support profile specific configuration #538

Merged
merged 3 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ $testContainer = $builder->getTestContainer();
* `ContainerBuilder#addPass()`: Adds an instance of a [Compiler Pass](compiler-passes.md) to be processed
* `ContainerBuilder#addDelayedPass()`: Adds a reference (class name and constructor arguments) of a [Compiler Pass](compiler-passes.md) to be processed
* `ContainerBuilder#addPackage()`: Adds a reference (class name and constructor arguments) of a [Package](packages.md) to be processed
* `ContainerBuilder#useDevelopmentMode()`: Optimises the generate container for development purposes (configures the compiler to track file changes and update the cache)
* `ContainerBuilder#enableDebugging()`: Configures the compiler to track file changes and update the cache, optimised for local development purposes
* `ContainerBuilder#setDumpDir()`: Configures the directory to be used to dump the cache files
* `ContainerBuilder#setParameter()`: Configures a dynamic parameter
* `ContainerBuilder#setBaseClass()`: Modifies which class should be used as base class for the container
* `ContainerBuilder#setProfileName()`: Enables the loading of application profile-specific services via the `when@{profile-name}` syntax

## Configuration file example

Expand All @@ -59,11 +60,12 @@ require __DIR__ . '/../vendor/autoload.php';
$builder = ContainerBuilder::xml(__FILE__, __NAMESPACE__);
$projectRoot = dirname(__DIR__);

if (getenv('APPLICATION_MODE', true) === 'development') {
$builder->useDevelopmentMode();
if (getenv('APP_PROFILE') !== 'prod') {
$builder->enableDebugging();
}

return $builder->setDumpDir($projectRoot . '/var/tmp')
return $builder->setProfileName(getenv('APP_PROFILE'))
->setDumpDir($projectRoot . '/var/tmp')
->setParameter('app.basedir', $projectRoot)
->addFile(__DIR__ . '/container.xml')
->getContainer();
Expand Down
14 changes: 14 additions & 0 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,25 @@ public function addDelayedPass(
*/
public function addPackage(string $className, array $constructArguments = []): Builder;

/**
* Configures the application profile name to support profile-specific services
*/
public function setProfileName(string $profileName): Builder;

/**
* Mark the container to be used as development mode
*
* @deprecated this method will be removed in favour of a more explicit name.
*
* @see enableDebugging
*/
public function useDevelopmentMode(): Builder;

/**
* Configure the container to track file updates
*/
public function enableDebugging(): Builder;

/**
* Configures the dump directory
*/
Expand Down
13 changes: 13 additions & 0 deletions src/Config/ContainerConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ final class ContainerConfiguration

private string $dumpDir;

private ?string $profileName = null;

/**
* phpcs:disable Generic.Files.LineLength
*
Expand All @@ -51,6 +53,16 @@ public function __construct(
$this->dumpDir = sys_get_temp_dir();
}

public function setProfileName(string $profileName): void
{
$this->profileName = $profileName;
}

public function profileName(): ?string
{
return $this->profileName;
}

/** @return Package[] */
public function getPackages(): array
{
Expand Down Expand Up @@ -183,6 +195,7 @@ public function getDumpFile(): string
{
return $this->dumpDir . DIRECTORY_SEPARATOR
. strtolower(str_replace('\\', '_', $this->namespace)) . DIRECTORY_SEPARATOR
. ($this->profileName !== null ? $this->profileName . DIRECTORY_SEPARATOR : '')
. self::CLASS_NAME . '.php';
}

Expand Down
28 changes: 20 additions & 8 deletions src/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
return self::xml($configurationFile, $namespace);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function xml(

Check failure on line 42 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

Default parameter value for parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::xml() changed from NULL to 'Symfony\\Component\\DependencyInjection\\ContainerBuilder'

Check failure on line 42 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

The parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::xml() changed from string|null to a non-contravariant string
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -51,11 +51,11 @@
);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function php(

Check failure on line 55 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

Default parameter value for parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::php() changed from NULL to 'Symfony\\Component\\DependencyInjection\\ContainerBuilder'

Check failure on line 55 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

The parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::php() changed from string|null to a non-contravariant string
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -64,11 +64,11 @@
);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function yaml(

Check failure on line 68 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

Default parameter value for parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::yaml() changed from NULL to 'Symfony\\Component\\DependencyInjection\\ContainerBuilder'

Check failure on line 68 in src/ContainerBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

The parameter $builderClass of Lcobucci\DependencyInjection\ContainerBuilder::yaml() changed from string|null to a non-contravariant string
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -77,11 +77,11 @@
);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function delegating(
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand Down Expand Up @@ -144,7 +144,19 @@
return $this;
}

public function setProfileName(string $profileName): Builder
{
$this->config->setProfileName($profileName);

return $this;
}

public function useDevelopmentMode(): Builder
{
return $this->enableDebugging();
}

public function enableDebugging(): Builder
{
$this->parameterBag->set('app.devmode', true);

Expand Down
19 changes: 10 additions & 9 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@
abstract class Generator
{
private Compiler $compiler;
/** @var class-string<SymfonyBuilder> */
private string $builderClass;

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public function __construct(

Check failure on line 21 in src/Generator.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

Default parameter value for parameter $builderClass of Lcobucci\DependencyInjection\Generator#__construct() changed from NULL to 'Symfony\\Component\\DependencyInjection\\ContainerBuilder'

Check failure on line 21 in src/Generator.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

The parameter $builderClass of Lcobucci\DependencyInjection\Generator#__construct() changed from string|null to a non-contravariant string

Check failure on line 21 in src/Generator.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

The parameter $builderClass of Lcobucci\DependencyInjection\Generator#__construct() changed from string|null to string
private string $configurationFile,
?string $builderClass = null,
private readonly string $configurationFile,
private readonly string $builderClass = SymfonyBuilder::class,
) {
$this->compiler = new Compiler();
$this->builderClass = $builderClass ?? SymfonyBuilder::class;
$this->compiler = new Compiler();
}

/**
Expand Down Expand Up @@ -54,7 +51,7 @@
$container = new $this->builderClass();
$container->addResource(new FileResource($this->configurationFile));

$loader = $this->getLoader($container, $config->getPaths());
$loader = $this->getLoader($container, $config->getPaths(), $config->profileName());

foreach ($config->getFiles() as $file) {
$loader->load($file);
Expand All @@ -64,5 +61,9 @@
}

/** @param string[] $paths */
abstract public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface;
abstract public function getLoader(

Check failure on line 64 in src/Generator.php

View workflow job for this annotation

GitHub Actions / Backwards compatibility check

Parameter profileName was added to Method getLoader() of class Lcobucci\DependencyInjection\Generator
SymfonyBuilder $container,
array $paths,
?string $profileName = null,
): LoaderInterface;
}
8 changes: 4 additions & 4 deletions src/Generators/Delegating.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
final class Delegating extends Generator
{
/** @inheritDoc */
public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface
public function getLoader(SymfonyBuilder $container, array $paths, ?string $profileName = null): LoaderInterface
{
$locator = new FileLocator($paths);

return new DelegatingLoader(
new LoaderResolver(
[
new XmlFileLoader($container, $locator),
new YamlFileLoader($container, $locator),
new PhpFileLoader($container, $locator),
new XmlFileLoader($container, $locator, $profileName),
new YamlFileLoader($container, $locator, $profileName),
new PhpFileLoader($container, $locator, $profileName),
],
),
);
Expand Down
3 changes: 2 additions & 1 deletion src/Generators/Php.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
final class Php extends Generator
{
/** @inheritDoc */
public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface
public function getLoader(SymfonyBuilder $container, array $paths, ?string $profileName = null): LoaderInterface
{
return new PhpFileLoader(
$container,
new FileLocator($paths),
$profileName,
);
}
}
3 changes: 2 additions & 1 deletion src/Generators/Xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
final class Xml extends Generator
{
/** @inheritDoc */
public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface
public function getLoader(SymfonyBuilder $container, array $paths, ?string $profileName = null): LoaderInterface
{
return new XmlFileLoader(
$container,
new FileLocator($paths),
$profileName,
);
}
}
3 changes: 2 additions & 1 deletion src/Generators/Yaml.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
final class Yaml extends Generator
{
/** @inheritDoc */
public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface
public function getLoader(SymfonyBuilder $container, array $paths, ?string $profileName = null): LoaderInterface
{
return new YamlFileLoader(
$container,
new FileLocator($paths),
$profileName,
);
}
}
25 changes: 25 additions & 0 deletions test/Config/ContainerConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,19 @@ public function getDumpFileShouldReturnTheFullPathOfDumpFile(): void
);
}

#[PHPUnit\Test]
public function getDumpFileShouldIncludeProfileNameWhenItIsSet(): void
{
$config = new ContainerConfiguration('Me\\MyApp');
$config->setProfileName('prod');

self::assertEquals(
sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'me_myapp' . DIRECTORY_SEPARATOR
. 'prod' . DIRECTORY_SEPARATOR . 'AppContainer.php',
$config->getDumpFile(),
);
}

#[PHPUnit\Test]
public function getDumpOptionsShouldReturnTheDumpingInformation(): void
{
Expand Down Expand Up @@ -357,4 +370,16 @@ public function withAddedNamespaceShouldModifyTheNamespaceOfANewInstanceOnly():
self::assertSame('Me\\MyApp\\AppContainer', $config->getClassName());
self::assertSame('Me\\MyApp\\Testing\\AppContainer', $other->getClassName());
}

#[PHPUnit\Test]
public function profileNameShouldBeConfigurable(): void
{
$config = new ContainerConfiguration('Me\\MyApp');

self::assertNull($config->profileName());

$config->setProfileName('test');

self::assertSame('test', $config->profileName());
}
}
16 changes: 13 additions & 3 deletions test/ContainerBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;

use function get_class;
Expand Down Expand Up @@ -43,7 +44,7 @@ public function configureDependencies(): void
public function namedConstructorsShouldSimplifyTheObjectCreation(
string $method,
Generator $generator,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): void {
$expected = new ContainerBuilder(
new ContainerConfiguration('Lcobucci\\DependencyInjection'),
Expand Down Expand Up @@ -177,11 +178,11 @@ public function setBaseClassShouldConfigureTheBaseClassAndReturnSelf(): void
}

#[PHPUnit\Test]
public function useDevelopmentModeShouldChangeTheParameterAndReturnSelf(): void
public function enableDebuggingShouldChangeTheParameterAndReturnSelf(): void
{
$builder = new ContainerBuilder($this->config, $this->generator, $this->parameterBag);

self::assertSame($builder, $builder->useDevelopmentMode());
self::assertSame($builder, $builder->enableDebugging());
self::assertTrue($this->parameterBag->get('app.devmode'));
}

Expand Down Expand Up @@ -231,4 +232,13 @@ public function getTestContainerShouldGenerateAndReturnTheContainer(): void
self::assertCount(1, $compilerPasses);
self::assertSame($this->parameterBag, $compilerPasses[0][0]);
}

#[PHPUnit\Test]
public function profileNameShouldBeConfigurable(): void
{
$builder = new ContainerBuilder($this->config, $this->generator, $this->parameterBag);
$builder->setProfileName('testing');

self::assertSame('testing', $this->config->profileName());
}
}
Loading