EmberModelGenerator::generateRelationships()   C
last analyzed

Complexity

Conditions 8
Paths 18

Size

Total Lines 36
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 26
nc 18
nop 2
1
<?php
2
namespace keeko\tools\generator\ember;
3
4
use keeko\framework\utils\NameUtils;
5
use keeko\tools\model\Relationship;
6
use phootwork\collection\Set;
7
use Propel\Generator\Model\Table;
8
use keeko\framework\schema\GeneratorDefinitionSchema;
9
10
class EmberModelGenerator extends AbstractEmberGenerator {
11
12
	public function generate(Table $model) {
13
		$class = new EmberClassGenerator('Model');
14
		$class->addImport('Model', 'ember-data/model');
15
		$class->addImport('attr', 'ember-data/attr');
16
17
		// columns
18
		$this->generateColumns($class, $model);
19
20
		// relationships
21
		$this->generateRelationships($class, $model);
22
23
		return $class->generate();
24
	}
25
26
	protected function generateColumns(EmberClassGenerator $class, Table $model) {
27
		$generator = $this->prj->getGeneratorDefinition();
28
		$filter = $this->getColumnFilter($generator, $model);
29
		foreach ($model->getColumns() as $col) {
30
			if (in_array($col, $filter)) {
31
				continue;
32
			}
33
34
			if ($col->isForeignKey() || $col->isPrimaryKey()) {
35
				continue;
36
			}
37
38
			$prop = NameUtils::toCamelCase($col->getPhpName());
39
			$default = null;
40
41
			switch ($col->getType()) {
42
				case 'NUMERIC':
43
				case 'DECIMAL':
44
				case 'TINYINT':
45
				case 'SMALLINT':
46
				case 'INTEGER':
47
				case 'BIGINT':
48
				case 'REAL':
49
				case 'FLOAT':
50
				case 'DOUBLE':
51
					$type = 'number';
52
					$defaultValue = $col->getDefaultValueString();
53
					if ($defaultValue != '0' && $defaultValue != 'null') {
54
						$default = $defaultValue;
55
					}
56
					break;
57
58
				case 'BOOLEAN':
59
					$type = 'boolean';
60
					$defaultValue = $col->getDefaultValueString();
61
					if ($defaultValue == 'false' || $defaultValue == 'true') {
62
						$default = $defaultValue;
63
					}
64
					break;
65
66
				case 'TIMESTAMP':
67
					$type = 'date';
68
					break;
69
70
				default:
71
					$type = 'string';
72
					$defaultValue = $col->getDefaultValueString();
73
					if ($defaultValue != 'null') {
74
						$default = $defaultValue;
75
					}
76
			}
77
78
			$value = sprintf('attr(\'%s\'%s)', $type,
79
				$default !== null ? ', {defaultValue: ' . $default . '}' : '');
80
81
			$class->setProperty($prop, $value);
82
		}
83
	}
84
85
	protected function generateRelationships(EmberClassGenerator $class, Table $model) {
86
		$relationships = $this->modelService->getRelationships($model);
87
		$imports = new Set();
88
		$inverses = $this->collectInverseRelationships($model);
89
90
		foreach ($relationships->getAll() as $relationship) {
91
			$type = NameUtils::dasherize($relationship->getForeign()->getOriginCommonName());
92
			$slug = $this->getSlug($relationship->getForeign());
93
94
			if ($relationship->getType() == Relationship::ONE_TO_ONE) {
95
				$prop = NameUtils::toCamelCase($relationship->getRelatedName());
96
				$inverse = isset($inverses[$prop]) ? ', {inverse: ' . $inverses[$prop] . '}' : '';
97
				$value = sprintf('belongsTo(\'%s/%s\'%s)', $slug, $type, $inverse);
98
				$imports->add('belongsTo');
99
			} else {
100
				$prop = NameUtils::toCamelCase($relationship->getRelatedPluralName());
101
				$inverse = isset($inverses[$prop]) ? ', {inverse: ' . $inverses[$prop] . '}' : '';
102
				$value = sprintf('hasMany(\'%s/%s\'%s)', $slug, $type, $inverse);
103
				$imports->add('hasMany');
104
			}
105
106
			$class->setProperty($prop, $value);
107
108
			if ($relationship->getType() == Relationship::MANY_TO_MANY && $relationship->isReflexive()) {
109
				$inverse = NameUtils::toCamelCase($relationship->getRelatedPluralName());
110
				$prop = NameUtils::toCamelCase($relationship->getReverseRelatedPluralTypeName());
111
				$value = sprintf('hasMany(\'%s/%s\', {inverse: \'%s\'})', $slug, $type, $inverse);
112
				$class->setProperty($prop, $value);
113
			}
114
		}
115
116
		if ($imports->size() > 0) {
117
			$import = sprintf('{ %s }', implode(', ', $imports->toArray()));
118
			$class->addImport($import, 'ember-data/relationships');
119
		}
120
	}
121
122
	private function collectInverseRelationships(Table $model) {
123
		$relationships = $this->modelService->getRelationships($model);
124
		$inverses = [];
125
126
		// find reflexive relationships
127
		foreach ($relationships->getAll() as $relationship) {
128
129
			// find reflexive one-to-many relationships
130
			if ($relationship->getType() == Relationship::ONE_TO_MANY && $relationship->isReflexive()) {
131
				$prop = NameUtils::toCamelCase($relationship->getRelatedPluralName());
132
				$inverses[$prop] = '\'' . NameUtils::toCamelCase($relationship->getReverseRelatedName()) . '\'';
133
134
				// reverse inverse
135
				$prop = NameUtils::toCamelCase($relationship->getReverseRelatedName());
136
				$inverses[$prop] = '\'' . NameUtils::toCamelCase($relationship->getRelatedPluralName()) . '\'';
137
			}
138
139
			// find reflexive many-to-many relationships
140
			if ($relationship->getType() == Relationship::MANY_TO_MANY && $relationship->isReflexive()) {
141
				$prop = NameUtils::toCamelCase($relationship->getRelatedPluralName());
142
				$inverses[$prop] = '\''.NameUtils::toCamelCase($relationship->getReverseRelatedPluralName()) . '\'';
143
			}
144
		}
145
146
// 		$dupes = [];
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
147
		foreach ($relationships->getAll() as $relationship) {
148
			$rels = $this->modelService->getRelationships($relationship->getForeign());
149
150
			// find null inverse one-to-one relationships
151
			foreach ($rels->getOneToOne() as $rel) {
152
				if ($rel->getForeign() == $model) {
153
					$prop = NameUtils::toCamelCase($relationship->getRelatedName());
154
					$inverses[$prop] = 'null';
155
// 					if (in_array($prop, $dupes) && !isset($inverses[$prop])) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
156
// 						$inverses[$prop] = 'null';
157
// 					} else {
158
// 						$dupes[] = $prop;
159
// 					}
160
				}
161
			}
162
163
			// find inverse one-to-many relationship
164
			foreach ($rels->getOneToMany() as $rel) {
165
				if ($rel->getForeign() == $model) {
166
					$prop = NameUtils::toCamelCase($rel->getReverseRelatedName());
167
					$inverses[$prop] = '\'' . NameUtils::toCamelCase($rel->getRelatedPluralName()) . '\'';
168
				}
169
			}
170
		}
171
172
		return $inverses;
173
	}
174
175
	private function getColumnFilter(GeneratorDefinitionSchema $generator, Table $model) {
176
		$read = $generator->getReadFilter($model->getOriginCommonName());
177
		$write = $generator->getWriteFilter($model->getOriginCommonName());
178
179
		$merge = [];
180
		foreach ($read as $field) {
181
			if (in_array($field, $write)) {
182
				$merge[] = $field;
183
			}
184
		}
185
186
		return $merge;
187
	}
188
}