Skip to content
Snippets Groups Projects
Select Git revision
  • 25760355ae07ce787decf329ffb08fb0ccf72f63
  • master default protected
  • php84
  • ll-api-test
  • 6.x
  • release_6.2.0
  • modif_maintenance_phtml
  • 6.0.x
  • detached2
  • detached
  • php82
  • feature_SearchAndSelectFilter
  • 5.x
  • 4.x
  • 7.2.1
  • 7.2.0
  • 6.2.0
  • 7.1.0
  • 7.0.0
  • 1.1.1
  • 6.1.7
  • 6.1.6
  • 6.1.5
  • 6.0.16
  • 6.0.15
  • 6.1.4
  • 6.0.14
  • 6.1.3
  • 6.0.13
  • 6.1.2
  • 6.0.12
  • 6.1.1
  • 6.1.0
  • 6.0.11
34 results

RunSQLProcess.php

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    RunSQLProcess.php 5.17 KiB
    <?php
    
    namespace UnicaenApp\Service\SQL;
    
    use Doctrine\DBAL\Connection;
    use Doctrine\DBAL\DBALException;
    use Exception;
    use UnicaenApp\Exception\RuntimeException;
    use Zend\Log\Logger;
    use Zend\Log\LoggerAwareTrait;
    
    class RunSQLProcess
    {
        use LoggerAwareTrait;
    
        /**
         * @var string
         */
        private $scriptPath;
    
        /**
         * @var string
         */
        private $logFilePath;
    
        /**
         * @var Connection
         */
        private $connection;
    
        /**
         * @var RunSQLQueryStack
         */
        private $queryStack;
    
        /**
         * @param string $scriptPath
         * @return self
         */
        public function setScriptPath($scriptPath)
        {
            $this->scriptPath = $scriptPath;
    
            return $this;
        }
    
        /**
         * @param Connection $connection
         * @return RunSQLProcess
         */
        public function setConnection(Connection $connection)
        {
            $this->connection = $connection;
    
            return $this;
        }
    
        /**
         * @param null|string $logFilePath
         * @return self
         */
        public function setLogFilePath($logFilePath = null)
        {
            $this->logFilePath = $logFilePath;
    
            return $this;
        }
    
        /**
         * Exécute dans la transaction courante toutes les instructions d'un script SQL.
         *
         * @return RunSQLResult
         */
        public function executeScript()
        {
            $this->validateScriptPath();
    
            $queries = $this->extractQueriesFromScript();
    
            $this->logger->info("+ Exécution du script '$this->scriptPath'.");
            $this->logger->info(sprintf("'--> Requêtes trouvées : %d", count($queries)));
    
            $result = $this->executeQueries($queries);
    
            $logFilePath = $this->logQueries();
            $this->logger->info("'--> Logs : " . $logFilePath);
    
            return $result;
        }
    
        /**
         * Exécute dans la transaction courante toutes les instructions d'un script SQL.
         *
         * @param string $query
         * @return RunSQLResult
         */
        public function executeQuery($query)
        {
            $this->logger->info("+ Exécution d'une requête.");
    
            $result = $this->executeQueries([$query]);
    
            $logFilePath = $this->logQueries();
            $this->logger->info("'--> Logs : " . $logFilePath);
    
            return $result;
        }
    
        private function validateScriptPath()
        {
            if (is_dir($this->scriptPath)) {
                throw new RuntimeException("Le fichier '$this->scriptPath' spécifié est un répertoire");
            }
            if (!is_readable($this->scriptPath)) {
                throw new RuntimeException("Le fichier '$this->scriptPath' n'est pas accessible");
            }
        }
    
        /**
         * Extrait les requêtes contenues dans le script.
         *
         * @return string[]
         */
        protected function extractQueriesFromScript()
        {
            $parts = preg_split("#^/$#m", file_get_contents($this->scriptPath));
            $queries = array_filter(array_map('trim', $parts));
    
            if (count($queries) === 0) {
                throw new RuntimeException("Aucune requête trouvée dans le script '$this->scriptPath'");
            }
    
            return $queries;
        }
    
        /**
         * Exécute dans la transaction courante les requêtes spécifiées.
         *
         * @param string[] $queries
         * @return RunSQLResult
         */
        private function executeQueries($queries)
        {
            $result = new RunSQLResult();
            $result->attachLogger($this->logger);
            $result->setIsSuccess(true);
    
            $this->queryStack = new RunSQLQueryStack();
    
            try {
                foreach ($queries as $q) {
                    $this->queryStack->startQuery($q);
                    $this->connection->executeQuery($q);
                    $this->queryStack->stopQuery();
                }
            } catch (DBALException $e) {
                $result->setIsSuccess(false);
                $result->setException($e);
    
                $this->queryStack->stopQueryWithException($e);
            }
    
            $result->setEndMicrotime();
    
            return $result;
        }
    
        /**
         * @return string
         */
        private function logQueries()
        {
            $logFilePath = $this->generateLogFilePath();
    
            $logger = new Logger();
            $logger->addWriter('stream', null, ['stream' => $logFilePath]);
    
            foreach ($this->queryStack->getQueries() as $query) {
                $logger->info("Requête : " . $query['sql']);
                if (isset($query['exception'])) {
                    /** @var Exception $exception */
                    $exception = $query['exception'];
                    $logger->info($exception->getMessage());
                    $logger->info($exception->getTraceAsString());
                }
                $logger->info("Temps d'exécution : " . $query['executionMS'] . " sec");
                $logger->info("---------------------------------------------------------------------------------------");
            }
    
            return $logFilePath;
        }
    
        /**
         * @return string
         */
        private function generateLogFilePath()
        {
            if ($this->logFilePath !== null) {
                return $this->logFilePath;
            }
    
            if ($this->scriptPath) {
                $this->logFilePath = sys_get_temp_dir() . '/' . basename($this->scriptPath) . '.log';
            } else {
                $this->logFilePath = sys_get_temp_dir() . '/' . uniqid('unicaen-app-run-sql-') . '.log';
            }
    
            return $this->logFilePath;
        }
    }