Passed
Push — master ( 17d642...dc2aec )
by Jean-Christophe
08:16
created

JsonApiRestController::getDatas()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.1406

Importance

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