Commit 8c880260 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Possibilité de spécifier un tableau de filtres dans la clé...

Possibilité de spécifier un tableau de filtres dans la clé 'column_value_filter' d'une source ou destination (et plus seulement un filtre unique).
parent 6fa5e6d0
Loading
Loading
Loading
Loading
+17 −10
Changes for config/unicaen-db-import.global.php.dist: 17 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@

namespace Application;

use UnicaenDbImport\Domain\Operation;
use UnicaenDbImport\Entity\Db\Source;

return [
@@ -72,9 +71,6 @@ return [
                    // Complément de l'URL de l'API permettant l'interrogation des données
                    'select' => '/regions?fields=nom,code',

                    // Nom de l'attribut ou colonne discriminant·e dans les données source, contenant l'identifiant unique.
                    'source_code_column' => 'code',

                    // Taille des pages de données demandée à l'API (si supportée par l'API)
                    //'page_size'          => 20,

@@ -86,7 +82,9 @@ return [
                    // en nouvelles valeurs de colonnes destination.
                    // Tableau ordonné de services ou de classes implémentant obligatoirement l'interface
                    // {@see \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface}.
                    'column_value_filter' => [],
                    'column_value_filter' => [
                        // ['name' => ToLowercaseColumnValueFilter::class, 'params' => ['columns' => ['code']]]
                    ],

                    // Spécification du filtre à utiliser pour transformer chaque nom de colonne/attribut source en
                    // le nom de la colonne dans la table destination. Valeurs possibles :
@@ -97,6 +95,11 @@ return [
                    // NB : par défaut, `\UnicaenDbImport\Filter\ColumnName\DefaultColumnNameFilter::class`
                    // est utilisé.
                    'column_name_filter' => \UnicaenDbImport\Filter\ColumnName\DefaultColumnNameFilter::class,

                    // Nom de l'attribut ou colonne discriminant·e dans les données source, contenant l'identifiant unique.
                    // NB : en cas de transformation de nom de colonne/attributs (clé 'column_name_filter'), c'est le
                    // nom transformé qu'il faut utiliser ici.
                    'source_code_column' => 'code',
                ],

                // Configuration de la destination des données importées
@@ -114,10 +117,10 @@ return [
                    // Nom de la colonne dans la table destination contenant l'identifiant unique
                    'source_code_column' => 'CODE',

                    // Service ou classe du filtre à utiliser pour transformer des valeurs de colonnes/attributs
                    // issues de la source en nouvelles valeurs de colonnes destination, implémentant
                    // Filtres de transformation à appliquer aux valeurs des colonnes destination.
                    // Tableau ordonné de services ou de classes implémentant obligatoirement l'interface
                    // {@see \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface}.
                    'column_value_filter' => null,
                    'column_value_filter' => [],

                    // Stratégie à utiliser pour générer les valeurs dans la colonne ID (clé primaire).
                    // Si la stratégie est `'SEQUENCE'`, la séquence spécifiée par 'id_sequence' sera utilisée.
@@ -157,7 +160,9 @@ return [
                    // Nom de la table source contenant les données à importer
                    //'table' => 'PAYS', // Équivalent de SELECT * FROM PAYS;

                    // Nom de la colonne dans la table/vue source contenant l'identifiant unique
                    // Nom de l'attribut ou colonne discriminant·e dans les données source, contenant l'identifiant unique.
                    // NB : en cas de transformation de nom de colonne/attributs (clé 'column_name_filter'), c'est le
                    // nom transformé qu'il faut utiliser ici.
                    'source_code_column' => 'COD_PAY',

                    // Filtre SQL éventuel à appliquer aux données sources.
@@ -223,7 +228,9 @@ return [
                    // Select SQL de mise en forme des données source à importer (NB: antinomique avec 'table')
                    //'select' => ''

                    // Nom de la colonne dans la table/vue source contenant l'identifiant unique
                    // Nom de l'attribut ou colonne discriminant·e dans les données source, contenant l'identifiant unique.
                    // NB : en cas de transformation de nom de colonne/attributs (clé 'column_name_filter'), c'est le
                    // nom transformé qu'il faut utiliser ici.
                    'source_code_column' => 'COD_PAY',

                    // Filtre éventuel à apliquer aux données sources
+17 −2
Changes for src/UnicaenDbImport/Config/ConfigException.php: 17 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
namespace UnicaenDbImport\Config;

use Exception;
use Symfony\Component\VarDumper\VarDumper;
use Throwable;

class ConfigException extends Exception
{
@@ -50,10 +52,23 @@ class ConfigException extends Exception
        return new static("La clé de config '$key' n'est pas autorisée");
    }

    public static function invalidValueForKey($key, string $expected = null): self
    public static function invalidValueForKey($key, string $expected = null, Throwable $previous = null): self
    {
        return new static(
            "La valeur associée à la clé de config '$key' n'est pas valide." .
            ($expected ? " Attendu : $expected." : ""));
            ($expected ? " Attendu : $expected." : ""),
            0,
            $previous
        );
    }

    public static function invalidValue($value, string $expected = null, Throwable $previous = null): self
    {
        return new static(
            "La valeur suivante n'est pas valide: " . print_r($value, true) . '.' .
            ($expected ? " Attendu : $expected." : ""),
            0,
            $previous
        );
    }
}
 No newline at end of file
+61 −29
Changes for src/UnicaenDbImport/Config/ConfigFactory.php: 61 added lines, 29 removed lines.
Original line number Diff line number Diff line
@@ -233,8 +233,16 @@ class ConfigFactory
            throw ConfigException::missingKeyInImport($key, $name);
        }

        try {
            $source = $this->createSource($importConfig['source']);
        } catch (ConfigException $e) {
            throw new ConfigException("Une erreur est suvenue lors de la création de la source de l'import '$name'.", null, $e);
        }
        try {
            $destination = $this->createDestination($importConfig['destination']);
        } catch (ConfigException $e) {
            throw new ConfigException("Une erreur est suvenue lors de la création de la destination de l'import '$name'.", null, $e);
        }

        $importConfig['source'] = $source;
        $importConfig['destination'] = $destination;
@@ -281,8 +289,16 @@ class ConfigFactory
            throw ConfigException::missingKeyInSynchro($key, $name);
        }

        try {
            $source = $this->createSource($synchroConfig['source']);
        } catch (ConfigException $e) {
            throw new ConfigException("Une erreur est suvenue lors de la création de la source de la synchro '$name'.", null, $e);
        }
        try {
            $destination = $this->createDestination($synchroConfig['destination']);
        } catch (ConfigException $e) {
            throw new ConfigException("Une erreur est suvenue lors de la création de la destination de la synchro '$name'.", null, $e);
        }

        $synchroConfig['source'] = $source;
        $synchroConfig['destination'] = $destination;
@@ -302,10 +318,7 @@ class ConfigFactory
        $connectionName = $sourceConfig['connection'];
        $sourceConfig['connection'] = $this->getConnectionByName($connectionName);

        $columnValueFilter = $sourceConfig['column_value_filter'] ?? null;
        if ($columnValueFilter !== null) {
            $sourceConfig['column_value_filter'] = $this->getColumnValueFilterInstance($columnValueFilter);
        }
        $sourceConfig['column_value_filter'] = $this->getColumnValueFilterInstances($sourceConfig, 'column_value_filter');

        $columnNameFilter = $sourceConfig['column_name_filter'] ?? null;
        if ($columnNameFilter !== null) {
@@ -327,10 +340,7 @@ class ConfigFactory
        $connectionName = $destinationConfig['connection'];
        $destinationConfig['connection'] = $this->getConnectionByName($connectionName);

        $columnValueFilter = $destinationConfig['column_value_filter'] ?? null;
        if ($columnValueFilter !== null) {
            $destinationConfig['column_value_filter'] = $this->getColumnValueFilterInstance($columnValueFilter);
        }
        $destinationConfig['column_value_filter'] = $this->getColumnValueFilterInstances($destinationConfig, 'column_value_filter');

        return Destination::fromConfig($destinationConfig);
    }
@@ -500,47 +510,69 @@ class ConfigFactory
        return $filterInstance;
    }

    /**
     * @return \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface[]
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function getColumnValueFilterInstances(array $sourceConfig, string $key): array
    {
        $columnValueFilter = $sourceConfig[$key] ?? [];

        $filterInstances = [];
        foreach ((array) $columnValueFilter as $spec) {
            try {
                $filterInstance = $this->getFilterInstance($spec);
            } catch (ConfigException $e) {
                throw ConfigException::invalidValueForKey($key, null, $e);
            }
            if ($filterInstance === NULL) {
                throw ConfigException::invalidValueForKey($key);
            }
            $filterInstances[] = $filterInstance;
        }

        return $filterInstances;
    }

    /**
     * @param string|ColumnValueFilterInterface $spec
     * @return \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function getColumnValueFilterInstance($spec): ColumnValueFilterInterface
    private function getFilterInstance($spec): ?ColumnValueFilterInterface
    {
        $filterInstance = NULL;

        if (is_string($spec)) {
            if ($this->container->has($spec)) {
                $filterInstance = $this->container->get($spec);
        if (is_array($spec)) {
            try {
                    Assertion::isInstanceOf($filterInstance, ColumnValueFilterInterface::class);
                Assertion::keyExists($spec, $key = 'name');
            } catch (AssertionFailedException $e) {
                    throw ConfigException::invalidValueForKey(
                        'column_name_filter',
                        "service implémentant " . ColumnValueFilterInterface::class
                    );
                throw ConfigException::missingKey($key);
            }
            $filterInstance = $this->getFilterInstance($spec[$key]);
            $filterParams = $spec['params'] ?? [];
            if ($filterParams) {
                $filterInstance->setParams($filterParams);
            }
        } elseif (is_string($spec)) {
            if ($this->container->has($spec)) {
                $filterInstance = $this->container->get($spec);
                if (!$filterInstance instanceof ColumnValueFilterInterface) {
                    throw ConfigException::invalidValue($spec, "service implémentant " . ColumnValueFilterInterface::class);
                }
            } elseif (class_exists($spec)) {
                $filterInstance = new $spec;
                try {
                    Assertion::isInstanceOf($filterInstance, ColumnValueFilterInterface::class);
                } catch (AssertionFailedException $e) {
                    throw ConfigException::invalidValueForKey(
                        'column_name_filter',
                        "instance de type " . ColumnValueFilterInterface::class
                    );
                if (!$filterInstance instanceof ColumnValueFilterInterface) {
                    throw ConfigException::invalidValue($spec, "instance de type " . ColumnValueFilterInterface::class);
                }
            }
        } elseif ($spec instanceof ColumnValueFilterInterface) {
            $filterInstance = $spec;
        }

        if ($filterInstance === NULL) {
            throw ConfigException::invalidValueForKey('column_name_filter');
        }

        return $filterInstance;
    }
}
 No newline at end of file
+1 −1
Changes for src/UnicaenDbImport/Domain/Destination.php: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ class Destination implements DestinationInterface
        return $this->config->get('extra', []);
    }

    public function getColumnValueFilter(): ?ColumnValueFilterInterface
    public function getColumnValueFilter(): array
    {
        return $this->config->get('column_value_filter');
    }
+3 −3
Changes for src/UnicaenDbImport/Domain/DestinationInterface.php: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -93,12 +93,12 @@ interface DestinationInterface
    public function getColumns(): array;

    /**
     * Retourne l'instance de filtre permettant de transformer une veleur de colonne/attribut source
     * Retourne les instances de filtres éventuels permettant de transformer une veleur de colonne/attribut source
     * en une valeur de colonne destination.
     *
     * @return \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface|null
     * @return \UnicaenDbImport\Filter\ColumnValue\ColumnValueFilterInterface[]
     */
    public function getColumnValueFilter(): ?ColumnValueFilterInterface;
    public function getColumnValueFilter(): array;

    /**
     * Retourne les éventuelles attributs libres complémentaires.
Loading