Skip to content
This repository has been archived by the owner on Aug 9, 2022. It is now read-only.

Commit

Permalink
#2 Add ParameterLoader service + ParameterLoadCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieu-ducrot committed Jul 5, 2021
1 parent 1db2615 commit db2577f
Show file tree
Hide file tree
Showing 19 changed files with 497 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/vendor/
composer.lock
/phpmetrics/
/phpunit-coverage-html/
coverage.*
.php_cs.cache
.phpunit.result.cache
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,8 @@ qualimetry: checkstyle lint-php cpd composer-validate metrics phpstan
phpunit:
vendor/bin/phpunit

phpunit-coverage:
coverage-text:
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text

coverage-html:
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html phpunit-coverage-html
21 changes: 21 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,24 @@ services:
Smart\ParameterBundle\Provider\ParameterProvider:
public: false
alias: smart_parameter.parameter_provider

smart_parameter.parameter_loader:
class: Smart\ParameterBundle\Loader\ParameterLoader
public: true
arguments:
- '@Doctrine\ORM\EntityManagerInterface'

Smart\ParameterBundle\Loader\ParameterLoader:
public: false
alias: smart_parameter.parameter_loader

smart_parameter.parameter_load_command:
class: Smart\ParameterBundle\Command\ParameterLoadCommand
public: true
arguments:
- '@smart_parameter.parameter_loader'
tags: ['console.command']

Smart\ParameterBundle\Command\ParameterLoadCommand:
public: false
alias: smart_parameter.parameter_load_command
70 changes: 70 additions & 0 deletions src/Command/ParameterLoadCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace Smart\ParameterBundle\Command;

use Smart\ParameterBundle\Loader\ParameterLoader;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* @author Mathieu Ducrot <[email protected]>
*/
class ParameterLoadCommand extends Command
{
private ParameterLoader $parameterLoader;

public function __construct(ParameterLoader $parameterLoader)
{
$this->parameterLoader = $parameterLoader;
parent::__construct();
}

protected function configure(): void
{
$this
->setName('smart:parameter:load')
->setDescription("Execute a loading of every parameters in the database.")
->setHelp(<<<EOT
The <info>%command.name%</info> command executes a loading of every parameters in the database:
<info>%command.full_name%</info>
Detail behavior on load:
- If a parameter isn't found in the database by his code, it will be inserted.
- If a parameter is found in the database by his code, his help attribut will be updated but the value will remain the same.
- If an existing parameter is not found in the configuration it will be deleted from the database.
EOT
)
->addOption('dry-run', null, InputOption::VALUE_NONE, "Simulates the result of the command without making any changes to the database")
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('SmartParameterBundle');
$io->text('Parameters are being loaded.');

$dryRun = $input->getOption('dry-run');
$logs = $this->parameterLoader->load($dryRun);

$io->text('Execution results:');
$io->listing([
"$logs[nb_inserted] parameters inserted.",
"$logs[nb_updated] parameters updated.",
"$logs[nb_skipped] parameters skipped.",
"$logs[nb_deleted] parameters deleted.",
]);

if ($dryRun) {
$io->text("<info>The command has dry-run option, so no change was done in the database.</info>");
}

return 0;
}
}
9 changes: 8 additions & 1 deletion src/DependencyInjection/SmartParameterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@ class SmartParameterExtension extends Extension
*/
public function load(array $configs, ContainerBuilder $container)
{
$this->processConfiguration(new Configuration(), $configs);
$config = $this->processConfiguration(new Configuration(), $configs);

$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
$loader->load('services.yaml');

$parameterLoader = $container->getDefinition('smart_parameter.parameter_loader');
if (isset($config['parameters']) and is_array($config['parameters'])) {
foreach ($config['parameters'] as $code => $data) {
$parameterLoader->addMethodCall('addParameter', [$code, $data]);
}
}
}
}
2 changes: 1 addition & 1 deletion src/Entity/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Parameter
/**
* @ORM\Column(name="help", type="text", nullable=true)
*/
private ?string $help;
private ?string $help = null;

public function __toString()
{
Expand Down
111 changes: 111 additions & 0 deletions src/Loader/ParameterLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

namespace Smart\ParameterBundle\Loader;

use Doctrine\ORM\EntityManagerInterface;
use Smart\ParameterBundle\Entity\Parameter;

/**
* @author Mathieu Ducrot <[email protected]>
*/
class ParameterLoader
{
const BATCH_SIZE = 20;

private EntityManagerInterface $entityManager;
private array $parameters;
private array $logs = [
"nb_updated" => 0,
"nb_skipped" => 0,
"nb_deleted" => 0,
"nb_inserted" => 0,
];
private bool $dryRun;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

public function addParameter(string $code, array $data): void
{
$this->parameters[$code] = $data;
}

/**
* if dryRun mode is set to true the changes are not flush in the database
*/
public function load(bool $dryRun = false): array
{
$this->entityManager->getConnection()->beginTransaction();
$this->dryRun = $dryRun;

try {
// @phpstan-ignore-next-line
$existingParameters = $this->entityManager->getRepository(Parameter::class)->findExisting();
$i = 1;
foreach ($existingParameters as $code => $parameter) {
$this->handleExistingParameters($code, $parameter, $i);
++$i;
}

$parameterToInsert = array_diff_key($this->parameters, $existingParameters);
foreach ($parameterToInsert as $code => $data) {
$this->handleParametersToInsert($code, $data, $i);
++$i;
}

if (!$this->dryRun) {
$this->entityManager->flush();
$this->entityManager->clear();
$this->entityManager->getConnection()->commit();
}
// @codeCoverageIgnoreStart
} catch (\Exception $e) {
$this->entityManager->getConnection()->rollBack();
}
// @codeCoverageIgnoreEnd

return $this->logs;
}

protected function handleExistingParameters(string $code, Parameter $parameter, int $i): void
{
if (isset($this->parameters[$code])) {
// update help for existing parameters
if (isset($this->parameters[$code]['help']) and $parameter->getHelp() !== $this->parameters[$code]['help']) {
$parameter->setHelp($this->parameters[$code]['help']);
$this->entityManager->persist($parameter);
$this->logs["nb_updated"]++;
} else {
$this->logs["nb_skipped"]++;
}
} else {
$this->entityManager->remove($parameter);
$this->logs["nb_deleted"]++;
}

if (($i % self::BATCH_SIZE) === 0 and !$this->dryRun) {
$this->entityManager->flush();
$this->entityManager->clear();
}
}

protected function handleParametersToInsert(string $code, array $data, int $i): void
{
$parameter = new Parameter();
$parameter->setCode($code);
$parameter->setValue($data['value']);
if (isset($data['help'])) {
$parameter->setHelp($data['help']);
}

$this->entityManager->persist($parameter);
$this->logs["nb_inserted"]++;

if (($i % self::BATCH_SIZE) === 0 and !$this->dryRun) {
$this->entityManager->flush();
$this->entityManager->clear();
}
}
}
11 changes: 10 additions & 1 deletion src/Repository/ParameterRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@
*/
class ParameterRepository extends EntityRepository
{

/**
* @return Parameter[]
*/
public function findExisting(): array
{
return $this->createQueryBuilder('p', 'p.code')
->getQuery()
->getResult()
;
}
}
23 changes: 23 additions & 0 deletions tests/AbstractWebTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

namespace Smart\ParameterBundle\Tests;

use Doctrine\ORM\EntityManagerInterface;
use Liip\TestFixturesBundle\Test\FixturesTrait;
use Smart\ParameterBundle\Entity\Parameter;
use Smart\ParameterBundle\Repository\ParameterRepository;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

/**
Expand All @@ -12,18 +15,38 @@ abstract class AbstractWebTestCase extends WebTestCase
{
use FixturesTrait;

private ?EntityManagerInterface $entityManager;

public function setUp(): void
{
parent::setUp();

self::bootKernel();
$this->entityManager = self::$container->get(EntityManagerInterface::class);

// Empty load to guarantee that the base will always be available
$this->loadFixtureFiles([]);
}

protected function tearDown(): void
{
parent::tearDown();

// avoid memory leaks
if ($this->entityManager != null) {
$this->entityManager->close();
$this->entityManager = null;
}
}

protected function getFixtureDir(): string
{
return __DIR__ . '/fixtures';
}

protected function getParameterRepository(): ParameterRepository
{
// @phpstan-ignore-next-line
return $this->entityManager->getRepository(Parameter::class);
}
}
Loading

0 comments on commit db2577f

Please sign in to comment.