Completed
Push — master ( 118f52...c5048d )
by Thomas
10:09
created

ModelSerializerTraitGenerator   C

Complexity

Total Complexity 17

Size/Duplication

Total Lines 216
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 11
Bugs 2 Features 1
Metric Value
wmc 17
c 11
b 2
f 1
lcom 1
cbo 19
dl 0
loc 216
rs 6.875

6 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 13 1
A generateIdentifyingMethods() 0 18 1
B generateAttributeMethods() 0 41 4
B generateHydrateMethod() 0 47 5
B generateRelationshipMethods() 0 76 5
A generateTypeInferencerAccess() 0 8 1
1
<?php
2
namespace keeko\tools\generator\serializer\base;
3
4
use gossi\codegen\model\PhpMethod;
5
use gossi\codegen\model\PhpParameter;
6
use gossi\codegen\model\PhpTrait;
7
use keeko\framework\utils\NameUtils;
8
use keeko\tools\generator\serializer\AbstractSerializerGenerator;
9
use keeko\tools\model\Relationship;
10
use Propel\Generator\Model\Table;
11
12
class ModelSerializerTraitGenerator extends AbstractSerializerGenerator {
13
14
	/**
15
	 *
16
	 * @param Table $model
17
	 * @return PhpTrait
18
	 */
19
	public function generate(Table $model) {
20
		$ns = $this->packageService->getNamespace();
21
		$fqcn = sprintf('%s\\serializer\\base\\%sSerializerTrait', $ns, $model->getPhpName());
22
		$trait = new PhpTrait($fqcn);
23
24
		$this->generateIdentifyingMethods($trait, $model);
25
		$this->generateAttributeMethods($trait, $model);
26
		$this->generateHydrateMethod($trait, $model);
27
		$this->generateRelationshipMethods($trait, $model);
28
		$this->generateTypeInferencerAccess($trait);
29
30
		return $trait;
31
	}
32
33
	protected function generateIdentifyingMethods(PhpTrait $trait, Table $model) {
34
		$package = $this->packageService->getPackage();
35
		$type = sprintf('%s/%s', $package->getKeeko()->getModule()->getSlug(), NameUtils::dasherize($model->getOriginCommonName()));
36
37
		$trait->setMethod(PhpMethod::create('getId')
38
			->addParameter(PhpParameter::create('model'))
39
			->setBody($this->twig->render('getId.twig'))
40
			->setType('string')
41
		);
42
43
		$trait->setMethod(PhpMethod::create('getType')
44
			->addParameter(PhpParameter::create('model'))
45
			->setBody($this->twig->render('getType.twig', [
46
				'type' => $type
47
			]))
48
			->setType('string')
49
		);
50
	}
51
52
	protected function generateAttributeMethods(PhpTrait $trait, Table $model) {
53
		$readFields = $this->codegenService->getReadFields($model->getOriginCommonName());
54
		$attrs = '';
55
56
		foreach ($readFields as $field) {
57
			$col = $model->getColumn($field);
58
			$param = $col->isTemporalType() ? '\DateTime::ISO8601' : '';
59
			$attrs .= sprintf("\t'%s' => \$model->get%s(%s),\n",
60
				NameUtils::dasherize($field), $col->getPhpName(), $param
61
			);
62
		}
63
64
		if (count($field) > 0) {
0 ignored issues
show
Bug introduced by
The variable $field seems to be defined by a foreach iteration on line 56. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
65
			$attrs = substr($attrs, 0, -2);
66
		}
67
68
		$trait->setMethod(PhpMethod::create('getAttributes')
69
			->addParameter(PhpParameter::create('model'))
70
			->addParameter(PhpParameter::create('fields')->setType('array')->setDefaultValue(null))
0 ignored issues
show
Deprecated Code introduced by
The method gossi\codegen\model\part...Part::setDefaultValue() has been deprecated with message: use `setValue()` instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
71
			->setBody($this->twig->render('getAttributes.twig', [
72
				'attrs' => $attrs
73
			]))
74
		);
75
76
		$trait->setMethod(PhpMethod::create('getSortFields')
77
			->setBody($this->twig->render('getFields.twig', [
78
				'fields' => $this->codegenService->arrayToCode(array_map(function ($field) {
79
					return NameUtils::dasherize($field);
80
				}, $readFields))
81
			]))
82
		);
83
84
		$readFields = $this->codegenService->getReadFields($model->getOriginCommonName());
85
		$trait->setMethod(PhpMethod::create('getFields')
86
			->setBody($this->twig->render('getFields.twig', [
87
				'fields' => $this->codegenService->arrayToCode(array_map(function ($field) {
88
					return NameUtils::dasherize($field);
89
				}, $readFields))
90
			]))
91
		);
92
	}
93
94
	protected function generateHydrateMethod(PhpTrait $trait, Table $model) {
95
		if ($model->isReadOnly()) {
96
			$body = $this->twig->render('hydrate-readonly.twig');
97
		} else {
98
			$trait->addUseStatement('keeko\\framework\\utils\\HydrateUtils');
99
			$modelName = $model->getOriginCommonName();
100
			$normalizer = $this->codegenService->getCodegen()->getNormalizer($modelName);
101
			$fields = $this->codegenService->getWriteFields($modelName);
102
			$code = '';
103
104
			foreach ($fields as $field) {
105
				$code .= sprintf("'%s'", NameUtils::dasherize($field));
106
				if ($normalizer->has($field)) {
107
					$code .= $this->twig->render('normalizer.twig', [
108
						'class' => $normalizer->get($field)
109
					]);
110
				}
111
112
				$code .= ', ';
113
			}
114
115
			if (strlen($code) > 0) {
116
				$code = substr($code, 0, -2);
117
			}
118
119
			$code = sprintf('[%s]', $code);
120
			$body = $this->twig->render('hydrate.twig', [
121
				'code' => $code,
122
				'normalizer' => $normalizer->size() > 0
123
			]);
124
125
			$trait->setMethod(PhpMethod::create('hydrateRelationships')
126
				->addParameter(PhpParameter::create('model'))
127
				->addParameter(PhpParameter::create('data'))
128
				->setAbstract(true)
129
				->setType('void')
130
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
131
			);
132
		}
133
134
		$trait->setMethod(PhpMethod::create('hydrate')
135
			->addParameter(PhpParameter::create('model'))
136
			->addParameter(PhpParameter::create('data'))
137
			->setBody($body)
138
			->setType('mixed', 'The model')
139
		);
140
	}
141
142
	protected function generateRelationshipMethods(PhpTrait $trait, Table $model) {
143
		if ($model->isReadOnly()) {
144
			return;
145
		}
146
147
		$fields = [];
148
		$relationships = $this->modelService->getRelationships($model);
149
150
		if ($relationships->size() > 0) {
151
			$trait->addUseStatement('Tobscure\\JsonApi\\Relationship');
152
			$trait->setMethod(PhpMethod::create('addRelationshipSelfLink')
153
				->addParameter(PhpParameter::create('relationship')
154
					->setType('Relationship')
155
				)
156
				->addParameter(PhpParameter::create('model')
157
					->setType('mixed')
158
				)
159
				->addParameter(PhpParameter::create('related')
160
					->setType('string')
161
				)
162
				->setAbstract(true)
163
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
164
				->setType('Relationship')
165
			);
166
		}
167
168
		foreach ($relationships->getAll() as $rel) {
169
			// one-to-one
170
			if ($rel->getType() == Relationship::ONE_TO_ONE) {
171
				$foreign = $rel->getForeign();
172
				$relatedName = $rel->getRelatedName();
173
				$typeName = $rel->getRelatedTypeName();
174
				$method = NameUtils::toCamelCase($relatedName);
175
				$fields[$typeName] = $foreign->getPhpName() . '::getSerializer()->getType(null)';
176
				$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName());
177
				$trait->addUseStatement('Tobscure\\JsonApi\\Resource');
178
179
				// read
180
				$body = $this->twig->render('to-one-read.twig', [
181
					'class' => $foreign->getPhpName(),
182
					'related' => $relatedName,
183
					'related_type' => $typeName
184
				]);
185
			}
186
187
			// ?-to-many
188
			else {
189
				$foreign = $rel->getForeign();
190
				$typeName = $rel->getRelatedPluralTypeName();
191
				$method = NameUtils::toCamelCase($rel->getRelatedPluralName());
192
				$fields[$typeName] = $foreign->getPhpName() . '::getSerializer()->getType(null)';
193
				$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName());
194
				$trait->addUseStatement('Tobscure\\JsonApi\\Collection');
195
196
				// read
197
				$body = $this->twig->render('to-many-read.twig', [
198
					'class' => $foreign->getPhpName(),
199
					'related' => $rel->getRelatedPluralName(),
200
					'related_type' => $rel->getRelatedTypeName()
201
				]);
202
			}
203
204
			// set read method on class
205
			$trait->setMethod(PhpMethod::create($method)
206
				->addParameter(PhpParameter::create('model'))
207
				->setBody($body)
208
				->setType('Relationship')
209
			);
210
		}
211
212
		$trait->setMethod(PhpMethod::create('getRelationships')
213
			->setBody($this->twig->render('getRelationships.twig', [
214
				'fields' => $fields
215
			]))
216
		);
217
	}
218
219
	protected function generateTypeInferencerAccess(PhpTrait $trait) {
220
		$namespace = $this->factory->getNamespaceGenerator()->getSerializerNamespace();
221
		$trait->addUseStatement($namespace . '\\TypeInferencer');
222
		$trait->setMethod(PhpMethod::create('getTypeInferencer')
223
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
224
			->setBody($this->twig->render('getTypeInferencer.twig'))
225
		);
226
	}
227
}