Passed
Push — master ( 5df63f...4c57ea )
by Jean-Christophe
06:08
created

JsonApiRestController   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 211
Duplicated Lines 0 %

Test Coverage

Coverage 46.81%

Importance

Changes 0
Metric Value
wmc 29
eloc 69
dl 0
loc 211
ccs 44
cts 94
cp 0.4681
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A _checkResource() 0 7 2
A _setResource() 0 3 1
A options() 0 1 1
A delete_() 0 3 1
A getOne_() 0 3 1
A _getTemplateFile() 0 2 1
A getAll_() 0 11 2
A updateOperation() 0 3 1
A _getApiVersion() 0 2 1
A AddOperation() 0 3 1
A getDatas() 0 14 3
A getRestServer() 0 2 1
A update_() 0 6 2
A index() 0 2 1
A getRelationShip_() 0 15 5
A add_() 0 3 1
A loadRelationshipsDatas() 0 7 4
1
<?php
2
3
namespace Ubiquity\controllers\rest\api\jsonapi;
4
5
use Ubiquity\orm\DAO;
6
use Ubiquity\controllers\rest\RestError;
7
use Ubiquity\controllers\Startup;
8
use Ubiquity\controllers\rest\RestBaseController;
9
use Ubiquity\utils\http\URequest;
10
use Ubiquity\orm\OrmUtils;
11
use Ubiquity\controllers\rest\RestServer;
12
use Ubiquity\controllers\crud\CRUDHelper;
13
14
/**
15
 * Rest JsonAPI implementation.
16
 * Ubiquity\controllers\rest\api\jsonapi$JsonApiRestController
17
 * This class is part of Ubiquity
18
 *
19
 * @author jcheron <[email protected]>
20
 * @version 1.1.2
21
 * @since Ubiquity 2.0.11
22
 *
23
 */
24
abstract class JsonApiRestController extends RestBaseController {
25
	const API_VERSION = 'JsonAPI 1.0';
26
27 5
	protected function _setResource($resource) {
28 5
		$modelsNS = $this->config ["mvcNS"] ["models"];
29 5
		$this->model = $modelsNS . "\\" . $this->_getResponseFormatter ()->getModel ( $resource );
30 5
	}
31
32 5
	protected function _checkResource($resource, $callback) {
33 5
		$this->_setResource ( $resource );
34 5
		if (class_exists ( $this->model )) {
35 5
			$callback ();
36
		} else {
37
			$error = new RestError ( 404, "Not existing class", $this->model . " class does not exists!", Startup::getController () . "/" . Startup::getAction () );
38
			echo $this->_format ( $error->asArray () );
39
		}
40 5
	}
41
42
	protected function getDatas() {
43
		$datas = URequest::getInput ();
44
		if (sizeof ( $datas ) > 0) {
45
			$datas = current ( array_keys ( $datas ) );
46
			$datas = json_decode ( $datas, true );
47
			$attributes = $datas ["data"] ["attributes"] ?? [ ];
48
			if (isset ( $datas ["data"] ["id"] )) {
49
				$key = OrmUtils::getFirstKey ( $this->model );
50
				$attributes [$key] = $datas ["data"] ["id"];
51
			}
52
			$this->loadRelationshipsDatas ( $datas, $attributes );
53
			return $attributes;
54
		}
55
		$this->addError ( 204, 'No content', 'The POST request has no content!' );
56
	}
57
58
	protected function loadRelationshipsDatas($datas, &$attributes) {
59
		if (isset ( $datas ['data'] ['relationships'] )) {
60
			$relationShips = $datas ['data'] ['relationships'];
61
			foreach ( $relationShips as $member => $data ) {
62
				if (isset ( $data ['data'] ['id'] )) {
63
					$m = OrmUtils::getJoinColumnName ( $this->model, $member );
64
					$attributes [$m] = $data ['data'] ['id'];
65
				}
66
			}
67
		}
68
	}
69
70
	/**
71
	 *
72
	 * @return RestServer
73
	 */
74 12
	protected function getRestServer(): RestServer {
75 12
		return new JsonApiRestServer ( $this->config );
76
	}
77
78
	protected function updateOperation($instance, $datas, $updateMany = false) {
79
		$instance->_new = false;
80
		return CRUDHelper::update ( $instance, $datas, false, $updateMany );
81
	}
82
83
	protected function AddOperation($instance, $datas, $insertMany = false) {
84
		$instance->_new = true;
85
		return CRUDHelper::update ( $instance, $datas, false, $insertMany );
86
	}
87
88
	/**
89
	 *
90
	 * @route("{resource}","methods"=>["options"],"priority"=>3000)
91
	 */
92
	public function options(...$resource) {
93
	}
94
95
	/**
96
	 *
97
	 * {@inheritdoc}
98
	 * @see \Ubiquity\controllers\rest\RestBaseController::index()
99
	 * @route("links/","methods"=>["get"],"priority"=>3000)
100
	 */
101 1
	public function index() {
102 1
		parent::index ();
103 1
	}
104
105
	/**
106
	 * Returns all the instances from the model $resource.
107
	 * Query parameters:
108
	 * - **include**: A string of associated members to load, comma separated (e.g. users,groups,organization...), or a boolean: true for all members, false for none (default: true).
109
	 * - **filter**: The filter to apply to the query (where part of an SQL query) (default: 1=1).
110
	 * - **page[number]**: The page to display (in this case, the page size is set to 1).
111
	 * - **page[size]**: The page size (count of instance per page) (default: 1).
112
	 *
113
	 * @route("{resource}/","methods"=>["get"],"priority"=>0)
114
	 */
115 1
	public function getAll_($resource) {
116
		$this->_checkResource ( $resource, function () {
117 1
			$filter = $this->getRequestParam ( 'filter', '1=1' );
118 1
			$pages = null;
119 1
			if (isset ( $_GET ['page'] )) {
120
				$pageNumber = $_GET ['page'] ['number'];
121
				$pageSize = $_GET ['page'] ['size'] ?? 1;
122
				$pages = $this->generatePagination ( $filter, $pageNumber, $pageSize );
123
			}
124 1
			$datas = DAO::getAll ( $this->model, $filter, $this->getInclude ( $this->getRequestParam ( 'include', true ) ) );
125 1
			echo $this->_getResponseFormatter ()->get ( $datas, $pages );
126 1
		} );
127 1
	}
128
129
	/**
130
	 * Returns an instance of $resource, by primary key $id.
131
	 *
132
	 * @param string $resource The resource (model) to use
133
	 * @param string $id The primary key value(s), if the primary key is composite, use a comma to separate the values (e.g. 1,115,AB)
134
	 *
135
	 * @route("{resource}/{id}/","methods"=>["get"],"priority"=>1000)
136
	 */
137 2
	public function getOne_($resource, $id) {
138
		$this->_checkResource ( $resource, function () use ($id) {
139 2
			$this->_getOne ( $id, true, false );
140 2
		} );
141 2
	}
142
143
	/**
144
	 * Returns an associated member value(s).
145
	 * Query parameters:
146
	 * - **include**: A string of associated members to load, comma separated (e.g. users,groups,organization...), or a boolean: true for all members, false for none (default: true).
147
	 *
148
	 * @param string $resource The resource (model) to use
149
	 * @param string $id The primary key value(s), if the primary key is composite, use a comma to separate the values (e.g. 1,115,AB)
150
	 * @param string $member The member to load
151
	 *
152
	 * @route("{resource}/{id}/relationships/{member}/","methods"=>["get"],"priority"=>2000)
153
	 */
154 3
	public function getRelationShip_($resource, $id, $member) {
155
		$this->_checkResource ( $resource, function () use ($id, $member) {
156 3
			$relations = OrmUtils::getAnnotFieldsInRelations ( $this->model );
157 3
			if (isset ( $relations [$member] )) {
158 3
				$include = $this->getRequestParam ( 'include', true );
159 3
				switch ($relations [$member] ['type']) {
160 3
					case 'manyToOne' :
161 1
						$this->_getManyToOne ( $id, $member, $include );
162 1
						break;
163 2
					case 'oneToMany' :
164 1
						$this->_getOneToMany ( $id, $member, $include );
165 1
						break;
166 1
					case 'manyToMany' :
167 1
						$this->_getManyToMany ( $id, $member, $include );
168 1
						break;
169
				}
170
			}
171 3
		} );
172 3
	}
173
174
	/**
175
	 * Inserts a new instance of $resource.
176
	 * Data attributes are send in data[attributes] request header
177
	 *
178
	 * @param string $resource The resource (model) to use
179
	 * @route("{resource}/","methods"=>["post"],"priority"=>0)
180
	 */
181
	public function add_($resource) {
182
		$this->_checkResource ( $resource, function () {
183
			parent::_add ();
184
		} );
185
	}
186
187
	/**
188
	 * Updates an existing instance of $resource.
189
	 * Data attributes are send in data[attributes] request header
190
	 *
191
	 * @param string $resource The resource (model) to use
192
	 *
193
	 * @route("{resource}/{id}","methods"=>["patch"],"priority"=>0)
194
	 */
195
	public function update_($resource, ...$id) {
196
		$this->_checkResource ( $resource, function () use ($id) {
197
			if (! $this->hasErrors ()) {
198
				parent::_update ( ...$id );
199
			} else {
200
				echo $this->displayErrors ();
201
			}
202
		} );
203
	}
204
205
	/**
206
	 * Deletes an existing instance of $resource.
207
	 *
208
	 * @param string $resource The resource (model) to use
209
	 * @param string $ids The primary key value(s), if the primary key is composite, use a comma to separate the values (e.g. 1,115,AB)
210
	 *
211
	 * @route("{resource}/{id}/","methods"=>["delete"],"priority"=>0)
212
	 */
213
	public function delete_($resource, ...$id) {
214
		$this->_checkResource ( $resource, function () use ($id) {
215
			$this->_delete ( $id );
216
		} );
217
	}
218
219
	/**
220
	 * Returns the api version.
221
	 *
222
	 * @return string
223
	 */
224 1
	public static function _getApiVersion() {
225 1
		return self::API_VERSION;
226
	}
227
228
	/**
229
	 * Returns the template for creating this type of controller
230
	 *
231
	 * @return string
232
	 */
233
	public static function _getTemplateFile() {
234
		return 'restApiController.tpl';
235
	}
236
}
237
238