Passed
Push — master ( d36a99...d31551 )
by Jean-Christophe
06:01
created

JsonApiRestController   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Test Coverage

Coverage 48.96%

Importance

Changes 0
Metric Value
wmc 30
eloc 71
dl 0
loc 218
ccs 47
cts 96
cp 0.4896
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getOne_() 0 3 1
A options() 0 1 1
A getAll_() 0 11 2
A updateOperation() 0 3 1
A _getApiVersion() 0 2 1
A getRequestParam() 0 5 2
A _checkResource() 0 7 2
A getDatas() 0 14 3
A AddOperation() 0 3 1
A delete_() 0 3 1
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 _setResource() 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.1
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
	/**
43
	 *
44
	 * @param string $param
45
	 * @param string|boolean $default
46
	 * @return string|boolean
47
	 */
48 4
	protected function getRequestParam($param, $default) {
49 4
		if (isset ( $_GET [$param] )) {
50
			return $_GET [$param];
51
		}
52 4
		return $default;
53
	}
54
55
	protected function getDatas() {
56
		$datas = URequest::getInput ();
57
		if (sizeof ( $datas ) > 0) {
58
			$datas = current ( array_keys ( $datas ) );
59
			$datas = json_decode ( $datas, true );
60
			$attributes = $datas ["data"] ["attributes"] ?? [ ];
61
			if (isset ( $datas ["data"] ["id"] )) {
62
				$key = OrmUtils::getFirstKey ( $this->model );
63
				$attributes [$key] = $datas ["data"] ["id"];
64
			}
65
			$this->loadRelationshipsDatas($datas, $attributes);
66
			return $attributes;
67
		}
68
		$this->addError ( 204, 'No content', 'The POST request has no content!' );
69
	}
70
	
71
	protected function loadRelationshipsDatas($datas,&$attributes){
72
		if(isset($datas['data']['relationships'])){
73
			$relationShips=$datas['data']['relationships'];
74
			foreach ($relationShips as $member=>$data){
75
				if(isset($data['data']['id'])){
76
					$m=OrmUtils::getJoinColumnName($this->model, $member);
77
					$attributes[$m]=$data['data']['id'];
78
				}
79
			}
80
		}
81
	}
82
83
	/**
84
	 *
85
	 * @return RestServer
86
	 */
87 8
	protected function getRestServer(): RestServer {
88 8
		return new JsonApiRestServer ( $this->config );
89
	}
90
	
91
	protected function updateOperation($instance,$datas,$updateMany=false){
92
		$instance->_new=false;
93
		return CRUDHelper::update($instance,$datas,false,$updateMany);
94
	}
95
	
96
	protected function AddOperation($instance,$datas,$insertMany=false){
97
		$instance->_new=true;
98
		return CRUDHelper::update($instance,$datas,false,$insertMany);
99
	}
100
101
	/**
102
	 *
103
	 * @route("{resource}","methods"=>["options"],"priority"=>3000)
104
	 */
105
	public function options(...$resource) {
106
	}
107
108
	/**
109
	 *
110
	 * {@inheritdoc}
111
	 * @see \Ubiquity\controllers\rest\RestBaseController::index()
112
	 * @route("links/","methods"=>["get"],"priority"=>3000)
113
	 */
114 1
	public function index() {
115 1
		parent::index ();
116 1
	}
117
118
	/**
119
	 * Returns all the instances from the model $resource.
120
	 * Query parameters:
121
	 * - **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).
122
	 * - **filter**: The filter to apply to the query (where part of an SQL query) (default: 1=1).
123
	 * - **page[number]**: The page to display (in this case, the page size is set to 1).
124
	 * - **page[size]**: The page size (count of instance per page) (default: 1).
125
	 *
126
	 * @route("{resource}/","methods"=>["get"],"priority"=>0)
127
	 */
128 1
	public function getAll_($resource) {
129
		$this->_checkResource ( $resource, function () {
130 1
			$filter = $this->getRequestParam ( 'filter', '1=1' );
131 1
			$pages = null;
132 1
			if (isset ( $_GET ['page'] )) {
133
				$pageNumber = $_GET ['page'] ['number'];
134
				$pageSize = $_GET ['page'] ['size'] ?? 1;
135
				$pages = $this->generatePagination ( $filter, $pageNumber, $pageSize );
136
			}
137 1
			$datas = DAO::getAll ( $this->model, $filter, $this->getInclude ( $this->getRequestParam ( 'include', true ) ) );
138 1
			echo $this->_getResponseFormatter ()->get ( $datas, $pages );
139 1
		} );
140 1
	}
141
142
	/**
143
	 * Returns an instance of $resource, by primary key $id.
144
	 * Query parameters:
145
	 * - **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).
146
	 * - **filter**: The filter to apply to the query (where part of an SQL query) (default: 1=1).
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
	 *
151
	 * @route("{resource}/{id}/","methods"=>["get"],"priority"=>1000)
152
	 */
153 2
	public function getOne_($resource, $id) {
154
		$this->_checkResource ( $resource, function () use ($id) {
155 2
			$this->_getOne ( $id, true, false );
156 2
		} );
157 2
	}
158
159
	/**
160
	 * Returns an associated member value(s).
161
	 * Query parameters:
162
	 * - **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).
163
	 *
164
	 * @param string $resource The resource (model) to use
165
	 * @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)
166
	 * @param string $member The member to load
167
	 *
168
	 * @route("{resource}/{id}/relationships/{member}/","methods"=>["get"],"priority"=>2000)
169
	 */
170 3
	public function getRelationShip_($resource, $id, $member) {
171
		$this->_checkResource ( $resource, function () use ($id, $member) {
172 3
			$relations = OrmUtils::getAnnotFieldsInRelations ( $this->model );
173 3
			if (isset ( $relations [$member] )) {
174 3
				$include = $this->getRequestParam ( 'include', true );
175 3
				switch ($relations [$member] ['type']) {
176 3
					case 'manyToOne' :
177 1
						$this->_getManyToOne ( $id, $member, $include );
178 1
						break;
179 2
					case 'oneToMany' :
180 1
						$this->_getOneToMany ( $id, $member, $include );
181 1
						break;
182 1
					case 'manyToMany' :
183 1
						$this->_getManyToMany ( $id, $member, $include );
184 1
						break;
185
				}
186
			}
187 3
		} );
188 3
	}
189
190
	/**
191
	 * Inserts a new instance of $resource.
192
	 * Data attributes are send in data[attributes] request header
193
	 *
194
	 * @param string $resource The resource (model) to use
195
	 * @route("{resource}/","methods"=>["post"],"priority"=>0)
196
	 */
197
	public function add_($resource) {
198
		$this->_checkResource ( $resource, function () {
199
			parent::_add ();
200
		} );
201
	}
202
203
	/**
204
	 * Updates an existing instance of $resource.
205
	 * Data attributes are send in data[attributes] request header
206
	 *
207
	 * @param string $resource The resource (model) to use
208
	 *
209
	 * @route("{resource}/{id}","methods"=>["patch"],"priority"=>0)
210
	 */
211
	public function update_($resource,...$id) {
212
		$this->_checkResource ( $resource, function () use ($id){
213
			if (! $this->hasErrors ()) {
214
				parent::_update ( ...$id );
215
			} else {
216
				echo $this->displayErrors ();
217
			}
218
		} );
219
	}
220
221
	/**
222
	 * Deletes an existing instance of $resource.
223
	 *
224
	 * @param string $resource The resource (model) to use
225
	 * @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)
226
	 *
227
	 * @route("{resource}/{id}/","methods"=>["delete"],"priority"=>0)
228
	 */
229
	public function delete_($resource, ...$id) {
230
		$this->_checkResource ( $resource, function () use ($id) {
231
			$this->_delete ( $id );
232
		} );
233
	}
234
235
	/**
236
	 * Returns the api version.
237
	 *
238
	 * @return string
239
	 */
240 1
	public static function _getApiVersion() {
241 1
		return self::API_VERSION;
242
	}
243
}
244
245