Completed
Push — master ( c5048d...43a701 )
by Thomas
06:21
created

ModelDomainTraitGenerator::generateDispatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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