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

WIP select generator & data extractor

parent 2aeaffba
Loading
Loading
Loading
Loading
Loading
+19 −3
Changes for config/module.config.php: 19 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ use Laminas\Router\Http\Segment;
use Laminas\ServiceManager\Factory\InvokableFactory;
use UnicaenDbImport\Controller\SourceController;
use UnicaenDbImport\Controller\SourceControllerFactory;
use UnicaenDbImport\Service\Api\Response\DataExtractor\ResponseDataExtractorPluginManagerFactory;
use UnicaenDbImport\Service\Api\Response\DataExtractor\ResponseDataExtractorPluginManager;
use UnicaenPrivilege\Guard\PrivilegeController;
use UnicaenDbImport\CodeGenerator\HelperAbstractFactory;
use UnicaenDbImport\Config\Config;
@@ -73,8 +75,24 @@ return [
        'import_observ_result_entity_class' => ImportObservResult::class,

        'connections' => [],

        'code_generators_mapping' => [],
        'code_generators_factories' => [],

        'api_response_data_extractors' => [
            'factories' => [
                HalResponseDataExtractor::class => InvokableFactory::class,
                SolrResponseDataExtractor::class => InvokableFactory::class,
                ArrayResponseDataExtractor::class => InvokableFactory::class,
            ],
            'config' => [
                // set d'extractors par défaut
                HalResponseDataExtractor::class => ['enabled' => true, 'priority' => 30], // plus prioritaire
                SolrResponseDataExtractor::class => ['enabled' => true, 'priority' => 20],
                ArrayResponseDataExtractor::class => ['enabled' => true, 'priority' => 10], // moins prioritaire
            ],
        ],

        'imports' => [],
        'synchros' => [],
    ],
@@ -642,9 +660,7 @@ return [
            ImportLogDatabaseService::class => ImportLogDatabaseServiceFactory::class,
            ApiService::class => ApiServiceFactory::class,

            ArrayResponseDataExtractor::class => InvokableFactory::class,
            HalResponseDataExtractor::class => InvokableFactory::class,
            SolrResponseDataExtractor::class => InvokableFactory::class,
            ResponseDataExtractorPluginManager::class => ResponseDataExtractorPluginManagerFactory::class,

            CodeGeneratorPluginManager::class => CodeGeneratorPluginManagerFactory::class,

+26 −7
Changes for src/UnicaenDbImport/CodeGenerator/CodeGenerator.php: 26 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace UnicaenDbImport\CodeGenerator;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Generator;
use RuntimeException;
use UnicaenDbImport\CodeGenerator\Helper\LogTableHelper;
use UnicaenDbImport\CodeGenerator\Helper\TableHelper;
@@ -222,24 +223,42 @@ abstract class CodeGenerator implements CodeGeneratorInterface

    /**
     * @param SourceInterface $source
     * @return string
     * @return iterable
     */
    public function generateSQLForSelectFromSource(SourceInterface $source): string
    public function generateSQLForSelectFromSource(SourceInterface $source): iterable
    {
        if ($source->getSelect()) {
            $query = $source->getSelect();
        if ($select = $source->getSelect()) {
            $queries = $this->normalizedSelect($select);
        } else {
            $sourceTable = $source->getTable();
            $query = $this->tableHelper->generateSQLForSelectFromTable($sourceTable);
            $queries = [$this->tableHelper->generateSQLForSelectFromTable($sourceTable)];
        }

        if ($where = $source->getWhere()) {
            $query = sprintf('SELECT * FROM (%s) tmp WHERE (%s)', $query, $where);
            if ($queries instanceof Generator) {
                $query = yield from $queries;
                yield sprintf('SELECT * FROM (%s) tmp WHERE (%s)', $query, $where);
            } else {
                $queries = array_map(
                    fn($query) => sprintf('SELECT * FROM (%s) tmp WHERE (%s)', $query, $where),
                    $queries
                );
            }
        }

        return $query;
        return $queries;
    }

    protected function normalizedSelect(string|iterable $select): iterable
    {
        if (is_iterable($select)) {
            return $select;
        } elseif (is_string($select)) {
            return [$select];
        } else {
            throw new RuntimeException("Format inattendu de spécification du/des selects");
        }
    }
    /**
     * @param SourceInterface $source
     * @param DestinationInterface $destination
+1 −2
Changes for src/UnicaenDbImport/CodeGenerator/CodeGeneratorInterface.php: 1 added line, 2 removed lines.
Original line number Diff line number Diff line
@@ -62,9 +62,8 @@ interface CodeGeneratorInterface

    /**
     * @param SourceInterface $source
     * @return string
     */
    public function generateSQLForSelectFromSource(SourceInterface $source): string;
    public function generateSQLForSelectFromSource(SourceInterface $source): iterable;

    /**
     * @param string $sourceTableName
+17 −0
Changes for src/UnicaenDbImport/Config/Config.php: 17 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -52,6 +52,11 @@ class Config
     */
    protected $codeGeneratorsFactoriesConfig = [];

    /**
     * API response data extractor's class => factory's class
     */
    protected array $apiResponseDataExtractorsConfig = [];

    /**
     * column's name => aliases
     * @var array
@@ -203,6 +208,18 @@ class Config
        return $this;
    }

    public function getApiResponseDataExtractorsConfig(): array
    {
        return $this->apiResponseDataExtractorsConfig;
    }

    public function setApiResponseDataExtractorsConfig(array $apiResponseDataExtractorsConfig): self
    {
        $this->apiResponseDataExtractorsConfig = $apiResponseDataExtractorsConfig;

        return $this;
    }

    /**
     * @return array [column => alias]
     */
+71 −2
Changes for src/UnicaenDbImport/Config/ConfigFactory.php: 71 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@ namespace UnicaenDbImport\Config;
use Assert\Assertion;
use Assert\AssertionFailedException;
use Doctrine\DBAL\Connection as DbConnection;
use Generator;
use Psr\Container\ContainerInterface;
use UnicaenDbImport\Domain\SelectGeneratorInterface;
use UnicaenDbImport\Connection\ApiConnection;
use UnicaenDbImport\Domain\Destination;
use UnicaenDbImport\Domain\Import;
@@ -13,6 +15,8 @@ use UnicaenDbImport\Domain\Source;
use UnicaenDbImport\Domain\Synchro;
use UnicaenDbImport\Filter\ColumnName\ArrayMapColumnNameFilter;
use UnicaenDbImport\Filter\ColumnName\ColumnNameFilterInterface;
use UnicaenDbImport\Service\Api\Response\DataExtractor\ResponseDataExtractorInterface;
use UnicaenDbImport\Service\Api\Response\DataExtractor\ResponseDataExtractorPluginManager;

class ConfigFactory
{
@@ -53,6 +57,7 @@ class ConfigFactory
        $importObservResultEntityClass = $this->getImportObservResultEntityClass();
        $codeGeneratorsConfig = $this->getCodeGeneratorsConfig();
        $codeGeneratorsFactoriesConfig = $this->getCodeGeneratorsFactoriesConfig();
        $apiResponseDataExtractorConfig = $this->getApiResponseDataExtractorConfig();
        $histoColumnsAliases = $this->getHistoColumnsAliases();
        $histoColumnsValues = $this->getHistoColumnsValues();
        $useImportObserv = $this->getUseImportObserv();
@@ -66,6 +71,7 @@ class ConfigFactory
        $config->setImportObservResultEntityClass($importObservResultEntityClass);
        $config->setCodeGeneratorsMappingConfig($codeGeneratorsConfig);
        $config->setCodeGeneratorsFactoriesConfig($codeGeneratorsFactoriesConfig);
        $config->setApiResponseDataExtractorsConfig($apiResponseDataExtractorConfig);
        $config->setHistoColumnsAliases($histoColumnsAliases);
        $config->setHistoColumnsValues($histoColumnsValues);
        $config->setUseImportObserv($useImportObserv);
@@ -337,17 +343,60 @@ class ConfigFactory
        $connectionName = $sourceConfig['connection'];
        $sourceConfig['connection'] = $this->getConnectionByName($connectionName);

        $sourceConfig['computed_columns'] = $this->getColumnValueFilterInstances($sourceConfig, 'computed_columns', $this->container);
        $sourceConfig['column_value_filter'] = $this->getColumnValueFilterInstances($sourceConfig, 'column_value_filter', $this->container);
        $sourceConfig['computed_columns'] = $this->getColumnValueFilterInstances($sourceConfig, 'computed_columns');
        $sourceConfig['column_value_filter'] = $this->getColumnValueFilterInstances($sourceConfig, 'column_value_filter');

        $columnNameFilter = $sourceConfig['column_name_filter'] ?? null;
        if ($columnNameFilter !== null) {
            $sourceConfig['column_name_filter'] = $this->getColumnNameFilterInstance($columnNameFilter);
        }

        $select = $sourceConfig[$key = 'select'] ?? null;
        if ($select && is_string($select) && $this->container->has($select)) {
            $serviceName = $select;
            $service = $this->container->get($serviceName);
            if (!$service instanceof SelectGeneratorInterface) {
                throw ConfigException::invalidValueForKey(
                    $key,
                    "Service implémentant " . SelectGeneratorInterface::class
                );
            }
            $sourceConfig[$key] = $service->getSelects();
        }

        $dataExtractor = $sourceConfig['data_extractor'] ?? null;
        if ($dataExtractor && is_string($dataExtractor)) {
            $sourceConfig['data_extractor'] = $this->getDataExtractorInstance($dataExtractor, 'data_extractor');
        }

        return Source::fromConfig($sourceConfig);
    }

    /**
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \UnicaenDbImport\Config\ConfigException
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    private function getDataExtractorInstance($dataExtractor, string $key)
    {
        if (is_string($dataExtractor)) {
            /** @var ResponseDataExtractorPluginManager $pluginManager */
            $pluginManager = $this->container->get(ResponseDataExtractorPluginManager::class);
            $serviceName = $dataExtractor;
            $service = $pluginManager->get($serviceName);
            if (!$service instanceof ResponseDataExtractorInterface) {
                throw ConfigException::invalidValueForKey(
                    $key,
                    "Service implémentant " . ResponseDataExtractorInterface::class
                );
            }

            return $service;
        }

        return $dataExtractor;
    }

    /**
     * @param array $destinationConfig
     * @return Destination
@@ -430,6 +479,26 @@ class ConfigFactory
        return $this->moduleConfig[$key];
    }

    /**
     * @return array
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function getApiResponseDataExtractorConfig(): array
    {
        try {
            Assertion::keyExists($this->moduleConfig, $key = 'api_response_data_extractors');
        } catch (AssertionFailedException $e) {
            throw ConfigException::missingKey($key);
        }
        try {
            Assertion::isArray($this->moduleConfig[$key]);
        } catch (AssertionFailedException $e) {
            throw ConfigException::invalidValueForKey($key, 'array');
        }

        return $this->moduleConfig[$key];
    }

    /**
     * @return array
     * @throws \UnicaenDbImport\Config\ConfigException
Loading