Completed
Push — master ( 4703e1...97bad7 )
by
unknown
11:22
created

GenerateDynamicBundleCommand::execute()   D

Complexity

Conditions 9
Paths 117

Size

Total Lines 111
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 59.6449

Importance

Changes 0
Metric Value
dl 0
loc 111
ccs 10
cts 69
cp 0.1449
rs 4.636
c 0
b 0
f 0
cc 9
eloc 62
nc 117
nop 2
crap 59.6449

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * generate dynamic bundles
4
 */
5
6
namespace Graviton\GeneratorBundle\Command;
7
8
use Graviton\GeneratorBundle\CommandRunner;
9
use Graviton\GeneratorBundle\Definition\JsonDefinition;
10
use Graviton\GeneratorBundle\Definition\JsonDefinitionArray;
11
use Graviton\GeneratorBundle\Definition\JsonDefinitionHash;
12
use Graviton\GeneratorBundle\Generator\DynamicBundleBundleGenerator;
13
use Graviton\GeneratorBundle\Manipulator\File\XmlManipulator;
14
use Graviton\GeneratorBundle\Definition\Loader\LoaderInterface;
15
use JMS\Serializer\SerializerInterface;
16
use Symfony\Component\Console\Command\Command;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\Finder\Finder;
22
use Symfony\Component\Finder\SplFileInfo;
23
24
/**
25
 * Here, we generate all "dynamic" Graviton bundles..
26
 *
27
 * @todo     create a new Application in-situ
28
 * @todo     see if we can get rid of container dependency..
29
 *
30
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
31
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
32
 * @link     http://swisscom.ch
33
 */
34
class GenerateDynamicBundleCommand extends Command
35
{
36
37
    /** @var  string */
38
    const BUNDLE_NAMESPACE = 'GravitonDyn';
39
40
    /** @var  string */
41
    const BUNDLE_NAME_MASK = self::BUNDLE_NAMESPACE.'/%sBundle';
42
43
    /** @var  string */
44
    const GENERATION_HASHFILE_FILENAME = 'genhash';
45
46
    /** @var  string */
47
    private $bundleBundleNamespace;
48
49
    /** @var  string */
50
    private $bundleBundleDir;
51
52
    /** @var  string */
53
    private $bundleBundleClassname;
54
55
    /** @var  string */
56
    private $bundleBundleClassfile;
57
58
    /** @var  array */
59
    private $bundleBundleList = [];
60
61
    /** @var array|null */
62
    private $bundleAdditions = null;
63
64
    /** @var array|null */
65
    private $serviceWhitelist = null;
66
67
    /**
68
     * @var CommandRunner
69
     */
70
    private $runner;
71
    /**
72
     * @var LoaderInterface
73
     */
74
    private $definitionLoader;
75
    /**
76
     * @var XmlManipulator
77
     */
78
    private $xmlManipulator;
79
    /**
80
     * @var SerializerInterface
81
     */
82
    private $serializer;
83
84
85
    /**
86
     * @param CommandRunner       $runner           Runs a console command.
87
     * @param XmlManipulator      $xmlManipulator   Helper to change the content of a xml file.
88
     * @param LoaderInterface     $definitionLoader JSON definition loader
89
     * @param SerializerInterface $serializer       Serializer
90
     * @param string|null         $bundleAdditions  Additional bundles list in JSON format
91
     * @param string|null         $serviceWhitelist Service whitelist in JSON format
92
     * @param string|null         $name             The name of the command; passing null means it must be set in
93
     *                                              configure()
94
     */
95 6
    public function __construct(
96
        CommandRunner       $runner,
97
        XmlManipulator      $xmlManipulator,
98
        LoaderInterface     $definitionLoader,
99
        SerializerInterface $serializer,
100
        $bundleAdditions = null,
101
        $serviceWhitelist = null,
102
        $name = null
103
    ) {
104 6
        parent::__construct($name);
105
106 6
        $this->runner = $runner;
107 6
        $this->xmlManipulator = $xmlManipulator;
108 6
        $this->definitionLoader = $definitionLoader;
109 6
        $this->serializer = $serializer;
110
111 6
        if ($bundleAdditions !== null && $bundleAdditions !== '') {
112
            $this->bundleAdditions = $bundleAdditions;
0 ignored issues
show
Documentation Bug introduced by
It seems like $bundleAdditions of type string is incompatible with the declared type array|null of property $bundleAdditions.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
113
        }
114 6
        if ($serviceWhitelist !== null && $serviceWhitelist !== '') {
115
            $this->serviceWhitelist = $serviceWhitelist;
0 ignored issues
show
Documentation Bug introduced by
It seems like $serviceWhitelist of type string is incompatible with the declared type array|null of property $serviceWhitelist.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
116
        }
117 6
    }
118
119
    /**
120
     * {@inheritDoc}
121
     *
122
     * @return void
123
     */
124 6
    protected function configure()
125
    {
126 6
        parent::configure();
127
128 6
        $this->addOption(
129 6
            'json',
130 6
            '',
131 6
            InputOption::VALUE_OPTIONAL,
132 3
            'Path to the json definition.'
133 3
        )
134 6
            ->addOption(
135 6
                'srcDir',
136 6
                '',
137 6
                InputOption::VALUE_OPTIONAL,
138 6
                'Src Dir',
139 6
                dirname(__FILE__) . '/../../../'
140 3
            )
141 6
            ->addOption(
142 6
                'bundleBundleName',
143 6
                '',
144 6
                InputOption::VALUE_OPTIONAL,
145 6
                'Which BundleBundle to manipulate to add our stuff',
146 3
                'GravitonDynBundleBundle'
147 3
            )
148 6
            ->addOption(
149 6
                'bundleFormat',
150 6
                '',
151 6
                InputOption::VALUE_OPTIONAL,
152 6
                'Which format',
153 3
                'xml'
154 3
            )
155 6
            ->setName('graviton:generate:dynamicbundles')
156 6
            ->setDescription(
157
                'Generates all dynamic bundles in the GravitonDyn namespace. Either give a path
158 3
                    to a single JSON file or a directory path containing multiple files.'
159 3
            );
160 6
    }
161
162
    /**
163
     * {@inheritDoc}
164
     *
165
     * @param InputInterface  $input  input
166
     * @param OutputInterface $output output
167
     *
168
     * @return void
169
     */
170 2
    protected function execute(InputInterface $input, OutputInterface $output)
171
    {
172
        /**
173
         * GENERATE THE BUNDLEBUNDLE
174
         */
175 2
        $namespace = sprintf(self::BUNDLE_NAME_MASK, 'Bundle');
176
177
        // GravitonDynBundleBundle
178 2
        $bundleName = str_replace('/', '', $namespace);
179
180
        // bundlebundle stuff..
181 2
        $this->bundleBundleNamespace = $namespace;
182 2
        $this->bundleBundleDir = $input->getOption('srcDir') . $namespace;
183 2
        $this->bundleBundleClassname = $bundleName;
184 2
        $this->bundleBundleClassfile = $this->bundleBundleDir . '/' . $this->bundleBundleClassname . '.php';
185
186 2
        $filesToWorkOn = $this->definitionLoader->load($input->getOption('json'));
187
188 2
        if (count($filesToWorkOn) < 1) {
189 2
            throw new \LogicException("Could not find any usable JSON files.");
190
        }
191
192
        $fs = new Filesystem();
193
194
        $this->createInitialBundleBundle($input->getOption('srcDir'));
195
196
        $templateHash = $this->getTemplateHash();
197
        $existingBundles = $this->getExistingBundleHashes($input->getOption('srcDir'));
198
199
        /**
200
         * GENERATE THE BUNDLE(S)
201
         */
202
        foreach ($filesToWorkOn as $jsonDef) {
203
            $thisIdName = $jsonDef->getId();
204
            $namespace = sprintf(self::BUNDLE_NAME_MASK, $thisIdName);
205
206
            $jsonDef->setNamespace($namespace);
207
208
            $bundleName = str_replace('/', '', $namespace);
209
            $this->bundleBundleList[] = $namespace;
210
211
            try {
212
                $bundleDir = $input->getOption('srcDir').$namespace;
213
                $thisHash = sha1($templateHash.PATH_SEPARATOR.serialize($jsonDef));
214
215
                $needsGeneration = true;
216
                if (isset($existingBundles[$bundleDir])) {
217
                    if ($existingBundles[$bundleDir] == $thisHash) {
218
                        $needsGeneration = false;
219
                    }
220
                    unset($existingBundles[$bundleDir]);
221
                }
222
223
                if ($needsGeneration) {
224
                    $this->generateBundle($namespace, $bundleName, $input, $output, $bundleDir);
225
                    $this->generateGenerationHashFile($bundleDir, $thisHash);
226
                }
227
228
                $this->generateBundleBundleClass();
229
230
                if ($needsGeneration) {
231
                    $this->generateSubResources($output, $jsonDef, $this->xmlManipulator, $bundleName, $namespace);
232
                    $this->generateMainResource($output, $jsonDef, $bundleName);
233
                    $this->generateValidationXml(
234
                        $this->xmlManipulator,
235
                        $this->getGeneratedValidationXmlPath($namespace)
236
                    );
237
238
                    $output->write(
239
                        PHP_EOL.
240
                        sprintf('<info>Generated "%s" from definition %s</info>', $bundleName, $jsonDef->getId()).
241
                        PHP_EOL
242
                    );
243
                } else {
244
                    $output->write(
245
                        PHP_EOL.
246
                        sprintf('<info>Using pre-existing "%s"</info>', $bundleName).
247
                        PHP_EOL
248
                    );
249
                }
250
            } catch (\Exception $e) {
251
                $output->writeln(
252
                    sprintf('<error>%s</error>', $e->getMessage())
253
                );
254
255
                // remove failed bundle from list
256
                array_pop($this->bundleBundleList);
257
            }
258
259
            $this->xmlManipulator->reset();
260
        }
261
262
        // whatever is left in $existingBundles is not defined anymore and needs to be deleted..
263
        foreach ($existingBundles as $dirName => $hash) {
264
            $fileInfo = new \SplFileInfo($dirName);
265
            $bundleClassName = $this->getBundleClassnameFromFolder($fileInfo->getFilename());
266
267
            // remove from bundlebundle list
268
            unset($this->bundleBundleList[array_search($bundleClassName, $this->bundleBundleList)]);
269
270
            $fs->remove($dirName);
271
272
            $output->write(
273
                PHP_EOL.
274
                sprintf('<info>Deleted obsolete bundle "%s"</info>', $dirName).
275
                PHP_EOL
276
            );
277
        }
278
279
        $this->generateBundleBundleClass();
280
    }
281
282
    /**
283
     * scans through all existing dynamic bundles, checks if there is a generation hash and collect that
284
     * all in an array that can be used for fast checking.
285
     *
286
     * @param string $baseDir base directory of dynamic bundles
287
     *
288
     * @return array key is bundlepath, value is the current hash
289
     */
290
    private function getExistingBundleHashes($baseDir)
291
    {
292
        $existingBundles = [];
293
        $fs = new Filesystem();
294
        $bundleBaseDir = $baseDir.self::BUNDLE_NAMESPACE;
295
296
        if (!$fs->exists($bundleBaseDir)) {
297
            return $existingBundles;
298
        }
299
300
        $bundleFinder = $this->getBundleFinder($baseDir);
301
302
        foreach ($bundleFinder as $bundleDir) {
0 ignored issues
show
Bug introduced by
The expression $bundleFinder of type null|object<Symfony\Component\Finder\Finder> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
303
            $genHash = '';
304
            $hashFileFinder = new Finder();
305
            $hashFileIterator = $hashFileFinder
306
                ->files()
307
                ->in($bundleDir->getPathname())
308
                ->name(self::GENERATION_HASHFILE_FILENAME)
309
                ->depth('== 0')
310
                ->getIterator();
311
312
            $hashFileIterator->rewind();
313
314
            $hashFile = $hashFileIterator->current();
315
            if ($hashFile instanceof SplFileInfo) {
316
                $genHash = $hashFile->getContents();
317
            }
318
319
            $existingBundles[$bundleDir->getPathname()] = $genHash;
320
        }
321
322
        return $existingBundles;
323
    }
324
325
    /**
326
     * we cannot just delete the BundleBundle at the beginning, we need to prefill
327
     * it with all existing dynamic bundles..
328
     *
329
     * @param string $baseDir base dir
330
     *
331
     * @return void
332
     */
333
    private function createInitialBundleBundle($baseDir)
334
    {
335
        $bundleFinder = $this->getBundleFinder($baseDir);
336
337
        if (!$bundleFinder) {
338
            return;
339
        }
340
341
        foreach ($bundleFinder as $bundleDir) {
342
            $this->bundleBundleList[] = $this->getBundleClassnameFromFolder($bundleDir->getFilename());
343
        }
344
345
        $this->generateBundleBundleClass();
346
    }
347
348
    /**
349
     * from a name of a folder of a bundle, this function returns the corresponding class name
350
     *
351
     * @param string $folderName folder name
352
     *
353
     * @return string
354
     */
355
    private function getBundleClassnameFromFolder($folderName)
356
    {
357
        if (substr($folderName, -6) == 'Bundle') {
358
            $folderName = substr($folderName, 0, -6);
359
        }
360
361
        return sprintf(self::BUNDLE_NAME_MASK, $folderName);
362
    }
363
364
    /**
365
     * returns a finder that iterates all bundle directories
366
     *
367
     * @param string $baseDir the base dir to search
368
     *
369
     * @return Finder|null finder or null if basedir does not exist
370
     */
371
    private function getBundleFinder($baseDir)
372
    {
373
        $bundleBaseDir = $baseDir.self::BUNDLE_NAMESPACE;
374
375
        if (!(new Filesystem())->exists($bundleBaseDir)) {
376
            return null;
377
        }
378
379
        $bundleFinder = new Finder();
380
        $bundleFinder->directories()->in($bundleBaseDir)->depth('== 0')->notName('BundleBundle');
381
382
        return $bundleFinder;
383
    }
384
385
    /**
386
     * Calculates a hash of all templates that generator uses to output it's file.
387
     * That way a regeneration will be triggered when one of them changes..
388
     *
389
     * @return string hash
390
     */
391
    private function getTemplateHash()
392
    {
393
        $templateDir = __DIR__ . '/../Resources/skeleton';
394
        $resourceFinder = new Finder();
395
        $resourceFinder->in($templateDir)->files()->sortByName();
396
        $templateTimes = '';
397
        foreach ($resourceFinder as $file) {
398
            $templateTimes .= PATH_SEPARATOR . $file->getMTime();
399
        }
400
        return sha1($templateTimes);
401
    }
402
403
    /**
404
     * Generate Bundle entities
405
     *
406
     * @param OutputInterface $output         Instance to sent text to be displayed on stout.
407
     * @param JsonDefinition  $jsonDef        Configuration to be generated the entity from.
408
     * @param XmlManipulator  $xmlManipulator Helper to safe the validation xml file.
409
     * @param string          $bundleName     Name of the bundle the entity shall be generated for.
410
     * @param string          $namespace      Absolute path to the bundle root dir.
411
     *
412
     * @return void
413
     * @throws \Exception
414
     */
415 4
    protected function generateSubResources(
416
        OutputInterface $output,
417
        JsonDefinition $jsonDef,
418
        XmlManipulator $xmlManipulator,
419
        $bundleName,
420
        $namespace
421
    ) {
422 4
        foreach ($this->getSubResources($jsonDef) as $subRecource) {
423
            $arguments = [
424
                'graviton:generate:resource',
425
                '--no-debug' => null,
426
                '--entity' => $bundleName . ':' . $subRecource->getId(),
427
                '--format' => 'xml',
428
                '--json' => $this->serializer->serialize($subRecource->getDef(), 'json'),
429
                '--fields' => $this->getFieldString($subRecource),
430
                '--no-controller' => 'true',
431
            ];
432
            $this->generateResource($arguments, $output, $jsonDef);
433
434
            // look for validation.xml and save it from over-writing ;-)
435
            // we basically get the xml content that was generated in order to save them later..
436
            $validationXml = $this->getGeneratedValidationXmlPath($namespace);
437
            if (file_exists($validationXml)) {
438
                $xmlManipulator->addNodes(file_get_contents($validationXml));
439
            }
440 2
        }
441 4
    }
442
443
    /**
444
     * Generate the actual Bundle
445
     *
446
     * @param OutputInterface $output     Instance to sent text to be displayed on stout.
447
     * @param JsonDefinition  $jsonDef    Configuration to be generated the entity from.
448
     * @param string          $bundleName Name of the bundle the entity shall be generated for.
449
     *
450
     * @return void
451
     */
452
    protected function generateMainResource(OutputInterface $output, JsonDefinition $jsonDef, $bundleName)
453
    {
454
        $fields = $jsonDef->getFields();
455
        if (!empty($fields)) {
456
            $arguments = array(
457
                'graviton:generate:resource',
458
                '--no-debug' => null,
459
                '--entity' => $bundleName . ':' . $jsonDef->getId(),
460
                '--json' => $this->serializer->serialize($jsonDef->getDef(), 'json'),
461
                '--format' => 'xml',
462
                '--fields' => $this->getFieldString($jsonDef)
463
            );
464
465
            $this->generateResource($arguments, $output, $jsonDef);
466
        }
467
    }
468
469
    /**
470
     * Get all sub hashes
471
     *
472
     * @param JsonDefinition $definition Main JSON definition
473
     * @return JsonDefinition[]
474
     */
475 6
    protected function getSubResources(JsonDefinition $definition)
476
    {
477 6
        $resources = [];
478 6
        foreach ($definition->getFields() as $field) {
479 4
            while ($field instanceof JsonDefinitionArray) {
480 4
                $field = $field->getElement();
481 2
            }
482 4
            if (!$field instanceof JsonDefinitionHash) {
483 4
                continue;
484
            }
485
486 2
            $subDefiniton = $field->getJsonDefinition();
487
488 2
            $resources = array_merge($this->getSubResources($subDefiniton), $resources);
489 2
            $resources[] = $subDefiniton;
490 3
        }
491
492 6
        return $resources;
493
    }
494
495
    /**
496
     * Gathers data for the command to run.
497
     *
498
     * @param array           $arguments Set of cli arguments passed to the command
499
     * @param OutputInterface $output    Output channel to send messages to.
500
     * @param JsonDefinition  $jsonDef   Configuration of the service
501
     *
502
     * @return void
503
     * @throws \LogicException
504
     */
505
    private function generateResource(array $arguments, OutputInterface $output, JsonDefinition $jsonDef)
506
    {
507
        // controller?
508
        $routerBase = $jsonDef->getRouterBase();
509
        if ($routerBase === false || $this->isNotWhitelistedController($routerBase)) {
510
            $arguments['--no-controller'] = 'true';
511
        }
512
513
        $this->runner->executeCommand($arguments, $output, 'Create resource call failed, see above. Exiting.');
514
    }
515
516
    /**
517
     * Generates a Bundle via command line (wrapping graviton:generate:bundle)
518
     *
519
     * @param string          $namespace    Namespace
520
     * @param string          $bundleName   Name of bundle
521
     * @param InputInterface  $input        Input
522
     * @param OutputInterface $output       Output
523
     * @param string          $deleteBefore Delete before directory
0 ignored issues
show
Documentation introduced by
Should the type for parameter $deleteBefore not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
524
     *
525
     * @return void
526
     *
527
     * @throws \LogicException
528
     */
529
    private function generateBundle(
530
        $namespace,
531
        $bundleName,
532
        InputInterface $input,
533
        OutputInterface $output,
534
        $deleteBefore = null
535
    ) {
536
        // first, create the bundle
537
        $arguments = array(
538
            'graviton:generate:bundle',
539
            '--no-debug' => null,
540
            '--namespace' => $namespace,
541
            '--bundle-name' => $bundleName,
542
            '--dir' => $input->getOption('srcDir'),
543
            '--format' => $input->getOption('bundleFormat'),
544
            '--doUpdateKernel' => 'false',
545
            '--loaderBundleName' => $input->getOption('bundleBundleName'),
546
        );
547
548
        if (!is_null($deleteBefore)) {
549
            $arguments['--deleteBefore'] = $deleteBefore;
550
        }
551
552
        $this->runner->executeCommand(
553
            $arguments,
554
            $output,
555
            'Create bundle call failed, see above. Exiting.'
556
        );
557
    }
558
559
    /**
560
     * Generates our BundleBundle for dynamic bundles.
561
     * It basically replaces the Bundle main class that got generated
562
     * by the Sensio bundle task and it includes all of our bundles there.
563
     *
564
     * @return void
565
     */
566
    private function generateBundleBundleClass()
567
    {
568
        $dbbGenerator = new DynamicBundleBundleGenerator();
569
570
        // add optional bundles if defined by parameter.
571
        if ($this->bundleAdditions !== null) {
572
            $dbbGenerator->setAdditions($this->bundleAdditions);
573
        }
574
575
        $dbbGenerator->generate(
576
            $this->bundleBundleList,
577
            $this->bundleBundleNamespace,
578
            $this->bundleBundleClassname,
579
            $this->bundleBundleClassfile
580
        );
581
    }
582
583
    /**
584
     * Returns the path to the generated validation.xml
585
     *
586
     * @param string $namespace Namespace
587
     *
588
     * @return string path
589
     */
590
    private function getGeneratedValidationXmlPath($namespace)
591
    {
592
        return dirname(__FILE__) . '/../../../' . $namespace . '/Resources/config/validation.xml';
593
    }
594
595
    /**
596
     * Returns the field string as described in the json file
597
     *
598
     * @param JsonDefinition $jsonDef The json def
599
     *
600
     * @return string CommandLine string for the generator command
601
     */
602
    private function getFieldString(JsonDefinition $jsonDef)
603
    {
604
        $ret = array();
605
606
        foreach ($jsonDef->getFields() as $field) {
607
            // don't add 'id' field it seems..
608
            if ($field->getName() != 'id') {
609
                $ret[] = $field->getName() . ':' . $field->getTypeDoctrine();
610
            }
611
        }
612
613
        return implode(
614
            ' ',
615
            $ret
616
        );
617
    }
618
619
    /**
620
     * Checks an optional environment setting if this $routerBase is whitelisted there.
621
     * If something is 'not whitelisted' (return true) means that the controller should not be generated.
622
     * This serves as a lowlevel possibility to disable the generation of certain controllers.
623
     * If we have no whitelist defined, we consider that all services should be generated (default).
624
     *
625
     * @param string $routerBase router base
626
     *
627
     * @return bool true if yes, false if not
628
     */
629
    private function isNotWhitelistedController($routerBase)
630
    {
631
        if ($this->serviceWhitelist === null) {
632
            return false;
633
        }
634
635
        return !in_array($routerBase, $this->serviceWhitelist, true);
636
    }
637
638
    /**
639
     * renders and stores the validation.xml file of a bundle.
640
     *
641
     * what are we doing here?
642
     * well, when we started to generate our subclasses (hashes in our own service) as own
643
     * Document classes, i had the problem that the validation.xml always got overwritten by the
644
     * console task. sadly, validation.xml is one file for all classes in the bundle.
645
     * so here we merge the generated validation.xml we saved in the loop before back into the
646
     * final validation.xml again. the final result should be one validation.xml including all
647
     * the validation rules for all the documents in this bundle.
648
     *
649
     * @todo we might just make this an option to the resource generator, i need to grok why this was an issue
650
     *
651
     * @param XmlManipulator $xmlManipulator Helper to safe the validation xml file.
652
     * @param string         $location       Location where to store the file.
653
     *
654
     * @return void
655
     */
656
    private function generateValidationXml(XmlManipulator $xmlManipulator, $location)
657
    {
658
        if (file_exists($location)) {
659
            $xmlManipulator
660
                ->renderDocument(file_get_contents($location))
661
                ->saveDocument($location);
662
        }
663
    }
664
665
    /**
666
     * Generates the file containing the hash to determine if this bundle needs regeneration
667
     *
668
     * @param string $bundleDir directory of the bundle
669
     * @param string $hash      the hash to save
670
     *
671
     * @return void
672
     */
673
    private function generateGenerationHashFile($bundleDir, $hash)
674
    {
675
        $fs = new Filesystem();
676
        if ($fs->exists($bundleDir)) {
677
            $fs->dumpFile($bundleDir.DIRECTORY_SEPARATOR.self::GENERATION_HASHFILE_FILENAME, $hash);
678
        }
679
    }
680
681
    /**
682
     * Returns an XMLElement from a generated validation.xml that was generated during Resources generation.
683
     *
684
     * @param string $namespace Namespace, ie GravitonDyn\ShowcaseBundle
685
     *
686
     * @return \SimpleXMLElement The element
687
     *
688
     * @deprecated is this really used?
689
     */
690
    public function getGeneratedValidationXml($namespace)
691
    {
692
        $validationXmlPath = $this->getGeneratedValidationXmlPath($namespace);
693
        if (file_exists($validationXmlPath)) {
694
            $validationXml = new \SimpleXMLElement(file_get_contents($validationXmlPath));
695
            $validationXml->registerXPathNamespace('sy', 'http://symfony.com/schema/dic/constraint-mapping');
696
        } else {
697
            throw new \LogicException('Could not find ' . $validationXmlPath . ' that should be generated.');
698
        }
699
700
        return $validationXml;
701
    }
702
}
703