Completed
Branch develop (eb876f)
by
unknown
21:14
created
htdocs/includes/restler/framework/Luracast/Restler/MemcacheCache.php 2 patches
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -14,127 +14,127 @@
 block discarded – undo
14 14
  */
15 15
 class MemcacheCache implements iCache
16 16
 {
17
-    /**
18
-     * The namespace that all of the cached entries will be stored under.  This allows multiple APIs to run concurrently.
19
-     *
20
-     * @var string
21
-     */
22
-    static public $namespace;
17
+	/**
18
+	 * The namespace that all of the cached entries will be stored under.  This allows multiple APIs to run concurrently.
19
+	 *
20
+	 * @var string
21
+	 */
22
+	static public $namespace;
23 23
     
24
-    /**
25
-     * @var string the memcache server hostname / IP address. For the memcache 
26
-     * cache method.
27
-     */
28
-    static public $memcacheServer = '127.0.0.1';
24
+	/**
25
+	 * @var string the memcache server hostname / IP address. For the memcache 
26
+	 * cache method.
27
+	 */
28
+	static public $memcacheServer = '127.0.0.1';
29 29
     
30
-    /**
31
-     * @var int the memcache server port. For the memcache cache method. 
32
-     */
33
-    static public $memcachePort = 11211;
30
+	/**
31
+	 * @var int the memcache server port. For the memcache cache method. 
32
+	 */
33
+	static public $memcachePort = 11211;
34 34
 
35 35
     
36
-    private $memcache;
36
+	private $memcache;
37 37
 
38
-    /**
39
-     * @param string $namespace
40
-     */
41
-    function __construct($namespace = 'restler')
42
-    {
43
-        self::$namespace = $namespace;
44
-        if (function_exists('memcache_connect')) {
45
-            $this->memcache = new \Memcache;
46
-            $this->memcache->connect(self::$memcacheServer, self::$memcachePort);
47
-        } else {
48
-            $this->memcacheNotAvailable('Memcache is not available for use as Restler Cache. Please make sure the the memcache php extension is installed.');
49
-        }
50
-    }
38
+	/**
39
+	 * @param string $namespace
40
+	 */
41
+	function __construct($namespace = 'restler')
42
+	{
43
+		self::$namespace = $namespace;
44
+		if (function_exists('memcache_connect')) {
45
+			$this->memcache = new \Memcache;
46
+			$this->memcache->connect(self::$memcacheServer, self::$memcachePort);
47
+		} else {
48
+			$this->memcacheNotAvailable('Memcache is not available for use as Restler Cache. Please make sure the the memcache php extension is installed.');
49
+		}
50
+	}
51 51
 
52
-    /**
53
-     * store data in the cache
54
-     *
55
-     *
56
-     * @param string $name
57
-     * @param mixed $data
58
-     *
59
-     * @return boolean true if successful
60
-     */
61
-    public function set($name, $data)
62
-    {
63
-        function_exists('memcache_set') || $this->memcacheNotAvailable();
52
+	/**
53
+	 * store data in the cache
54
+	 *
55
+	 *
56
+	 * @param string $name
57
+	 * @param mixed $data
58
+	 *
59
+	 * @return boolean true if successful
60
+	 */
61
+	public function set($name, $data)
62
+	{
63
+		function_exists('memcache_set') || $this->memcacheNotAvailable();
64 64
 
65
-        try {
66
-            return $this->memcache->set(self::$namespace . "-" . $name, $data);
67
-        } catch
68
-        (\Exception $exception) {
69
-            return false;
70
-        }
71
-    }
65
+		try {
66
+			return $this->memcache->set(self::$namespace . "-" . $name, $data);
67
+		} catch
68
+		(\Exception $exception) {
69
+			return false;
70
+		}
71
+	}
72 72
 
73
-    private function memcacheNotAvailable($message = 'Memcache is not available.')
74
-    {
75
-        throw new \Exception($message);
76
-    }
73
+	private function memcacheNotAvailable($message = 'Memcache is not available.')
74
+	{
75
+		throw new \Exception($message);
76
+	}
77 77
 
78
-    /**
79
-     * retrieve data from the cache
80
-     *
81
-     *
82
-     * @param string $name
83
-     * @param bool $ignoreErrors
84
-     *
85
-     * @throws \Exception
86
-     * @return mixed
87
-     */
88
-    public function get($name, $ignoreErrors = false)
89
-    {
90
-        function_exists('memcache_get') || $this->memcacheNotAvailable();
78
+	/**
79
+	 * retrieve data from the cache
80
+	 *
81
+	 *
82
+	 * @param string $name
83
+	 * @param bool $ignoreErrors
84
+	 *
85
+	 * @throws \Exception
86
+	 * @return mixed
87
+	 */
88
+	public function get($name, $ignoreErrors = false)
89
+	{
90
+		function_exists('memcache_get') || $this->memcacheNotAvailable();
91 91
 
92
-        try {
93
-            return $this->memcache->get(self::$namespace . "-" . $name);
94
-        } catch (\Exception $exception) {
95
-            if (!$ignoreErrors) {
96
-                throw $exception;
97
-            }
98
-            return null;
99
-        }
100
-    }
92
+		try {
93
+			return $this->memcache->get(self::$namespace . "-" . $name);
94
+		} catch (\Exception $exception) {
95
+			if (!$ignoreErrors) {
96
+				throw $exception;
97
+			}
98
+			return null;
99
+		}
100
+	}
101 101
 
102
-    /**
103
-     * delete data from the cache
104
-     *
105
-     *
106
-     * @param string $name
107
-     * @param bool $ignoreErrors
108
-     *
109
-     * @throws \Exception
110
-     * @return boolean true if successful
111
-     */
112
-    public function clear($name, $ignoreErrors = false)
113
-    {
114
-        function_exists('memcache_delete') || $this->memcacheNotAvailable();
102
+	/**
103
+	 * delete data from the cache
104
+	 *
105
+	 *
106
+	 * @param string $name
107
+	 * @param bool $ignoreErrors
108
+	 *
109
+	 * @throws \Exception
110
+	 * @return boolean true if successful
111
+	 */
112
+	public function clear($name, $ignoreErrors = false)
113
+	{
114
+		function_exists('memcache_delete') || $this->memcacheNotAvailable();
115 115
 
116
-        try {
117
-            $this->memcache->delete(self::$namespace . "-" . $name);
118
-        } catch (\Exception $exception) {
119
-            if (!$ignoreErrors) {
120
-                throw $exception;
121
-            }
122
-        }
123
-    }
116
+		try {
117
+			$this->memcache->delete(self::$namespace . "-" . $name);
118
+		} catch (\Exception $exception) {
119
+			if (!$ignoreErrors) {
120
+				throw $exception;
121
+			}
122
+		}
123
+	}
124 124
 
125
-    /**
126
-     * check if the given name is cached
127
-     *
128
-     *
129
-     * @param string $name
130
-     *
131
-     * @return boolean true if cached
132
-     */
133
-    public function isCached($name)
134
-    {
135
-        function_exists('memcache_get') || $this->memcacheNotAvailable();
136
-        $data = $this->memcache->get(self::$namespace . "-" . $name);
137
-        return !empty($data);
138
-    }
125
+	/**
126
+	 * check if the given name is cached
127
+	 *
128
+	 *
129
+	 * @param string $name
130
+	 *
131
+	 * @return boolean true if cached
132
+	 */
133
+	public function isCached($name)
134
+	{
135
+		function_exists('memcache_get') || $this->memcacheNotAvailable();
136
+		$data = $this->memcache->get(self::$namespace . "-" . $name);
137
+		return !empty($data);
138
+	}
139 139
 
140 140
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -6 removed lines patch added patch discarded remove patch
@@ -63,9 +63,8 @@  discard block
 block discarded – undo
63 63
         function_exists('memcache_set') || $this->memcacheNotAvailable();
64 64
 
65 65
         try {
66
-            return $this->memcache->set(self::$namespace . "-" . $name, $data);
67
-        } catch
68
-        (\Exception $exception) {
66
+            return $this->memcache->set(self::$namespace."-".$name, $data);
67
+        } catch (\Exception $exception) {
69 68
             return false;
70 69
         }
71 70
     }
@@ -90,7 +89,7 @@  discard block
 block discarded – undo
90 89
         function_exists('memcache_get') || $this->memcacheNotAvailable();
91 90
 
92 91
         try {
93
-            return $this->memcache->get(self::$namespace . "-" . $name);
92
+            return $this->memcache->get(self::$namespace."-".$name);
94 93
         } catch (\Exception $exception) {
95 94
             if (!$ignoreErrors) {
96 95
                 throw $exception;
@@ -114,7 +113,7 @@  discard block
 block discarded – undo
114 113
         function_exists('memcache_delete') || $this->memcacheNotAvailable();
115 114
 
116 115
         try {
117
-            $this->memcache->delete(self::$namespace . "-" . $name);
116
+            $this->memcache->delete(self::$namespace."-".$name);
118 117
         } catch (\Exception $exception) {
119 118
             if (!$ignoreErrors) {
120 119
                 throw $exception;
@@ -133,7 +132,7 @@  discard block
 block discarded – undo
133 132
     public function isCached($name)
134 133
     {
135 134
         function_exists('memcache_get') || $this->memcacheNotAvailable();
136
-        $data = $this->memcache->get(self::$namespace . "-" . $name);
135
+        $data = $this->memcache->get(self::$namespace."-".$name);
137 136
         return !empty($data);
138 137
     }
139 138
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/iAuthenticate.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -15,11 +15,11 @@
 block discarded – undo
15 15
  */
16 16
 interface iAuthenticate extends iFilter
17 17
 {
18
-    /**
19
-     * @return string string to be used with WWW-Authenticate header
20
-     * @example Basic
21
-     * @example Digest
22
-     * @example OAuth
23
-     */
24
-    public function __getWWWAuthenticateString();
18
+	/**
19
+	 * @return string string to be used with WWW-Authenticate header
20
+	 * @example Basic
21
+	 * @example Digest
22
+	 * @example OAuth
23
+	 */
24
+	public function __getWWWAuthenticateString();
25 25
 }
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Restler.php 3 patches
Indentation   +1631 added lines, -1631 removed lines patch added patch discarded remove patch
@@ -55,1635 +55,1635 @@
 block discarded – undo
55 55
  */
56 56
 class Restler extends EventDispatcher
57 57
 {
58
-    const VERSION = '3.1.0';
59
-
60
-    // ==================================================================
61
-    //
62
-    // Public variables
63
-    //
64
-    // ------------------------------------------------------------------
65
-    /**
66
-     * Reference to the last exception thrown
67
-     * @var RestException
68
-     */
69
-    public $exception = null;
70
-    /**
71
-     * Used in production mode to store the routes and more
72
-     *
73
-     * @var iCache
74
-     */
75
-    public $cache;
76
-    /**
77
-     * URL of the currently mapped service
78
-     *
79
-     * @var string
80
-     */
81
-    public $url;
82
-    /**
83
-     * Http request method of the current request.
84
-     * Any value between [GET, PUT, POST, DELETE]
85
-     *
86
-     * @var string
87
-     */
88
-    public $requestMethod;
89
-    /**
90
-     * Requested data format.
91
-     * Instance of the current format class
92
-     * which implements the iFormat interface
93
-     *
94
-     * @var iFormat
95
-     * @example jsonFormat, xmlFormat, yamlFormat etc
96
-     */
97
-    public $requestFormat;
98
-    /**
99
-     * Response data format.
100
-     *
101
-     * Instance of the current format class
102
-     * which implements the iFormat interface
103
-     *
104
-     * @var iFormat
105
-     * @example jsonFormat, xmlFormat, yamlFormat etc
106
-     */
107
-    public $responseFormat;
108
-    /**
109
-     * Http status code
110
-     *
111
-     * @var int|null when specified it will override @status comment
112
-     */
113
-    public $responseCode=null;
114
-    /**
115
-     * @var string base url of the api service
116
-     */
117
-    protected $baseUrl;
118
-    /**
119
-     * @var bool Used for waiting till verifying @format
120
-     *           before throwing content negotiation failed
121
-     */
122
-    protected $requestFormatDiffered = false;
123
-    /**
124
-     * method information including metadata
125
-     *
126
-     * @var ApiMethodInfo
127
-     */
128
-    public $apiMethodInfo;
129
-    /**
130
-     * @var int for calculating execution time
131
-     */
132
-    protected $startTime;
133
-    /**
134
-     * When set to false, it will run in debug mode and parse the
135
-     * class files every time to map it to the URL
136
-     *
137
-     * @var boolean
138
-     */
139
-    protected $productionMode = false;
140
-    public $refreshCache = false;
141
-    /**
142
-     * Caching of url map is enabled or not
143
-     *
144
-     * @var boolean
145
-     */
146
-    protected $cached;
147
-    /**
148
-     * @var int
149
-     */
150
-    protected $apiVersion = 1;
151
-    /**
152
-     * @var int
153
-     */
154
-    protected $requestedApiVersion = 1;
155
-    /**
156
-     * @var int
157
-     */
158
-    protected $apiMinimumVersion = 1;
159
-    /**
160
-     * @var array
161
-     */
162
-    protected $apiVersionMap = array();
163
-    /**
164
-     * Associated array that maps formats to their respective format class name
165
-     *
166
-     * @var array
167
-     */
168
-    protected $formatMap = array();
169
-    /**
170
-     * List of the Mime Types that can be produced as a response by this API
171
-     *
172
-     * @var array
173
-     */
174
-    protected $writableMimeTypes = array();
175
-    /**
176
-     * List of the Mime Types that are supported for incoming requests by this API
177
-     *
178
-     * @var array
179
-     */
180
-    protected $readableMimeTypes = array();
181
-    /**
182
-     * Associated array that maps formats to their respective format class name
183
-     *
184
-     * @var array
185
-     */
186
-    protected $formatOverridesMap = array('extensions' => array());
187
-    /**
188
-     * list of filter classes
189
-     *
190
-     * @var array
191
-     */
192
-    protected $filterClasses = array();
193
-    /**
194
-     * instances of filter classes that are executed after authentication
195
-     *
196
-     * @var array
197
-     */
198
-    protected $postAuthFilterClasses = array();
199
-
200
-
201
-    // ==================================================================
202
-    //
203
-    // Protected variables
204
-    //
205
-    // ------------------------------------------------------------------
206
-
207
-    /**
208
-     * Data sent to the service
209
-     *
210
-     * @var array
211
-     */
212
-    protected $requestData = array();
213
-    /**
214
-     * list of authentication classes
215
-     *
216
-     * @var array
217
-     */
218
-    protected $authClasses = array();
219
-    /**
220
-     * list of error handling classes
221
-     *
222
-     * @var array
223
-     */
224
-    protected $errorClasses = array();
225
-    protected $authenticated = false;
226
-    protected $authVerified = false;
227
-    /**
228
-     * @var mixed
229
-     */
230
-    protected $responseData;
231
-
232
-    /**
233
-     * Constructor
234
-     *
235
-     * @param boolean $productionMode    When set to false, it will run in
236
-     *                                   debug mode and parse the class files
237
-     *                                   every time to map it to the URL
238
-     *
239
-     * @param bool    $refreshCache      will update the cache when set to true
240
-     */
241
-    public function __construct($productionMode = false, $refreshCache = false)
242
-    {
243
-        parent::__construct();
244
-        $this->startTime = time();
245
-        Util::$restler = $this;
246
-        Scope::set('Restler', $this);
247
-        $this->productionMode = $productionMode;
248
-        if (is_null(Defaults::$cacheDirectory)) {
249
-            Defaults::$cacheDirectory = dirname($_SERVER['SCRIPT_FILENAME']) .
250
-                DIRECTORY_SEPARATOR . 'cache';
251
-        }
252
-        $this->cache = new Defaults::$cacheClass();
253
-        $this->refreshCache = $refreshCache;
254
-        // use this to rebuild cache every time in production mode
255
-        if ($productionMode && $refreshCache) {
256
-            $this->cached = false;
257
-        }
258
-    }
259
-
260
-    /**
261
-     * Main function for processing the api request
262
-     * and return the response
263
-     *
264
-     * @throws Exception     when the api service class is missing
265
-     * @throws RestException to send error response
266
-     */
267
-    public function handle()
268
-    {
269
-        try {
270
-            try {
271
-                try {
272
-                    $this->get();
273
-                } catch (Exception $e) {
274
-                    $this->requestData
275
-                        = array(Defaults::$fullRequestDataName => array());
276
-                    if (!$e instanceof RestException) {
277
-                        $e = new RestException(
278
-                            500,
279
-                            $this->productionMode ? null : $e->getMessage(),
280
-                            array(),
281
-                            $e
282
-                        );
283
-                    }
284
-                    $this->route();
285
-                    throw $e;
286
-                }
287
-                if (Defaults::$useVendorMIMEVersioning)
288
-                    $this->responseFormat = $this->negotiateResponseFormat();
289
-                $this->route();
290
-            } catch (Exception $e) {
291
-                $this->negotiate();
292
-                if (!$e instanceof RestException) {
293
-                    $e = new RestException(
294
-                        500,
295
-                        $this->productionMode ? null : $e->getMessage(),
296
-                        array(),
297
-                        $e
298
-                    );
299
-                }
300
-                throw $e;
301
-            }
302
-            $this->negotiate();
303
-            $this->preAuthFilter();
304
-            $this->authenticate();
305
-            $this->postAuthFilter();
306
-            $this->validate();
307
-            $this->preCall();
308
-            $this->call();
309
-            $this->compose();
310
-            $this->postCall();
311
-            if (Defaults::$returnResponse) {
312
-                return $this->respond();
313
-            }
314
-            $this->respond();
315
-        } catch (Exception $e) {
316
-            try{
317
-                if (Defaults::$returnResponse) {
318
-                    return $this->message($e);
319
-                }
320
-                $this->message($e);
321
-            } catch (Exception $e2) {
322
-                if (Defaults::$returnResponse) {
323
-                    return $this->message($e2);
324
-                }
325
-                $this->message($e2);
326
-            }
327
-        }
328
-    }
329
-
330
-    /**
331
-     * read the request details
332
-     *
333
-     * Find out the following
334
-     *  - baseUrl
335
-     *  - url requested
336
-     *  - version requested (if url based versioning)
337
-     *  - http verb/method
338
-     *  - negotiate content type
339
-     *  - request data
340
-     *  - set defaults
341
-     */
342
-    protected function get()
343
-    {
344
-        $this->dispatch('get');
345
-        if (empty($this->formatMap)) {
346
-            $this->setSupportedFormats('JsonFormat');
347
-        }
348
-        $this->url = $this->getPath();
349
-        $this->requestMethod = Util::getRequestMethod();
350
-        $this->requestFormat = $this->getRequestFormat();
351
-        $this->requestData = $this->getRequestData(false);
352
-
353
-        //parse defaults
354
-        foreach ($_GET as $key => $value) {
355
-            if (isset(Defaults::$aliases[$key])) {
356
-                $_GET[Defaults::$aliases[$key]] = $value;
357
-                unset($_GET[$key]);
358
-                $key = Defaults::$aliases[$key];
359
-            }
360
-            if (in_array($key, Defaults::$overridables)) {
361
-                Defaults::setProperty($key, $value);
362
-            }
363
-        }
364
-    }
365
-
366
-    /**
367
-     * Returns a list of the mime types (e.g.  ["application/json","application/xml"]) that the API can respond with
368
-     * @return array
369
-     */
370
-    public function getWritableMimeTypes()
371
-    {
372
-        return $this->writableMimeTypes;
373
-    }
374
-
375
-    /**
376
-     * Returns the list of Mime Types for the request that the API can understand
377
-     * @return array
378
-     */
379
-    public function getReadableMimeTypes()
380
-    {
381
-        return $this->readableMimeTypes;
382
-    }
383
-
384
-    /**
385
-     * Call this method and pass all the formats that should be  supported by
386
-     * the API Server. Accepts multiple parameters
387
-     *
388
-     * @param string ,... $formatName   class name of the format class that
389
-     *                                  implements iFormat
390
-     *
391
-     * @example $restler->setSupportedFormats('JsonFormat', 'XmlFormat'...);
392
-     * @throws Exception
393
-     */
394
-    public function setSupportedFormats($format = null /*[, $format2...$farmatN]*/)
395
-    {
396
-        $args = func_get_args();
397
-        $extensions = array();
398
-        $throwException = $this->requestFormatDiffered;
399
-        $this->writableMimeTypes = $this->readableMimeTypes = array();
400
-        foreach ($args as $className) {
401
-
402
-            $obj = Scope::get($className);
403
-
404
-            if (!$obj instanceof iFormat)
405
-                throw new Exception('Invalid format class; must implement ' .
406
-                    'iFormat interface');
407
-            if ($throwException && get_class($obj) == get_class($this->requestFormat)) {
408
-                $throwException = false;
409
-            }
410
-
411
-            foreach ($obj->getMIMEMap() as $mime => $extension) {
412
-                if($obj->isWritable()){
413
-                    $this->writableMimeTypes[]=$mime;
414
-                    $extensions[".$extension"] = true;
415
-                }
416
-                if($obj->isReadable())
417
-                    $this->readableMimeTypes[]=$mime;
418
-                if (!isset($this->formatMap[$extension]))
419
-                    $this->formatMap[$extension] = $className;
420
-                if (!isset($this->formatMap[$mime]))
421
-                    $this->formatMap[$mime] = $className;
422
-            }
423
-        }
424
-        if ($throwException) {
425
-            throw new RestException(
426
-                403,
427
-                'Content type `' . $this->requestFormat->getMIME() . '` is not supported.'
428
-            );
429
-        }
430
-        $this->formatMap['default'] = $args[0];
431
-        $this->formatMap['extensions'] = array_keys($extensions);
432
-    }
433
-
434
-    /**
435
-     * Call this method and pass all the formats that can be used to override
436
-     * the supported formats using `@format` comment. Accepts multiple parameters
437
-     *
438
-     * @param string ,... $formatName   class name of the format class that
439
-     *                                  implements iFormat
440
-     *
441
-     * @example $restler->setOverridingFormats('JsonFormat', 'XmlFormat'...);
442
-     * @throws Exception
443
-     */
444
-    public function setOverridingFormats($format = null /*[, $format2...$farmatN]*/)
445
-    {
446
-        $args = func_get_args();
447
-        $extensions = array();
448
-        foreach ($args as $className) {
449
-
450
-            $obj = Scope::get($className);
451
-
452
-            if (!$obj instanceof iFormat)
453
-                throw new Exception('Invalid format class; must implement ' .
454
-                    'iFormat interface');
455
-
456
-            foreach ($obj->getMIMEMap() as $mime => $extension) {
457
-                if (!isset($this->formatOverridesMap[$extension]))
458
-                    $this->formatOverridesMap[$extension] = $className;
459
-                if (!isset($this->formatOverridesMap[$mime]))
460
-                    $this->formatOverridesMap[$mime] = $className;
461
-                if($obj->isWritable())
462
-                    $extensions[".$extension"] = true;
463
-            }
464
-        }
465
-        $this->formatOverridesMap['extensions'] = array_keys($extensions);
466
-    }
467
-
468
-    /**
469
-     * Set one or more string to be considered as the base url
470
-     *
471
-     * When more than one base url is provided, restler will make
472
-     * use of $_SERVER['HTTP_HOST'] to find the right one
473
-     *
474
-     * @param string ,... $url
475
-     */
476
-    public function setBaseUrls($url /*[, $url2...$urlN]*/)
477
-    {
478
-        if (func_num_args() > 1) {
479
-            $urls = func_get_args();
480
-            usort($urls, function ($a, $b) {
481
-                return strlen($a) - strlen($b);
482
-            });
483
-            foreach ($urls as $u) {
484
-                if (0 === strpos($_SERVER['HTTP_HOST'], parse_url($u, PHP_URL_HOST))) {
485
-                    $this->baseUrl = $u;
486
-                    return;
487
-                }
488
-            }
489
-        }
490
-        $this->baseUrl = $url;
491
-    }
492
-
493
-    /**
494
-     * Parses the request url and get the api path
495
-     *
496
-     * @return string api path
497
-     */
498
-    protected function getPath()
499
-    {
500
-        // fix SCRIPT_NAME for PHP 5.4 built-in web server
501
-        if (false === strpos($_SERVER['SCRIPT_NAME'], '.php'))
502
-            $_SERVER['SCRIPT_NAME']
503
-                = '/' . substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT']) + 1);
504
-
505
-        list($base, $path) = Util::splitCommonPath(
506
-            strtok(urldecode($_SERVER['REQUEST_URI']), '?'), //remove query string
507
-            $_SERVER['SCRIPT_NAME']
508
-        );
509
-
510
-        if (!$this->baseUrl) {
511
-            // Fix port number retrieval if port is specified in HOST header.
512
-            $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
513
-            $portPos = strpos($host,":");
514
-            if ($portPos){
515
-               $port = substr($host,$portPos+1);
516
-            } else {
517
-               $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : '80';
518
-               $port = isset($_SERVER['HTTP_X_FORWARDED_PORT']) ? $_SERVER['HTTP_X_FORWARDED_PORT'] : $port; // Amazon ELB
519
-            }
520
-            $https = $port == '443' ||
521
-                (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || // Amazon ELB
522
-                (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on');
523
-            $baseUrl = ($https ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'];
524
-            if (!$https && $port != '80' || $https && $port != '443')
525
-                $baseUrl .= ':' . $port;
526
-            $this->baseUrl = $baseUrl . $base;
527
-        } elseif (!empty($base) && false === strpos($this->baseUrl, $base)) {
528
-            $this->baseUrl .= $base;
529
-        }
530
-
531
-        $path = str_replace(
532
-            array_merge(
533
-                $this->formatMap['extensions'],
534
-                $this->formatOverridesMap['extensions']
535
-            ),
536
-            '',
537
-            rtrim($path, '/') //remove trailing slash if found
538
-        );
539
-
540
-        if (Defaults::$useUrlBasedVersioning && strlen($path) && $path[0] == 'v') {
541
-            $version = intval(substr($path, 1));
542
-            if ($version && $version <= $this->apiVersion) {
543
-                $this->requestedApiVersion = $version;
544
-                $path = explode('/', $path, 2);
545
-                $path = count($path) == 2 ? $path[1] : '';
546
-            }
547
-        } else {
548
-            $this->requestedApiVersion = $this->apiMinimumVersion;
549
-        }
550
-        return $path;
551
-    }
552
-
553
-    /**
554
-     * Parses the request to figure out format of the request data
555
-     *
556
-     * @throws RestException
557
-     * @return iFormat any class that implements iFormat
558
-     * @example JsonFormat
559
-     */
560
-    protected function getRequestFormat()
561
-    {
562
-        $format = null ;
563
-        // check if client has sent any information on request format
564
-        if (
565
-            !empty($_SERVER['CONTENT_TYPE']) ||
566
-            (
567
-                !empty($_SERVER['HTTP_CONTENT_TYPE']) &&
568
-                $_SERVER['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']
569
-            )
570
-        ) {
571
-            $mime = $_SERVER['CONTENT_TYPE'];
572
-            if (false !== $pos = strpos($mime, ';')) {
573
-                $mime = substr($mime, 0, $pos);
574
-            }
575
-            if ($mime == UrlEncodedFormat::MIME)
576
-                $format = Scope::get('UrlEncodedFormat');
577
-            elseif (isset($this->formatMap[$mime])) {
578
-                $format = Scope::get($this->formatMap[$mime]);
579
-                $format->setMIME($mime);
580
-            } elseif (!$this->requestFormatDiffered && isset($this->formatOverridesMap[$mime])) {
581
-                //if our api method is not using an @format comment
582
-                //to point to this $mime, we need to throw 403 as in below
583
-                //but since we don't know that yet, we need to defer that here
584
-                $format = Scope::get($this->formatOverridesMap[$mime]);
585
-                $format->setMIME($mime);
586
-                $this->requestFormatDiffered = true;
587
-            } else {
588
-                throw new RestException(
589
-                    403,
590
-                    "Content type `$mime` is not supported."
591
-                );
592
-            }
593
-        }
594
-        if(!$format){
595
-            $format = Scope::get($this->formatMap['default']);
596
-        }
597
-        return $format;
598
-    }
599
-
600
-    public function getRequestStream()
601
-    {
602
-        static $tempStream = false;
603
-        if (!$tempStream) {
604
-            $tempStream = fopen('php://temp', 'r+');
605
-            $rawInput = fopen('php://input', 'r');
606
-            stream_copy_to_stream($rawInput, $tempStream);
607
-        }
608
-        rewind($tempStream);
609
-        return $tempStream;
610
-    }
611
-
612
-    /**
613
-     * Parses the request data and returns it
614
-     *
615
-     * @param bool $includeQueryParameters
616
-     *
617
-     * @return array php data
618
-     */
619
-    public function getRequestData($includeQueryParameters = true)
620
-    {
621
-        $get = UrlEncodedFormat::decoderTypeFix($_GET);
622
-        if ($this->requestMethod == 'PUT'
623
-            || $this->requestMethod == 'PATCH'
624
-            || $this->requestMethod == 'POST'
625
-        ) {
626
-            if (!empty($this->requestData)) {
627
-                return $includeQueryParameters
628
-                    ? $this->requestData + $get
629
-                    : $this->requestData;
630
-            }
631
-
632
-            $stream = $this->getRequestStream();
633
-            if($stream === FALSE)
634
-                return array();
635
-            $r = $this->requestFormat instanceof iDecodeStream
636
-                ? $this->requestFormat->decodeStream($stream)
637
-                : $this->requestFormat->decode(stream_get_contents($stream));
638
-
639
-            $r = is_array($r)
640
-                ? array_merge($r, array(Defaults::$fullRequestDataName => $r))
641
-                : array(Defaults::$fullRequestDataName => $r);
642
-            return $includeQueryParameters
643
-                ? $r + $get
644
-                : $r;
645
-        }
646
-        return $includeQueryParameters ? $get : array(); //no body
647
-    }
648
-
649
-    /**
650
-     * Find the api method to execute for the requested Url
651
-     */
652
-    protected function route()
653
-    {
654
-        $this->dispatch('route');
655
-
656
-        $params = $this->getRequestData();
657
-
658
-        //backward compatibility for restler 2 and below
659
-        if (!Defaults::$smartParameterParsing) {
660
-            $params = $params + array(Defaults::$fullRequestDataName => $params);
661
-        }
662
-
663
-        $this->apiMethodInfo = $o = Routes::find(
664
-            $this->url, $this->requestMethod,
665
-            $this->requestedApiVersion, $params
666
-        );
667
-        //set defaults based on api method comments
668
-        if (isset($o->metadata)) {
669
-            foreach (Defaults::$fromComments as $key => $defaultsKey) {
670
-                if (array_key_exists($key, $o->metadata)) {
671
-                    $value = $o->metadata[$key];
672
-                    Defaults::setProperty($defaultsKey, $value);
673
-                }
674
-            }
675
-        }
676
-        if (!isset($o->className))
677
-            throw new RestException(404);
678
-
679
-        if(isset($this->apiVersionMap[$o->className])){
680
-            Scope::$classAliases[Util::getShortName($o->className)]
681
-                = $this->apiVersionMap[$o->className][$this->requestedApiVersion];
682
-        }
683
-
684
-        foreach ($this->authClasses as $auth) {
685
-            if (isset($this->apiVersionMap[$auth])) {
686
-                Scope::$classAliases[$auth] = $this->apiVersionMap[$auth][$this->requestedApiVersion];
687
-            } elseif (isset($this->apiVersionMap[Scope::$classAliases[$auth]])) {
688
-                Scope::$classAliases[$auth]
689
-                    = $this->apiVersionMap[Scope::$classAliases[$auth]][$this->requestedApiVersion];
690
-            }
691
-        }
692
-    }
693
-
694
-    /**
695
-     * Negotiate the response details such as
696
-     *  - cross origin resource sharing
697
-     *  - media type
698
-     *  - charset
699
-     *  - language
700
-     *
701
-     * @throws RestException
702
-     */
703
-    protected function negotiate()
704
-    {
705
-        $this->dispatch('negotiate');
706
-        $this->negotiateCORS();
707
-        $this->responseFormat = $this->negotiateResponseFormat();
708
-        $this->negotiateCharset();
709
-        $this->negotiateLanguage();
710
-    }
711
-
712
-    protected function negotiateCORS()
713
-    {
714
-        if (
715
-            $this->requestMethod == 'OPTIONS'
716
-            && Defaults::$crossOriginResourceSharing
717
-        ) {
718
-            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
719
-                header('Access-Control-Allow-Methods: '
720
-                    . Defaults::$accessControlAllowMethods);
721
-
722
-            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
723
-                header('Access-Control-Allow-Headers: '
724
-                    . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
725
-
726
-            header('Access-Control-Allow-Origin: ' .
727
-                ((Defaults::$accessControlAllowOrigin == '*' && isset($_SERVER['HTTP_ORIGIN']))
728
-                    ? $_SERVER['HTTP_ORIGIN'] : Defaults::$accessControlAllowOrigin));
729
-            header('Access-Control-Allow-Credentials: true');
730
-
731
-            exit(0);
732
-        }
733
-    }
734
-
735
-    // ==================================================================
736
-    //
737
-    // Protected functions
738
-    //
739
-    // ------------------------------------------------------------------
740
-
741
-    /**
742
-     * Parses the request to figure out the best format for response.
743
-     * Extension, if present, overrides the Accept header
744
-     *
745
-     * @throws RestException
746
-     * @return iFormat
747
-     * @example JsonFormat
748
-     */
749
-    protected function negotiateResponseFormat()
750
-    {
751
-        $metadata = Util::nestedValue($this, 'apiMethodInfo', 'metadata');
752
-        //check if the api method insists on response format using @format comment
753
-
754
-        if ($metadata && isset($metadata['format'])) {
755
-            $formats = explode(',', (string)$metadata['format']);
756
-            foreach ($formats as $i => $f) {
757
-                $f = trim($f);
758
-                if (!in_array($f, $this->formatOverridesMap))
759
-                    throw new RestException(
760
-                        500,
761
-                        "Given @format is not present in overriding formats. Please call `\$r->setOverridingFormats('$f');` first."
762
-                    );
763
-                $formats[$i] = $f;
764
-            }
765
-            call_user_func_array(array($this, 'setSupportedFormats'), $formats);
766
-        }
767
-
768
-        // check if client has specified an extension
769
-        /** @var $format iFormat*/
770
-        $format = null;
771
-        $extensions = explode(
772
-            '.',
773
-            parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
774
-        );
775
-        while ($extensions) {
776
-            $extension = array_pop($extensions);
777
-            $extension = explode('/', $extension);
778
-            $extension = array_shift($extension);
779
-            if ($extension && isset($this->formatMap[$extension])) {
780
-                $format = Scope::get($this->formatMap[$extension]);
781
-                $format->setExtension($extension);
782
-                // echo "Extension $extension";
783
-                return $format;
784
-            }
785
-        }
786
-        // check if client has sent list of accepted data formats
787
-        if (isset($_SERVER['HTTP_ACCEPT'])) {
788
-            $acceptList = Util::sortByPriority($_SERVER['HTTP_ACCEPT']);
789
-            foreach ($acceptList as $accept => $quality) {
790
-                if (isset($this->formatMap[$accept])) {
791
-                    $format = Scope::get($this->formatMap[$accept]);
792
-                    $format->setMIME($accept);
793
-                    //echo "MIME $accept";
794
-                    // Tell cache content is based on Accept header
795
-                    @header('Vary: Accept');
796
-
797
-                    return $format;
798
-                } elseif (false !== ($index = strrpos($accept, '+'))) {
799
-                    $mime = substr($accept, 0, $index);
800
-                    if (is_string(Defaults::$apiVendor)
801
-                        && 0 === stripos($mime,
802
-                            'application/vnd.'
803
-                            . Defaults::$apiVendor . '-v')
804
-                    ) {
805
-                        $extension = substr($accept, $index + 1);
806
-                        if (isset($this->formatMap[$extension])) {
807
-                            //check the MIME and extract version
808
-                            $version = intval(substr($mime,
809
-                                18 + strlen(Defaults::$apiVendor)));
810
-                            if ($version > 0 && $version <= $this->apiVersion) {
811
-                                $this->requestedApiVersion = $version;
812
-                                $format = Scope::get($this->formatMap[$extension]);
813
-                                $format->setExtension($extension);
814
-                                // echo "Extension $extension";
815
-                                Defaults::$useVendorMIMEVersioning = true;
816
-                                @header('Vary: Accept');
817
-
818
-                                return $format;
819
-                            }
820
-                        }
821
-                    }
822
-
823
-                }
824
-            }
825
-        } else {
826
-            // RFC 2616: If no Accept header field is
827
-            // present, then it is assumed that the
828
-            // client accepts all media types.
829
-            $_SERVER['HTTP_ACCEPT'] = '*/*';
830
-        }
831
-        if (strpos($_SERVER['HTTP_ACCEPT'], '*') !== false) {
832
-            if (false !== strpos($_SERVER['HTTP_ACCEPT'], 'application/*')) {
833
-                $format = Scope::get('JsonFormat');
834
-            } elseif (false !== strpos($_SERVER['HTTP_ACCEPT'], 'text/*')) {
835
-                $format = Scope::get('XmlFormat');
836
-            } elseif (false !== strpos($_SERVER['HTTP_ACCEPT'], '*/*')) {
837
-                $format = Scope::get($this->formatMap['default']);
838
-            }
839
-        }
840
-        if (empty($format)) {
841
-            // RFC 2616: If an Accept header field is present, and if the
842
-            // server cannot send a response which is acceptable according to
843
-            // the combined Accept field value, then the server SHOULD send
844
-            // a 406 (not acceptable) response.
845
-            $format = Scope::get($this->formatMap['default']);
846
-            $this->responseFormat = $format;
847
-            throw new RestException(
848
-                406,
849
-                'Content negotiation failed. ' .
850
-                'Try `' . $format->getMIME() . '` instead.'
851
-            );
852
-        } else {
853
-            // Tell cache content is based at Accept header
854
-            @header("Vary: Accept");
855
-            return $format;
856
-        }
857
-    }
858
-
859
-    protected function negotiateCharset()
860
-    {
861
-        if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
862
-            $found = false;
863
-            $charList = Util::sortByPriority($_SERVER['HTTP_ACCEPT_CHARSET']);
864
-            foreach ($charList as $charset => $quality) {
865
-                if (in_array($charset, Defaults::$supportedCharsets)) {
866
-                    $found = true;
867
-                    Defaults::$charset = $charset;
868
-                    break;
869
-                }
870
-            }
871
-            if (!$found) {
872
-                if (strpos($_SERVER['HTTP_ACCEPT_CHARSET'], '*') !== false) {
873
-                    //use default charset
874
-                } else {
875
-                    throw new RestException(
876
-                        406,
877
-                        'Content negotiation failed. ' .
878
-                        'Requested charset is not supported'
879
-                    );
880
-                }
881
-            }
882
-        }
883
-    }
884
-
885
-    protected function negotiateLanguage()
886
-    {
887
-        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
888
-            $found = false;
889
-            $langList = Util::sortByPriority($_SERVER['HTTP_ACCEPT_LANGUAGE']);
890
-            foreach ($langList as $lang => $quality) {
891
-                foreach (Defaults::$supportedLanguages as $supported) {
892
-                    if (strcasecmp($supported, $lang) == 0) {
893
-                        $found = true;
894
-                        Defaults::$language = $supported;
895
-                        break 2;
896
-                    }
897
-                }
898
-            }
899
-            if (!$found) {
900
-                if (strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], '*') !== false) {
901
-                    //use default language
902
-                } else {
903
-                    //ignore
904
-                }
905
-            }
906
-        }
907
-    }
908
-
909
-    /**
910
-     * Filer api calls before authentication
911
-     */
912
-    protected function preAuthFilter()
913
-    {
914
-        if (empty($this->filterClasses)) {
915
-            return;
916
-        }
917
-        $this->dispatch('preAuthFilter');
918
-        foreach ($this->filterClasses as $filterClass) {
919
-            /**
920
-             * @var iFilter
921
-             */
922
-            $filterObj = Scope::get($filterClass);
923
-
924
-            if (!$filterObj instanceof iFilter) {
925
-                throw new RestException (
926
-                    500, 'Filter Class ' .
927
-                    'should implement iFilter');
928
-            } else if (!($ok = $filterObj->__isAllowed())) {
929
-                if (is_null($ok)
930
-                    && $filterObj instanceof iUseAuthentication
931
-                ) {
932
-                    //handle at authentication stage
933
-                    $this->postAuthFilterClasses[] = $filterClass;
934
-                    continue;
935
-                }
936
-                throw new RestException(403); //Forbidden
937
-            }
938
-        }
939
-    }
940
-
941
-    protected function authenticate()
942
-    {
943
-        $o = &$this->apiMethodInfo;
944
-        $accessLevel = max(Defaults::$apiAccessLevel, $o->accessLevel);
945
-        if ($accessLevel || count($this->postAuthFilterClasses)) {
946
-            $this->dispatch('authenticate');
947
-            if (!count($this->authClasses) && $accessLevel > 1) {
948
-                throw new RestException(
949
-                    403,
950
-                    'at least one Authentication Class is required'
951
-                );
952
-            }
953
-            $unauthorized = false;
954
-            foreach ($this->authClasses as $authClass) {
955
-                try {
956
-                    $authObj = Scope::get($authClass);
957
-                    if (!method_exists($authObj, Defaults::$authenticationMethod)) {
958
-                        throw new RestException (
959
-                            500, 'Authentication Class ' .
960
-                            'should implement iAuthenticate');
961
-                    } elseif (
962
-                    !$authObj->{Defaults::$authenticationMethod}()
963
-                    ) {
964
-                        throw new RestException(401);
965
-                    }
966
-                    $unauthorized = false;
967
-                    break;
968
-                } catch (InvalidAuthCredentials $e) {
969
-                    $this->authenticated = false;
970
-                    throw $e;
971
-                } catch (RestException $e) {
972
-                    if (!$unauthorized) {
973
-                        $unauthorized = $e;
974
-                    }
975
-                }
976
-            }
977
-            $this->authVerified = true;
978
-            if ($unauthorized) {
979
-                if ($accessLevel > 1) { //when it is not a hybrid api
980
-                    throw $unauthorized;
981
-                } else {
982
-                    $this->authenticated = false;
983
-                }
984
-            } else {
985
-                $this->authenticated = true;
986
-            }
987
-        }
988
-    }
989
-
990
-    /**
991
-     * Filer api calls after authentication
992
-     */
993
-    protected function postAuthFilter()
994
-    {
995
-        if(empty($this->postAuthFilterClasses)) {
996
-            return;
997
-        }
998
-        $this->dispatch('postAuthFilter');
999
-        foreach ($this->postAuthFilterClasses as $filterClass) {
1000
-            Scope::get($filterClass);
1001
-        }
1002
-    }
1003
-
1004
-    protected function validate()
1005
-    {
1006
-        if (!Defaults::$autoValidationEnabled) {
1007
-            return;
1008
-        }
1009
-        $this->dispatch('validate');
1010
-
1011
-        $o = & $this->apiMethodInfo;
1012
-        foreach ($o->metadata['param'] as $index => $param) {
1013
-            $info = & $param [CommentParser::$embeddedDataName];
1014
-            if (!isset ($info['validate'])
1015
-                || $info['validate'] != false
1016
-            ) {
1017
-                if (isset($info['method'])) {
1018
-                    $info ['apiClassInstance'] = Scope::get($o->className);
1019
-                }
1020
-                //convert to instance of ValidationInfo
1021
-                $info = new ValidationInfo($param);
1022
-                //initialize validator
1023
-                Scope::get(Defaults::$validatorClass);
1024
-                $validator = Defaults::$validatorClass;
1025
-                //if(!is_subclass_of($validator, 'Luracast\\Restler\\Data\\iValidate')) {
1026
-                //changed the above test to below for addressing this php bug
1027
-                //https://bugs.php.net/bug.php?id=53727
1028
-                if (function_exists("$validator::validate")) {
1029
-                    throw new \UnexpectedValueException(
1030
-                        '`Defaults::$validatorClass` must implement `iValidate` interface'
1031
-                    );
1032
-                }
1033
-                $valid = $o->parameters[$index];
1034
-                $o->parameters[$index] = null;
1035
-                if (empty(Validator::$exceptions))
1036
-                    $o->metadata['param'][$index]['autofocus'] = true;
1037
-                $valid = $validator::validate(
1038
-                    $valid, $info
1039
-                );
1040
-                $o->parameters[$index] = $valid;
1041
-                unset($o->metadata['param'][$index]['autofocus']);
1042
-            }
1043
-        }
1044
-    }
1045
-
1046
-    protected function call()
1047
-    {
1048
-        $this->dispatch('call');
1049
-        $o = & $this->apiMethodInfo;
1050
-        $accessLevel = max(Defaults::$apiAccessLevel,
1051
-            $o->accessLevel);
1052
-        if (function_exists('newrelic_name_transaction'))
1053
-            newrelic_name_transaction("{$o->className}/{$o->methodName}");
1054
-        $object =  Scope::get($o->className);
1055
-        switch ($accessLevel) {
1056
-            case 3 : //protected method
1057
-                $reflectionMethod = new \ReflectionMethod(
1058
-                    $object,
1059
-                    $o->methodName
1060
-                );
1061
-                $reflectionMethod->setAccessible(true);
1062
-                $result = $reflectionMethod->invokeArgs(
1063
-                    $object,
1064
-                    $o->parameters
1065
-                );
1066
-                break;
1067
-            default :
1068
-                $result = call_user_func_array(array(
1069
-                    $object,
1070
-                    $o->methodName
1071
-                ), $o->parameters);
1072
-        }
1073
-        $this->responseData = $result;
1074
-    }
1075
-
1076
-    protected function compose()
1077
-    {
1078
-        $this->dispatch('compose');
1079
-        $this->composeHeaders();
1080
-        /**
1081
-         * @var iCompose Default Composer
1082
-         */
1083
-        $compose = Scope::get(Defaults::$composeClass);
1084
-        $this->responseData = is_null($this->responseData) &&
1085
-        Defaults::$emptyBodyForNullResponse
1086
-            ? ''
1087
-            : $this->responseFormat->encode(
1088
-                $compose->response($this->responseData),
1089
-                !$this->productionMode
1090
-            );
1091
-    }
1092
-
1093
-    public function composeHeaders(RestException $e = null)
1094
-    {
1095
-        //only GET method should be cached if allowed by API developer
1096
-        $expires = $this->requestMethod == 'GET' ? Defaults::$headerExpires : 0;
1097
-        if(!is_array(Defaults::$headerCacheControl))
1098
-            Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
1099
-        $cacheControl = Defaults::$headerCacheControl[0];
1100
-        if ($expires > 0) {
1101
-            $cacheControl = $this->apiMethodInfo->accessLevel
1102
-                ? 'private, ' : 'public, ';
1103
-            $cacheControl .= end(Defaults::$headerCacheControl);
1104
-            $cacheControl = str_replace('{expires}', $expires, $cacheControl);
1105
-            $expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
1106
-        }
1107
-        @header('Cache-Control: ' . $cacheControl);
1108
-        @header('Expires: ' . $expires);
1109
-        @header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
1110
-
1111
-        if (Defaults::$crossOriginResourceSharing
1112
-            && isset($_SERVER['HTTP_ORIGIN'])
1113
-        ) {
1114
-            header('Access-Control-Allow-Origin: ' .
1115
-                (Defaults::$accessControlAllowOrigin == '*'
1116
-                    ? $_SERVER['HTTP_ORIGIN']
1117
-                    : Defaults::$accessControlAllowOrigin)
1118
-            );
1119
-            header('Access-Control-Allow-Credentials: true');
1120
-            header('Access-Control-Max-Age: 86400');
1121
-        }
1122
-
1123
-        $this->responseFormat->setCharset(Defaults::$charset);
1124
-        $charset = $this->responseFormat->getCharset()
1125
-            ? : Defaults::$charset;
1126
-
1127
-        @header('Content-Type: ' . (
1128
-            Defaults::$useVendorMIMEVersioning
1129
-                ? 'application/vnd.'
1130
-                . Defaults::$apiVendor
1131
-                . "-v{$this->requestedApiVersion}"
1132
-                . '+' . $this->responseFormat->getExtension()
1133
-                : $this->responseFormat->getMIME())
1134
-            . '; charset=' . $charset
1135
-        );
1136
-
1137
-        @header('Content-Language: ' . Defaults::$language);
1138
-
1139
-        if (isset($this->apiMethodInfo->metadata['header'])) {
1140
-            foreach ($this->apiMethodInfo->metadata['header'] as $header)
1141
-                @header($header, true);
1142
-        }
1143
-        $code = 200;
1144
-        if (!Defaults::$suppressResponseCode) {
1145
-            if ($e) {
1146
-                $code = $e->getCode();
1147
-            } elseif ($this->responseCode) {
1148
-                $code = $this->responseCode;
1149
-            } elseif (isset($this->apiMethodInfo->metadata['status'])) {
1150
-                $code = $this->apiMethodInfo->metadata['status'];
1151
-            }
1152
-        }
1153
-        $this->responseCode = $code;
1154
-        @header(
1155
-            "{$_SERVER['SERVER_PROTOCOL']} $code " .
1156
-            (isset(RestException::$codes[$code]) ? RestException::$codes[$code] : '')
1157
-        );
1158
-    }
1159
-
1160
-    protected function respond()
1161
-    {
1162
-        $this->dispatch('respond');
1163
-        //handle throttling
1164
-        if (Defaults::$throttle) {
1165
-            $elapsed = time() - $this->startTime;
1166
-            if (Defaults::$throttle / 1e3 > $elapsed) {
1167
-                usleep(1e6 * (Defaults::$throttle / 1e3 - $elapsed));
1168
-            }
1169
-        }
1170
-        if ($this->responseCode == 401) {
1171
-            $authString = count($this->authClasses)
1172
-                ? Scope::get($this->authClasses[0])->__getWWWAuthenticateString()
1173
-                : 'Unknown';
1174
-            @header('WWW-Authenticate: ' . $authString, false);
1175
-        }
1176
-        $this->dispatch('complete');
1177
-        if (Defaults::$returnResponse) {
1178
-            return $this->responseData;
1179
-        } else {
1180
-            echo $this->responseData;
1181
-            exit;
1182
-        }
1183
-    }
1184
-
1185
-    protected function message(Exception $exception)
1186
-    {
1187
-        $this->dispatch('message');
1188
-
1189
-        if (!$exception instanceof RestException) {
1190
-            $exception = new RestException(
1191
-                500,
1192
-                $this->productionMode ? null : $exception->getMessage(),
1193
-                array(),
1194
-                $exception
1195
-            );
1196
-        }
1197
-
1198
-        $this->exception = $exception;
1199
-
1200
-        $method = 'handle' . $exception->getCode();
1201
-        $handled = false;
1202
-        foreach ($this->errorClasses as $className) {
1203
-            if (method_exists($className, $method)) {
1204
-                $obj = Scope::get($className);
1205
-                if ($obj->$method($exception))
1206
-                    $handled = true;
1207
-            }
1208
-        }
1209
-        if ($handled) {
1210
-            return;
1211
-        }
1212
-        if (!isset($this->responseFormat)) {
1213
-            $this->responseFormat = Scope::get('JsonFormat');
1214
-        }
1215
-        $this->composeHeaders($exception);
1216
-        /**
1217
-         * @var iCompose Default Composer
1218
-         */
1219
-        $compose = Scope::get(Defaults::$composeClass);
1220
-        $this->responseData = $this->responseFormat->encode(
1221
-            $compose->message($exception),
1222
-            !$this->productionMode
1223
-        );
1224
-        if (Defaults::$returnResponse) {
1225
-            return $this->respond();
1226
-        }
1227
-        $this->respond();
1228
-    }
1229
-
1230
-    /**
1231
-     * Provides backward compatibility with older versions of Restler
1232
-     *
1233
-     * @param int $version restler version
1234
-     *
1235
-     * @throws \OutOfRangeException
1236
-     */
1237
-    public function setCompatibilityMode($version = 2)
1238
-    {
1239
-        if ($version <= intval(self::VERSION) && $version > 0) {
1240
-            require __DIR__."/compatibility/restler{$version}.php";
1241
-            return;
1242
-        }
1243
-        throw new \OutOfRangeException();
1244
-    }
1245
-
1246
-    /**
1247
-     * @param int $version                 maximum version number supported
1248
-     *                                     by  the api
1249
-     * @param int $minimum                 minimum version number supported
1250
-     * (optional)
1251
-     *
1252
-     * @throws InvalidArgumentException
1253
-     * @return void
1254
-     */
1255
-    public function setAPIVersion($version = 1, $minimum = 1)
1256
-    {
1257
-        if (!is_int($version) && $version < 1) {
1258
-            throw new InvalidArgumentException
1259
-            ('version should be an integer greater than 0');
1260
-        }
1261
-        $this->apiVersion = $version;
1262
-        if (is_int($minimum)) {
1263
-            $this->apiMinimumVersion = $minimum;
1264
-        }
1265
-    }
1266
-
1267
-    /**
1268
-     * Classes implementing iFilter interface can be added for filtering out
1269
-     * the api consumers.
1270
-     *
1271
-     * It can be used for rate limiting based on usage from a specific ip
1272
-     * address or filter by country, device etc.
1273
-     *
1274
-     * @param $className
1275
-     */
1276
-    public function addFilterClass($className)
1277
-    {
1278
-        $this->filterClasses[] = $className;
1279
-    }
1280
-
1281
-    /**
1282
-     * protected methods will need at least one authentication class to be set
1283
-     * in order to allow that method to be executed
1284
-     *
1285
-     * @param string $className     of the authentication class
1286
-     * @param string $resourcePath  optional url prefix for mapping
1287
-     */
1288
-    public function addAuthenticationClass($className, $resourcePath = null)
1289
-    {
1290
-        $this->authClasses[] = $className;
1291
-        $this->addAPIClass($className, $resourcePath);
1292
-    }
1293
-
1294
-    /**
1295
-     * Add api classes through this method.
1296
-     *
1297
-     * All the public methods that do not start with _ (underscore)
1298
-     * will be will be exposed as the public api by default.
1299
-     *
1300
-     * All the protected methods that do not start with _ (underscore)
1301
-     * will exposed as protected api which will require authentication
1302
-     *
1303
-     * @param string $className       name of the service class
1304
-     * @param string $resourcePath    optional url prefix for mapping, uses
1305
-     *                                lowercase version of the class name when
1306
-     *                                not specified
1307
-     *
1308
-     * @return null
1309
-     *
1310
-     * @throws Exception when supplied with invalid class name
1311
-     */
1312
-    public function addAPIClass($className, $resourcePath = null)
1313
-    {
1314
-        try{
1315
-            if ($this->productionMode && is_null($this->cached)) {
1316
-                $routes = $this->cache->get('routes');
1317
-                if (isset($routes) && is_array($routes)) {
1318
-                    $this->apiVersionMap = $routes['apiVersionMap'];
1319
-                    unset($routes['apiVersionMap']);
1320
-                    Routes::fromArray($routes);
1321
-                    $this->cached = true;
1322
-                } else {
1323
-                    $this->cached = false;
1324
-                }
1325
-            }
1326
-            if (isset(Scope::$classAliases[$className])) {
1327
-                $className = Scope::$classAliases[$className];
1328
-            }
1329
-            if (!$this->cached) {
1330
-                $maxVersionMethod = '__getMaximumSupportedVersion';
1331
-                if (class_exists($className)) {
1332
-                    if (method_exists($className, $maxVersionMethod)) {
1333
-                        $max = $className::$maxVersionMethod();
1334
-                        for ($i = 1; $i <= $max; $i++) {
1335
-                            $this->apiVersionMap[$className][$i] = $className;
1336
-                        }
1337
-                    } else {
1338
-                        $this->apiVersionMap[$className][1] = $className;
1339
-                    }
1340
-                }
1341
-                //versioned api
1342
-                if (false !== ($index = strrpos($className, '\\'))) {
1343
-                    $name = substr($className, 0, $index)
1344
-                        . '\\v{$version}' . substr($className, $index);
1345
-                } else if (false !== ($index = strrpos($className, '_'))) {
1346
-                    $name = substr($className, 0, $index)
1347
-                        . '_v{$version}' . substr($className, $index);
1348
-                } else {
1349
-                    $name = 'v{$version}\\' . $className;
1350
-                }
1351
-
1352
-                for ($version = $this->apiMinimumVersion;
1353
-                     $version <= $this->apiVersion;
1354
-                     $version++) {
1355
-
1356
-                    $versionedClassName = str_replace('{$version}', $version,
1357
-                        $name);
1358
-                    if (class_exists($versionedClassName)) {
1359
-                        Routes::addAPIClass($versionedClassName,
1360
-                            Util::getResourcePath(
1361
-                                $className,
1362
-                                $resourcePath
1363
-                            ),
1364
-                            $version
1365
-                        );
1366
-                        if (method_exists($versionedClassName, $maxVersionMethod)) {
1367
-                            $max = $versionedClassName::$maxVersionMethod();
1368
-                            for ($i = $version; $i <= $max; $i++) {
1369
-                                $this->apiVersionMap[$className][$i] = $versionedClassName;
1370
-                            }
1371
-                        } else {
1372
-                            $this->apiVersionMap[$className][$version] = $versionedClassName;
1373
-                        }
1374
-                    } elseif (isset($this->apiVersionMap[$className][$version])) {
1375
-                        Routes::addAPIClass($this->apiVersionMap[$className][$version],
1376
-                            Util::getResourcePath(
1377
-                                $className,
1378
-                                $resourcePath
1379
-                            ),
1380
-                            $version
1381
-                        );
1382
-                    }
1383
-                }
1384
-
1385
-            }
1386
-        } catch (Exception $e) {
1387
-            $e = new Exception(
1388
-                "addAPIClass('$className') failed. ".$e->getMessage(),
1389
-                $e->getCode(),
1390
-                $e
1391
-            );
1392
-            $this->setSupportedFormats('JsonFormat');
1393
-            $this->message($e);
1394
-        }
1395
-    }
1396
-
1397
-    /**
1398
-     * Add class for custom error handling
1399
-     *
1400
-     * @param string $className   of the error handling class
1401
-     */
1402
-    public function addErrorClass($className)
1403
-    {
1404
-        $this->errorClasses[] = $className;
1405
-    }
1406
-
1407
-    /**
1408
-     * protected methods will need at least one authentication class to be set
1409
-     * in order to allow that method to be executed.  When multiple authentication
1410
-     * classes are in use, this function provides better performance by setting
1411
-     * all auth classes through a single function call.
1412
-     *
1413
-     * @param array $classNames     array of associative arrays containing
1414
-     *                              the authentication class name & optional
1415
-     *                              url prefix for mapping.
1416
-     */
1417
-    public function setAuthClasses(array $classNames)
1418
-    {
1419
-        $this->authClasses = array_merge($this->authClasses, array_values($classNames));
1420
-    }
1421
-
1422
-    /**
1423
-     * Add multiple api classes through this method.
1424
-     *
1425
-     * This method provides better performance when large number
1426
-     * of API classes are in use as it processes them all at once,
1427
-     * as opposed to hundreds (or more) addAPIClass calls.
1428
-     *
1429
-     *
1430
-     * All the public methods that do not start with _ (underscore)
1431
-     * will be will be exposed as the public api by default.
1432
-     *
1433
-     * All the protected methods that do not start with _ (underscore)
1434
-     * will exposed as protected api which will require authentication
1435
-     *
1436
-     * @param array $map        array of associative arrays containing
1437
-     *                          the class name & optional url prefix
1438
-     *                          for mapping.
1439
-     *
1440
-     * @return null
1441
-     *
1442
-     * @throws Exception when supplied with invalid class name
1443
-     */
1444
-    public function mapAPIClasses(array $map)
1445
-    {
1446
-        try {
1447
-            if ($this->productionMode && is_null($this->cached)) {
1448
-                $routes = $this->cache->get('routes');
1449
-                if (isset($routes) && is_array($routes)) {
1450
-                    $this->apiVersionMap = $routes['apiVersionMap'];
1451
-                    unset($routes['apiVersionMap']);
1452
-                    Routes::fromArray($routes);
1453
-                    $this->cached = true;
1454
-                } else {
1455
-                    $this->cached = false;
1456
-                }
1457
-            }
1458
-            $maxVersionMethod = '__getMaximumSupportedVersion';
1459
-            if (!$this->productionMode || !$this->cached) {
1460
-                foreach ($map as $className => $resourcePath) {
1461
-                    if (is_numeric($className)) {
1462
-                        $className = $resourcePath;
1463
-                        $resourcePath = null;
1464
-                    }
1465
-                    if (isset(Scope::$classAliases[$className])) {
1466
-                        $className = Scope::$classAliases[$className];
1467
-                    }
1468
-                    if (class_exists($className)) {
1469
-                        if (method_exists($className, $maxVersionMethod)) {
1470
-                            $max = $className::$maxVersionMethod();
1471
-                            for ($i = 1; $i <= $max; $i++) {
1472
-                                $this->apiVersionMap[$className][$i] = $className;
1473
-                            }
1474
-                        } else {
1475
-                            $this->apiVersionMap[$className][1] = $className;
1476
-                        }
1477
-                    }
1478
-                    //versioned api
1479
-                    if (false !== ($index = strrpos($className, '\\'))) {
1480
-                        $name = substr($className, 0, $index)
1481
-                            . '\\v{$version}' . substr($className, $index);
1482
-                    } else {
1483
-                        if (false !== ($index = strrpos($className, '_'))) {
1484
-                            $name = substr($className, 0, $index)
1485
-                                . '_v{$version}' . substr($className, $index);
1486
-                        } else {
1487
-                            $name = 'v{$version}\\' . $className;
1488
-                        }
1489
-                    }
1490
-
1491
-                    for ($version = $this->apiMinimumVersion;
1492
-                         $version <= $this->apiVersion;
1493
-                         $version++) {
1494
-
1495
-                        $versionedClassName = str_replace('{$version}', $version,
1496
-                            $name);
1497
-                        if (class_exists($versionedClassName)) {
1498
-                            Routes::addAPIClass($versionedClassName,
1499
-                                Util::getResourcePath(
1500
-                                    $className,
1501
-                                    $resourcePath
1502
-                                ),
1503
-                                $version
1504
-                            );
1505
-                            if (method_exists($versionedClassName, $maxVersionMethod)) {
1506
-                                $max = $versionedClassName::$maxVersionMethod();
1507
-                                for ($i = $version; $i <= $max; $i++) {
1508
-                                    $this->apiVersionMap[$className][$i] = $versionedClassName;
1509
-                                }
1510
-                            } else {
1511
-                                $this->apiVersionMap[$className][$version] = $versionedClassName;
1512
-                            }
1513
-                        } elseif (isset($this->apiVersionMap[$className][$version])) {
1514
-                            Routes::addAPIClass($this->apiVersionMap[$className][$version],
1515
-                                Util::getResourcePath(
1516
-                                    $className,
1517
-                                    $resourcePath
1518
-                                ),
1519
-                                $version
1520
-                            );
1521
-                        }
1522
-                    }
1523
-                }
1524
-            }
1525
-        } catch (Exception $e) {
1526
-            $e = new Exception(
1527
-                "mapAPIClasses failed. " . $e->getMessage(),
1528
-                $e->getCode(),
1529
-                $e
1530
-            );
1531
-            $this->setSupportedFormats('JsonFormat');
1532
-            $this->message($e);
1533
-        }
1534
-    }
1535
-
1536
-    /**
1537
-     * Associated array that maps formats to their respective format class name
1538
-     *
1539
-     * @return array
1540
-     */
1541
-    public function getFormatMap()
1542
-    {
1543
-        return $this->formatMap;
1544
-    }
1545
-
1546
-    /**
1547
-     * API version requested by the client
1548
-     * @return int
1549
-     */
1550
-    public function getRequestedApiVersion()
1551
-    {
1552
-        return $this->requestedApiVersion;
1553
-    }
1554
-
1555
-    /**
1556
-     * When false, restler will run in debug mode and parse the class files
1557
-     * every time to map it to the URL
1558
-     *
1559
-     * @return bool
1560
-     */
1561
-    public function getProductionMode()
1562
-    {
1563
-        return $this->productionMode;
1564
-    }
1565
-
1566
-    /**
1567
-     * Chosen API version
1568
-     *
1569
-     * @return int
1570
-     */
1571
-    public function getApiVersion()
1572
-    {
1573
-        return $this->apiVersion;
1574
-    }
1575
-
1576
-    /**
1577
-     * Base Url of the API Service
1578
-     *
1579
-     * @return string
1580
-     *
1581
-     * @example http://localhost/restler3
1582
-     * @example http://restler3.com
1583
-     */
1584
-    public function getBaseUrl()
1585
-    {
1586
-        return $this->baseUrl;
1587
-    }
1588
-
1589
-    /**
1590
-     * List of events that fired already
1591
-     *
1592
-     * @return array
1593
-     */
1594
-    public function getEvents()
1595
-    {
1596
-        return $this->events;
1597
-    }
1598
-
1599
-    /**
1600
-     * Magic method to expose some protected variables
1601
-     *
1602
-     * @param string $name name of the hidden property
1603
-     *
1604
-     * @return null|mixed
1605
-     */
1606
-    public function __get($name)
1607
-    {
1608
-        if ($name[0] == '_') {
1609
-            $hiddenProperty = substr($name, 1);
1610
-            if (isset($this->$hiddenProperty)) {
1611
-                return $this->$hiddenProperty;
1612
-            }
1613
-        }
1614
-        return null;
1615
-    }
1616
-
1617
-    /**
1618
-     * Store the url map cache if needed
1619
-     */
1620
-    public function __destruct()
1621
-    {
1622
-        if ($this->productionMode && !$this->cached) {
1623
-            if (empty($this->url) && empty($this->requestMethod)) {
1624
-                // url and requestMethod is NOT set:
1625
-                // This can only happen, when an exception was thrown outside of restler, so that the method Restler::handle was NOT called.
1626
-                // In this case, the routes can now be corrupt/incomplete, because we don't know, if all API-classes could be registered
1627
-                // before the exception was thrown. So, don't cache the routes, because the routes can now be corrupt/incomplete!
1628
-                return;
1629
-            }
1630
-            if ($this->exception instanceof RestException && $this->exception->getStage() === 'setup') {
1631
-                // An exception has occured during configuration of restler. Maybe we could not add all API-classes correctly!
1632
-                // So, don't cache the routes, because the routes can now be corrupt/incomplete!
1633
-                return;
1634
-            }
1635
-
1636
-            $this->cache->set(
1637
-                'routes',
1638
-                Routes::toArray() +
1639
-                array('apiVersionMap' => $this->apiVersionMap)
1640
-            );
1641
-        }
1642
-    }
1643
-
1644
-    /**
1645
-     * pre call
1646
-     *
1647
-     * call _pre_{methodName)_{extension} if exists with the same parameters as
1648
-     * the api method
1649
-     *
1650
-     * @example _pre_get_json
1651
-     *
1652
-     */
1653
-    protected function preCall()
1654
-    {
1655
-        $o = & $this->apiMethodInfo;
1656
-        $preCall = '_pre_' . $o->methodName . '_'
1657
-            . $this->requestFormat->getExtension();
1658
-
1659
-        if (method_exists($o->className, $preCall)) {
1660
-            $this->dispatch('preCall');
1661
-            call_user_func_array(array(
1662
-                Scope::get($o->className),
1663
-                $preCall
1664
-            ), $o->parameters);
1665
-        }
1666
-    }
1667
-
1668
-    /**
1669
-     * post call
1670
-     *
1671
-     * call _post_{methodName}_{extension} if exists with the composed and
1672
-     * serialized (applying the repose format) response data
1673
-     *
1674
-     * @example _post_get_json
1675
-     */
1676
-    protected function postCall()
1677
-    {
1678
-        $o = & $this->apiMethodInfo;
1679
-        $postCall = '_post_' . $o->methodName . '_' .
1680
-            $this->responseFormat->getExtension();
1681
-        if (method_exists($o->className, $postCall)) {
1682
-            $this->dispatch('postCall');
1683
-            $this->responseData = call_user_func(array(
1684
-                Scope::get($o->className),
1685
-                $postCall
1686
-            ), $this->responseData);
1687
-        }
1688
-    }
58
+	const VERSION = '3.1.0';
59
+
60
+	// ==================================================================
61
+	//
62
+	// Public variables
63
+	//
64
+	// ------------------------------------------------------------------
65
+	/**
66
+	 * Reference to the last exception thrown
67
+	 * @var RestException
68
+	 */
69
+	public $exception = null;
70
+	/**
71
+	 * Used in production mode to store the routes and more
72
+	 *
73
+	 * @var iCache
74
+	 */
75
+	public $cache;
76
+	/**
77
+	 * URL of the currently mapped service
78
+	 *
79
+	 * @var string
80
+	 */
81
+	public $url;
82
+	/**
83
+	 * Http request method of the current request.
84
+	 * Any value between [GET, PUT, POST, DELETE]
85
+	 *
86
+	 * @var string
87
+	 */
88
+	public $requestMethod;
89
+	/**
90
+	 * Requested data format.
91
+	 * Instance of the current format class
92
+	 * which implements the iFormat interface
93
+	 *
94
+	 * @var iFormat
95
+	 * @example jsonFormat, xmlFormat, yamlFormat etc
96
+	 */
97
+	public $requestFormat;
98
+	/**
99
+	 * Response data format.
100
+	 *
101
+	 * Instance of the current format class
102
+	 * which implements the iFormat interface
103
+	 *
104
+	 * @var iFormat
105
+	 * @example jsonFormat, xmlFormat, yamlFormat etc
106
+	 */
107
+	public $responseFormat;
108
+	/**
109
+	 * Http status code
110
+	 *
111
+	 * @var int|null when specified it will override @status comment
112
+	 */
113
+	public $responseCode=null;
114
+	/**
115
+	 * @var string base url of the api service
116
+	 */
117
+	protected $baseUrl;
118
+	/**
119
+	 * @var bool Used for waiting till verifying @format
120
+	 *           before throwing content negotiation failed
121
+	 */
122
+	protected $requestFormatDiffered = false;
123
+	/**
124
+	 * method information including metadata
125
+	 *
126
+	 * @var ApiMethodInfo
127
+	 */
128
+	public $apiMethodInfo;
129
+	/**
130
+	 * @var int for calculating execution time
131
+	 */
132
+	protected $startTime;
133
+	/**
134
+	 * When set to false, it will run in debug mode and parse the
135
+	 * class files every time to map it to the URL
136
+	 *
137
+	 * @var boolean
138
+	 */
139
+	protected $productionMode = false;
140
+	public $refreshCache = false;
141
+	/**
142
+	 * Caching of url map is enabled or not
143
+	 *
144
+	 * @var boolean
145
+	 */
146
+	protected $cached;
147
+	/**
148
+	 * @var int
149
+	 */
150
+	protected $apiVersion = 1;
151
+	/**
152
+	 * @var int
153
+	 */
154
+	protected $requestedApiVersion = 1;
155
+	/**
156
+	 * @var int
157
+	 */
158
+	protected $apiMinimumVersion = 1;
159
+	/**
160
+	 * @var array
161
+	 */
162
+	protected $apiVersionMap = array();
163
+	/**
164
+	 * Associated array that maps formats to their respective format class name
165
+	 *
166
+	 * @var array
167
+	 */
168
+	protected $formatMap = array();
169
+	/**
170
+	 * List of the Mime Types that can be produced as a response by this API
171
+	 *
172
+	 * @var array
173
+	 */
174
+	protected $writableMimeTypes = array();
175
+	/**
176
+	 * List of the Mime Types that are supported for incoming requests by this API
177
+	 *
178
+	 * @var array
179
+	 */
180
+	protected $readableMimeTypes = array();
181
+	/**
182
+	 * Associated array that maps formats to their respective format class name
183
+	 *
184
+	 * @var array
185
+	 */
186
+	protected $formatOverridesMap = array('extensions' => array());
187
+	/**
188
+	 * list of filter classes
189
+	 *
190
+	 * @var array
191
+	 */
192
+	protected $filterClasses = array();
193
+	/**
194
+	 * instances of filter classes that are executed after authentication
195
+	 *
196
+	 * @var array
197
+	 */
198
+	protected $postAuthFilterClasses = array();
199
+
200
+
201
+	// ==================================================================
202
+	//
203
+	// Protected variables
204
+	//
205
+	// ------------------------------------------------------------------
206
+
207
+	/**
208
+	 * Data sent to the service
209
+	 *
210
+	 * @var array
211
+	 */
212
+	protected $requestData = array();
213
+	/**
214
+	 * list of authentication classes
215
+	 *
216
+	 * @var array
217
+	 */
218
+	protected $authClasses = array();
219
+	/**
220
+	 * list of error handling classes
221
+	 *
222
+	 * @var array
223
+	 */
224
+	protected $errorClasses = array();
225
+	protected $authenticated = false;
226
+	protected $authVerified = false;
227
+	/**
228
+	 * @var mixed
229
+	 */
230
+	protected $responseData;
231
+
232
+	/**
233
+	 * Constructor
234
+	 *
235
+	 * @param boolean $productionMode    When set to false, it will run in
236
+	 *                                   debug mode and parse the class files
237
+	 *                                   every time to map it to the URL
238
+	 *
239
+	 * @param bool    $refreshCache      will update the cache when set to true
240
+	 */
241
+	public function __construct($productionMode = false, $refreshCache = false)
242
+	{
243
+		parent::__construct();
244
+		$this->startTime = time();
245
+		Util::$restler = $this;
246
+		Scope::set('Restler', $this);
247
+		$this->productionMode = $productionMode;
248
+		if (is_null(Defaults::$cacheDirectory)) {
249
+			Defaults::$cacheDirectory = dirname($_SERVER['SCRIPT_FILENAME']) .
250
+				DIRECTORY_SEPARATOR . 'cache';
251
+		}
252
+		$this->cache = new Defaults::$cacheClass();
253
+		$this->refreshCache = $refreshCache;
254
+		// use this to rebuild cache every time in production mode
255
+		if ($productionMode && $refreshCache) {
256
+			$this->cached = false;
257
+		}
258
+	}
259
+
260
+	/**
261
+	 * Main function for processing the api request
262
+	 * and return the response
263
+	 *
264
+	 * @throws Exception     when the api service class is missing
265
+	 * @throws RestException to send error response
266
+	 */
267
+	public function handle()
268
+	{
269
+		try {
270
+			try {
271
+				try {
272
+					$this->get();
273
+				} catch (Exception $e) {
274
+					$this->requestData
275
+						= array(Defaults::$fullRequestDataName => array());
276
+					if (!$e instanceof RestException) {
277
+						$e = new RestException(
278
+							500,
279
+							$this->productionMode ? null : $e->getMessage(),
280
+							array(),
281
+							$e
282
+						);
283
+					}
284
+					$this->route();
285
+					throw $e;
286
+				}
287
+				if (Defaults::$useVendorMIMEVersioning)
288
+					$this->responseFormat = $this->negotiateResponseFormat();
289
+				$this->route();
290
+			} catch (Exception $e) {
291
+				$this->negotiate();
292
+				if (!$e instanceof RestException) {
293
+					$e = new RestException(
294
+						500,
295
+						$this->productionMode ? null : $e->getMessage(),
296
+						array(),
297
+						$e
298
+					);
299
+				}
300
+				throw $e;
301
+			}
302
+			$this->negotiate();
303
+			$this->preAuthFilter();
304
+			$this->authenticate();
305
+			$this->postAuthFilter();
306
+			$this->validate();
307
+			$this->preCall();
308
+			$this->call();
309
+			$this->compose();
310
+			$this->postCall();
311
+			if (Defaults::$returnResponse) {
312
+				return $this->respond();
313
+			}
314
+			$this->respond();
315
+		} catch (Exception $e) {
316
+			try{
317
+				if (Defaults::$returnResponse) {
318
+					return $this->message($e);
319
+				}
320
+				$this->message($e);
321
+			} catch (Exception $e2) {
322
+				if (Defaults::$returnResponse) {
323
+					return $this->message($e2);
324
+				}
325
+				$this->message($e2);
326
+			}
327
+		}
328
+	}
329
+
330
+	/**
331
+	 * read the request details
332
+	 *
333
+	 * Find out the following
334
+	 *  - baseUrl
335
+	 *  - url requested
336
+	 *  - version requested (if url based versioning)
337
+	 *  - http verb/method
338
+	 *  - negotiate content type
339
+	 *  - request data
340
+	 *  - set defaults
341
+	 */
342
+	protected function get()
343
+	{
344
+		$this->dispatch('get');
345
+		if (empty($this->formatMap)) {
346
+			$this->setSupportedFormats('JsonFormat');
347
+		}
348
+		$this->url = $this->getPath();
349
+		$this->requestMethod = Util::getRequestMethod();
350
+		$this->requestFormat = $this->getRequestFormat();
351
+		$this->requestData = $this->getRequestData(false);
352
+
353
+		//parse defaults
354
+		foreach ($_GET as $key => $value) {
355
+			if (isset(Defaults::$aliases[$key])) {
356
+				$_GET[Defaults::$aliases[$key]] = $value;
357
+				unset($_GET[$key]);
358
+				$key = Defaults::$aliases[$key];
359
+			}
360
+			if (in_array($key, Defaults::$overridables)) {
361
+				Defaults::setProperty($key, $value);
362
+			}
363
+		}
364
+	}
365
+
366
+	/**
367
+	 * Returns a list of the mime types (e.g.  ["application/json","application/xml"]) that the API can respond with
368
+	 * @return array
369
+	 */
370
+	public function getWritableMimeTypes()
371
+	{
372
+		return $this->writableMimeTypes;
373
+	}
374
+
375
+	/**
376
+	 * Returns the list of Mime Types for the request that the API can understand
377
+	 * @return array
378
+	 */
379
+	public function getReadableMimeTypes()
380
+	{
381
+		return $this->readableMimeTypes;
382
+	}
383
+
384
+	/**
385
+	 * Call this method and pass all the formats that should be  supported by
386
+	 * the API Server. Accepts multiple parameters
387
+	 *
388
+	 * @param string ,... $formatName   class name of the format class that
389
+	 *                                  implements iFormat
390
+	 *
391
+	 * @example $restler->setSupportedFormats('JsonFormat', 'XmlFormat'...);
392
+	 * @throws Exception
393
+	 */
394
+	public function setSupportedFormats($format = null /*[, $format2...$farmatN]*/)
395
+	{
396
+		$args = func_get_args();
397
+		$extensions = array();
398
+		$throwException = $this->requestFormatDiffered;
399
+		$this->writableMimeTypes = $this->readableMimeTypes = array();
400
+		foreach ($args as $className) {
401
+
402
+			$obj = Scope::get($className);
403
+
404
+			if (!$obj instanceof iFormat)
405
+				throw new Exception('Invalid format class; must implement ' .
406
+					'iFormat interface');
407
+			if ($throwException && get_class($obj) == get_class($this->requestFormat)) {
408
+				$throwException = false;
409
+			}
410
+
411
+			foreach ($obj->getMIMEMap() as $mime => $extension) {
412
+				if($obj->isWritable()){
413
+					$this->writableMimeTypes[]=$mime;
414
+					$extensions[".$extension"] = true;
415
+				}
416
+				if($obj->isReadable())
417
+					$this->readableMimeTypes[]=$mime;
418
+				if (!isset($this->formatMap[$extension]))
419
+					$this->formatMap[$extension] = $className;
420
+				if (!isset($this->formatMap[$mime]))
421
+					$this->formatMap[$mime] = $className;
422
+			}
423
+		}
424
+		if ($throwException) {
425
+			throw new RestException(
426
+				403,
427
+				'Content type `' . $this->requestFormat->getMIME() . '` is not supported.'
428
+			);
429
+		}
430
+		$this->formatMap['default'] = $args[0];
431
+		$this->formatMap['extensions'] = array_keys($extensions);
432
+	}
433
+
434
+	/**
435
+	 * Call this method and pass all the formats that can be used to override
436
+	 * the supported formats using `@format` comment. Accepts multiple parameters
437
+	 *
438
+	 * @param string ,... $formatName   class name of the format class that
439
+	 *                                  implements iFormat
440
+	 *
441
+	 * @example $restler->setOverridingFormats('JsonFormat', 'XmlFormat'...);
442
+	 * @throws Exception
443
+	 */
444
+	public function setOverridingFormats($format = null /*[, $format2...$farmatN]*/)
445
+	{
446
+		$args = func_get_args();
447
+		$extensions = array();
448
+		foreach ($args as $className) {
449
+
450
+			$obj = Scope::get($className);
451
+
452
+			if (!$obj instanceof iFormat)
453
+				throw new Exception('Invalid format class; must implement ' .
454
+					'iFormat interface');
455
+
456
+			foreach ($obj->getMIMEMap() as $mime => $extension) {
457
+				if (!isset($this->formatOverridesMap[$extension]))
458
+					$this->formatOverridesMap[$extension] = $className;
459
+				if (!isset($this->formatOverridesMap[$mime]))
460
+					$this->formatOverridesMap[$mime] = $className;
461
+				if($obj->isWritable())
462
+					$extensions[".$extension"] = true;
463
+			}
464
+		}
465
+		$this->formatOverridesMap['extensions'] = array_keys($extensions);
466
+	}
467
+
468
+	/**
469
+	 * Set one or more string to be considered as the base url
470
+	 *
471
+	 * When more than one base url is provided, restler will make
472
+	 * use of $_SERVER['HTTP_HOST'] to find the right one
473
+	 *
474
+	 * @param string ,... $url
475
+	 */
476
+	public function setBaseUrls($url /*[, $url2...$urlN]*/)
477
+	{
478
+		if (func_num_args() > 1) {
479
+			$urls = func_get_args();
480
+			usort($urls, function ($a, $b) {
481
+				return strlen($a) - strlen($b);
482
+			});
483
+			foreach ($urls as $u) {
484
+				if (0 === strpos($_SERVER['HTTP_HOST'], parse_url($u, PHP_URL_HOST))) {
485
+					$this->baseUrl = $u;
486
+					return;
487
+				}
488
+			}
489
+		}
490
+		$this->baseUrl = $url;
491
+	}
492
+
493
+	/**
494
+	 * Parses the request url and get the api path
495
+	 *
496
+	 * @return string api path
497
+	 */
498
+	protected function getPath()
499
+	{
500
+		// fix SCRIPT_NAME for PHP 5.4 built-in web server
501
+		if (false === strpos($_SERVER['SCRIPT_NAME'], '.php'))
502
+			$_SERVER['SCRIPT_NAME']
503
+				= '/' . substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT']) + 1);
504
+
505
+		list($base, $path) = Util::splitCommonPath(
506
+			strtok(urldecode($_SERVER['REQUEST_URI']), '?'), //remove query string
507
+			$_SERVER['SCRIPT_NAME']
508
+		);
509
+
510
+		if (!$this->baseUrl) {
511
+			// Fix port number retrieval if port is specified in HOST header.
512
+			$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
513
+			$portPos = strpos($host,":");
514
+			if ($portPos){
515
+			   $port = substr($host,$portPos+1);
516
+			} else {
517
+			   $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : '80';
518
+			   $port = isset($_SERVER['HTTP_X_FORWARDED_PORT']) ? $_SERVER['HTTP_X_FORWARDED_PORT'] : $port; // Amazon ELB
519
+			}
520
+			$https = $port == '443' ||
521
+				(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || // Amazon ELB
522
+				(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on');
523
+			$baseUrl = ($https ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'];
524
+			if (!$https && $port != '80' || $https && $port != '443')
525
+				$baseUrl .= ':' . $port;
526
+			$this->baseUrl = $baseUrl . $base;
527
+		} elseif (!empty($base) && false === strpos($this->baseUrl, $base)) {
528
+			$this->baseUrl .= $base;
529
+		}
530
+
531
+		$path = str_replace(
532
+			array_merge(
533
+				$this->formatMap['extensions'],
534
+				$this->formatOverridesMap['extensions']
535
+			),
536
+			'',
537
+			rtrim($path, '/') //remove trailing slash if found
538
+		);
539
+
540
+		if (Defaults::$useUrlBasedVersioning && strlen($path) && $path[0] == 'v') {
541
+			$version = intval(substr($path, 1));
542
+			if ($version && $version <= $this->apiVersion) {
543
+				$this->requestedApiVersion = $version;
544
+				$path = explode('/', $path, 2);
545
+				$path = count($path) == 2 ? $path[1] : '';
546
+			}
547
+		} else {
548
+			$this->requestedApiVersion = $this->apiMinimumVersion;
549
+		}
550
+		return $path;
551
+	}
552
+
553
+	/**
554
+	 * Parses the request to figure out format of the request data
555
+	 *
556
+	 * @throws RestException
557
+	 * @return iFormat any class that implements iFormat
558
+	 * @example JsonFormat
559
+	 */
560
+	protected function getRequestFormat()
561
+	{
562
+		$format = null ;
563
+		// check if client has sent any information on request format
564
+		if (
565
+			!empty($_SERVER['CONTENT_TYPE']) ||
566
+			(
567
+				!empty($_SERVER['HTTP_CONTENT_TYPE']) &&
568
+				$_SERVER['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']
569
+			)
570
+		) {
571
+			$mime = $_SERVER['CONTENT_TYPE'];
572
+			if (false !== $pos = strpos($mime, ';')) {
573
+				$mime = substr($mime, 0, $pos);
574
+			}
575
+			if ($mime == UrlEncodedFormat::MIME)
576
+				$format = Scope::get('UrlEncodedFormat');
577
+			elseif (isset($this->formatMap[$mime])) {
578
+				$format = Scope::get($this->formatMap[$mime]);
579
+				$format->setMIME($mime);
580
+			} elseif (!$this->requestFormatDiffered && isset($this->formatOverridesMap[$mime])) {
581
+				//if our api method is not using an @format comment
582
+				//to point to this $mime, we need to throw 403 as in below
583
+				//but since we don't know that yet, we need to defer that here
584
+				$format = Scope::get($this->formatOverridesMap[$mime]);
585
+				$format->setMIME($mime);
586
+				$this->requestFormatDiffered = true;
587
+			} else {
588
+				throw new RestException(
589
+					403,
590
+					"Content type `$mime` is not supported."
591
+				);
592
+			}
593
+		}
594
+		if(!$format){
595
+			$format = Scope::get($this->formatMap['default']);
596
+		}
597
+		return $format;
598
+	}
599
+
600
+	public function getRequestStream()
601
+	{
602
+		static $tempStream = false;
603
+		if (!$tempStream) {
604
+			$tempStream = fopen('php://temp', 'r+');
605
+			$rawInput = fopen('php://input', 'r');
606
+			stream_copy_to_stream($rawInput, $tempStream);
607
+		}
608
+		rewind($tempStream);
609
+		return $tempStream;
610
+	}
611
+
612
+	/**
613
+	 * Parses the request data and returns it
614
+	 *
615
+	 * @param bool $includeQueryParameters
616
+	 *
617
+	 * @return array php data
618
+	 */
619
+	public function getRequestData($includeQueryParameters = true)
620
+	{
621
+		$get = UrlEncodedFormat::decoderTypeFix($_GET);
622
+		if ($this->requestMethod == 'PUT'
623
+			|| $this->requestMethod == 'PATCH'
624
+			|| $this->requestMethod == 'POST'
625
+		) {
626
+			if (!empty($this->requestData)) {
627
+				return $includeQueryParameters
628
+					? $this->requestData + $get
629
+					: $this->requestData;
630
+			}
631
+
632
+			$stream = $this->getRequestStream();
633
+			if($stream === FALSE)
634
+				return array();
635
+			$r = $this->requestFormat instanceof iDecodeStream
636
+				? $this->requestFormat->decodeStream($stream)
637
+				: $this->requestFormat->decode(stream_get_contents($stream));
638
+
639
+			$r = is_array($r)
640
+				? array_merge($r, array(Defaults::$fullRequestDataName => $r))
641
+				: array(Defaults::$fullRequestDataName => $r);
642
+			return $includeQueryParameters
643
+				? $r + $get
644
+				: $r;
645
+		}
646
+		return $includeQueryParameters ? $get : array(); //no body
647
+	}
648
+
649
+	/**
650
+	 * Find the api method to execute for the requested Url
651
+	 */
652
+	protected function route()
653
+	{
654
+		$this->dispatch('route');
655
+
656
+		$params = $this->getRequestData();
657
+
658
+		//backward compatibility for restler 2 and below
659
+		if (!Defaults::$smartParameterParsing) {
660
+			$params = $params + array(Defaults::$fullRequestDataName => $params);
661
+		}
662
+
663
+		$this->apiMethodInfo = $o = Routes::find(
664
+			$this->url, $this->requestMethod,
665
+			$this->requestedApiVersion, $params
666
+		);
667
+		//set defaults based on api method comments
668
+		if (isset($o->metadata)) {
669
+			foreach (Defaults::$fromComments as $key => $defaultsKey) {
670
+				if (array_key_exists($key, $o->metadata)) {
671
+					$value = $o->metadata[$key];
672
+					Defaults::setProperty($defaultsKey, $value);
673
+				}
674
+			}
675
+		}
676
+		if (!isset($o->className))
677
+			throw new RestException(404);
678
+
679
+		if(isset($this->apiVersionMap[$o->className])){
680
+			Scope::$classAliases[Util::getShortName($o->className)]
681
+				= $this->apiVersionMap[$o->className][$this->requestedApiVersion];
682
+		}
683
+
684
+		foreach ($this->authClasses as $auth) {
685
+			if (isset($this->apiVersionMap[$auth])) {
686
+				Scope::$classAliases[$auth] = $this->apiVersionMap[$auth][$this->requestedApiVersion];
687
+			} elseif (isset($this->apiVersionMap[Scope::$classAliases[$auth]])) {
688
+				Scope::$classAliases[$auth]
689
+					= $this->apiVersionMap[Scope::$classAliases[$auth]][$this->requestedApiVersion];
690
+			}
691
+		}
692
+	}
693
+
694
+	/**
695
+	 * Negotiate the response details such as
696
+	 *  - cross origin resource sharing
697
+	 *  - media type
698
+	 *  - charset
699
+	 *  - language
700
+	 *
701
+	 * @throws RestException
702
+	 */
703
+	protected function negotiate()
704
+	{
705
+		$this->dispatch('negotiate');
706
+		$this->negotiateCORS();
707
+		$this->responseFormat = $this->negotiateResponseFormat();
708
+		$this->negotiateCharset();
709
+		$this->negotiateLanguage();
710
+	}
711
+
712
+	protected function negotiateCORS()
713
+	{
714
+		if (
715
+			$this->requestMethod == 'OPTIONS'
716
+			&& Defaults::$crossOriginResourceSharing
717
+		) {
718
+			if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
719
+				header('Access-Control-Allow-Methods: '
720
+					. Defaults::$accessControlAllowMethods);
721
+
722
+			if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
723
+				header('Access-Control-Allow-Headers: '
724
+					. $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
725
+
726
+			header('Access-Control-Allow-Origin: ' .
727
+				((Defaults::$accessControlAllowOrigin == '*' && isset($_SERVER['HTTP_ORIGIN']))
728
+					? $_SERVER['HTTP_ORIGIN'] : Defaults::$accessControlAllowOrigin));
729
+			header('Access-Control-Allow-Credentials: true');
730
+
731
+			exit(0);
732
+		}
733
+	}
734
+
735
+	// ==================================================================
736
+	//
737
+	// Protected functions
738
+	//
739
+	// ------------------------------------------------------------------
740
+
741
+	/**
742
+	 * Parses the request to figure out the best format for response.
743
+	 * Extension, if present, overrides the Accept header
744
+	 *
745
+	 * @throws RestException
746
+	 * @return iFormat
747
+	 * @example JsonFormat
748
+	 */
749
+	protected function negotiateResponseFormat()
750
+	{
751
+		$metadata = Util::nestedValue($this, 'apiMethodInfo', 'metadata');
752
+		//check if the api method insists on response format using @format comment
753
+
754
+		if ($metadata && isset($metadata['format'])) {
755
+			$formats = explode(',', (string)$metadata['format']);
756
+			foreach ($formats as $i => $f) {
757
+				$f = trim($f);
758
+				if (!in_array($f, $this->formatOverridesMap))
759
+					throw new RestException(
760
+						500,
761
+						"Given @format is not present in overriding formats. Please call `\$r->setOverridingFormats('$f');` first."
762
+					);
763
+				$formats[$i] = $f;
764
+			}
765
+			call_user_func_array(array($this, 'setSupportedFormats'), $formats);
766
+		}
767
+
768
+		// check if client has specified an extension
769
+		/** @var $format iFormat*/
770
+		$format = null;
771
+		$extensions = explode(
772
+			'.',
773
+			parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
774
+		);
775
+		while ($extensions) {
776
+			$extension = array_pop($extensions);
777
+			$extension = explode('/', $extension);
778
+			$extension = array_shift($extension);
779
+			if ($extension && isset($this->formatMap[$extension])) {
780
+				$format = Scope::get($this->formatMap[$extension]);
781
+				$format->setExtension($extension);
782
+				// echo "Extension $extension";
783
+				return $format;
784
+			}
785
+		}
786
+		// check if client has sent list of accepted data formats
787
+		if (isset($_SERVER['HTTP_ACCEPT'])) {
788
+			$acceptList = Util::sortByPriority($_SERVER['HTTP_ACCEPT']);
789
+			foreach ($acceptList as $accept => $quality) {
790
+				if (isset($this->formatMap[$accept])) {
791
+					$format = Scope::get($this->formatMap[$accept]);
792
+					$format->setMIME($accept);
793
+					//echo "MIME $accept";
794
+					// Tell cache content is based on Accept header
795
+					@header('Vary: Accept');
796
+
797
+					return $format;
798
+				} elseif (false !== ($index = strrpos($accept, '+'))) {
799
+					$mime = substr($accept, 0, $index);
800
+					if (is_string(Defaults::$apiVendor)
801
+						&& 0 === stripos($mime,
802
+							'application/vnd.'
803
+							. Defaults::$apiVendor . '-v')
804
+					) {
805
+						$extension = substr($accept, $index + 1);
806
+						if (isset($this->formatMap[$extension])) {
807
+							//check the MIME and extract version
808
+							$version = intval(substr($mime,
809
+								18 + strlen(Defaults::$apiVendor)));
810
+							if ($version > 0 && $version <= $this->apiVersion) {
811
+								$this->requestedApiVersion = $version;
812
+								$format = Scope::get($this->formatMap[$extension]);
813
+								$format->setExtension($extension);
814
+								// echo "Extension $extension";
815
+								Defaults::$useVendorMIMEVersioning = true;
816
+								@header('Vary: Accept');
817
+
818
+								return $format;
819
+							}
820
+						}
821
+					}
822
+
823
+				}
824
+			}
825
+		} else {
826
+			// RFC 2616: If no Accept header field is
827
+			// present, then it is assumed that the
828
+			// client accepts all media types.
829
+			$_SERVER['HTTP_ACCEPT'] = '*/*';
830
+		}
831
+		if (strpos($_SERVER['HTTP_ACCEPT'], '*') !== false) {
832
+			if (false !== strpos($_SERVER['HTTP_ACCEPT'], 'application/*')) {
833
+				$format = Scope::get('JsonFormat');
834
+			} elseif (false !== strpos($_SERVER['HTTP_ACCEPT'], 'text/*')) {
835
+				$format = Scope::get('XmlFormat');
836
+			} elseif (false !== strpos($_SERVER['HTTP_ACCEPT'], '*/*')) {
837
+				$format = Scope::get($this->formatMap['default']);
838
+			}
839
+		}
840
+		if (empty($format)) {
841
+			// RFC 2616: If an Accept header field is present, and if the
842
+			// server cannot send a response which is acceptable according to
843
+			// the combined Accept field value, then the server SHOULD send
844
+			// a 406 (not acceptable) response.
845
+			$format = Scope::get($this->formatMap['default']);
846
+			$this->responseFormat = $format;
847
+			throw new RestException(
848
+				406,
849
+				'Content negotiation failed. ' .
850
+				'Try `' . $format->getMIME() . '` instead.'
851
+			);
852
+		} else {
853
+			// Tell cache content is based at Accept header
854
+			@header("Vary: Accept");
855
+			return $format;
856
+		}
857
+	}
858
+
859
+	protected function negotiateCharset()
860
+	{
861
+		if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
862
+			$found = false;
863
+			$charList = Util::sortByPriority($_SERVER['HTTP_ACCEPT_CHARSET']);
864
+			foreach ($charList as $charset => $quality) {
865
+				if (in_array($charset, Defaults::$supportedCharsets)) {
866
+					$found = true;
867
+					Defaults::$charset = $charset;
868
+					break;
869
+				}
870
+			}
871
+			if (!$found) {
872
+				if (strpos($_SERVER['HTTP_ACCEPT_CHARSET'], '*') !== false) {
873
+					//use default charset
874
+				} else {
875
+					throw new RestException(
876
+						406,
877
+						'Content negotiation failed. ' .
878
+						'Requested charset is not supported'
879
+					);
880
+				}
881
+			}
882
+		}
883
+	}
884
+
885
+	protected function negotiateLanguage()
886
+	{
887
+		if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
888
+			$found = false;
889
+			$langList = Util::sortByPriority($_SERVER['HTTP_ACCEPT_LANGUAGE']);
890
+			foreach ($langList as $lang => $quality) {
891
+				foreach (Defaults::$supportedLanguages as $supported) {
892
+					if (strcasecmp($supported, $lang) == 0) {
893
+						$found = true;
894
+						Defaults::$language = $supported;
895
+						break 2;
896
+					}
897
+				}
898
+			}
899
+			if (!$found) {
900
+				if (strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], '*') !== false) {
901
+					//use default language
902
+				} else {
903
+					//ignore
904
+				}
905
+			}
906
+		}
907
+	}
908
+
909
+	/**
910
+	 * Filer api calls before authentication
911
+	 */
912
+	protected function preAuthFilter()
913
+	{
914
+		if (empty($this->filterClasses)) {
915
+			return;
916
+		}
917
+		$this->dispatch('preAuthFilter');
918
+		foreach ($this->filterClasses as $filterClass) {
919
+			/**
920
+			 * @var iFilter
921
+			 */
922
+			$filterObj = Scope::get($filterClass);
923
+
924
+			if (!$filterObj instanceof iFilter) {
925
+				throw new RestException (
926
+					500, 'Filter Class ' .
927
+					'should implement iFilter');
928
+			} else if (!($ok = $filterObj->__isAllowed())) {
929
+				if (is_null($ok)
930
+					&& $filterObj instanceof iUseAuthentication
931
+				) {
932
+					//handle at authentication stage
933
+					$this->postAuthFilterClasses[] = $filterClass;
934
+					continue;
935
+				}
936
+				throw new RestException(403); //Forbidden
937
+			}
938
+		}
939
+	}
940
+
941
+	protected function authenticate()
942
+	{
943
+		$o = &$this->apiMethodInfo;
944
+		$accessLevel = max(Defaults::$apiAccessLevel, $o->accessLevel);
945
+		if ($accessLevel || count($this->postAuthFilterClasses)) {
946
+			$this->dispatch('authenticate');
947
+			if (!count($this->authClasses) && $accessLevel > 1) {
948
+				throw new RestException(
949
+					403,
950
+					'at least one Authentication Class is required'
951
+				);
952
+			}
953
+			$unauthorized = false;
954
+			foreach ($this->authClasses as $authClass) {
955
+				try {
956
+					$authObj = Scope::get($authClass);
957
+					if (!method_exists($authObj, Defaults::$authenticationMethod)) {
958
+						throw new RestException (
959
+							500, 'Authentication Class ' .
960
+							'should implement iAuthenticate');
961
+					} elseif (
962
+					!$authObj->{Defaults::$authenticationMethod}()
963
+					) {
964
+						throw new RestException(401);
965
+					}
966
+					$unauthorized = false;
967
+					break;
968
+				} catch (InvalidAuthCredentials $e) {
969
+					$this->authenticated = false;
970
+					throw $e;
971
+				} catch (RestException $e) {
972
+					if (!$unauthorized) {
973
+						$unauthorized = $e;
974
+					}
975
+				}
976
+			}
977
+			$this->authVerified = true;
978
+			if ($unauthorized) {
979
+				if ($accessLevel > 1) { //when it is not a hybrid api
980
+					throw $unauthorized;
981
+				} else {
982
+					$this->authenticated = false;
983
+				}
984
+			} else {
985
+				$this->authenticated = true;
986
+			}
987
+		}
988
+	}
989
+
990
+	/**
991
+	 * Filer api calls after authentication
992
+	 */
993
+	protected function postAuthFilter()
994
+	{
995
+		if(empty($this->postAuthFilterClasses)) {
996
+			return;
997
+		}
998
+		$this->dispatch('postAuthFilter');
999
+		foreach ($this->postAuthFilterClasses as $filterClass) {
1000
+			Scope::get($filterClass);
1001
+		}
1002
+	}
1003
+
1004
+	protected function validate()
1005
+	{
1006
+		if (!Defaults::$autoValidationEnabled) {
1007
+			return;
1008
+		}
1009
+		$this->dispatch('validate');
1010
+
1011
+		$o = & $this->apiMethodInfo;
1012
+		foreach ($o->metadata['param'] as $index => $param) {
1013
+			$info = & $param [CommentParser::$embeddedDataName];
1014
+			if (!isset ($info['validate'])
1015
+				|| $info['validate'] != false
1016
+			) {
1017
+				if (isset($info['method'])) {
1018
+					$info ['apiClassInstance'] = Scope::get($o->className);
1019
+				}
1020
+				//convert to instance of ValidationInfo
1021
+				$info = new ValidationInfo($param);
1022
+				//initialize validator
1023
+				Scope::get(Defaults::$validatorClass);
1024
+				$validator = Defaults::$validatorClass;
1025
+				//if(!is_subclass_of($validator, 'Luracast\\Restler\\Data\\iValidate')) {
1026
+				//changed the above test to below for addressing this php bug
1027
+				//https://bugs.php.net/bug.php?id=53727
1028
+				if (function_exists("$validator::validate")) {
1029
+					throw new \UnexpectedValueException(
1030
+						'`Defaults::$validatorClass` must implement `iValidate` interface'
1031
+					);
1032
+				}
1033
+				$valid = $o->parameters[$index];
1034
+				$o->parameters[$index] = null;
1035
+				if (empty(Validator::$exceptions))
1036
+					$o->metadata['param'][$index]['autofocus'] = true;
1037
+				$valid = $validator::validate(
1038
+					$valid, $info
1039
+				);
1040
+				$o->parameters[$index] = $valid;
1041
+				unset($o->metadata['param'][$index]['autofocus']);
1042
+			}
1043
+		}
1044
+	}
1045
+
1046
+	protected function call()
1047
+	{
1048
+		$this->dispatch('call');
1049
+		$o = & $this->apiMethodInfo;
1050
+		$accessLevel = max(Defaults::$apiAccessLevel,
1051
+			$o->accessLevel);
1052
+		if (function_exists('newrelic_name_transaction'))
1053
+			newrelic_name_transaction("{$o->className}/{$o->methodName}");
1054
+		$object =  Scope::get($o->className);
1055
+		switch ($accessLevel) {
1056
+			case 3 : //protected method
1057
+				$reflectionMethod = new \ReflectionMethod(
1058
+					$object,
1059
+					$o->methodName
1060
+				);
1061
+				$reflectionMethod->setAccessible(true);
1062
+				$result = $reflectionMethod->invokeArgs(
1063
+					$object,
1064
+					$o->parameters
1065
+				);
1066
+				break;
1067
+			default :
1068
+				$result = call_user_func_array(array(
1069
+					$object,
1070
+					$o->methodName
1071
+				), $o->parameters);
1072
+		}
1073
+		$this->responseData = $result;
1074
+	}
1075
+
1076
+	protected function compose()
1077
+	{
1078
+		$this->dispatch('compose');
1079
+		$this->composeHeaders();
1080
+		/**
1081
+		 * @var iCompose Default Composer
1082
+		 */
1083
+		$compose = Scope::get(Defaults::$composeClass);
1084
+		$this->responseData = is_null($this->responseData) &&
1085
+		Defaults::$emptyBodyForNullResponse
1086
+			? ''
1087
+			: $this->responseFormat->encode(
1088
+				$compose->response($this->responseData),
1089
+				!$this->productionMode
1090
+			);
1091
+	}
1092
+
1093
+	public function composeHeaders(RestException $e = null)
1094
+	{
1095
+		//only GET method should be cached if allowed by API developer
1096
+		$expires = $this->requestMethod == 'GET' ? Defaults::$headerExpires : 0;
1097
+		if(!is_array(Defaults::$headerCacheControl))
1098
+			Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
1099
+		$cacheControl = Defaults::$headerCacheControl[0];
1100
+		if ($expires > 0) {
1101
+			$cacheControl = $this->apiMethodInfo->accessLevel
1102
+				? 'private, ' : 'public, ';
1103
+			$cacheControl .= end(Defaults::$headerCacheControl);
1104
+			$cacheControl = str_replace('{expires}', $expires, $cacheControl);
1105
+			$expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
1106
+		}
1107
+		@header('Cache-Control: ' . $cacheControl);
1108
+		@header('Expires: ' . $expires);
1109
+		@header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
1110
+
1111
+		if (Defaults::$crossOriginResourceSharing
1112
+			&& isset($_SERVER['HTTP_ORIGIN'])
1113
+		) {
1114
+			header('Access-Control-Allow-Origin: ' .
1115
+				(Defaults::$accessControlAllowOrigin == '*'
1116
+					? $_SERVER['HTTP_ORIGIN']
1117
+					: Defaults::$accessControlAllowOrigin)
1118
+			);
1119
+			header('Access-Control-Allow-Credentials: true');
1120
+			header('Access-Control-Max-Age: 86400');
1121
+		}
1122
+
1123
+		$this->responseFormat->setCharset(Defaults::$charset);
1124
+		$charset = $this->responseFormat->getCharset()
1125
+			? : Defaults::$charset;
1126
+
1127
+		@header('Content-Type: ' . (
1128
+			Defaults::$useVendorMIMEVersioning
1129
+				? 'application/vnd.'
1130
+				. Defaults::$apiVendor
1131
+				. "-v{$this->requestedApiVersion}"
1132
+				. '+' . $this->responseFormat->getExtension()
1133
+				: $this->responseFormat->getMIME())
1134
+			. '; charset=' . $charset
1135
+		);
1136
+
1137
+		@header('Content-Language: ' . Defaults::$language);
1138
+
1139
+		if (isset($this->apiMethodInfo->metadata['header'])) {
1140
+			foreach ($this->apiMethodInfo->metadata['header'] as $header)
1141
+				@header($header, true);
1142
+		}
1143
+		$code = 200;
1144
+		if (!Defaults::$suppressResponseCode) {
1145
+			if ($e) {
1146
+				$code = $e->getCode();
1147
+			} elseif ($this->responseCode) {
1148
+				$code = $this->responseCode;
1149
+			} elseif (isset($this->apiMethodInfo->metadata['status'])) {
1150
+				$code = $this->apiMethodInfo->metadata['status'];
1151
+			}
1152
+		}
1153
+		$this->responseCode = $code;
1154
+		@header(
1155
+			"{$_SERVER['SERVER_PROTOCOL']} $code " .
1156
+			(isset(RestException::$codes[$code]) ? RestException::$codes[$code] : '')
1157
+		);
1158
+	}
1159
+
1160
+	protected function respond()
1161
+	{
1162
+		$this->dispatch('respond');
1163
+		//handle throttling
1164
+		if (Defaults::$throttle) {
1165
+			$elapsed = time() - $this->startTime;
1166
+			if (Defaults::$throttle / 1e3 > $elapsed) {
1167
+				usleep(1e6 * (Defaults::$throttle / 1e3 - $elapsed));
1168
+			}
1169
+		}
1170
+		if ($this->responseCode == 401) {
1171
+			$authString = count($this->authClasses)
1172
+				? Scope::get($this->authClasses[0])->__getWWWAuthenticateString()
1173
+				: 'Unknown';
1174
+			@header('WWW-Authenticate: ' . $authString, false);
1175
+		}
1176
+		$this->dispatch('complete');
1177
+		if (Defaults::$returnResponse) {
1178
+			return $this->responseData;
1179
+		} else {
1180
+			echo $this->responseData;
1181
+			exit;
1182
+		}
1183
+	}
1184
+
1185
+	protected function message(Exception $exception)
1186
+	{
1187
+		$this->dispatch('message');
1188
+
1189
+		if (!$exception instanceof RestException) {
1190
+			$exception = new RestException(
1191
+				500,
1192
+				$this->productionMode ? null : $exception->getMessage(),
1193
+				array(),
1194
+				$exception
1195
+			);
1196
+		}
1197
+
1198
+		$this->exception = $exception;
1199
+
1200
+		$method = 'handle' . $exception->getCode();
1201
+		$handled = false;
1202
+		foreach ($this->errorClasses as $className) {
1203
+			if (method_exists($className, $method)) {
1204
+				$obj = Scope::get($className);
1205
+				if ($obj->$method($exception))
1206
+					$handled = true;
1207
+			}
1208
+		}
1209
+		if ($handled) {
1210
+			return;
1211
+		}
1212
+		if (!isset($this->responseFormat)) {
1213
+			$this->responseFormat = Scope::get('JsonFormat');
1214
+		}
1215
+		$this->composeHeaders($exception);
1216
+		/**
1217
+		 * @var iCompose Default Composer
1218
+		 */
1219
+		$compose = Scope::get(Defaults::$composeClass);
1220
+		$this->responseData = $this->responseFormat->encode(
1221
+			$compose->message($exception),
1222
+			!$this->productionMode
1223
+		);
1224
+		if (Defaults::$returnResponse) {
1225
+			return $this->respond();
1226
+		}
1227
+		$this->respond();
1228
+	}
1229
+
1230
+	/**
1231
+	 * Provides backward compatibility with older versions of Restler
1232
+	 *
1233
+	 * @param int $version restler version
1234
+	 *
1235
+	 * @throws \OutOfRangeException
1236
+	 */
1237
+	public function setCompatibilityMode($version = 2)
1238
+	{
1239
+		if ($version <= intval(self::VERSION) && $version > 0) {
1240
+			require __DIR__."/compatibility/restler{$version}.php";
1241
+			return;
1242
+		}
1243
+		throw new \OutOfRangeException();
1244
+	}
1245
+
1246
+	/**
1247
+	 * @param int $version                 maximum version number supported
1248
+	 *                                     by  the api
1249
+	 * @param int $minimum                 minimum version number supported
1250
+	 * (optional)
1251
+	 *
1252
+	 * @throws InvalidArgumentException
1253
+	 * @return void
1254
+	 */
1255
+	public function setAPIVersion($version = 1, $minimum = 1)
1256
+	{
1257
+		if (!is_int($version) && $version < 1) {
1258
+			throw new InvalidArgumentException
1259
+			('version should be an integer greater than 0');
1260
+		}
1261
+		$this->apiVersion = $version;
1262
+		if (is_int($minimum)) {
1263
+			$this->apiMinimumVersion = $minimum;
1264
+		}
1265
+	}
1266
+
1267
+	/**
1268
+	 * Classes implementing iFilter interface can be added for filtering out
1269
+	 * the api consumers.
1270
+	 *
1271
+	 * It can be used for rate limiting based on usage from a specific ip
1272
+	 * address or filter by country, device etc.
1273
+	 *
1274
+	 * @param $className
1275
+	 */
1276
+	public function addFilterClass($className)
1277
+	{
1278
+		$this->filterClasses[] = $className;
1279
+	}
1280
+
1281
+	/**
1282
+	 * protected methods will need at least one authentication class to be set
1283
+	 * in order to allow that method to be executed
1284
+	 *
1285
+	 * @param string $className     of the authentication class
1286
+	 * @param string $resourcePath  optional url prefix for mapping
1287
+	 */
1288
+	public function addAuthenticationClass($className, $resourcePath = null)
1289
+	{
1290
+		$this->authClasses[] = $className;
1291
+		$this->addAPIClass($className, $resourcePath);
1292
+	}
1293
+
1294
+	/**
1295
+	 * Add api classes through this method.
1296
+	 *
1297
+	 * All the public methods that do not start with _ (underscore)
1298
+	 * will be will be exposed as the public api by default.
1299
+	 *
1300
+	 * All the protected methods that do not start with _ (underscore)
1301
+	 * will exposed as protected api which will require authentication
1302
+	 *
1303
+	 * @param string $className       name of the service class
1304
+	 * @param string $resourcePath    optional url prefix for mapping, uses
1305
+	 *                                lowercase version of the class name when
1306
+	 *                                not specified
1307
+	 *
1308
+	 * @return null
1309
+	 *
1310
+	 * @throws Exception when supplied with invalid class name
1311
+	 */
1312
+	public function addAPIClass($className, $resourcePath = null)
1313
+	{
1314
+		try{
1315
+			if ($this->productionMode && is_null($this->cached)) {
1316
+				$routes = $this->cache->get('routes');
1317
+				if (isset($routes) && is_array($routes)) {
1318
+					$this->apiVersionMap = $routes['apiVersionMap'];
1319
+					unset($routes['apiVersionMap']);
1320
+					Routes::fromArray($routes);
1321
+					$this->cached = true;
1322
+				} else {
1323
+					$this->cached = false;
1324
+				}
1325
+			}
1326
+			if (isset(Scope::$classAliases[$className])) {
1327
+				$className = Scope::$classAliases[$className];
1328
+			}
1329
+			if (!$this->cached) {
1330
+				$maxVersionMethod = '__getMaximumSupportedVersion';
1331
+				if (class_exists($className)) {
1332
+					if (method_exists($className, $maxVersionMethod)) {
1333
+						$max = $className::$maxVersionMethod();
1334
+						for ($i = 1; $i <= $max; $i++) {
1335
+							$this->apiVersionMap[$className][$i] = $className;
1336
+						}
1337
+					} else {
1338
+						$this->apiVersionMap[$className][1] = $className;
1339
+					}
1340
+				}
1341
+				//versioned api
1342
+				if (false !== ($index = strrpos($className, '\\'))) {
1343
+					$name = substr($className, 0, $index)
1344
+						. '\\v{$version}' . substr($className, $index);
1345
+				} else if (false !== ($index = strrpos($className, '_'))) {
1346
+					$name = substr($className, 0, $index)
1347
+						. '_v{$version}' . substr($className, $index);
1348
+				} else {
1349
+					$name = 'v{$version}\\' . $className;
1350
+				}
1351
+
1352
+				for ($version = $this->apiMinimumVersion;
1353
+					 $version <= $this->apiVersion;
1354
+					 $version++) {
1355
+
1356
+					$versionedClassName = str_replace('{$version}', $version,
1357
+						$name);
1358
+					if (class_exists($versionedClassName)) {
1359
+						Routes::addAPIClass($versionedClassName,
1360
+							Util::getResourcePath(
1361
+								$className,
1362
+								$resourcePath
1363
+							),
1364
+							$version
1365
+						);
1366
+						if (method_exists($versionedClassName, $maxVersionMethod)) {
1367
+							$max = $versionedClassName::$maxVersionMethod();
1368
+							for ($i = $version; $i <= $max; $i++) {
1369
+								$this->apiVersionMap[$className][$i] = $versionedClassName;
1370
+							}
1371
+						} else {
1372
+							$this->apiVersionMap[$className][$version] = $versionedClassName;
1373
+						}
1374
+					} elseif (isset($this->apiVersionMap[$className][$version])) {
1375
+						Routes::addAPIClass($this->apiVersionMap[$className][$version],
1376
+							Util::getResourcePath(
1377
+								$className,
1378
+								$resourcePath
1379
+							),
1380
+							$version
1381
+						);
1382
+					}
1383
+				}
1384
+
1385
+			}
1386
+		} catch (Exception $e) {
1387
+			$e = new Exception(
1388
+				"addAPIClass('$className') failed. ".$e->getMessage(),
1389
+				$e->getCode(),
1390
+				$e
1391
+			);
1392
+			$this->setSupportedFormats('JsonFormat');
1393
+			$this->message($e);
1394
+		}
1395
+	}
1396
+
1397
+	/**
1398
+	 * Add class for custom error handling
1399
+	 *
1400
+	 * @param string $className   of the error handling class
1401
+	 */
1402
+	public function addErrorClass($className)
1403
+	{
1404
+		$this->errorClasses[] = $className;
1405
+	}
1406
+
1407
+	/**
1408
+	 * protected methods will need at least one authentication class to be set
1409
+	 * in order to allow that method to be executed.  When multiple authentication
1410
+	 * classes are in use, this function provides better performance by setting
1411
+	 * all auth classes through a single function call.
1412
+	 *
1413
+	 * @param array $classNames     array of associative arrays containing
1414
+	 *                              the authentication class name & optional
1415
+	 *                              url prefix for mapping.
1416
+	 */
1417
+	public function setAuthClasses(array $classNames)
1418
+	{
1419
+		$this->authClasses = array_merge($this->authClasses, array_values($classNames));
1420
+	}
1421
+
1422
+	/**
1423
+	 * Add multiple api classes through this method.
1424
+	 *
1425
+	 * This method provides better performance when large number
1426
+	 * of API classes are in use as it processes them all at once,
1427
+	 * as opposed to hundreds (or more) addAPIClass calls.
1428
+	 *
1429
+	 *
1430
+	 * All the public methods that do not start with _ (underscore)
1431
+	 * will be will be exposed as the public api by default.
1432
+	 *
1433
+	 * All the protected methods that do not start with _ (underscore)
1434
+	 * will exposed as protected api which will require authentication
1435
+	 *
1436
+	 * @param array $map        array of associative arrays containing
1437
+	 *                          the class name & optional url prefix
1438
+	 *                          for mapping.
1439
+	 *
1440
+	 * @return null
1441
+	 *
1442
+	 * @throws Exception when supplied with invalid class name
1443
+	 */
1444
+	public function mapAPIClasses(array $map)
1445
+	{
1446
+		try {
1447
+			if ($this->productionMode && is_null($this->cached)) {
1448
+				$routes = $this->cache->get('routes');
1449
+				if (isset($routes) && is_array($routes)) {
1450
+					$this->apiVersionMap = $routes['apiVersionMap'];
1451
+					unset($routes['apiVersionMap']);
1452
+					Routes::fromArray($routes);
1453
+					$this->cached = true;
1454
+				} else {
1455
+					$this->cached = false;
1456
+				}
1457
+			}
1458
+			$maxVersionMethod = '__getMaximumSupportedVersion';
1459
+			if (!$this->productionMode || !$this->cached) {
1460
+				foreach ($map as $className => $resourcePath) {
1461
+					if (is_numeric($className)) {
1462
+						$className = $resourcePath;
1463
+						$resourcePath = null;
1464
+					}
1465
+					if (isset(Scope::$classAliases[$className])) {
1466
+						$className = Scope::$classAliases[$className];
1467
+					}
1468
+					if (class_exists($className)) {
1469
+						if (method_exists($className, $maxVersionMethod)) {
1470
+							$max = $className::$maxVersionMethod();
1471
+							for ($i = 1; $i <= $max; $i++) {
1472
+								$this->apiVersionMap[$className][$i] = $className;
1473
+							}
1474
+						} else {
1475
+							$this->apiVersionMap[$className][1] = $className;
1476
+						}
1477
+					}
1478
+					//versioned api
1479
+					if (false !== ($index = strrpos($className, '\\'))) {
1480
+						$name = substr($className, 0, $index)
1481
+							. '\\v{$version}' . substr($className, $index);
1482
+					} else {
1483
+						if (false !== ($index = strrpos($className, '_'))) {
1484
+							$name = substr($className, 0, $index)
1485
+								. '_v{$version}' . substr($className, $index);
1486
+						} else {
1487
+							$name = 'v{$version}\\' . $className;
1488
+						}
1489
+					}
1490
+
1491
+					for ($version = $this->apiMinimumVersion;
1492
+						 $version <= $this->apiVersion;
1493
+						 $version++) {
1494
+
1495
+						$versionedClassName = str_replace('{$version}', $version,
1496
+							$name);
1497
+						if (class_exists($versionedClassName)) {
1498
+							Routes::addAPIClass($versionedClassName,
1499
+								Util::getResourcePath(
1500
+									$className,
1501
+									$resourcePath
1502
+								),
1503
+								$version
1504
+							);
1505
+							if (method_exists($versionedClassName, $maxVersionMethod)) {
1506
+								$max = $versionedClassName::$maxVersionMethod();
1507
+								for ($i = $version; $i <= $max; $i++) {
1508
+									$this->apiVersionMap[$className][$i] = $versionedClassName;
1509
+								}
1510
+							} else {
1511
+								$this->apiVersionMap[$className][$version] = $versionedClassName;
1512
+							}
1513
+						} elseif (isset($this->apiVersionMap[$className][$version])) {
1514
+							Routes::addAPIClass($this->apiVersionMap[$className][$version],
1515
+								Util::getResourcePath(
1516
+									$className,
1517
+									$resourcePath
1518
+								),
1519
+								$version
1520
+							);
1521
+						}
1522
+					}
1523
+				}
1524
+			}
1525
+		} catch (Exception $e) {
1526
+			$e = new Exception(
1527
+				"mapAPIClasses failed. " . $e->getMessage(),
1528
+				$e->getCode(),
1529
+				$e
1530
+			);
1531
+			$this->setSupportedFormats('JsonFormat');
1532
+			$this->message($e);
1533
+		}
1534
+	}
1535
+
1536
+	/**
1537
+	 * Associated array that maps formats to their respective format class name
1538
+	 *
1539
+	 * @return array
1540
+	 */
1541
+	public function getFormatMap()
1542
+	{
1543
+		return $this->formatMap;
1544
+	}
1545
+
1546
+	/**
1547
+	 * API version requested by the client
1548
+	 * @return int
1549
+	 */
1550
+	public function getRequestedApiVersion()
1551
+	{
1552
+		return $this->requestedApiVersion;
1553
+	}
1554
+
1555
+	/**
1556
+	 * When false, restler will run in debug mode and parse the class files
1557
+	 * every time to map it to the URL
1558
+	 *
1559
+	 * @return bool
1560
+	 */
1561
+	public function getProductionMode()
1562
+	{
1563
+		return $this->productionMode;
1564
+	}
1565
+
1566
+	/**
1567
+	 * Chosen API version
1568
+	 *
1569
+	 * @return int
1570
+	 */
1571
+	public function getApiVersion()
1572
+	{
1573
+		return $this->apiVersion;
1574
+	}
1575
+
1576
+	/**
1577
+	 * Base Url of the API Service
1578
+	 *
1579
+	 * @return string
1580
+	 *
1581
+	 * @example http://localhost/restler3
1582
+	 * @example http://restler3.com
1583
+	 */
1584
+	public function getBaseUrl()
1585
+	{
1586
+		return $this->baseUrl;
1587
+	}
1588
+
1589
+	/**
1590
+	 * List of events that fired already
1591
+	 *
1592
+	 * @return array
1593
+	 */
1594
+	public function getEvents()
1595
+	{
1596
+		return $this->events;
1597
+	}
1598
+
1599
+	/**
1600
+	 * Magic method to expose some protected variables
1601
+	 *
1602
+	 * @param string $name name of the hidden property
1603
+	 *
1604
+	 * @return null|mixed
1605
+	 */
1606
+	public function __get($name)
1607
+	{
1608
+		if ($name[0] == '_') {
1609
+			$hiddenProperty = substr($name, 1);
1610
+			if (isset($this->$hiddenProperty)) {
1611
+				return $this->$hiddenProperty;
1612
+			}
1613
+		}
1614
+		return null;
1615
+	}
1616
+
1617
+	/**
1618
+	 * Store the url map cache if needed
1619
+	 */
1620
+	public function __destruct()
1621
+	{
1622
+		if ($this->productionMode && !$this->cached) {
1623
+			if (empty($this->url) && empty($this->requestMethod)) {
1624
+				// url and requestMethod is NOT set:
1625
+				// This can only happen, when an exception was thrown outside of restler, so that the method Restler::handle was NOT called.
1626
+				// In this case, the routes can now be corrupt/incomplete, because we don't know, if all API-classes could be registered
1627
+				// before the exception was thrown. So, don't cache the routes, because the routes can now be corrupt/incomplete!
1628
+				return;
1629
+			}
1630
+			if ($this->exception instanceof RestException && $this->exception->getStage() === 'setup') {
1631
+				// An exception has occured during configuration of restler. Maybe we could not add all API-classes correctly!
1632
+				// So, don't cache the routes, because the routes can now be corrupt/incomplete!
1633
+				return;
1634
+			}
1635
+
1636
+			$this->cache->set(
1637
+				'routes',
1638
+				Routes::toArray() +
1639
+				array('apiVersionMap' => $this->apiVersionMap)
1640
+			);
1641
+		}
1642
+	}
1643
+
1644
+	/**
1645
+	 * pre call
1646
+	 *
1647
+	 * call _pre_{methodName)_{extension} if exists with the same parameters as
1648
+	 * the api method
1649
+	 *
1650
+	 * @example _pre_get_json
1651
+	 *
1652
+	 */
1653
+	protected function preCall()
1654
+	{
1655
+		$o = & $this->apiMethodInfo;
1656
+		$preCall = '_pre_' . $o->methodName . '_'
1657
+			. $this->requestFormat->getExtension();
1658
+
1659
+		if (method_exists($o->className, $preCall)) {
1660
+			$this->dispatch('preCall');
1661
+			call_user_func_array(array(
1662
+				Scope::get($o->className),
1663
+				$preCall
1664
+			), $o->parameters);
1665
+		}
1666
+	}
1667
+
1668
+	/**
1669
+	 * post call
1670
+	 *
1671
+	 * call _post_{methodName}_{extension} if exists with the composed and
1672
+	 * serialized (applying the repose format) response data
1673
+	 *
1674
+	 * @example _post_get_json
1675
+	 */
1676
+	protected function postCall()
1677
+	{
1678
+		$o = & $this->apiMethodInfo;
1679
+		$postCall = '_post_' . $o->methodName . '_' .
1680
+			$this->responseFormat->getExtension();
1681
+		if (method_exists($o->className, $postCall)) {
1682
+			$this->dispatch('postCall');
1683
+			$this->responseData = call_user_func(array(
1684
+				Scope::get($o->className),
1685
+				$postCall
1686
+			), $this->responseData);
1687
+		}
1688
+	}
1689 1689
 }
Please login to merge, or discard this patch.
Spacing   +60 added lines, -61 removed lines patch added patch discarded remove patch
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
      *
111 111
      * @var int|null when specified it will override @status comment
112 112
      */
113
-    public $responseCode=null;
113
+    public $responseCode = null;
114 114
     /**
115 115
      * @var string base url of the api service
116 116
      */
@@ -246,8 +246,8 @@  discard block
 block discarded – undo
246 246
         Scope::set('Restler', $this);
247 247
         $this->productionMode = $productionMode;
248 248
         if (is_null(Defaults::$cacheDirectory)) {
249
-            Defaults::$cacheDirectory = dirname($_SERVER['SCRIPT_FILENAME']) .
250
-                DIRECTORY_SEPARATOR . 'cache';
249
+            Defaults::$cacheDirectory = dirname($_SERVER['SCRIPT_FILENAME']).
250
+                DIRECTORY_SEPARATOR.'cache';
251 251
         }
252 252
         $this->cache = new Defaults::$cacheClass();
253 253
         $this->refreshCache = $refreshCache;
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
             }
314 314
             $this->respond();
315 315
         } catch (Exception $e) {
316
-            try{
316
+            try {
317 317
                 if (Defaults::$returnResponse) {
318 318
                     return $this->message($e);
319 319
                 }
@@ -402,19 +402,19 @@  discard block
 block discarded – undo
402 402
             $obj = Scope::get($className);
403 403
 
404 404
             if (!$obj instanceof iFormat)
405
-                throw new Exception('Invalid format class; must implement ' .
405
+                throw new Exception('Invalid format class; must implement '.
406 406
                     'iFormat interface');
407 407
             if ($throwException && get_class($obj) == get_class($this->requestFormat)) {
408 408
                 $throwException = false;
409 409
             }
410 410
 
411 411
             foreach ($obj->getMIMEMap() as $mime => $extension) {
412
-                if($obj->isWritable()){
413
-                    $this->writableMimeTypes[]=$mime;
412
+                if ($obj->isWritable()) {
413
+                    $this->writableMimeTypes[] = $mime;
414 414
                     $extensions[".$extension"] = true;
415 415
                 }
416
-                if($obj->isReadable())
417
-                    $this->readableMimeTypes[]=$mime;
416
+                if ($obj->isReadable())
417
+                    $this->readableMimeTypes[] = $mime;
418 418
                 if (!isset($this->formatMap[$extension]))
419 419
                     $this->formatMap[$extension] = $className;
420 420
                 if (!isset($this->formatMap[$mime]))
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
         if ($throwException) {
425 425
             throw new RestException(
426 426
                 403,
427
-                'Content type `' . $this->requestFormat->getMIME() . '` is not supported.'
427
+                'Content type `'.$this->requestFormat->getMIME().'` is not supported.'
428 428
             );
429 429
         }
430 430
         $this->formatMap['default'] = $args[0];
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
             $obj = Scope::get($className);
451 451
 
452 452
             if (!$obj instanceof iFormat)
453
-                throw new Exception('Invalid format class; must implement ' .
453
+                throw new Exception('Invalid format class; must implement '.
454 454
                     'iFormat interface');
455 455
 
456 456
             foreach ($obj->getMIMEMap() as $mime => $extension) {
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
                     $this->formatOverridesMap[$extension] = $className;
459 459
                 if (!isset($this->formatOverridesMap[$mime]))
460 460
                     $this->formatOverridesMap[$mime] = $className;
461
-                if($obj->isWritable())
461
+                if ($obj->isWritable())
462 462
                     $extensions[".$extension"] = true;
463 463
             }
464 464
         }
@@ -477,7 +477,7 @@  discard block
 block discarded – undo
477 477
     {
478 478
         if (func_num_args() > 1) {
479 479
             $urls = func_get_args();
480
-            usort($urls, function ($a, $b) {
480
+            usort($urls, function($a, $b) {
481 481
                 return strlen($a) - strlen($b);
482 482
             });
483 483
             foreach ($urls as $u) {
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
         // fix SCRIPT_NAME for PHP 5.4 built-in web server
501 501
         if (false === strpos($_SERVER['SCRIPT_NAME'], '.php'))
502 502
             $_SERVER['SCRIPT_NAME']
503
-                = '/' . substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT']) + 1);
503
+                = '/'.substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT']) + 1);
504 504
 
505 505
         list($base, $path) = Util::splitCommonPath(
506 506
             strtok(urldecode($_SERVER['REQUEST_URI']), '?'), //remove query string
@@ -510,9 +510,9 @@  discard block
 block discarded – undo
510 510
         if (!$this->baseUrl) {
511 511
             // Fix port number retrieval if port is specified in HOST header.
512 512
             $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
513
-            $portPos = strpos($host,":");
514
-            if ($portPos){
515
-               $port = substr($host,$portPos+1);
513
+            $portPos = strpos($host, ":");
514
+            if ($portPos) {
515
+               $port = substr($host, $portPos + 1);
516 516
             } else {
517 517
                $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : '80';
518 518
                $port = isset($_SERVER['HTTP_X_FORWARDED_PORT']) ? $_SERVER['HTTP_X_FORWARDED_PORT'] : $port; // Amazon ELB
@@ -520,10 +520,10 @@  discard block
 block discarded – undo
520 520
             $https = $port == '443' ||
521 521
                 (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || // Amazon ELB
522 522
                 (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on');
523
-            $baseUrl = ($https ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'];
523
+            $baseUrl = ($https ? 'https://' : 'http://').$_SERVER['SERVER_NAME'];
524 524
             if (!$https && $port != '80' || $https && $port != '443')
525
-                $baseUrl .= ':' . $port;
526
-            $this->baseUrl = $baseUrl . $base;
525
+                $baseUrl .= ':'.$port;
526
+            $this->baseUrl = $baseUrl.$base;
527 527
         } elseif (!empty($base) && false === strpos($this->baseUrl, $base)) {
528 528
             $this->baseUrl .= $base;
529 529
         }
@@ -559,7 +559,7 @@  discard block
 block discarded – undo
559 559
      */
560 560
     protected function getRequestFormat()
561 561
     {
562
-        $format = null ;
562
+        $format = null;
563 563
         // check if client has sent any information on request format
564 564
         if (
565 565
             !empty($_SERVER['CONTENT_TYPE']) ||
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
                 );
592 592
             }
593 593
         }
594
-        if(!$format){
594
+        if (!$format) {
595 595
             $format = Scope::get($this->formatMap['default']);
596 596
         }
597 597
         return $format;
@@ -630,7 +630,7 @@  discard block
 block discarded – undo
630 630
             }
631 631
 
632 632
             $stream = $this->getRequestStream();
633
-            if($stream === FALSE)
633
+            if ($stream === FALSE)
634 634
                 return array();
635 635
             $r = $this->requestFormat instanceof iDecodeStream
636 636
                 ? $this->requestFormat->decodeStream($stream)
@@ -676,7 +676,7 @@  discard block
 block discarded – undo
676 676
         if (!isset($o->className))
677 677
             throw new RestException(404);
678 678
 
679
-        if(isset($this->apiVersionMap[$o->className])){
679
+        if (isset($this->apiVersionMap[$o->className])) {
680 680
             Scope::$classAliases[Util::getShortName($o->className)]
681 681
                 = $this->apiVersionMap[$o->className][$this->requestedApiVersion];
682 682
         }
@@ -723,7 +723,7 @@  discard block
 block discarded – undo
723 723
                 header('Access-Control-Allow-Headers: '
724 724
                     . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
725 725
 
726
-            header('Access-Control-Allow-Origin: ' .
726
+            header('Access-Control-Allow-Origin: '.
727 727
                 ((Defaults::$accessControlAllowOrigin == '*' && isset($_SERVER['HTTP_ORIGIN']))
728 728
                     ? $_SERVER['HTTP_ORIGIN'] : Defaults::$accessControlAllowOrigin));
729 729
             header('Access-Control-Allow-Credentials: true');
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
         //check if the api method insists on response format using @format comment
753 753
 
754 754
         if ($metadata && isset($metadata['format'])) {
755
-            $formats = explode(',', (string)$metadata['format']);
755
+            $formats = explode(',', (string) $metadata['format']);
756 756
             foreach ($formats as $i => $f) {
757 757
                 $f = trim($f);
758 758
                 if (!in_array($f, $this->formatOverridesMap))
@@ -800,7 +800,7 @@  discard block
 block discarded – undo
800 800
                     if (is_string(Defaults::$apiVendor)
801 801
                         && 0 === stripos($mime,
802 802
                             'application/vnd.'
803
-                            . Defaults::$apiVendor . '-v')
803
+                            . Defaults::$apiVendor.'-v')
804 804
                     ) {
805 805
                         $extension = substr($accept, $index + 1);
806 806
                         if (isset($this->formatMap[$extension])) {
@@ -846,8 +846,8 @@  discard block
 block discarded – undo
846 846
             $this->responseFormat = $format;
847 847
             throw new RestException(
848 848
                 406,
849
-                'Content negotiation failed. ' .
850
-                'Try `' . $format->getMIME() . '` instead.'
849
+                'Content negotiation failed. '.
850
+                'Try `'.$format->getMIME().'` instead.'
851 851
             );
852 852
         } else {
853 853
             // Tell cache content is based at Accept header
@@ -874,7 +874,7 @@  discard block
 block discarded – undo
874 874
                 } else {
875 875
                     throw new RestException(
876 876
                         406,
877
-                        'Content negotiation failed. ' .
877
+                        'Content negotiation failed. '.
878 878
                         'Requested charset is not supported'
879 879
                     );
880 880
                 }
@@ -922,8 +922,8 @@  discard block
 block discarded – undo
922 922
             $filterObj = Scope::get($filterClass);
923 923
 
924 924
             if (!$filterObj instanceof iFilter) {
925
-                throw new RestException (
926
-                    500, 'Filter Class ' .
925
+                throw new RestException(
926
+                    500, 'Filter Class '.
927 927
                     'should implement iFilter');
928 928
             } else if (!($ok = $filterObj->__isAllowed())) {
929 929
                 if (is_null($ok)
@@ -955,8 +955,8 @@  discard block
 block discarded – undo
955 955
                 try {
956 956
                     $authObj = Scope::get($authClass);
957 957
                     if (!method_exists($authObj, Defaults::$authenticationMethod)) {
958
-                        throw new RestException (
959
-                            500, 'Authentication Class ' .
958
+                        throw new RestException(
959
+                            500, 'Authentication Class '.
960 960
                             'should implement iAuthenticate');
961 961
                     } elseif (
962 962
                     !$authObj->{Defaults::$authenticationMethod}()
@@ -992,7 +992,7 @@  discard block
 block discarded – undo
992 992
      */
993 993
     protected function postAuthFilter()
994 994
     {
995
-        if(empty($this->postAuthFilterClasses)) {
995
+        if (empty($this->postAuthFilterClasses)) {
996 996
             return;
997 997
         }
998 998
         $this->dispatch('postAuthFilter');
@@ -1051,7 +1051,7 @@  discard block
 block discarded – undo
1051 1051
             $o->accessLevel);
1052 1052
         if (function_exists('newrelic_name_transaction'))
1053 1053
             newrelic_name_transaction("{$o->className}/{$o->methodName}");
1054
-        $object =  Scope::get($o->className);
1054
+        $object = Scope::get($o->className);
1055 1055
         switch ($accessLevel) {
1056 1056
             case 3 : //protected method
1057 1057
                 $reflectionMethod = new \ReflectionMethod(
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
     {
1095 1095
         //only GET method should be cached if allowed by API developer
1096 1096
         $expires = $this->requestMethod == 'GET' ? Defaults::$headerExpires : 0;
1097
-        if(!is_array(Defaults::$headerCacheControl))
1097
+        if (!is_array(Defaults::$headerCacheControl))
1098 1098
             Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
1099 1099
         $cacheControl = Defaults::$headerCacheControl[0];
1100 1100
         if ($expires > 0) {
@@ -1104,14 +1104,14 @@  discard block
 block discarded – undo
1104 1104
             $cacheControl = str_replace('{expires}', $expires, $cacheControl);
1105 1105
             $expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
1106 1106
         }
1107
-        @header('Cache-Control: ' . $cacheControl);
1108
-        @header('Expires: ' . $expires);
1109
-        @header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
1107
+        @header('Cache-Control: '.$cacheControl);
1108
+        @header('Expires: '.$expires);
1109
+        @header('X-Powered-By: Luracast Restler v'.Restler::VERSION);
1110 1110
 
1111 1111
         if (Defaults::$crossOriginResourceSharing
1112 1112
             && isset($_SERVER['HTTP_ORIGIN'])
1113 1113
         ) {
1114
-            header('Access-Control-Allow-Origin: ' .
1114
+            header('Access-Control-Allow-Origin: '.
1115 1115
                 (Defaults::$accessControlAllowOrigin == '*'
1116 1116
                     ? $_SERVER['HTTP_ORIGIN']
1117 1117
                     : Defaults::$accessControlAllowOrigin)
@@ -1122,19 +1122,19 @@  discard block
 block discarded – undo
1122 1122
 
1123 1123
         $this->responseFormat->setCharset(Defaults::$charset);
1124 1124
         $charset = $this->responseFormat->getCharset()
1125
-            ? : Defaults::$charset;
1125
+            ?: Defaults::$charset;
1126 1126
 
1127
-        @header('Content-Type: ' . (
1127
+        @header('Content-Type: '.(
1128 1128
             Defaults::$useVendorMIMEVersioning
1129 1129
                 ? 'application/vnd.'
1130 1130
                 . Defaults::$apiVendor
1131 1131
                 . "-v{$this->requestedApiVersion}"
1132
-                . '+' . $this->responseFormat->getExtension()
1132
+                . '+'.$this->responseFormat->getExtension()
1133 1133
                 : $this->responseFormat->getMIME())
1134
-            . '; charset=' . $charset
1134
+            . '; charset='.$charset
1135 1135
         );
1136 1136
 
1137
-        @header('Content-Language: ' . Defaults::$language);
1137
+        @header('Content-Language: '.Defaults::$language);
1138 1138
 
1139 1139
         if (isset($this->apiMethodInfo->metadata['header'])) {
1140 1140
             foreach ($this->apiMethodInfo->metadata['header'] as $header)
@@ -1152,7 +1152,7 @@  discard block
 block discarded – undo
1152 1152
         }
1153 1153
         $this->responseCode = $code;
1154 1154
         @header(
1155
-            "{$_SERVER['SERVER_PROTOCOL']} $code " .
1155
+            "{$_SERVER['SERVER_PROTOCOL']} $code ".
1156 1156
             (isset(RestException::$codes[$code]) ? RestException::$codes[$code] : '')
1157 1157
         );
1158 1158
     }
@@ -1171,7 +1171,7 @@  discard block
 block discarded – undo
1171 1171
             $authString = count($this->authClasses)
1172 1172
                 ? Scope::get($this->authClasses[0])->__getWWWAuthenticateString()
1173 1173
                 : 'Unknown';
1174
-            @header('WWW-Authenticate: ' . $authString, false);
1174
+            @header('WWW-Authenticate: '.$authString, false);
1175 1175
         }
1176 1176
         $this->dispatch('complete');
1177 1177
         if (Defaults::$returnResponse) {
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
 
1198 1198
         $this->exception = $exception;
1199 1199
 
1200
-        $method = 'handle' . $exception->getCode();
1200
+        $method = 'handle'.$exception->getCode();
1201 1201
         $handled = false;
1202 1202
         foreach ($this->errorClasses as $className) {
1203 1203
             if (method_exists($className, $method)) {
@@ -1255,8 +1255,7 @@  discard block
 block discarded – undo
1255 1255
     public function setAPIVersion($version = 1, $minimum = 1)
1256 1256
     {
1257 1257
         if (!is_int($version) && $version < 1) {
1258
-            throw new InvalidArgumentException
1259
-            ('version should be an integer greater than 0');
1258
+            throw new InvalidArgumentException('version should be an integer greater than 0');
1260 1259
         }
1261 1260
         $this->apiVersion = $version;
1262 1261
         if (is_int($minimum)) {
@@ -1311,7 +1310,7 @@  discard block
 block discarded – undo
1311 1310
      */
1312 1311
     public function addAPIClass($className, $resourcePath = null)
1313 1312
     {
1314
-        try{
1313
+        try {
1315 1314
             if ($this->productionMode && is_null($this->cached)) {
1316 1315
                 $routes = $this->cache->get('routes');
1317 1316
                 if (isset($routes) && is_array($routes)) {
@@ -1341,12 +1340,12 @@  discard block
 block discarded – undo
1341 1340
                 //versioned api
1342 1341
                 if (false !== ($index = strrpos($className, '\\'))) {
1343 1342
                     $name = substr($className, 0, $index)
1344
-                        . '\\v{$version}' . substr($className, $index);
1343
+                        . '\\v{$version}'.substr($className, $index);
1345 1344
                 } else if (false !== ($index = strrpos($className, '_'))) {
1346 1345
                     $name = substr($className, 0, $index)
1347
-                        . '_v{$version}' . substr($className, $index);
1346
+                        . '_v{$version}'.substr($className, $index);
1348 1347
                 } else {
1349
-                    $name = 'v{$version}\\' . $className;
1348
+                    $name = 'v{$version}\\'.$className;
1350 1349
                 }
1351 1350
 
1352 1351
                 for ($version = $this->apiMinimumVersion;
@@ -1478,13 +1477,13 @@  discard block
 block discarded – undo
1478 1477
                     //versioned api
1479 1478
                     if (false !== ($index = strrpos($className, '\\'))) {
1480 1479
                         $name = substr($className, 0, $index)
1481
-                            . '\\v{$version}' . substr($className, $index);
1480
+                            . '\\v{$version}'.substr($className, $index);
1482 1481
                     } else {
1483 1482
                         if (false !== ($index = strrpos($className, '_'))) {
1484 1483
                             $name = substr($className, 0, $index)
1485
-                                . '_v{$version}' . substr($className, $index);
1484
+                                . '_v{$version}'.substr($className, $index);
1486 1485
                         } else {
1487
-                            $name = 'v{$version}\\' . $className;
1486
+                            $name = 'v{$version}\\'.$className;
1488 1487
                         }
1489 1488
                     }
1490 1489
 
@@ -1524,7 +1523,7 @@  discard block
 block discarded – undo
1524 1523
             }
1525 1524
         } catch (Exception $e) {
1526 1525
             $e = new Exception(
1527
-                "mapAPIClasses failed. " . $e->getMessage(),
1526
+                "mapAPIClasses failed. ".$e->getMessage(),
1528 1527
                 $e->getCode(),
1529 1528
                 $e
1530 1529
             );
@@ -1653,7 +1652,7 @@  discard block
 block discarded – undo
1653 1652
     protected function preCall()
1654 1653
     {
1655 1654
         $o = & $this->apiMethodInfo;
1656
-        $preCall = '_pre_' . $o->methodName . '_'
1655
+        $preCall = '_pre_'.$o->methodName.'_'
1657 1656
             . $this->requestFormat->getExtension();
1658 1657
 
1659 1658
         if (method_exists($o->className, $preCall)) {
@@ -1676,7 +1675,7 @@  discard block
 block discarded – undo
1676 1675
     protected function postCall()
1677 1676
     {
1678 1677
         $o = & $this->apiMethodInfo;
1679
-        $postCall = '_post_' . $o->methodName . '_' .
1678
+        $postCall = '_post_'.$o->methodName.'_'.
1680 1679
             $this->responseFormat->getExtension();
1681 1680
         if (method_exists($o->className, $postCall)) {
1682 1681
             $this->dispatch('postCall');
Please login to merge, or discard this patch.
Braces   +66 added lines, -45 removed lines patch added patch discarded remove patch
@@ -284,8 +284,9 @@  discard block
 block discarded – undo
284 284
                     $this->route();
285 285
                     throw $e;
286 286
                 }
287
-                if (Defaults::$useVendorMIMEVersioning)
288
-                    $this->responseFormat = $this->negotiateResponseFormat();
287
+                if (Defaults::$useVendorMIMEVersioning) {
288
+                                    $this->responseFormat = $this->negotiateResponseFormat();
289
+                }
289 290
                 $this->route();
290 291
             } catch (Exception $e) {
291 292
                 $this->negotiate();
@@ -401,9 +402,10 @@  discard block
 block discarded – undo
401 402
 
402 403
             $obj = Scope::get($className);
403 404
 
404
-            if (!$obj instanceof iFormat)
405
-                throw new Exception('Invalid format class; must implement ' .
405
+            if (!$obj instanceof iFormat) {
406
+                            throw new Exception('Invalid format class; must implement ' .
406 407
                     'iFormat interface');
408
+            }
407 409
             if ($throwException && get_class($obj) == get_class($this->requestFormat)) {
408 410
                 $throwException = false;
409 411
             }
@@ -413,12 +415,15 @@  discard block
 block discarded – undo
413 415
                     $this->writableMimeTypes[]=$mime;
414 416
                     $extensions[".$extension"] = true;
415 417
                 }
416
-                if($obj->isReadable())
417
-                    $this->readableMimeTypes[]=$mime;
418
-                if (!isset($this->formatMap[$extension]))
419
-                    $this->formatMap[$extension] = $className;
420
-                if (!isset($this->formatMap[$mime]))
421
-                    $this->formatMap[$mime] = $className;
418
+                if($obj->isReadable()) {
419
+                                    $this->readableMimeTypes[]=$mime;
420
+                }
421
+                if (!isset($this->formatMap[$extension])) {
422
+                                    $this->formatMap[$extension] = $className;
423
+                }
424
+                if (!isset($this->formatMap[$mime])) {
425
+                                    $this->formatMap[$mime] = $className;
426
+                }
422 427
             }
423 428
         }
424 429
         if ($throwException) {
@@ -449,17 +454,21 @@  discard block
 block discarded – undo
449 454
 
450 455
             $obj = Scope::get($className);
451 456
 
452
-            if (!$obj instanceof iFormat)
453
-                throw new Exception('Invalid format class; must implement ' .
457
+            if (!$obj instanceof iFormat) {
458
+                            throw new Exception('Invalid format class; must implement ' .
454 459
                     'iFormat interface');
460
+            }
455 461
 
456 462
             foreach ($obj->getMIMEMap() as $mime => $extension) {
457
-                if (!isset($this->formatOverridesMap[$extension]))
458
-                    $this->formatOverridesMap[$extension] = $className;
459
-                if (!isset($this->formatOverridesMap[$mime]))
460
-                    $this->formatOverridesMap[$mime] = $className;
461
-                if($obj->isWritable())
462
-                    $extensions[".$extension"] = true;
463
+                if (!isset($this->formatOverridesMap[$extension])) {
464
+                                    $this->formatOverridesMap[$extension] = $className;
465
+                }
466
+                if (!isset($this->formatOverridesMap[$mime])) {
467
+                                    $this->formatOverridesMap[$mime] = $className;
468
+                }
469
+                if($obj->isWritable()) {
470
+                                    $extensions[".$extension"] = true;
471
+                }
463 472
             }
464 473
         }
465 474
         $this->formatOverridesMap['extensions'] = array_keys($extensions);
@@ -498,9 +507,10 @@  discard block
 block discarded – undo
498 507
     protected function getPath()
499 508
     {
500 509
         // fix SCRIPT_NAME for PHP 5.4 built-in web server
501
-        if (false === strpos($_SERVER['SCRIPT_NAME'], '.php'))
502
-            $_SERVER['SCRIPT_NAME']
510
+        if (false === strpos($_SERVER['SCRIPT_NAME'], '.php')) {
511
+                    $_SERVER['SCRIPT_NAME']
503 512
                 = '/' . substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT']) + 1);
513
+        }
504 514
 
505 515
         list($base, $path) = Util::splitCommonPath(
506 516
             strtok(urldecode($_SERVER['REQUEST_URI']), '?'), //remove query string
@@ -521,8 +531,9 @@  discard block
 block discarded – undo
521 531
                 (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || // Amazon ELB
522 532
                 (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on');
523 533
             $baseUrl = ($https ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'];
524
-            if (!$https && $port != '80' || $https && $port != '443')
525
-                $baseUrl .= ':' . $port;
534
+            if (!$https && $port != '80' || $https && $port != '443') {
535
+                            $baseUrl .= ':' . $port;
536
+            }
526 537
             $this->baseUrl = $baseUrl . $base;
527 538
         } elseif (!empty($base) && false === strpos($this->baseUrl, $base)) {
528 539
             $this->baseUrl .= $base;
@@ -572,9 +583,9 @@  discard block
 block discarded – undo
572 583
             if (false !== $pos = strpos($mime, ';')) {
573 584
                 $mime = substr($mime, 0, $pos);
574 585
             }
575
-            if ($mime == UrlEncodedFormat::MIME)
576
-                $format = Scope::get('UrlEncodedFormat');
577
-            elseif (isset($this->formatMap[$mime])) {
586
+            if ($mime == UrlEncodedFormat::MIME) {
587
+                            $format = Scope::get('UrlEncodedFormat');
588
+            } elseif (isset($this->formatMap[$mime])) {
578 589
                 $format = Scope::get($this->formatMap[$mime]);
579 590
                 $format->setMIME($mime);
580 591
             } elseif (!$this->requestFormatDiffered && isset($this->formatOverridesMap[$mime])) {
@@ -630,8 +641,9 @@  discard block
 block discarded – undo
630 641
             }
631 642
 
632 643
             $stream = $this->getRequestStream();
633
-            if($stream === FALSE)
634
-                return array();
644
+            if($stream === FALSE) {
645
+                            return array();
646
+            }
635 647
             $r = $this->requestFormat instanceof iDecodeStream
636 648
                 ? $this->requestFormat->decodeStream($stream)
637 649
                 : $this->requestFormat->decode(stream_get_contents($stream));
@@ -673,8 +685,9 @@  discard block
 block discarded – undo
673 685
                 }
674 686
             }
675 687
         }
676
-        if (!isset($o->className))
677
-            throw new RestException(404);
688
+        if (!isset($o->className)) {
689
+                    throw new RestException(404);
690
+        }
678 691
 
679 692
         if(isset($this->apiVersionMap[$o->className])){
680 693
             Scope::$classAliases[Util::getShortName($o->className)]
@@ -715,13 +728,15 @@  discard block
 block discarded – undo
715 728
             $this->requestMethod == 'OPTIONS'
716 729
             && Defaults::$crossOriginResourceSharing
717 730
         ) {
718
-            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
719
-                header('Access-Control-Allow-Methods: '
731
+            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
732
+                            header('Access-Control-Allow-Methods: '
720 733
                     . Defaults::$accessControlAllowMethods);
734
+            }
721 735
 
722
-            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
723
-                header('Access-Control-Allow-Headers: '
736
+            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
737
+                            header('Access-Control-Allow-Headers: '
724 738
                     . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
739
+            }
725 740
 
726 741
             header('Access-Control-Allow-Origin: ' .
727 742
                 ((Defaults::$accessControlAllowOrigin == '*' && isset($_SERVER['HTTP_ORIGIN']))
@@ -755,11 +770,12 @@  discard block
 block discarded – undo
755 770
             $formats = explode(',', (string)$metadata['format']);
756 771
             foreach ($formats as $i => $f) {
757 772
                 $f = trim($f);
758
-                if (!in_array($f, $this->formatOverridesMap))
759
-                    throw new RestException(
773
+                if (!in_array($f, $this->formatOverridesMap)) {
774
+                                    throw new RestException(
760 775
                         500,
761 776
                         "Given @format is not present in overriding formats. Please call `\$r->setOverridingFormats('$f');` first."
762 777
                     );
778
+                }
763 779
                 $formats[$i] = $f;
764 780
             }
765 781
             call_user_func_array(array($this, 'setSupportedFormats'), $formats);
@@ -1032,8 +1048,9 @@  discard block
 block discarded – undo
1032 1048
                 }
1033 1049
                 $valid = $o->parameters[$index];
1034 1050
                 $o->parameters[$index] = null;
1035
-                if (empty(Validator::$exceptions))
1036
-                    $o->metadata['param'][$index]['autofocus'] = true;
1051
+                if (empty(Validator::$exceptions)) {
1052
+                                    $o->metadata['param'][$index]['autofocus'] = true;
1053
+                }
1037 1054
                 $valid = $validator::validate(
1038 1055
                     $valid, $info
1039 1056
                 );
@@ -1049,8 +1066,9 @@  discard block
 block discarded – undo
1049 1066
         $o = & $this->apiMethodInfo;
1050 1067
         $accessLevel = max(Defaults::$apiAccessLevel,
1051 1068
             $o->accessLevel);
1052
-        if (function_exists('newrelic_name_transaction'))
1053
-            newrelic_name_transaction("{$o->className}/{$o->methodName}");
1069
+        if (function_exists('newrelic_name_transaction')) {
1070
+                    newrelic_name_transaction("{$o->className}/{$o->methodName}");
1071
+        }
1054 1072
         $object =  Scope::get($o->className);
1055 1073
         switch ($accessLevel) {
1056 1074
             case 3 : //protected method
@@ -1094,8 +1112,9 @@  discard block
 block discarded – undo
1094 1112
     {
1095 1113
         //only GET method should be cached if allowed by API developer
1096 1114
         $expires = $this->requestMethod == 'GET' ? Defaults::$headerExpires : 0;
1097
-        if(!is_array(Defaults::$headerCacheControl))
1098
-            Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
1115
+        if(!is_array(Defaults::$headerCacheControl)) {
1116
+                    Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
1117
+        }
1099 1118
         $cacheControl = Defaults::$headerCacheControl[0];
1100 1119
         if ($expires > 0) {
1101 1120
             $cacheControl = $this->apiMethodInfo->accessLevel
@@ -1137,8 +1156,9 @@  discard block
 block discarded – undo
1137 1156
         @header('Content-Language: ' . Defaults::$language);
1138 1157
 
1139 1158
         if (isset($this->apiMethodInfo->metadata['header'])) {
1140
-            foreach ($this->apiMethodInfo->metadata['header'] as $header)
1141
-                @header($header, true);
1159
+            foreach ($this->apiMethodInfo->metadata['header'] as $header) {
1160
+                            @header($header, true);
1161
+            }
1142 1162
         }
1143 1163
         $code = 200;
1144 1164
         if (!Defaults::$suppressResponseCode) {
@@ -1202,8 +1222,9 @@  discard block
 block discarded – undo
1202 1222
         foreach ($this->errorClasses as $className) {
1203 1223
             if (method_exists($className, $method)) {
1204 1224
                 $obj = Scope::get($className);
1205
-                if ($obj->$method($exception))
1206
-                    $handled = true;
1225
+                if ($obj->$method($exception)) {
1226
+                                    $handled = true;
1227
+                }
1207 1228
             }
1208 1229
         }
1209 1230
         if ($handled) {
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/PassThrough.php 3 patches
Indentation   +72 added lines, -72 removed lines patch added patch discarded remove patch
@@ -14,77 +14,77 @@
 block discarded – undo
14 14
  */
15 15
 class PassThrough
16 16
 {
17
-    public static $mimeTypes = array(
18
-        'js' => 'text/javascript',
19
-        'css' => 'text/css',
20
-        'png' => 'image/png',
21
-        'jpg' => 'image/jpeg',
22
-        'gif' => 'image/gif',
23
-        'html' => 'text/html',
24
-    );
17
+	public static $mimeTypes = array(
18
+		'js' => 'text/javascript',
19
+		'css' => 'text/css',
20
+		'png' => 'image/png',
21
+		'jpg' => 'image/jpeg',
22
+		'gif' => 'image/gif',
23
+		'html' => 'text/html',
24
+	);
25 25
 
26
-    /**
27
-     * Serve a file outside web root
28
-     *
29
-     * Respond with a file stored outside web accessible path
30
-     *
31
-     * @param string $filename      full path for the file to be served
32
-     * @param bool   $forceDownload should the we download instead of viewing
33
-     * @param int    $expires       cache expiry in number of seconds
34
-     * @param bool   $isPublic      cache control, is it public or private
35
-     *
36
-     * @throws RestException
37
-     *
38
-     */
39
-    public static function file($filename, $forceDownload = false, $expires = 0, $isPublic = true)
40
-    {
41
-        if (!is_file($filename))
42
-            throw new RestException(404);
43
-        if (!is_readable($filename))
44
-            throw new RestException(403);
45
-        $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
46
-        if (!$mime = Util::nestedValue(static::$mimeTypes, $extension)) {
47
-            if (!function_exists('finfo_open')) {
48
-                throw new RestException(
49
-                    500,
50
-                    'Unable to find media type of ' .
51
-                    basename($filename) .
52
-                    ' either enable fileinfo php extension or update ' .
53
-                    'PassThrough::$mimeTypes to include mime type for ' . $extension .
54
-                    ' extension'
55
-                );
56
-            }
57
-            $finfo = finfo_open(FILEINFO_MIME_TYPE);
58
-            $mime = finfo_file($finfo, $filename);
59
-        }
60
-        if (!is_array(Defaults::$headerCacheControl))
61
-            Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
62
-        $cacheControl = Defaults::$headerCacheControl[0];
63
-        if ($expires > 0) {
64
-            $cacheControl = $isPublic ? 'public' : 'private';
65
-            $cacheControl .= end(Defaults::$headerCacheControl);
66
-            $cacheControl = str_replace('{expires}', $expires, $cacheControl);
67
-            $expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
68
-        }
69
-        header('Cache-Control: ' . $cacheControl);
70
-        header('Expires: ' . $expires);
71
-        $lastModified = filemtime($filename);
72
-        if (
73
-            isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
74
-            strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified
75
-        ) {
76
-            header("{$_SERVER['SERVER_PROTOCOL']} 304 Not Modified");
77
-            exit;
78
-        }
79
-        header('Last-Modified: ' . date('r', $lastModified));
80
-        header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
81
-        header('Content-type: ' . $mime);
82
-        header("Content-Length: " . filesize($filename));
83
-        if ($forceDownload) {
84
-            header("Content-Transfer-Encoding: binary");
85
-            header('Content-Disposition: attachment; filename="' . $filename . '"');
86
-        }
87
-        readfile($filename);
88
-        exit;
89
-    }
26
+	/**
27
+	 * Serve a file outside web root
28
+	 *
29
+	 * Respond with a file stored outside web accessible path
30
+	 *
31
+	 * @param string $filename      full path for the file to be served
32
+	 * @param bool   $forceDownload should the we download instead of viewing
33
+	 * @param int    $expires       cache expiry in number of seconds
34
+	 * @param bool   $isPublic      cache control, is it public or private
35
+	 *
36
+	 * @throws RestException
37
+	 *
38
+	 */
39
+	public static function file($filename, $forceDownload = false, $expires = 0, $isPublic = true)
40
+	{
41
+		if (!is_file($filename))
42
+			throw new RestException(404);
43
+		if (!is_readable($filename))
44
+			throw new RestException(403);
45
+		$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
46
+		if (!$mime = Util::nestedValue(static::$mimeTypes, $extension)) {
47
+			if (!function_exists('finfo_open')) {
48
+				throw new RestException(
49
+					500,
50
+					'Unable to find media type of ' .
51
+					basename($filename) .
52
+					' either enable fileinfo php extension or update ' .
53
+					'PassThrough::$mimeTypes to include mime type for ' . $extension .
54
+					' extension'
55
+				);
56
+			}
57
+			$finfo = finfo_open(FILEINFO_MIME_TYPE);
58
+			$mime = finfo_file($finfo, $filename);
59
+		}
60
+		if (!is_array(Defaults::$headerCacheControl))
61
+			Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
62
+		$cacheControl = Defaults::$headerCacheControl[0];
63
+		if ($expires > 0) {
64
+			$cacheControl = $isPublic ? 'public' : 'private';
65
+			$cacheControl .= end(Defaults::$headerCacheControl);
66
+			$cacheControl = str_replace('{expires}', $expires, $cacheControl);
67
+			$expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
68
+		}
69
+		header('Cache-Control: ' . $cacheControl);
70
+		header('Expires: ' . $expires);
71
+		$lastModified = filemtime($filename);
72
+		if (
73
+			isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
74
+			strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified
75
+		) {
76
+			header("{$_SERVER['SERVER_PROTOCOL']} 304 Not Modified");
77
+			exit;
78
+		}
79
+		header('Last-Modified: ' . date('r', $lastModified));
80
+		header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
81
+		header('Content-type: ' . $mime);
82
+		header("Content-Length: " . filesize($filename));
83
+		if ($forceDownload) {
84
+			header("Content-Transfer-Encoding: binary");
85
+			header('Content-Disposition: attachment; filename="' . $filename . '"');
86
+		}
87
+		readfile($filename);
88
+		exit;
89
+	}
90 90
 } 
91 91
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -47,10 +47,10 @@  discard block
 block discarded – undo
47 47
             if (!function_exists('finfo_open')) {
48 48
                 throw new RestException(
49 49
                     500,
50
-                    'Unable to find media type of ' .
51
-                    basename($filename) .
52
-                    ' either enable fileinfo php extension or update ' .
53
-                    'PassThrough::$mimeTypes to include mime type for ' . $extension .
50
+                    'Unable to find media type of '.
51
+                    basename($filename).
52
+                    ' either enable fileinfo php extension or update '.
53
+                    'PassThrough::$mimeTypes to include mime type for '.$extension.
54 54
                     ' extension'
55 55
                 );
56 56
             }
@@ -66,8 +66,8 @@  discard block
 block discarded – undo
66 66
             $cacheControl = str_replace('{expires}', $expires, $cacheControl);
67 67
             $expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expires);
68 68
         }
69
-        header('Cache-Control: ' . $cacheControl);
70
-        header('Expires: ' . $expires);
69
+        header('Cache-Control: '.$cacheControl);
70
+        header('Expires: '.$expires);
71 71
         $lastModified = filemtime($filename);
72 72
         if (
73 73
             isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
@@ -76,13 +76,13 @@  discard block
 block discarded – undo
76 76
             header("{$_SERVER['SERVER_PROTOCOL']} 304 Not Modified");
77 77
             exit;
78 78
         }
79
-        header('Last-Modified: ' . date('r', $lastModified));
80
-        header('X-Powered-By: Luracast Restler v' . Restler::VERSION);
81
-        header('Content-type: ' . $mime);
82
-        header("Content-Length: " . filesize($filename));
79
+        header('Last-Modified: '.date('r', $lastModified));
80
+        header('X-Powered-By: Luracast Restler v'.Restler::VERSION);
81
+        header('Content-type: '.$mime);
82
+        header("Content-Length: ".filesize($filename));
83 83
         if ($forceDownload) {
84 84
             header("Content-Transfer-Encoding: binary");
85
-            header('Content-Disposition: attachment; filename="' . $filename . '"');
85
+            header('Content-Disposition: attachment; filename="'.$filename.'"');
86 86
         }
87 87
         readfile($filename);
88 88
         exit;
Please login to merge, or discard this patch.
Braces   +9 added lines, -6 removed lines patch added patch discarded remove patch
@@ -38,10 +38,12 @@  discard block
 block discarded – undo
38 38
      */
39 39
     public static function file($filename, $forceDownload = false, $expires = 0, $isPublic = true)
40 40
     {
41
-        if (!is_file($filename))
42
-            throw new RestException(404);
43
-        if (!is_readable($filename))
44
-            throw new RestException(403);
41
+        if (!is_file($filename)) {
42
+                    throw new RestException(404);
43
+        }
44
+        if (!is_readable($filename)) {
45
+                    throw new RestException(403);
46
+        }
45 47
         $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
46 48
         if (!$mime = Util::nestedValue(static::$mimeTypes, $extension)) {
47 49
             if (!function_exists('finfo_open')) {
@@ -57,8 +59,9 @@  discard block
 block discarded – undo
57 59
             $finfo = finfo_open(FILEINFO_MIME_TYPE);
58 60
             $mime = finfo_file($finfo, $filename);
59 61
         }
60
-        if (!is_array(Defaults::$headerCacheControl))
61
-            Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
62
+        if (!is_array(Defaults::$headerCacheControl)) {
63
+                    Defaults::$headerCacheControl = array(Defaults::$headerCacheControl);
64
+        }
62 65
         $cacheControl = Defaults::$headerCacheControl[0];
63 66
         if ($expires > 0) {
64 67
             $cacheControl = $isPublic ? 'public' : 'private';
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/iIdentifyUser.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -16,48 +16,48 @@
 block discarded – undo
16 16
  */
17 17
 interface iIdentifyUser
18 18
 {
19
-    /**
20
-     * A way to uniquely identify the current api consumer
21
-     *
22
-     * When his user id is known it should be used otherwise ip address
23
-     * can be used
24
-     *
25
-     * @param bool $includePlatform Should we consider user alone or should
26
-     *                              consider the application/platform/device
27
-     *                              as well for generating unique id
28
-     *
29
-     * @return string
30
-     */
31
-    public static function getUniqueIdentifier($includePlatform = false);
19
+	/**
20
+	 * A way to uniquely identify the current api consumer
21
+	 *
22
+	 * When his user id is known it should be used otherwise ip address
23
+	 * can be used
24
+	 *
25
+	 * @param bool $includePlatform Should we consider user alone or should
26
+	 *                              consider the application/platform/device
27
+	 *                              as well for generating unique id
28
+	 *
29
+	 * @return string
30
+	 */
31
+	public static function getUniqueIdentifier($includePlatform = false);
32 32
 
33
-    /**
34
-     * User identity to be used for caching purpose
35
-     *
36
-     * When the dynamic cache service places an object in the cache, it needs to
37
-     * label it with a unique identifying string known as a cache ID. This
38
-     * method gives that identifier
39
-     *
40
-     * @return string
41
-     */
42
-    public static function getCacheIdentifier();
33
+	/**
34
+	 * User identity to be used for caching purpose
35
+	 *
36
+	 * When the dynamic cache service places an object in the cache, it needs to
37
+	 * label it with a unique identifying string known as a cache ID. This
38
+	 * method gives that identifier
39
+	 *
40
+	 * @return string
41
+	 */
42
+	public static function getCacheIdentifier();
43 43
 
44
-    /**
45
-     * Authentication classes should call this method
46
-     *
47
-     * @param string $id user id as identified by the authentication classes
48
-     *
49
-     * @return void
50
-     */
51
-    public static function setUniqueIdentifier($id);
44
+	/**
45
+	 * Authentication classes should call this method
46
+	 *
47
+	 * @param string $id user id as identified by the authentication classes
48
+	 *
49
+	 * @return void
50
+	 */
51
+	public static function setUniqueIdentifier($id);
52 52
 
53
-    /**
54
-     * User identity for caching purpose
55
-     *
56
-     * In a role based access control system this will be based on role
57
-     *
58
-     * @param $id
59
-     *
60
-     * @return void
61
-     */
62
-    public static function setCacheIdentifier($id);
53
+	/**
54
+	 * User identity for caching purpose
55
+	 *
56
+	 * In a role based access control system this will be based on role
57
+	 *
58
+	 * @param $id
59
+	 *
60
+	 * @return void
61
+	 */
62
+	public static function setCacheIdentifier($id);
63 63
 }
64 64
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/User.php 3 patches
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -15,86 +15,86 @@
 block discarded – undo
15 15
  */
16 16
 class User implements iIdentifyUser
17 17
 {
18
-    private static $initialized = false;
19
-    public static $id = null;
20
-    public static $cacheId = null;
21
-    public static $ip;
22
-    public static $browser = '';
23
-    public static $platform = '';
18
+	private static $initialized = false;
19
+	public static $id = null;
20
+	public static $cacheId = null;
21
+	public static $ip;
22
+	public static $browser = '';
23
+	public static $platform = '';
24 24
 
25
-    public static function init()
26
-    {
27
-        static::$initialized = true;
28
-        static::$ip = static::getIpAddress();
29
-    }
25
+	public static function init()
26
+	{
27
+		static::$initialized = true;
28
+		static::$ip = static::getIpAddress();
29
+	}
30 30
 
31
-    public static function getUniqueIdentifier($includePlatform = false)
32
-    {
33
-        if (!static::$initialized) static::init();
34
-        return static::$id ? : base64_encode('ip:' . ($includePlatform
35
-            ? static::$ip . '-' . static::$platform
36
-            : static::$ip
37
-        ));
38
-    }
31
+	public static function getUniqueIdentifier($includePlatform = false)
32
+	{
33
+		if (!static::$initialized) static::init();
34
+		return static::$id ? : base64_encode('ip:' . ($includePlatform
35
+			? static::$ip . '-' . static::$platform
36
+			: static::$ip
37
+		));
38
+	}
39 39
 
40
-    public static function getIpAddress($ignoreProxies = false)
41
-    {
42
-        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR',
43
-                     'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP',
44
-                     'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED',
45
-                     'REMOTE_ADDR') as $key) {
46
-            if (array_key_exists($key, $_SERVER) === true) {
47
-                foreach (explode(',', $_SERVER[$key]) as $ip) {
48
-                    $ip = trim($ip); // just to be safe
40
+	public static function getIpAddress($ignoreProxies = false)
41
+	{
42
+		foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR',
43
+					 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP',
44
+					 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED',
45
+					 'REMOTE_ADDR') as $key) {
46
+			if (array_key_exists($key, $_SERVER) === true) {
47
+				foreach (explode(',', $_SERVER[$key]) as $ip) {
48
+					$ip = trim($ip); // just to be safe
49 49
 
50
-                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4
51
-                        | FILTER_FLAG_NO_PRIV_RANGE
52
-                        | FILTER_FLAG_NO_RES_RANGE) !== false
53
-                    ) {
54
-                        return $ip;
55
-                    }
56
-                }
57
-            }
58
-        }
59
-    }
50
+					if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4
51
+						| FILTER_FLAG_NO_PRIV_RANGE
52
+						| FILTER_FLAG_NO_RES_RANGE) !== false
53
+					) {
54
+						return $ip;
55
+					}
56
+				}
57
+			}
58
+		}
59
+	}
60 60
 
61
-    /**
62
-     * Authentication classes should call this method
63
-     *
64
-     * @param string $id user id as identified by the authentication classes
65
-     *
66
-     * @return void
67
-     */
68
-    public static function setUniqueIdentifier($id)
69
-    {
70
-        static::$id = $id;
71
-    }
61
+	/**
62
+	 * Authentication classes should call this method
63
+	 *
64
+	 * @param string $id user id as identified by the authentication classes
65
+	 *
66
+	 * @return void
67
+	 */
68
+	public static function setUniqueIdentifier($id)
69
+	{
70
+		static::$id = $id;
71
+	}
72 72
 
73
-    /**
74
-     * User identity to be used for caching purpose
75
-     *
76
-     * When the dynamic cache service places an object in the cache, it needs to
77
-     * label it with a unique identifying string known as a cache ID. This
78
-     * method gives that identifier
79
-     *
80
-     * @return string
81
-     */
82
-    public static function getCacheIdentifier()
83
-    {
84
-        return static::$cacheId ?: static::$id;
85
-    }
73
+	/**
74
+	 * User identity to be used for caching purpose
75
+	 *
76
+	 * When the dynamic cache service places an object in the cache, it needs to
77
+	 * label it with a unique identifying string known as a cache ID. This
78
+	 * method gives that identifier
79
+	 *
80
+	 * @return string
81
+	 */
82
+	public static function getCacheIdentifier()
83
+	{
84
+		return static::$cacheId ?: static::$id;
85
+	}
86 86
 
87
-    /**
88
-     * User identity for caching purpose
89
-     *
90
-     * In a role based access control system this will be based on role
91
-     *
92
-     * @param $id
93
-     *
94
-     * @return void
95
-     */
96
-    public static function setCacheIdentifier($id)
97
-    {
98
-        static::$cacheId = $id;
99
-    }
87
+	/**
88
+	 * User identity for caching purpose
89
+	 *
90
+	 * In a role based access control system this will be based on role
91
+	 *
92
+	 * @param $id
93
+	 *
94
+	 * @return void
95
+	 */
96
+	public static function setCacheIdentifier($id)
97
+	{
98
+		static::$cacheId = $id;
99
+	}
100 100
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -31,8 +31,8 @@
 block discarded – undo
31 31
     public static function getUniqueIdentifier($includePlatform = false)
32 32
     {
33 33
         if (!static::$initialized) static::init();
34
-        return static::$id ? : base64_encode('ip:' . ($includePlatform
35
-            ? static::$ip . '-' . static::$platform
34
+        return static::$id ?: base64_encode('ip:'.($includePlatform
35
+            ? static::$ip.'-'.static::$platform
36 36
             : static::$ip
37 37
         ));
38 38
     }
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -30,7 +30,9 @@
 block discarded – undo
30 30
 
31 31
     public static function getUniqueIdentifier($includePlatform = false)
32 32
     {
33
-        if (!static::$initialized) static::init();
33
+        if (!static::$initialized) {
34
+        	static::init();
35
+        }
34 36
         return static::$id ? : base64_encode('ip:' . ($includePlatform
35 37
             ? static::$ip . '-' . static::$platform
36 38
             : static::$ip
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Flash.php 1 patch
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -19,156 +19,156 @@
 block discarded – undo
19 19
  */
20 20
 class Flash implements ArrayAccess
21 21
 {
22
-    const SUCCESS = 'success';
23
-    const INFO = 'info';
24
-    const WARNING = 'warning';
25
-    const DANGER = 'danger';
26
-
27
-    /**
28
-     * @var Flash
29
-     */
30
-    private static $instance;
31
-    private $usedOnce = false;
32
-
33
-    /**
34
-     * Flash a success message to user
35
-     *
36
-     * @param string $message
37
-     * @param string $header
38
-     *
39
-     * @return Flash
40
-     */
41
-    public static function success($message, $header = '')
42
-    {
43
-        return static::message($message, $header, Flash::SUCCESS);
44
-    }
45
-
46
-    /**
47
-     * Flash a info message to user
48
-     *
49
-     * @param string $message
50
-     * @param string $header
51
-     *
52
-     * @return Flash
53
-     */
54
-    public static function info($message, $header = '')
55
-    {
56
-        return static::message($message, $header, Flash::INFO);
57
-    }
58
-
59
-    /**
60
-     * Flash a warning message to user
61
-     *
62
-     * @param string $message
63
-     * @param string $header
64
-     *
65
-     * @return Flash
66
-     */
67
-    public static function warning($message, $header = '')
68
-    {
69
-        return static::message($message, $header, Flash::WARNING);
70
-    }
71
-
72
-    /**
73
-     * Flash a error message to user
74
-     *
75
-     * @param string $message
76
-     * @param string $header
77
-     *
78
-     * @return Flash
79
-     */
80
-    public static function danger($message, $header = '')
81
-    {
82
-        return static::message($message, $header, Flash::DANGER);
83
-    }
84
-
85
-    /**
86
-     * Flash a message to user
87
-     *
88
-     * @param string $text message text
89
-     * @param string $header
90
-     * @param string $type
91
-     *
92
-     * @return Flash
93
-     */
94
-    public static function message($text, $header = '', $type = Flash::WARNING)
95
-    {
96
-        return static::set(array('message' => $text, 'header' => $header, 'type' => $type));
97
-    }
98
-
99
-    /**
100
-     * Set some data for one time use
101
-     *
102
-     * @param array $data array of key value pairs {@type associative}
103
-     *
104
-     * @return Flash
105
-     */
106
-    public static function set(array $data)
107
-    {
108
-        if (!static::$instance) {
109
-            static::$instance = new Flash();
110
-        }
111
-        if (!isset($_SESSION['flash'])) {
112
-            $_SESSION['flash'] = array();
113
-        }
114
-        $_SESSION['flash'] += $data;
115
-        HtmlFormat::$data['flash'] = static::$instance;
116
-
117
-        return static::$instance;
118
-    }
119
-
120
-    public function __get($name)
121
-    {
122
-        $this->usedOnce = true;
123
-
124
-        return Util::nestedValue($_SESSION, 'flash', $name);
125
-    }
126
-
127
-    public function __isset($name)
128
-    {
129
-        return !is_null(Util::nestedValue($_SESSION, 'flash', $name));
130
-    }
131
-
132
-    public function __destruct()
133
-    {
134
-        if ($this->usedOnce) {
135
-            unset($_SESSION['flash']);
136
-        }
137
-    }
138
-
139
-    /**
140
-     * Specify data which should be serialized to JSON
141
-     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
142
-     * @return mixed data which can be serialized by <b>json_encode</b>,
143
-     * which is a value of any type other than a resource.
144
-     */
145
-    public function jsonSerialize()
146
-    {
147
-        $this->usedOnce = true;
148
-
149
-        return isset($_SESSION['flash'])
150
-            ? $_SESSION['flash']
151
-            : array();
152
-    }
153
-
154
-
155
-    public function offsetExists($offset)
156
-    {
157
-        return $this->__isset($offset);
158
-    }
159
-
160
-    public function offsetGet($offset)
161
-    {
162
-        return $this->__get($offset);
163
-    }
164
-
165
-    public function offsetSet($offset, $value)
166
-    {
167
-        //not implemented
168
-    }
169
-
170
-    public function offsetUnset($offset)
171
-    {
172
-        //not implemented
173
-    }
22
+	const SUCCESS = 'success';
23
+	const INFO = 'info';
24
+	const WARNING = 'warning';
25
+	const DANGER = 'danger';
26
+
27
+	/**
28
+	 * @var Flash
29
+	 */
30
+	private static $instance;
31
+	private $usedOnce = false;
32
+
33
+	/**
34
+	 * Flash a success message to user
35
+	 *
36
+	 * @param string $message
37
+	 * @param string $header
38
+	 *
39
+	 * @return Flash
40
+	 */
41
+	public static function success($message, $header = '')
42
+	{
43
+		return static::message($message, $header, Flash::SUCCESS);
44
+	}
45
+
46
+	/**
47
+	 * Flash a info message to user
48
+	 *
49
+	 * @param string $message
50
+	 * @param string $header
51
+	 *
52
+	 * @return Flash
53
+	 */
54
+	public static function info($message, $header = '')
55
+	{
56
+		return static::message($message, $header, Flash::INFO);
57
+	}
58
+
59
+	/**
60
+	 * Flash a warning message to user
61
+	 *
62
+	 * @param string $message
63
+	 * @param string $header
64
+	 *
65
+	 * @return Flash
66
+	 */
67
+	public static function warning($message, $header = '')
68
+	{
69
+		return static::message($message, $header, Flash::WARNING);
70
+	}
71
+
72
+	/**
73
+	 * Flash a error message to user
74
+	 *
75
+	 * @param string $message
76
+	 * @param string $header
77
+	 *
78
+	 * @return Flash
79
+	 */
80
+	public static function danger($message, $header = '')
81
+	{
82
+		return static::message($message, $header, Flash::DANGER);
83
+	}
84
+
85
+	/**
86
+	 * Flash a message to user
87
+	 *
88
+	 * @param string $text message text
89
+	 * @param string $header
90
+	 * @param string $type
91
+	 *
92
+	 * @return Flash
93
+	 */
94
+	public static function message($text, $header = '', $type = Flash::WARNING)
95
+	{
96
+		return static::set(array('message' => $text, 'header' => $header, 'type' => $type));
97
+	}
98
+
99
+	/**
100
+	 * Set some data for one time use
101
+	 *
102
+	 * @param array $data array of key value pairs {@type associative}
103
+	 *
104
+	 * @return Flash
105
+	 */
106
+	public static function set(array $data)
107
+	{
108
+		if (!static::$instance) {
109
+			static::$instance = new Flash();
110
+		}
111
+		if (!isset($_SESSION['flash'])) {
112
+			$_SESSION['flash'] = array();
113
+		}
114
+		$_SESSION['flash'] += $data;
115
+		HtmlFormat::$data['flash'] = static::$instance;
116
+
117
+		return static::$instance;
118
+	}
119
+
120
+	public function __get($name)
121
+	{
122
+		$this->usedOnce = true;
123
+
124
+		return Util::nestedValue($_SESSION, 'flash', $name);
125
+	}
126
+
127
+	public function __isset($name)
128
+	{
129
+		return !is_null(Util::nestedValue($_SESSION, 'flash', $name));
130
+	}
131
+
132
+	public function __destruct()
133
+	{
134
+		if ($this->usedOnce) {
135
+			unset($_SESSION['flash']);
136
+		}
137
+	}
138
+
139
+	/**
140
+	 * Specify data which should be serialized to JSON
141
+	 * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
142
+	 * @return mixed data which can be serialized by <b>json_encode</b>,
143
+	 * which is a value of any type other than a resource.
144
+	 */
145
+	public function jsonSerialize()
146
+	{
147
+		$this->usedOnce = true;
148
+
149
+		return isset($_SESSION['flash'])
150
+			? $_SESSION['flash']
151
+			: array();
152
+	}
153
+
154
+
155
+	public function offsetExists($offset)
156
+	{
157
+		return $this->__isset($offset);
158
+	}
159
+
160
+	public function offsetGet($offset)
161
+	{
162
+		return $this->__get($offset);
163
+	}
164
+
165
+	public function offsetSet($offset, $value)
166
+	{
167
+		//not implemented
168
+	}
169
+
170
+	public function offsetUnset($offset)
171
+	{
172
+		//not implemented
173
+	}
174 174
 }
175 175
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/iFilter.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -16,15 +16,15 @@
 block discarded – undo
16 16
  */
17 17
 interface iFilter
18 18
 {
19
-    /**
20
-     * Access verification method.
21
-     *
22
-     * API access will be denied when this method returns false
23
-     *
24
-     * @abstract
25
-     * @return boolean true when api access is allowed false otherwise
26
-     */
27
-    public function __isAllowed();
19
+	/**
20
+	 * Access verification method.
21
+	 *
22
+	 * API access will be denied when this method returns false
23
+	 *
24
+	 * @abstract
25
+	 * @return boolean true when api access is allowed false otherwise
26
+	 */
27
+	public function __isAllowed();
28 28
 
29 29
 }
30 30
 
Please login to merge, or discard this patch.
includes/restler/framework/Luracast/Restler/compatibility/iAuthenticate.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -6,5 +6,5 @@
 block discarded – undo
6 6
  */
7 7
 interface iAuthenticate
8 8
 {
9
-    public function __isAuthenticated();
9
+	public function __isAuthenticated();
10 10
 }
11 11
\ No newline at end of file
Please login to merge, or discard this patch.