EmberModelGenerator   B
last analyzed

Complexity

Total Complexity 45

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 45
lcom 1
cbo 10
dl 0
loc 179
rs 8.3673
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 13 1
C generateColumns() 0 58 22
C generateRelationships() 0 36 8
C collectInverseRelationships() 0 52 11
A getColumnFilter() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like EmberModelGenerator often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EmberModelGenerator, and based on these observations, apply Extract Interface, too.

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
}