Completed
Push — feature/EVO-5985-real-upload-c... ( f8846f...273dbd )
by
unknown
11:15
created

ResourceGenerator::addArgumentsToService()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 3
crap 6
1
<?php
2
/**
3
 * generator code for resources
4
 */
5
6
namespace Graviton\GeneratorBundle\Generator;
7
8
use Sensio\Bundle\GeneratorBundle\Model\EntityGeneratorResult;
9
use Doctrine\Common\Collections\ArrayCollection;
10
use Graviton\GeneratorBundle\Definition\JsonDefinition;
11
use Graviton\GeneratorBundle\Generator\ResourceGenerator\FieldMapper;
12
use Graviton\GeneratorBundle\Generator\ResourceGenerator\ParameterBuilder;
13
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
14
use Symfony\Component\Filesystem\Filesystem;
15
use Symfony\Component\HttpKernel\HttpKernelInterface;
16
use Doctrine\Bundle\DoctrineBundle\Registry as DoctrineRegistry;
17
18
/**
19
 * bundle containing various code generators
20
 *
21
 * This code is more or less loosley based on SensioBundleGenerator. It could
22
 * use some refactoring to duplicate less for that, but this is how i finally
23
 * got a working version.
24
 *
25
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
26
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
27
 * @link     http://swisscom.ch
28
 *
29
 * @todo     split all the xml handling on services.conf into a Manipulator
30
 */
31
class ResourceGenerator extends AbstractGenerator
32
{
33
    /**
34
     * @private Filesystem
35
     */
36
    private $filesystem;
37
38
    /**
39
     * @private DoctrineRegistry
40
     */
41
    private $doctrine;
42
43
    /**
44
     * @private HttpKernelInterface
45
     */
46
    private $kernel;
47
48
    /**
49
     * our json file definition
50
     *
51
     * @var JsonDefinition|null
52
     */
53
    private $json = null;
54
55
    /**
56
     * @var ArrayCollection
57
     */
58
    protected $xmlParameters;
59
60
    /**
61
     * @var \DomDocument
62
     */
63
    private $serviceDOM;
64
65
    /**
66
     * @var FieldMapper
67
     */
68
    private $mapper;
69
70
    /**
71
     * @var boolean
72
     */
73
    private $generateController = false;
74
75
    /**
76
     * @var ParameterBuilder
77
     */
78
    private $parameterBuilder;
79
80
    /**
81
     * Instantiates generator object
82
     *
83
     * @param Filesystem          $filesystem       fs abstraction layer
84
     * @param DoctrineRegistry    $doctrine         odm registry
85
     * @param HttpKernelInterface $kernel           app kernel
86
     * @param FieldMapper         $mapper           field type mapper
87
     * @param ParameterBuilder    $parameterBuilder param builder
88
     */
89 2
    public function __construct(
90
        Filesystem $filesystem,
91
        DoctrineRegistry $doctrine,
92
        HttpKernelInterface $kernel,
93
        FieldMapper $mapper,
94
        ParameterBuilder $parameterBuilder
95
    ) {
96 2
        $this->filesystem = $filesystem;
97 2
        $this->doctrine = $doctrine;
98 2
        $this->kernel = $kernel;
99 2
        $this->mapper = $mapper;
100 2
        $this->parameterBuilder = $parameterBuilder;
101 2
        $this->xmlParameters = new ArrayCollection();
102 2
    }
103
104
    /**
105
     * @param JsonDefinition $json optional JsonDefinition object
106
     *
107
     * @return void
108
     */
109
    public function setJson(JsonDefinition $json)
110
    {
111
        $this->json = $json;
112
    }
113
114
    /**
115
     * @param boolean $generateController should the controller be generated or not
116
     *
117
     * @return void
118
     */
119
    public function setGenerateController($generateController)
120
    {
121
        $this->generateController = $generateController;
122
    }
123
124
    /**
125
     * generate the resource with all its bits and parts
126
     *
127
     * @param BundleInterface $bundle   bundle
128
     * @param string          $document document name
129
     * @param string          $format   format of config files (please use xml)
130
     * @param array           $fields   fields to add
131
     *
132
     * @return EntityGeneratorResult
133
     */
134
    public function generate(
135
        BundleInterface $bundle,
136
        $document,
137
        $format,
138
        array $fields
139
    ) {
140
        $dir = $bundle->getPath();
141
        $basename = $this->getBundleBaseName($document);
142
        $bundleNamespace = substr(get_class($bundle), 0, 0 - strlen($bundle->getName()));
143
144
        if (!is_null($this->json)) {
145
            $this->json->setNamespace($bundleNamespace);
146
        }
147
148
        // add more info to the fields array
149
        $mapper = $this->mapper;
150
        $fields = array_map(
151
            function ($field) use ($mapper) {
152
                return $mapper->map($field, $this->json);
153
            },
154
            $fields
155
        );
156
        $parameters = $this->parameterBuilder
157
            ->setParameter('document', $document)
158
            ->setParameter('base', $bundleNamespace)
159
            ->setParameter('bundle', $bundle->getName())
160
            ->setParameter('format', $format)
161
            ->setParameter('json', $this->json)
162
            ->setParameter('fields', $fields)
163
            ->setParameter('basename', $basename)
164
            ->setParameter('isrecordOriginFlagSet', $this->json->isRecordOriginFlagSet())
165
            ->setParameter('recordOriginModifiable', $this->json->isRecordOriginModifiable())
166
            ->setParameter('collection', $this->json->getServiceCollection())
167
            ->setParameter('indexes', $this->json->getIndexes())
168
            ->getParameters();
169
170
        $this->generateDocument($parameters, $dir, $document);
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
        return new EntityGeneratorResult(
185
            $dir . '/Document/' . $document . '.php',
186
            $dir . '/Repository/' . $document . 'Repository.php',
187
            $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml'
188
        );
189
    }
190
191
    /**
192
     * Writes the current services definition to a file.
193
     *
194
     * @param string $dir base bundle dir
195
     *
196
     * @return void
197
     */
198 8
    protected function persistServicesXML($dir)
199
    {
200 8
        $services = $this->loadServices($dir);
201
202 8
        file_put_contents($dir . '/Resources/config/services.xml', $services->saveXML());
203 8
    }
204
205
    /**
206
     * generate document part of a resource
207
     *
208
     * @param array  $parameters twig parameters
209
     * @param string $dir        base bundle dir
210
     * @param string $document   document name
211
     *
212
     * @return void
213
     */
214 6
    protected function generateDocument($parameters, $dir, $document)
215
    {
216
        // doctrine mapping normal class
217 6
        $this->renderFile(
218 6
            'document/Document.mongodb.xml.twig',
219 6
            $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml',
220
            $parameters
221 3
        );
222
223
        // doctrine mapping embedded
224 6
        $this->renderFile(
225 6
            'document/Document.mongodb.xml.twig',
226 6
            $dir . '/Resources/config/doctrine/' . $document . 'Embedded.mongodb.xml',
227 3
            array_merge(
228 3
                $parameters,
229
                [
230 6
                    'document' => $document.'Embedded',
231 3
                    'docType' => 'embedded-document'
232 3
                ]
233 3
            )
234 3
        );
235
236 6
        $this->renderFile(
237 6
            'document/Document.php.twig',
238 6
            $dir . '/Document/' . $document . '.php',
239
            $parameters
240 3
        );
241 6
        $this->renderFile(
242 6
            'document/DocumentEmbedded.php.twig',
243 6
            $dir . '/Document/' . $document . 'Embedded.php',
244
            $parameters
245 3
        );
246 6
        $this->renderFile(
247 6
            'document/DocumentBase.php.twig',
248 6
            $dir . '/Document/' . $document . 'Base.php',
249
            $parameters
250 3
        );
251
252 6
        $this->generateServices($parameters, $dir, $document);
253 6
    }
254
255
    /**
256
     * update xml services
257
     *
258
     * @param array  $parameters twig parameters
259
     * @param string $dir        base bundle dir
260
     * @param string $document   document name
261
     *
262
     * @return void
263
     */
264 6
    protected function generateServices($parameters, $dir, $document)
265
    {
266 6
        $services = $this->loadServices($dir);
267
268 6
        $bundleParts = explode('\\', $parameters['base']);
269 6
        $shortName = $bundleParts[0];
270 6
        $shortBundle = $this->getBundleBaseName($bundleParts[1]);
271
272 6
        $docName = implode(
273 6
            '.',
274
            array(
275 6
                strtolower($shortName),
276 6
                strtolower($shortBundle),
277 6
                'document',
278 6
                strtolower($parameters['document'])
279 3
            )
280 3
        );
281
282 6
        $this->addXMLParameter(
283 6
            $parameters['base'] . 'Document\\' . $parameters['document'],
284 3
            $docName . '.class'
285 3
        );
286
287 6
        $this->addXMLParameter(
288 6
            $parameters['json']->getRoles(),
289 6
            $docName . '.roles',
290 3
            'collection'
291 3
        );
292
293 6
        $services = $this->addService(
294 3
            $services,
295
            $docName
296 3
        );
297
298 6
        $repoName = implode(
299 6
            '.',
300
            array(
301 6
                strtolower($shortName),
302 6
                strtolower($shortBundle),
303 6
                'repository',
304 6
                strtolower($parameters['document'])
305 3
            )
306 3
        );
307
308
        // normal repo service
309 6
        $services = $this->addParam(
310 3
            $services,
311 6
            $repoName . '.class',
312 6
            $parameters['base'] . 'Repository\\' . $parameters['document']
313 3
        );
314
315 6
        $this->addService(
316 3
            $services,
317 3
            $repoName,
318 6
            null,
319 6
            null,
320 6
            array(),
321 6
            null,
322
            array(
323
                array(
324 6
                    'type' => 'string',
325 6
                    'value' => $parameters['bundle'] . ':' . $document
326 3
                )
327 3
            ),
328 6
            'doctrine_mongodb.odm.default_document_manager',
329 3
            'getRepository'
330 3
        );
331
332
        // embedded repo service
333 6
        $services = $this->addParam(
334 3
            $services,
335 6
            $repoName . 'embedded.class',
336 6
            $parameters['base'] . 'Repository\\' . $parameters['document'] . 'Embedded'
337 3
        );
338
339 6
        $this->addService(
340 3
            $services,
341 6
            $repoName . 'embedded',
342 6
            null,
343 6
            null,
344 6
            array(),
345 6
            null,
346
            array(
347
                array(
348 6
                    'type' => 'string',
349 6
                    'value' => $parameters['bundle'] . ':' . $document . 'Embedded'
350 3
                )
351 3
            ),
352 6
            'doctrine_mongodb.odm.default_document_manager',
353 3
            'getRepository'
354 3
        );
355
356 6
        $this->renderFile(
357 6
            'document/DocumentRepository.php.twig',
358 6
            $dir . '/Repository/' . $document . 'Repository.php',
359
            $parameters
360 3
        );
361 6
        $this->renderFile(
362 6
            'document/DocumentRepository.php.twig',
363 6
            $dir . '/Repository/' . $document . 'EmbeddedRepository.php',
364 3
            array_merge(
365 3
                $parameters,
366
                [
367 6
                    'document' => $document.'Embedded',
368
                ]
369 3
            )
370 3
        );
371
372 6
        $this->persistServicesXML($dir);
373 6
    }
374
375
    /**
376
     * Generates the parameters section of the services.xml file.
377
     *
378
     * @param string $dir base bundle dir
379
     *
380
     * @return void
381
     */
382 2
    protected function generateParameters($dir)
383
    {
384 2
        if ($this->xmlParameters->count() > 0) {
385 2
            $services = $this->loadServices($dir);
386
387 2
            foreach ($this->xmlParameters as $parameter) {
388 2
                switch ($parameter['type']) {
389 2
                    case 'collection':
390 2
                        $this->addCollectionParam($services, $parameter['key'], $parameter['content']);
391 2
                        break;
392 2
                    case 'string':
393 1
                    default:
394 2
                        $this->addParam($services, $parameter['key'], $parameter['content']);
395 1
                }
396 1
            }
397 1
        }
398
399 2
        $this->persistServicesXML($dir);
400 2
    }
401
402
    /**
403
     * Registers information to be generated to a parameter tag.
404
     *
405
     * @param mixed  $value Content of the tag
406
     * @param string $key   Content of the key attribute
407
     * @param string $type  Type of the tag
408
     *
409
     * @return void
410
     */
411 2
    protected function addXmlParameter($value, $key, $type = 'string')
412
    {
413
        $element = array(
414 2
            'content' => $value,
415 2
            'key' => $key,
416 2
            'type' => strtolower($type),
417 1
        );
418
419 2
        if (!isset($this->xmlParameters)) {
420
            $this->xmlParameters = new ArrayCollection();
421
        }
422
423 2
        if (!$this->xmlParameters->contains($element)) {
424 2
            $this->xmlParameters->add($element);
425 1
        }
426 2
    }
427
428
    /**
429
     * load services.xml
430
     *
431
     * @param string $dir base dir
432
     *
433
     * @return \DOMDocument
434
     */
435 4
    protected function loadServices($dir)
436
    {
437 4
        if (empty($this->serviceDOM)) {
438 4
            $this->serviceDOM = new \DOMDocument;
439 4
            $this->serviceDOM->formatOutput = true;
440 4
            $this->serviceDOM->preserveWhiteSpace = false;
441 4
            $this->serviceDOM->load($dir . '/Resources/config/services.xml');
442 2
        }
443
444 4
        return $this->serviceDOM;
445
    }
446
447
    /**
448
     * add param to services.xml
449
     *
450
     * @param \DOMDocument $dom   services.xml document
451
     * @param string       $key   parameter key
452
     * @param string       $value parameter value
453
     *
454
     * @return \DOMDocument
455
     */
456 12
    protected function addParam(\DOMDocument $dom, $key, $value)
457
    {
458 12
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
459
460 12
        if (!$this->parameterNodeExists($dom, $key)) {
461 12
            $attrNode = $dom->createElement('parameter', $value);
462
463 12
            $this->addAttributeToNode('key', $key, $dom, $attrNode);
464
465 12
            $paramNode->appendChild($attrNode);
466 6
        }
467
468 12
        return $dom;
469
    }
470
471
    /**
472
     * Adds a new parameter tag to parameters section reflecting the defined roles.
473
     *
474
     * @param \DOMDocument $dom    services.xml document
475
     * @param string       $key    parameter key
476
     * @param array        $values parameter value
477
     *
478
     * @return void
479
     *
480
     * @link http://symfony.com/doc/current/book/service_container.html#array-parameters
481
     */
482 4
    protected function addCollectionParam(\DomDocument $dom, $key, array $values)
483
    {
484 4
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
485
486 4
        if (!$this->parameterNodeExists($dom, $key)) {
487 4
            if (!empty($values)) {
488 4
                $rolesNode = $dom->createElement('parameter');
489 4
                $this->addAttributeToNode('key', $key, $dom, $rolesNode);
490 4
                $this->addAttributeToNode('type', 'collection', $dom, $rolesNode);
491
492 4
                foreach ($values as $item) {
493 4
                    $roleNode = $dom->createElement('parameter', $item);
494 4
                    $rolesNode->appendChild($roleNode);
495 2
                }
496
497 4
                $paramNode->appendChild($rolesNode);
498 2
            }
499 2
        }
500
501 4
    }
502
503
    /**
504
     * Determines, if the provided key attribute was already claimed by a parameter node.
505
     *
506
     * @param \DomDocument $dom Current document
507
     * @param string       $key Key to be found in document
508
     *
509
     * @return bool
510
     */
511 14
    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...
512
    {
513 14
        $xpath = new \DomXpath($dom);
514 14
        $nodes = $xpath->query('//parameters/parameter[@key="' . $key . '"]');
515
516 14
        return $nodes->length > 0;
517
    }
518
519
    /**
520
     * add node if missing
521
     *
522
     * @param \DOMDocument $dom          document
523
     * @param string       $element      name for new node element
524
     * @param string       $insertBefore xPath query of the new node shall be added before
525
     * @param string       $container    name of container tag
526
     *
527
     * @return \DOMNode new element node
528
     */
529 14
    private function addNodeIfMissing(&$dom, $element, $insertBefore = '', $container = 'container')
530
    {
531 14
        $container = $dom->getElementsByTagName($container)
532 14
            ->item(0);
533 14
        $nodes = $dom->getElementsByTagName($element);
534 14
        if ($nodes->length < 1) {
535 14
            $newNode = $dom->createElement($element);
536
537 14
            if (!empty($insertBefore)) {
538 14
                $xpath = new \DomXpath($dom);
539 14
                $found = $xpath->query($insertBefore);
540
541 14
                if ($found->length > 0) {
542
                    $container->insertBefore($newNode, $found->item(0));
543
                } else {
544 14
                    $container->appendChild($newNode);
545
                }
546 7
            } else {
547 7
                $container->appendChild($newNode);
548
            }
549 7
        } else {
550 4
            $newNode = $nodes->item(0);
551
        }
552
553 14
        return $newNode;
554
    }
555
556
    /**
557
     * add attribute to node if needed
558
     *
559
     * @param string       $name  attribute name
560
     * @param string       $value attribute value
561
     * @param \DOMDocument $dom   document
562
     * @param \DOMElement  $node  parent node
563
     *
564
     * @return void
565
     */
566 14
    private function addAttributeToNode($name, $value, $dom, $node)
567
    {
568 14
        if ($value) {
569 14
            $attr = $dom->createAttribute($name);
570 14
            $attr->value = $value;
571 14
            $node->appendChild($attr);
572 7
        }
573 14
    }
574
575
    /**
576
     * add service to services.xml
577
     *
578
     * @param \DOMDocument $dom            services.xml dom
579
     * @param string       $id             id of new service
580
     * @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...
581
     * @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...
582
     * @param array        $calls          methodCalls to add
583
     * @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...
584
     * @param array        $arguments      service arguments
585
     * @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...
586
     * @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...
587
     *
588
     * @return \DOMDocument
589
     */
590
    protected function addService(
591
        $dom,
592
        $id,
593
        $parent = null,
594
        $scope = null,
595
        array $calls = array(),
596
        $tag = null,
597
        array $arguments = array(),
598
        $factoryService = null,
599
        $factoryMethod = null
600
    ) {
601
        $servicesNode = $this->addNodeIfMissing($dom, 'services');
602
603
        $xpath = new \DomXpath($dom);
604
605
        // add controller to services
606
        $nodes = $xpath->query('//services/service[@id="' . $id . '"]');
607
        if ($nodes->length < 1) {
608
            $attrNode = $dom->createElement('service');
609
610
            $this->addAttributeToNode('id', $id, $dom, $attrNode);
611
            $this->addAttributeToNode('class', '%' . $id . '.class%', $dom, $attrNode);
612
            $this->addAttributeToNode('parent', $parent, $dom, $attrNode);
613
            $this->addAttributeToNode('scope', $scope, $dom, $attrNode);
614
            if ($factoryService && $factoryMethod) {
615
                $factoryNode = $dom->createElement('factory');
616
                $this->addAttributeToNode('service', $factoryService, $dom, $factoryNode);
617
                $this->addAttributeToNode('method', $factoryMethod, $dom, $factoryNode);
618
                $attrNode->appendChild($factoryNode);
619
            }
620
            $this->addCallsToService($calls, $dom, $attrNode);
621
622
            if ($tag) {
623
                $tagNode = $dom->createElement('tag');
624
625
                $this->addAttributeToNode('name', $tag, $dom, $tagNode);
626
627
                // get stuff from json definition
628
                if ($this->json instanceof JsonDefinition) {
629
                    // id is also name of collection in mongodb
630
                    $this->addAttributeToNode('collection', $this->json->getId(), $dom, $tagNode);
631
632
                    // is this read only?
633
                    if ($this->json->isReadOnlyService()) {
634
                        $this->addAttributeToNode('read-only', 'true', $dom, $tagNode);
635
                    }
636
637
                    // router base defined?
638
                    $routerBase = $this->json->getRouterBase();
639
                    if ($routerBase !== false) {
640
                        $this->addAttributeToNode('router-base', $routerBase, $dom, $tagNode);
641
                    }
642
                }
643
644
                $attrNode->appendChild($tagNode);
645
            }
646
647
            $this->addArgumentsToService($arguments, $dom, $attrNode);
648
649
            $servicesNode->appendChild($attrNode);
650
        }
651
652
        return $dom;
653
    }
654
655
    /**
656
     * add calls to service
657
     *
658
     * @param array        $calls info on calls to create
659
     * @param \DOMDocument $dom   current domdocument
660
     * @param \DOMElement  $node  node to add call to
661
     *
662
     * @return void
663
     */
664
    private function addCallsToService($calls, $dom, $node)
665
    {
666
        foreach ($calls as $call) {
667
            $this->addCallToService($call, $dom, $node);
668
        }
669
    }
670
671
    /**
672
     * add call to service
673
     *
674
     * @param array        $call info on call node to create
675
     * @param \DOMDocument $dom  current domdocument
676
     * @param \DOMElement  $node node to add call to
677
     *
678
     * @return void
679
     */
680
    private function addCallToService($call, $dom, $node)
681
    {
682
        $callNode = $dom->createElement('call');
683
684
        $attr = $dom->createAttribute('method');
685
        $attr->value = $call['method'];
686
        $callNode->appendChild($attr);
687
688
        $argNode = $dom->createElement('argument');
689
690
        $attr = $dom->createAttribute('type');
691
        $attr->value = 'service';
692
        $argNode->appendChild($attr);
693
694
        $attr = $dom->createAttribute('id');
695
        $attr->value = $call['service'];
696
        $argNode->appendChild($attr);
697
698
        $callNode->appendChild($argNode);
699
700
        $node->appendChild($callNode);
701
    }
702
703
    /**
704
     * add arguments to servie
705
     *
706
     * @param array        $arguments arguments to create
707
     * @param \DOMDocument $dom       dom document to add to
708
     * @param \DOMElement  $node      node to use as parent
709
     *
710
     * @return void
711
     */
712
    private function addArgumentsToService($arguments, $dom, $node)
713
    {
714
        foreach ($arguments as $argument) {
715
            $this->addArgumentToService($argument, $dom, $node);
716
        }
717
    }
718
719
    /**
720
     * add argument to service
721
     *
722
     * @param array        $argument info on argument to create
723
     * @param \DOMDocument $dom      dom document to add to
724
     * @param \DOMElement  $node     node to use as parent
725
     *
726
     * @return void
727
     */
728
    private function addArgumentToService($argument, $dom, $node)
729
    {
730
        $isService = $argument['type'] == 'service';
731
732
        if ($isService) {
733
            $argNode = $dom->createElement('argument');
734
735
            $idArg = $dom->createAttribute('id');
736
            $idArg->value = $argument['id'];
737
            $argNode->appendChild($idArg);
738
        } else {
739
            $argNode = $dom->createElement('argument', $argument['value']);
740
        }
741
742
        $argType = $dom->createAttribute('type');
743
        $argType->value = $argument['type'];
744
        $argNode->appendChild($argType);
745
746
        $node->appendChild($argNode);
747
    }
748
749
    /**
750
     * generate serializer part of a resource
751
     *
752
     * @param array  $parameters twig parameters
753
     * @param string $dir        base bundle dir
754
     * @param string $document   document name
755
     *
756
     * @return void
757
     */
758
    protected function generateSerializer(array $parameters, $dir, $document)
759
    {
760
        // @TODO in Embedded and document just render the differences..
761
        $this->renderFile(
762
            'serializer/Document.xml.twig',
763
            $dir . '/Resources/config/serializer/Document.' . $document . 'Embedded.xml',
764
            array_merge(
765
                $parameters,
766
                [
767
                    'document' => $document.'Embedded',
768
                    'noIdField' => true,
769
                    'realIdField' => true
770
                ]
771
            )
772
        );
773
        foreach ($parameters['fields'] as $key => $field) {
774
            if (substr($field['serializerType'], 0, 14) == 'array<Graviton' &&
775
                strpos($field['serializerType'], '\\Entity') === false
776
            ) {
777
                $parameters['fields'][$key]['serializerType'] = substr($field['serializerType'], 0, -1).'Embedded>';
778
            } elseif (substr($field['serializerType'], 0, 8) == 'Graviton' &&
779
                strpos($field['serializerType'], '\\Entity') === false
780
            ) {
781
                $parameters['fields'][$key]['serializerType'] = $field['serializerType'].'Embedded';
782
            }
783
        }
784
        $this->renderFile(
785
            'serializer/Document.xml.twig',
786
            $dir . '/Resources/config/serializer/Document.' . $document . '.xml',
787
            array_merge(
788
                $parameters,
789
                [
790
                    'realIdField' => false
791
                ]
792
            )
793
        );
794
        $this->renderFile(
795
            'serializer/Document.xml.twig',
796
            $dir . '/Resources/config/serializer/Document.' . $document . 'Base.xml',
797
            array_merge(
798
                $parameters,
799
                [
800
                    'document' => $document.'Base',
801
                    'realIdField' => false
802
                ]
803
            )
804
        );
805
806
    }
807
808
    /**
809
     * generate model part of a resource
810
     *
811
     * @param array  $parameters twig parameters
812
     * @param string $dir        base bundle dir
813
     * @param string $document   document name
814
     *
815
     * @return void
816
     */
817
    protected function generateModel(array $parameters, $dir, $document)
818
    {
819
        $this->renderFile(
820
            'model/Model.php.twig',
821
            $dir . '/Model/' . $document . '.php',
822
            $parameters
823
        );
824
        $this->renderFile(
825
            'model/schema.json.twig',
826
            $dir . '/Resources/config/schema/' . $document . '.json',
827
            $parameters
828
        );
829
830
        // embedded versions
831
        $this->renderFile(
832
            'model/Model.php.twig',
833
            $dir . '/Model/' . $document . 'Embedded.php',
834
            array_merge($parameters, ['document' => $document.'Embedded'])
835
        );
836
        $this->renderFile(
837
            'model/schema.json.twig',
838
            $dir . '/Resources/config/schema/' . $document . 'Embedded.json',
839
            array_merge($parameters, ['document' => $document.'Embedded'])
840
        );
841
842
        $this->renderFile(
843
            'validator/validation.xml.twig',
844
            $dir . '/Resources/config/validation.xml',
845
            $parameters
846
        );
847
848
        $services = $this->loadServices($dir);
849
850
        $bundleParts = explode('\\', $parameters['base']);
851
        $shortName = strtolower($bundleParts[0]);
852
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
853
        $paramName = implode('.', array($shortName, $shortBundle, 'model', strtolower($parameters['document'])));
854
        $repoName = implode('.', array($shortName, $shortBundle, 'repository', strtolower($parameters['document'])));
855
856
        $this->addXmlParameter($parameters['base'] . 'Model\\' . $parameters['document'], $paramName . '.class');
857
858
        // normal service
859
        $this->addService(
860
            $services,
861
            $paramName,
862
            'graviton.rest.model',
863
            null,
864
            array(
865
                [
866
                    'method' => 'setRepository',
867
                    'service' => $repoName
868
                ],
869
            ),
870
            null
871
        );
872
873
        // embedded service
874
        $this->addXmlParameter(
875
            $parameters['base'] . 'Model\\' . $parameters['document'] . 'Embedded',
876
            $paramName . 'embedded.class'
877
        );
878
879
        $this->addService(
880
            $services,
881
            $paramName . 'embedded',
882
            'graviton.rest.model',
883
            null,
884
            array(
885
                [
886
                    'method' => 'setRepository',
887
                    'service' => $repoName . 'embedded'
888
                ],
889
            ),
890
            null
891
        );
892
893
        $this->persistServicesXML($dir);
894
    }
895
896
    /**
897
     * generate RESTful controllers ans service configs
898
     *
899
     * @param array  $parameters twig parameters
900
     * @param string $dir        base bundle dir
901
     * @param string $document   document name
902
     *
903
     * @return void
904
     */
905
    protected function generateController(array $parameters, $dir, $document)
906
    {
907
        $this->renderFile(
908
            'controller/DocumentController.php.twig',
909
            $dir . '/Controller/' . $document . 'Controller.php',
910
            $parameters
911
        );
912
913
        $services = $this->loadServices($dir);
914
915
        $bundleParts = explode('\\', $parameters['base']);
916
        $shortName = strtolower($bundleParts[0]);
917
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
918
        $paramName = implode('.', array($shortName, $shortBundle, 'controller', strtolower($parameters['document'])));
919
920
        $this->addXmlParameter(
921
            $parameters['base'] . 'Controller\\' . $parameters['document'] . 'Controller',
922
            $paramName . '.class'
923
        );
924
925
        $this->addService(
926
            $services,
927
            $paramName,
928
            $parameters['parent'],
929
            'request',
930
            array(
931
                array(
932
                    'method' => 'setModel',
933
                    'service' => implode(
934
                        '.',
935
                        array($shortName, $shortBundle, 'model', strtolower($parameters['document']))
936
                    )
937
                )
938
            ),
939
            'graviton.rest'
940
        );
941
942
        $this->persistServicesXML($dir);
943
    }
944
945
    /**
946
     * generates fixtures
947
     *
948
     * @param array  $parameters twig parameters
949
     * @param string $dir        base bundle dir
950
     * @param string $document   document name
951
     *
952
     * @return void
953
     */
954
    protected function generateFixtures(array $parameters, $dir, $document)
955
    {
956
        $parameters['fixtures_json'] = addcslashes(json_encode($this->json->getFixtures()), "'");
957
        $parameters['fixtureOrder'] = $this->json->getFixtureOrder();
958
959
        $this->renderFile(
960
            'fixtures/LoadFixtures.php.twig',
961
            $dir . '/DataFixtures/MongoDB/Load' . $document . 'Data.php',
962
            $parameters
963
        );
964
    }
965
}
966