DoctrineFormGenerator::getFieldsFromMetadata()   B
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 28
Code Lines 16

Duplication

Lines 5
Ratio 17.86 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 5
loc 28
rs 8.439
ccs 14
cts 14
cp 1
cc 5
eloc 16
nc 7
nop 1
crap 5
1
<?php
2
3
namespace Pgs\RestfonyBundle\Generator;
4
5
use Pgs\RestfonyBundle\Manipulator\RestFormServiceManipulator;
6
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
7
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
8
use Doctrine\ORM\Mapping\ClassMetadataInfo;
9
10
class DoctrineFormGenerator extends Generator
11
{
12
    protected $bundlePath;
13
    protected $entity;
14
    protected $entityClass;
15
    protected $namespace;
16
    protected $metadata;
17
18
    /**
19
     * @param BundleInterface   $bundle         The bundle in which to create the class
20
     * @param string            $entity         The entity relative class name
21
     * @param ClassMetadataInfo $metadata       The entity metadata class
22
     */
23 3
    public function __construct(BundleInterface $bundle, $entity, ClassMetadataInfo $metadata)
24
    {
25 3
        if (count($metadata->getIdentifier()) > 1) {
26 1
            throw new \RuntimeException(__CLASS__ . ' does not support entity classes with multiple primary keys.');
27
        }
28
29 2
        $this->entityClass = $this->prepareEntityClass($entity);
30 2
        $this->namespace = $bundle->getNamespace();
31 2
        $this->bundlePath = $bundle->getPath();
32 2
        $this->entity = $entity;
33 2
        $this->metadata = $metadata;
34 2
    }
35
36 2
    protected function prepareEntityClass($entity)
37
    {
38 2
        return substr($entity, strpos($entity, '\\'));
39
    }
40
41
    /**
42
     * Generates the entity form class if it does not exist.
43
     *
44
     * @param bool $forceOverwrite
45
     */
46 2
    public function generate($forceOverwrite = false)
47
    {
48 2
        $formPath = $this->prepareFilePath('/Form/Type/', 'Type');
49
50 2
        if (!$this->canWriteToFile($formPath, $forceOverwrite)) {
51 1
            throw new \RuntimeException(sprintf(
52 1
                'Unable to generate the %s form class as it already exists under the file: %s',
53 1
                $this->entityClass . 'Type',
54
                $formPath
55
            ));
56
        }
57
58 1
        $this->renderFile(
59 1
            'form/FormType.php.twig',
60
            $formPath,
61
            [
62 1
                'fields'                => $this->getFieldsFromMetadata($this->metadata),
63 1
                'associations'          => $this->metadata->associationMappings,
64 1
                'namespace'             => $this->namespace,
65 1
                'entity_namespace'      => $this->prepareEntityNamespace($this->entity),
66 1
                'entity_class'          => $this->entityClass,
67
                'rest_support'          => true,
68 1
                'rest_form_type_name'   => $this->prepareFormAlias($this->entityClass),
69 1
                'form_type_name'        => $this->prepareFormTypeName($this->entity, $this->namespace, $this->entityClass)
70
            ]
71
        );
72
73 1
        $this->renderFile(
74 1
            'form/FormFilterType.php.twig',
75 1
            $this->prepareFilePath('/Form/Filter/', 'FilterType'),
76
            [
77 1
                'namespace'             => $this->namespace,
78 1
                'entity_namespace'      => $this->prepareEntityNamespace($this->entity),
79 1
                'entity_class'          => $this->entityClass,
80
                'rest_support'          => true,
81 1
                'rest_form_type_name'   => $this->prepareFormAlias($this->entityClass),
82 1
                'form_type_name'        => $this->prepareFormTypeName($this->entity, $this->namespace, $this->entityClass) . 'filter'
83
            ]
84
        );
85 1
    }
86
87 1
    protected function canWriteToFile($path, $forceOverwrite = false)
88
    {
89 1
        return !file_exists($path) || $forceOverwrite;
90
    }
91
92 1
    protected function prepareEntityNamespace($entity)
93
    {
94 1
        $result = [];
95 1
        preg_match(addslashes('/:(([A-z0-9\]+)\)?[A-z0-9]+$/'), $entity, $result);
96 1
        return isset($result[2]) ? $result[2] : '';
97
    }
98
99
    protected function prepareFormAlias($entityClass)
100
    {
101 1
        return ltrim(preg_replace_callback('|[A-Z]+|', function ($data) {
102 1
            return '_'.strtolower($data[0]);
103 1
        }, $entityClass), '_');
104
    }
105
106 1
    protected function prepareFormTypeName($entity, $namespace, $entityClass)
107
    {
108 1
        $parts = explode('\\', $entity);
109 1
        return strtolower(
110 1
            str_replace('\\', '_', $namespace)
111 1
            . ($parts ? '_' : '')
112 1
            . implode('_', $parts)
113 1
            . '_' . $entityClass
114
        );
115
    }
116
117 2
    protected function prepareFilePath($path, $postfix)
118
    {
119 2
        return $this->bundlePath . $path . str_replace('\\', '/', $this->entity) . $postfix . '.php';
120
    }
121
122
    /**
123
     * Returns an array of fields. Fields can be both column fields and
124
     * association fields.
125
     *
126
     * @param ClassMetadataInfo $metadata
127
     *
128
     * @return array $fields
129
     */
130 1
    protected function getFieldsFromMetadata(ClassMetadataInfo $metadata)
131
    {
132 1
        $fields = array_merge($metadata->fieldMappings, $metadata->getAssociationMappings());
133
134
        // Remove the primary key field if it's not managed manually
135 1
        if (!$metadata->isIdentifierNatural()) {
136 1
            foreach ($metadata->getIdentifier() as $identifier) {
137 1
                unset($fields[$identifier]);
138
            }
139
        }
140
141 1
        foreach ($metadata->getAssociationMappings() as $fieldName => $relation) {
142
            $multiTypes = array(
143 1
                ClassMetadataInfo::ONE_TO_MANY,
144 1
                ClassMetadataInfo::MANY_TO_MANY,
145
            );
146 1 View Code Duplication
            if (in_array($relation['type'], $multiTypes)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147 1
                $fields[$fieldName]['relatedType'] = 'collection';
148
            } else {
149 1
                $fields[$fieldName]['relatedType'] = 'entity';
150
            }
151
152 1
            $fields[$fieldName]['relatedEntityShortcut'] =
153 1
                $this->getEntityBundleShortcut($fields[$fieldName]['targetEntity']);
154
        }
155
156 1
        return $fields;
157
    }
158
159
    /**
160
     * Take an entity name and return the shortcut name
161
     * eg Acme\DemoBundle\Entity\Notes -> AcemDemoBundle:Notes.
162
     *
163
     * @param string $entity fully qualified class name of the entity
164
     */
165 1
    protected function getEntityBundleShortcut($entity)
166
    {
167
        // wrap in EntityManager's Class Metadata function avoid problems with cached proxy classes
168 1
        $path = explode('\Entity\\', $entity);
169
170 1
        return str_replace('\\', '', $path[0]).':'.$path[1];
171
    }
172
}
173