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

generateManyToManyRelationshipUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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