Completed
Push — feature/new-generator ( 571f69 )
by
unknown
63:32
created

GenerateCommand   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 21
lcom 1
cbo 11
dl 0
loc 214
rs 10
c 1
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A configure() 0 7 1
A execute() 0 47 2
D getDefinitions() 0 44 10
A buildDynBundle() 0 22 1
B buildDocument() 0 32 5
A buildServiceAndRoutes() 0 9 1
1
<?php
2
/**
3
 * Generates the versions.yml file
4
 */
5
6
namespace Graviton\GeneratorV2Bundle\Command;
7
8
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Helper\ProgressBar;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Filesystem\Filesystem;
14
use Symfony\Bundle\FrameworkBundle\Console\Application;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\Finder\Finder;
17
use Symfony\Bundle\TwigBundle\TwigEngine;
18
use Symfony\Component\Yaml\Yaml;
19
20
/**
21
 * Reads out the used versions with composer and git and writes them in a file 'versions.yml'
22
 *
23
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
24
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
25
 * @link     http://swisscom.ch
26
 */
27
class GenerateCommand extends Command
28
{
29
    const NAME = 'generate-v2:generate';
30
31
    /** @var String wrapper or core */
32
    private $contextMode;
33
34
    /** @var String location for dynamic directory */
35
    private $dynamicDir;
36
37
    /** @var String location for dynamic directory */
38
    private $skeletonDir;
39
40
    /** @var array Service routes */
41
    private $routes = [];
42
43
    /** @var OutputInterface */
44
    private $output;
45
46
    /** @var Filesystem */
47
    private $filesystem;
48
49
    /** @var TwigEngine */
50
    private $templating;
51
52
    public function __construct(Filesystem $filesystem, $templating)
53
    {
54
        $this->filesystem = $filesystem;
55
        $this->templating = $templating;
56
57
        parent::__construct();
58
    }
59
60
    protected function configure()
61
    {
62
        $this->setName(self::NAME)
63
            ->setDescription(
64
                'Generates the versions.yml file according to definition in app/config/version_service.yml'
65
            );
66
    }
67
68
    protected function execute(InputInterface $input, OutputInterface $output)
69
    {
70
        $this->output = $output;
71
        /** @var Application $application */
72
        $application = $this->getApplication();
73
        /** @var ContainerInterface $container */
74
        $container = $application->getKernel()->getContainer();
75
        $rootDir = $container->getParameter('kernel.root_dir');
76
77
        if (strpos($rootDir, 'vendor')) {
78
            $this->output->writeln('Generating content for Wrapper mode');
79
            $this->contextMode = 'wrapper';
80
            $realDir = realpath($rootDir . '/../../../../');
81
            $this->skeletonDir = $realDir.'/vendor/graviton/graviton/src/Graviton/GeneratorV2Bundle/Resources/Skeleton';
82
        } else {
83
            $this->output->writeln('Generating content for Graviton core mode');
84
            $this->contextMode = 'core';
85
            $realDir = realpath($rootDir . '/../');
86
            $this->skeletonDir = $realDir . '/src/Graviton/GeneratorV2Bundle/Resources/Skeleton';
87
        }
88
        // Dynamic Dir, Will always be in vendor/graviton folder
89
        $this->dynamicDir = $realDir . '/vendor/graviton/graviton-dyn/src/GravitonDyn';
90
91
        // Is GravitonDyn Exists, remove it
92
        $this->output->writeln('Removing old Dynamic Dir');
93
        $this->filesystem->remove($this->dynamicDir);
94
95
        // Find the Definitions
96
        $this->output->writeln('Scanning for definitions');
97
        $definitions = $this->getDefinitions($realDir);
98
        $this->output->writeln('Definitions Found: '.count($definitions));
99
100
        // Build the basic bundle structure
101
        $this->buildDynBundle();
102
103
        // TODO Build the Documents
104
        $this->buildDocument($definitions);
105
106
        // TODO Build service and routing
107
        $this->buildServiceAndRoutes();
108
109
        // Register bundle
110
111
        // Build document getters and setter
112
        // php app/console doctrine:mongodb:generate:documents GravitonDynBundle
113
114
    }
115
116
    /**
117
     * Check project for files to be generated
118
     *
119
     * @param $realDir
120
     * @return array
121
     */
122
    private function getDefinitions($realDir)
123
    {
124
        $files = [];
125
        if ('wrapper' == $this->contextMode) {
126
            $directories = [
127
                $realDir . '/vendor/graviton',
128
                $realDir . '/vendor/grv',
129
            ];
130
        } else {
131
            $directories = [
132
                $realDir . '/src'
133
            ];
134
            if (is_dir($realDir . '/vendor/grv')) {
135
                $directories[] = $realDir . '/vendor/grv';
136
            }
137
            if (is_dir($realDir . '/vendor/graviton')) {
138
                $directories[] = $realDir . '/vendor/graviton';
139
            }
140
        }
141
        $finder = new Finder();
142
        $finder->files()->in($directories)->name('*.json');
143
        foreach ($finder as $file) {
144
            $path = $file->getRealPath();
145
            if (strpos($path, '/Resources/')) {
146
                $json = json_decode($file->getContents());
147
                if (json_last_error()) {
148
                    throw new InvalidConfigurationException($path.': '.json_last_error_msg());
149
                }
150
                if (isset($json->service, $json->service->routerBase)) {
151
                    if (!isset($json->id)) {
152
                        throw new InvalidConfigurationException($path.': This definition do not have required "id"');
153
                    }
154
                    if (array_key_exists($json->service->routerBase, $this->routes)) {
155
                        throw new InvalidConfigurationException(
156
                            $path.': '.$json->service->routerBase.': Route already exists!! '.$json->id
157
                        );
158
                    }
159
                    $this->routes[$json->service->routerBase] = $json->id;
160
                }
161
                $files[] = $json;
162
            }
163
        }
164
        return $files;
165
    }
166
167
    /**
168
     * Create the basic structure
169
     */
170
    private function buildDynBundle()
171
    {
172
        // Base directories
173
        $this->output->writeln('Creating Directories');
174
        $this->filesystem->mkdir($this->dynamicDir);
175
        $this->filesystem->mkdir($this->dynamicDir.'/Resources');
176
        $this->filesystem->mkdir($this->dynamicDir.'/Resources/config');
177
        $this->filesystem->mkdir($this->dynamicDir.'/Resources/schema');
178
        $this->filesystem->mkdir($this->dynamicDir.'/DependencyInjection');
179
        $this->filesystem->mkdir($this->dynamicDir.'/Document');
180
181
        // Base files
182
        $this->output->writeln('Creating Base files');
183
        $this->filesystem->dumpFile(
184
            $this->dynamicDir.'/GravitonDynBundle.php',
185
            $this->templating->render($this->skeletonDir.'/GravitonDynBundle.php.twig', [])
186
        );
187
        $this->filesystem->dumpFile(
188
            $this->dynamicDir.'/DependencyInjection/GravitonDynExtension.php',
189
            $this->templating->render($this->skeletonDir.'/DependencyInjection/GravitonDynExtension.php.twig', [])
190
        );
191
    }
192
193
    /**
194
     * Building Db Documents
195
     *
196
     * @param $definitions
197
     */
198
    private function buildDocument($definitions)
199
    {
200
        $progress = new ProgressBar($this->output, count($definitions));
201
        $progress->setMessage('Building documents');
202
203
        foreach ($definitions as $def)
204
        {
205
            $build = [
206
                'document'    => $def->id,
207
                'title'       => isset($def->title) ? $def->title : $def->id,
208
                'description' => isset($def->description) ? $def->description : $def->id,
209
                'fields'      => isset($def->target->fields) ? (array) $def->target->fields : (array) $def->properties
210
            ];
211
212
            // Schema
213
            $this->filesystem->dumpFile(
214
                $this->dynamicDir.'/Resources/schema/'.$def->id.'.json',
215
                json_encode($build, JSON_PRETTY_PRINT)
216
            );
217
            // Doctrine Document mapping
218
            $this->filesystem->dumpFile(
219
                $this->dynamicDir.'/Document/'.$def->id.'.php',
220
                $this->templating->render($this->skeletonDir.'/Document/Document.php.twig', $build)
221
            );
222
            $progress->setMessage('Task in progress...');
223
            $progress->advance();
224
            break;
225
        }
226
        $progress->setMessage('Task is finished');
227
        $progress->finish();
228
        $this->output->writeln("\n");
229
    }
230
231
    private function buildServiceAndRoutes()
232
    {
233
        // Build parameters Routes to be Used in RestService
234
        $string = Yaml::dump(['parameters'=> ['routes' => $this->routes]]);
235
        $this->filesystem->dumpFile(
236
            $this->dynamicDir.'/Resources/config/parameters.yml',
237
            $string
238
        );
239
    }
240
}
241