Completed
Branch feature/moar-test-optimizing (8cffd1)
by Lucas
19:31 queued 13:44
created

ResourceGenerator::generateServices()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 112
Code Lines 75

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 3.2062
Metric Value
dl 0
loc 112
ccs 28
cts 85
cp 0.3294
rs 8.2857
cc 2
eloc 75
nc 2
nop 4
crap 3.2062

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
 * 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
    public function __construct(
89
        Filesystem $filesystem,
90
        DoctrineRegistry $doctrine,
91
        HttpKernelInterface $kernel,
92
        FieldMapper $mapper,
93
        ParameterBuilder $parameterBuilder
94
    ) {
95
        $this->filesystem = $filesystem;
96
        $this->doctrine = $doctrine;
97
        $this->kernel = $kernel;
98
        $this->mapper = $mapper;
99
        $this->parameterBuilder = $parameterBuilder;
100
        $this->xmlParameters = new ArrayCollection();
101
    }
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
            $this->addAttributeToNode('factory-service', $factoryService, $dom, $attrNode);
613
            $this->addAttributeToNode('factory-method', $factoryMethod, $dom, $attrNode);
614
            $this->addCallsToService($calls, $dom, $attrNode);
615
616
            if ($tag) {
617
                $tagNode = $dom->createElement('tag');
618
619
                $this->addAttributeToNode('name', $tag, $dom, $tagNode);
620
621
                // get stuff from json definition
622
                if ($this->json instanceof JsonDefinition) {
623
                    // id is also name of collection in mongodb
624
                    $this->addAttributeToNode('collection', $this->json->getId(), $dom, $tagNode);
625
626
                    // is this read only?
627
                    if ($this->json->isReadOnlyService()) {
628
                        $this->addAttributeToNode('read-only', 'true', $dom, $tagNode);
629
                    }
630
631
                    // router base defined?
632
                    $routerBase = $this->json->getRouterBase();
633
                    if ($routerBase !== false) {
634
                        $this->addAttributeToNode('router-base', $routerBase, $dom, $tagNode);
635
                    }
636
                }
637
638
                $attrNode->appendChild($tagNode);
639
            }
640
641
            $this->addArgumentsToService($arguments, $dom, $attrNode);
642
643
            $servicesNode->appendChild($attrNode);
644
        }
645
646
        return $dom;
647
    }
648
649
    /**
650
     * add calls to service
651
     *
652
     * @param array        $calls info on calls to create
653
     * @param \DOMDocument $dom   current domdocument
654
     * @param \DOMElement  $node  node to add call to
655
     *
656
     * @return void
657
     */
658
    private function addCallsToService($calls, $dom, $node)
659
    {
660
        foreach ($calls as $call) {
661
            $this->addCallToService($call, $dom, $node);
662
        }
663
    }
664
665
    /**
666
     * add call to service
667
     *
668
     * @param array        $call info on call node to create
669
     * @param \DOMDocument $dom  current domdocument
670
     * @param \DOMElement  $node node to add call to
671
     *
672
     * @return void
673
     */
674
    private function addCallToService($call, $dom, $node)
675
    {
676
        $callNode = $dom->createElement('call');
677
678
        $attr = $dom->createAttribute('method');
679
        $attr->value = $call['method'];
680
        $callNode->appendChild($attr);
681
682
        $argNode = $dom->createElement('argument');
683
684
        $attr = $dom->createAttribute('type');
685
        $attr->value = 'service';
686
        $argNode->appendChild($attr);
687
688
        $attr = $dom->createAttribute('id');
689
        $attr->value = $call['service'];
690
        $argNode->appendChild($attr);
691
692
        $callNode->appendChild($argNode);
693
694
        $node->appendChild($callNode);
695
    }
696
697
    /**
698
     * add arguments to servie
699
     *
700
     * @param array        $arguments arguments to create
701
     * @param \DOMDocument $dom       dom document to add to
702
     * @param \DOMElement  $node      node to use as parent
703
     *
704
     * @return void
705
     */
706
    private function addArgumentsToService($arguments, $dom, $node)
707
    {
708
        foreach ($arguments as $argument) {
709
            $this->addArgumentToService($argument, $dom, $node);
710
        }
711
    }
712
713
    /**
714
     * add argument to service
715
     *
716
     * @param array        $argument info on argument to create
717
     * @param \DOMDocument $dom      dom document to add to
718
     * @param \DOMElement  $node     node to use as parent
719
     *
720
     * @return void
721
     */
722
    private function addArgumentToService($argument, $dom, $node)
723
    {
724
        $isService = $argument['type'] == 'service';
725
726
        if ($isService) {
727
            $argNode = $dom->createElement('argument');
728
729
            $idArg = $dom->createAttribute('id');
730
            $idArg->value = $argument['id'];
731
            $argNode->appendChild($idArg);
732
        } else {
733
            $argNode = $dom->createElement('argument', $argument['value']);
734
        }
735
736
        $argType = $dom->createAttribute('type');
737
        $argType->value = $argument['type'];
738
        $argNode->appendChild($argType);
739
740
        $node->appendChild($argNode);
741
    }
742
743
    /**
744
     * generate serializer part of a resource
745
     *
746
     * @param array  $parameters twig parameters
747
     * @param string $dir        base bundle dir
748
     * @param string $document   document name
749
     *
750
     * @return void
751
     */
752
    protected function generateSerializer(array $parameters, $dir, $document)
753
    {
754
        // @TODO in Embedded and document just render the differences..
755
        $this->renderFile(
756
            'serializer/Document.xml.twig',
757
            $dir . '/Resources/config/serializer/Document.' . $document . 'Embedded.xml',
758
            array_merge(
759
                $parameters,
760
                [
761
                    'document' => $document.'Embedded',
762
                    'noIdField' => true,
763
                    'realIdField' => true
764
                ]
765
            )
766
        );
767
        foreach ($parameters['fields'] as $key => $field) {
768
            if (substr($field['serializerType'], 0, 14) == 'array<Graviton' &&
769
                strpos($field['serializerType'], '\\Entity') === false
770
            ) {
771
                $parameters['fields'][$key]['serializerType'] = substr($field['serializerType'], 0, -1).'Embedded>';
772
            } elseif (substr($field['serializerType'], 0, 8) == 'Graviton' &&
773
                strpos($field['serializerType'], '\\Entity') === false
774
            ) {
775
                $parameters['fields'][$key]['serializerType'] = $field['serializerType'].'Embedded';
776
            }
777
        }
778
        $this->renderFile(
779
            'serializer/Document.xml.twig',
780
            $dir . '/Resources/config/serializer/Document.' . $document . '.xml',
781
            array_merge(
782
                $parameters,
783
                [
784
                    'realIdField' => false
785
                ]
786
            )
787
        );
788
        $this->renderFile(
789
            'serializer/Document.xml.twig',
790
            $dir . '/Resources/config/serializer/Document.' . $document . 'Base.xml',
791
            array_merge(
792
                $parameters,
793
                [
794
                    'document' => $document.'Base',
795
                    'realIdField' => false
796
                ]
797
            )
798
        );
799
800
    }
801
802
    /**
803
     * generate model part of a resource
804
     *
805
     * @param array  $parameters twig parameters
806
     * @param string $dir        base bundle dir
807
     * @param string $document   document name
808
     *
809
     * @return void
810
     */
811
    protected function generateModel(array $parameters, $dir, $document)
812
    {
813
        $this->renderFile(
814
            'model/Model.php.twig',
815
            $dir . '/Model/' . $document . '.php',
816
            $parameters
817
        );
818
        $this->renderFile(
819
            'model/schema.json.twig',
820
            $dir . '/Resources/config/schema/' . $document . '.json',
821
            $parameters
822
        );
823
824
        // embedded versions
825
        $this->renderFile(
826
            'model/Model.php.twig',
827
            $dir . '/Model/' . $document . 'Embedded.php',
828
            array_merge($parameters, ['document' => $document.'Embedded'])
829
        );
830
        $this->renderFile(
831
            'model/schema.json.twig',
832
            $dir . '/Resources/config/schema/' . $document . 'Embedded.json',
833
            array_merge($parameters, ['document' => $document.'Embedded'])
834
        );
835
836
        $this->renderFile(
837
            'validator/validation.xml.twig',
838
            $dir . '/Resources/config/validation.xml',
839
            $parameters
840
        );
841
842
        $services = $this->loadServices($dir);
843
844
        $bundleParts = explode('\\', $parameters['base']);
845
        $shortName = strtolower($bundleParts[0]);
846
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
847
        $paramName = implode('.', array($shortName, $shortBundle, 'model', strtolower($parameters['document'])));
848
        $repoName = implode('.', array($shortName, $shortBundle, 'repository', strtolower($parameters['document'])));
849
850
        $this->addXmlParameter($parameters['base'] . 'Model\\' . $parameters['document'], $paramName . '.class');
851
852
        // normal service
853
        $this->addService(
854
            $services,
855
            $paramName,
856
            'graviton.rest.model',
857
            null,
858
            array(
859
                [
860
                    'method' => 'setRepository',
861
                    'service' => $repoName
862
                ],
863
            ),
864
            null
865
        );
866
867
        // embedded service
868
        $this->addXmlParameter(
869
            $parameters['base'] . 'Model\\' . $parameters['document'] . 'Embedded',
870
            $paramName . 'embedded.class'
871
        );
872
873
        $this->addService(
874
            $services,
875
            $paramName . 'embedded',
876
            'graviton.rest.model',
877
            null,
878
            array(
879
                [
880
                    'method' => 'setRepository',
881
                    'service' => $repoName . 'embedded'
882
                ],
883
            ),
884
            null
885
        );
886
887
        $this->persistServicesXML($dir);
888
    }
889
890
    /**
891
     * generate RESTful controllers ans service configs
892
     *
893
     * @param array  $parameters twig parameters
894
     * @param string $dir        base bundle dir
895
     * @param string $document   document name
896
     *
897
     * @return void
898
     */
899
    protected function generateController(array $parameters, $dir, $document)
900
    {
901
        $this->renderFile(
902
            'controller/DocumentController.php.twig',
903
            $dir . '/Controller/' . $document . 'Controller.php',
904
            $parameters
905
        );
906
907
        $services = $this->loadServices($dir);
908
909
        $bundleParts = explode('\\', $parameters['base']);
910
        $shortName = strtolower($bundleParts[0]);
911
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
912
        $paramName = implode('.', array($shortName, $shortBundle, 'controller', strtolower($parameters['document'])));
913
914
        $this->addXmlParameter(
915
            $parameters['base'] . 'Controller\\' . $parameters['document'] . 'Controller',
916
            $paramName . '.class'
917
        );
918
919
        $this->addService(
920
            $services,
921
            $paramName,
922
            $parameters['parent'],
923
            'request',
924
            array(
925
                array(
926
                    'method' => 'setModel',
927
                    'service' => implode(
928
                        '.',
929
                        array($shortName, $shortBundle, 'model', strtolower($parameters['document']))
930
                    )
931
                )
932
            ),
933
            'graviton.rest'
934
        );
935
936
        $this->persistServicesXML($dir);
937
    }
938
939
    /**
940
     * generates fixtures
941
     *
942
     * @param array  $parameters twig parameters
943
     * @param string $dir        base bundle dir
944
     * @param string $document   document name
945
     *
946
     * @return void
947
     */
948
    protected function generateFixtures(array $parameters, $dir, $document)
949
    {
950
        $parameters['fixtures_json'] = addcslashes(json_encode($this->json->getFixtures()), "'");
951
        $parameters['fixtureOrder'] = $this->json->getFixtureOrder();
952
953
        $this->renderFile(
954
            'fixtures/LoadFixtures.php.twig',
955
            $dir . '/DataFixtures/MongoDB/Load' . $document . 'Data.php',
956
            $parameters
957
        );
958
    }
959
}
960