Skip to content

Commit

Permalink
Merge pull request #538 from lcobucci/support-profile-specific-config…
Browse files Browse the repository at this point in the history
…uration

Support profile specific configuration
  • Loading branch information
lcobucci authored Nov 10, 2024
2 parents c36e18c + cff59c1 commit f4b8a7b
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 31 deletions.
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 @@ public static function default(string $configurationFile, string $namespace): se
return self::xml($configurationFile, $namespace);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function xml(
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -51,11 +51,11 @@ public static function xml(
);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function php(
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -64,11 +64,11 @@ public static function php(
);
}

/** @param class-string<SymfonyBuilder>|null $builderClass */
/** @param class-string<SymfonyBuilder> $builderClass */
public static function yaml(
string $configurationFile,
string $namespace,
?string $builderClass = null,
string $builderClass = SymfonyBuilder::class,
): self {
return new self(
new ContainerConfiguration($namespace),
Expand All @@ -77,11 +77,11 @@ public static function yaml(
);
}

/** @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 @@ public function addPackage(string $className, array $constructArguments = []): B
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(
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 @@ public function initializeContainer(ContainerConfiguration $config): SymfonyBuil
$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 @@ public function initializeContainer(ContainerConfiguration $config): SymfonyBuil
}

/** @param string[] $paths */
abstract public function getLoader(SymfonyBuilder $container, array $paths): LoaderInterface;
abstract public function getLoader(
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());
}
}

0 comments on commit f4b8a7b

Please sign in to comment.