Completed
Push — master ( bbdfc2...ebac7c )
by Thomas
05:30
created

ApiDefinitionGenerator::generate()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 27
rs 8.8571
cc 2
eloc 17
nc 2
nop 2
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 $needsPagedMeta = 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->needsPagedMeta = 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/PagedMeta');
33
34
		// writable model
35
		$writable = $definitions->get('Writable' . $modelObjectName)->setType('object')->getProperties();
36
		$this->generateModelProperties($writable, $model, true);
37
38
		// readable model
39
		$readable = $definitions->get($modelObjectName)->setType('object')->getProperties();
40
		$this->generateModelProperties($readable, $model, false);
41
	}
42
43
	protected function generateModelProperties(Definitions $props, Table $model, $write = false) {
44
		// links
45
		if (!$write) {
46
			$links = $props->get('links')->setType('object')->getProperties();
47
			$links->get('self')->setType('string');
48
		}
49
50
		// data
51
		$data = $this->generateResourceData($props);
52
53
		// attributes
54
		$attrs = $data->get('attributes');
55
		$attrs->setType('object');
56
		$this->generateModelAttributes($attrs->getProperties(), $model, $write);
57
58
		// relationships
59
		if ($this->hasRelationships($model)) {
60
			$relationships = $data->get('relationships')->setType('object')->getProperties();
61
			$this->generateModelRelationships($relationships, $model, $write);
62
		}
63
	}
64
65
	protected function generateModelAttributes(Definitions $props, Table $model, $write = false) {
66
		$modelName = $model->getOriginCommonName();
67
		$filter = $write
68
			? $this->project->getGeneratorDefinition()->getWriteFilter($modelName)
69
			: $this->project->getGeneratorDefinition()->getReadFilter($modelName);
70
71
		if ($write) {
72
			$filter = array_merge($filter, $this->generatorDefinitionService->getComputedFields($model));
73
		}
74
75
		// no id, already in identifier
76
		$filter[] = 'id';
77
		$types = ['int' => 'integer'];
78
79
		foreach ($model->getColumns() as $col) {
80
			$prop = $col->getName();
81
82
			if (!in_array($prop, $filter)) {
83
				$type = $col->getPhpType();
84
				if (isset($types[$type])) {
85
					$type = $types[$type];
86
				}
87
				$props->get($prop)->setType($type);
88
			}
89
		}
90
91
		return $props;
92
	}
93
94
	protected function hasRelationships(Table $model) {
95
		$relationships = $this->modelService->getRelationships($model);
96
		return $relationships->size() > 0;
97
	}
98
99
	protected function generateModelRelationships(Definitions $props, Table $model, $write = false) {
100
		$relationships = $this->modelService->getRelationships($model);
101
102
		foreach ($relationships->getAll() as $relationship) {
103
			// one-to-one
104
			if ($relationship->getType() == Relationship::ONE_TO_ONE) {
105
				$typeName = $relationship->getRelatedTypeName();
106
				$rel = $props->get($typeName)->setType('object')->getProperties();
107
108
				// links
109
				if (!$write) {
110
					$links = $rel->get('links')->setType('object')->getProperties();
111
					$links->get('self')->setType('string');
112
				}
113
114
				// data
115
				$this->generateResourceData($rel);
116
			}
117
118
			// ?-to-many
119
			else {
120
				$typeName = $relationship->getRelatedPluralTypeName();
121
				$rel = $props->get($typeName)->setType('object')->getProperties();
122
123
				// links
124
				if (!$write) {
125
					$links = $rel->get('links')->setType('object')->getProperties();
126
					$links->get('self')->setType('string');
127
				}
128
129
				// data
130
				$this->needsResourceIdentifier = true;
131
				$rel->get('data')
132
					->setType('array')
133
					->getItems()->setRef('#/definitions/ResourceIdentifier');
134
			}
135
		}
136
	}
137
138
	protected function generateResourceData(Definitions $props) {
139
		$data = $props->get('data')->setType('object')->getProperties();
140
		$props->get('id')->setType('string');
141
		$props->get('type')->setType('string');
142
		return $data;
143
	}
144
145
	public function needsPagedMeta() {
146
		return $this->needsPagedMeta;
147
	}
148
149
	public function needsResourceIdentifier() {
150
		return $this->needsResourceIdentifier;
151
	}
152
}