generateToManyRelationshipRemove()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 61
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 61
rs 9.5147
c 0
b 0
f 0
cc 3
eloc 44
nc 2
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
use phootwork\lang\Text;
15
16
class ModelDomainTraitGenerator extends ReadOnlyModelDomainTraitGenerator {
17
18
	public function generate(Table $model) {
19
		$trait = parent::generate($model);
20
21
		// generate event
22
		$event = $this->generateEvent($model);
23
		$trait->addUseStatement($event->getQualifiedName());
24
		$this->generateDispatch($trait, $model);
25
26
		// generate CUD methods
27
		$this->generateNormalize($trait, $model);
28
		$this->generateHydrate($trait, $model);
29
		$this->generateCreate($trait, $model);
30
		$this->generateUpdate($trait, $model);
31
		$this->generateDelete($trait, $model);
32
33
		// generate relationship methods
34
		if (!$model->isReadOnly()) {
35
			$relationships = $this->modelService->getRelationships($model);
36
37
			foreach ($relationships->getAll() as $relationship) {
38
				switch ($relationship->getType()) {
39
					case Relationship::ONE_TO_ONE:
40
						$this->generateToOneRelationshipSet($trait, $relationship);
41
						break;
42
43
					case Relationship::ONE_TO_MANY:
44
						$this->generateToManyRelationshipAdd($trait, $relationship);
45
						$this->generateToManyRelationshipRemove($trait, $relationship);
46
						$this->generateOneToManyRelationshipUpdate($trait, $relationship);
47
						break;
48
49
					case Relationship::MANY_TO_MANY:
50
						$this->generateToManyRelationshipAdd($trait, $relationship);
51
						$this->generateToManyRelationshipRemove($trait, $relationship);
52
						$this->generateManyToManyRelationshipUpdate($trait, $relationship);
53
						break;
54
				}
55
			}
56
		}
57
58
		return $trait;
59
	}
60
61
	/**
62
	 *
63
	 * @param Table $model
64
	 * @return PhpClass
65
	 */
66
	protected function generateEvent(Table $model) {
67
		$package = $this->packageService->getPackage();
68
		$slug = $package->getKeeko()->getModule()->getSlug();
69
		$modelName = $model->getOriginCommonName();
70
71
		$class = new PhpClass();
72
		$class->setNamespace(str_replace('model', 'event', $model->getNamespace()));
73
		$class->setName($model->getPhpName() . 'Event');
74
		$class->setParentClassName('Event');
75
		if ($model->getPhpName() == 'Event') {
76
			$class->addUseStatement($model->getNamespace() . '\\' . $model->getPhpName(), 'Model');
77
		} else {
78
			$class->addUseStatement($model->getNamespace() . '\\' . $model->getPhpName());
79
		}
80
		$class->addUseStatement('Symfony\Component\EventDispatcher\Event');
81
82
		// constants
83
		$class->setConstant('PRE_CREATE', sprintf('%s.%s.pre_create', $slug, $modelName));
84
		$class->setConstant('POST_CREATE', sprintf('%s.%s.post_create', $slug, $modelName));
85
		$class->setConstant('PRE_UPDATE', sprintf('%s.%s.pre_update', $slug, $modelName));
86
		$class->setConstant('POST_UPDATE', sprintf('%s.%s.post_update', $slug, $modelName));
87
		$class->setConstant('PRE_SAVE', sprintf('%s.%s.pre_save', $slug, $modelName));
88
		$class->setConstant('POST_SAVE', sprintf('%s.%s.post_save', $slug, $modelName));
89
		$class->setConstant('PRE_DELETE', sprintf('%s.%s.pre_delete', $slug, $modelName));
90
		$class->setConstant('POST_DELETE', sprintf('%s.%s.post_delete', $slug, $modelName));
91
92
		// generate relationship constants
93
		if (!$model->isReadOnly()) {
94
			$relationships = $this->modelService->getRelationships($model);
95
96
			foreach ($relationships->getAll() as $relationship) {
97
				// one-to-one relationships
98
				if ($relationship->getType() == Relationship::ONE_TO_ONE) {
99
					$snake = NameUtils::toSnakeCase($relationship->getRelatedName());
100
					$name = strtoupper($snake);
101
					$class->setConstant('PRE_' . $name . '_UPDATE', sprintf('%s.%s.pre_%s_update', $slug, $modelName, $snake));
102
					$class->setConstant('POST_' . $name . '_UPDATE', sprintf('%s.%s.post_%s_update', $slug, $modelName, $snake));
103
				}
104
105
				// others
106
				else {
107
					$snake = NameUtils::toSnakeCase($relationship->getRelatedPluralName());
108
					$name = strtoupper($snake);
109
					$class->setConstant('PRE_' . $name . '_ADD', sprintf('%s.%s.pre_%s_add', $slug, $modelName, $snake));
110
					$class->setConstant('POST_' . $name . '_ADD', sprintf('%s.%s.post_%s_add', $slug, $modelName, $snake));
111
					$class->setConstant('PRE_' . $name . '_REMOVE', sprintf('%s.%s.pre_%s_add', $slug, $modelName, $snake));
112
					$class->setConstant('POST_' . $name . '_REMOVE', sprintf('%s.%s.post_%s_add', $slug, $modelName, $snake));
113
					$class->setConstant('PRE_' . $name . '_UPDATE', sprintf('%s.%s.pre_%s_update', $slug, $modelName, $snake));
114
					$class->setConstant('POST_' . $name . '_UPDATE', sprintf('%s.%s.post_%s_update', $slug, $modelName, $snake));
115
				}
116
			}
117
		}
118
119
		// properties
120
		$modelVariableName = $model->getCamelCaseName();
121
		$class->setProperty(PhpProperty::create($modelVariableName)
122
			->setType($model->getPackage())
123
			->setVisibility(PhpProperty::VISIBILITY_PROTECTED)
124
		);
125
126
		// constructor
127
		$type = $model->getPhpName() == 'Event' ? 'Model' : $model->getPhpName();
128
		$class->setMethod(PhpMethod::create('__construct')
129
			->addParameter(PhpParameter::create($modelVariableName)->setType($type))
130
			->setBody('$this->' . $modelVariableName . ' = $' . $modelVariableName .';')
131
		);
132
133
		// getModel()
134
		$class->setMethod(PhpMethod::create('get' . $model->getPhpName())
135
			->setType($model->getPhpName())
136
			->setBody('return $this->' . $modelVariableName .';')
137
		);
138
139
		$this->codeService->dumpStruct($class, true);
140
141
		return $class;
142
	}
143
144
	protected function generateDispatch(PhpTrait $trait, Table $model) {
145
		$trait->setMethod(PhpMethod::create('dispatch')
146
			->addParameter(PhpParameter::create('type')
147
				->setType('string')
148
			)
149
			->addParameter(PhpParameter::create('model')
150
				->setType($model->getPhpName())
151
			)
152
			->addParameter(PhpParameter::create('data')
153
				->setType('array')
154
				->setExpression('[]')
155
			)
156
			->setBody($this->twig->render('dispatch.twig', [
157
				'class' => $model->getPhpName()
158
			]))
159
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
160
		);
161
	}
162
163
	protected function generateNormalize(PhpTrait $trait, Table $model) {
164
		$modelName = $model->getOriginCommonName();
165
		$normalizer = $this->project->getGeneratorDefinition()->getNormalizer($modelName);
166
		$fields = $this->generatorDefinitionService->getWriteFields($modelName);
167
		$code = '';
168
169
		foreach ($fields as $field) {
170
			if ($normalizer->has($field)) {
171
				$class = new Text($normalizer->get($field));
172
				if (!$class->startsWith('\\')) {
173
					$class = $class->prepend('\\');
174
				}
175
				$code .= $this->twig->render('normalizer-field.twig', [
176
					'class' => $class->toString(),
177
					'field' => $field
178
				]);
179
			}
180
		}
181
182
		$body = $this->twig->render('normalizer.twig', [
183
			'code' => $code
184
		]);		
185
186
		$trait->setMethod(PhpMethod::create('normalize')
187
			->addParameter(PhpParameter::create('data')->setType('array'))
188
			->setBody($body)
189
			->setType('array', 'normalized data')
190
		);
191
	}
192
	
193
	protected function generateHydrate(PhpTrait $trait, Table $model) {
194
		$trait->addUseStatement('keeko\\framework\\utils\\HydrateUtils');
195
		$modelName = $model->getOriginCommonName();
196
		$fields = $this->generatorDefinitionService->getWriteFields($modelName);
197
		$code = '';
198
199
		foreach ($fields as $field) {
200
			$code .= sprintf("'%s'", NameUtils::dasherize($field));
201
			$code .= ', ';
202
		}
203
204
		if (strlen($code) > 0) {
205
			$code = substr($code, 0, -2);
206
		}
207
208
		$code = sprintf('[%s]', $code);
209
		$body = $this->twig->render('hydrate.twig', [
210
			'code' => $code
211
		]);
212
		
213
	
214
		$trait->setMethod(PhpMethod::create('hydrate')
215
			->addParameter(PhpParameter::create('model'))
216
			->addParameter(PhpParameter::create('data'))
217
			->setBody($body)
218
			->setType('mixed', 'The model')
219
		);
220
	}
221
222
	protected function generateCreate(PhpTrait $trait, Table $model) {
223
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Created');
224
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
225
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
226
227
		$trait->setMethod(PhpMethod::create('create')
228
			->addParameter(PhpParameter::create('data'))
229
			->setBody($this->twig->render('create.twig', [
230
				'class' => $model->getPhpName()
231
			]))
232
			->setDescription('Creates a new ' . $model->getPhpName() . ' with the provided data')
233
			->setType('PayloadInterface')
234
		);
235
	}
236
237
	protected function generateUpdate(PhpTrait $trait, Table $model) {
238
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Updated');
239
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotUpdated');
240
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
241
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
242
243
		$trait->setMethod(PhpMethod::create('update')
244
			->addParameter(PhpParameter::create('id'))
245
			->addParameter(PhpParameter::create('data'))
246
			->setBody($this->twig->render('update.twig', [
247
				'class' => $model->getPhpName()
248
			]))
249
			->setDescription('Updates a ' . $model->getPhpName() . ' with the given id' .
250
				'and the provided data')
251
			->setType('PayloadInterface')
252
		);
253
	}
254
255
	protected function generateDelete(PhpTrait $trait, Table $model) {
256
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\Deleted');
257
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotDeleted');
258
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotFound');
259
260
		$trait->setMethod(PhpMethod::create('delete')
261
			->addParameter(PhpParameter::create('id'))
262
			->setBody($this->twig->render('delete.twig', [
263
				'class' => $model->getPhpName()
264
			]))
265
			->setDescription('Deletes a ' . $model->getPhpName() . ' with the given id')
266
			->setType('PayloadInterface')
267
		);
268
	}
269
270
	protected function generateToOneRelationshipSet(PhpTrait $trait, Relationship $relationship) {
271
		$model = $relationship->getModel();
272
		$name = $relationship->getRelatedName();
273
		$trait->setMethod(PhpMethod::create('set' . $name . 'Id')
274
			->setDescription(str_replace('{foreign}', $relationship->getRelatedName(), 'Sets the {foreign} id'))
275
			->addParameter(PhpParameter::create('id'))
276
			->addParameter(PhpParameter::create('relatedId'))
277
			->setBody($this->twig->render('to-one-set.twig', [
278
				'class' => $model->getPhpName(),
279
				'related_name' => $name,
280
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedName()))
281
			]))
282
			->setType('PayloadInterface')
283
		);
284
285
		$trait->setMethod(PhpMethod::create('doSet' . $name . 'Id')
286
			->setDescription(str_replace('{foreign}', $relationship->getRelatedName(), 'Internal mechanism to set the {foreign} id'))
287
			->addParameter(PhpParameter::create('model')
288
				->setType($model->getPhpName())
289
			)
290
			->addParameter(PhpParameter::create('relatedId'))
291
			->setBody($this->twig->render('do-to-one-set.twig', [
292
				'local' => $relationship->getForeignKey()->getLocalColumn()->getPhpName()
293
			]))
294
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
295
		);
296
	}
297
298
	protected function generateToManyRelationshipAdd(PhpTrait $trait, Relationship $relationship) {
299
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
300
301
		$model = $relationship->getModel();
302
		$foreign = $relationship->getForeign();
303
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
304
		$trait->setMethod(PhpMethod::create('add' . $relationship->getRelatedPluralName())
305
			->setDescription('Adds ' . $relationship->getRelatedPluralName() . ' to ' . $model->getPhpName())
306
			->addParameter(PhpParameter::create('id'))
307
			->addParameter(PhpParameter::create('data'))
308
			->setBody($this->twig->render('to-many-add.twig', [
309
				'class' => $model->getPhpName(),
310
				'related_name' => $relationship->getRelatedPluralName(),
311
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
312
			]))
313
			->setType('PayloadInterface')
314
		);
315
316
		$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
317
		$trait->setMethod(PhpMethod::create('doAdd' . $relationship->getRelatedPluralName())
318
			->setDescription('Interal mechanism to add ' . $relationship->getRelatedPluralName() . ' to ' . $model->getPhpName())
319
			->addParameter(PhpParameter::create('model')
320
				->setType($model->getPhpName())
321
			)
322
			->addParameter(PhpParameter::create('data'))
323
			->setBody($this->twig->render('do-to-many-add.twig', [
324
				'foreign_class' => $foreign->getPhpName(),
325
				'method_name' => $methodNameGenerator->generateMethodName($relationship)
326
			]))
327
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
328
		);
329
330
		// reflexive add method on many-to-many relationship
331
		if ($relationship->getType() == Relationship::MANY_TO_MANY && $relationship->isReflexive()) {
332
			$trait->setMethod(PhpMethod::create('add' . $relationship->getReverseRelatedPluralName())
333
				->setDescription('Adds ' . $relationship->getReverseRelatedPluralName() . ' to ' . $model->getPhpName())
334
				->addParameter(PhpParameter::create('id'))
335
				->addParameter(PhpParameter::create('data'))
336
				->setBody($this->twig->render('to-many-add.twig', [
337
					'class' => $model->getPhpName(),
338
					'related_name' => $relationship->getReverseRelatedPluralName(),
339
					'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
340
				]))
341
				->setType('PayloadInterface')
342
			);
343
344
			$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
345
			$trait->setMethod(PhpMethod::create('doAdd' . $relationship->getReverseRelatedPluralName())
346
				->setDescription('Interal mechanism to add ' . $relationship->getReverseRelatedPluralName() . ' to ' . $model->getPhpName())
347
				->addParameter(PhpParameter::create('model')
348
					->setType($model->getPhpName())
349
				)
350
				->addParameter(PhpParameter::create('data'))
351
				->setBody($this->twig->render('do-to-many-add.twig', [
352
					'foreign_class' => $foreign->getPhpName(),
353
					'method_name' => $methodNameGenerator->generateReverseMethodName($relationship)
354
				]))
355
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
356
			);
357
		}
358
	}
359
360
	protected function generateToManyRelationshipRemove(PhpTrait $trait, Relationship $relationship) {
361
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
362
363
		$model = $relationship->getModel();
364
		$foreign = $relationship->getForeign();
365
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
366
		$trait->setMethod(PhpMethod::create('remove' . $relationship->getRelatedPluralName())
367
			->setDescription('Removes ' . $relationship->getRelatedPluralName() . ' from ' . $model->getPhpName())
368
			->addParameter(PhpParameter::create('id'))
369
			->addParameter(PhpParameter::create('data'))
370
			->setBody($this->twig->render('to-many-remove.twig', [
371
				'class' => $model->getPhpName(),
372
				'related_name' => $relationship->getRelatedPluralName(),
373
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
374
			]))
375
			->setType('PayloadInterface')
376
		);
377
378
		$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
379
		$trait->setMethod(PhpMethod::create('doRemove' . $relationship->getRelatedPluralName())
380
			->setDescription('Interal mechanism to remove ' . $relationship->getRelatedPluralName() . ' from ' . $model->getPhpName())
381
			->addParameter(PhpParameter::create('model')
382
				->setType($model->getPhpName())
383
				)
384
			->addParameter(PhpParameter::create('data'))
385
			->setBody($this->twig->render('do-to-many-remove.twig', [
386
				'foreign_class' => $foreign->getPhpName(),
387
				'method_name' => $methodNameGenerator->generateMethodName($relationship)
388
			]))
389
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
390
		);
391
392
		// reflexive remove method on many-to-many relationship
393
		if ($relationship->getType() == Relationship::MANY_TO_MANY && $relationship->isReflexive()) {
394
			$trait->setMethod(PhpMethod::create('remove' . $relationship->getReverseRelatedPluralName())
395
				->setDescription('Removes ' . $relationship->getReverseRelatedPluralName() . ' from ' . $model->getPhpName())
396
				->addParameter(PhpParameter::create('id'))
397
				->addParameter(PhpParameter::create('data'))
398
				->setBody($this->twig->render('to-many-remove.twig', [
399
					'class' => $model->getPhpName(),
400
					'related_name' => $relationship->getReverseRelatedPluralName(),
401
					'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
402
				]))
403
				->setType('PayloadInterface')
404
			);
405
406
			$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
407
			$trait->setMethod(PhpMethod::create('doRemove' . $relationship->getReverseRelatedPluralName())
408
				->setDescription('Interal mechanism to remove ' . $relationship->getReverseRelatedPluralName() . ' from ' . $model->getPhpName())
409
				->addParameter(PhpParameter::create('model')
410
					->setType($model->getPhpName())
411
				)
412
				->addParameter(PhpParameter::create('data'))
413
				->setBody($this->twig->render('do-to-many-remove.twig', [
414
					'foreign_class' => $foreign->getPhpName(),
415
					'method_name' => $methodNameGenerator->generateMethodName($relationship)
416
				]))
417
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
418
			);
419
		}
420
	}
421
422
	protected function generateOneToManyRelationshipUpdate(PhpTrait $trait, OneToManyRelationship $relationship) {
423
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
424
		$trait->addUseStatement('keeko\\framework\\exceptions\\ErrorsException');
425
426
		$model = $relationship->getModel();
427
		$foreign = $relationship->getForeign();
428
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
429
		$trait->setMethod(PhpMethod::create('update' . $relationship->getRelatedPluralName())
430
			->setDescription('Updates ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
431
			->addParameter(PhpParameter::create('id'))
432
			->addParameter(PhpParameter::create('data'))
433
			->setBody($this->twig->render('one-to-many-update.twig', [
434
				'class' => $model->getPhpName(),
435
				'related_name' => $relationship->getRelatedPluralName(),
436
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
437
			]))
438
			->setType('PayloadInterface')
439
		);
440
441
		$trait->setMethod(PhpMethod::create('doUpdate' . $relationship->getRelatedPluralName())
442
			->setDescription('Internal update mechanism of ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
443
			->addParameter(PhpParameter::create('model')
444
				->setType($model->getPhpName())
445
			)
446
			->addParameter(PhpParameter::create('data'))
447
			->setBody($this->twig->render('do-one-to-many-update.twig', [
448
				'related' => $relationship->getRelatedName(),
449
				'reverse_related' => $relationship->getReverseRelatedName(),
450
				'foreign_class' => $foreign->getPhpName()
451
			]))
452
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
453
		);
454
	}
455
456
	protected function generateManyToManyRelationshipUpdate(PhpTrait $trait, ManyToManyRelationship $relationship) {
457
		$trait->addUseStatement('keeko\\framework\\domain\\payload\\NotValid');
458
		$trait->addUseStatement('keeko\\framework\\exceptions\\ErrorsException');
459
460
		$model = $relationship->getModel();
461
		$foreign = $relationship->getForeign();
462
		$middle = $relationship->getMiddle();
463
		$trait->addUseStatement($middle->getNamespace() . '\\' . $middle->getPhpName() . 'Query');
464
		$trait->addUseStatement($foreign->getNamespace() . '\\' . $foreign->getPhpName() . 'Query');
465
		$trait->setMethod(PhpMethod::create('update' . $relationship->getRelatedPluralName())
466
			->setDescription('Updates ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
467
			->addParameter(PhpParameter::create('id'))
468
			->addParameter(PhpParameter::create('data'))
469
			->setBody($this->twig->render('many-to-many-update.twig', [
470
				'class' => $model->getPhpName(),
471
				'related_name' => $relationship->getRelatedPluralName(),
472
				'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
473
			]))
474
			->setType('PayloadInterface')
475
		);
476
477
		$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
478
		$trait->setMethod(PhpMethod::create('doUpdate' . $relationship->getRelatedPluralName())
479
			->setDescription('Internal update mechanism of ' . $relationship->getRelatedPluralName() . ' on ' . $model->getPhpName())
480
			->addParameter(PhpParameter::create('model')
481
				->setType($model->getPhpName())
482
			)
483
			->addParameter(PhpParameter::create('data'))
484
			->setBody($this->twig->render('do-many-to-many-update.twig', [
485
				'method_name' => $methodNameGenerator->generateMethodName($relationship),
486
				'reverse_related' => $methodNameGenerator->generateReverseMethodName($relationship),
487
				'foreign_class' => $foreign->getPhpName(),
488
				'middle_class' => $middle->getPhpName(),
489
			]))
490
			->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
491
		);
492
493
		// reflexive update methods
494
		if ($relationship->isReflexive()) {
495
			$trait->setMethod(PhpMethod::create('update' . $relationship->getReverseRelatedPluralName())
496
				->setDescription('Updates ' . $relationship->getReverseRelatedPluralName() . ' on ' . $model->getPhpName())
497
				->addParameter(PhpParameter::create('id'))
498
				->addParameter(PhpParameter::create('data'))
499
				->setBody($this->twig->render('many-to-many-update.twig', [
500
					'class' => $model->getPhpName(),
501
					'related_name' => $relationship->getReverseRelatedName(),
502
					'const' => strtoupper(NameUtils::toSnakeCase($relationship->getRelatedPluralName()))
503
				]))
504
				->setType('PayloadInterface')
505
			);
506
507
			$methodNameGenerator = $this->factory->getRelationshipMethodNameGenerator();
508
			$trait->setMethod(PhpMethod::create('doUpdate' . $relationship->getReverseRelatedPluralName())
509
				->setDescription('Internal update mechanism of ' . $relationship->getReverseRelatedPluralName() . ' on ' . $model->getPhpName())
510
				->addParameter(PhpParameter::create('model')
511
					->setType($model->getPhpName())
512
				)
513
				->addParameter(PhpParameter::create('data'))
514
				->setBody($this->twig->render('do-many-to-many-update.twig', [
515
					'method_name' => $methodNameGenerator->generateReverseMethodName($relationship),
516
					'reverse_related' => $methodNameGenerator->generateMethodName($relationship),
517
					'foreign_class' => $foreign->getPhpName(),
518
					'middle_class' => $middle->getPhpName(),
519
				]))
520
				->setVisibility(PhpMethod::VISIBILITY_PROTECTED)
521
			);
522
		}
523
	}
524
}
525