APIDatabaseError class for SQL error, which send debug info to slim\log
[dolibarr-api.git] / mediatypehandler.php
1 <?php
2
3 function marsh_response($resp) {
4     $app = \Slim\Slim::getInstance();
5     return $app->request()->mediatype->marsh_response($resp);
6 }
7
8 class MediaTypeMiddleware extends \Slim\Middleware {
9     public $default_mtype = 'application/json';
10
11     public $supported_out;
12
13     public $supported_in;
14
15     public function __construct() {
16         $this->supported_in=array(
17             'application/json' => array($this, 'json_decode'),
18         );
19         $this->supported_out=array_merge($this->supported_in, array(
20             'application/json' => array($this, 'json_encode'),
21             'text/html'        => array($this, 'human_encode'),
22         ));;
23     }
24
25     public function call() {
26         $this->app->request()->mediatype=$this;
27
28         try {
29             $this->handle_request();
30             $this->next->call();
31         } catch(\Slim\Exception\Stop $e) {
32
33         }
34     }
35
36     /**
37      * http://bililite.com/blog/2010/01/06/parsing-the-http-accept-header/
38      */
39     protected function parse_accept($accept_header) {
40         $types = array();
41         foreach(explode(',', $accept_header) as $mediaRange){
42             @list($type, $qparam) = preg_split('/\s*;\s*/', $mediaRange);
43             $q = substr ($qparam, 0, 2) == 'q=' ? floatval(substr($qparam,2)) : 1;
44             if($q <= 0) continue;
45             if(substr($type, -1) == '*') $q -= 0.0001;
46             if(@$type[0] == '*') $q -= 0.0001;
47             $types[$type] = $q;
48         }
49         arsort($types);
50         foreach($types as $t => $q) {
51             if(array_key_exists($t, $this->supported_out)) {
52                 return $t;
53             }
54         }
55         return null;
56     }
57
58     public function marsh_response($resp) {
59         $client_accept = $this->app->request()->headers('HTTP_ACCEPT');
60         if(!is_null($client_accept) && ($chosen=$this->parse_accept($client_accept)) !== null)
61             $mtype_out = $chosen;
62         elseif(array_key_exists($this->mtype, $this->supported_out))
63             $mtype_out = $this->mtype;
64         else
65             $mtype_out = $this->default_mtype;
66
67         $this->app->response()['Content-Type'] = $mtype_out.'; charset=utf-8';
68         return call_user_func($this->supported_out[$mtype_out], $resp);
69     }
70
71     public function handle_request() {
72         $this->mtype=$this->app->request()->getMediaType();
73         if(is_null($this->mtype))
74             return;
75
76         if(isset($this->supported_in[$this->mtype])) {
77             $env = $this->app->environment();
78             $result = call_user_func($this->supported_in[$this->mtype], $env['slim.input']);
79             if ($result) {
80                 $env['slim.input_original'] = $env['slim.input'];
81                 $env['slim.input'] = $result;
82             } else {
83                 halt_error(415, new APIError('Unable to decode data'));
84             }
85         } else {
86             halt_error(415, new APIError('This service only supports JSON'));
87         }
88     }
89
90     public function json_decode($input) {
91         if (function_exists('json_decode')) {
92             $result = json_decode($input, true);
93             if ($result) {
94                 return $result;
95             }
96         }
97     }
98
99     public function json_encode($obj) {
100         return json_encode($obj, JSON_PRETTY_PRINT);
101     }
102
103     public function human_encode($obj) {
104         $out = '';
105         function is_numeric_array(&$arr) {
106             $i = 0;
107             foreach($arr as $k => &$v) {
108                 if(!is_int($k) || $k != $i) {
109                     return false;
110                 }
111                 $i++;
112             }
113             return true;
114         }
115         /* recursive closure, yay */
116         $recurs = function(&$obj) use(&$out, &$recurs) {
117             $is_numarr=is_numeric_array($obj);
118
119             if(!$is_numarr) {
120                 $longest_key=0;
121                 array_walk($obj, function(&$v, &$k) use (&$longest_key) {
122                     $longest_key=max($longest_key, strlen($k));
123                 });
124                 $longest_key += 2;
125                 $format_key=function($k) use($longest_key) {
126                     $padding=str_repeat(' ', $longest_key-strlen($k));
127                     return '<b>'.htmlentities($k).'</b>'.$padding.'=> ';
128                 };
129             } else {
130                 $format_key=function($k) {
131                     return '';
132                 };
133             }
134
135             $out.= '<ul>';
136             foreach($obj as $k => &$v) {
137                 if(is_array($v) || is_object($v)) {
138                     $out .= '<li>'.$format_key($k).'[';
139                     $recurs($v);
140                     $out .= '],</li>';
141                 } else {
142                     $out .= '<li>'.$format_key($k).(is_null($v) ? '<i>null</i>' : htmlentities((string)$v)).'</li>';
143                 }
144             }
145             $out .= '</ul>';
146         };
147         $out .= '<!doctype html><html><head><style>body { font-family: monospace; } ul { padding-left: 20px; } ul ul { padding-left: 30px; } li { list-style-type: none; white-space: pre; }</style></head><body>';
148         $k=key($obj);
149         $out .= '<h3>'.htmlentities($k).'&thinsp;:</h3>';
150         $recurs($obj[$k]);
151         $out .= '</body></html>';
152         return $out;
153     }
154 }