Completed
Push — master ( 8dc01e...5d6ae3 )
by Thomas
09:59
created

ApiDefinitionGenerator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 14
dl 0
loc 144
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
B generate() 0 28 2
A generateModelProperties() 0 21 3
B generateModelAttributes() 0 28 6
A hasRelationships() 0 4 1
B generateModelRelationships() 0 38 5
A generateResourceData() 0 6 1
A needsPaginationDefinition() 0 3 1
A needsResourceIdentifier() 0 3 1
1
<?php
2
namespace keeko\tools\generator\api;
3
4
use gossi\swagger\collections\Definitions;
5
use keeko\framework\utils\NameUtils;
6
use keeko\tools\generator\AbstractGenerator;
7
use Propel\Generator\Model\Table;
8
use keeko\tools\model\Relationship;
9
10
class ApiDefinitionGenerator extends AbstractGenerator {
11
12
	private $needsPaginationDefinition = false;
13
	private $needsResourceIdentifier = false;
14
15
	public function generate(Definitions $definitions, Table $model) {
16
		// stop if model is excluded
17
		$generatorDefinition = $this->project->getGeneratorDefinition();
18
		if ($generatorDefinition->getExcludedApi()->contains($model->getOriginCommonName())) {
19
			return;
20
		}
21
22
		$this->logger->notice('Generating Definition for: ' . $model->getOriginCommonName());
23
		$modelObjectName = $model->getPhpName();
24
25
		// paged model
26
		$this->needsPaginationDefinition = true;
27
		$pagedModel = 'Paged' . NameUtils::pluralize($modelObjectName);
28
		$paged = $definitions->get($pagedModel)->setType('object')->getProperties();
29
		$paged->get('data')
30
			->setType('array')
31
			->getItems()->setRef('#/definitions/' . $modelObjectName);
32
		$paged->get('meta')->setRef('#/definitions/PaginationMeta');
33
		$paged->get('links')->setRef('#/definitions/PaginationLinks');
34
35
		// writable model
36
		$writable = $definitions->get('Writable' . $modelObjectName)->setType('object')->getProperties();
37
		$this->generateModelProperties($writable, $model, true);
38
39
		// readable model
40
		$readable = $definitions->get($modelObjectName)->setType('object')->getProperties();
41
		$this->generateModelProperties($readable, $model, false);
42
	}
43
44
	protected function generateModelProperties(Definitions $props, Table $model, $write = false) {
45
		// links
46
		if (!$write) {
47
			$links = $props->get('links')->setType('object')->getProperties();
48
			$links->get('self')->setType('string');
49
		}
50
51
		// data
52
		$data = $this->generateResourceData($props);
53
54
		// attributes
55
		$attrs = $data->get('attributes');
56
		$attrs->setType('object');
57
		$this->generateModelAttributes($attrs->getProperties(), $model, $write);
58
59
		// relationships
60
		if ($this->hasRelationships($model)) {
61
			$relationships = $data->get('relationships')->setType('object')->getProperties();
62
			$this->generateModelRelationships($relationships, $model, $write);
63
		}
64
	}
65
66
	protected function generateModelAttributes(Definitions $props, Table $model, $write = false) {
67
		$modelName = $model->getOriginCommonName();
68
		$filter = $write
69
			? $this->project->getGeneratorDefinition()->getWriteFilter($modelName)
70
			: $this->project->getGeneratorDefinition()->getReadFilter($modelName);
71
72
		if ($write) {
73
			$filter = array_merge($filter, $this->generatorDefinitionService->getComputedFields($model));
74
		}
75
76
		// no id, already in identifier
77
		$filter[] = 'id';
78
		$types = ['int' => 'integer'];
79
80
		foreach ($model->getColumns() as $col) {
81
			$prop = $col->getName();
82
83
			if (!in_array($prop, $filter)) {
84
				$type = $col->getPhpType();
85
				if (isset($types[$type])) {
86
					$type = $types[$type];
87
				}
88
				$props->get($prop)->setType($type);
89
			}
90
		}
91
92
		return $props;
93
	}
94
95
	protected function hasRelationships(Table $model) {
96
		$relationships = $this->modelService->getRelationships($model);
97
		return $relationships->size() > 0;
98
	}
99
100
	protected function generateModelRelationships(Definitions $props, Table $model, $write = false) {
101
		$relationships = $this->modelService->getRelationships($model);
102
103
		foreach ($relationships->getAll() as $relationship) {
104
			// one-to-one
105
			if ($relationship->getType() == Relationship::ONE_TO_ONE) {
106
				$typeName = $relationship->getRelatedTypeName();
107
				$rel = $props->get($typeName)->setType('object')->getProperties();
108
109
				// links
110
				if (!$write) {
111
					$links = $rel->get('links')->setType('object')->getProperties();
112
					$links->get('self')->setType('string');
113
				}
114
115
				// data
116
				$this->generateResourceData($rel);
117
			}
118
119
			// ?-to-many
120
			else {
121
				$typeName = $relationship->getRelatedPluralTypeName();
122
				$rel = $props->get($typeName)->setType('object')->getProperties();
123
124
				// links
125
				if (!$write) {
126
					$links = $rel->get('links')->setType('object')->getProperties();
127
					$links->get('self')->setType('string');
128
				}
129
130
				// data
131
				$this->needsResourceIdentifier = true;
132
				$rel->get('data')
133
					->setType('array')
134
					->getItems()->setRef('#/definitions/ResourceIdentifier');
135
			}
136
		}
137
	}
138
139
	protected function generateResourceData(Definitions $props) {
140
		$data = $props->get('data')->setType('object')->getProperties();
141
		$props->get('id')->setType('string');
142
		$props->get('type')->setType('string');
143
		return $data;
144
	}
145
146
	public function needsPaginationDefinition() {
147
		return $this->needsPaginationDefinition;
148
	}
149
150
	public function needsResourceIdentifier() {
151
		return $this->needsResourceIdentifier;
152
	}
153
}