Completed
Push — master ( 5d27f2...d6c5c0 )
by Thomas
08:45
created

ModelSerializerTraitGenerator   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 10
Bugs 1 Features 1
Metric Value
wmc 16
c 10
b 1
f 1
lcom 1
cbo 15
dl 0
loc 206
rs 9.1666

5 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 12 1
A generateIdentifyingMethods() 0 18 1
B generateAttributeMethods() 0 41 4
B generateHydrateMethod() 0 47 5
B generateRelationshipMethods() 0 76 5
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 Propel\Generator\Model\Table;
10
use keeko\tools\model\Relationship;
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
		$class = new PhpTrait($fqcn);
23
		
24
		$this->generateIdentifyingMethods($class, $model);
25
		$this->generateAttributeMethods($class, $model);
26
		$this->generateHydrateMethod($class, $model);
27
		$this->generateRelationshipMethods($class, $model);
28
		
29
		return $class;
30
	}
31
	
32
	protected function generateIdentifyingMethods(PhpTrait $class, Table $model) {
33
		$package = $this->packageService->getPackage();
34
		$type = sprintf('%s/%s', $package->getKeeko()->getModule()->getSlug(), NameUtils::dasherize($model->getOriginCommonName()));
35
		
36
		$class->setMethod(PhpMethod::create('getId')
37
			->addParameter(PhpParameter::create('model'))
38
			->setBody($this->twig->render('getId.twig'))
39
			->setType('string')
40
		);
41
		
42
		$class->setMethod(PhpMethod::create('getType')
43
			->addParameter(PhpParameter::create('model'))
44
			->setBody($this->twig->render('getType.twig', [
45
				'type' => $type
46
			]))
47
			->setType('string')
48
		);
49
	}
50
	
51
	protected function generateAttributeMethods(PhpTrait $class, Table $model) {
52
		$readFields = $this->codegenService->getReadFields($model->getOriginCommonName());
53
		$attrs = '';
54
		
55
		foreach ($readFields as $field) {
56
			$col = $model->getColumn($field);
57
			$param = $col->isTemporalType() ? '\DateTime::ISO8601' : '';
58
			$attrs .= sprintf("\t'%s' => \$model->get%s(%s),\n", 
59
				NameUtils::dasherize($field), $col->getPhpName(), $param
60
			);
61
		}
62
		
63
		if (count($field) > 0) {
0 ignored issues
show
Bug introduced by
The variable $field seems to be defined by a foreach iteration on line 55. 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...
64
			$attrs = substr($attrs, 0, -1);
65
		}
66
		
67
		$class->setMethod(PhpMethod::create('getAttributes')
68
			->addParameter(PhpParameter::create('model'))
69
			->addParameter(PhpParameter::create('fields')->setType('array')->setDefaultValue(null))
70
			->setBody($this->twig->render('getAttributes.twig', [
71
				'attrs' => $attrs
72
			]))
73
		);
74
		
75
		$class->setMethod(PhpMethod::create('getSortFields')
76
			->setBody($this->twig->render('getFields.twig', [
77
				'fields' => $this->codegenService->arrayToCode(array_map(function ($field) {
78
					return NameUtils::dasherize($field);
79
				}, $readFields))
80
			]))
81
		);
82
		
83
		$readFields = $this->codegenService->getReadFields($model->getOriginCommonName());
84
		$class->setMethod(PhpMethod::create('getFields')
85
			->setBody($this->twig->render('getFields.twig', [
86
				'fields' => $this->codegenService->arrayToCode(array_map(function ($field) {
87
					return NameUtils::dasherize($field);
88
				}, $readFields))
89
			]))
90
		);
91
	}
92
93
	protected function generateHydrateMethod(PhpTrait $trait, Table $model) {
94
		if ($model->isReadOnly()) {
95
			$body = $this->twig->render('hydrate-readonly.twig');
96
		} else {
97
			$trait->addUseStatement('keeko\\framework\\utils\\HydrateUtils');
98
			$modelName = $model->getOriginCommonName();
99
			$normalizer = $this->codegenService->getCodegen()->getNormalizer($modelName);
0 ignored issues
show
Bug introduced by
The method getNormalizer() does not seem to exist on object<keeko\framework\schema\CodegenSchema>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
100
			$fields = $this->codegenService->getWriteFields($modelName);
101
			$code = '';
102
			
103
			foreach ($fields as $field) {
104
				$code .= sprintf("'%s'", NameUtils::dasherize($field));
105
				if ($normalizer->has($field)) {
106
					$code .= $this->twig->render('normalizer.twig', [
107
						'class' => $normalizer->get($field)
108
					]);
109
				}
110
		
111
				$code .= ', ';
112
			}
113
			
114
			if (strlen($code) > 0) {
115
				$code = substr($code, 0, -2);
116
			}
117
			
118
			$code = sprintf('[%s]', $code);
119
			$body = $this->twig->render('hydrate.twig', [
120
				'code' => $code,
121
				'normalizer' => $normalizer->size() > 0
122
			]);
123
			
124
			$trait->setMethod(PhpMethod::create('hydrateRelationships')
125
				->addParameter(PhpParameter::create('model'))
126
				->addParameter(PhpParameter::create('data'))
127
				->setAbstract(true)
128
				->setType('void')
129
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
130
			);
131
		}
132
		
133
		$trait->setMethod(PhpMethod::create('hydrate')
134
			->addParameter(PhpParameter::create('model'))
135
			->addParameter(PhpParameter::create('data'))
136
			->setBody($body)
137
			->setType('mixed', 'The model')
138
		);
139
	}
140
	
141
	protected function generateRelationshipMethods(PhpTrait $class, Table $model) {
142
		if ($model->isReadOnly()) {
143
			return;
144
		}
145
146
		$fields = [];
147
		$relationships = $this->modelService->getRelationships($model);
148
		
149
		if ($relationships->size() > 0) {
150
			$class->addUseStatement('Tobscure\\JsonApi\\Relationship');
151
			$class->setMethod(PhpMethod::create('addRelationshipSelfLink')
152
				->addParameter(PhpParameter::create('relationship')
153
					->setType('Relationship')
154
				)
155
				->addParameter(PhpParameter::create('model')
156
					->setType('mixed')
157
				)
158
				->addParameter(PhpParameter::create('related')
159
					->setType('string')
160
				)
161
				->setAbstract(true)
162
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
163
				->setType('Relationship')
164
			);
165
		}
166
		
167
		foreach ($relationships->getAll() as $rel) {
168
			// one-to-one
169
			if ($rel->getType() == Relationship::ONE_TO_ONE) {
170
				$foreign = $rel->getForeign();
171
				$relatedName = $rel->getRelatedName();
172
				$typeName = $rel->getRelatedTypeName();
173
				$method = NameUtils::toCamelCase($relatedName);
174
				$fields[$typeName] = $foreign->getPhpName() . '::getSerializer()->getType(null)';
175
				$class->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName());
176
				$class->addUseStatement('Tobscure\\JsonApi\\Resource');
177
			
178
				// read
179
				$body = $this->twig->render('to-one-read.twig', [
180
					'class' => $foreign->getPhpName(),
181
					'related' => $relatedName,
182
					'related_type' => $typeName
183
				]);
184
			}
185
		
186
			// ?-to-many
187
			else {
188
				$foreign = $rel->getForeign();
189
				$typeName = $rel->getRelatedPluralTypeName();
190
				$method = NameUtils::toCamelCase($rel->getRelatedPluralName());
191
				$fields[$typeName] = $foreign->getPhpName() . '::getSerializer()->getType(null)';
192
				$class->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName());
193
				$class->addUseStatement('Tobscure\\JsonApi\\Collection');
194
				
195
				// read
196
				$body = $this->twig->render('to-many-read.twig', [
197
					'class' => $foreign->getPhpName(),
198
					'related' => $rel->getRelatedPluralName(),
199
					'related_type' => $rel->getRelatedTypeName()
200
				]);
201
			}
202
			
203
			// set read method on class
204
			$class->setMethod(PhpMethod::create($method)
205
				->addParameter(PhpParameter::create('model'))
206
				->setBody($body)
207
				->setType('Relationship')
208
			);
209
		}
210
		
211
		$class->setMethod(PhpMethod::create('getRelationships')
212
			->setBody($this->twig->render('getRelationships.twig', [
213
				'fields' => $fields
214
			]))
215
		);
216
	}
217
}