Commit feca088f authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Refactorisation : extraction d'une classe mère abtsraite...

Refactorisation : extraction d'une classe mère abtsraite AbstractDatabaseService et de ImportLogDatabaseService.
parent 2224e78b
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ Changelog
- Suppression de 2 lignes intruses dans la config
- DatabaseService::truncateDestinationTable() : on vérifie désormais que les données contiennent un source_id, sinon le vidage partiel est inopérant.
- Préparation de la suppression du paramètre de config 'intermediate_table_auto_drop'
- Refactorisation : extraction d'une classe mère abtsraite AbstractDatabaseService et de ImportLogDatabaseService.

6.0.2
-----
+3 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ use UnicaenDbImport\Service\CodeGenerator\CodeGeneratorPluginManager;
use UnicaenDbImport\Service\CodeGenerator\CodeGeneratorPluginManagerFactory;
use UnicaenDbImport\Service\Database\DatabaseService;
use UnicaenDbImport\Service\Database\DatabaseServiceFactory;
use UnicaenDbImport\Service\Database\ImportLogDatabaseService;
use UnicaenDbImport\Service\Database\ImportLogDatabaseServiceFactory;
use UnicaenDbImport\Service\Facade\ImportFacadeService;
use UnicaenDbImport\Service\Facade\ImportFacadeServiceFactory;
use UnicaenDbImport\Service\Facade\LogFacadeService;
@@ -557,6 +559,7 @@ return [
            LogFacadeService::class => LogFacadeServiceFactory::class,

            DatabaseService::class => DatabaseServiceFactory::class,
            ImportLogDatabaseService::class => ImportLogDatabaseServiceFactory::class,
            ApiService::class => ApiServiceFactory::class,

            CodeGeneratorPluginManager::class => CodeGeneratorPluginManagerFactory::class,
+127 −0
Original line number Diff line number Diff line
<?php

namespace UnicaenDbImport\Service\Database;

use Assert\Assertion;
use Assert\AssertionFailedException;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use UnicaenDbImport\CodeGenerator\CodeGenerator;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\QueryExecutor;
use UnicaenDbImport\Service\CodeGenerator\CodeGeneratorPluginManager;
use UnicaenDbImport\Service\Exception\DatabaseServiceException;

abstract class AbstractDatabaseService
{
    protected CodeGeneratorPluginManager $codeGeneratorPluginManager;
    protected array $codeGeneratorsConfig;
    protected CodeGenerator $codeGenerator;
    /** @var CodeGenerator[] */
    protected array $cachedCodeGenerators = [];

    protected QueryExecutor $queryExecutor;

    protected SourceInterface $source;
    protected DestinationInterface $destination;

    /**
     * DatabaseHelper constructor.
     *
     * @param CodeGeneratorPluginManager $codeGeneratorPluginManager
     * @param array                      $codeGeneratorsConfig
     * @param QueryExecutor              $queryExecutor
     */
    public function __construct(
        CodeGeneratorPluginManager $codeGeneratorPluginManager,
        array $codeGeneratorsConfig,
        QueryExecutor $queryExecutor)
    {
        $this->codeGeneratorPluginManager = $codeGeneratorPluginManager;
        $this->codeGeneratorsConfig = $codeGeneratorsConfig;
        $this->queryExecutor = $queryExecutor;
    }

    public function setSource(SourceInterface $source): void
    {
        $this->source = $source;
    }

    public function setDestination(DestinationInterface $destination): void
    {
        $this->destination = $destination;

        $this->initCodeGeneratorFromDestination();
    }

    /**
     * Détermine, selon la plateforme de bdd destination, le générateur de code SQL à utiliser.
     *
     * @return CodeGenerator
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function initCodeGeneratorFromDestination(): CodeGenerator
    {
        if ($this->destination === null) {
            throw DatabaseServiceException::error("Une destination doit être spécifiée avant l'appel de cette méthode");
        }

        try {
            $platformClass = get_class($this->destination->getConnection()->getDatabasePlatform());
        } catch (Exception $e) {
            throw DatabaseServiceException::error(
                "Impossible de déterminer la plateforme de la base de données destination", $e);
        }

        if (! isset($this->cachedCodeGenerators[$platformClass])) {
            try {
                Assertion::keyExists($this->codeGeneratorsConfig, $platformClass);
            } catch (AssertionFailedException $e) {
                throw DatabaseServiceException::error(
                    "Aucun CodeGenerator configuré pour la plateforme de base de données suivante : " . $platformClass, $e);
            }

            $codeGeneratorClass = $this->codeGeneratorsConfig[$platformClass];
            $codeGenerator = $this->codeGeneratorPluginManager->get($codeGeneratorClass);

            $this->cachedCodeGenerators[$platformClass] = $codeGenerator;
        }

        $this->codeGenerator = $this->cachedCodeGenerators[$platformClass];

        return $this->codeGenerator;
    }

    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    protected function assertTableExists(string $tableName, Connection $connection, ?string $message = null)
    {
        $sql = $this->codeGenerator->generateSQLForTableExistenceCheck($tableName);
        try {
            $result = $this->queryExecutor->fetchAll($sql, $connection);
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur lors du test d'existence de la table '$tableName'", $e);
        }
        $exists = $this->codeGenerator->convertTableExistenceCheckResultToBoolean($result);
        if (!$exists) {
            throw DatabaseServiceException::error(sprintf(
                $message ?: "La table '%s' nécessaire au fonctionnement est introuvable dans la base destination. ",
                $tableName
            ));
        }
    }

    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    protected function rollBack(Connection $connection)
    {
        try {
            $connection->rollBack();
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur rencontrée lors du rollback !", $e);
        }
    }
}
 No newline at end of file
+1 −191
Original line number Diff line number Diff line
@@ -2,21 +2,12 @@

namespace UnicaenDbImport\Service\Database;

use Assert\Assertion;
use Assert\AssertionFailedException;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use UnicaenDbImport\CodeGenerator\CodeGenerator;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\Operation;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservServiceAwareTrait;
use UnicaenDbImport\QueryExecutor;
use UnicaenDbImport\Service\CodeGenerator\CodeGeneratorPluginManager;
use UnicaenDbImport\Service\Exception\DatabaseServiceException;

class DatabaseService
class DatabaseService extends AbstractDatabaseService
{
    use ImportObservServiceAwareTrait;

@@ -24,114 +15,6 @@ class DatabaseService
    const SOURCE_TABLE_CODE_COLUMN = 'CODE';
    const DATA_SLICE_SIZE_FOR_INSERT = 1000;

    /**
     * @var CodeGeneratorPluginManager
     */
    protected $codeGeneratorPluginManager;

    /**
     * @var array
     */
    protected $codeGeneratorsConfig;

    /**
     * @var CodeGenerator
     */
    protected $codeGenerator;

    /**
     * @var CodeGenerator[]
     */
    protected $cachedCodeGenerators = [];

    /**
     * @var QueryExecutor
     */
    protected $queryExecutor;

    /**
     * @var SourceInterface $source
     */
    protected $source;

    /**
     * @var DestinationInterface $destination
     */
    protected $destination;

    /**
     * DatabaseHelper constructor.
     *
     * @param CodeGeneratorPluginManager $codeGeneratorPluginManager
     * @param array                      $codeGeneratorsConfig
     * @param QueryExecutor              $queryExecutor
     */
    public function __construct(
        CodeGeneratorPluginManager $codeGeneratorPluginManager,
        array $codeGeneratorsConfig,
        QueryExecutor $queryExecutor)
    {
        $this->codeGeneratorPluginManager = $codeGeneratorPluginManager;
        $this->codeGeneratorsConfig = $codeGeneratorsConfig;
        $this->queryExecutor = $queryExecutor;
    }

    /**
     * @param SourceInterface $source
     */
    public function setSource(SourceInterface $source): void
    {
        $this->source = $source;
    }

    /**
     * @param DestinationInterface $destination
     */
    public function setDestination(DestinationInterface $destination): void
    {
        $this->destination = $destination;

        $this->initCodeGeneratorFromDestination();
    }

    /**
     * Détermine, selon la plateforme de bdd destination, le générateur de code SQL à utiliser.
     *
     * @return CodeGenerator
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function initCodeGeneratorFromDestination(): CodeGenerator
    {
        if ($this->destination === null) {
            throw DatabaseServiceException::error("Une destination doit être spécifiée avant l'appel de cette méthode");
        }

        try {
            $platformClass = get_class($this->destination->getConnection()->getDatabasePlatform());
        } catch (Exception $e) {
            throw DatabaseServiceException::error(
                "Impossible de déterminer la plateforme de la base de données destination", $e);
        }

        if (! isset($this->cachedCodeGenerators[$platformClass])) {
            try {
                Assertion::keyExists($this->codeGeneratorsConfig, $platformClass);
            } catch (AssertionFailedException $e) {
                throw DatabaseServiceException::error(
                    "Aucun CodeGenerator configuré pour la plateforme de base de données suivante : " . $platformClass, $e);
            }

            $codeGeneratorClass = $this->codeGeneratorsConfig[$platformClass];
            $codeGenerator = $this->codeGeneratorPluginManager->get($codeGeneratorClass);

            $this->cachedCodeGenerators[$platformClass] = $codeGenerator;
        }

        $this->codeGenerator = $this->cachedCodeGenerators[$platformClass];

        return $this->codeGenerator;
    }

    /**
     * Validation de la table destination.
     *
@@ -218,26 +101,6 @@ class DatabaseService
        $this->assertTableExists($tableName, $connection);
    }

    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    private function assertTableExists(string $tableName, Connection $connection, ?string $message = null)
    {
        $sql = $this->codeGenerator->generateSQLForTableExistenceCheck($tableName);
        try {
            $result = $this->queryExecutor->fetchAll($sql, $connection);
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur lors du test d'existence de la table '$tableName'", $e);
        }
        $exists = $this->codeGenerator->convertTableExistenceCheckResultToBoolean($result);
        if (!$exists) {
            throw DatabaseServiceException::error(sprintf(
                $message ?: "La table '%s' nécessaire au fonctionnement est introuvable dans la base destination. ",
                $tableName
            ));
        }
    }

    /**
     * Vérifie dans la table SOURCE qu'il existe bien une source ayant le 'code' spécifié.
     *
@@ -262,31 +125,6 @@ class DatabaseService
        }
    }

    /**
     *
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function createImportLogTableIfNotExists()
    {
        $connection = $this->destination->getConnection();
        $importLogTable = $this->destination->getLogTable();

        try {
            $this->assertTableExists($importLogTable, $connection);
            return;
        } catch (DatabaseServiceException $e) {
            // :-) la table existe
        }

        // create table
        $sql = $this->codeGenerator->generateSQLForImportLogTableCreation($this->destination->getLogTable());
        try {
            $this->queryExecutor->exec($sql, $connection);
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur lors de la création de la table de log '$importLogTable'", $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
@@ -388,18 +226,6 @@ class DatabaseService
        return $count;
    }

    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    protected function rollBack(Connection $connection)
    {
        try {
            $connection->rollBack();
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur rencontrée lors du rollback !", $e);
        }
    }

    /**
     * @param string $tableName
     * @param string|null|false $idColumnSequence
@@ -666,20 +492,4 @@ class DatabaseService
            throw DatabaseServiceException::error("Erreur lors du fetch", $e);
        }
    }

    /**
     * @param ResultInterface $result
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function saveResultToLogTable(ResultInterface $result)
    {
        $importLogTable = $this->destination->getLogTable();

        $sql = $this->codeGenerator->generateSQLForInsertResultIntoLogTable($result, $importLogTable);
        try {
            $this->queryExecutor->exec($sql, $this->destination->getConnection());
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Insert impossible dans la table de log '$importLogTable'", $e);
        }
    }
}
 No newline at end of file
+50 −0
Original line number Diff line number Diff line
<?php

namespace UnicaenDbImport\Service\Database;

use Doctrine\DBAL\Exception;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Service\Exception\DatabaseServiceException;

class ImportLogDatabaseService extends AbstractDatabaseService
{
    /**
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function createImportLogTableIfNotExists()
    {
        $connection = $this->destination->getConnection();
        $importLogTable = $this->destination->getLogTable();

        try {
            $this->assertTableExists($importLogTable, $connection);
            return;
        } catch (DatabaseServiceException $e) {
            // la table n'existe pas
        }

        // create table
        $sql = $this->codeGenerator->generateSQLForImportLogTableCreation($this->destination->getLogTable());
        try {
            $this->queryExecutor->exec($sql, $connection);
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Erreur lors de la création de la table de log '$importLogTable'", $e);
        }
    }

    /**
     * @param ResultInterface $result
     * @throws \UnicaenDbImport\Service\Exception\DatabaseServiceException
     */
    public function saveResultToLogTable(ResultInterface $result)
    {
        $importLogTable = $this->destination->getLogTable();

        $sql = $this->codeGenerator->generateSQLForInsertResultIntoLogTable($result, $importLogTable);
        try {
            $this->queryExecutor->exec($sql, $this->destination->getConnection());
        } catch (Exception $e) {
            throw DatabaseServiceException::error("Insert impossible dans la table de log '$importLogTable'", $e);
        }
    }
}
 No newline at end of file
Loading