Completed
Push — master ( 0feaa6...f4afa6 )
by Jean-Christophe
01:33
created

RestController::finalize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace micro\controllers\rest;
4
5
use micro\controllers\Controller;
6
use micro\orm\DAO;
7
use micro\controllers\Startup;
8
use micro\utils\StrUtils;
9
use micro\cache\CacheManager;
10
use micro\utils\RequestUtils;
11
12
/**
13
 * @author jc
14
 * Abstract base class for Rest controllers
15
 *
16
 */
17
abstract class RestController extends Controller {
18
	protected $config;
19
	protected $model;
20
	protected $contentType;
21
	protected $restCache;
22
	/**
23
	 * @var ResponseFormatter
24
	 */
25
	protected $responseFormatter;
26
27
	/**
28
	 * @var RestServer
29
	 */
30
	protected $server;
31
32
	public function __construct(){
33
		if(!\headers_sent()){
34
			@\set_exception_handler(array ($this,'_errorHandler' ));
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
35
			$this->config=Startup::getConfig();
36
			$this->server=new RestServer($this->config);
37
			$this->server->cors();
38
			$this->responseFormatter=new ResponseFormatter();
39
			$this->contentType="application/json";
40
			$this->server->_setContentType($this->contentType);
41
			$this->restCache=CacheManager::getRestCacheController(\get_class($this));
42
		}
43
		parent::__construct();
44
	}
45
46
	public function isValid(){
47
		if(isset($this->restCache["authorizations"])){
48
			if(\array_search(Startup::getAction(), $this->restCache["authorizations"])!==false){
49
				return $this->server->isValid();
50
			}
51
		}
52
		return true;
53
	}
54
55
	public function onInvalidControl(){
56
		throw new \Exception('HTTP/1.1 401 Unauthorized, you need an access token for this request',401);
57
	}
58
59
	public function connect(){
60
		$this->server->connect($this);
61
	}
62
63
	public function initialize(){
64
		$thisClass=\get_class($this);
65
		if(!isset($this->model))
66
			$this->model=CacheManager::getRestResource($thisClass);
67
		if(!isset($this->model)){
68
			$modelsNS=$this->config["mvcNS"]["models"];
69
			$this->model=$modelsNS."\\".$this->responseFormatter->getModel($thisClass);
70
		}
71
		$this->connectDb($this->config);
72
	}
73
74
	public function finalize(){
75
		parent::finalize();
76
		$this->server->finalizeTokens();
77
	}
78
79
80
81
	public function _errorHandler($e){
82
		$code=500;
83
		if($e->getCode()!==0)
84
			$code=$e->getCode();
85
		$this->_setResponseCode($code);
86
		echo $this->responseFormatter->formatException($e);
87
	}
88
89
	public function _setResponseCode($value){
90
		\http_response_code($value);
91
	}
92
93
	protected function connectDb($config){
94
		$db=$config["database"];
95
		if($db["dbName"]!==""){
96
			DAO::connect($db["type"],$db["dbName"],@$db["serverName"],@$db["port"],@$db["user"],@$db["password"],@$db["cache"]);
97
		}
98
	}
99
100
	/**
101
	 * Updates $instance with $values
102
	 * To eventually be redefined in derived classes
103
	 * @param object $instance the instance to update
104
	 * @param array $values
105
	 */
106
	protected function _setValuesToObject($instance,$values){
107
		RequestUtils::setValuesToObject($instance,$values);
108
	}
109
110
	public function index() {
111
			$datas=DAO::getAll($this->model);
112
			$datas=\array_map(function($o){return $o->_rest;}, $datas);
113
			echo $this->responseFormatter->get($datas);
114
	}
115
116
	/**
117
	 * @param string $condition
118
	 * @param boolean $loadManyToOne
119
	 * @param boolean $loadOneToMany
120
	 * @param boolean $useCache
121
	 */
122
	public function get($condition="1=1",$loadManyToOne=false,$loadOneToMany=false,$useCache=false){
123
		try{
124
			$condition=\urldecode($condition);
125
			$loadManyToOne=StrUtils::isBooleanTrue($loadManyToOne);
126
			$loadOneToMany=StrUtils::isBooleanTrue($loadOneToMany);
127
			$useCache=StrUtils::isBooleanTrue($useCache);
128
			$datas=DAO::getAll($this->model,$condition,$loadManyToOne,$loadOneToMany,$useCache);
129
			$datas=\array_map(function($o){return $o->_rest;}, $datas);
130
			echo $this->responseFormatter->get($datas);
131
		}catch (\Exception $e){
132
			$this->_setResponseCode(500);
133
			echo $this->responseFormatter->formatException($e);
134
		}
135
	}
136
137
	/**
138
	 * @param string $keyValues
139
	 * @param boolean $loadManyToOne
140
	 * @param boolean $loadOneToMany
141
	 * @param boolean $useCache
142
	 */
143
	public function getOne($keyValues,$loadManyToOne=false,$loadOneToMany=false,$useCache=false){
144
		$keyValues=\urldecode($keyValues);
145
		$loadManyToOne=StrUtils::isBooleanTrue($loadManyToOne);
146
		$loadOneToMany=StrUtils::isBooleanTrue($loadOneToMany);
147
		$useCache=StrUtils::isBooleanTrue($useCache);
148
		$data=DAO::getOne($this->model, $keyValues,$loadManyToOne,$loadOneToMany,$useCache);
149
		if(isset($data)){
150
			$_SESSION["_restInstance"]=$data;
151
			echo $this->responseFormatter->getOne($data->_rest);
152
		}
153
		else{
154
			$this->_setResponseCode(404);
155
			echo $this->responseFormatter->format(["message"=>"No result found","keyValues"=>$keyValues]);
156
		}
157
	}
158
159
	public function _format($arrayMessage){
160
		return $this->responseFormatter->format($arrayMessage);
161
	}
162
163
	/**
164
	 * @param string $member
165
	 * @param boolean $useCache
166
	 * @throws \Exception
167
	 */
168 View Code Duplication
	public function getOneToMany($member,$useCache=false){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
		if(isset($_SESSION["_restInstance"])){
170
			$useCache=StrUtils::isBooleanTrue($useCache);
171
			$datas=DAO::getOneToMany($_SESSION["_restInstance"], $member,null,$useCache);
172
			$datas=\array_map(function($o){return $o->_rest;}, $datas);
173
			echo $this->responseFormatter->get($datas);
174
		}else{
175
			throw new \Exception("You have to call getOne before calling getOneToMany.");
176
		}
177
	}
178
179
	/**
180
	 * @param string $member
181
	 * @param boolean $useCache
182
	 * @throws \Exception
183
	 */
184 View Code Duplication
	public function getManyToMany($member,$useCache=false){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
		if(isset($_SESSION["_restInstance"])){
186
			$useCache=StrUtils::isBooleanTrue($useCache);
187
			$datas=DAO::getManyToMany($_SESSION["_restInstance"], $member,null,$useCache);
188
			$datas=\array_map(function($o){return $o->_rest;}, $datas);
189
			echo $this->responseFormatter->get($datas);
190
		}else{
191
			throw new \Exception("You have to call getOne before calling getManyToMany.");
192
		}
193
	}
194
195
	/**
196
	 * Update an instance of $model selected by the primary key $keyValues
197
	 * @param array $keyValues
198
	 * @authorization
199
	 */
200
	public function update(...$keyValues){
201
		$instance=DAO::getOne($this->model, $keyValues);
202
		if(isset($instance)){
203
			$this->_setValuesToObject($instance,RequestUtils::getInput());
0 ignored issues
show
Bug introduced by
It seems like \micro\utils\RequestUtils::getInput() targeting micro\utils\RequestUtils::getInput() can also be of type null; however, micro\controllers\rest\R...r::_setValuesToObject() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
204
			$result=DAO::update($instance);
205
			if($result){
206
				echo $this->responseFormatter->format(["status"=>"updated","data"=>$instance->_rest]);
207
			}else{
208
				throw new \Exception("Unable to update the instance");
209
			}
210
		}else{
211
			$this->_setResponseCode(404);
212
			echo $this->responseFormatter->format(["message"=>"No result found","keyValues"=>$keyValues]);
213
		}
214
	}
215
}
216