0011984: printing events with tags is broken for daysview
[tine20] / tine20 / Tinebase / Http / Server.php
1 <?php
2 /**
3  * Zend Framework
4  *
5  * LICENSE
6  *
7  * This source file is subject to the new BSD license that is bundled
8  * with this package in the file LICENSE.txt.
9  * It is also available through the world-wide-web at this URL:
10  * http://framework.zend.com/license/new-bsd
11  * If you did not receive a copy of the license and are unable to
12  * obtain it through the world-wide-web, please send an email
13  * to license@zend.com so we can send you a copy immediately.
14  *
15  * @category   Zend
16  * @package    Zend_Http
17  * @subpackage Server
18  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
20  */
21
22 /**
23  * Zend_Server_Interface
24  */
25 require_once 'Zend/Server/Interface.php';
26
27 /**
28  * Zend_Server_Reflection
29  */
30 require_once 'Zend/Server/Reflection.php';
31
32 /**
33  * Zend_Json_Server_Exception
34  */
35 require_once 'Zend/Json/Server/Exception.php';
36
37 /**
38  * Zend_Server_Abstract
39  */
40 require_once 'Zend/Server/Abstract.php';
41
42 /**
43  * Zend_Json
44  */
45 require_once 'Zend/Json.php';
46
47 /**
48  * @category   Zend
49  * @package    Zend_Http
50  * @subpackage Server
51  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
52  * @license    http://framework.zend.com/license/new-bsd     New BSD License
53  */
54 class Tinebase_Http_Server extends Zend_Server_Abstract implements Zend_Server_Interface {
55     /**
56      * @var Zend_Server_Reflection
57      */
58     private $_reflection = null;
59     
60     /**
61      * Class Constructor Args
62      */
63     private $_args = array();
64     
65     /**
66      * @var array An array of Zend_Server_Reflect_Method
67      */
68     private $_functions = array();
69     
70     /**
71      * @var string Current Method
72      */
73     private $_method;
74     
75     /**
76      * Constructor
77      */
78     public function __construct()
79     {
80         set_exception_handler(array($this, "fault"));
81         $this->_reflection = new Zend_Server_Reflection();
82     }
83
84     /**
85      * Implement Zend_Server_Interface::handle()
86      * 
87      * the called functions output the generated content directly themself
88      *
89      * @param array $request
90      */
91     public function handle($request = false)
92     {
93         if (!$request) {
94             $request = $_REQUEST;
95         }
96         if (isset($request['method'])) {
97             $this->_method = $request['method'];
98             if (isset($this->_functions[$this->_method])) {
99                 if ($this->_functions[$this->_method] instanceof Zend_Server_Reflection_Function || $this->_functions[$this->_method] instanceof Zend_Server_Reflection_Method && $this->_functions[$this->_method]->isPublic()) {
100                     $request_keys = array_keys($request);
101                     array_walk($request_keys, array(__CLASS__, "lowerCase"));
102                     $request = array_combine($request_keys, $request);
103                     
104                     $func_args = $this->_functions[$this->_method]->getParameters();
105                     
106                     $calling_args = array();
107                     foreach ($func_args as $arg) {
108                         if (isset($request[strtolower($arg->getName())])) {
109                             $calling_args[] = $request[strtolower($arg->getName())];
110                         }
111                     }
112                     
113                     foreach ($request as $key => $value) {
114                         if (substr($key, 0, 3) == 'arg') {
115                             $key = str_replace('arg', '', $key);
116                             $calling_args[$key]= $value;
117                         }
118                     }
119                     
120                     if (sizeof($calling_args) < sizeof($func_args)) {
121                         throw new Zend_Json_Server_Exception('Invalid Method Call to ' .$this->_method. '. Requires ' .sizeof($func_args). ', ' .sizeof($calling_args). ' given.', 400);
122                     }
123                     
124                     if ($this->_functions[$this->_method] instanceof Zend_Server_Reflection_Method) {
125                         // Get class
126                         $class = $this->_functions[$this->_method]->getDeclaringClass()->getName();
127         
128                         if ($this->_functions[$this->_method]->isStatic()) {
129                             // for some reason, invokeArgs() does not work the same as 
130                             // invoke(), and expects the first argument to be an object. 
131                             // So, using a callback if the method is static.
132                             $result = call_user_func_array(array($class, $this->_functions[$this->_method]->getName()), $calling_args);
133                         }
134         
135                         // Object methods
136                         try {
137                             if ($this->_functions[$this->_method]->getDeclaringClass()->getConstructor()) {
138                                 $object = $this->_functions[$this->_method]->getDeclaringClass()->newInstanceArgs($this->_args);
139                             } else {
140                                 $object = $this->_functions[$this->_method]->getDeclaringClass()->newInstance();
141                             }
142                         } catch (Exception $e) {
143                             throw new Zend_Json_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $this->_functions[$this->_method]->getName(), 500);
144                         }
145                         
146                         // the called function generates the needed output
147                         $this->_functions[$this->_method]->invokeArgs($object, $calling_args);
148                     } else {
149                         // the called function generates the needed output
150                         call_user_func_array($this->_functions[$this->_method]->getName(), $calling_args); //$result = $this->_functions[$this->_method]->invokeArgs($calling_args);
151                     }
152                     
153                 } else {
154                     throw new Zend_Json_Server_Exception("Unknown Method '$this->_method'.", 400);
155                 }
156             } else {
157                 throw new Zend_Json_Server_Exception("Unknown Method '$this->_method'.", 400);
158             }
159         } else {
160             throw new Zend_Json_Server_Exception("No Method Specified.", 404);
161         }
162     }
163     
164     /**
165      * Implement Zend_Server_Interface::setClass()
166      *
167      * @param string $classname Class name
168      * @param string $namespace Class namespace (unused)
169      * @param array $argv An array of Constructor Arguments
170      */
171     public function setClass($classname, $namespace = '', $argv = array())
172     {
173         $this->_args = $argv;
174         foreach ($this->_reflection->reflectClass($classname, $argv)->getMethods() as $method) {
175             $prefix = ($namespace === '' ? $classname : $namespace);
176             $this->_functions[$prefix .'.'. $method->getName()] = $method;
177         }
178     }
179     
180     /**
181      * Implement Zend_Server_Interface::fault()
182      *
183      * @param string $fault Message
184      * @param int $code Error Code
185      */
186     public function fault($exception = null, $code = null)
187     {
188         if (isset($this->_functions[$this->_method])) {
189             $function = $this->_functions[$this->_method];
190         } else {
191             $function = $this->_method;
192         }
193         
194         if ($function instanceof Zend_Server_Reflection_Method) {
195             $class = $function->getDeclaringClass()->getName();
196         } else {
197             $class = false;
198         }
199         
200         if ($function instanceof Zend_Server_Reflection_Method) {
201             $method = $function->getName();
202         } else {
203             $method = $function;
204         }
205         
206         $error['msg'] = "Call to $method failed.";
207         $error['code'] = 404;
208         
209         if ($exception instanceof Exception) {
210             $error['msg'] = $exception->getMessage();
211             $error['code'] = $exception->getCode();
212             $error['trace'] = $exception->getTrace();
213         } elseif (!is_null($exception)) {
214             $error['msg'] = $exception;
215         }
216         
217         if (!is_null($code)) {
218             $error['code'] = $code;
219         }
220         
221         if (!headers_sent()) {
222             header('Content-Type: text/html; charset=utf-8');
223             if (is_null($code)) {
224                 header("HTTP/1.0 400 Bad Request");
225             } else {
226                 if ($code == 404) {
227                     header("HTTP/1.0 $code File Not Found");
228                 } else {
229                     header("HTTP/1.0 $code Bad Request");
230                 }
231             }
232         }
233         echo "<pre>";
234         var_dump($error);
235         echo "</pre>";
236     }
237     
238     /**
239      * Implement Zend_Server_Interface::addFunction()
240      *
241      * @param string $function Function Name
242      * @param string $namespace Function namespace (unused)
243      */
244     public function addFunction($function, $namespace = '')
245     {
246         if (!is_array($function)) {
247             $function = (array) $function;
248         }
249         
250         foreach ($function as $func) {
251             if (is_callable($func) && !in_array($func, self::$magic_methods)) {
252                 $this->_functions[$func] = $this->_reflection->reflectFunction($func);
253             } else {
254                 throw new Zend_Json_Server_Exception("Invalid Method Added to Service.");
255             }
256         }
257     }
258     
259     /**
260      * Implement Zend_Server_Interface::getFunctions()
261      *
262      * @return array An array of Zend_Server_Reflection_Method's
263      */
264     public function getFunctions()
265     {
266         return $this->_functions;
267     }
268     
269     /**
270      * Implement Zend_Server_Interface::loadFunctions()
271      *
272      * @todo Implement
273      * @param array $functions
274      */
275     public function loadFunctions($functions)
276     {
277         
278     }
279     
280     /**
281      * Implement Zend_Server_Interface::setPersistence()
282      * 
283      * @todo Implement
284      * @param int $mode
285      */
286     public function setPersistence($mode)
287     {
288         
289     }
290
291     /**
292      * Map PHP type to protocol type
293      * -> we need to implement that because it is declared abstract in Zend_Server_Abstract
294      * -> is needed for ZF 1.7
295      * 
296      * @param  string $type 
297      * @return string
298      * 
299      */
300     protected function _fixType($type)
301     {
302         return $type;
303     }
304     
305     /**
306      * Lowercase a string
307      *
308      * Lowercase's a string by reference
309      * -> moved here from Zend_Server_Abstract because it is marked as deprecated there
310      * 
311      * @param  string $string value
312      * @param  string $key
313      * @return string Lower cased string
314      */
315     public static function lowerCase(&$value, &$key)
316     {
317         return $value = strtolower($value);
318     }    
319 }