Completed
Push — feature/symfony3-compat ( 63d226 )
by Lucas
17:23
created

ResourceGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1
Metric Value
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.4285
cc 1
eloc 12
nc 1
nop 5
crap 1
1
<?php
2
/**
3
 * generator code for resources
4
 */
5
6
namespace Graviton\GeneratorBundle\Generator;
7
8
use Doctrine\Common\Collections\ArrayCollection;
9
use Graviton\GeneratorBundle\Definition\JsonDefinition;
10
use Graviton\GeneratorBundle\Generator\ResourceGenerator\FieldMapper;
11
use Graviton\GeneratorBundle\Generator\ResourceGenerator\ParameterBuilder;
12
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
13
use Symfony\Component\Filesystem\Filesystem;
14
use Symfony\Component\HttpKernel\HttpKernelInterface;
15
use Doctrine\Bundle\DoctrineBundle\Registry as DoctrineRegistry;
16
17
/**
18
 * bundle containing various code generators
19
 *
20
 * This code is more or less loosley based on SensioBundleGenerator. It could
21
 * use some refactoring to duplicate less for that, but this is how i finally
22
 * got a working version.
23
 *
24
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
25
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
26
 * @link     http://swisscom.ch
27
 *
28
 * @todo     split all the xml handling on services.conf into a Manipulator
29
 */
30
class ResourceGenerator extends AbstractGenerator
31
{
32
    /**
33
     * @private Filesystem
34
     */
35
    private $filesystem;
36
37
    /**
38
     * @private DoctrineRegistry
39
     */
40
    private $doctrine;
41
42
    /**
43
     * @private HttpKernelInterface
44
     */
45
    private $kernel;
46
47
    /**
48
     * our json file definition
49
     *
50
     * @var JsonDefinition|null
51
     */
52
    private $json = null;
53
54
    /**
55
     * @var ArrayCollection
56
     */
57
    protected $xmlParameters;
58
59
    /**
60
     * @var \DomDocument
61
     */
62
    private $serviceDOM;
63
64
    /**
65
     * @var FieldMapper
66
     */
67
    private $mapper;
68
69
    /**
70
     * @var boolean
71
     */
72
    private $generateController = false;
73
74
    /**
75
     * @var ParameterBuilder
76
     */
77
    private $parameterBuilder;
78
79
    /**
80
     * Instantiates generator object
81
     *
82
     * @param Filesystem          $filesystem       fs abstraction layer
83
     * @param DoctrineRegistry    $doctrine         odm registry
84
     * @param HttpKernelInterface $kernel           app kernel
85
     * @param FieldMapper         $mapper           field type mapper
86
     * @param ParameterBuilder    $parameterBuilder param builder
87
     */
88 2
    public function __construct(
89
        Filesystem $filesystem,
90
        DoctrineRegistry $doctrine,
91
        HttpKernelInterface $kernel,
92
        FieldMapper $mapper,
93
        ParameterBuilder $parameterBuilder
94
    ) {
95 2
        $this->filesystem = $filesystem;
96 2
        $this->doctrine = $doctrine;
97 2
        $this->kernel = $kernel;
98 2
        $this->mapper = $mapper;
99 2
        $this->parameterBuilder = $parameterBuilder;
100 2
        $this->xmlParameters = new ArrayCollection();
101 2
    }
102
103
    /**
104
     * @param JsonDefinition $json optional JsonDefinition object
105
     *
106
     * @return void
107
     */
108
    public function setJson(JsonDefinition $json)
109
    {
110
        $this->json = $json;
111
    }
112
113
    /**
114
     * @param boolean $generateController should the controller be generated or not
115
     *
116
     * @return void
117
     */
118
    public function setGenerateController($generateController)
119
    {
120
        $this->generateController = $generateController;
121
    }
122
123
    /**
124
     * generate the resource with all its bits and parts
125
     *
126
     * @param BundleInterface $bundle         bundle
127
     * @param string          $document       document name
128
     * @param string          $format         format of config files (please use xml)
129
     * @param array           $fields         fields to add
130
     * @param boolean         $withRepository generate repository class
131
     *
132
     * @return void
133
     */
134
    public function generate(
135
        BundleInterface $bundle,
136
        $document,
137
        $format,
138
        array $fields,
139
        $withRepository
140
    ) {
141
        $dir = $bundle->getPath();
142
        $basename = $this->getBundleBaseName($document);
143
        $bundleNamespace = substr(get_class($bundle), 0, 0 - strlen($bundle->getName()));
144
145
        if (!is_null($this->json)) {
146
            $this->json->setNamespace($bundleNamespace);
147
        }
148
149
        // add more info to the fields array
150
        $mapper = $this->mapper;
151
        $fields = array_map(
152
            function ($field) use ($mapper) {
153
                return $mapper->map($field, $this->json);
154
            },
155
            $fields
156
        );
157
        $parameters = $this->parameterBuilder
158
            ->setParameter('document', $document)
159
            ->setParameter('base', $bundleNamespace)
160
            ->setParameter('bundle', $bundle->getName())
161
            ->setParameter('format', $format)
162
            ->setParameter('json', $this->json)
163
            ->setParameter('fields', $fields)
164
            ->setParameter('basename', $basename)
165
            ->setParameter('isrecordOriginFlagSet', $this->json->isRecordOriginFlagSet())
166
            ->setParameter('recordOriginModifiable', $this->json->isRecordOriginModifiable())
167
            ->setParameter('collection', $this->json->getServiceCollection())
168
            ->getParameters();
169
170
        $this->generateDocument($parameters, $dir, $document, $withRepository);
171
        $this->generateSerializer($parameters, $dir, $document);
172
        $this->generateModel($parameters, $dir, $document);
173
174
        if ($this->json instanceof JsonDefinition && $this->json->hasFixtures() === true) {
175
            $this->generateFixtures($parameters, $dir, $document);
176
        }
177
178
        if ($this->generateController) {
179
            $this->generateController($parameters, $dir, $document);
180
        }
181
182
        $this->generateParameters($dir);
183
    }
184
185
    /**
186
     * Writes the current services definition to a file.
187
     *
188
     * @param string $dir base bundle dir
189
     *
190
     * @return void
191
     */
192 8
    protected function persistServicesXML($dir)
193
    {
194 8
        $services = $this->loadServices($dir);
195
196 8
        file_put_contents($dir . '/Resources/config/services.xml', $services->saveXML());
197 8
    }
198
199
    /**
200
     * generate document part of a resource
201
     *
202
     * @param array   $parameters     twig parameters
203
     * @param string  $dir            base bundle dir
204
     * @param string  $document       document name
205
     * @param boolean $withRepository generate repository class
206
     *
207
     * @return void
208
     */
209 6
    protected function generateDocument($parameters, $dir, $document, $withRepository)
210
    {
211
        // doctrine mapping normal class
212 6
        $this->renderFile(
213 6
            'document/Document.mongodb.xml.twig',
214 6
            $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml',
215
            $parameters
216 3
        );
217
218
        // doctrine mapping embedded
219 6
        $this->renderFile(
220 6
            'document/Document.mongodb.xml.twig',
221 6
            $dir . '/Resources/config/doctrine/' . $document . 'Embedded.mongodb.xml',
222 3
            array_merge(
223 3
                $parameters,
224
                [
225 6
                    'document' => $document.'Embedded',
226 6
                    'docType' => 'embedded-document',
227
                ]
228 3
            )
229 3
        );
230
231 6
        $this->renderFile(
232 6
            'document/Document.php.twig',
233 6
            $dir . '/Document/' . $document . '.php',
234
            $parameters
235 3
        );
236 6
        $this->renderFile(
237 6
            'document/DocumentEmbedded.php.twig',
238 6
            $dir . '/Document/' . $document . 'Embedded.php',
239
            $parameters
240 3
        );
241 6
        $this->renderFile(
242 6
            'document/DocumentBase.php.twig',
243 6
            $dir . '/Document/' . $document . 'Base.php',
244
            $parameters
245 3
        );
246
247 6
        $this->generateServices($parameters, $dir, $document, $withRepository);
248 6
    }
249
250
    /**
251
     * update xml services
252
     *
253
     * @param array   $parameters     twig parameters
254
     * @param string  $dir            base bundle dir
255
     * @param string  $document       document name
256
     * @param boolean $withRepository generate repository class
257
     *
258
     * @return void
259
     */
260 6
    protected function generateServices($parameters, $dir, $document, $withRepository)
261
    {
262 6
        $services = $this->loadServices($dir);
263
264 6
        $bundleParts = explode('\\', $parameters['base']);
265 6
        $shortName = $bundleParts[0];
266 6
        $shortBundle = $this->getBundleBaseName($bundleParts[1]);
267
268 6
        $docName = implode(
269 6
            '.',
270
            array(
271 6
                strtolower($shortName),
272 6
                strtolower($shortBundle),
273 6
                'document',
274 6
                strtolower($parameters['document'])
275 3
            )
276 3
        );
277
278 6
        $this->addXMLParameter(
279 6
            $parameters['base'] . 'Document\\' . $parameters['document'],
280 3
            $docName . '.class'
281 3
        );
282
283 6
        $this->addXMLParameter(
284 6
            $parameters['json']->getRoles(),
285 6
            $docName . '.roles',
286 3
            'collection'
287 3
        );
288
289 6
        $services = $this->addService(
290 3
            $services,
291
            $docName
292 3
        );
293
294 6
        if ($withRepository) {
295
            $repoName = implode(
296
                '.',
297
                array(
298
                    strtolower($shortName),
299
                    strtolower($shortBundle),
300
                    'repository',
301
                    strtolower($parameters['document'])
302
                )
303
            );
304
305
            // normal repo service
306
            $services = $this->addParam(
307
                $services,
308
                $repoName . '.class',
309
                $parameters['base'] . 'Repository\\' . $parameters['document']
310
            );
311
312
            $this->addService(
313
                $services,
314
                $repoName,
315
                null,
316
                null,
317
                array(),
318
                null,
319
                array(
320
                    array(
321
                        'type' => 'string',
322
                        'value' => $parameters['bundle'] . ':' . $document
323
                    )
324
                ),
325
                'doctrine_mongodb.odm.default_document_manager',
326
                'getRepository'
327
            );
328
329
            // embedded repo service
330
            $services = $this->addParam(
331
                $services,
332
                $repoName . 'embedded.class',
333
                $parameters['base'] . 'Repository\\' . $parameters['document'] . 'Embedded'
334
            );
335
336
            $this->addService(
337
                $services,
338
                $repoName . 'embedded',
339
                null,
340
                null,
341
                array(),
342
                null,
343
                array(
344
                    array(
345
                        'type' => 'string',
346
                        'value' => $parameters['bundle'] . ':' . $document . 'Embedded'
347
                    )
348
                ),
349
                'doctrine_mongodb.odm.default_document_manager',
350
                'getRepository'
351
            );
352
353
            $this->renderFile(
354
                'document/DocumentRepository.php.twig',
355
                $dir . '/Repository/' . $document . 'Repository.php',
356
                $parameters
357
            );
358
            $this->renderFile(
359
                'document/DocumentRepository.php.twig',
360
                $dir . '/Repository/' . $document . 'EmbeddedRepository.php',
361
                array_merge(
362
                    $parameters,
363
                    [
364
                        'document' => $document.'Embedded',
365
                    ]
366
                )
367
            );
368
        }
369
370 6
        $this->persistServicesXML($dir);
371 6
    }
372
373
    /**
374
     * Generates the parameters section of the services.xml file.
375
     *
376
     * @param string $dir base bundle dir
377
     *
378
     * @return void
379
     */
380 2
    protected function generateParameters($dir)
381
    {
382 2
        if ($this->xmlParameters->count() > 0) {
383 2
            $services = $this->loadServices($dir);
384
385 2
            foreach ($this->xmlParameters as $parameter) {
386 2
                switch ($parameter['type']) {
387 2
                    case 'collection':
388 2
                        $this->addCollectionParam($services, $parameter['key'], $parameter['content']);
389 2
                        break;
390 2
                    case 'string':
391 1
                    default:
392 2
                        $this->addParam($services, $parameter['key'], $parameter['content']);
393 1
                }
394 1
            }
395 1
        }
396
397 2
        $this->persistServicesXML($dir);
398 2
    }
399
400
    /**
401
     * Registers information to be generated to a parameter tag.
402
     *
403
     * @param mixed  $value Content of the tag
404
     * @param string $key   Content of the key attribute
405
     * @param string $type  Type of the tag
406
     *
407
     * @return void
408
     */
409 2
    protected function addXmlParameter($value, $key, $type = 'string')
410
    {
411
        $element = array(
412 2
            'content' => $value,
413 2
            'key' => $key,
414 2
            'type' => strtolower($type),
415 1
        );
416
417 2
        if (!isset($this->xmlParameters)) {
418
            $this->xmlParameters = new ArrayCollection();
419
        }
420
421 2
        if (!$this->xmlParameters->contains($element)) {
422 2
            $this->xmlParameters->add($element);
423 1
        }
424 2
    }
425
426
    /**
427
     * load services.xml
428
     *
429
     * @param string $dir base dir
430
     *
431
     * @return \DOMDocument
432
     */
433 4
    protected function loadServices($dir)
434
    {
435 4
        if (empty($this->serviceDOM)) {
436 4
            $this->serviceDOM = new \DOMDocument;
437 4
            $this->serviceDOM->formatOutput = true;
438 4
            $this->serviceDOM->preserveWhiteSpace = false;
439 4
            $this->serviceDOM->load($dir . '/Resources/config/services.xml');
440 2
        }
441
442 4
        return $this->serviceDOM;
443
    }
444
445
    /**
446
     * add param to services.xml
447
     *
448
     * @param \DOMDocument $dom   services.xml document
449
     * @param string       $key   parameter key
450
     * @param string       $value parameter value
451
     *
452
     * @return \DOMDocument
453
     */
454 6
    protected function addParam(\DOMDocument $dom, $key, $value)
455
    {
456 6
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
457
458 6
        if (!$this->parameterNodeExists($dom, $key)) {
459 6
            $attrNode = $dom->createElement('parameter', $value);
460
461 6
            $this->addAttributeToNode('key', $key, $dom, $attrNode);
462
463 6
            $paramNode->appendChild($attrNode);
464 3
        }
465
466 6
        return $dom;
467
    }
468
469
    /**
470
     * Adds a new parameter tag to parameters section reflecting the defined roles.
471
     *
472
     * @param \DOMDocument $dom    services.xml document
473
     * @param string       $key    parameter key
474
     * @param array        $values parameter value
475
     *
476
     * @return void
477
     *
478
     * @link http://symfony.com/doc/current/book/service_container.html#array-parameters
479
     */
480 4
    protected function addCollectionParam(\DomDocument $dom, $key, array $values)
481
    {
482 4
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
483
484 4
        if (!$this->parameterNodeExists($dom, $key)) {
485 4
            if (!empty($values)) {
486 4
                $rolesNode = $dom->createElement('parameter');
487 4
                $this->addAttributeToNode('key', $key, $dom, $rolesNode);
488 4
                $this->addAttributeToNode('type', 'collection', $dom, $rolesNode);
489
490 4
                foreach ($values as $item) {
491 4
                    $roleNode = $dom->createElement('parameter', $item);
492 4
                    $rolesNode->appendChild($roleNode);
493 2
                }
494
495 4
                $paramNode->appendChild($rolesNode);
496 2
            }
497 2
        }
498
499 4
    }
500
501
    /**
502
     * Determines, if the provided key attribute was already claimed by a parameter node.
503
     *
504
     * @param \DomDocument $dom Current document
505
     * @param string       $key Key to be found in document
506
     *
507
     * @return bool
508
     */
509 8
    private function parameterNodeExists(\DomDocument $dom, $key)
0 ignored issues
show
Coding Style introduced by
function parameterNodeExists() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
510
    {
511 8
        $xpath = new \DomXpath($dom);
512 8
        $nodes = $xpath->query('//parameters/parameter[@key="' . $key . '"]');
513
514 8
        return $nodes->length > 0;
515
    }
516
517
    /**
518
     * add node if missing
519
     *
520
     * @param \DOMDocument $dom          document
521
     * @param string       $element      name for new node element
522
     * @param string       $insertBefore xPath query of the new node shall be added before
523
     * @param string       $container    name of container tag
524
     *
525
     * @return \DOMNode new element node
526
     */
527 8
    private function addNodeIfMissing(&$dom, $element, $insertBefore = '', $container = 'container')
528
    {
529 8
        $container = $dom->getElementsByTagName($container)
530 8
            ->item(0);
531 8
        $nodes = $dom->getElementsByTagName($element);
532 8
        if ($nodes->length < 1) {
533 8
            $newNode = $dom->createElement($element);
534
535 8
            if (!empty($insertBefore)) {
536 8
                $xpath = new \DomXpath($dom);
537 8
                $found = $xpath->query($insertBefore);
538
539 8
                if ($found->length > 0) {
540
                    $container->insertBefore($newNode, $found->item(0));
541
                } else {
542 8
                    $container->appendChild($newNode);
543
                }
544 4
            } else {
545 4
                $container->appendChild($newNode);
546
            }
547 4
        } else {
548 4
            $newNode = $nodes->item(0);
549
        }
550
551 8
        return $newNode;
552
    }
553
554
    /**
555
     * add attribute to node if needed
556
     *
557
     * @param string       $name  attribute name
558
     * @param string       $value attribute value
559
     * @param \DOMDocument $dom   document
560
     * @param \DOMElement  $node  parent node
561
     *
562
     * @return void
563
     */
564 8
    private function addAttributeToNode($name, $value, $dom, $node)
565
    {
566 8
        if ($value) {
567 8
            $attr = $dom->createAttribute($name);
568 8
            $attr->value = $value;
569 8
            $node->appendChild($attr);
570 4
        }
571 8
    }
572
573
    /**
574
     * add service to services.xml
575
     *
576
     * @param \DOMDocument $dom            services.xml dom
577
     * @param string       $id             id of new service
578
     * @param string       $parent         parent for service
0 ignored issues
show
Documentation introduced by
Should the type for parameter $parent 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...
579
     * @param string       $scope          scope of service
0 ignored issues
show
Documentation introduced by
Should the type for parameter $scope 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...
580
     * @param array        $calls          methodCalls to add
581
     * @param string       $tag            tag name or empty if no tag needed
0 ignored issues
show
Documentation introduced by
Should the type for parameter $tag 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...
582
     * @param array        $arguments      service arguments
583
     * @param string       $factoryService factory service id
0 ignored issues
show
Documentation introduced by
Should the type for parameter $factoryService 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...
584
     * @param string       $factoryMethod  factory method name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $factoryMethod 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...
585
     *
586
     * @return \DOMDocument
587
     */
588
    protected function addService(
589
        $dom,
590
        $id,
591
        $parent = null,
592
        $scope = null,
593
        array $calls = array(),
594
        $tag = null,
595
        array $arguments = array(),
596
        $factoryService = null,
597
        $factoryMethod = null
598
    ) {
599
        $servicesNode = $this->addNodeIfMissing($dom, 'services');
600
601
        $xpath = new \DomXpath($dom);
602
603
        // add controller to services
604
        $nodes = $xpath->query('//services/service[@id="' . $id . '"]');
605
        if ($nodes->length < 1) {
606
            $attrNode = $dom->createElement('service');
607
608
            $this->addAttributeToNode('id', $id, $dom, $attrNode);
609
            $this->addAttributeToNode('class', '%' . $id . '.class%', $dom, $attrNode);
610
            $this->addAttributeToNode('parent', $parent, $dom, $attrNode);
611
            $this->addAttributeToNode('scope', $scope, $dom, $attrNode);
612
            if ($factoryService && $factoryMethod) {
613
                $factoryNode = $dom->createElement('factory');
614
                $this->addAttributeToNode('service', $factoryService, $dom, $factoryNode);
615
                $this->addAttributeToNode('method', $factoryMethod, $dom, $factoryNode);
616
                $attrNode->appendChild($factoryNode);
617
            }
618
            $this->addCallsToService($calls, $dom, $attrNode);
619
620
            if ($tag) {
621
                $tagNode = $dom->createElement('tag');
622
623
                $this->addAttributeToNode('name', $tag, $dom, $tagNode);
624
625
                // get stuff from json definition
626
                if ($this->json instanceof JsonDefinition) {
627
                    // id is also name of collection in mongodb
628
                    $this->addAttributeToNode('collection', $this->json->getId(), $dom, $tagNode);
629
630
                    // is this read only?
631
                    if ($this->json->isReadOnlyService()) {
632
                        $this->addAttributeToNode('read-only', 'true', $dom, $tagNode);
633
                    }
634
635
                    // router base defined?
636
                    $routerBase = $this->json->getRouterBase();
637
                    if ($routerBase !== false) {
638
                        $this->addAttributeToNode('router-base', $routerBase, $dom, $tagNode);
639
                    }
640
                }
641
642
                $attrNode->appendChild($tagNode);
643
            }
644
645
            $this->addArgumentsToService($arguments, $dom, $attrNode);
646
647
            $servicesNode->appendChild($attrNode);
648
        }
649
650
        return $dom;
651
    }
652
653
    /**
654
     * add calls to service
655
     *
656
     * @param array        $calls info on calls to create
657
     * @param \DOMDocument $dom   current domdocument
658
     * @param \DOMElement  $node  node to add call to
659
     *
660
     * @return void
661
     */
662
    private function addCallsToService($calls, $dom, $node)
663
    {
664
        foreach ($calls as $call) {
665
            $this->addCallToService($call, $dom, $node);
666
        }
667
    }
668
669
    /**
670
     * add call to service
671
     *
672
     * @param array        $call info on call node to create
673
     * @param \DOMDocument $dom  current domdocument
674
     * @param \DOMElement  $node node to add call to
675
     *
676
     * @return void
677
     */
678
    private function addCallToService($call, $dom, $node)
679
    {
680
        $callNode = $dom->createElement('call');
681
682
        $attr = $dom->createAttribute('method');
683
        $attr->value = $call['method'];
684
        $callNode->appendChild($attr);
685
686
        $argNode = $dom->createElement('argument');
687
688
        $attr = $dom->createAttribute('type');
689
        $attr->value = 'service';
690
        $argNode->appendChild($attr);
691
692
        $attr = $dom->createAttribute('id');
693
        $attr->value = $call['service'];
694
        $argNode->appendChild($attr);
695
696
        $callNode->appendChild($argNode);
697
698
        $node->appendChild($callNode);
699
    }
700
701
    /**
702
     * add arguments to servie
703
     *
704
     * @param array        $arguments arguments to create
705
     * @param \DOMDocument $dom       dom document to add to
706
     * @param \DOMElement  $node      node to use as parent
707
     *
708
     * @return void
709
     */
710
    private function addArgumentsToService($arguments, $dom, $node)
711
    {
712
        foreach ($arguments as $argument) {
713
            $this->addArgumentToService($argument, $dom, $node);
714
        }
715
    }
716
717
    /**
718
     * add argument to service
719
     *
720
     * @param array        $argument info on argument to create
721
     * @param \DOMDocument $dom      dom document to add to
722
     * @param \DOMElement  $node     node to use as parent
723
     *
724
     * @return void
725
     */
726
    private function addArgumentToService($argument, $dom, $node)
727
    {
728
        $isService = $argument['type'] == 'service';
729
730
        if ($isService) {
731
            $argNode = $dom->createElement('argument');
732
733
            $idArg = $dom->createAttribute('id');
734
            $idArg->value = $argument['id'];
735
            $argNode->appendChild($idArg);
736
        } else {
737
            $argNode = $dom->createElement('argument', $argument['value']);
738
        }
739
740
        $argType = $dom->createAttribute('type');
741
        $argType->value = $argument['type'];
742
        $argNode->appendChild($argType);
743
744
        $node->appendChild($argNode);
745
    }
746
747
    /**
748
     * generate serializer part of a resource
749
     *
750
     * @param array  $parameters twig parameters
751
     * @param string $dir        base bundle dir
752
     * @param string $document   document name
753
     *
754
     * @return void
755
     */
756
    protected function generateSerializer(array $parameters, $dir, $document)
757
    {
758
        // @TODO in Embedded and document just render the differences..
759
        $this->renderFile(
760
            'serializer/Document.xml.twig',
761
            $dir . '/Resources/config/serializer/Document.' . $document . 'Embedded.xml',
762
            array_merge(
763
                $parameters,
764
                [
765
                    'document' => $document.'Embedded',
766
                    'noIdField' => true,
767
                    'realIdField' => true
768
                ]
769
            )
770
        );
771
        foreach ($parameters['fields'] as $key => $field) {
772
            if (substr($field['serializerType'], 0, 14) == 'array<Graviton' &&
773
                strpos($field['serializerType'], '\\Entity') === false
774
            ) {
775
                $parameters['fields'][$key]['serializerType'] = substr($field['serializerType'], 0, -1).'Embedded>';
776
            } elseif (substr($field['serializerType'], 0, 8) == 'Graviton' &&
777
                strpos($field['serializerType'], '\\Entity') === false
778
            ) {
779
                $parameters['fields'][$key]['serializerType'] = $field['serializerType'].'Embedded';
780
            }
781
        }
782
        $this->renderFile(
783
            'serializer/Document.xml.twig',
784
            $dir . '/Resources/config/serializer/Document.' . $document . '.xml',
785
            array_merge(
786
                $parameters,
787
                [
788
                    'realIdField' => false
789
                ]
790
            )
791
        );
792
        $this->renderFile(
793
            'serializer/Document.xml.twig',
794
            $dir . '/Resources/config/serializer/Document.' . $document . 'Base.xml',
795
            array_merge(
796
                $parameters,
797
                [
798
                    'document' => $document.'Base',
799
                    'realIdField' => false
800
                ]
801
            )
802
        );
803
804
    }
805
806
    /**
807
     * generate model part of a resource
808
     *
809
     * @param array  $parameters twig parameters
810
     * @param string $dir        base bundle dir
811
     * @param string $document   document name
812
     *
813
     * @return void
814
     */
815
    protected function generateModel(array $parameters, $dir, $document)
816
    {
817
        $this->renderFile(
818
            'model/Model.php.twig',
819
            $dir . '/Model/' . $document . '.php',
820
            $parameters
821
        );
822
        $this->renderFile(
823
            'model/schema.json.twig',
824
            $dir . '/Resources/config/schema/' . $document . '.json',
825
            $parameters
826
        );
827
828
        // embedded versions
829
        $this->renderFile(
830
            'model/Model.php.twig',
831
            $dir . '/Model/' . $document . 'Embedded.php',
832
            array_merge($parameters, ['document' => $document.'Embedded'])
833
        );
834
        $this->renderFile(
835
            'model/schema.json.twig',
836
            $dir . '/Resources/config/schema/' . $document . 'Embedded.json',
837
            array_merge($parameters, ['document' => $document.'Embedded'])
838
        );
839
840
        $this->renderFile(
841
            'validator/validation.xml.twig',
842
            $dir . '/Resources/config/validation.xml',
843
            $parameters
844
        );
845
846
        $services = $this->loadServices($dir);
847
848
        $bundleParts = explode('\\', $parameters['base']);
849
        $shortName = strtolower($bundleParts[0]);
850
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
851
        $paramName = implode('.', array($shortName, $shortBundle, 'model', strtolower($parameters['document'])));
852
        $repoName = implode('.', array($shortName, $shortBundle, 'repository', strtolower($parameters['document'])));
853
854
        $this->addXmlParameter($parameters['base'] . 'Model\\' . $parameters['document'], $paramName . '.class');
855
856
        // normal service
857
        $this->addService(
858
            $services,
859
            $paramName,
860
            'graviton.rest.model',
861
            null,
862
            array(
863
                [
864
                    'method' => 'setRepository',
865
                    'service' => $repoName
866
                ],
867
            ),
868
            null
869
        );
870
871
        // embedded service
872
        $this->addXmlParameter(
873
            $parameters['base'] . 'Model\\' . $parameters['document'] . 'Embedded',
874
            $paramName . 'embedded.class'
875
        );
876
877
        $this->addService(
878
            $services,
879
            $paramName . 'embedded',
880
            'graviton.rest.model',
881
            null,
882
            array(
883
                [
884
                    'method' => 'setRepository',
885
                    'service' => $repoName . 'embedded'
886
                ],
887
            ),
888
            null
889
        );
890
891
        $this->persistServicesXML($dir);
892
    }
893
894
    /**
895
     * generate RESTful controllers ans service configs
896
     *
897
     * @param array  $parameters twig parameters
898
     * @param string $dir        base bundle dir
899
     * @param string $document   document name
900
     *
901
     * @return void
902
     */
903
    protected function generateController(array $parameters, $dir, $document)
904
    {
905
        $this->renderFile(
906
            'controller/DocumentController.php.twig',
907
            $dir . '/Controller/' . $document . 'Controller.php',
908
            $parameters
909
        );
910
911
        $services = $this->loadServices($dir);
912
913
        $bundleParts = explode('\\', $parameters['base']);
914
        $shortName = strtolower($bundleParts[0]);
915
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
916
        $paramName = implode('.', array($shortName, $shortBundle, 'controller', strtolower($parameters['document'])));
917
918
        $this->addXmlParameter(
919
            $parameters['base'] . 'Controller\\' . $parameters['document'] . 'Controller',
920
            $paramName . '.class'
921
        );
922
923
        $this->addService(
924
            $services,
925
            $paramName,
926
            $parameters['parent'],
927
            'request',
928
            array(
929
                array(
930
                    'method' => 'setModel',
931
                    'service' => implode(
932
                        '.',
933
                        array($shortName, $shortBundle, 'model', strtolower($parameters['document']))
934
                    )
935
                )
936
            ),
937
            'graviton.rest'
938
        );
939
940
        $this->persistServicesXML($dir);
941
    }
942
943
    /**
944
     * generates fixtures
945
     *
946
     * @param array  $parameters twig parameters
947
     * @param string $dir        base bundle dir
948
     * @param string $document   document name
949
     *
950
     * @return void
951
     */
952
    protected function generateFixtures(array $parameters, $dir, $document)
953
    {
954
        $parameters['fixtures_json'] = addcslashes(json_encode($this->json->getFixtures()), "'");
955
        $parameters['fixtureOrder'] = $this->json->getFixtureOrder();
956
957
        $this->renderFile(
958
            'fixtures/LoadFixtures.php.twig',
959
            $dir . '/DataFixtures/MongoDB/Load' . $document . 'Data.php',
960
            $parameters
961
        );
962
    }
963
}
964