Subversion Repositories Applications.referentiel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 jpm 1
<?php
2
// In : utf8 url_encoded (get et post)
3
// Out : utf8
4
 
5
// TODO : gerer les retours : dans ce controleur : code retour et envoi ...
6
class JRest {
7
 
8
 	/** Parsed configuration file */
9
    private $config;
10
 
11
	/** The HTTP request method used. */
12
	private $method = 'GET';
13
 
14
	/** The HTTP request data sent (if any). */
15
	private $requestData = NULL;
16
 
17
	/** Nom resource. */
18
	private $resource = NULL;
19
 
20
	/** Identifiant unique resource. */
21
	private $uid = NULL;
22
 
23
	/**
24
	 * Constructor. Parses the configuration file "JRest.ini", grabs any request data sent, records the HTTP
25
	 * request method used and parses the request URL to find out the requested resource
26
	 * @param str iniFile Configuration file to use
27
	 */
28
	public function JRest($iniFile = 'jrest.ini.php') {
29
		$this->config = parse_ini_file($iniFile, TRUE);
30
		if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER['QUERY_STRING'])) {
31
			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) {
32
				$this->requestData = '';
33
				$httpContent = fopen('php://input', 'r');
34
				while ($data = fread($httpContent, 1024)) {
35
					$this->requestData .= $data;
36
				}
37
				fclose($httpContent);
38
			}
39
			if (strlen($_SERVER['QUERY_STRING']) == 0) {
40
				$len = strlen($_SERVER['REQUEST_URI']);
41
			} else {
42
				$len = -(strlen($_SERVER['QUERY_STRING']) + 1);
43
			}
44
			$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseURL']), $len);
45
 
46
			$urlParts = explode('/', $urlString);
47
 
48
			if (isset($urlParts[0])) $this->resource = $urlParts[0];
49
			if (count($urlParts) > 1 && $urlParts[1] != '') {
50
				array_shift($urlParts);
51
				foreach ($urlParts as $uid) {
52
					if ($uid != '') {
53
						$this->uid[] = urldecode($uid);
54
					}
55
				}
56
			}
57
 
58
			$this->method = $_SERVER['REQUEST_METHOD'];
59
		} else {
60
			trigger_error('I require the server variables REQUEST_URI, REQUEST_METHOD and QUERY_STRING to work.', E_USER_ERROR);
61
		}
62
	}
63
 
64
	/**
65
	 * Execute the request.
66
	 */
67
	function exec() {
68
		switch ($this->method) {
69
			case 'GET':
70
				$this->get();
71
				break;
72
			case 'POST':
73
				$this->post();
74
				break;
75
			case 'DELETE':
76
				$this->delete();
77
				break;
78
			case 'PUT':
79
				$this->add();
80
				break;
81
		}
82
	}
83
 
84
	/**
85
	 * Execute a GET request. A GET request fetches a list of resource when no resource name is given, a list of element
86
	 * when a resource name is given, or a resource element when a resource and resource unique identifier are given. It does not change the
87
	 * database contents.
88
	 */
89
	private function get() {
90
		if ($this->resource) {
91
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
92
			$resource_class = ucfirst($this->resource);
93
			if (file_exists($resource_file))  {
94
				include_once $resource_file;
95
				if (class_exists($resource_class)) {
96
					$service = new $resource_class($this->config);
97
					if ($this->uid) { // get a resource element
98
						if (method_exists($service, 'getElement')) {
99
							$service->getElement($this->uid);
100
						}
101
					} elseif (method_exists($service, 'getRessource')) { // get all elements of a ressource
102
						$service->getRessource();
103
					}
104
				}
105
			}
106
		} else { // get resources
107
			// include set.jrest.php, instanticiation et appel
108
		}
109
	}
110
 
111
	private function post() {
112
	   	$pairs = array();
113
		// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
114
	   	if ($this->requestData) {
115
			$pairs = $this->parseRequestData();
116
		}
117
 
118
		// Ajout des informations concernant l'upload de fichier passées dans la variable $_FILE
119
		if(isset($_FILES)) {
120
			foreach ($_FILES as $v) {
121
				$pairs[$v['name']] = $v;
122
			}
123
 
124
			// Ne pas effacer cette ligne ! Elle est indispensable pour les services du Carnet en ligne
125
			// qui n'utilisent que le tableau pairs dans les posts
126
			$pairs = array_merge($pairs, $_POST);
127
		}
128
 
129
		// gestion du contenu du post
130
		if(isset($_POST))
131
		{
132
			// Safari ne sait pas envoyer des DELETE avec gwt...
133
			// Nous utilisons le parametre "action" passé dans le POST qui doit contenir DELETE pour lancer la supression
134
			if ($pairs['action'] == 'DELETE') {
135
				$this->delete();
136
				return;
137
			}
138
 
139
			if (count($pairs) != 0) {
140
				if ($this->uid) { // get a resource element
141
					$resource_file = 'services/'.ucfirst($this->resource).'.php';
142
					$resource_class = ucfirst($this->resource);
143
					if (file_exists($resource_file)) {
144
						include_once $resource_file;
145
						if (class_exists($resource_class)) {
146
							$service = new $resource_class($this->config);
147
							if (method_exists($service,'updateElement')) { // Update element
148
								// TODO : a voir le retour ...
149
								if ($service->updateElement($this->uid, $pairs)) {
150
									$this->created();
151
								}
152
							}
153
						}
154
					}
155
				} else { // get all elements of a ressource
156
					$this->add($pairs);
157
				}
158
			} else {
159
				$this->lengthRequired();
160
			}
161
		}
162
	}
163
 
164
	private function delete() {
165
		$resource_file = 'services/'.ucfirst($this->resource).'.php';
166
		$resource_class = ucfirst($this->resource);
167
		if (file_exists($resource_file)) {
168
			include_once $resource_file;
169
			if (class_exists($resource_class)) {
170
				$service = new $resource_class($this->config);
171
				if ($this->uid) { // get a resource element
172
		 			if (method_exists($service, 'deleteElement')) { // Delete element
173
						if ($service->deleteElement($this->uid)) {
174
							$this->noContent();
175
						}
176
	 				}
177
				}
178
			}
179
		}
180
	}
181
 
182
	private function add($pairs = null) {
183
		if (is_null($pairs)) {
184
			$pairs = array();
185
			// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
186
			// FIXME : vérifier que l'on récupère bien les données passées par PUT
187
		   	if ($this->requestData) {
188
				$pairs = $this->parseRequestData();
189
			}
190
		}
191
 
192
		if (count($pairs) != 0) {
193
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
194
			$resource_class = ucfirst($this->resource);
195
			if (file_exists($resource_file)) {
196
				include_once $resource_file;
197
				if (class_exists($resource_class)) {
198
					$service = new $resource_class($this->config);
199
					if (method_exists($service,'createElement')) { // Create a new element
200
						if ($service->createElement($pairs)) {
201
							$this->created();
202
						}
203
					}
204
				}
205
			}
206
		} else {
207
			$this->lengthRequired();
208
		}
209
	}
210
 
211
	/**
212
	 * Parse the HTTP request data.
213
	 * @return str[] Array of name value pairs
214
	 */
215
	private function parseRequestData() {
216
		$values = array();
217
		$pairs = explode('&', $this->requestData);
218
		foreach ($pairs as $pair) {
219
			$parts = explode('=', $pair);
220
			if (isset($parts[0]) && isset($parts[1])) {
221
				$parts[1] = rtrim(urldecode($parts[1]));
222
				$values[$parts[0]] = $parts[1];
223
			}
224
		}
225
		return $values;
226
	}
227
 
228
	/**
229
	 * Send a HTTP 201 response header.
230
	 */
231
	private function created($url = FALSE) {
232
		header('HTTP/1.0 201 Created');
233
		if ($url) {
234
			header('Location: '.$url);
235
		}
236
	}
237
 
238
	/**
239
	 * Send a HTTP 204 response header.
240
	 */
241
	private function noContent() {
242
		header('HTTP/1.0 204 No Content');
243
	}
244
 
245
	/**
246
	 * Send a HTTP 400 response header.
247
	 */
248
	private function badRequest() {
249
		header('HTTP/1.0 400 Bad Request');
250
	}
251
 
252
	/**
253
	 * Send a HTTP 401 response header.
254
	 */
255
	private function unauthorized($realm = 'JRest') {
256
		if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
257
			header('WWW-Authenticate: Basic realm="'.$realm.'"');
258
		}
259
		header('HTTP/1.0 401 Unauthorized');
260
	}
261
 
262
	/**
263
	 * Send a HTTP 404 response header.
264
	 */
265
	private function notFound() {
266
		header('HTTP/1.0 404 Not Found');
267
	}
268
 
269
	/**
270
	 * Send a HTTP 405 response header.
271
	 */
272
	private function methodNotAllowed($allowed = 'GET, HEAD') {
273
		header('HTTP/1.0 405 Method Not Allowed');
274
		header('Allow: '.$allowed);
275
	}
276
 
277
	/**
278
	 * Send a HTTP 406 response header.
279
	 */
280
	private function notAcceptable() {
281
		header('HTTP/1.0 406 Not Acceptable');
282
		echo join(', ', array_keys($this->config['renderers']));
283
	}
284
 
285
	/**
286
	 * Send a HTTP 411 response header.
287
	 */
288
	private function lengthRequired() {
289
		header('HTTP/1.0 411 Length Required');
290
	}
291
 
292
	/**
293
	 * Send a HTTP 500 response header.
294
	 */
295
	private function internalServerError() {
296
		header('HTTP/1.0 500 Internal Server Error');
297
	}
298
}
299
?>