Completed
Push — master ( 7aeea3...5d27f2 )
by Thomas
09:03
created

ModelSerializerTraitGenerator   B

Complexity

Total Complexity 16

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Importance

Changes 9
Bugs 1 Features 1
Metric Value
wmc 16
c 9
b 1
f 1
lcom 1
cbo 16
dl 0
loc 203
rs 8.4614

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