Completed
Branch develop (2b264a)
by
unknown
24:37
created
htdocs/includes/restler/framework/Luracast/Restler/Data/ValidationInfo.php 2 patches
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -19,255 +19,255 @@
 block discarded – undo
19 19
  */
20 20
 class ValidationInfo implements iValueObject
21 21
 {
22
-    /**
23
-     * @var mixed given value for the parameter
24
-     */
25
-    public $value;
26
-    /**
27
-     * @var string proper name for given parameter
28
-     */
29
-    public $label;
30
-    /**
31
-     * @var string html element that can be used to represent the parameter for
32
-     *             input
33
-     */
34
-    public $field;
35
-    /**
36
-     * @var mixed default value for the parameter
37
-     */
38
-    public $default;
39
-    /**
40
-     * Name of the variable being validated
41
-     *
42
-     * @var string variable name
43
-     */
44
-    public $name;
22
+	/**
23
+	 * @var mixed given value for the parameter
24
+	 */
25
+	public $value;
26
+	/**
27
+	 * @var string proper name for given parameter
28
+	 */
29
+	public $label;
30
+	/**
31
+	 * @var string html element that can be used to represent the parameter for
32
+	 *             input
33
+	 */
34
+	public $field;
35
+	/**
36
+	 * @var mixed default value for the parameter
37
+	 */
38
+	public $default;
39
+	/**
40
+	 * Name of the variable being validated
41
+	 *
42
+	 * @var string variable name
43
+	 */
44
+	public $name;
45 45
 
46
-    /**
47
-     * @var bool is it required or not
48
-     */
49
-    public $required;
46
+	/**
47
+	 * @var bool is it required or not
48
+	 */
49
+	public $required;
50 50
 
51
-    /**
52
-     * @var string body or header or query where this parameter is coming from
53
-     * in the http request
54
-     */
55
-    public $from;
51
+	/**
52
+	 * @var string body or header or query where this parameter is coming from
53
+	 * in the http request
54
+	 */
55
+	public $from;
56 56
 
57
-    /**
58
-     * Data type of the variable being validated.
59
-     * It will be mostly string
60
-     *
61
-     * @var string|array multiple types are specified it will be of
62
-     *      type array otherwise it will be a string
63
-     */
64
-    public $type;
57
+	/**
58
+	 * Data type of the variable being validated.
59
+	 * It will be mostly string
60
+	 *
61
+	 * @var string|array multiple types are specified it will be of
62
+	 *      type array otherwise it will be a string
63
+	 */
64
+	public $type;
65 65
 
66
-    /**
67
-     * When the type is array, this field is used to define the type of the
68
-     * contents of the array
69
-     *
70
-     * @var string|null when all the items in an array are of certain type, we
71
-     * can set this property. It will be null if the items can be of any type
72
-     */
73
-    public $contentType;
66
+	/**
67
+	 * When the type is array, this field is used to define the type of the
68
+	 * contents of the array
69
+	 *
70
+	 * @var string|null when all the items in an array are of certain type, we
71
+	 * can set this property. It will be null if the items can be of any type
72
+	 */
73
+	public $contentType;
74 74
 
75
-    /**
76
-     * Should we attempt to fix the value?
77
-     * When set to false validation class should throw
78
-     * an exception or return false for the validate call.
79
-     * When set to true it will attempt to fix the value if possible
80
-     * or throw an exception or return false when it cant be fixed.
81
-     *
82
-     * @var boolean true or false
83
-     */
84
-    public $fix = false;
75
+	/**
76
+	 * Should we attempt to fix the value?
77
+	 * When set to false validation class should throw
78
+	 * an exception or return false for the validate call.
79
+	 * When set to true it will attempt to fix the value if possible
80
+	 * or throw an exception or return false when it cant be fixed.
81
+	 *
82
+	 * @var boolean true or false
83
+	 */
84
+	public $fix = false;
85 85
 
86
-    /**
87
-     * @var array of children to be validated
88
-     */
89
-    public $children = null;
86
+	/**
87
+	 * @var array of children to be validated
88
+	 */
89
+	public $children = null;
90 90
 
91
-    // ==================================================================
92
-    //
93
-    // VALUE RANGE
94
-    //
95
-    // ------------------------------------------------------------------
96
-    /**
97
-     * Given value should match one of the values in the array
98
-     *
99
-     * @var array of choices to match to
100
-     */
101
-    public $choice;
102
-    /**
103
-     * If the type is string it will set the lower limit for length
104
-     * else will specify the lower limit for the value
105
-     *
106
-     * @var number minimum value
107
-     */
108
-    public $min;
109
-    /**
110
-     * If the type is string it will set the upper limit limit for length
111
-     * else will specify the upper limit for the value
112
-     *
113
-     * @var number maximum value
114
-     */
115
-    public $max;
91
+	// ==================================================================
92
+	//
93
+	// VALUE RANGE
94
+	//
95
+	// ------------------------------------------------------------------
96
+	/**
97
+	 * Given value should match one of the values in the array
98
+	 *
99
+	 * @var array of choices to match to
100
+	 */
101
+	public $choice;
102
+	/**
103
+	 * If the type is string it will set the lower limit for length
104
+	 * else will specify the lower limit for the value
105
+	 *
106
+	 * @var number minimum value
107
+	 */
108
+	public $min;
109
+	/**
110
+	 * If the type is string it will set the upper limit limit for length
111
+	 * else will specify the upper limit for the value
112
+	 *
113
+	 * @var number maximum value
114
+	 */
115
+	public $max;
116 116
 
117
-    // ==================================================================
118
-    //
119
-    // REGEX VALIDATION
120
-    //
121
-    // ------------------------------------------------------------------
122
-    /**
123
-     * RegEx pattern to match the value
124
-     *
125
-     * @var string regular expression
126
-     */
127
-    public $pattern;
117
+	// ==================================================================
118
+	//
119
+	// REGEX VALIDATION
120
+	//
121
+	// ------------------------------------------------------------------
122
+	/**
123
+	 * RegEx pattern to match the value
124
+	 *
125
+	 * @var string regular expression
126
+	 */
127
+	public $pattern;
128 128
 
129
-    // ==================================================================
130
-    //
131
-    // CUSTOM VALIDATION
132
-    //
133
-    // ------------------------------------------------------------------
134
-    /**
135
-     * Rules specified for the parameter in the php doc comment.
136
-     * It is passed to the validation method as the second parameter
137
-     *
138
-     * @var array custom rule set
139
-     */
140
-    public $rules;
129
+	// ==================================================================
130
+	//
131
+	// CUSTOM VALIDATION
132
+	//
133
+	// ------------------------------------------------------------------
134
+	/**
135
+	 * Rules specified for the parameter in the php doc comment.
136
+	 * It is passed to the validation method as the second parameter
137
+	 *
138
+	 * @var array custom rule set
139
+	 */
140
+	public $rules;
141 141
 
142
-    /**
143
-     * Specifying a custom error message will override the standard error
144
-     * message return by the validator class
145
-     *
146
-     * @var string custom error response
147
-     */
148
-    public $message;
142
+	/**
143
+	 * Specifying a custom error message will override the standard error
144
+	 * message return by the validator class
145
+	 *
146
+	 * @var string custom error response
147
+	 */
148
+	public $message;
149 149
 
150
-    // ==================================================================
151
-    //
152
-    // METHODS
153
-    //
154
-    // ------------------------------------------------------------------
150
+	// ==================================================================
151
+	//
152
+	// METHODS
153
+	//
154
+	// ------------------------------------------------------------------
155 155
 
156
-    /**
157
-     * Name of the method to be used for validation.
158
-     * It will be receiving two parameters $input, $rules (array)
159
-     *
160
-     * @var string validation method name
161
-     */
162
-    public $method;
156
+	/**
157
+	 * Name of the method to be used for validation.
158
+	 * It will be receiving two parameters $input, $rules (array)
159
+	 *
160
+	 * @var string validation method name
161
+	 */
162
+	public $method;
163 163
 
164
-    /**
165
-     * Instance of the API class currently being called. It will be null most of
166
-     * the time. Only when method is defined it will contain an instance.
167
-     * This behavior is for lazy loading of the API class
168
-     *
169
-     * @var null|object will be null or api class instance
170
-     */
171
-    public $apiClassInstance = null;
164
+	/**
165
+	 * Instance of the API class currently being called. It will be null most of
166
+	 * the time. Only when method is defined it will contain an instance.
167
+	 * This behavior is for lazy loading of the API class
168
+	 *
169
+	 * @var null|object will be null or api class instance
170
+	 */
171
+	public $apiClassInstance = null;
172 172
 
173
-    public static function numericValue($value)
174
-    {
175
-        return ( int )$value == $value
176
-            ? ( int )$value
177
-            : floatval($value);
178
-    }
173
+	public static function numericValue($value)
174
+	{
175
+		return ( int )$value == $value
176
+			? ( int )$value
177
+			: floatval($value);
178
+	}
179 179
 
180
-    public static function arrayValue($value)
181
-    {
182
-        return is_array($value) ? $value : array(
183
-            $value
184
-        );
185
-    }
180
+	public static function arrayValue($value)
181
+	{
182
+		return is_array($value) ? $value : array(
183
+			$value
184
+		);
185
+	}
186 186
 
187
-    public static function stringValue($value, $glue = ',')
188
-    {
189
-        return is_array($value)
190
-            ? implode($glue, $value)
191
-            : ( string )$value;
192
-    }
187
+	public static function stringValue($value, $glue = ',')
188
+	{
189
+		return is_array($value)
190
+			? implode($glue, $value)
191
+			: ( string )$value;
192
+	}
193 193
 
194
-    public static function booleanValue($value)
195
-    {
196
-        return is_bool($value)
197
-            ? $value
198
-            : $value !== 'false';
199
-    }
194
+	public static function booleanValue($value)
195
+	{
196
+		return is_bool($value)
197
+			? $value
198
+			: $value !== 'false';
199
+	}
200 200
 
201
-    public static function filterArray(array $data, $keepNumericKeys)
202
-    {
203
-        $r = array();
204
-        foreach ($data as $key => $value) {
205
-            if (is_numeric($key)) {
206
-                if ($keepNumericKeys) {
207
-                    $r[$key] = $value;
208
-                }
209
-            } elseif (!$keepNumericKeys) {
210
-                $r[$key] = $value;
211
-            }
212
-        }
213
-        return $r;
214
-    }
201
+	public static function filterArray(array $data, $keepNumericKeys)
202
+	{
203
+		$r = array();
204
+		foreach ($data as $key => $value) {
205
+			if (is_numeric($key)) {
206
+				if ($keepNumericKeys) {
207
+					$r[$key] = $value;
208
+				}
209
+			} elseif (!$keepNumericKeys) {
210
+				$r[$key] = $value;
211
+			}
212
+		}
213
+		return $r;
214
+	}
215 215
 
216
-    public function __toString()
217
-    {
218
-        return ' new ValidationInfo() ';
219
-    }
216
+	public function __toString()
217
+	{
218
+		return ' new ValidationInfo() ';
219
+	}
220 220
 
221
-    private function getProperty(array &$from, $property)
222
-    {
223
-        $p = Util::nestedValue($from, $property);
224
-        unset($from[$property]);
225
-        $p2 = Util::nestedValue(
226
-            $from, CommentParser::$embeddedDataName, $property
227
-        );
228
-        unset($from[CommentParser::$embeddedDataName][$property]);
221
+	private function getProperty(array &$from, $property)
222
+	{
223
+		$p = Util::nestedValue($from, $property);
224
+		unset($from[$property]);
225
+		$p2 = Util::nestedValue(
226
+			$from, CommentParser::$embeddedDataName, $property
227
+		);
228
+		unset($from[CommentParser::$embeddedDataName][$property]);
229 229
 
230
-        if ($property == 'type' && $p == 'array' && $p2) {
231
-            $this->contentType = $p2;
232
-            return $p;
233
-        }
234
-        $r = is_null($p2) ? (is_null($p) ? null : $p) : $p2;
235
-        if (!is_null($r)) {
236
-            if ($property == 'min' || $property == 'max') {
237
-                return static::numericValue($r);
238
-            } elseif ($property == 'required' || $property == 'fix') {
239
-                return static::booleanValue($r);
240
-            } elseif ($property == 'choice') {
241
-                return static::arrayValue($r);
242
-            } elseif ($property == 'pattern') {
243
-                return static::stringValue($r);
244
-            }
245
-        }
246
-        return $r;
247
-    }
230
+		if ($property == 'type' && $p == 'array' && $p2) {
231
+			$this->contentType = $p2;
232
+			return $p;
233
+		}
234
+		$r = is_null($p2) ? (is_null($p) ? null : $p) : $p2;
235
+		if (!is_null($r)) {
236
+			if ($property == 'min' || $property == 'max') {
237
+				return static::numericValue($r);
238
+			} elseif ($property == 'required' || $property == 'fix') {
239
+				return static::booleanValue($r);
240
+			} elseif ($property == 'choice') {
241
+				return static::arrayValue($r);
242
+			} elseif ($property == 'pattern') {
243
+				return static::stringValue($r);
244
+			}
245
+		}
246
+		return $r;
247
+	}
248 248
 
249
-    public function __construct(array $info)
250
-    {
251
-        $properties = get_object_vars($this);
252
-        unset($properties['contentType']);
253
-        foreach ($properties as $property => $value) {
254
-            $this->{$property} = $this->getProperty($info, $property);
255
-        }
256
-        $inner = Util::nestedValue($info, 'properties');
257
-        $this->rules = !empty($inner) ? $inner + $info : $info;
258
-        unset($this->rules['properties']);
259
-        if (is_string($this->type) && $this->type == 'integer') {
260
-            $this->type = 'int';
261
-        }
262
-    }
249
+	public function __construct(array $info)
250
+	{
251
+		$properties = get_object_vars($this);
252
+		unset($properties['contentType']);
253
+		foreach ($properties as $property => $value) {
254
+			$this->{$property} = $this->getProperty($info, $property);
255
+		}
256
+		$inner = Util::nestedValue($info, 'properties');
257
+		$this->rules = !empty($inner) ? $inner + $info : $info;
258
+		unset($this->rules['properties']);
259
+		if (is_string($this->type) && $this->type == 'integer') {
260
+			$this->type = 'int';
261
+		}
262
+	}
263 263
 
264
-    /**
265
-     * Magic Method used for creating instance at run time
266
-     */
267
-    public static function __set_state(array $info)
268
-    {
269
-        $o = new self ($info);
270
-        return $o;
271
-    }
264
+	/**
265
+	 * Magic Method used for creating instance at run time
266
+	 */
267
+	public static function __set_state(array $info)
268
+	{
269
+		$o = new self ($info);
270
+		return $o;
271
+	}
272 272
 }
273 273
 
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -172,8 +172,8 @@  discard block
 block discarded – undo
172 172
 
173 173
     public static function numericValue($value)
174 174
     {
175
-        return ( int )$value == $value
176
-            ? ( int )$value
175
+        return (int) $value == $value
176
+            ? (int) $value
177 177
             : floatval($value);
178 178
     }
179 179
 
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
     {
189 189
         return is_array($value)
190 190
             ? implode($glue, $value)
191
-            : ( string )$value;
191
+            : (string) $value;
192 192
     }
193 193
 
194 194
     public static function booleanValue($value)
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
      */
267 267
     public static function __set_state(array $info)
268 268
     {
269
-        $o = new self ($info);
269
+        $o = new self($info);
270 270
         return $o;
271 271
     }
272 272
 }
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Compose.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -15,58 +15,58 @@
 block discarded – undo
15 15
  */
16 16
 class Compose implements iCompose
17 17
 {
18
-    /**
19
-     * @var bool When restler is not running in production mode, this value will
20
-     * be checked to include the debug information on error response
21
-     */
22
-    public static $includeDebugInfo = true;
23
-    /**
24
-     * Current Restler instance
25
-     * Injected at runtime
26
-     *
27
-     * @var Restler
28
-     */
29
-    public $restler;
18
+	/**
19
+	 * @var bool When restler is not running in production mode, this value will
20
+	 * be checked to include the debug information on error response
21
+	 */
22
+	public static $includeDebugInfo = true;
23
+	/**
24
+	 * Current Restler instance
25
+	 * Injected at runtime
26
+	 *
27
+	 * @var Restler
28
+	 */
29
+	public $restler;
30 30
 
31
-    /**
32
-     * Result of an api call is passed to this method
33
-     * to create a standard structure for the data
34
-     *
35
-     * @param mixed $result can be a primitive or array or object
36
-     *
37
-     * @return mixed
38
-     */
39
-    public function response($result)
40
-    {
41
-        //TODO: check Defaults::language and change result accordingly
42
-        return $result;
43
-    }
31
+	/**
32
+	 * Result of an api call is passed to this method
33
+	 * to create a standard structure for the data
34
+	 *
35
+	 * @param mixed $result can be a primitive or array or object
36
+	 *
37
+	 * @return mixed
38
+	 */
39
+	public function response($result)
40
+	{
41
+		//TODO: check Defaults::language and change result accordingly
42
+		return $result;
43
+	}
44 44
 
45
-    /**
46
-     * When the api call results in RestException this method
47
-     * will be called to return the error message
48
-     *
49
-     * @param RestException $exception exception that has reasons for failure
50
-     *
51
-     * @return array
52
-     */
53
-    public function message(RestException $exception)
54
-    {
55
-        //TODO: check Defaults::language and change result accordingly
56
-        $r = array(
57
-            'error' => array(
58
-                    'code' => $exception->getCode(),
59
-                    'message' => $exception->getErrorMessage(),
60
-                ) + $exception->getDetails()
61
-        );
62
-        if (!Scope::get('Restler')->getProductionMode() && self::$includeDebugInfo) {
63
-            $r += array(
64
-                'debug' => array(
65
-                    'source' => $exception->getSource(),
66
-                    'stages' => $exception->getStages(),
67
-                )
68
-            );
69
-        }
70
-        return $r;
71
-    }
45
+	/**
46
+	 * When the api call results in RestException this method
47
+	 * will be called to return the error message
48
+	 *
49
+	 * @param RestException $exception exception that has reasons for failure
50
+	 *
51
+	 * @return array
52
+	 */
53
+	public function message(RestException $exception)
54
+	{
55
+		//TODO: check Defaults::language and change result accordingly
56
+		$r = array(
57
+			'error' => array(
58
+					'code' => $exception->getCode(),
59
+					'message' => $exception->getErrorMessage(),
60
+				) + $exception->getDetails()
61
+		);
62
+		if (!Scope::get('Restler')->getProductionMode() && self::$includeDebugInfo) {
63
+			$r += array(
64
+				'debug' => array(
65
+					'source' => $exception->getSource(),
66
+					'stages' => $exception->getStages(),
67
+				)
68
+			);
69
+		}
70
+		return $r;
71
+	}
72 72
 }
73 73
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Resources.php 3 patches
Indentation   +984 added lines, -984 removed lines patch added patch discarded remove patch
@@ -19,988 +19,988 @@
 block discarded – undo
19 19
  */
20 20
 class Resources implements iUseAuthentication, iProvideMultiVersionApi
21 21
 {
22
-    /**
23
-     * @var bool should protected resources be shown to unauthenticated users?
24
-     */
25
-    public static $hideProtected = true;
26
-    /**
27
-     * @var bool should we use format as extension?
28
-     */
29
-    public static $useFormatAsExtension = true;
30
-    /**
31
-     * @var bool should we include newer apis in the list? works only when
32
-     * Defaults::$useUrlBasedVersioning is set to true;
33
-     */
34
-    public static $listHigherVersions = true;
35
-    /**
36
-     * @var array all http methods specified here will be excluded from
37
-     * documentation
38
-     */
39
-    public static $excludedHttpMethods = array('OPTIONS');
40
-    /**
41
-     * @var array all paths beginning with any of the following will be excluded
42
-     * from documentation
43
-     */
44
-    public static $excludedPaths = array();
45
-    /**
46
-     * @var bool
47
-     */
48
-    public static $placeFormatExtensionBeforeDynamicParts = true;
49
-    /**
50
-     * @var bool should we group all the operations with the same url or not
51
-     */
52
-    public static $groupOperations = false;
53
-    /**
54
-     * @var null|callable if the api methods are under access control mechanism
55
-     * you can attach a function here that returns true or false to determine
56
-     * visibility of a protected api method. this function will receive method
57
-     * info as the only parameter.
58
-     */
59
-    public static $accessControlFunction = null;
60
-    /**
61
-     * @var array type mapping for converting data types to javascript / swagger
62
-     */
63
-    public static $dataTypeAlias = array(
64
-        'string' => 'string',
65
-        'int' => 'int',
66
-        'number' => 'float',
67
-        'float' => 'float',
68
-        'bool' => 'boolean',
69
-        'boolean' => 'boolean',
70
-        'NULL' => 'null',
71
-        'array' => 'Array',
72
-        'object' => 'Object',
73
-        'stdClass' => 'Object',
74
-        'mixed' => 'string',
75
-        'DateTime' => 'Date'
76
-    );
77
-    /**
78
-     * @var array configurable symbols to differentiate public, hybrid and
79
-     * protected api
80
-     */
81
-    public static $apiDescriptionSuffixSymbols = array(
82
-        0 => '&nbsp; <i class="icon-unlock-alt icon-large"></i>', //public api
83
-        1 => '&nbsp; <i class="icon-adjust icon-large"></i>', //hybrid api
84
-        2 => '&nbsp; <i class="icon-lock icon-large"></i>', //protected api
85
-    );
86
-
87
-    /**
88
-     * Injected at runtime
89
-     *
90
-     * @var Restler instance of restler
91
-     */
92
-    public $restler;
93
-    /**
94
-     * @var string when format is not used as the extension this property is
95
-     * used to set the extension manually
96
-     */
97
-    public $formatString = '';
98
-    protected $_models;
99
-    protected $_bodyParam;
100
-    /**
101
-     * @var bool|stdClass
102
-     */
103
-    protected $_fullDataRequested = false;
104
-    protected $crud = array(
105
-        'POST' => 'create',
106
-        'GET' => 'retrieve',
107
-        'PUT' => 'update',
108
-        'DELETE' => 'delete',
109
-        'PATCH' => 'partial update'
110
-    );
111
-    protected static $prefixes = array(
112
-        'get' => 'retrieve',
113
-        'index' => 'list',
114
-        'post' => 'create',
115
-        'put' => 'update',
116
-        'patch' => 'modify',
117
-        'delete' => 'remove',
118
-    );
119
-    protected $_authenticated = false;
120
-    protected $cacheName = '';
121
-
122
-    public function __construct()
123
-    {
124
-        if (static::$useFormatAsExtension) {
125
-            $this->formatString = '.{format}';
126
-        }
127
-    }
128
-
129
-    /**
130
-     * This method will be called first for filter classes and api classes so
131
-     * that they can respond accordingly for filer method call and api method
132
-     * calls
133
-     *
134
-     *
135
-     * @param bool $isAuthenticated passes true when the authentication is
136
-     *                              done, false otherwise
137
-     *
138
-     * @return mixed
139
-     */
140
-    public function __setAuthenticationStatus($isAuthenticated = false)
141
-    {
142
-        $this->_authenticated = $isAuthenticated;
143
-    }
144
-
145
-    /**
146
-     * pre call for get($id)
147
-     *
148
-     * if cache is present, use cache
149
-     */
150
-    public function _pre_get_json($id)
151
-    {
152
-        $userClass = Defaults::$userIdentifierClass;
153
-        $this->cacheName = $userClass::getCacheIdentifier() . '_resources_' . $id;
154
-        if ($this->restler->getProductionMode()
155
-            && !$this->restler->refreshCache
156
-            && $this->restler->cache->isCached($this->cacheName)
157
-        ) {
158
-            //by pass call, compose, postCall stages and directly send response
159
-            $this->restler->composeHeaders();
160
-            die($this->restler->cache->get($this->cacheName));
161
-        }
162
-    }
163
-
164
-    /**
165
-     * post call for get($id)
166
-     *
167
-     * create cache if in production mode
168
-     *
169
-     * @param $responseData
170
-     *
171
-     * @internal param string $data composed json output
172
-     *
173
-     * @return string
174
-     */
175
-    public function _post_get_json($responseData)
176
-    {
177
-        if ($this->restler->getProductionMode()) {
178
-            $this->restler->cache->set($this->cacheName, $responseData);
179
-        }
180
-        return $responseData;
181
-    }
182
-
183
-    /**
184
-     * @access hybrid
185
-     *
186
-     * @param string $id
187
-     *
188
-     * @throws RestException
189
-     * @return null|stdClass
190
-     *
191
-     * @url    GET {id}
192
-     */
193
-    public function get($id = '')
194
-    {
195
-        $version = $this->restler->getRequestedApiVersion();
196
-        if (empty($id)) {
197
-            //do nothing
198
-        } elseif (false !== ($pos = strpos($id, '-v'))) {
199
-            //$version = intval(substr($id, $pos + 2));
200
-            $id = substr($id, 0, $pos);
201
-        } elseif ($id[0] == 'v' && is_numeric($v = substr($id, 1))) {
202
-            $id = '';
203
-            //$version = $v;
204
-        } elseif ($id == 'root' || $id == 'index') {
205
-            $id = '';
206
-        }
207
-        $this->_models = new stdClass();
208
-        $r = null;
209
-        $count = 0;
210
-
211
-        $tSlash = !empty($id);
212
-        $target = empty($id) ? '' : $id;
213
-        $tLen = strlen($target);
214
-
215
-        $filter = array();
216
-
217
-        $routes
218
-            = Util::nestedValue(Routes::toArray(), "v$version")
219
-            ? : array();
220
-
221
-        $prefix = Defaults::$useUrlBasedVersioning ? "/v$version" : '';
222
-
223
-        foreach ($routes as $value) {
224
-            foreach ($value as $httpMethod => $route) {
225
-                if (in_array($httpMethod, static::$excludedHttpMethods)) {
226
-                    continue;
227
-                }
228
-                $fullPath = $route['url'];
229
-                if ($fullPath !== $target && !Text::beginsWith($fullPath, $target)) {
230
-                    continue;
231
-                }
232
-                $fLen = strlen($fullPath);
233
-                if ($tSlash) {
234
-                    if ($fLen != $tLen && !Text::beginsWith($fullPath, $target . '/'))
235
-                        continue;
236
-                } elseif ($fLen > $tLen + 1 && $fullPath[$tLen + 1] != '{' && !Text::beginsWith($fullPath, '{')) {
237
-                    //when mapped to root exclude paths that have static parts
238
-                    //they are listed else where under that static part name
239
-                    continue;
240
-                }
241
-
242
-                if (!static::verifyAccess($route)) {
243
-                    continue;
244
-                }
245
-                foreach (static::$excludedPaths as $exclude) {
246
-                    if (empty($exclude)) {
247
-                        if ($fullPath == $exclude)
248
-                            continue 2;
249
-                    } elseif (Text::beginsWith($fullPath, $exclude)) {
250
-                        continue 2;
251
-                    }
252
-                }
253
-                $m = $route['metadata'];
254
-                if ($id == '' && $m['resourcePath'] != '') {
255
-                    continue;
256
-                }
257
-                if (isset($filter[$httpMethod][$fullPath])) {
258
-                    continue;
259
-                }
260
-                $filter[$httpMethod][$fullPath] = true;
261
-                // reset body params
262
-                $this->_bodyParam = array(
263
-                    'required' => false,
264
-                    'description' => array()
265
-                );
266
-                $count++;
267
-                $className = $this->_noNamespace($route['className']);
268
-                if (!$r) {
269
-                    $resourcePath = '/'
270
-                        . trim($m['resourcePath'], '/');
271
-                    $r = $this->_operationListing($resourcePath);
272
-                }
273
-                $parts = explode('/', $fullPath);
274
-                $pos = count($parts) - 1;
275
-                if (count($parts) == 1 && $httpMethod == 'GET') {
276
-                } else {
277
-                    for ($i = 0; $i < count($parts); $i++) {
278
-                        if (strlen($parts[$i]) && $parts[$i][0] == '{') {
279
-                            $pos = $i - 1;
280
-                            break;
281
-                        }
282
-                    }
283
-                }
284
-                $nickname = $this->_nickname($route);
285
-                $index = static::$placeFormatExtensionBeforeDynamicParts && $pos > 0 ? $pos : 0;
286
-                if (!empty($parts[$index]))
287
-                    $parts[$index] .= $this->formatString;
288
-
289
-                $fullPath = implode('/', $parts);
290
-                $description = isset(
291
-                $m['classDescription'])
292
-                    ? $m['classDescription']
293
-                    : $className . ' API';
294
-                if (empty($m['description'])) {
295
-                    $m['description'] = $this->restler->getProductionMode()
296
-                        ? ''
297
-                        : 'routes to <mark>'
298
-                        . $route['className']
299
-                        . '::'
300
-                        . $route['methodName'] . '();</mark>';
301
-                }
302
-                if (empty($m['longDescription'])) {
303
-                    $m['longDescription'] = $this->restler->getProductionMode()
304
-                        ? ''
305
-                        : 'Add PHPDoc long description to '
306
-                        . "<mark>$className::"
307
-                        . $route['methodName'] . '();</mark>'
308
-                        . '  (the api method) to write here';
309
-                }
310
-                $operation = $this->_operation(
311
-                    $route,
312
-                    $nickname,
313
-                    $httpMethod,
314
-                    $m['description'],
315
-                    $m['longDescription']
316
-                );
317
-                if (isset($m['throws'])) {
318
-                    foreach ($m['throws'] as $exception) {
319
-                        $operation->errorResponses[] = array(
320
-                            'reason' => $exception['message'],
321
-                            'code' => $exception['code']);
322
-                    }
323
-                }
324
-                if (isset($m['param'])) {
325
-                    foreach ($m['param'] as $param) {
326
-                        //combine body params as one
327
-                        $p = $this->_parameter($param);
328
-                        if ($p->paramType == 'body') {
329
-                            $this->_appendToBody($p);
330
-                        } else {
331
-                            $operation->parameters[] = $p;
332
-                        }
333
-                    }
334
-                }
335
-                if (
336
-                    count($this->_bodyParam['description']) ||
337
-                    (
338
-                        $this->_fullDataRequested &&
339
-                        $httpMethod != 'GET' &&
340
-                        $httpMethod != 'DELETE'
341
-                    )
342
-                ) {
343
-                    $operation->parameters[] = $this->_getBody();
344
-                }
345
-                if (isset($m['return']['type'])) {
346
-                    $responseClass = $m['return']['type'];
347
-                    if (is_string($responseClass)) {
348
-                        if (class_exists($responseClass)) {
349
-                            $this->_model($responseClass);
350
-                            $operation->responseClass
351
-                                = $this->_noNamespace($responseClass);
352
-                        } elseif (strtolower($responseClass) == 'array') {
353
-                            $operation->responseClass = 'Array';
354
-                            $rt = $m['return'];
355
-                            if (isset(
356
-                            $rt[CommentParser::$embeddedDataName]['type'])
357
-                            ) {
358
-                                $rt = $rt[CommentParser::$embeddedDataName]
359
-                                ['type'];
360
-                                if (class_exists($rt)) {
361
-                                    $this->_model($rt);
362
-                                    $operation->responseClass .= '[' .
363
-                                        $this->_noNamespace($rt) . ']';
364
-                                }
365
-                            }
366
-                        }
367
-                    }
368
-                }
369
-                $api = false;
370
-
371
-                if (static::$groupOperations) {
372
-                    foreach ($r->apis as $a) {
373
-                        if ($a->path == "$prefix/$fullPath") {
374
-                            $api = $a;
375
-                            break;
376
-                        }
377
-                    }
378
-                }
379
-
380
-                if (!$api) {
381
-                    $api = $this->_api("$prefix/$fullPath", $description);
382
-                    $r->apis[] = $api;
383
-                }
384
-
385
-                $api->operations[] = $operation;
386
-            }
387
-        }
388
-        if (!$count) {
389
-            throw new RestException(404);
390
-        }
391
-        if (!is_null($r))
392
-            $r->models = $this->_models;
393
-        usort(
394
-            $r->apis,
395
-            function ($a, $b) {
396
-                $order = array(
397
-                    'GET' => 1,
398
-                    'POST' => 2,
399
-                    'PUT' => 3,
400
-                    'PATCH' => 4,
401
-                    'DELETE' => 5
402
-                );
403
-                return
404
-                    $a->operations[0]->httpMethod ==
405
-                    $b->operations[0]->httpMethod
406
-                        ? $a->path > $b->path
407
-                        : $order[$a->operations[0]->httpMethod] >
408
-                        $order[$b->operations[0]->httpMethod];
409
-
410
-            }
411
-        );
412
-        return $r;
413
-    }
414
-
415
-    protected function _nickname(array $route)
416
-    {
417
-        static $hash = array();
418
-        $method = $route['methodName'];
419
-        if (isset(static::$prefixes[$method])) {
420
-            $method = static::$prefixes[$method];
421
-        } else {
422
-            $method = str_replace(
423
-                array_keys(static::$prefixes),
424
-                array_values(static::$prefixes),
425
-                $method
426
-            );
427
-        }
428
-        while (isset($hash[$method]) && $route['url'] != $hash[$method]) {
429
-            //create another one
430
-            $method .= '_';
431
-        }
432
-        $hash[$method] = $route['url'];
433
-        return $method;
434
-    }
435
-
436
-    protected function _noNamespace($className)
437
-    {
438
-        $className = explode('\\', $className);
439
-        return end($className);
440
-    }
441
-
442
-    protected function _operationListing($resourcePath = '/')
443
-    {
444
-        $r = $this->_resourceListing();
445
-        $r->resourcePath = $resourcePath;
446
-        $r->models = new stdClass();
447
-        return $r;
448
-    }
449
-
450
-    protected function _resourceListing()
451
-    {
452
-        $r = new stdClass();
453
-        $r->apiVersion = (string)$this->restler->_requestedApiVersion;
454
-        $r->swaggerVersion = "1.1";
455
-        $r->basePath = $this->restler->getBaseUrl();
456
-        $r->produces = $this->restler->getWritableMimeTypes();
457
-        $r->consumes = $this->restler->getReadableMimeTypes();
458
-        $r->apis = array();
459
-        return $r;
460
-    }
461
-
462
-    protected function _api($path, $description = '')
463
-    {
464
-        $r = new stdClass();
465
-        $r->path = $path;
466
-        $r->description =
467
-            empty($description) && $this->restler->getProductionMode()
468
-                ? 'Use PHPDoc comment to describe here'
469
-                : $description;
470
-        $r->operations = array();
471
-        return $r;
472
-    }
473
-
474
-    protected function _operation(
475
-        $route,
476
-        $nickname,
477
-        $httpMethod = 'GET',
478
-        $summary = 'description',
479
-        $notes = 'long description',
480
-        $responseClass = 'void'
481
-    )
482
-    {
483
-        //reset body params
484
-        $this->_bodyParam = array(
485
-            'required' => false,
486
-            'description' => array()
487
-        );
488
-
489
-        $r = new stdClass();
490
-        $r->httpMethod = $httpMethod;
491
-        $r->nickname = $nickname;
492
-        $r->responseClass = $responseClass;
493
-
494
-        $r->parameters = array();
495
-
496
-        $r->summary = $summary . ($route['accessLevel'] > 2
497
-                ? static::$apiDescriptionSuffixSymbols[2]
498
-                : static::$apiDescriptionSuffixSymbols[$route['accessLevel']]
499
-            );
500
-        $r->notes = $notes;
501
-
502
-        $r->errorResponses = array();
503
-        return $r;
504
-    }
505
-
506
-    protected function _parameter($param)
507
-    {
508
-        $r = new stdClass();
509
-        $r->name = $param['name'];
510
-        $r->description = !empty($param['description'])
511
-            ? $param['description'] . '.'
512
-            : ($this->restler->getProductionMode()
513
-                ? ''
514
-                : 'add <mark>@param {type} $' . $r->name
515
-                . ' {comment}</mark> to describe here');
516
-        //paramType can be path or query or body or header
517
-        $r->paramType = Util::nestedValue($param, CommentParser::$embeddedDataName, 'from') ? : 'query';
518
-        $r->required = isset($param['required']) && $param['required'];
519
-        if (isset($param['default'])) {
520
-            $r->defaultValue = $param['default'];
521
-        } elseif (isset($param[CommentParser::$embeddedDataName]['example'])) {
522
-            $r->defaultValue
523
-                = $param[CommentParser::$embeddedDataName]['example'];
524
-        }
525
-        $r->allowMultiple = false;
526
-        $type = 'string';
527
-        if (isset($param['type'])) {
528
-            $type = $param['type'];
529
-            if (is_array($type)) {
530
-                $type = array_shift($type);
531
-            }
532
-            if ($type == 'array') {
533
-                $contentType = Util::nestedValue(
534
-                    $param,
535
-                    CommentParser::$embeddedDataName,
536
-                    'type'
537
-                );
538
-                if ($contentType) {
539
-                    if ($contentType == 'indexed') {
540
-                        $type = 'Array';
541
-                    } elseif ($contentType == 'associative') {
542
-                        $type = 'Object';
543
-                    } else {
544
-                        $type = "Array[$contentType]";
545
-                    }
546
-                    if (Util::isObjectOrArray($contentType)) {
547
-                        $this->_model($contentType);
548
-                    }
549
-                } elseif (isset(static::$dataTypeAlias[$type])) {
550
-                    $type = static::$dataTypeAlias[$type];
551
-                }
552
-            } elseif (Util::isObjectOrArray($type)) {
553
-                $this->_model($type);
554
-            } elseif (isset(static::$dataTypeAlias[$type])) {
555
-                $type = static::$dataTypeAlias[$type];
556
-            }
557
-        }
558
-        $r->dataType = $type;
559
-        if (isset($param[CommentParser::$embeddedDataName])) {
560
-            $p = $param[CommentParser::$embeddedDataName];
561
-            if (isset($p['min']) && isset($p['max'])) {
562
-                $r->allowableValues = array(
563
-                    'valueType' => 'RANGE',
564
-                    'min' => $p['min'],
565
-                    'max' => $p['max'],
566
-                );
567
-            } elseif (isset($p['choice'])) {
568
-                $r->allowableValues = array(
569
-                    'valueType' => 'LIST',
570
-                    'values' => $p['choice']
571
-                );
572
-            }
573
-        }
574
-        return $r;
575
-    }
576
-
577
-    protected function _appendToBody($p)
578
-    {
579
-        if ($p->name === Defaults::$fullRequestDataName) {
580
-            $this->_fullDataRequested = $p;
581
-            unset($this->_bodyParam['names'][Defaults::$fullRequestDataName]);
582
-            return;
583
-        }
584
-        $this->_bodyParam['description'][$p->name]
585
-            = "$p->name"
586
-            . ' : <tag>' . $p->dataType . '</tag> '
587
-            . ($p->required ? ' <i>(required)</i> - ' : ' - ')
588
-            . $p->description;
589
-        $this->_bodyParam['required'] = $p->required
590
-            || $this->_bodyParam['required'];
591
-        $this->_bodyParam['names'][$p->name] = $p;
592
-    }
593
-
594
-    protected function _getBody()
595
-    {
596
-        $r = new stdClass();
597
-        $n = isset($this->_bodyParam['names'])
598
-            ? array_values($this->_bodyParam['names'])
599
-            : array();
600
-        if (count($n) == 1) {
601
-            if (isset($this->_models->{$n[0]->dataType})) {
602
-                // ============ custom class ===================
603
-                $r = $n[0];
604
-                $c = $this->_models->{$r->dataType};
605
-                $a = $c->properties;
606
-                $r->description = "Paste JSON data here";
607
-                if (count($a)) {
608
-                    $r->description .= " with the following"
609
-                        . (count($a) > 1 ? ' properties.' : ' property.');
610
-                    foreach ($a as $k => $v) {
611
-                        $r->description .= "<hr/>$k : <tag>"
612
-                            . $v['type'] . '</tag> '
613
-                            . (isset($v['required']) ? '(required)' : '')
614
-                            . ' - ' . $v['description'];
615
-                    }
616
-                }
617
-                $r->defaultValue = "{\n    \""
618
-                    . implode("\": \"\",\n    \"",
619
-                        array_keys($c->properties))
620
-                    . "\": \"\"\n}";
621
-                return $r;
622
-            } elseif (false !== ($p = strpos($n[0]->dataType, '['))) {
623
-                // ============ array of custom class ===============
624
-                $r = $n[0];
625
-                $t = substr($r->dataType, $p + 1, -1);
626
-                if ($c = Util::nestedValue($this->_models, $t)) {
627
-                    $a = $c->properties;
628
-                    $r->description = "Paste JSON data here";
629
-                    if (count($a)) {
630
-                        $r->description .= " with an array of objects with the following"
631
-                            . (count($a) > 1 ? ' properties.' : ' property.');
632
-                        foreach ($a as $k => $v) {
633
-                            $r->description .= "<hr/>$k : <tag>"
634
-                                . $v['type'] . '</tag> '
635
-                                . (isset($v['required']) ? '(required)' : '')
636
-                                . ' - ' . $v['description'];
637
-                        }
638
-                    }
639
-                    $r->defaultValue = "[\n    {\n        \""
640
-                        . implode("\": \"\",\n        \"",
641
-                            array_keys($c->properties))
642
-                        . "\": \"\"\n    }\n]";
643
-                    return $r;
644
-                } else {
645
-                    $r->description = "Paste JSON data here with an array of $t values.";
646
-                    $r->defaultValue = "[ ]";
647
-                    return $r;
648
-                }
649
-            } elseif ($n[0]->dataType == 'Array') {
650
-                // ============ array ===============================
651
-                $r = $n[0];
652
-                $r->description = "Paste JSON array data here"
653
-                    . ($r->required ? ' (required) . ' : '. ')
654
-                    . "<br/>$r->description";
655
-                $r->defaultValue = "[\n    {\n        \""
656
-                    . "property\" : \"\"\n    }\n]";
657
-                return $r;
658
-            } elseif ($n[0]->dataType == 'Object') {
659
-                // ============ object ==============================
660
-                $r = $n[0];
661
-                $r->description = "Paste JSON object data here"
662
-                    . ($r->required ? ' (required) . ' : '. ')
663
-                    . "<br/>$r->description";
664
-                $r->defaultValue = "{\n    \""
665
-                    . "property\" : \"\"\n}";
666
-                return $r;
667
-            }
668
-        }
669
-        $p = array_values($this->_bodyParam['description']);
670
-        $r->name = 'REQUEST_BODY';
671
-        $r->description = "Paste JSON data here";
672
-        if (count($p) == 0 && $this->_fullDataRequested) {
673
-            $r->required = $this->_fullDataRequested->required;
674
-            $r->defaultValue = "{\n    \"property\" : \"\"\n}";
675
-        } else {
676
-            $r->description .= " with the following"
677
-                . (count($p) > 1 ? ' properties.' : ' property.')
678
-                . '<hr/>'
679
-                . implode("<hr/>", $p);
680
-            $r->required = $this->_bodyParam['required'];
681
-            // Create default object that includes parameters to be submitted
682
-            $defaultObject = new \StdClass();
683
-            foreach ($this->_bodyParam['names'] as $name => $values) {
684
-                if (!$values->required)
685
-                    continue;
686
-                if (class_exists($values->dataType)) {
687
-                    $myClassName = $values->dataType;
688
-                    $defaultObject->$name = new $myClassName();
689
-                } else {
690
-                    $defaultObject->$name = '';
691
-                }
692
-            }
693
-            $r->defaultValue = Scope::get('JsonFormat')->encode($defaultObject, true);
694
-        }
695
-        $r->paramType = 'body';
696
-        $r->allowMultiple = false;
697
-        $r->dataType = 'Object';
698
-        return $r;
699
-    }
700
-
701
-    protected function _model($className, $instance = null)
702
-    {
703
-        $id = $this->_noNamespace($className);
704
-        if (isset($this->_models->{$id})) {
705
-            return;
706
-        }
707
-        $properties = array();
708
-        if (!$instance) {
709
-            if (!class_exists($className))
710
-                return;
711
-            $instance = new $className();
712
-        }
713
-        $data = get_object_vars($instance);
714
-        $reflectionClass = new \ReflectionClass($className);
715
-        foreach ($data as $key => $value) {
716
-
717
-            $propertyMetaData = null;
718
-
719
-            try {
720
-                $property = $reflectionClass->getProperty($key);
721
-                if ($c = $property->getDocComment()) {
722
-                    $propertyMetaData = Util::nestedValue(
723
-                        CommentParser::parse($c),
724
-                        'var'
725
-                    );
726
-                }
727
-            } catch (\ReflectionException $e) {
728
-            }
729
-
730
-            if (is_null($propertyMetaData)) {
731
-                $type = $this->getType($value, true);
732
-                $description = '';
733
-            } else {
734
-                $type = Util::nestedValue(
735
-                    $propertyMetaData,
736
-                    'type'
737
-                ) ? : $this->getType($value, true);
738
-                $description = Util::nestedValue(
739
-                    $propertyMetaData,
740
-                    'description'
741
-                ) ? : '';
742
-
743
-                if (class_exists($type)) {
744
-                    $this->_model($type);
745
-                    $type = $this->_noNamespace($type);
746
-                }
747
-            }
748
-
749
-            if (isset(static::$dataTypeAlias[$type])) {
750
-                $type = static::$dataTypeAlias[$type];
751
-            }
752
-            $properties[$key] = array(
753
-                'type' => $type,
754
-                'description' => $description
755
-            );
756
-            if (Util::nestedValue(
757
-                $propertyMetaData,
758
-                CommentParser::$embeddedDataName,
759
-                'required'
760
-            )
761
-            ) {
762
-                $properties[$key]['required'] = true;
763
-            }
764
-            if ($type == 'Array') {
765
-                $itemType = Util::nestedValue(
766
-                    $propertyMetaData,
767
-                    CommentParser::$embeddedDataName,
768
-                    'type'
769
-                ) ? :
770
-                    (count($value)
771
-                        ? $this->getType(end($value), true)
772
-                        : 'string');
773
-                if (class_exists($itemType)) {
774
-                    $this->_model($itemType);
775
-                    $itemType = $this->_noNamespace($itemType);
776
-                }
777
-                $properties[$key]['items'] = array(
778
-                    'type' => $itemType,
779
-                    /*'description' => '' */ //TODO: add description
780
-                );
781
-            } else if (preg_match('/^Array\[(.+)\]$/', $type, $matches)) {
782
-                $itemType = $matches[1];
783
-                $properties[$key]['type'] = 'Array';
784
-                $properties[$key]['items']['type'] = $this->_noNamespace($itemType);
785
-
786
-                if (class_exists($itemType)) {
787
-                    $this->_model($itemType);
788
-                }
789
-            }
790
-        }
791
-        if (!empty($properties)) {
792
-            $model = new stdClass();
793
-            $model->id = $id;
794
-            $model->properties = $properties;
795
-            $this->_models->{$id} = $model;
796
-        }
797
-    }
798
-
799
-    /**
800
-     * Find the data type of the given value.
801
-     *
802
-     *
803
-     * @param mixed $o given value for finding type
804
-     *
805
-     * @param bool $appendToModels if an object is found should we append to
806
-     *                              our models list?
807
-     *
808
-     * @return string
809
-     *
810
-     * @access private
811
-     */
812
-    public function getType($o, $appendToModels = false)
813
-    {
814
-        if (is_object($o)) {
815
-            $oc = get_class($o);
816
-            if ($appendToModels) {
817
-                $this->_model($oc, $o);
818
-            }
819
-            return $this->_noNamespace($oc);
820
-        }
821
-        if (is_array($o)) {
822
-            if (count($o)) {
823
-                $child = end($o);
824
-                if (Util::isObjectOrArray($child)) {
825
-                    $childType = $this->getType($child, $appendToModels);
826
-                    return "Array[$childType]";
827
-                }
828
-            }
829
-            return 'array';
830
-        }
831
-        if (is_bool($o)) return 'boolean';
832
-        if (is_numeric($o)) return is_float($o) ? 'float' : 'int';
833
-        return 'string';
834
-    }
835
-
836
-    /**
837
-     * pre call for index()
838
-     *
839
-     * if cache is present, use cache
840
-     */
841
-    public function _pre_index_json()
842
-    {
843
-        $userClass = Defaults::$userIdentifierClass;
844
-        $this->cacheName = $userClass::getCacheIdentifier()
845
-            . '_resources-v'
846
-            . $this->restler->_requestedApiVersion;
847
-        if ($this->restler->getProductionMode()
848
-            && !$this->restler->refreshCache
849
-            && $this->restler->cache->isCached($this->cacheName)
850
-        ) {
851
-            //by pass call, compose, postCall stages and directly send response
852
-            $this->restler->composeHeaders();
853
-            die($this->restler->cache->get($this->cacheName));
854
-        }
855
-    }
856
-
857
-    /**
858
-     * post call for index()
859
-     *
860
-     * create cache if in production mode
861
-     *
862
-     * @param $responseData
863
-     *
864
-     * @internal param string $data composed json output
865
-     *
866
-     * @return string
867
-     */
868
-    public function _post_index_json($responseData)
869
-    {
870
-        if ($this->restler->getProductionMode()) {
871
-            $this->restler->cache->set($this->cacheName, $responseData);
872
-        }
873
-        return $responseData;
874
-    }
875
-
876
-    /**
877
-     * @access hybrid
878
-     * @return \stdClass
879
-     */
880
-    public function index()
881
-    {
882
-        if (!static::$accessControlFunction && Defaults::$accessControlFunction)
883
-            static::$accessControlFunction = Defaults::$accessControlFunction;
884
-        $version = $this->restler->getRequestedApiVersion();
885
-        $allRoutes = Util::nestedValue(Routes::toArray(), "v$version");
886
-        $r = $this->_resourceListing();
887
-        $map = array();
888
-        if (isset($allRoutes['*'])) {
889
-            $this->_mapResources($allRoutes['*'], $map, $version);
890
-            unset($allRoutes['*']);
891
-        }
892
-        $this->_mapResources($allRoutes, $map, $version);
893
-        foreach ($map as $path => $description) {
894
-            if (!Text::contains($path, '{')) {
895
-                //add id
896
-                $r->apis[] = array(
897
-                    'path' => $path . $this->formatString,
898
-                    'description' => $description
899
-                );
900
-            }
901
-        }
902
-        if (Defaults::$useUrlBasedVersioning && static::$listHigherVersions) {
903
-            $nextVersion = $version + 1;
904
-            if ($nextVersion <= $this->restler->getApiVersion()) {
905
-                list($status, $data) = $this->_loadResource("/v$nextVersion/resources.json");
906
-                if ($status == 200) {
907
-                    $r->apis = array_merge($r->apis, $data->apis);
908
-                    $r->apiVersion = $data->apiVersion;
909
-                }
910
-            }
911
-
912
-        }
913
-        return $r;
914
-    }
915
-
916
-    protected function _loadResource($url)
917
-    {
918
-        $ch = curl_init($this->restler->getBaseUrl() . $url
919
-            . (empty($_GET) ? '' : '?' . http_build_query($_GET)));
920
-        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
921
-        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
922
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
923
-        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
924
-            'Accept:application/json',
925
-        ));
926
-        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);        
927
-        $result = json_decode(curl_exec($ch));
928
-        $http_status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
929
-        return array($http_status, $result);
930
-    }
931
-
932
-    protected function _mapResources(array $allRoutes, array &$map, $version = 1)
933
-    {
934
-        foreach ($allRoutes as $fullPath => $routes) {
935
-            $path = explode('/', $fullPath);
936
-            $resource = isset($path[0]) ? $path[0] : '';
937
-            if ($resource == 'resources' || Text::endsWith($resource, 'index'))
938
-                continue;
939
-            foreach ($routes as $httpMethod => $route) {
940
-                if (in_array($httpMethod, static::$excludedHttpMethods)) {
941
-                    continue;
942
-                }
943
-                if (!static::verifyAccess($route)) {
944
-                    continue;
945
-                }
946
-
947
-                foreach (static::$excludedPaths as $exclude) {
948
-                    if (empty($exclude)) {
949
-                        if ($fullPath == $exclude)
950
-                            continue 2;
951
-                    } elseif (Text::beginsWith($fullPath, $exclude)) {
952
-                        continue 2;
953
-                    }
954
-                }
955
-
956
-                $res = $resource
957
-                    ? ($version == 1 ? "/resources/$resource" : "/v$version/resources/$resource-v$version")
958
-                    : ($version == 1 ? "/resources/root" : "/v$version/resources/root-v$version");
959
-
960
-                if (empty($map[$res])) {
961
-                    $map[$res] = isset(
962
-                    $route['metadata']['classDescription'])
963
-                        ? $route['metadata']['classDescription'] : '';
964
-                }
965
-            }
966
-        }
967
-    }
968
-
969
-    /**
970
-     * Maximum api version supported by the api class
971
-     * @return int
972
-     */
973
-    public static function __getMaximumSupportedVersion()
974
-    {
975
-        return Scope::get('Restler')->getApiVersion();
976
-    }
977
-
978
-    /**
979
-     * Verifies that the requesting user is allowed to view the docs for this API
980
-     *
981
-     * @param $route
982
-     *
983
-     * @return boolean True if the user should be able to view this API's docs
984
-     */
985
-    protected function verifyAccess($route)
986
-    {
987
-        if ($route['accessLevel'] < 2) {
988
-            return true;
989
-        }
990
-        if (
991
-            static::$hideProtected
992
-            && !$this->_authenticated
993
-            && $route['accessLevel'] > 1
994
-        ) {
995
-            return false;
996
-        }
997
-        if ($this->_authenticated
998
-            && static::$accessControlFunction
999
-            && (!call_user_func(
1000
-                static::$accessControlFunction, $route['metadata']))
1001
-        ) {
1002
-            return false;
1003
-        }
1004
-        return true;
1005
-    }
22
+	/**
23
+	 * @var bool should protected resources be shown to unauthenticated users?
24
+	 */
25
+	public static $hideProtected = true;
26
+	/**
27
+	 * @var bool should we use format as extension?
28
+	 */
29
+	public static $useFormatAsExtension = true;
30
+	/**
31
+	 * @var bool should we include newer apis in the list? works only when
32
+	 * Defaults::$useUrlBasedVersioning is set to true;
33
+	 */
34
+	public static $listHigherVersions = true;
35
+	/**
36
+	 * @var array all http methods specified here will be excluded from
37
+	 * documentation
38
+	 */
39
+	public static $excludedHttpMethods = array('OPTIONS');
40
+	/**
41
+	 * @var array all paths beginning with any of the following will be excluded
42
+	 * from documentation
43
+	 */
44
+	public static $excludedPaths = array();
45
+	/**
46
+	 * @var bool
47
+	 */
48
+	public static $placeFormatExtensionBeforeDynamicParts = true;
49
+	/**
50
+	 * @var bool should we group all the operations with the same url or not
51
+	 */
52
+	public static $groupOperations = false;
53
+	/**
54
+	 * @var null|callable if the api methods are under access control mechanism
55
+	 * you can attach a function here that returns true or false to determine
56
+	 * visibility of a protected api method. this function will receive method
57
+	 * info as the only parameter.
58
+	 */
59
+	public static $accessControlFunction = null;
60
+	/**
61
+	 * @var array type mapping for converting data types to javascript / swagger
62
+	 */
63
+	public static $dataTypeAlias = array(
64
+		'string' => 'string',
65
+		'int' => 'int',
66
+		'number' => 'float',
67
+		'float' => 'float',
68
+		'bool' => 'boolean',
69
+		'boolean' => 'boolean',
70
+		'NULL' => 'null',
71
+		'array' => 'Array',
72
+		'object' => 'Object',
73
+		'stdClass' => 'Object',
74
+		'mixed' => 'string',
75
+		'DateTime' => 'Date'
76
+	);
77
+	/**
78
+	 * @var array configurable symbols to differentiate public, hybrid and
79
+	 * protected api
80
+	 */
81
+	public static $apiDescriptionSuffixSymbols = array(
82
+		0 => '&nbsp; <i class="icon-unlock-alt icon-large"></i>', //public api
83
+		1 => '&nbsp; <i class="icon-adjust icon-large"></i>', //hybrid api
84
+		2 => '&nbsp; <i class="icon-lock icon-large"></i>', //protected api
85
+	);
86
+
87
+	/**
88
+	 * Injected at runtime
89
+	 *
90
+	 * @var Restler instance of restler
91
+	 */
92
+	public $restler;
93
+	/**
94
+	 * @var string when format is not used as the extension this property is
95
+	 * used to set the extension manually
96
+	 */
97
+	public $formatString = '';
98
+	protected $_models;
99
+	protected $_bodyParam;
100
+	/**
101
+	 * @var bool|stdClass
102
+	 */
103
+	protected $_fullDataRequested = false;
104
+	protected $crud = array(
105
+		'POST' => 'create',
106
+		'GET' => 'retrieve',
107
+		'PUT' => 'update',
108
+		'DELETE' => 'delete',
109
+		'PATCH' => 'partial update'
110
+	);
111
+	protected static $prefixes = array(
112
+		'get' => 'retrieve',
113
+		'index' => 'list',
114
+		'post' => 'create',
115
+		'put' => 'update',
116
+		'patch' => 'modify',
117
+		'delete' => 'remove',
118
+	);
119
+	protected $_authenticated = false;
120
+	protected $cacheName = '';
121
+
122
+	public function __construct()
123
+	{
124
+		if (static::$useFormatAsExtension) {
125
+			$this->formatString = '.{format}';
126
+		}
127
+	}
128
+
129
+	/**
130
+	 * This method will be called first for filter classes and api classes so
131
+	 * that they can respond accordingly for filer method call and api method
132
+	 * calls
133
+	 *
134
+	 *
135
+	 * @param bool $isAuthenticated passes true when the authentication is
136
+	 *                              done, false otherwise
137
+	 *
138
+	 * @return mixed
139
+	 */
140
+	public function __setAuthenticationStatus($isAuthenticated = false)
141
+	{
142
+		$this->_authenticated = $isAuthenticated;
143
+	}
144
+
145
+	/**
146
+	 * pre call for get($id)
147
+	 *
148
+	 * if cache is present, use cache
149
+	 */
150
+	public function _pre_get_json($id)
151
+	{
152
+		$userClass = Defaults::$userIdentifierClass;
153
+		$this->cacheName = $userClass::getCacheIdentifier() . '_resources_' . $id;
154
+		if ($this->restler->getProductionMode()
155
+			&& !$this->restler->refreshCache
156
+			&& $this->restler->cache->isCached($this->cacheName)
157
+		) {
158
+			//by pass call, compose, postCall stages and directly send response
159
+			$this->restler->composeHeaders();
160
+			die($this->restler->cache->get($this->cacheName));
161
+		}
162
+	}
163
+
164
+	/**
165
+	 * post call for get($id)
166
+	 *
167
+	 * create cache if in production mode
168
+	 *
169
+	 * @param $responseData
170
+	 *
171
+	 * @internal param string $data composed json output
172
+	 *
173
+	 * @return string
174
+	 */
175
+	public function _post_get_json($responseData)
176
+	{
177
+		if ($this->restler->getProductionMode()) {
178
+			$this->restler->cache->set($this->cacheName, $responseData);
179
+		}
180
+		return $responseData;
181
+	}
182
+
183
+	/**
184
+	 * @access hybrid
185
+	 *
186
+	 * @param string $id
187
+	 *
188
+	 * @throws RestException
189
+	 * @return null|stdClass
190
+	 *
191
+	 * @url    GET {id}
192
+	 */
193
+	public function get($id = '')
194
+	{
195
+		$version = $this->restler->getRequestedApiVersion();
196
+		if (empty($id)) {
197
+			//do nothing
198
+		} elseif (false !== ($pos = strpos($id, '-v'))) {
199
+			//$version = intval(substr($id, $pos + 2));
200
+			$id = substr($id, 0, $pos);
201
+		} elseif ($id[0] == 'v' && is_numeric($v = substr($id, 1))) {
202
+			$id = '';
203
+			//$version = $v;
204
+		} elseif ($id == 'root' || $id == 'index') {
205
+			$id = '';
206
+		}
207
+		$this->_models = new stdClass();
208
+		$r = null;
209
+		$count = 0;
210
+
211
+		$tSlash = !empty($id);
212
+		$target = empty($id) ? '' : $id;
213
+		$tLen = strlen($target);
214
+
215
+		$filter = array();
216
+
217
+		$routes
218
+			= Util::nestedValue(Routes::toArray(), "v$version")
219
+			? : array();
220
+
221
+		$prefix = Defaults::$useUrlBasedVersioning ? "/v$version" : '';
222
+
223
+		foreach ($routes as $value) {
224
+			foreach ($value as $httpMethod => $route) {
225
+				if (in_array($httpMethod, static::$excludedHttpMethods)) {
226
+					continue;
227
+				}
228
+				$fullPath = $route['url'];
229
+				if ($fullPath !== $target && !Text::beginsWith($fullPath, $target)) {
230
+					continue;
231
+				}
232
+				$fLen = strlen($fullPath);
233
+				if ($tSlash) {
234
+					if ($fLen != $tLen && !Text::beginsWith($fullPath, $target . '/'))
235
+						continue;
236
+				} elseif ($fLen > $tLen + 1 && $fullPath[$tLen + 1] != '{' && !Text::beginsWith($fullPath, '{')) {
237
+					//when mapped to root exclude paths that have static parts
238
+					//they are listed else where under that static part name
239
+					continue;
240
+				}
241
+
242
+				if (!static::verifyAccess($route)) {
243
+					continue;
244
+				}
245
+				foreach (static::$excludedPaths as $exclude) {
246
+					if (empty($exclude)) {
247
+						if ($fullPath == $exclude)
248
+							continue 2;
249
+					} elseif (Text::beginsWith($fullPath, $exclude)) {
250
+						continue 2;
251
+					}
252
+				}
253
+				$m = $route['metadata'];
254
+				if ($id == '' && $m['resourcePath'] != '') {
255
+					continue;
256
+				}
257
+				if (isset($filter[$httpMethod][$fullPath])) {
258
+					continue;
259
+				}
260
+				$filter[$httpMethod][$fullPath] = true;
261
+				// reset body params
262
+				$this->_bodyParam = array(
263
+					'required' => false,
264
+					'description' => array()
265
+				);
266
+				$count++;
267
+				$className = $this->_noNamespace($route['className']);
268
+				if (!$r) {
269
+					$resourcePath = '/'
270
+						. trim($m['resourcePath'], '/');
271
+					$r = $this->_operationListing($resourcePath);
272
+				}
273
+				$parts = explode('/', $fullPath);
274
+				$pos = count($parts) - 1;
275
+				if (count($parts) == 1 && $httpMethod == 'GET') {
276
+				} else {
277
+					for ($i = 0; $i < count($parts); $i++) {
278
+						if (strlen($parts[$i]) && $parts[$i][0] == '{') {
279
+							$pos = $i - 1;
280
+							break;
281
+						}
282
+					}
283
+				}
284
+				$nickname = $this->_nickname($route);
285
+				$index = static::$placeFormatExtensionBeforeDynamicParts && $pos > 0 ? $pos : 0;
286
+				if (!empty($parts[$index]))
287
+					$parts[$index] .= $this->formatString;
288
+
289
+				$fullPath = implode('/', $parts);
290
+				$description = isset(
291
+				$m['classDescription'])
292
+					? $m['classDescription']
293
+					: $className . ' API';
294
+				if (empty($m['description'])) {
295
+					$m['description'] = $this->restler->getProductionMode()
296
+						? ''
297
+						: 'routes to <mark>'
298
+						. $route['className']
299
+						. '::'
300
+						. $route['methodName'] . '();</mark>';
301
+				}
302
+				if (empty($m['longDescription'])) {
303
+					$m['longDescription'] = $this->restler->getProductionMode()
304
+						? ''
305
+						: 'Add PHPDoc long description to '
306
+						. "<mark>$className::"
307
+						. $route['methodName'] . '();</mark>'
308
+						. '  (the api method) to write here';
309
+				}
310
+				$operation = $this->_operation(
311
+					$route,
312
+					$nickname,
313
+					$httpMethod,
314
+					$m['description'],
315
+					$m['longDescription']
316
+				);
317
+				if (isset($m['throws'])) {
318
+					foreach ($m['throws'] as $exception) {
319
+						$operation->errorResponses[] = array(
320
+							'reason' => $exception['message'],
321
+							'code' => $exception['code']);
322
+					}
323
+				}
324
+				if (isset($m['param'])) {
325
+					foreach ($m['param'] as $param) {
326
+						//combine body params as one
327
+						$p = $this->_parameter($param);
328
+						if ($p->paramType == 'body') {
329
+							$this->_appendToBody($p);
330
+						} else {
331
+							$operation->parameters[] = $p;
332
+						}
333
+					}
334
+				}
335
+				if (
336
+					count($this->_bodyParam['description']) ||
337
+					(
338
+						$this->_fullDataRequested &&
339
+						$httpMethod != 'GET' &&
340
+						$httpMethod != 'DELETE'
341
+					)
342
+				) {
343
+					$operation->parameters[] = $this->_getBody();
344
+				}
345
+				if (isset($m['return']['type'])) {
346
+					$responseClass = $m['return']['type'];
347
+					if (is_string($responseClass)) {
348
+						if (class_exists($responseClass)) {
349
+							$this->_model($responseClass);
350
+							$operation->responseClass
351
+								= $this->_noNamespace($responseClass);
352
+						} elseif (strtolower($responseClass) == 'array') {
353
+							$operation->responseClass = 'Array';
354
+							$rt = $m['return'];
355
+							if (isset(
356
+							$rt[CommentParser::$embeddedDataName]['type'])
357
+							) {
358
+								$rt = $rt[CommentParser::$embeddedDataName]
359
+								['type'];
360
+								if (class_exists($rt)) {
361
+									$this->_model($rt);
362
+									$operation->responseClass .= '[' .
363
+										$this->_noNamespace($rt) . ']';
364
+								}
365
+							}
366
+						}
367
+					}
368
+				}
369
+				$api = false;
370
+
371
+				if (static::$groupOperations) {
372
+					foreach ($r->apis as $a) {
373
+						if ($a->path == "$prefix/$fullPath") {
374
+							$api = $a;
375
+							break;
376
+						}
377
+					}
378
+				}
379
+
380
+				if (!$api) {
381
+					$api = $this->_api("$prefix/$fullPath", $description);
382
+					$r->apis[] = $api;
383
+				}
384
+
385
+				$api->operations[] = $operation;
386
+			}
387
+		}
388
+		if (!$count) {
389
+			throw new RestException(404);
390
+		}
391
+		if (!is_null($r))
392
+			$r->models = $this->_models;
393
+		usort(
394
+			$r->apis,
395
+			function ($a, $b) {
396
+				$order = array(
397
+					'GET' => 1,
398
+					'POST' => 2,
399
+					'PUT' => 3,
400
+					'PATCH' => 4,
401
+					'DELETE' => 5
402
+				);
403
+				return
404
+					$a->operations[0]->httpMethod ==
405
+					$b->operations[0]->httpMethod
406
+						? $a->path > $b->path
407
+						: $order[$a->operations[0]->httpMethod] >
408
+						$order[$b->operations[0]->httpMethod];
409
+
410
+			}
411
+		);
412
+		return $r;
413
+	}
414
+
415
+	protected function _nickname(array $route)
416
+	{
417
+		static $hash = array();
418
+		$method = $route['methodName'];
419
+		if (isset(static::$prefixes[$method])) {
420
+			$method = static::$prefixes[$method];
421
+		} else {
422
+			$method = str_replace(
423
+				array_keys(static::$prefixes),
424
+				array_values(static::$prefixes),
425
+				$method
426
+			);
427
+		}
428
+		while (isset($hash[$method]) && $route['url'] != $hash[$method]) {
429
+			//create another one
430
+			$method .= '_';
431
+		}
432
+		$hash[$method] = $route['url'];
433
+		return $method;
434
+	}
435
+
436
+	protected function _noNamespace($className)
437
+	{
438
+		$className = explode('\\', $className);
439
+		return end($className);
440
+	}
441
+
442
+	protected function _operationListing($resourcePath = '/')
443
+	{
444
+		$r = $this->_resourceListing();
445
+		$r->resourcePath = $resourcePath;
446
+		$r->models = new stdClass();
447
+		return $r;
448
+	}
449
+
450
+	protected function _resourceListing()
451
+	{
452
+		$r = new stdClass();
453
+		$r->apiVersion = (string)$this->restler->_requestedApiVersion;
454
+		$r->swaggerVersion = "1.1";
455
+		$r->basePath = $this->restler->getBaseUrl();
456
+		$r->produces = $this->restler->getWritableMimeTypes();
457
+		$r->consumes = $this->restler->getReadableMimeTypes();
458
+		$r->apis = array();
459
+		return $r;
460
+	}
461
+
462
+	protected function _api($path, $description = '')
463
+	{
464
+		$r = new stdClass();
465
+		$r->path = $path;
466
+		$r->description =
467
+			empty($description) && $this->restler->getProductionMode()
468
+				? 'Use PHPDoc comment to describe here'
469
+				: $description;
470
+		$r->operations = array();
471
+		return $r;
472
+	}
473
+
474
+	protected function _operation(
475
+		$route,
476
+		$nickname,
477
+		$httpMethod = 'GET',
478
+		$summary = 'description',
479
+		$notes = 'long description',
480
+		$responseClass = 'void'
481
+	)
482
+	{
483
+		//reset body params
484
+		$this->_bodyParam = array(
485
+			'required' => false,
486
+			'description' => array()
487
+		);
488
+
489
+		$r = new stdClass();
490
+		$r->httpMethod = $httpMethod;
491
+		$r->nickname = $nickname;
492
+		$r->responseClass = $responseClass;
493
+
494
+		$r->parameters = array();
495
+
496
+		$r->summary = $summary . ($route['accessLevel'] > 2
497
+				? static::$apiDescriptionSuffixSymbols[2]
498
+				: static::$apiDescriptionSuffixSymbols[$route['accessLevel']]
499
+			);
500
+		$r->notes = $notes;
501
+
502
+		$r->errorResponses = array();
503
+		return $r;
504
+	}
505
+
506
+	protected function _parameter($param)
507
+	{
508
+		$r = new stdClass();
509
+		$r->name = $param['name'];
510
+		$r->description = !empty($param['description'])
511
+			? $param['description'] . '.'
512
+			: ($this->restler->getProductionMode()
513
+				? ''
514
+				: 'add <mark>@param {type} $' . $r->name
515
+				. ' {comment}</mark> to describe here');
516
+		//paramType can be path or query or body or header
517
+		$r->paramType = Util::nestedValue($param, CommentParser::$embeddedDataName, 'from') ? : 'query';
518
+		$r->required = isset($param['required']) && $param['required'];
519
+		if (isset($param['default'])) {
520
+			$r->defaultValue = $param['default'];
521
+		} elseif (isset($param[CommentParser::$embeddedDataName]['example'])) {
522
+			$r->defaultValue
523
+				= $param[CommentParser::$embeddedDataName]['example'];
524
+		}
525
+		$r->allowMultiple = false;
526
+		$type = 'string';
527
+		if (isset($param['type'])) {
528
+			$type = $param['type'];
529
+			if (is_array($type)) {
530
+				$type = array_shift($type);
531
+			}
532
+			if ($type == 'array') {
533
+				$contentType = Util::nestedValue(
534
+					$param,
535
+					CommentParser::$embeddedDataName,
536
+					'type'
537
+				);
538
+				if ($contentType) {
539
+					if ($contentType == 'indexed') {
540
+						$type = 'Array';
541
+					} elseif ($contentType == 'associative') {
542
+						$type = 'Object';
543
+					} else {
544
+						$type = "Array[$contentType]";
545
+					}
546
+					if (Util::isObjectOrArray($contentType)) {
547
+						$this->_model($contentType);
548
+					}
549
+				} elseif (isset(static::$dataTypeAlias[$type])) {
550
+					$type = static::$dataTypeAlias[$type];
551
+				}
552
+			} elseif (Util::isObjectOrArray($type)) {
553
+				$this->_model($type);
554
+			} elseif (isset(static::$dataTypeAlias[$type])) {
555
+				$type = static::$dataTypeAlias[$type];
556
+			}
557
+		}
558
+		$r->dataType = $type;
559
+		if (isset($param[CommentParser::$embeddedDataName])) {
560
+			$p = $param[CommentParser::$embeddedDataName];
561
+			if (isset($p['min']) && isset($p['max'])) {
562
+				$r->allowableValues = array(
563
+					'valueType' => 'RANGE',
564
+					'min' => $p['min'],
565
+					'max' => $p['max'],
566
+				);
567
+			} elseif (isset($p['choice'])) {
568
+				$r->allowableValues = array(
569
+					'valueType' => 'LIST',
570
+					'values' => $p['choice']
571
+				);
572
+			}
573
+		}
574
+		return $r;
575
+	}
576
+
577
+	protected function _appendToBody($p)
578
+	{
579
+		if ($p->name === Defaults::$fullRequestDataName) {
580
+			$this->_fullDataRequested = $p;
581
+			unset($this->_bodyParam['names'][Defaults::$fullRequestDataName]);
582
+			return;
583
+		}
584
+		$this->_bodyParam['description'][$p->name]
585
+			= "$p->name"
586
+			. ' : <tag>' . $p->dataType . '</tag> '
587
+			. ($p->required ? ' <i>(required)</i> - ' : ' - ')
588
+			. $p->description;
589
+		$this->_bodyParam['required'] = $p->required
590
+			|| $this->_bodyParam['required'];
591
+		$this->_bodyParam['names'][$p->name] = $p;
592
+	}
593
+
594
+	protected function _getBody()
595
+	{
596
+		$r = new stdClass();
597
+		$n = isset($this->_bodyParam['names'])
598
+			? array_values($this->_bodyParam['names'])
599
+			: array();
600
+		if (count($n) == 1) {
601
+			if (isset($this->_models->{$n[0]->dataType})) {
602
+				// ============ custom class ===================
603
+				$r = $n[0];
604
+				$c = $this->_models->{$r->dataType};
605
+				$a = $c->properties;
606
+				$r->description = "Paste JSON data here";
607
+				if (count($a)) {
608
+					$r->description .= " with the following"
609
+						. (count($a) > 1 ? ' properties.' : ' property.');
610
+					foreach ($a as $k => $v) {
611
+						$r->description .= "<hr/>$k : <tag>"
612
+							. $v['type'] . '</tag> '
613
+							. (isset($v['required']) ? '(required)' : '')
614
+							. ' - ' . $v['description'];
615
+					}
616
+				}
617
+				$r->defaultValue = "{\n    \""
618
+					. implode("\": \"\",\n    \"",
619
+						array_keys($c->properties))
620
+					. "\": \"\"\n}";
621
+				return $r;
622
+			} elseif (false !== ($p = strpos($n[0]->dataType, '['))) {
623
+				// ============ array of custom class ===============
624
+				$r = $n[0];
625
+				$t = substr($r->dataType, $p + 1, -1);
626
+				if ($c = Util::nestedValue($this->_models, $t)) {
627
+					$a = $c->properties;
628
+					$r->description = "Paste JSON data here";
629
+					if (count($a)) {
630
+						$r->description .= " with an array of objects with the following"
631
+							. (count($a) > 1 ? ' properties.' : ' property.');
632
+						foreach ($a as $k => $v) {
633
+							$r->description .= "<hr/>$k : <tag>"
634
+								. $v['type'] . '</tag> '
635
+								. (isset($v['required']) ? '(required)' : '')
636
+								. ' - ' . $v['description'];
637
+						}
638
+					}
639
+					$r->defaultValue = "[\n    {\n        \""
640
+						. implode("\": \"\",\n        \"",
641
+							array_keys($c->properties))
642
+						. "\": \"\"\n    }\n]";
643
+					return $r;
644
+				} else {
645
+					$r->description = "Paste JSON data here with an array of $t values.";
646
+					$r->defaultValue = "[ ]";
647
+					return $r;
648
+				}
649
+			} elseif ($n[0]->dataType == 'Array') {
650
+				// ============ array ===============================
651
+				$r = $n[0];
652
+				$r->description = "Paste JSON array data here"
653
+					. ($r->required ? ' (required) . ' : '. ')
654
+					. "<br/>$r->description";
655
+				$r->defaultValue = "[\n    {\n        \""
656
+					. "property\" : \"\"\n    }\n]";
657
+				return $r;
658
+			} elseif ($n[0]->dataType == 'Object') {
659
+				// ============ object ==============================
660
+				$r = $n[0];
661
+				$r->description = "Paste JSON object data here"
662
+					. ($r->required ? ' (required) . ' : '. ')
663
+					. "<br/>$r->description";
664
+				$r->defaultValue = "{\n    \""
665
+					. "property\" : \"\"\n}";
666
+				return $r;
667
+			}
668
+		}
669
+		$p = array_values($this->_bodyParam['description']);
670
+		$r->name = 'REQUEST_BODY';
671
+		$r->description = "Paste JSON data here";
672
+		if (count($p) == 0 && $this->_fullDataRequested) {
673
+			$r->required = $this->_fullDataRequested->required;
674
+			$r->defaultValue = "{\n    \"property\" : \"\"\n}";
675
+		} else {
676
+			$r->description .= " with the following"
677
+				. (count($p) > 1 ? ' properties.' : ' property.')
678
+				. '<hr/>'
679
+				. implode("<hr/>", $p);
680
+			$r->required = $this->_bodyParam['required'];
681
+			// Create default object that includes parameters to be submitted
682
+			$defaultObject = new \StdClass();
683
+			foreach ($this->_bodyParam['names'] as $name => $values) {
684
+				if (!$values->required)
685
+					continue;
686
+				if (class_exists($values->dataType)) {
687
+					$myClassName = $values->dataType;
688
+					$defaultObject->$name = new $myClassName();
689
+				} else {
690
+					$defaultObject->$name = '';
691
+				}
692
+			}
693
+			$r->defaultValue = Scope::get('JsonFormat')->encode($defaultObject, true);
694
+		}
695
+		$r->paramType = 'body';
696
+		$r->allowMultiple = false;
697
+		$r->dataType = 'Object';
698
+		return $r;
699
+	}
700
+
701
+	protected function _model($className, $instance = null)
702
+	{
703
+		$id = $this->_noNamespace($className);
704
+		if (isset($this->_models->{$id})) {
705
+			return;
706
+		}
707
+		$properties = array();
708
+		if (!$instance) {
709
+			if (!class_exists($className))
710
+				return;
711
+			$instance = new $className();
712
+		}
713
+		$data = get_object_vars($instance);
714
+		$reflectionClass = new \ReflectionClass($className);
715
+		foreach ($data as $key => $value) {
716
+
717
+			$propertyMetaData = null;
718
+
719
+			try {
720
+				$property = $reflectionClass->getProperty($key);
721
+				if ($c = $property->getDocComment()) {
722
+					$propertyMetaData = Util::nestedValue(
723
+						CommentParser::parse($c),
724
+						'var'
725
+					);
726
+				}
727
+			} catch (\ReflectionException $e) {
728
+			}
729
+
730
+			if (is_null($propertyMetaData)) {
731
+				$type = $this->getType($value, true);
732
+				$description = '';
733
+			} else {
734
+				$type = Util::nestedValue(
735
+					$propertyMetaData,
736
+					'type'
737
+				) ? : $this->getType($value, true);
738
+				$description = Util::nestedValue(
739
+					$propertyMetaData,
740
+					'description'
741
+				) ? : '';
742
+
743
+				if (class_exists($type)) {
744
+					$this->_model($type);
745
+					$type = $this->_noNamespace($type);
746
+				}
747
+			}
748
+
749
+			if (isset(static::$dataTypeAlias[$type])) {
750
+				$type = static::$dataTypeAlias[$type];
751
+			}
752
+			$properties[$key] = array(
753
+				'type' => $type,
754
+				'description' => $description
755
+			);
756
+			if (Util::nestedValue(
757
+				$propertyMetaData,
758
+				CommentParser::$embeddedDataName,
759
+				'required'
760
+			)
761
+			) {
762
+				$properties[$key]['required'] = true;
763
+			}
764
+			if ($type == 'Array') {
765
+				$itemType = Util::nestedValue(
766
+					$propertyMetaData,
767
+					CommentParser::$embeddedDataName,
768
+					'type'
769
+				) ? :
770
+					(count($value)
771
+						? $this->getType(end($value), true)
772
+						: 'string');
773
+				if (class_exists($itemType)) {
774
+					$this->_model($itemType);
775
+					$itemType = $this->_noNamespace($itemType);
776
+				}
777
+				$properties[$key]['items'] = array(
778
+					'type' => $itemType,
779
+					/*'description' => '' */ //TODO: add description
780
+				);
781
+			} else if (preg_match('/^Array\[(.+)\]$/', $type, $matches)) {
782
+				$itemType = $matches[1];
783
+				$properties[$key]['type'] = 'Array';
784
+				$properties[$key]['items']['type'] = $this->_noNamespace($itemType);
785
+
786
+				if (class_exists($itemType)) {
787
+					$this->_model($itemType);
788
+				}
789
+			}
790
+		}
791
+		if (!empty($properties)) {
792
+			$model = new stdClass();
793
+			$model->id = $id;
794
+			$model->properties = $properties;
795
+			$this->_models->{$id} = $model;
796
+		}
797
+	}
798
+
799
+	/**
800
+	 * Find the data type of the given value.
801
+	 *
802
+	 *
803
+	 * @param mixed $o given value for finding type
804
+	 *
805
+	 * @param bool $appendToModels if an object is found should we append to
806
+	 *                              our models list?
807
+	 *
808
+	 * @return string
809
+	 *
810
+	 * @access private
811
+	 */
812
+	public function getType($o, $appendToModels = false)
813
+	{
814
+		if (is_object($o)) {
815
+			$oc = get_class($o);
816
+			if ($appendToModels) {
817
+				$this->_model($oc, $o);
818
+			}
819
+			return $this->_noNamespace($oc);
820
+		}
821
+		if (is_array($o)) {
822
+			if (count($o)) {
823
+				$child = end($o);
824
+				if (Util::isObjectOrArray($child)) {
825
+					$childType = $this->getType($child, $appendToModels);
826
+					return "Array[$childType]";
827
+				}
828
+			}
829
+			return 'array';
830
+		}
831
+		if (is_bool($o)) return 'boolean';
832
+		if (is_numeric($o)) return is_float($o) ? 'float' : 'int';
833
+		return 'string';
834
+	}
835
+
836
+	/**
837
+	 * pre call for index()
838
+	 *
839
+	 * if cache is present, use cache
840
+	 */
841
+	public function _pre_index_json()
842
+	{
843
+		$userClass = Defaults::$userIdentifierClass;
844
+		$this->cacheName = $userClass::getCacheIdentifier()
845
+			. '_resources-v'
846
+			. $this->restler->_requestedApiVersion;
847
+		if ($this->restler->getProductionMode()
848
+			&& !$this->restler->refreshCache
849
+			&& $this->restler->cache->isCached($this->cacheName)
850
+		) {
851
+			//by pass call, compose, postCall stages and directly send response
852
+			$this->restler->composeHeaders();
853
+			die($this->restler->cache->get($this->cacheName));
854
+		}
855
+	}
856
+
857
+	/**
858
+	 * post call for index()
859
+	 *
860
+	 * create cache if in production mode
861
+	 *
862
+	 * @param $responseData
863
+	 *
864
+	 * @internal param string $data composed json output
865
+	 *
866
+	 * @return string
867
+	 */
868
+	public function _post_index_json($responseData)
869
+	{
870
+		if ($this->restler->getProductionMode()) {
871
+			$this->restler->cache->set($this->cacheName, $responseData);
872
+		}
873
+		return $responseData;
874
+	}
875
+
876
+	/**
877
+	 * @access hybrid
878
+	 * @return \stdClass
879
+	 */
880
+	public function index()
881
+	{
882
+		if (!static::$accessControlFunction && Defaults::$accessControlFunction)
883
+			static::$accessControlFunction = Defaults::$accessControlFunction;
884
+		$version = $this->restler->getRequestedApiVersion();
885
+		$allRoutes = Util::nestedValue(Routes::toArray(), "v$version");
886
+		$r = $this->_resourceListing();
887
+		$map = array();
888
+		if (isset($allRoutes['*'])) {
889
+			$this->_mapResources($allRoutes['*'], $map, $version);
890
+			unset($allRoutes['*']);
891
+		}
892
+		$this->_mapResources($allRoutes, $map, $version);
893
+		foreach ($map as $path => $description) {
894
+			if (!Text::contains($path, '{')) {
895
+				//add id
896
+				$r->apis[] = array(
897
+					'path' => $path . $this->formatString,
898
+					'description' => $description
899
+				);
900
+			}
901
+		}
902
+		if (Defaults::$useUrlBasedVersioning && static::$listHigherVersions) {
903
+			$nextVersion = $version + 1;
904
+			if ($nextVersion <= $this->restler->getApiVersion()) {
905
+				list($status, $data) = $this->_loadResource("/v$nextVersion/resources.json");
906
+				if ($status == 200) {
907
+					$r->apis = array_merge($r->apis, $data->apis);
908
+					$r->apiVersion = $data->apiVersion;
909
+				}
910
+			}
911
+
912
+		}
913
+		return $r;
914
+	}
915
+
916
+	protected function _loadResource($url)
917
+	{
918
+		$ch = curl_init($this->restler->getBaseUrl() . $url
919
+			. (empty($_GET) ? '' : '?' . http_build_query($_GET)));
920
+		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
921
+		curl_setopt($ch, CURLOPT_TIMEOUT, 15);
922
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
923
+		curl_setopt($ch, CURLOPT_HTTPHEADER, array(
924
+			'Accept:application/json',
925
+		));
926
+		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);        
927
+		$result = json_decode(curl_exec($ch));
928
+		$http_status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
929
+		return array($http_status, $result);
930
+	}
931
+
932
+	protected function _mapResources(array $allRoutes, array &$map, $version = 1)
933
+	{
934
+		foreach ($allRoutes as $fullPath => $routes) {
935
+			$path = explode('/', $fullPath);
936
+			$resource = isset($path[0]) ? $path[0] : '';
937
+			if ($resource == 'resources' || Text::endsWith($resource, 'index'))
938
+				continue;
939
+			foreach ($routes as $httpMethod => $route) {
940
+				if (in_array($httpMethod, static::$excludedHttpMethods)) {
941
+					continue;
942
+				}
943
+				if (!static::verifyAccess($route)) {
944
+					continue;
945
+				}
946
+
947
+				foreach (static::$excludedPaths as $exclude) {
948
+					if (empty($exclude)) {
949
+						if ($fullPath == $exclude)
950
+							continue 2;
951
+					} elseif (Text::beginsWith($fullPath, $exclude)) {
952
+						continue 2;
953
+					}
954
+				}
955
+
956
+				$res = $resource
957
+					? ($version == 1 ? "/resources/$resource" : "/v$version/resources/$resource-v$version")
958
+					: ($version == 1 ? "/resources/root" : "/v$version/resources/root-v$version");
959
+
960
+				if (empty($map[$res])) {
961
+					$map[$res] = isset(
962
+					$route['metadata']['classDescription'])
963
+						? $route['metadata']['classDescription'] : '';
964
+				}
965
+			}
966
+		}
967
+	}
968
+
969
+	/**
970
+	 * Maximum api version supported by the api class
971
+	 * @return int
972
+	 */
973
+	public static function __getMaximumSupportedVersion()
974
+	{
975
+		return Scope::get('Restler')->getApiVersion();
976
+	}
977
+
978
+	/**
979
+	 * Verifies that the requesting user is allowed to view the docs for this API
980
+	 *
981
+	 * @param $route
982
+	 *
983
+	 * @return boolean True if the user should be able to view this API's docs
984
+	 */
985
+	protected function verifyAccess($route)
986
+	{
987
+		if ($route['accessLevel'] < 2) {
988
+			return true;
989
+		}
990
+		if (
991
+			static::$hideProtected
992
+			&& !$this->_authenticated
993
+			&& $route['accessLevel'] > 1
994
+		) {
995
+			return false;
996
+		}
997
+		if ($this->_authenticated
998
+			&& static::$accessControlFunction
999
+			&& (!call_user_func(
1000
+				static::$accessControlFunction, $route['metadata']))
1001
+		) {
1002
+			return false;
1003
+		}
1004
+		return true;
1005
+	}
1006 1006
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -27 removed lines patch added patch discarded remove patch
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
     public function _pre_get_json($id)
151 151
     {
152 152
         $userClass = Defaults::$userIdentifierClass;
153
-        $this->cacheName = $userClass::getCacheIdentifier() . '_resources_' . $id;
153
+        $this->cacheName = $userClass::getCacheIdentifier().'_resources_'.$id;
154 154
         if ($this->restler->getProductionMode()
155 155
             && !$this->restler->refreshCache
156 156
             && $this->restler->cache->isCached($this->cacheName)
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 
217 217
         $routes
218 218
             = Util::nestedValue(Routes::toArray(), "v$version")
219
-            ? : array();
219
+            ?: array();
220 220
 
221 221
         $prefix = Defaults::$useUrlBasedVersioning ? "/v$version" : '';
222 222
 
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
                 }
232 232
                 $fLen = strlen($fullPath);
233 233
                 if ($tSlash) {
234
-                    if ($fLen != $tLen && !Text::beginsWith($fullPath, $target . '/'))
234
+                    if ($fLen != $tLen && !Text::beginsWith($fullPath, $target.'/'))
235 235
                         continue;
236 236
                 } elseif ($fLen > $tLen + 1 && $fullPath[$tLen + 1] != '{' && !Text::beginsWith($fullPath, '{')) {
237 237
                     //when mapped to root exclude paths that have static parts
@@ -290,21 +290,21 @@  discard block
 block discarded – undo
290 290
                 $description = isset(
291 291
                 $m['classDescription'])
292 292
                     ? $m['classDescription']
293
-                    : $className . ' API';
293
+                    : $className.' API';
294 294
                 if (empty($m['description'])) {
295 295
                     $m['description'] = $this->restler->getProductionMode()
296 296
                         ? ''
297 297
                         : 'routes to <mark>'
298 298
                         . $route['className']
299 299
                         . '::'
300
-                        . $route['methodName'] . '();</mark>';
300
+                        . $route['methodName'].'();</mark>';
301 301
                 }
302 302
                 if (empty($m['longDescription'])) {
303 303
                     $m['longDescription'] = $this->restler->getProductionMode()
304 304
                         ? ''
305 305
                         : 'Add PHPDoc long description to '
306 306
                         . "<mark>$className::"
307
-                        . $route['methodName'] . '();</mark>'
307
+                        . $route['methodName'].'();</mark>'
308 308
                         . '  (the api method) to write here';
309 309
                 }
310 310
                 $operation = $this->_operation(
@@ -359,8 +359,8 @@  discard block
 block discarded – undo
359 359
                                 ['type'];
360 360
                                 if (class_exists($rt)) {
361 361
                                     $this->_model($rt);
362
-                                    $operation->responseClass .= '[' .
363
-                                        $this->_noNamespace($rt) . ']';
362
+                                    $operation->responseClass .= '['.
363
+                                        $this->_noNamespace($rt).']';
364 364
                                 }
365 365
                             }
366 366
                         }
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
             $r->models = $this->_models;
393 393
         usort(
394 394
             $r->apis,
395
-            function ($a, $b) {
395
+            function($a, $b) {
396 396
                 $order = array(
397 397
                     'GET' => 1,
398 398
                     'POST' => 2,
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
     protected function _resourceListing()
451 451
     {
452 452
         $r = new stdClass();
453
-        $r->apiVersion = (string)$this->restler->_requestedApiVersion;
453
+        $r->apiVersion = (string) $this->restler->_requestedApiVersion;
454 454
         $r->swaggerVersion = "1.1";
455 455
         $r->basePath = $this->restler->getBaseUrl();
456 456
         $r->produces = $this->restler->getWritableMimeTypes();
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
 
494 494
         $r->parameters = array();
495 495
 
496
-        $r->summary = $summary . ($route['accessLevel'] > 2
496
+        $r->summary = $summary.($route['accessLevel'] > 2
497 497
                 ? static::$apiDescriptionSuffixSymbols[2]
498 498
                 : static::$apiDescriptionSuffixSymbols[$route['accessLevel']]
499 499
             );
@@ -508,13 +508,13 @@  discard block
 block discarded – undo
508 508
         $r = new stdClass();
509 509
         $r->name = $param['name'];
510 510
         $r->description = !empty($param['description'])
511
-            ? $param['description'] . '.'
511
+            ? $param['description'].'.'
512 512
             : ($this->restler->getProductionMode()
513 513
                 ? ''
514
-                : 'add <mark>@param {type} $' . $r->name
514
+                : 'add <mark>@param {type} $'.$r->name
515 515
                 . ' {comment}</mark> to describe here');
516 516
         //paramType can be path or query or body or header
517
-        $r->paramType = Util::nestedValue($param, CommentParser::$embeddedDataName, 'from') ? : 'query';
517
+        $r->paramType = Util::nestedValue($param, CommentParser::$embeddedDataName, 'from') ?: 'query';
518 518
         $r->required = isset($param['required']) && $param['required'];
519 519
         if (isset($param['default'])) {
520 520
             $r->defaultValue = $param['default'];
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
         }
584 584
         $this->_bodyParam['description'][$p->name]
585 585
             = "$p->name"
586
-            . ' : <tag>' . $p->dataType . '</tag> '
586
+            . ' : <tag>'.$p->dataType.'</tag> '
587 587
             . ($p->required ? ' <i>(required)</i> - ' : ' - ')
588 588
             . $p->description;
589 589
         $this->_bodyParam['required'] = $p->required
@@ -609,9 +609,9 @@  discard block
 block discarded – undo
609 609
                         . (count($a) > 1 ? ' properties.' : ' property.');
610 610
                     foreach ($a as $k => $v) {
611 611
                         $r->description .= "<hr/>$k : <tag>"
612
-                            . $v['type'] . '</tag> '
612
+                            . $v['type'].'</tag> '
613 613
                             . (isset($v['required']) ? '(required)' : '')
614
-                            . ' - ' . $v['description'];
614
+                            . ' - '.$v['description'];
615 615
                     }
616 616
                 }
617 617
                 $r->defaultValue = "{\n    \""
@@ -631,9 +631,9 @@  discard block
 block discarded – undo
631 631
                             . (count($a) > 1 ? ' properties.' : ' property.');
632 632
                         foreach ($a as $k => $v) {
633 633
                             $r->description .= "<hr/>$k : <tag>"
634
-                                . $v['type'] . '</tag> '
634
+                                . $v['type'].'</tag> '
635 635
                                 . (isset($v['required']) ? '(required)' : '')
636
-                                . ' - ' . $v['description'];
636
+                                . ' - '.$v['description'];
637 637
                         }
638 638
                     }
639 639
                     $r->defaultValue = "[\n    {\n        \""
@@ -734,11 +734,11 @@  discard block
 block discarded – undo
734 734
                 $type = Util::nestedValue(
735 735
                     $propertyMetaData,
736 736
                     'type'
737
-                ) ? : $this->getType($value, true);
737
+                ) ?: $this->getType($value, true);
738 738
                 $description = Util::nestedValue(
739 739
                     $propertyMetaData,
740 740
                     'description'
741
-                ) ? : '';
741
+                ) ?: '';
742 742
 
743 743
                 if (class_exists($type)) {
744 744
                     $this->_model($type);
@@ -766,8 +766,7 @@  discard block
 block discarded – undo
766 766
                     $propertyMetaData,
767 767
                     CommentParser::$embeddedDataName,
768 768
                     'type'
769
-                ) ? :
770
-                    (count($value)
769
+                ) ?: (count($value)
771 770
                         ? $this->getType(end($value), true)
772 771
                         : 'string');
773 772
                 if (class_exists($itemType)) {
@@ -894,7 +893,7 @@  discard block
 block discarded – undo
894 893
             if (!Text::contains($path, '{')) {
895 894
                 //add id
896 895
                 $r->apis[] = array(
897
-                    'path' => $path . $this->formatString,
896
+                    'path' => $path.$this->formatString,
898 897
                     'description' => $description
899 898
                 );
900 899
             }
@@ -915,8 +914,8 @@  discard block
 block discarded – undo
915 914
 
916 915
     protected function _loadResource($url)
917 916
     {
918
-        $ch = curl_init($this->restler->getBaseUrl() . $url
919
-            . (empty($_GET) ? '' : '?' . http_build_query($_GET)));
917
+        $ch = curl_init($this->restler->getBaseUrl().$url
918
+            . (empty($_GET) ? '' : '?'.http_build_query($_GET)));
920 919
         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
921 920
         curl_setopt($ch, CURLOPT_TIMEOUT, 15);
922 921
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -925,7 +924,7 @@  discard block
 block discarded – undo
925 924
         ));
926 925
         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);        
927 926
         $result = json_decode(curl_exec($ch));
928
-        $http_status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
927
+        $http_status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
929 928
         return array($http_status, $result);
930 929
     }
931 930
 
Please login to merge, or discard this patch.
Braces   +33 added lines, -20 removed lines patch added patch discarded remove patch
@@ -231,8 +231,9 @@  discard block
 block discarded – undo
231 231
                 }
232 232
                 $fLen = strlen($fullPath);
233 233
                 if ($tSlash) {
234
-                    if ($fLen != $tLen && !Text::beginsWith($fullPath, $target . '/'))
235
-                        continue;
234
+                    if ($fLen != $tLen && !Text::beginsWith($fullPath, $target . '/')) {
235
+                                            continue;
236
+                    }
236 237
                 } elseif ($fLen > $tLen + 1 && $fullPath[$tLen + 1] != '{' && !Text::beginsWith($fullPath, '{')) {
237 238
                     //when mapped to root exclude paths that have static parts
238 239
                     //they are listed else where under that static part name
@@ -244,8 +245,9 @@  discard block
 block discarded – undo
244 245
                 }
245 246
                 foreach (static::$excludedPaths as $exclude) {
246 247
                     if (empty($exclude)) {
247
-                        if ($fullPath == $exclude)
248
-                            continue 2;
248
+                        if ($fullPath == $exclude) {
249
+                                                    continue 2;
250
+                        }
249 251
                     } elseif (Text::beginsWith($fullPath, $exclude)) {
250 252
                         continue 2;
251 253
                     }
@@ -283,8 +285,9 @@  discard block
 block discarded – undo
283 285
                 }
284 286
                 $nickname = $this->_nickname($route);
285 287
                 $index = static::$placeFormatExtensionBeforeDynamicParts && $pos > 0 ? $pos : 0;
286
-                if (!empty($parts[$index]))
287
-                    $parts[$index] .= $this->formatString;
288
+                if (!empty($parts[$index])) {
289
+                                    $parts[$index] .= $this->formatString;
290
+                }
288 291
 
289 292
                 $fullPath = implode('/', $parts);
290 293
                 $description = isset(
@@ -388,8 +391,9 @@  discard block
 block discarded – undo
388 391
         if (!$count) {
389 392
             throw new RestException(404);
390 393
         }
391
-        if (!is_null($r))
392
-            $r->models = $this->_models;
394
+        if (!is_null($r)) {
395
+                    $r->models = $this->_models;
396
+        }
393 397
         usort(
394 398
             $r->apis,
395 399
             function ($a, $b) {
@@ -681,8 +685,9 @@  discard block
 block discarded – undo
681 685
             // Create default object that includes parameters to be submitted
682 686
             $defaultObject = new \StdClass();
683 687
             foreach ($this->_bodyParam['names'] as $name => $values) {
684
-                if (!$values->required)
685
-                    continue;
688
+                if (!$values->required) {
689
+                                    continue;
690
+                }
686 691
                 if (class_exists($values->dataType)) {
687 692
                     $myClassName = $values->dataType;
688 693
                     $defaultObject->$name = new $myClassName();
@@ -706,8 +711,9 @@  discard block
 block discarded – undo
706 711
         }
707 712
         $properties = array();
708 713
         if (!$instance) {
709
-            if (!class_exists($className))
710
-                return;
714
+            if (!class_exists($className)) {
715
+                            return;
716
+            }
711 717
             $instance = new $className();
712 718
         }
713 719
         $data = get_object_vars($instance);
@@ -828,8 +834,12 @@  discard block
 block discarded – undo
828 834
             }
829 835
             return 'array';
830 836
         }
831
-        if (is_bool($o)) return 'boolean';
832
-        if (is_numeric($o)) return is_float($o) ? 'float' : 'int';
837
+        if (is_bool($o)) {
838
+        	return 'boolean';
839
+        }
840
+        if (is_numeric($o)) {
841
+        	return is_float($o) ? 'float' : 'int';
842
+        }
833 843
         return 'string';
834 844
     }
835 845
 
@@ -879,8 +889,9 @@  discard block
 block discarded – undo
879 889
      */
880 890
     public function index()
881 891
     {
882
-        if (!static::$accessControlFunction && Defaults::$accessControlFunction)
883
-            static::$accessControlFunction = Defaults::$accessControlFunction;
892
+        if (!static::$accessControlFunction && Defaults::$accessControlFunction) {
893
+                    static::$accessControlFunction = Defaults::$accessControlFunction;
894
+        }
884 895
         $version = $this->restler->getRequestedApiVersion();
885 896
         $allRoutes = Util::nestedValue(Routes::toArray(), "v$version");
886 897
         $r = $this->_resourceListing();
@@ -934,8 +945,9 @@  discard block
 block discarded – undo
934 945
         foreach ($allRoutes as $fullPath => $routes) {
935 946
             $path = explode('/', $fullPath);
936 947
             $resource = isset($path[0]) ? $path[0] : '';
937
-            if ($resource == 'resources' || Text::endsWith($resource, 'index'))
938
-                continue;
948
+            if ($resource == 'resources' || Text::endsWith($resource, 'index')) {
949
+                            continue;
950
+            }
939 951
             foreach ($routes as $httpMethod => $route) {
940 952
                 if (in_array($httpMethod, static::$excludedHttpMethods)) {
941 953
                     continue;
@@ -946,8 +958,9 @@  discard block
 block discarded – undo
946 958
 
947 959
                 foreach (static::$excludedPaths as $exclude) {
948 960
                     if (empty($exclude)) {
949
-                        if ($fullPath == $exclude)
950
-                            continue 2;
961
+                        if ($fullPath == $exclude) {
962
+                                                    continue 2;
963
+                        }
951 964
                     } elseif (Text::beginsWith($fullPath, $exclude)) {
952 965
                         continue 2;
953 966
                     }
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Scope.php 2 patches
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -17,221 +17,221 @@
 block discarded – undo
17 17
  */
18 18
 class Scope
19 19
 {
20
-    public static $classAliases = array(
21
-
22
-        //Core
23
-        'Restler'            => 'Luracast\Restler\Restler',
24
-
25
-        //Format classes
26
-        'AmfFormat'          => 'Luracast\Restler\Format\AmfFormat',
27
-        'JsFormat'           => 'Luracast\Restler\Format\JsFormat',
28
-        'JsonFormat'         => 'Luracast\Restler\Format\JsonFormat',
29
-        'HtmlFormat'         => 'Luracast\Restler\Format\HtmlFormat',
30
-        'PlistFormat'        => 'Luracast\Restler\Format\PlistFormat',
31
-        'UploadFormat'       => 'Luracast\Restler\Format\UploadFormat',
32
-        'UrlEncodedFormat'   => 'Luracast\Restler\Format\UrlEncodedFormat',
33
-        'XmlFormat'          => 'Luracast\Restler\Format\XmlFormat',
34
-        'YamlFormat'         => 'Luracast\Restler\Format\YamlFormat',
35
-        'CsvFormat'          => 'Luracast\Restler\Format\CsvFormat',
36
-        'TsvFormat'          => 'Luracast\Restler\Format\TsvFormat',
37
-
38
-        //Filter classes
39
-        'RateLimit'          => 'Luracast\Restler\Filter\RateLimit',
40
-
41
-        //UI classes
42
-        'Forms'              => 'Luracast\Restler\UI\Forms',
43
-        'Nav'                => 'Luracast\Restler\UI\Nav',
44
-        'Emmet'              => 'Luracast\Restler\UI\Emmet',
45
-        'T'                  => 'Luracast\Restler\UI\Tags',
46
-
47
-        //API classes
48
-        'Resources'          => 'Luracast\Restler\Resources',
49
-        'Explorer'           => 'Luracast\Restler\Explorer\v2\Explorer',
50
-        'Explorer1'          => 'Luracast\Restler\Explorer\v1\Explorer',
51
-        'Explorer2'          => 'Luracast\Restler\Explorer\v2\Explorer',
52
-
53
-        //Cache classes
54
-        'HumanReadableCache' => 'Luracast\Restler\HumanReadableCache',
55
-        'ApcCache'           => 'Luracast\Restler\ApcCache',
56
-        'MemcacheCache'      => 'Luracast\Restler\MemcacheCache',
57
-
58
-        //Utility classes
59
-        'Object'             => 'Luracast\Restler\Data\Obj',
60
-        'Text'               => 'Luracast\Restler\Data\Text',
61
-        'Arr'                => 'Luracast\Restler\Data\Arr',
62
-
63
-        //Exception
64
-        'RestException'      => 'Luracast\Restler\RestException'
65
-    );
66
-    /**
67
-     * @var null|Callable adding a resolver function that accepts
68
-     * the class name as the parameter and returns an instance of the class
69
-     * as a singleton. Allows the use of your favourite DI container
70
-     */
71
-    public static $resolver = null;
72
-    public static $properties = array();
73
-    protected static $instances = array();
74
-    protected static $registry = array();
75
-
76
-    /**
77
-     * @param string   $name
78
-     * @param callable $function
79
-     * @param bool     $singleton
80
-     */
81
-    public static function register($name, $function, $singleton = true)
82
-    {
83
-        static::$registry[$name] = (object)compact('function', 'singleton');
84
-    }
85
-
86
-    public static function set($name, $instance)
87
-    {
88
-        static::$instances[$name] = (object)array('instance' => $instance);
89
-    }
90
-
91
-    public static function get($name)
92
-    {
93
-        $r = null;
94
-        $initialized = false;
95
-        $properties = array();
96
-        if (array_key_exists($name, static::$instances)) {
97
-            $initialized = true;
98
-            $r = static::$instances[$name]->instance;
99
-        } elseif (!empty(static::$registry[$name])) {
100
-            $function = static::$registry[$name]->function;
101
-            $r = $function();
102
-            if (static::$registry[$name]->singleton) {
103
-                static::$instances[$name] = (object)array('instance' => $r);
104
-            }
105
-        } elseif (is_callable(static::$resolver) && false === stristr($name, 'Luracast\Restler')) {
106
-            $fullName = $name;
107
-            if (isset(static::$classAliases[$name])) {
108
-                $fullName = static::$classAliases[$name];
109
-            }
110
-            /** @var Callable $function */
111
-            $function = static::$resolver;
112
-            $r = $function($fullName);
113
-            static::$instances[$name] = (object)array('instance' => $r);
114
-            static::$instances[$name]->initPending = true;
115
-        } else {
116
-            $fullName = $name;
117
-            if (isset(static::$classAliases[$name])) {
118
-                $fullName = static::$classAliases[$name];
119
-            }
120
-            if (class_exists($fullName)) {
121
-                $shortName = Util::getShortName($name);
122
-                $r = new $fullName();
123
-                static::$instances[$name] = (object)array('instance' => $r);
124
-                if ($name != 'Restler') {
125
-                    /** @var Restler restler */
126
-                    $r->restler = static::get('Restler');
127
-                    $m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
128
-                    if ($m) {
129
-                        $properties = Util::nestedValue(
130
-                            $m, 'class', $fullName,
131
-                            CommentParser::$embeddedDataName
132
-                        ) ?: (Util::nestedValue(
133
-                            $m, 'class', $shortName,
134
-                            CommentParser::$embeddedDataName
135
-                        ) ?: array());
136
-                    } else {
137
-                        static::$instances[$name]->initPending = true;
138
-                    }
139
-                }
140
-            }
141
-        }
142
-        if (
143
-            $r instanceof iUseAuthentication &&
144
-            $r->restler && $r->restler->_authVerified &&
145
-            !isset(static::$instances[$name]->authVerified)
146
-        ) {
147
-            static::$instances[$name]->authVerified = true;
148
-            $r->__setAuthenticationStatus($r->restler->_authenticated);
149
-        }
150
-        if (isset(static::$instances[$name]->initPending)) {
151
-            $m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
152
-            $fullName = $name;
153
-            if (class_exists($name)) {
154
-                $shortName = Util::getShortName($name);
155
-            } else {
156
-                $shortName = $name;
157
-                if (isset(static::$classAliases[$name])) {
158
-                    $fullName = static::$classAliases[$name];
159
-                }
160
-            }
161
-            if ($m) {
162
-                $properties = Util::nestedValue(
163
-                    $m, 'class', $fullName,
164
-                    CommentParser::$embeddedDataName
165
-                ) ?: (Util::nestedValue(
166
-                    $m, 'class', $shortName,
167
-                    CommentParser::$embeddedDataName
168
-                ) ?: array());
169
-                unset(static::$instances[$name]->initPending);
170
-                $initialized = false;
171
-            }
172
-        }
173
-        if (!$initialized && is_object($r)) {
174
-            $properties += static::$properties;
175
-            $objectVars = get_object_vars($r);
176
-            $className = get_class($r);
177
-            foreach ($properties as $property => $value) {
178
-                if (property_exists($className, $property)) {
179
-                    //if not a static property
180
-                    array_key_exists($property, $objectVars)
181
-                        ? $r->{$property} = $value
182
-                        : $r::$$property = $value;
183
-                }
184
-            }
185
-        }
186
-        return $r;
187
-    }
188
-
189
-    /**
190
-     * Get fully qualified class name for the given scope
191
-     *
192
-     * @param string $className
193
-     * @param array  $scope local scope
194
-     *
195
-     * @return string|boolean returns the class name or false
196
-     */
197
-    public static function resolve($className, array $scope)
198
-    {
199
-        if (empty($className) || !is_string($className)) {
200
-            return false;
201
-        }
202
-
203
-        if (self::isPrimitiveDataType($className)) {
204
-            return false;
205
-        }
206
-
207
-        $divider = '\\';
208
-        if ($className[0] == $divider) {
209
-            $qualified = trim($className, $divider);
210
-        } elseif (array_key_exists($className, $scope)) {
211
-            $qualified = $scope[$className];
212
-        } else {
213
-            $qualified = $scope['*'] . $className;
214
-        }
215
-        if (class_exists($qualified)) {
216
-            return $qualified;
217
-        }
218
-        if (isset(static::$classAliases[$className])) {
219
-            $qualified = static::$classAliases[$className];
220
-            if (class_exists($qualified)) {
221
-                return $qualified;
222
-            }
223
-        }
224
-        return false;
225
-    }
226
-
227
-    /**
228
-     * @param string $stringName
229
-     *
230
-     * @return boolean
231
-     */
232
-    private static function isPrimitiveDataType($stringName)
233
-    {
234
-        $primitiveDataTypes = array('Array', 'array', 'bool', 'boolean', 'float', 'int', 'integer', 'string');
235
-        return in_array($stringName, $primitiveDataTypes);
236
-    }
20
+	public static $classAliases = array(
21
+
22
+		//Core
23
+		'Restler'            => 'Luracast\Restler\Restler',
24
+
25
+		//Format classes
26
+		'AmfFormat'          => 'Luracast\Restler\Format\AmfFormat',
27
+		'JsFormat'           => 'Luracast\Restler\Format\JsFormat',
28
+		'JsonFormat'         => 'Luracast\Restler\Format\JsonFormat',
29
+		'HtmlFormat'         => 'Luracast\Restler\Format\HtmlFormat',
30
+		'PlistFormat'        => 'Luracast\Restler\Format\PlistFormat',
31
+		'UploadFormat'       => 'Luracast\Restler\Format\UploadFormat',
32
+		'UrlEncodedFormat'   => 'Luracast\Restler\Format\UrlEncodedFormat',
33
+		'XmlFormat'          => 'Luracast\Restler\Format\XmlFormat',
34
+		'YamlFormat'         => 'Luracast\Restler\Format\YamlFormat',
35
+		'CsvFormat'          => 'Luracast\Restler\Format\CsvFormat',
36
+		'TsvFormat'          => 'Luracast\Restler\Format\TsvFormat',
37
+
38
+		//Filter classes
39
+		'RateLimit'          => 'Luracast\Restler\Filter\RateLimit',
40
+
41
+		//UI classes
42
+		'Forms'              => 'Luracast\Restler\UI\Forms',
43
+		'Nav'                => 'Luracast\Restler\UI\Nav',
44
+		'Emmet'              => 'Luracast\Restler\UI\Emmet',
45
+		'T'                  => 'Luracast\Restler\UI\Tags',
46
+
47
+		//API classes
48
+		'Resources'          => 'Luracast\Restler\Resources',
49
+		'Explorer'           => 'Luracast\Restler\Explorer\v2\Explorer',
50
+		'Explorer1'          => 'Luracast\Restler\Explorer\v1\Explorer',
51
+		'Explorer2'          => 'Luracast\Restler\Explorer\v2\Explorer',
52
+
53
+		//Cache classes
54
+		'HumanReadableCache' => 'Luracast\Restler\HumanReadableCache',
55
+		'ApcCache'           => 'Luracast\Restler\ApcCache',
56
+		'MemcacheCache'      => 'Luracast\Restler\MemcacheCache',
57
+
58
+		//Utility classes
59
+		'Object'             => 'Luracast\Restler\Data\Obj',
60
+		'Text'               => 'Luracast\Restler\Data\Text',
61
+		'Arr'                => 'Luracast\Restler\Data\Arr',
62
+
63
+		//Exception
64
+		'RestException'      => 'Luracast\Restler\RestException'
65
+	);
66
+	/**
67
+	 * @var null|Callable adding a resolver function that accepts
68
+	 * the class name as the parameter and returns an instance of the class
69
+	 * as a singleton. Allows the use of your favourite DI container
70
+	 */
71
+	public static $resolver = null;
72
+	public static $properties = array();
73
+	protected static $instances = array();
74
+	protected static $registry = array();
75
+
76
+	/**
77
+	 * @param string   $name
78
+	 * @param callable $function
79
+	 * @param bool     $singleton
80
+	 */
81
+	public static function register($name, $function, $singleton = true)
82
+	{
83
+		static::$registry[$name] = (object)compact('function', 'singleton');
84
+	}
85
+
86
+	public static function set($name, $instance)
87
+	{
88
+		static::$instances[$name] = (object)array('instance' => $instance);
89
+	}
90
+
91
+	public static function get($name)
92
+	{
93
+		$r = null;
94
+		$initialized = false;
95
+		$properties = array();
96
+		if (array_key_exists($name, static::$instances)) {
97
+			$initialized = true;
98
+			$r = static::$instances[$name]->instance;
99
+		} elseif (!empty(static::$registry[$name])) {
100
+			$function = static::$registry[$name]->function;
101
+			$r = $function();
102
+			if (static::$registry[$name]->singleton) {
103
+				static::$instances[$name] = (object)array('instance' => $r);
104
+			}
105
+		} elseif (is_callable(static::$resolver) && false === stristr($name, 'Luracast\Restler')) {
106
+			$fullName = $name;
107
+			if (isset(static::$classAliases[$name])) {
108
+				$fullName = static::$classAliases[$name];
109
+			}
110
+			/** @var Callable $function */
111
+			$function = static::$resolver;
112
+			$r = $function($fullName);
113
+			static::$instances[$name] = (object)array('instance' => $r);
114
+			static::$instances[$name]->initPending = true;
115
+		} else {
116
+			$fullName = $name;
117
+			if (isset(static::$classAliases[$name])) {
118
+				$fullName = static::$classAliases[$name];
119
+			}
120
+			if (class_exists($fullName)) {
121
+				$shortName = Util::getShortName($name);
122
+				$r = new $fullName();
123
+				static::$instances[$name] = (object)array('instance' => $r);
124
+				if ($name != 'Restler') {
125
+					/** @var Restler restler */
126
+					$r->restler = static::get('Restler');
127
+					$m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
128
+					if ($m) {
129
+						$properties = Util::nestedValue(
130
+							$m, 'class', $fullName,
131
+							CommentParser::$embeddedDataName
132
+						) ?: (Util::nestedValue(
133
+							$m, 'class', $shortName,
134
+							CommentParser::$embeddedDataName
135
+						) ?: array());
136
+					} else {
137
+						static::$instances[$name]->initPending = true;
138
+					}
139
+				}
140
+			}
141
+		}
142
+		if (
143
+			$r instanceof iUseAuthentication &&
144
+			$r->restler && $r->restler->_authVerified &&
145
+			!isset(static::$instances[$name]->authVerified)
146
+		) {
147
+			static::$instances[$name]->authVerified = true;
148
+			$r->__setAuthenticationStatus($r->restler->_authenticated);
149
+		}
150
+		if (isset(static::$instances[$name]->initPending)) {
151
+			$m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
152
+			$fullName = $name;
153
+			if (class_exists($name)) {
154
+				$shortName = Util::getShortName($name);
155
+			} else {
156
+				$shortName = $name;
157
+				if (isset(static::$classAliases[$name])) {
158
+					$fullName = static::$classAliases[$name];
159
+				}
160
+			}
161
+			if ($m) {
162
+				$properties = Util::nestedValue(
163
+					$m, 'class', $fullName,
164
+					CommentParser::$embeddedDataName
165
+				) ?: (Util::nestedValue(
166
+					$m, 'class', $shortName,
167
+					CommentParser::$embeddedDataName
168
+				) ?: array());
169
+				unset(static::$instances[$name]->initPending);
170
+				$initialized = false;
171
+			}
172
+		}
173
+		if (!$initialized && is_object($r)) {
174
+			$properties += static::$properties;
175
+			$objectVars = get_object_vars($r);
176
+			$className = get_class($r);
177
+			foreach ($properties as $property => $value) {
178
+				if (property_exists($className, $property)) {
179
+					//if not a static property
180
+					array_key_exists($property, $objectVars)
181
+						? $r->{$property} = $value
182
+						: $r::$$property = $value;
183
+				}
184
+			}
185
+		}
186
+		return $r;
187
+	}
188
+
189
+	/**
190
+	 * Get fully qualified class name for the given scope
191
+	 *
192
+	 * @param string $className
193
+	 * @param array  $scope local scope
194
+	 *
195
+	 * @return string|boolean returns the class name or false
196
+	 */
197
+	public static function resolve($className, array $scope)
198
+	{
199
+		if (empty($className) || !is_string($className)) {
200
+			return false;
201
+		}
202
+
203
+		if (self::isPrimitiveDataType($className)) {
204
+			return false;
205
+		}
206
+
207
+		$divider = '\\';
208
+		if ($className[0] == $divider) {
209
+			$qualified = trim($className, $divider);
210
+		} elseif (array_key_exists($className, $scope)) {
211
+			$qualified = $scope[$className];
212
+		} else {
213
+			$qualified = $scope['*'] . $className;
214
+		}
215
+		if (class_exists($qualified)) {
216
+			return $qualified;
217
+		}
218
+		if (isset(static::$classAliases[$className])) {
219
+			$qualified = static::$classAliases[$className];
220
+			if (class_exists($qualified)) {
221
+				return $qualified;
222
+			}
223
+		}
224
+		return false;
225
+	}
226
+
227
+	/**
228
+	 * @param string $stringName
229
+	 *
230
+	 * @return boolean
231
+	 */
232
+	private static function isPrimitiveDataType($stringName)
233
+	{
234
+		$primitiveDataTypes = array('Array', 'array', 'bool', 'boolean', 'float', 'int', 'integer', 'string');
235
+		return in_array($stringName, $primitiveDataTypes);
236
+	}
237 237
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -80,12 +80,12 @@  discard block
 block discarded – undo
80 80
      */
81 81
     public static function register($name, $function, $singleton = true)
82 82
     {
83
-        static::$registry[$name] = (object)compact('function', 'singleton');
83
+        static::$registry[$name] = (object) compact('function', 'singleton');
84 84
     }
85 85
 
86 86
     public static function set($name, $instance)
87 87
     {
88
-        static::$instances[$name] = (object)array('instance' => $instance);
88
+        static::$instances[$name] = (object) array('instance' => $instance);
89 89
     }
90 90
 
91 91
     public static function get($name)
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
             $function = static::$registry[$name]->function;
101 101
             $r = $function();
102 102
             if (static::$registry[$name]->singleton) {
103
-                static::$instances[$name] = (object)array('instance' => $r);
103
+                static::$instances[$name] = (object) array('instance' => $r);
104 104
             }
105 105
         } elseif (is_callable(static::$resolver) && false === stristr($name, 'Luracast\Restler')) {
106 106
             $fullName = $name;
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
             /** @var Callable $function */
111 111
             $function = static::$resolver;
112 112
             $r = $function($fullName);
113
-            static::$instances[$name] = (object)array('instance' => $r);
113
+            static::$instances[$name] = (object) array('instance' => $r);
114 114
             static::$instances[$name]->initPending = true;
115 115
         } else {
116 116
             $fullName = $name;
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
             if (class_exists($fullName)) {
121 121
                 $shortName = Util::getShortName($name);
122 122
                 $r = new $fullName();
123
-                static::$instances[$name] = (object)array('instance' => $r);
123
+                static::$instances[$name] = (object) array('instance' => $r);
124 124
                 if ($name != 'Restler') {
125 125
                     /** @var Restler restler */
126 126
                     $r->restler = static::get('Restler');
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
         } elseif (array_key_exists($className, $scope)) {
211 211
             $qualified = $scope[$className];
212 212
         } else {
213
-            $qualified = $scope['*'] . $className;
213
+            $qualified = $scope['*'].$className;
214 214
         }
215 215
         if (class_exists($qualified)) {
216 216
             return $qualified;
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/RestException.php 2 patches
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -80,10 +80,10 @@  discard block
 block discarded – undo
80 80
     public function __construct($httpStatusCode, $errorMessage = null, array $details = array(), Exception $previous = null)
81 81
     {
82 82
         $events = Scope::get('Restler')->getEvents();
83
-        if(count($events)<= 1){
83
+        if (count($events) <= 1) {
84 84
             $this->stage = 'setup';
85 85
         } else {
86
-            $this->stage = $previous ? $events[count($events)-2] : end($events);
86
+            $this->stage = $previous ? $events[count($events) - 2] : end($events);
87 87
         }
88 88
         $this->details = $details;
89 89
         parent::__construct($errorMessage, $httpStatusCode, $previous);
@@ -119,8 +119,8 @@  discard block
 block discarded – undo
119 119
         $statusCode = $this->getCode();
120 120
         $message = $this->getMessage();
121 121
         if (isset(RestException::$codes[$statusCode])) {
122
-            $message = RestException::$codes[$statusCode] .
123
-                (empty($message) ? '' : ': ' . $message);
122
+            $message = RestException::$codes[$statusCode].
123
+                (empty($message) ? '' : ': '.$message);
124 124
         }
125 125
         return $message;
126 126
     }
@@ -131,9 +131,9 @@  discard block
 block discarded – undo
131 131
         while ($e->getPrevious()) {
132 132
             $e = $e->getPrevious();
133 133
         }
134
-        return basename($e->getFile()) . ':'
135
-        . $e->getLine() . ' at '
136
-        . $this->getStage() . ' stage';
134
+        return basename($e->getFile()).':'
135
+        . $e->getLine().' at '
136
+        . $this->getStage().' stage';
137 137
     }
138 138
 }
139 139
 
Please login to merge, or discard this patch.
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -19,120 +19,120 @@
 block discarded – undo
19 19
 
20 20
 class RestException extends Exception
21 21
 {
22
-    /**
23
-     * HTTP status codes
24
-     *
25
-     * @var array
26
-     */
27
-    public static $codes = array(
28
-        100 => 'Continue',
29
-        101 => 'Switching Protocols',
30
-        200 => 'OK',
31
-        201 => 'Created',
32
-        202 => 'Accepted',
33
-        203 => 'Non-Authoritative Information',
34
-        204 => 'No Content',
35
-        205 => 'Reset Content',
36
-        206 => 'Partial Content',
37
-        300 => 'Multiple Choices',
38
-        301 => 'Moved Permanently',
39
-        302 => 'Found',
40
-        303 => 'See Other',
41
-        304 => 'Not Modified',
42
-        305 => 'Use Proxy',
43
-        306 => '(Unused)',
44
-        307 => 'Temporary Redirect',
45
-        400 => 'Bad Request',
46
-        401 => 'Unauthorized',
47
-        402 => 'Payment Required',
48
-        403 => 'Forbidden',
49
-        404 => 'Not Found',
50
-        405 => 'Method Not Allowed',
51
-        406 => 'Not Acceptable',
52
-        407 => 'Proxy Authentication Required',
53
-        408 => 'Request Timeout',
54
-        409 => 'Conflict',
55
-        410 => 'Gone',
56
-        411 => 'Length Required',
57
-        412 => 'Precondition Failed',
58
-        413 => 'Request Entity Too Large',
59
-        414 => 'Request-URI Too Long',
60
-        415 => 'Unsupported Media Type',
61
-        416 => 'Requested Range Not Satisfiable',
62
-        417 => 'Expectation Failed',
63
-        429 => 'Too Many Requests', //still in draft but used for rate limiting
64
-        500 => 'Internal Server Error',
65
-        501 => 'Not Implemented',
66
-        502 => 'Bad Gateway',
67
-        503 => 'Service Unavailable',
68
-        504 => 'Gateway Timeout',
69
-        505 => 'HTTP Version Not Supported'
70
-    );
71
-    private $details;
72
-    private $stage;
22
+	/**
23
+	 * HTTP status codes
24
+	 *
25
+	 * @var array
26
+	 */
27
+	public static $codes = array(
28
+		100 => 'Continue',
29
+		101 => 'Switching Protocols',
30
+		200 => 'OK',
31
+		201 => 'Created',
32
+		202 => 'Accepted',
33
+		203 => 'Non-Authoritative Information',
34
+		204 => 'No Content',
35
+		205 => 'Reset Content',
36
+		206 => 'Partial Content',
37
+		300 => 'Multiple Choices',
38
+		301 => 'Moved Permanently',
39
+		302 => 'Found',
40
+		303 => 'See Other',
41
+		304 => 'Not Modified',
42
+		305 => 'Use Proxy',
43
+		306 => '(Unused)',
44
+		307 => 'Temporary Redirect',
45
+		400 => 'Bad Request',
46
+		401 => 'Unauthorized',
47
+		402 => 'Payment Required',
48
+		403 => 'Forbidden',
49
+		404 => 'Not Found',
50
+		405 => 'Method Not Allowed',
51
+		406 => 'Not Acceptable',
52
+		407 => 'Proxy Authentication Required',
53
+		408 => 'Request Timeout',
54
+		409 => 'Conflict',
55
+		410 => 'Gone',
56
+		411 => 'Length Required',
57
+		412 => 'Precondition Failed',
58
+		413 => 'Request Entity Too Large',
59
+		414 => 'Request-URI Too Long',
60
+		415 => 'Unsupported Media Type',
61
+		416 => 'Requested Range Not Satisfiable',
62
+		417 => 'Expectation Failed',
63
+		429 => 'Too Many Requests', //still in draft but used for rate limiting
64
+		500 => 'Internal Server Error',
65
+		501 => 'Not Implemented',
66
+		502 => 'Bad Gateway',
67
+		503 => 'Service Unavailable',
68
+		504 => 'Gateway Timeout',
69
+		505 => 'HTTP Version Not Supported'
70
+	);
71
+	private $details;
72
+	private $stage;
73 73
 
74
-    /**
75
-     * @param int         $httpStatusCode http status code
76
-     * @param string|null $errorMessage   error message
77
-     * @param array       $details        any extra detail about the exception
78
-     * @param Exception   $previous       previous exception if any
79
-     */
80
-    public function __construct($httpStatusCode, $errorMessage = null, array $details = array(), Exception $previous = null)
81
-    {
82
-        $events = Scope::get('Restler')->getEvents();
83
-        if(count($events)<= 1){
84
-            $this->stage = 'setup';
85
-        } else {
86
-            $this->stage = $previous ? $events[count($events)-2] : end($events);
87
-        }
88
-        $this->details = $details;
89
-        parent::__construct($errorMessage, $httpStatusCode, $previous);
90
-    }
74
+	/**
75
+	 * @param int         $httpStatusCode http status code
76
+	 * @param string|null $errorMessage   error message
77
+	 * @param array       $details        any extra detail about the exception
78
+	 * @param Exception   $previous       previous exception if any
79
+	 */
80
+	public function __construct($httpStatusCode, $errorMessage = null, array $details = array(), Exception $previous = null)
81
+	{
82
+		$events = Scope::get('Restler')->getEvents();
83
+		if(count($events)<= 1){
84
+			$this->stage = 'setup';
85
+		} else {
86
+			$this->stage = $previous ? $events[count($events)-2] : end($events);
87
+		}
88
+		$this->details = $details;
89
+		parent::__construct($errorMessage, $httpStatusCode, $previous);
90
+	}
91 91
 
92
-    /**
93
-     * Get extra details about the exception
94
-     *
95
-     * @return array details array
96
-     */
97
-    public function getDetails()
98
-    {
99
-        return $this->details;
100
-    }
92
+	/**
93
+	 * Get extra details about the exception
94
+	 *
95
+	 * @return array details array
96
+	 */
97
+	public function getDetails()
98
+	{
99
+		return $this->details;
100
+	}
101 101
 
102
-    public function getStage()
103
-    {
104
-        return $this->stage;
105
-    }
102
+	public function getStage()
103
+	{
104
+		return $this->stage;
105
+	}
106 106
 
107
-    public function getStages()
108
-    {
109
-        $e = Scope::get('Restler')->getEvents();
110
-        $i = array_search($this->stage, $e);
111
-        return array(
112
-            'success' => array_slice($e, 0, $i),
113
-            'failure' => array_slice($e, $i),
114
-        );
115
-    }
107
+	public function getStages()
108
+	{
109
+		$e = Scope::get('Restler')->getEvents();
110
+		$i = array_search($this->stage, $e);
111
+		return array(
112
+			'success' => array_slice($e, 0, $i),
113
+			'failure' => array_slice($e, $i),
114
+		);
115
+	}
116 116
 
117
-    public function getErrorMessage()
118
-    {
119
-        $statusCode = $this->getCode();
120
-        $message = $this->getMessage();
121
-        if (isset(RestException::$codes[$statusCode])) {
122
-            $message = RestException::$codes[$statusCode] .
123
-                (empty($message) ? '' : ': ' . $message);
124
-        }
125
-        return $message;
126
-    }
117
+	public function getErrorMessage()
118
+	{
119
+		$statusCode = $this->getCode();
120
+		$message = $this->getMessage();
121
+		if (isset(RestException::$codes[$statusCode])) {
122
+			$message = RestException::$codes[$statusCode] .
123
+				(empty($message) ? '' : ': ' . $message);
124
+		}
125
+		return $message;
126
+	}
127 127
 
128
-    public function getSource()
129
-    {
130
-        $e = $this;
131
-        while ($e->getPrevious()) {
132
-            $e = $e->getPrevious();
133
-        }
134
-        return basename($e->getFile()) . ':'
135
-        . $e->getLine() . ' at '
136
-        . $this->getStage() . ' stage';
137
-    }
128
+	public function getSource()
129
+	{
130
+		$e = $this;
131
+		while ($e->getPrevious()) {
132
+			$e = $e->getPrevious();
133
+		}
134
+		return basename($e->getFile()) . ':'
135
+		. $e->getLine() . ' at '
136
+		. $this->getStage() . ' stage';
137
+	}
138 138
 }
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/iUseAuthentication.php 2 patches
Indentation   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -15,18 +15,18 @@
 block discarded – undo
15 15
  */
16 16
 interface iUseAuthentication
17 17
 {
18
-    /**
19
-     * This method will be called first for filter classes and api classes so
20
-     * that they can respond accordingly for filer method call and api method
21
-     * calls
22
-     *
23
-     * @abstract
24
-     *
25
-     * @param bool $isAuthenticated passes true when the authentication is
26
-     * done false otherwise
27
-     *
28
-     * @return mixed
29
-     */
30
-    public function __setAuthenticationStatus($isAuthenticated=false);
18
+	/**
19
+	 * This method will be called first for filter classes and api classes so
20
+	 * that they can respond accordingly for filer method call and api method
21
+	 * calls
22
+	 *
23
+	 * @abstract
24
+	 *
25
+	 * @param bool $isAuthenticated passes true when the authentication is
26
+	 * done false otherwise
27
+	 *
28
+	 * @return mixed
29
+	 */
30
+	public function __setAuthenticationStatus($isAuthenticated=false);
31 31
 }
32 32
 
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -27,6 +27,6 @@
 block discarded – undo
27 27
      *
28 28
      * @return mixed
29 29
      */
30
-    public function __setAuthenticationStatus($isAuthenticated=false);
30
+    public function __setAuthenticationStatus($isAuthenticated = false);
31 31
 }
32 32
 
Please login to merge, or discard this patch.
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.