Completed
Pull Request — develop (#441)
by
unknown
273:25 queued 268:07
created

ResourceGenerator::addService()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 64
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 64
ccs 0
cts 36
cp 0
rs 6.8232
cc 8
eloc 39
nc 13
nop 9
crap 72

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
        
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
            ->setParameter('indexes', $this->json->getIndexes())
169
            ->setParameter('searchables', $this->json->getSearchables())
170
            ->getParameters();
171
172
        $this->generateDocument($parameters, $dir, $document);
173
        $this->generateSerializer($parameters, $dir, $document);
174
        $this->generateModel($parameters, $dir, $document);
175
176
        if ($this->json instanceof JsonDefinition && $this->json->hasFixtures() === true) {
177
            $this->generateFixtures($parameters, $dir, $document);
178
        }
179
180
        if ($this->generateController) {
181
            $this->generateController($parameters, $dir, $document);
182
        }
183
184
        $this->generateParameters($dir);
185
186
        return new EntityGeneratorResult(
187
            $dir . '/Document/' . $document . '.php',
188
            $dir . '/Repository/' . $document . 'Repository.php',
189
            $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml'
190
        );
191
    }
192
193
    /**
194
     * Writes the current services definition to a file.
195
     *
196
     * @param string $dir base bundle dir
197
     *
198
     * @return void
199
     */
200 8
    protected function persistServicesXML($dir)
201
    {
202 8
        $services = $this->loadServices($dir);
203
204 8
        file_put_contents($dir . '/Resources/config/services.xml', $services->saveXML());
205 8
    }
206
207
    /**
208
     * generate document part of a resource
209
     *
210
     * @param array  $parameters twig parameters
211
     * @param string $dir        base bundle dir
212
     * @param string $document   document name
213
     *
214
     * @return void
215
     */
216 6
    protected function generateDocument($parameters, $dir, $document)
217
    {
218
        // doctrine mapping normal class
219 6
        $this->renderFile(
220 6
            'document/Document.mongodb.xml.twig',
221 6
            $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml',
222
            $parameters
223 3
        );
224
225
        // doctrine mapping embedded
226 6
        $this->renderFile(
227 6
            'document/Document.mongodb.xml.twig',
228 6
            $dir . '/Resources/config/doctrine/' . $document . 'Embedded.mongodb.xml',
229 3
            array_merge(
230 3
                $parameters,
231
                [
232 6
                    'document' => $document.'Embedded',
233 3
                    'docType' => 'embedded-document'
234 3
                ]
235 3
            )
236 3
        );
237
238 6
        $this->renderFile(
239 6
            'document/Document.php.twig',
240 6
            $dir . '/Document/' . $document . '.php',
241
            $parameters
242 3
        );
243 6
        $this->renderFile(
244 6
            'document/DocumentEmbedded.php.twig',
245 6
            $dir . '/Document/' . $document . 'Embedded.php',
246
            $parameters
247 3
        );
248 6
        $this->renderFile(
249 6
            'document/DocumentBase.php.twig',
250 6
            $dir . '/Document/' . $document . 'Base.php',
251
            $parameters
252 3
        );
253
254 6
        $this->generateServices($parameters, $dir, $document);
255 6
    }
256
257
    /**
258
     * update xml services
259
     *
260
     * @param array  $parameters twig parameters
261
     * @param string $dir        base bundle dir
262
     * @param string $document   document name
263
     *
264
     * @return void
265
     */
266 6
    protected function generateServices($parameters, $dir, $document)
267
    {
268 6
        $services = $this->loadServices($dir);
269
270 6
        $bundleParts = explode('\\', $parameters['base']);
271 6
        $shortName = $bundleParts[0];
272 6
        $shortBundle = $this->getBundleBaseName($bundleParts[1]);
273
274 6
        $docName = implode(
275 6
            '.',
276
            array(
277 6
                strtolower($shortName),
278 6
                strtolower($shortBundle),
279 6
                'document',
280 6
                strtolower($parameters['document'])
281 3
            )
282 3
        );
283
284 6
        $this->addXMLParameter(
285 6
            $parameters['base'] . 'Document\\' . $parameters['document'],
286 3
            $docName . '.class'
287 3
        );
288
289 6
        $this->addXMLParameter(
290 6
            $parameters['json']->getRoles(),
291 6
            $docName . '.roles',
292 3
            'collection'
293 3
        );
294
295 6
        $services = $this->addService(
296 3
            $services,
297
            $docName
298 3
        );
299
300 6
        $repoName = implode(
301 6
            '.',
302
            array(
303 6
                strtolower($shortName),
304 6
                strtolower($shortBundle),
305 6
                'repository',
306 6
                strtolower($parameters['document'])
307 3
            )
308 3
        );
309
310
        // normal repo service
311 6
        $services = $this->addParam(
312 3
            $services,
313 6
            $repoName . '.class',
314 6
            $parameters['base'] . 'Repository\\' . $parameters['document']
315 3
        );
316
317 6
        $this->addService(
318 3
            $services,
319 3
            $repoName,
320 6
            null,
321 6
            null,
322 6
            array(),
323 6
            null,
324
            array(
325
                array(
326 6
                    'type' => 'string',
327 6
                    'value' => $parameters['bundle'] . ':' . $document
328 3
                )
329 3
            ),
330 6
            'doctrine_mongodb.odm.default_document_manager',
331 3
            'getRepository'
332 3
        );
333
334
        // embedded repo service
335 6
        $services = $this->addParam(
336 3
            $services,
337 6
            $repoName . 'embedded.class',
338 6
            $parameters['base'] . 'Repository\\' . $parameters['document'] . 'Embedded'
339 3
        );
340
341 6
        $this->addService(
342 3
            $services,
343 6
            $repoName . 'embedded',
344 6
            null,
345 6
            null,
346 6
            array(),
347 6
            null,
348
            array(
349
                array(
350 6
                    'type' => 'string',
351 6
                    'value' => $parameters['bundle'] . ':' . $document . 'Embedded'
352 3
                )
353 3
            ),
354 6
            'doctrine_mongodb.odm.default_document_manager',
355 3
            'getRepository'
356 3
        );
357
358 6
        $this->renderFile(
359 6
            'document/DocumentRepository.php.twig',
360 6
            $dir . '/Repository/' . $document . 'Repository.php',
361
            $parameters
362 3
        );
363 6
        $this->renderFile(
364 6
            'document/DocumentRepository.php.twig',
365 6
            $dir . '/Repository/' . $document . 'EmbeddedRepository.php',
366 3
            array_merge(
367 3
                $parameters,
368
                [
369 6
                    'document' => $document.'Embedded',
370
                ]
371 3
            )
372 3
        );
373
374 6
        $this->persistServicesXML($dir);
375 6
    }
376
377
    /**
378
     * Generates the parameters section of the services.xml file.
379
     *
380
     * @param string $dir base bundle dir
381
     *
382
     * @return void
383
     */
384 2
    protected function generateParameters($dir)
385
    {
386 2
        if ($this->xmlParameters->count() > 0) {
387 2
            $services = $this->loadServices($dir);
388
389 2
            foreach ($this->xmlParameters as $parameter) {
390 2
                switch ($parameter['type']) {
391 2
                    case 'collection':
392 2
                        $this->addCollectionParam($services, $parameter['key'], $parameter['content']);
393 2
                        break;
394 2
                    case 'string':
395 1
                    default:
396 2
                        $this->addParam($services, $parameter['key'], $parameter['content']);
397 1
                }
398 1
            }
399 1
        }
400
401 2
        $this->persistServicesXML($dir);
402 2
    }
403
404
    /**
405
     * Registers information to be generated to a parameter tag.
406
     *
407
     * @param mixed  $value Content of the tag
408
     * @param string $key   Content of the key attribute
409
     * @param string $type  Type of the tag
410
     *
411
     * @return void
412
     */
413 2
    protected function addXmlParameter($value, $key, $type = 'string')
414
    {
415
        $element = array(
416 2
            'content' => $value,
417 2
            'key' => $key,
418 2
            'type' => strtolower($type),
419 1
        );
420
421 2
        if (!isset($this->xmlParameters)) {
422
            $this->xmlParameters = new ArrayCollection();
423
        }
424
425 2
        if (!$this->xmlParameters->contains($element)) {
426 2
            $this->xmlParameters->add($element);
427 1
        }
428 2
    }
429
430
    /**
431
     * load services.xml
432
     *
433
     * @param string $dir base dir
434
     *
435
     * @return \DOMDocument
436
     */
437 4
    protected function loadServices($dir)
438
    {
439 4
        if (empty($this->serviceDOM)) {
440 4
            $this->serviceDOM = new \DOMDocument;
441 4
            $this->serviceDOM->formatOutput = true;
442 4
            $this->serviceDOM->preserveWhiteSpace = false;
443 4
            $this->serviceDOM->load($dir . '/Resources/config/services.xml');
444 2
        }
445
446 4
        return $this->serviceDOM;
447
    }
448
449
    /**
450
     * add param to services.xml
451
     *
452
     * @param \DOMDocument $dom   services.xml document
453
     * @param string       $key   parameter key
454
     * @param string       $value parameter value
455
     *
456
     * @return \DOMDocument
457
     */
458 12
    protected function addParam(\DOMDocument $dom, $key, $value)
459
    {
460 12
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
461
462 12
        if (!$this->parameterNodeExists($dom, $key)) {
463 12
            $attrNode = $dom->createElement('parameter', $value);
464
465 12
            $this->addAttributeToNode('key', $key, $dom, $attrNode);
466
467 12
            $paramNode->appendChild($attrNode);
468 6
        }
469
470 12
        return $dom;
471
    }
472
473
    /**
474
     * Adds a new parameter tag to parameters section reflecting the defined roles.
475
     *
476
     * @param \DOMDocument $dom    services.xml document
477
     * @param string       $key    parameter key
478
     * @param array        $values parameter value
479
     *
480
     * @return void
481
     *
482
     * @link http://symfony.com/doc/current/book/service_container.html#array-parameters
483
     */
484 4
    protected function addCollectionParam(\DomDocument $dom, $key, array $values)
485
    {
486 4
        $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services');
487
488 4
        if (!$this->parameterNodeExists($dom, $key)) {
489 4
            if (!empty($values)) {
490 4
                $rolesNode = $dom->createElement('parameter');
491 4
                $this->addAttributeToNode('key', $key, $dom, $rolesNode);
492 4
                $this->addAttributeToNode('type', 'collection', $dom, $rolesNode);
493
494 4
                foreach ($values as $item) {
495 4
                    $roleNode = $dom->createElement('parameter', $item);
496 4
                    $rolesNode->appendChild($roleNode);
497 2
                }
498
499 4
                $paramNode->appendChild($rolesNode);
500 2
            }
501 2
        }
502
503 4
    }
504
505
    /**
506
     * Determines, if the provided key attribute was already claimed by a parameter node.
507
     *
508
     * @param \DomDocument $dom Current document
509
     * @param string       $key Key to be found in document
510
     *
511
     * @return bool
512
     */
513 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...
514
    {
515 14
        $xpath = new \DomXpath($dom);
516 14
        $nodes = $xpath->query('//parameters/parameter[@key="' . $key . '"]');
517
518 14
        return $nodes->length > 0;
519
    }
520
521
    /**
522
     * add node if missing
523
     *
524
     * @param \DOMDocument $dom          document
525
     * @param string       $element      name for new node element
526
     * @param string       $insertBefore xPath query of the new node shall be added before
527
     * @param string       $container    name of container tag
528
     *
529
     * @return \DOMNode new element node
530
     */
531 14
    private function addNodeIfMissing(&$dom, $element, $insertBefore = '', $container = 'container')
532
    {
533 14
        $container = $dom->getElementsByTagName($container)
534 14
            ->item(0);
535 14
        $nodes = $dom->getElementsByTagName($element);
536 14
        if ($nodes->length < 1) {
537 14
            $newNode = $dom->createElement($element);
538
539 14
            if (!empty($insertBefore)) {
540 14
                $xpath = new \DomXpath($dom);
541 14
                $found = $xpath->query($insertBefore);
542
543 14
                if ($found->length > 0) {
544
                    $container->insertBefore($newNode, $found->item(0));
545
                } else {
546 14
                    $container->appendChild($newNode);
547
                }
548 7
            } else {
549 7
                $container->appendChild($newNode);
550
            }
551 7
        } else {
552 4
            $newNode = $nodes->item(0);
553
        }
554
555 14
        return $newNode;
556
    }
557
558
    /**
559
     * add attribute to node if needed
560
     *
561
     * @param string       $name  attribute name
562
     * @param string       $value attribute value
563
     * @param \DOMDocument $dom   document
564
     * @param \DOMElement  $node  parent node
565
     *
566
     * @return void
567
     */
568 14
    private function addAttributeToNode($name, $value, $dom, $node)
569
    {
570 14
        if ($value) {
571 14
            $attr = $dom->createAttribute($name);
572 14
            $attr->value = $value;
573 14
            $node->appendChild($attr);
574 7
        }
575 14
    }
576
577
    /**
578
     * add service to services.xml
579
     *
580
     * @param \DOMDocument $dom            services.xml dom
581
     * @param string       $id             id of new service
582
     * @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...
583
     * @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...
584
     * @param array        $calls          methodCalls to add
585
     * @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...
586
     * @param array        $arguments      service arguments
587
     * @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...
588
     * @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...
589
     *
590
     * @return \DOMDocument
591
     */
592
    protected function addService(
593
        $dom,
594
        $id,
595
        $parent = null,
596
        $scope = null,
597
        array $calls = array(),
598
        $tag = null,
599
        array $arguments = array(),
600
        $factoryService = null,
601
        $factoryMethod = null
602
    ) {
603
        $servicesNode = $this->addNodeIfMissing($dom, 'services');
604
605
        $xpath = new \DomXpath($dom);
606
607
        // add controller to services
608
        $nodes = $xpath->query('//services/service[@id="' . $id . '"]');
609
        if ($nodes->length < 1) {
610
            $attrNode = $dom->createElement('service');
611
612
            $this->addAttributeToNode('id', $id, $dom, $attrNode);
613
            $this->addAttributeToNode('class', '%' . $id . '.class%', $dom, $attrNode);
614
            $this->addAttributeToNode('parent', $parent, $dom, $attrNode);
615
            $this->addAttributeToNode('scope', $scope, $dom, $attrNode);
616
            if ($factoryService && $factoryMethod) {
617
                $factoryNode = $dom->createElement('factory');
618
                $this->addAttributeToNode('service', $factoryService, $dom, $factoryNode);
619
                $this->addAttributeToNode('method', $factoryMethod, $dom, $factoryNode);
620
                $attrNode->appendChild($factoryNode);
621
            }
622
            $this->addCallsToService($calls, $dom, $attrNode);
623
624
            if ($tag) {
625
                $tagNode = $dom->createElement('tag');
626
627
                $this->addAttributeToNode('name', $tag, $dom, $tagNode);
628
629
                // get stuff from json definition
630
                if ($this->json instanceof JsonDefinition) {
631
                    // id is also name of collection in mongodb
632
                    $this->addAttributeToNode('collection', $this->json->getId(), $dom, $tagNode);
633
634
                    // is this read only?
635
                    if ($this->json->isReadOnlyService()) {
636
                        $this->addAttributeToNode('read-only', 'true', $dom, $tagNode);
637
                    }
638
639
                    // router base defined?
640
                    $routerBase = $this->json->getRouterBase();
641
                    if ($routerBase !== false) {
642
                        $this->addAttributeToNode('router-base', $routerBase, $dom, $tagNode);
643
                    }
644
                }
645
646
                $attrNode->appendChild($tagNode);
647
            }
648
649
            $this->addArgumentsToService($arguments, $dom, $attrNode);
650
651
            $servicesNode->appendChild($attrNode);
652
        }
653
654
        return $dom;
655
    }
656
657
    /**
658
     * add calls to service
659
     *
660
     * @param array        $calls info on calls to create
661
     * @param \DOMDocument $dom   current domdocument
662
     * @param \DOMElement  $node  node to add call to
663
     *
664
     * @return void
665
     */
666
    private function addCallsToService($calls, $dom, $node)
667
    {
668
        foreach ($calls as $call) {
669
            $this->addCallToService($call, $dom, $node);
670
        }
671
    }
672
673
    /**
674
     * add call to service
675
     *
676
     * @param array        $call info on call node to create
677
     * @param \DOMDocument $dom  current domdocument
678
     * @param \DOMElement  $node node to add call to
679
     *
680
     * @return void
681
     */
682
    private function addCallToService($call, $dom, $node)
683
    {
684
        $callNode = $dom->createElement('call');
685
686
        $attr = $dom->createAttribute('method');
687
        $attr->value = $call['method'];
688
        $callNode->appendChild($attr);
689
690
        $argNode = $dom->createElement('argument');
691
692
        $attr = $dom->createAttribute('type');
693
        $attr->value = 'service';
694
        $argNode->appendChild($attr);
695
696
        $attr = $dom->createAttribute('id');
697
        $attr->value = $call['service'];
698
        $argNode->appendChild($attr);
699
700
        $callNode->appendChild($argNode);
701
702
        $node->appendChild($callNode);
703
    }
704
705
    /**
706
     * add arguments to servie
707
     *
708
     * @param array        $arguments arguments to create
709
     * @param \DOMDocument $dom       dom document to add to
710
     * @param \DOMElement  $node      node to use as parent
711
     *
712
     * @return void
713
     */
714
    private function addArgumentsToService($arguments, $dom, $node)
715
    {
716
        foreach ($arguments as $argument) {
717
            $this->addArgumentToService($argument, $dom, $node);
718
        }
719
    }
720
721
    /**
722
     * add argument to service
723
     *
724
     * @param array        $argument info on argument to create
725
     * @param \DOMDocument $dom      dom document to add to
726
     * @param \DOMElement  $node     node to use as parent
727
     *
728
     * @return void
729
     */
730
    private function addArgumentToService($argument, $dom, $node)
731
    {
732
        $isService = $argument['type'] == 'service';
733
734
        if ($isService) {
735
            $argNode = $dom->createElement('argument');
736
737
            $idArg = $dom->createAttribute('id');
738
            $idArg->value = $argument['id'];
739
            $argNode->appendChild($idArg);
740
        } else {
741
            $argNode = $dom->createElement('argument', $argument['value']);
742
        }
743
744
        $argType = $dom->createAttribute('type');
745
        $argType->value = $argument['type'];
746
        $argNode->appendChild($argType);
747
748
        $node->appendChild($argNode);
749
    }
750
751
    /**
752
     * generate serializer part of a resource
753
     *
754
     * @param array  $parameters twig parameters
755
     * @param string $dir        base bundle dir
756
     * @param string $document   document name
757
     *
758
     * @return void
759
     */
760
    protected function generateSerializer(array $parameters, $dir, $document)
761
    {
762
        // @TODO in Embedded and document just render the differences..
763
        $this->renderFile(
764
            'serializer/Document.xml.twig',
765
            $dir . '/Resources/config/serializer/Document.' . $document . 'Embedded.xml',
766
            array_merge(
767
                $parameters,
768
                [
769
                    'document' => $document.'Embedded',
770
                    'noIdField' => true,
771
                    'realIdField' => true
772
                ]
773
            )
774
        );
775
776
        foreach ($parameters['fields'] as $key => $field) {
777
            if (substr($field['serializerType'], 0, 14) == 'array<Graviton' &&
778
                strpos($field['serializerType'], '\\Entity') === false &&
779
                $field['relType'] == 'embed'
780
            ) {
781
                $parameters['fields'][$key]['serializerType'] = substr($field['serializerType'], 0, -1).'Embedded>';
782
            } elseif (substr($field['serializerType'], 0, 8) == 'Graviton' &&
783
                strpos($field['serializerType'], '\\Entity') === false &&
784
                $field['relType'] == 'embed'
785
            ) {
786
                $parameters['fields'][$key]['serializerType'] = $field['serializerType'].'Embedded';
787
            }
788
        }
789
        $this->renderFile(
790
            'serializer/Document.xml.twig',
791
            $dir . '/Resources/config/serializer/Document.' . $document . '.xml',
792
            array_merge(
793
                $parameters,
794
                [
795
                    'realIdField' => false
796
                ]
797
            )
798
        );
799
        $this->renderFile(
800
            'serializer/Document.xml.twig',
801
            $dir . '/Resources/config/serializer/Document.' . $document . 'Base.xml',
802
            array_merge(
803
                $parameters,
804
                [
805
                    'document' => $document.'Base',
806
                    'realIdField' => false
807
                ]
808
            )
809
        );
810
811
    }
812
813
    /**
814
     * generate model part of a resource
815
     *
816
     * @param array  $parameters twig parameters
817
     * @param string $dir        base bundle dir
818
     * @param string $document   document name
819
     *
820
     * @return void
821
     */
822
    protected function generateModel(array $parameters, $dir, $document)
823
    {
824
        $this->renderFile(
825
            'model/Model.php.twig',
826
            $dir . '/Model/' . $document . '.php',
827
            $parameters
828
        );
829
        $this->renderFile(
830
            'model/schema.json.twig',
831
            $dir . '/Resources/config/schema/' . $document . '.json',
832
            $parameters
833
        );
834
835
        // embedded versions
836
        $this->renderFile(
837
            'model/Model.php.twig',
838
            $dir . '/Model/' . $document . 'Embedded.php',
839
            array_merge($parameters, ['document' => $document.'Embedded'])
840
        );
841
        $this->renderFile(
842
            'model/schema.json.twig',
843
            $dir . '/Resources/config/schema/' . $document . 'Embedded.json',
844
            array_merge($parameters, ['document' => $document.'Embedded'])
845
        );
846
847
        $this->renderFile(
848
            'validator/validation.xml.twig',
849
            $dir . '/Resources/config/validation.xml',
850
            $parameters
851
        );
852
853
        $services = $this->loadServices($dir);
854
855
        $bundleParts = explode('\\', $parameters['base']);
856
        $shortName = strtolower($bundleParts[0]);
857
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
858
        $paramName = implode('.', array($shortName, $shortBundle, 'model', strtolower($parameters['document'])));
859
        $repoName = implode('.', array($shortName, $shortBundle, 'repository', strtolower($parameters['document'])));
860
861
        $this->addXmlParameter($parameters['base'] . 'Model\\' . $parameters['document'], $paramName . '.class');
862
863
        // normal service
864
        $this->addService(
865
            $services,
866
            $paramName,
867
            'graviton.rest.model',
868
            null,
869
            array(
870
                [
871
                    'method' => 'setRepository',
872
                    'service' => $repoName
873
                ],
874
            ),
875
            null
876
        );
877
878
        // embedded service
879
        $this->addXmlParameter(
880
            $parameters['base'] . 'Model\\' . $parameters['document'] . 'Embedded',
881
            $paramName . 'embedded.class'
882
        );
883
884
        $this->addService(
885
            $services,
886
            $paramName . 'embedded',
887
            'graviton.rest.model',
888
            null,
889
            array(
890
                [
891
                    'method' => 'setRepository',
892
                    'service' => $repoName . 'embedded'
893
                ],
894
            ),
895
            null
896
        );
897
898
        $this->persistServicesXML($dir);
899
    }
900
901
    /**
902
     * generate RESTful controllers ans service configs
903
     *
904
     * @param array  $parameters twig parameters
905
     * @param string $dir        base bundle dir
906
     * @param string $document   document name
907
     *
908
     * @return void
909
     */
910
    protected function generateController(array $parameters, $dir, $document)
911
    {
912
        $this->renderFile(
913
            'controller/DocumentController.php.twig',
914
            $dir . '/Controller/' . $document . 'Controller.php',
915
            $parameters
916
        );
917
918
        $services = $this->loadServices($dir);
919
920
        $bundleParts = explode('\\', $parameters['base']);
921
        $shortName = strtolower($bundleParts[0]);
922
        $shortBundle = strtolower(substr($bundleParts[1], 0, -6));
923
        $paramName = implode('.', array($shortName, $shortBundle, 'controller', strtolower($parameters['document'])));
924
925
        $this->addXmlParameter(
926
            $parameters['base'] . 'Controller\\' . $parameters['document'] . 'Controller',
927
            $paramName . '.class'
928
        );
929
930
        $this->addService(
931
            $services,
932
            $paramName,
933
            $parameters['parent'],
934
            'request',
935
            array(
936
                array(
937
                    'method' => 'setModel',
938
                    'service' => implode(
939
                        '.',
940
                        array($shortName, $shortBundle, 'model', strtolower($parameters['document']))
941
                    )
942
                )
943
            ),
944
            'graviton.rest'
945
        );
946
947
        $this->persistServicesXML($dir);
948
    }
949
950
    /**
951
     * generates fixtures
952
     *
953
     * @param array  $parameters twig parameters
954
     * @param string $dir        base bundle dir
955
     * @param string $document   document name
956
     *
957
     * @return void
958
     */
959
    protected function generateFixtures(array $parameters, $dir, $document)
960
    {
961
        $parameters['fixtures_json'] = addcslashes(json_encode($this->json->getFixtures()), "'");
962
        $parameters['fixtureOrder'] = $this->json->getFixtureOrder();
963
964
        $this->renderFile(
965
            'fixtures/LoadFixtures.php.twig',
966
            $dir . '/DataFixtures/MongoDB/Load' . $document . 'Data.php',
967
            $parameters
968
        );
969
    }
970
}
971