Completed
Push — master ( c7b947...966759 )
by Thomas
08:09
created

generateOneToManyRelationshipUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 22
rs 9.2
cc 1
eloc 18
nc 1
nop 2
1
<?php
2
namespace keeko\tools\generator\domain\base;
3
4
use gossi\codegen\model\PhpClass;
5
use gossi\codegen\model\PhpMethod;
6
use gossi\codegen\model\PhpParameter;
7
use gossi\codegen\model\PhpProperty;
8
use gossi\codegen\model\PhpTrait;
9
use keeko\framework\utils\NameUtils;
10
use keeko\tools\model\Relationship;
11
use Propel\Generator\Model\Table;
12
use keeko\tools\model\ManyToManyRelationship;
13
use keeko\tools\model\OneToManyRelationship;
14
15
class ModelDomainTraitGenerator extends ReadOnlyModelDomainTraitGenerator {
16
	
17
	public function generate(Table $model) {
18
		$trait = parent::generate($model);
19
		
20
		// generate event
21
		$event = $this->generateEvent($model);
22
		$trait->addUseStatement($event->getQualifiedName());
23
24
		// generate CUD methods
25
		$this->generateCreate($trait, $model);
26
		$this->generateUpdate($trait, $model);
27
		$this->generateDelete($trait, $model);
28
29
		// generate relationship methods
30
		if (!$model->isReadOnly()) {
31
			$relationships = $this->modelService->getRelationships($model);
32
			
33
			foreach ($relationships->getAll() as $relationship) {
34
				switch ($relationship->getType()) {
35
					case Relationship::ONE_TO_ONE:
36
						$this->generateToOneRelationshipSet($trait, $relationship);
37
						break;
38
						
39
					case Relationship::ONE_TO_MANY:
40
						$this->generateToManyRelationshipAdd($trait, $relationship);
41
						$this->generateToManyRelationshipRemove($trait, $relationship);
42
						$this->generateOneToManyRelationshipUpdate($trait, $relationship);
43
						break;
44
					
45
					case Relationship::MANY_TO_MANY:
46
						$this->generateToManyRelationshipAdd($trait, $relationship);
47
						$this->generateToManyRelationshipRemove($trait, $relationship);
48
						$this->generateManyToManyRelationshipUpdate($trait, $relationship);
49
						break;
50
				}
51
			}
52
		}
53
54
		return $trait;
55
	}
56
	
57
	/**
58
	 * 
59
	 * @param Table $model
60
	 * @return PhpClass
61
	 */
62
	protected function generateEvent(Table $model) {
63
		$package = $this->packageService->getPackage();
64
		$slug = $package->getKeeko()->getModule()->getSlug();
65
		$modelName = $model->getOriginCommonName();
66
		
67
		$class = new PhpClass();
68
		$class->setNamespace(str_replace('model', 'event', $model->getNamespace()));
69
		$class->setName($model->getPhpName() . 'Event');
70
		$class->setParentClassName('Event');
71
		$class->addUseStatement($model->getNamespace() . '\\' . $model->getPhpName());
72
		$class->addUseStatement('Symfony\Component\EventDispatcher\Event');
73
		
74
		// constants
75
		$class->setConstant('PRE_CREATE', sprintf('%s.%s.pre_create', $slug, $modelName));
76
		$class->setConstant('POST_CREATE', sprintf('%s.%s.post_create', $slug, $modelName));
77
		$class->setConstant('PRE_UPDATE', sprintf('%s.%s.pre_update', $slug, $modelName));
78
		$class->setConstant('POST_UPDATE', sprintf('%s.%s.post_update', $slug, $modelName));
79
		$class->setConstant('PRE_SAVE', sprintf('%s.%s.pre_save', $slug, $modelName));
80
		$class->setConstant('POST_SAVE', sprintf('%s.%s.post_save', $slug, $modelName));
81
		$class->setConstant('PRE_DELETE', sprintf('%s.%s.pre_delete', $slug, $modelName));
82
		$class->setConstant('POST_DELETE', sprintf('%s.%s.post_delete', $slug, $modelName));
83
		
84
		// generate relationship constants
85
		if (!$model->isReadOnly()) {
86
			$relationships = $this->modelService->getRelationships($model);
87
			
88
			foreach ($relationships->getAll() as $relationship) {
89
				// one-to-one relationships
90
				if ($relationship->getType() == Relationship::ONE_TO_ONE) {
91
					$snake = NameUtils::toSnakeCase($relationship->getRelatedName());
92
					$name = strtoupper($snake);
93
					$class->setConstant('PRE_' . $name . '_UPDATE', sprintf('%s.%s.pre_%s_update', $slug, $modelName, $snake));
94
					$class->setConstant('POST_' . $name . '_UPDATE', sprintf('%s.%s.post_%s_update', $slug, $modelName, $snake));
95
				}
96
				
97
				// others
98
				else {
99
					$snake = NameUtils::toSnakeCase($relationship->getRelatedPluralName());
100
					$name = strtoupper($snake);
101
					$class->setConstant('PRE_' . $name . '_ADD', sprintf('%s.%s.pre_%s_add', $slug, $modelName, $snake));
102
					$class->setConstant('POST_' . $name . '_ADD', sprintf('%s.%s.post_%s_add', $slug, $modelName, $snake));
103
					$class->setConstant('PRE_' . $name . '_REMOVE', sprintf('%s.%s.pre_%s_add', $slug, $modelName, $snake));
104
					$class->setConstant('POST_' . $name . '_REMOVE', sprintf('%s.%s.post_%s_add', $slug, $modelName, $snake));
105
					$class->setConstant('PRE_' . $name . '_UPDATE', sprintf('%s.%s.pre_%s_update', $slug, $modelName, $snake));
106
					$class->setConstant('POST_' . $name . '_UPDATE', sprintf('%s.%s.post_%s_update', $slug, $modelName, $snake));
107
				}
108
			}
109
		}
110
		
111
		// properties
112
		$modelVariableName = $model->getCamelCaseName();
113
		$class->setProperty(PhpProperty::create($modelVariableName)
114
			->setType($model->getPackage())
115
			->setVisibility(PhpProperty::VISIBILITY_PROTECTED)
116
		);
117
		
118
		// constructor
119
		$class->setMethod(PhpMethod::create('__construct')
120
			->addParameter(PhpParameter::create($modelVariableName)->setType($model->getPhpName()))
121
			->setBody('$this->' . $modelVariableName . ' = $' . $modelVariableName .';')
122
		);
123
		
124
		// getModel()
125
		$class->setMethod(PhpMethod::create('get' . $model->getPhpName())
126
			->setType($model->getPhpName())
127
			->setBody('return $this->' . $modelVariableName .';')
128
		);
129
		
130
		$this->codegenService->dumpStruct($class, true);
131
		
132
		return $class;
133
	}
134
	
135
	protected function generateCreate(PhpTrait $trait, Table $model) {
136
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Created');
137
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
138
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
139
	
140
		$trait->setMethod(PhpMethod::create('create')
141
			->addParameter(PhpParameter::create('data'))
142
			->setBody($this->twig->render('create.twig', [
143
				'model' => NameUtils::toCamelCase($model->getOriginCommonName()),
144
				'class' => $model->getPhpName()
145
			]))
146
			->setDescription('Creates a new ' . $model->getPhpName() . ' with the provided data')
147
			->setType('PayloadInterface')
148
		);
149
	}
150
	
151
	protected function generateUpdate(PhpTrait $trait, Table $model) {
152
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Updated');
153
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotUpdated');
154
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
155
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
156
		
157
		$trait->setMethod(PhpMethod::create('update')
158
			->addParameter(PhpParameter::create('id'))
159
			->addParameter(PhpParameter::create('data'))
160
			->setBody($this->twig->render('update.twig', [
161
				'model' => NameUtils::toCamelCase($model->getOriginCommonName()),
162
				'class' => $model->getPhpName()
163
			]))
164
			->setDescription('Updates a ' . $model->getPhpName() . ' with the given id' .
165
				'and the provided data')
166
			->setType('PayloadInterface')
167
		);
168
	}
169
	
170
	protected function generateDelete(PhpTrait $trait, Table $model) {
171
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Deleted');
172
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotDeleted');
173
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
174
		
175
		$trait->setMethod(PhpMethod::create('delete')
176
			->addParameter(PhpParameter::create('id'))
177
			->setBody($this->twig->render('delete.twig', [
178
				'model' => NameUtils::toCamelCase($model->getOriginCommonName()),
179
				'class' => $model->getPhpName()
180
			]))
181
			->setDescription('Deletes a ' . $model->getPhpName() . ' with the given id')
182
			->setType('PayloadInterface')
183
		);
184
	}
185
	
186
	protected function generateToOneRelationshipSet(PhpTrait $trait, Relationship $relationship) {
187
		$model = $relationship->getModel();
188
		$name = $relationship->getRelatedName();
189
		$localId = NameUtils::toCamelCase($name) . 'Id';
190
		$trait->setMethod(PhpMethod::create('set' . $name . 'Id')
191
			->setDescription(str_replace('{foreign}', $relationship->getRelatedName(), 'Sets the {foreign} id'))
192
			->addParameter(PhpParameter::create('id'))
193
			->addParameter(PhpParameter::create($localId))
194
			->setBody($this->twig->render('to-one-set.twig', [
195
				'model' => NameUtils::toCamelCase($model->getOriginCommonName()),
196
				'class' => $model->getPhpName(),
197
				'fk_id' => $localId,
198
				'local' => $relationship->getForeignKey()->getLocalColumn()->getPhpName(),
199
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedName()))
200
			]))
201
			->setType('PayloadInterface')
202
		);
203
	}
204
	
205
	protected function generateToManyRelationshipAdd(PhpTrait $trait, Relationship $relationship) {
206
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
207
		
208
		$model = $relationship->getModel();
209
		$foreign = $relationship->getForeign();
210
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
211
		$trait->setMethod(PhpMethod::create('add' . $relationship->getRelatedPluralName())
212
			->setDescription('Adds ' . $relationship->getRelatedPluralName() . ' to ' . $model->getPhpName())
213
			->addParameter(PhpParameter::create('id'))
214
			->addParameter(PhpParameter::create('data'))
215
			->setBody($this->twig->render('to-many-add.twig', [
216
				'model' => $model->getCamelCaseName(),
217
				'class' => $model->getPhpName(),			
218
				'related' => $relationship->getRelatedName(),
219
				'foreign_model' => $foreign->getCamelCaseName(),
220
				'foreign_class' => $foreign->getPhpName(),
221
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
222
			]))
223
			->setType('PayloadInterface')
224
		);
225
	}
226
	
227
	protected function generateToManyRelationshipRemove(PhpTrait $trait, Relationship $relationship) {
228
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
229
		
230
		$model = $relationship->getModel();
231
		$foreign = $relationship->getForeign();
232
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
233
		$trait->setMethod(PhpMethod::create('remove' . $relationship->getRelatedPluralName())
234
			->setDescription('Removes ' . $relationship->getRelatedPluralName() . ' from ' . $model->getPhpName())
235
			->addParameter(PhpParameter::create('id'))
236
			->addParameter(PhpParameter::create('data'))
237
			->setBody($this->twig->render('to-many-remove.twig', [
238
				'model' => $model->getCamelCaseName(),
239
				'class' => $model->getPhpName(),
240
				'related' => $relationship->getRelatedName(),
241
				'foreign_model' => $foreign->getCamelCaseName(),
242
				'foreign_class' => $foreign->getPhpName(),
243
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
244
			]))
245
			->setType('PayloadInterface')
246
		);
247
	}
248
	
249
	protected function generateOneToManyRelationshipUpdate(PhpTrait $trait, OneToManyRelationship $relationship) {
250
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
251
	
252
		$model = $relationship->getModel();
253
		$foreign = $relationship->getForeign();
254
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
255
		$trait->setMethod(PhpMethod::create('update' . $relationship->getRelatedPluralName())
256
			->setDescription('Updates ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
257
			->addParameter(PhpParameter::create('id'))
258
			->addParameter(PhpParameter::create('data'))
259
			->setBody($this->twig->render('one-to-many-update.twig', [
260
				'model' => $model->getCamelCaseName(),
261
				'class' => $model->getPhpName(),
262
				'related' => $relationship->getRelatedName(),
263
				'reverse_related' => $relationship->getReverseRelatedName(),
264
				'foreign_model' => $foreign->getCamelCaseName(),
265
				'foreign_class' => $foreign->getPhpName(),
266
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
267
			]))
268
			->setType('PayloadInterface')
269
		);
270
	}
271
	
272
	protected function generateManyToManyRelationshipUpdate(PhpTrait $trait, ManyToManyRelationship $relationship) {
273
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
274
	
275
		$model = $relationship->getModel();
276
		$foreign = $relationship->getForeign();
277
		$middle = $relationship->getMiddle();
278
		$trait->addUseStatement($middle->getNamespace() . '\\' . $middle->getPhpName() . 'Query');
279
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
280
		$trait->setMethod(PhpMethod::create('update' . $relationship->getRelatedPluralName())
281
			->setDescription('Updates ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
282
			->addParameter(PhpParameter::create('id'))
283
			->addParameter(PhpParameter::create('data'))
284
			->setBody($this->twig->render('many-to-many-update.twig', [
285
				'model' => $model->getCamelCaseName(),
286
				'class' => $model->getPhpName(),
287
				'related' => $relationship->getRelatedName(),
288
				'reverse_related' => $relationship->getReverseRelatedName(),
289
				'foreign_model' => $foreign->getCamelCaseName(),
290
				'foreign_class' => $foreign->getPhpName(),
291
				'middle_class' => $middle->getPhpName(),
292
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
293
			]))
294
			->setType('PayloadInterface')
295
		);
296
	}
297
}