Skip to content
Snippets Groups Projects
Select Git revision
  • d9778b6459182e5495ba9f88a81122b6c948f8e7
  • master default protected
  • detached3
  • detached4
  • detached2
  • detached
  • php82
  • 6.6.1
  • 6.6.0
  • 6.5.0
  • 6.4.0
  • 6.3.0
  • 6.2.3
  • 6.2.2
  • 6.2.1
  • 6.2.0
  • 6.1.5
  • 6.1.4
  • 6.1.3
  • 6.1.2
  • 6.1.1
  • 6.1.0
  • 6.0.10
  • 6.0.9
  • 6.0.8
  • 6.0.7
  • 6.0.6
27 results

CodeGeneratorService.php

Blame
  • Laurent Lécluse's avatar
    Laurent Lecluse authored
    - Prise en compte des PSR 0/4
    - Meilleure logs à la génération
    d9778b64
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    CodeGeneratorService.php 14.04 KiB
    <?php
    
    namespace UnicaenCode\Service;
    
    use Exception;
    use UnicaenCode\Form\AbstractForm;
    use UnicaenCode\Form\FormMaker;
    use UnicaenCode\Generator\GeneratorFromInterface;
    use UnicaenCode\Generator\GeneratorInterface;
    use UnicaenCode\Service\Traits\ConfigServiceAwareTrait;
    use UnicaenCode\Util;
    use Laminas\Console\Console;
    use Laminas\Http\Request;
    use Laminas\Mvc\Controller\AbstractActionController;
    use Laminas\Stdlib\ArrayUtils;
    use Laminas\Stdlib\Parameters;
    
    /**
     *
     *
     * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
     */
    class CodeGeneratorService
    {
        use ConfigServiceAwareTrait;
    
    
        public function generer(array $params): array
        {
            $oriParams = $params;
    
            if ($title = $params['title'] ?? null) {
                if (Console::isConsole()) {
                    echo $title."\n";
                } else {
                    echo '<h1>' . $title . '</h1>';
                }
            }
    
            $doGen = true;
            if (Console::isConsole()) {
                $console = $this->paramsFromConsole();
                foreach ($oriParams as $name => $value) {
                    if (is_array($value)) {
                        if (array_key_exists($name, $console)) {
                            $params[$name] = $console[$name];
                        } else {
                            $params[$name] = $value['value'] ?? null;
                        }
                    }
                }
            } else {
                $formParams = [];
                if (Util::$controller->getRequest()->isPost()) {
                    $post = Util::$controller->getRequest()->getPost()->toArray();
                } else {
                    $post  = [];
                    $doGen = false;
                }
                foreach ($oriParams as $name => $value) {
                    if (is_array($value)) {
                        $formParams[$name] = $value;
                        if (array_key_exists($name, $post)) {
                            $formParams[$name]['value'] = $post[$name];
                        }
                    }
                }
    
                $form = FormMaker::createFromArray($formParams);
                if ($form->hasSaisieElements()) {
                    $form->afficher();
                } else {
                    $doGen = true;
                }
    
                foreach ($oriParams as $name => $value) {
                    if (is_array($value)) {
                        $params[$name] = $form->getParamValue($name);
                    }
                }
    
                if ($cmd = $this->genCmd($oriParams, $params)) {
                    $params['commandLine'] = $cmd;
                }
            }
    
            if ($doGen) {
                $params = $this->generate($params);
            }
    
            return $params;
        }
    
    
    
        protected function paramsFromConsole(): array
        {
            $params = [];
    
            $request = Util::$controller->getRequest();
            $ps      = $request->getParams()->toArray();
            $i       = 0;
            while (array_key_exists('p' . $i, $ps)) {
                $param = $ps['p' . $i];
                $eq    = strpos($param, '=');
                if (false !== $eq) {
                    $key   = substr($param, 0, $eq);
                    $value = substr($param, $eq + 1);
    
                    if ($value === 'true') $value = true;
                    if ($value === 'false') $value = false;
    
                    $params[$key] = $value;
                }
                $i++;
            }
    
            return $params;
        }
    
    
    
        public function getParams(string $name): array
        {
            $paramsDirs = $this->getServiceConfig()->getParamsDirs();
    
            foreach ($paramsDirs as $paramsDir) {
                $paramsFile = $paramsDir . '/' . $name . '.php';
                if (file_exists($paramsFile)) break;
            }
    
            if (!$paramsFile) {
                throw new Exception('Le fichier de paramètres ' . $name . ' n\'a pas été trouvé dans les répertoires de paramètres d\'UnicaenCode');
            }
    
            $params = require $paramsFile;
    
            return $params;
        }
    
    
    
        protected function generate(array $params): array
        {
            /* Passage du générateur */
            $generator = $params['generator'] ?? null;
    
            if (is_string($generator)) {
                if ($generator = $this->getGenerator($generator)) {
                    $params = $generator->generate($params);
                }
            } elseif (is_callable($generator)) {
                $params = $generator($params);
            }
    
    
            /* On crée les sous-configs */
            $genFrom = $this->getServiceConfig()->getGeneratorsFrom();
            foreach ($genFrom as $key => $genConf) {
                $this->generateFrom($params, $key);
            }
    
            foreach ($params as $name => $value) {
                if (is_array($value) && !array_key_exists($name, $genFrom)) {
                    $params[$name] = $this->generate($value);
                }
            }
    
            $params = $this->runTriggers($params);
    
            /* Génération du fichier final & rendu */
            $params = $this->makeCode($params);
    
            if (Console::isConsole()){
                $this->write($params);
            }else{
                $this->echo($params);
            }
    
            if (isset($params['commandLine'])) {
                ?>
                <h1>Création des fichiers depuis la ligne de commandes</h1>
                <div class="alert alert-warning">
                    <p>Pour ajouter les fichiers listés ci-dessus à votre projet (hors exemples de configuration), lancez depuis le répertoire de votre projet la
                        commande suivante :
                        <br/>
                        <code><?= $params['commandLine'] ?></code>
    
                    </p>
                </div>
                <?php
            }
    
            return $params;
        }
    
    
    
        protected function genCmd(array $oriParams, array $params): ?string
        {
            $diff = [];
            foreach ($oriParams as $key => $oriVal) {
                if (is_callable($oriVal)) continue;
                if (is_array($oriVal)) $oriVal = $oriVal['value'] ?? null;
                if ($oriVal != $params[$key]) {
                    $diff[$key] = $params[$key];
                }
            }
    
            $cmd      = 'php public/index.php UnicaenCode ';
            $viewName = Util::$controller->params()->fromRoute('view');
            $cmd      .= $viewName;
            if (!empty($diff)) {
                foreach ($diff as $k => $v) {
                    if ($v === true) $v = 'true';
                    if ($v === false) $v = 'false';
    
                    $cmd .= ' ' . $k . '=' . escapeshellarg($v);
                }
            }
    
            return $cmd;
        }
    
    
    
        public function generateFrom(array &$params, string $key)
        {
            $genFrom   = $this->getServiceConfig()->getGeneratorsFrom();
            $generator = $genFrom[$key]['generator'] ?? null;
            $useParams = $genFrom[$key]['useParams'] ?? [];
    
            if (array_key_exists($key, $params) && $params[$key] === true) {
                $subParams = self::transferParams($params, $useParams);
                if ($generator) {
                    $subParams['generator'] = $generator;
                }
                $params[$key] = $this->generate($subParams);
            }
        }
    
    
    
        public static function transferParams(array $params, array $useParams): array
        {
            $subParams = [];
            foreach ($useParams as $useParam) {
                if (isset($params[$useParam])) $subParams[$useParam] = $params[$useParam];
            }
    
            return $subParams;
        }
    
    
    
        protected function runTriggers(array $params): array
        {
            $triggers = $this->getServiceConfig()->getTriggers();
            foreach ($triggers as $t) {
                $function = $t['function'];
                unset($t['function']);
                $run = true;
                if (!empty($t)) {
                    foreach ($t as $pn => $pv) {
                        if (!isset($params[$pn])) {
                            $run = false;
                            break;
                        }
                        if (is_array($pv)) {
                            if (!in_array($params[$pn], $pv)) {
                                $run = false;
                                break;
                            }
                        } else {
                            if ($params[$pn] != $pv) {
                                $run = false;
                                break;
                            }
                        }
                    }
                }
                if ($run) {
                    $params = $function($params);
                }
            }
    
            return $params;
        }
    
    
    
        /**
         *
         * @throws Exception
         */
        protected function makeCode(array $params)
        {
            $template = $params['template'] ?? null;
    
            if (!$template) return $params;
    
            $code = $this->getTemplateCode($template);
    
            foreach ($params as $param => $value) {
                if (!is_array($value) && !is_object($value)) {
                    $code = $this->codeSetVariable($code, $param, $value);
                }
            }
    
            $code = trim($code); // éviter les espaces inutiles en début et fin de fichier
    
            /* On débarasse le code de ses caractères inutiles !! */
            $code = explode(PHP_EOL, $code);
            foreach ($code as $i => $line) {
                if (trim($line)) {
                    $code[$i] = rtrim($line);
                } else {
                    $code[$i] = '';
                }
            }
            $code = implode(PHP_EOL, $code);
    
            $params['code'] = $code;
    
            return $params;
        }
    
    
    
        public function getGenerator(string $generator): ?GeneratorInterface
        {
            $genClass = $generator;
            if (!class_exists($generator)) {
                $generator = 'UnicaenCode\\Generator\\' . $generator;
            }
            if (class_exists($generator)) {
                return new $generator;
            }
    
            return null;
        }
    
    
    
        public function getTemplateCode(string $template): string
        {
            $templateDirs = $this->getServiceConfig()->getTemplateDirs();
            $templateFile = null;
            foreach ($templateDirs as $templateDir) {
                $templateFile = $templateDir . '/' . $template . '.php';
                if (file_exists($templateFile)) break;
            }
    
            if (!$templateFile) {
                throw new Exception('Le modèle ' . $template . ' n\'a pas été trouvé dans les répertoires de modèles d\'UnicaenCode');
            }
    
            return file_get_contents($templateFile);
        }
    
    
    
        protected function codeSetVariable($code, $param, $value)
        {
            // Si c'est un tableau alors on concatène en string...
            if (is_array($param)) {
                $param = implode('', $param);
            }
    
            // application des paramètres simples
            $code = str_replace('<' . $param . '>', $value, $code);
    
            // Gestion des conditions
            $if = '<if ' . $param . '>';
            while (false !== ($begin = strpos($code, $if))) {
                $endIf = '<endif ' . $param . '>';
    
                $end = strpos($code, $endIf, $begin);
    
                if ($value) {
                    $ifCode = ltrim(substr($code, $begin + strlen($if), $end - $begin - strlen($if)));
                } else {
                    $ifCode = '';
                }
    
                $end += strlen($endIf);
    
                if (isset($code[$begin - 1]) && isset($code[$end])) {
                    $b = trim($code[$begin - 1]);
                    $e = trim($code[$end]);
                    // ATTENTION : il n'y pas de support des retours chariot Windows (\n\r) car ils font 2 caractères ! ! !
                    if ($b === '' && $e === '') $end++; // pour éviter les retours chariot ou espaces inutiles
                }
    
                $code = substr($code, 0, $begin) . $ifCode . substr($code, $end);
            }
    
            // Gestion des conditions
            $if = '<if ' . $param . ' notrim>';
            while (false !== ($begin = strpos($code, $if))) {
                $endIf = '<endif ' . $param . '>';
    
                $end = strpos($code, $endIf, $begin);
    
                if ($value) {
                    $ifCode = substr($code, $begin + strlen($if), $end - $begin - strlen($if));
                } else {
                    $ifCode = '';
                }
    
                $end += strlen($endIf);
    
                if (isset($code[$begin - 1]) && isset($code[$end])) {
                    $b = trim($code[$begin - 1]);
                    $e = trim($code[$end]);
                    // ATTENTION : il n'y pas de support des retours chariot Windows (\n\r) car ils font 2 caractères ! ! !
                    if ($b === '' && $e === '') $end++; // pour éviter les retours chariot ou espaces inutiles
                }
    
                $code = substr($code, 0, $begin) . $ifCode . substr($code, $end);
            }
    
            // restitution
            return $code;
        }
    
    
    
        /**
         * @param array $params
         *
         * @return $this
         */
        protected function echo(array $params): self
        {
            $expanded = $params['expanded'] ?? true;
            $filename = $params['filename'] ?? 'Code source (fichier sans nom)';
            $code     = $params['code'] ?? null;
            $write    = $params['write'] ?? true;
    
            $id = uniqid('bloc_code_');
            ?>
            <a role="button" data-toggle="collapse" href="#<?= $id ?>" aria-expanded="<?= $expanded ? 'true' : 'false' ?>" aria-controls="collapseExample">
                <?= $filename ?>
            </a>
            <?php if (!$write): ?>
                <span class="label label-warning">A TRAITER MANUELLEMENT</span>
            <?php endif; ?>
            <br/>
            <div class="collapse<?= $expanded ? ' in' : '' ?>" id="<?= $id ?>">
                <?php Util::highlight($code, 'php', true, ['show-line-numbers' => true]); ?>
            </div>
            <?php
    
            return $this;
        }
    
    
    
        /**
         * @param array $params
         *
         * @return $this
         */
        protected function write(array $params): self
        {
            $write    = $params['write'] ?? true;
            $filename = $params['filename'] ?? null;
            $code     = $params['code'] ?? null;
    
            if (!$filename){
                return $this;
            }
    
            $outputDir = $params['outputDir'] ?? getcwd();
            $filename  = $outputDir . '/' . $filename;
    
            if (!$write){
                echo 'A TRAITER MANUELLEMENT : '.$filename."\n";
    
                return $this;
            }
    
            $parts = explode('/', substr($filename, 1));
            array_pop($parts);
            $dir = '';
            foreach ($parts as $part) {
                if (!is_dir(($dir .= "/$part"))) {
                    mkdir($dir);
                    chmod($dir, 0777);
                }
            }
    
            file_put_contents($filename, $code);
            echo 'FICHIER ECRIT : '.$filename."\n";
            chmod($filename, 0777);
    
            return $this;
        }
    }