-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclass.cb_abstract_provider.php
126 lines (117 loc) · 5.08 KB
/
class.cb_abstract_provider.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
/* This file is part of cbapi.
* Copyright © 2011-2012 stiftung kulturserver.de ggmbh <[email protected]>
*
* cbapi is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cbapi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with cbapi. If not, see <http://www.gnu.org/licenses/>.
*/
Cb::import('InterfaceCbAuthorizationProvider', 'CbAuthorizationProvider', 'CbContentFormatter', 'CbApiException');
/**
* Providers handle AJAX requests (or any other requests) by clients,
* execute the necessary actions and output the results in the required format.
* You can specify an authorization provider which checks if the specified
* method is allowed. If no authorization provider is given all actions are
* allowed.
*/
abstract class CbAbstractProvider {
protected $auth_provider; ///< Authorization provider to check ACLs.
protected $handlers; ///< Handlers for specific methods.
protected $default_handler; ///< Handler to be called if no specific handler is given.
protected $formatter; ///< Formatter for the output.
protected $cache_provider; ///< Timout for the HTTP cache.
protected $config; ///< Application configuration.
protected function instantiate($thing)
{
if (is_string($thing)) {
$class = new ReflectionClass($thing);
$thing = $class->newInstance($this->config);
}
return $thing;
}
protected function getHandler($key)
{
if (isset($this->handlers[$key])) {
return ($this->handlers[$key] = $this->instantiate($this->handlers[$key]));
} else {
return ($this->default_handler = $this->instantiate($this->default_handler));
}
}
/**
* Create an abstract provider.
* @param array $handlers Handlers for various methods.
* @param array $config Application Configuration.
*/
protected function __construct(array $handlers = array(), $config = array())
{
$this->config = $config;
$this->cache_provider = $config['cache_provider'] ?
$this->instantiate($config['cache_provider']) :
new CbCacheProvider($config);
$this->auth_provider = $this->instantiate($config['auth_provider']);
$this->handlers = $handlers;
$this->default_handler = $config['default_handler'];
$this->formatter = $config['formatter'] ?
$this->instantiate($config['formatter']) :
new CbContentFormatter($config);
}
/**
* Handle the specified request (or $_REQUEST if null), check authorization,
* catch any errors, set the required HTTP response codes and headers, and
* finally output the error message or the result.
* @param array $request Request to be handled. If null, use $_REQUEST instead.
*/
public function handle(array $request = null)
{
try {
if (!$request) $request = array_merge($_COOKIE, $_POST, $_GET);
$method = strtolower(isset($request['method']) ? $request['method'] : $_SERVER['REQUEST_METHOD']);
$meta = $this->getMetadata($method, $request);
if (isset($meta['vary'])) {
$vary = array_map("ucfirst", array_map("strtolower",
is_array($meta['vary']) ? $meta['vary'] : array($meta['vary'])));
if (!in_array("Accept", $vary)) $vary[] = 'Accept';
header('Vary: '. implode(',', $vary), false);
} else {
header('Vary: Accept', false);
}
if (method_exists($this->formatter, 'negotiate')) {
$formatter = $this->formatter->negotiate(
isset($meta['formats']) ? $meta['formats'] : null,
isset($request['format']) ? $request['format'] : null
);
} else {
$formatter = $this->formatter;
}
header('Content-type: ' . $formatter->contentType());
$name = isset($meta['name']) ? $meta['name'] : '';
try {
if (!$this->cache_provider->run($meta)) return;
if ($this->auth_provider) $this->auth_provider->assert($method, $request);
$result = $this->execHandler($method, $request);
$formatter->format($name, $result);
} catch (CbApiException $e) {
$e->outputHeaders();
if (method_exists($formatter, 'exception')) {
$formatter->exception($name, $request, $e);
} else {
$formatter->format($name, new CbContentAdapter($e->getUserData()));
}
}
} catch (Exception $e) {
header("HTTP/1.0 500 Internal Server Error");
die();
}
}
abstract protected function execHandler($method, $request);
abstract protected function getMetadata($method, $request);
}