RenderCommand.php 5.57 KB
Newer Older
1
<?php declare(strict_types=1);
2
/*
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * This file is part of "irstea/plantuml-bundle".
 *
 * Copyright (C) 2016-2019 IRSTEA
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License and the GNU
 * Lesser General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
19
 */
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
20

21 22 23 24 25 26 27 28 29
namespace Irstea\PlantUmlBundle\Command;

use Irstea\PlantUmlBundle\Model\Graph;
use Irstea\PlantUmlBundle\Writer\StreamWriter;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
30
use Symfony\Component\Console\Style\SymfonyStyle;
31
use Symfony\Component\Filesystem\Filesystem;
32
use Symfony\Component\Process\ExecutableFinder;
33 34

/**
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
35
 * Description of ImportAffiliationCommand.
36 37 38 39 40 41 42 43
 */
class RenderCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('irstea:plantuml:render')
            ->setDescription("Créer la page d'un graphe ou plusieurs graphes.")
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
44 45
            ->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'Répertoire de destination.')
            ->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format du fichier à générer')
46 47 48 49
            ->addArgument('graph', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Graphe à générer');
    }

    /**
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
50
     * @param InputInterface  $input
51 52 53 54 55 56 57 58 59
     * @param OutputInterface $output
     * @SuppressWarnings(UnusedFormalParameter)
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $graphs = $input->getArgument('graph') ?: $this->getContainer()->getParameter('irstea_plant_uml.graph_keys');
        $format = $input->getOption('format') ?: $this->getContainer()->getParameter('irstea_plant_uml.output.format');
        $outputDir = $input->getOption('output') ?: $this->getContainer()->getParameter('irstea_plant_uml.output.directory');

60 61
        $io = new SymfonyStyle($input, $output);

Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
62 63
        foreach ($graphs as $name) {
            $target = $outputDir . DIRECTORY_SEPARATOR . $name . '.' . $format;
64 65 66

            $io->section("Graphe: $name");

67
            $graph = $this->getContainer()->get("irstea_plant_uml.graph.$name");
68 69

            $this->renderGraph($graph, $target, $format, $io);
70 71 72
        }
    }

73 74 75 76 77 78 79
    /**
     * @param Graph $graph
     * @param $target
     * @param $format
     * @param SymfonyStyle $io
     */
    private function renderGraph(Graph $graph, $target, $format, SymfonyStyle $io): void
80
    {
81 82
        $io->writeln("Fichier de sortie: <comment>$target</comment>");

83 84 85 86 87 88
        if (OutputInterface::VERBOSITY_VERY_VERBOSE <= $io->getVerbosity()) {
            $desc = [];
            $graph->toConfig($desc);
            $io->writeln(json_encode($desc, JSON_PRETTY_PRINT));
        }

Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
89
        $io->write('Exploration des classes: ');
90
        $graph->visitAll();
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
91
        $io->writeln('<info>Ok</info>.');
92

Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
93
        $io->write('Démarrage de PlantUML: ');
94
        list($proc, $pipes) = $this->startProcess($target, $format);
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
95
        $io->writeln('<info>Ok</info>.');
96

Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
97
        $io->write('Génération du graphe: ');
98 99 100
        $writer = new StreamWriter($pipes[0]);
        $graph->writeTo($writer);
        fclose($pipes[0]);
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
101
        $io->writeln('<info>Ok</info>.');
102

Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
103
        $io->write('Rendu graphique par PlantUML: ');
104 105
        $res = proc_close($proc);

106
        if ($res === 0) {
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
107
            $io->writeln('<info>Ok</info>.');
108
        } else {
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
109
            $io->writeln('<error>Nok</error>.');
110
        }
111 112
    }

113 114 115 116 117 118
    /**
     * @param $target
     * @param $format
     * @return array
     */
    private function startProcess($target, $format): array
119
    {
120 121 122 123
        $ctn = $this->getContainer();
        $javaBin = $this->findExecutable($ctn->getParameter('irstea_plant_uml.binaries.java'));
        $dotBin = $this->findExecutable($ctn->getParameter('irstea_plant_uml.binaries.dot'));

124 125 126
        $fs = new Filesystem();
        $fs->mkdir(dirname($target));

Raidelet Nicolas's avatar
Raidelet Nicolas committed
127 128 129
        $cmd = implode(
            ' ',
            [
130
                $javaBin,
Raidelet Nicolas's avatar
Raidelet Nicolas committed
131 132 133
                '-jar',
                $ctn->getParameter('irstea_plant_uml.binaries.plamtuml_jar'),
                '-graphvizdot',
134
                $dotBin,
Raidelet Nicolas's avatar
Raidelet Nicolas committed
135 136 137 138
                '-pipe',
                '-t' . $format,
            ]
        );
139 140 141 142 143 144 145

        $desc = [
            // stdin
            ['pipe', 'r'],
            // stdout
            ['file', $target, 'wt'],
            // stderr
Guillaume Perréal's avatar
CS.  
Guillaume Perréal committed
146
            STDERR,
147 148 149 150 151 152 153
        ];
        $pipes = [];

        $proc = proc_open($cmd, $desc, $pipes);

        return [$proc, $pipes];
    }
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

    /**
     * @param string $nameOrPath
     * @return string
     */
    private function findExecutable(string $nameOrPath): string
    {
        if (\file_exists($nameOrPath) && \is_executable($nameOrPath)) {
            return $nameOrPath;
        }
        $exec = new ExecutableFinder();
        $path = $exec->find($nameOrPath);
        if ($path === null) {
            throw new \RuntimeException("cannot find executable: $nameOrPath");
        }
        return $path;
    }
171
}