Completed
Branch develop (aa6d31)
by
unknown
24:05
created
htdocs/includes/restler/framework/Luracast/Restler/Data/iValidate.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -14,19 +14,19 @@
 block discarded – undo
14 14
  */
15 15
 interface iValidate {
16 16
 
17
-    /**
18
-     * method used for validation.
19
-     *
20
-     * @param mixed $input
21
-     *            data that needs to be validated
22
-     * @param ValidationInfo $info
23
-     *            information to be used for validation
24
-     * @return boolean false in case of failure or fixed value in the expected
25
-     *         type
26
-     * @throws \Luracast\Restler\RestException 400 with information about the
27
-     * failed
28
-     * validation
29
-     */
30
-    public static function validate($input, ValidationInfo $info);
17
+	/**
18
+	 * method used for validation.
19
+	 *
20
+	 * @param mixed $input
21
+	 *            data that needs to be validated
22
+	 * @param ValidationInfo $info
23
+	 *            information to be used for validation
24
+	 * @return boolean false in case of failure or fixed value in the expected
25
+	 *         type
26
+	 * @throws \Luracast\Restler\RestException 400 with information about the
27
+	 * failed
28
+	 * validation
29
+	 */
30
+	public static function validate($input, ValidationInfo $info);
31 31
 }
32 32
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/Obj.php 1 patch
Indentation   +132 added lines, -132 removed lines patch added patch discarded remove patch
@@ -15,143 +15,143 @@
 block discarded – undo
15 15
  */
16 16
 class Obj
17 17
 {
18
-    /**
19
-     * @var bool|string|callable
20
-     */
21
-    public static $stringEncoderFunction = false;
22
-    /**
23
-     * @var bool|string|callable
24
-     */
25
-    public static $numberEncoderFunction = false;
26
-    /**
27
-     * @var array key value pairs for fixing value types using functions.
28
-     * For example
29
-     *
30
-     *      'id'=>'intval'      will make sure all values of the id properties
31
-     *                          will be converted to integers intval function
32
-     *      'password'=> null   will remove all the password entries
33
-     */
34
-    public static $fix = array();
35
-    /**
36
-     * @var string character that is used to identify sub objects
37
-     *
38
-     * For example
39
-     *
40
-     * when Object::$separatorChar = '.';
41
-     *
42
-     * array('my.object'=>true) will result in
43
-     *
44
-     * array(
45
-     *    'my'=>array('object'=>true)
46
-     * );
47
-     */
48
-    public static $separatorChar = null;
49
-    /**
50
-     * @var bool set it to true when empty arrays, blank strings, null values
51
-     * to be automatically removed from response
52
-     */
53
-    public static $removeEmpty = false;
54
-    /**
55
-     * @var bool set it to true to remove all null values from the result
56
-     */
57
-    public static $removeNull = false;
18
+	/**
19
+	 * @var bool|string|callable
20
+	 */
21
+	public static $stringEncoderFunction = false;
22
+	/**
23
+	 * @var bool|string|callable
24
+	 */
25
+	public static $numberEncoderFunction = false;
26
+	/**
27
+	 * @var array key value pairs for fixing value types using functions.
28
+	 * For example
29
+	 *
30
+	 *      'id'=>'intval'      will make sure all values of the id properties
31
+	 *                          will be converted to integers intval function
32
+	 *      'password'=> null   will remove all the password entries
33
+	 */
34
+	public static $fix = array();
35
+	/**
36
+	 * @var string character that is used to identify sub objects
37
+	 *
38
+	 * For example
39
+	 *
40
+	 * when Object::$separatorChar = '.';
41
+	 *
42
+	 * array('my.object'=>true) will result in
43
+	 *
44
+	 * array(
45
+	 *    'my'=>array('object'=>true)
46
+	 * );
47
+	 */
48
+	public static $separatorChar = null;
49
+	/**
50
+	 * @var bool set it to true when empty arrays, blank strings, null values
51
+	 * to be automatically removed from response
52
+	 */
53
+	public static $removeEmpty = false;
54
+	/**
55
+	 * @var bool set it to true to remove all null values from the result
56
+	 */
57
+	public static $removeNull = false;
58 58
 
59
-    /**
60
-     * Convenience function that converts the given object
61
-     * in to associative array
62
-     *
63
-     * @static
64
-     *
65
-     * @param mixed $object                          that needs to be converted
66
-     *
67
-     * @param bool  $forceObjectTypeWhenEmpty        when set to true outputs
68
-     *                                               actual type  (array or
69
-     *                                               object) rather than
70
-     *                                               always an array when the
71
-     *                                               array/object is empty
72
-     *
73
-     * @return array
74
-     */
75
-    public static function toArray($object,
76
-                                   $forceObjectTypeWhenEmpty = false)
77
-    {
78
-        //if ($object instanceof JsonSerializable) { //wont work on PHP < 5.4
79
-        if (is_object($object)) {
80
-            if (method_exists($object, 'jsonSerialize')) {
81
-                $object = $object->jsonSerialize();
82
-            } elseif (method_exists($object, '__sleep')) {
83
-                $properties = $object->__sleep();
84
-                $array = array();
85
-                foreach ($properties as $key) {
86
-                    $value = self::toArray($object->{$key},
87
-                        $forceObjectTypeWhenEmpty);
88
-                    if (self::$stringEncoderFunction && is_string($value)) {
89
-                        $value = self::$stringEncoderFunction ($value);
90
-                    } elseif (self::$numberEncoderFunction && is_numeric($value)) {
91
-                        $value = self::$numberEncoderFunction ($value);
92
-                    }
93
-                    $array [$key] = $value;
94
-                }
95
-                return $array;
96
-            }
97
-        }
98
-        if (is_array($object) || is_object($object)) {
99
-            $count = 0;
100
-            $array = array();
101
-            foreach ($object as $key => $value) {
102
-                if (
103
-                    is_string(self::$separatorChar) &&
104
-                    false !== strpos($key, self::$separatorChar)
105
-                ) {
106
-                    list($key, $obj) = explode(self::$separatorChar, $key, 2);
107
-                    $object[$key][$obj] = $value;
108
-                    $value = $object[$key];
109
-                }
110
-                if (self::$removeEmpty && empty($value) && !is_numeric($value) && !is_bool($value)) {
111
-                    continue;
112
-                } elseif (self::$removeNull && is_null($value)) {
113
-                    continue;
114
-                }
115
-                if (array_key_exists($key, self::$fix)) {
116
-                    if (isset(self::$fix[$key])) {
117
-                        $value = call_user_func(self::$fix[$key], $value);
118
-                    } else {
119
-                        continue;
120
-                    }
121
-                }
122
-                $value = self::toArray($value, $forceObjectTypeWhenEmpty);
123
-                if (self::$stringEncoderFunction && is_string($value)) {
124
-                    $value = self::$encoderFunctionName ($value);
125
-                } elseif (self::$numberEncoderFunction && is_numeric($value)) {
126
-                    $value = self::$numberEncoderFunction ($value);
127
-                }
128
-                $array [$key] = $value;
129
-                $count++;
130
-            }
131
-            return $forceObjectTypeWhenEmpty && $count == 0 ? $object : $array;
132
-        }
59
+	/**
60
+	 * Convenience function that converts the given object
61
+	 * in to associative array
62
+	 *
63
+	 * @static
64
+	 *
65
+	 * @param mixed $object                          that needs to be converted
66
+	 *
67
+	 * @param bool  $forceObjectTypeWhenEmpty        when set to true outputs
68
+	 *                                               actual type  (array or
69
+	 *                                               object) rather than
70
+	 *                                               always an array when the
71
+	 *                                               array/object is empty
72
+	 *
73
+	 * @return array
74
+	 */
75
+	public static function toArray($object,
76
+								   $forceObjectTypeWhenEmpty = false)
77
+	{
78
+		//if ($object instanceof JsonSerializable) { //wont work on PHP < 5.4
79
+		if (is_object($object)) {
80
+			if (method_exists($object, 'jsonSerialize')) {
81
+				$object = $object->jsonSerialize();
82
+			} elseif (method_exists($object, '__sleep')) {
83
+				$properties = $object->__sleep();
84
+				$array = array();
85
+				foreach ($properties as $key) {
86
+					$value = self::toArray($object->{$key},
87
+						$forceObjectTypeWhenEmpty);
88
+					if (self::$stringEncoderFunction && is_string($value)) {
89
+						$value = self::$stringEncoderFunction ($value);
90
+					} elseif (self::$numberEncoderFunction && is_numeric($value)) {
91
+						$value = self::$numberEncoderFunction ($value);
92
+					}
93
+					$array [$key] = $value;
94
+				}
95
+				return $array;
96
+			}
97
+		}
98
+		if (is_array($object) || is_object($object)) {
99
+			$count = 0;
100
+			$array = array();
101
+			foreach ($object as $key => $value) {
102
+				if (
103
+					is_string(self::$separatorChar) &&
104
+					false !== strpos($key, self::$separatorChar)
105
+				) {
106
+					list($key, $obj) = explode(self::$separatorChar, $key, 2);
107
+					$object[$key][$obj] = $value;
108
+					$value = $object[$key];
109
+				}
110
+				if (self::$removeEmpty && empty($value) && !is_numeric($value) && !is_bool($value)) {
111
+					continue;
112
+				} elseif (self::$removeNull && is_null($value)) {
113
+					continue;
114
+				}
115
+				if (array_key_exists($key, self::$fix)) {
116
+					if (isset(self::$fix[$key])) {
117
+						$value = call_user_func(self::$fix[$key], $value);
118
+					} else {
119
+						continue;
120
+					}
121
+				}
122
+				$value = self::toArray($value, $forceObjectTypeWhenEmpty);
123
+				if (self::$stringEncoderFunction && is_string($value)) {
124
+					$value = self::$encoderFunctionName ($value);
125
+				} elseif (self::$numberEncoderFunction && is_numeric($value)) {
126
+					$value = self::$numberEncoderFunction ($value);
127
+				}
128
+				$array [$key] = $value;
129
+				$count++;
130
+			}
131
+			return $forceObjectTypeWhenEmpty && $count == 0 ? $object : $array;
132
+		}
133 133
 
134
-        return $object;
135
-    }
134
+		return $object;
135
+	}
136 136
 
137
-    public function __get($name)
138
-    {
139
-        isset(self::$fix[$name]) ? self::$fix[$name] : null;
140
-    }
137
+	public function __get($name)
138
+	{
139
+		isset(self::$fix[$name]) ? self::$fix[$name] : null;
140
+	}
141 141
 
142
-    public function __set($name, $function)
143
-    {
144
-        self::$fix[$name] = $function;
145
-    }
142
+	public function __set($name, $function)
143
+	{
144
+		self::$fix[$name] = $function;
145
+	}
146 146
 
147
-    public function __isset($name)
148
-    {
149
-        return isset(self::$fix[$name]);
150
-    }
147
+	public function __isset($name)
148
+	{
149
+		return isset(self::$fix[$name]);
150
+	}
151 151
 
152
-    public function __unset($name)
153
-    {
154
-        unset(self::$fix[$name]);
155
-    }
152
+	public function __unset($name)
153
+	{
154
+		unset(self::$fix[$name]);
155
+	}
156 156
 }
157 157
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/ValueObject.php 1 patch
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -16,46 +16,46 @@
 block discarded – undo
16 16
 class ValueObject implements iValueObject
17 17
 {
18 18
 
19
-    public function __toString()
20
-    {
21
-        return ' new ' . get_called_class() . '() ';
22
-    }
19
+	public function __toString()
20
+	{
21
+		return ' new ' . get_called_class() . '() ';
22
+	}
23 23
 
24
-    public static function __set_state(array $properties)
25
-    {
26
-        $class = get_called_class();
27
-        $instance = new $class ();
28
-        $vars = get_object_vars($instance);
29
-        foreach ($properties as $property => $value) {
30
-            if (property_exists($instance, $property)) {
31
-                // see if the property is accessible
32
-                if (array_key_exists($property, $vars)) {
33
-                    $instance->{$property} = $value;
34
-                } else {
35
-                    $method = 'set' . ucfirst($property);
36
-                    if (method_exists($instance, $method)) {
37
-                        call_user_func(array(
38
-                            $instance,
39
-                            $method
40
-                        ), $value);
41
-                    }
42
-                }
43
-            }
44
-        }
45
-        return $instance;
46
-    }
24
+	public static function __set_state(array $properties)
25
+	{
26
+		$class = get_called_class();
27
+		$instance = new $class ();
28
+		$vars = get_object_vars($instance);
29
+		foreach ($properties as $property => $value) {
30
+			if (property_exists($instance, $property)) {
31
+				// see if the property is accessible
32
+				if (array_key_exists($property, $vars)) {
33
+					$instance->{$property} = $value;
34
+				} else {
35
+					$method = 'set' . ucfirst($property);
36
+					if (method_exists($instance, $method)) {
37
+						call_user_func(array(
38
+							$instance,
39
+							$method
40
+						), $value);
41
+					}
42
+				}
43
+			}
44
+		}
45
+		return $instance;
46
+	}
47 47
 
48
-    public function __toArray()
49
-    {
50
-        $r = get_object_vars($this);
51
-        $methods = get_class_methods($this);
52
-        foreach ($methods as $m) {
53
-            if (substr($m, 0, 3) == 'get') {
54
-                $r [lcfirst(substr($m, 3))] = @$this->{$m} ();
55
-            }
56
-        }
57
-        return $r;
58
-    }
48
+	public function __toArray()
49
+	{
50
+		$r = get_object_vars($this);
51
+		$methods = get_class_methods($this);
52
+		foreach ($methods as $m) {
53
+			if (substr($m, 0, 3) == 'get') {
54
+				$r [lcfirst(substr($m, 3))] = @$this->{$m} ();
55
+			}
56
+		}
57
+		return $r;
58
+	}
59 59
 
60 60
 }
61 61
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/iValueObject.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -16,24 +16,24 @@
 block discarded – undo
16 16
 interface iValueObject
17 17
 {
18 18
 
19
-    /**
20
-     * This static method is called for creating an instance of the class by
21
-     * passing the initiation values as an array.
22
-     *
23
-     * @static
24
-     * @abstract
25
-     *
26
-     * @param array $properties
27
-     *
28
-     * @return iValueObject
29
-     */
30
-    public static function __set_state(array $properties);
19
+	/**
20
+	 * This static method is called for creating an instance of the class by
21
+	 * passing the initiation values as an array.
22
+	 *
23
+	 * @static
24
+	 * @abstract
25
+	 *
26
+	 * @param array $properties
27
+	 *
28
+	 * @return iValueObject
29
+	 */
30
+	public static function __set_state(array $properties);
31 31
 
32
-    /**
33
-     * This method provides a string representation for the instance
34
-     *
35
-     * @return string
36
-     */
37
-    public function __toString();
32
+	/**
33
+	 * This method provides a string representation for the instance
34
+	 *
35
+	 * @return string
36
+	 */
37
+	public function __toString();
38 38
 }
39 39
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/ApiMethodInfo.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -15,41 +15,41 @@
 block discarded – undo
15 15
  */
16 16
 class ApiMethodInfo extends ValueObject
17 17
 {
18
-    /**
19
-     * @var string target url
20
-     */
21
-    public $url;
22
-    /**
23
-     * @var string
24
-     */
25
-    public $className;
26
-    /**
27
-     * @var string
28
-     */
29
-    public $methodName;
30
-    /**
31
-     * @var array parameters to be passed to the api method
32
-     */
33
-    public $parameters = array();
34
-    /**
35
-     * @var array information on parameters in the form of array(name => index)
36
-     */
37
-    public $arguments = array();
38
-    /**
39
-     * @var array default values for parameters if any
40
-     * in the form of array(index => value)
41
-     */
42
-    public $defaults = array();
43
-    /**
44
-     * @var array key => value pair of method meta information
45
-     */
46
-    public $metadata = array();
47
-    /**
48
-     * @var int access level
49
-     * 0 - @public - available for all
50
-     * 1 - @hybrid - both public and protected (enhanced info for authorized)
51
-     * 2 - @protected comment - only for authenticated users
52
-     * 3 - protected method - only for authenticated users
53
-     */
54
-    public $accessLevel = 0;
18
+	/**
19
+	 * @var string target url
20
+	 */
21
+	public $url;
22
+	/**
23
+	 * @var string
24
+	 */
25
+	public $className;
26
+	/**
27
+	 * @var string
28
+	 */
29
+	public $methodName;
30
+	/**
31
+	 * @var array parameters to be passed to the api method
32
+	 */
33
+	public $parameters = array();
34
+	/**
35
+	 * @var array information on parameters in the form of array(name => index)
36
+	 */
37
+	public $arguments = array();
38
+	/**
39
+	 * @var array default values for parameters if any
40
+	 * in the form of array(index => value)
41
+	 */
42
+	public $defaults = array();
43
+	/**
44
+	 * @var array key => value pair of method meta information
45
+	 */
46
+	public $metadata = array();
47
+	/**
48
+	 * @var int access level
49
+	 * 0 - @public - available for all
50
+	 * 1 - @hybrid - both public and protected (enhanced info for authorized)
51
+	 * 2 - @protected comment - only for authenticated users
52
+	 * 3 - protected method - only for authenticated users
53
+	 */
54
+	public $accessLevel = 0;
55 55
 }
56 56
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/Validator.php 1 patch
Indentation   +675 added lines, -675 removed lines patch added patch discarded remove patch
@@ -22,706 +22,706 @@
 block discarded – undo
22 22
  */
23 23
 class Validator implements iValidate
24 24
 {
25
-    public static $holdException = false;
26
-    public static $exceptions = array();
25
+	public static $holdException = false;
26
+	public static $exceptions = array();
27 27
 
28
-    public static $preFilters = array(
29
-        //'*'            => 'some_global_filter', //applied to all parameters
30
-        'string' => 'trim', //apply filter function by type (string)
31
-        //'string'       => 'strip_tags',
32
-        //'string'       => 'htmlspecialchars',
33
-        //'int'          => 'abs',
34
-        //'float'        => 'abs',
35
-        //'CustomClass'  => 'MyFilterClass::custom',
36
-        //                  please note that you wont get an instance
37
-        //                  of CustomClass. you will get an array instead
38
-    );
28
+	public static $preFilters = array(
29
+		//'*'            => 'some_global_filter', //applied to all parameters
30
+		'string' => 'trim', //apply filter function by type (string)
31
+		//'string'       => 'strip_tags',
32
+		//'string'       => 'htmlspecialchars',
33
+		//'int'          => 'abs',
34
+		//'float'        => 'abs',
35
+		//'CustomClass'  => 'MyFilterClass::custom',
36
+		//                  please note that you wont get an instance
37
+		//                  of CustomClass. you will get an array instead
38
+	);
39 39
 
40
-    /**
41
-     * Validate alphabetic characters.
42
-     *
43
-     * Check that given value contains only alphabetic characters.
44
-     *
45
-     * @param                $input
46
-     * @param ValidationInfo $info
47
-     *
48
-     * @return string
49
-     *
50
-     * @throws Invalid
51
-     */
52
-    public static function alpha($input, ValidationInfo $info = null)
53
-    {
54
-        if (ctype_alpha($input)) {
55
-            return $input;
56
-        }
57
-        if ($info && $info->fix) {
58
-            //remove non alpha characters
59
-            return preg_replace("/[^a-z]/i", "", $input);
60
-        }
61
-        throw new Invalid('Expecting only alphabetic characters.');
62
-    }
40
+	/**
41
+	 * Validate alphabetic characters.
42
+	 *
43
+	 * Check that given value contains only alphabetic characters.
44
+	 *
45
+	 * @param                $input
46
+	 * @param ValidationInfo $info
47
+	 *
48
+	 * @return string
49
+	 *
50
+	 * @throws Invalid
51
+	 */
52
+	public static function alpha($input, ValidationInfo $info = null)
53
+	{
54
+		if (ctype_alpha($input)) {
55
+			return $input;
56
+		}
57
+		if ($info && $info->fix) {
58
+			//remove non alpha characters
59
+			return preg_replace("/[^a-z]/i", "", $input);
60
+		}
61
+		throw new Invalid('Expecting only alphabetic characters.');
62
+	}
63 63
 
64
-    /**
65
-     * Validate UUID strings.
66
-     *
67
-     * Check that given value contains only alpha numeric characters and the length is 36 chars.
68
-     *
69
-     * @param                $input
70
-     * @param ValidationInfo $info
71
-     *
72
-     * @return string
73
-     *
74
-     * @throws Invalid
75
-     */
76
-    public static function uuid($input, ValidationInfo $info = null)
77
-    {
78
-        if (is_string($input) && preg_match(
79
-                '/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i',
80
-                $input
81
-            )) {
82
-            return strtolower($input);
83
-        }
84
-        throw new Invalid('Expecting a Universally Unique IDentifier (UUID) string.');
85
-    }
64
+	/**
65
+	 * Validate UUID strings.
66
+	 *
67
+	 * Check that given value contains only alpha numeric characters and the length is 36 chars.
68
+	 *
69
+	 * @param                $input
70
+	 * @param ValidationInfo $info
71
+	 *
72
+	 * @return string
73
+	 *
74
+	 * @throws Invalid
75
+	 */
76
+	public static function uuid($input, ValidationInfo $info = null)
77
+	{
78
+		if (is_string($input) && preg_match(
79
+				'/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i',
80
+				$input
81
+			)) {
82
+			return strtolower($input);
83
+		}
84
+		throw new Invalid('Expecting a Universally Unique IDentifier (UUID) string.');
85
+	}
86 86
 
87
-    /**
88
-     * Validate alpha numeric characters.
89
-     *
90
-     * Check that given value contains only alpha numeric characters.
91
-     *
92
-     * @param                $input
93
-     * @param ValidationInfo $info
94
-     *
95
-     * @return string
96
-     *
97
-     * @throws Invalid
98
-     */
99
-    public static function alphanumeric($input, ValidationInfo $info = null)
100
-    {
101
-        if (ctype_alnum($input)) {
102
-            return $input;
103
-        }
104
-        if ($info && $info->fix) {
105
-            //remove non alpha numeric and space characters
106
-            return preg_replace("/[^a-z0-9 ]/i", "", $input);
107
-        }
108
-        throw new Invalid('Expecting only alpha numeric characters.');
109
-    }
87
+	/**
88
+	 * Validate alpha numeric characters.
89
+	 *
90
+	 * Check that given value contains only alpha numeric characters.
91
+	 *
92
+	 * @param                $input
93
+	 * @param ValidationInfo $info
94
+	 *
95
+	 * @return string
96
+	 *
97
+	 * @throws Invalid
98
+	 */
99
+	public static function alphanumeric($input, ValidationInfo $info = null)
100
+	{
101
+		if (ctype_alnum($input)) {
102
+			return $input;
103
+		}
104
+		if ($info && $info->fix) {
105
+			//remove non alpha numeric and space characters
106
+			return preg_replace("/[^a-z0-9 ]/i", "", $input);
107
+		}
108
+		throw new Invalid('Expecting only alpha numeric characters.');
109
+	}
110 110
 
111
-    /**
112
-     * Validate printable characters.
113
-     *
114
-     * Check that given value contains only printable characters.
115
-     *
116
-     * @param                $input
117
-     * @param ValidationInfo $info
118
-     *
119
-     * @return string
120
-     *
121
-     * @throws Invalid
122
-     */
123
-    public static function printable($input, ValidationInfo $info = null)
124
-    {
125
-        if (ctype_print($input)) {
126
-            return $input;
127
-        }
128
-        if ($info && $info->fix) {
129
-            //remove non printable characters
130
-            return preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $input);
131
-        }
132
-        throw new Invalid('Expecting only printable characters.');
133
-    }
111
+	/**
112
+	 * Validate printable characters.
113
+	 *
114
+	 * Check that given value contains only printable characters.
115
+	 *
116
+	 * @param                $input
117
+	 * @param ValidationInfo $info
118
+	 *
119
+	 * @return string
120
+	 *
121
+	 * @throws Invalid
122
+	 */
123
+	public static function printable($input, ValidationInfo $info = null)
124
+	{
125
+		if (ctype_print($input)) {
126
+			return $input;
127
+		}
128
+		if ($info && $info->fix) {
129
+			//remove non printable characters
130
+			return preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $input);
131
+		}
132
+		throw new Invalid('Expecting only printable characters.');
133
+	}
134 134
 
135
-    /**
136
-     * Validate hexadecimal digits.
137
-     *
138
-     * Check that given value contains only hexadecimal digits.
139
-     *
140
-     * @param                $input
141
-     * @param ValidationInfo $info
142
-     *
143
-     * @return string
144
-     *
145
-     * @throws Invalid
146
-     */
147
-    public static function hex($input, ValidationInfo $info = null)
148
-    {
149
-        if (ctype_xdigit($input)) {
150
-            return $input;
151
-        }
152
-        throw new Invalid('Expecting only hexadecimal digits.');
153
-    }
135
+	/**
136
+	 * Validate hexadecimal digits.
137
+	 *
138
+	 * Check that given value contains only hexadecimal digits.
139
+	 *
140
+	 * @param                $input
141
+	 * @param ValidationInfo $info
142
+	 *
143
+	 * @return string
144
+	 *
145
+	 * @throws Invalid
146
+	 */
147
+	public static function hex($input, ValidationInfo $info = null)
148
+	{
149
+		if (ctype_xdigit($input)) {
150
+			return $input;
151
+		}
152
+		throw new Invalid('Expecting only hexadecimal digits.');
153
+	}
154 154
 
155
-    /**
156
-     * Color specified as hexadecimals
157
-     *
158
-     * Check that given value contains only color.
159
-     *
160
-     * @param                     $input
161
-     * @param ValidationInfo|null $info
162
-     *
163
-     * @return string
164
-     * @throws Invalid
165
-     */
166
-    public static function color($input, ValidationInfo $info = null)
167
-    {
168
-        if (preg_match('/^#[a-f0-9]{6}$/i', $input)) {
169
-            return $input;
170
-        }
171
-        throw new Invalid('Expecting color as hexadecimal digits.');
172
-    }
155
+	/**
156
+	 * Color specified as hexadecimals
157
+	 *
158
+	 * Check that given value contains only color.
159
+	 *
160
+	 * @param                     $input
161
+	 * @param ValidationInfo|null $info
162
+	 *
163
+	 * @return string
164
+	 * @throws Invalid
165
+	 */
166
+	public static function color($input, ValidationInfo $info = null)
167
+	{
168
+		if (preg_match('/^#[a-f0-9]{6}$/i', $input)) {
169
+			return $input;
170
+		}
171
+		throw new Invalid('Expecting color as hexadecimal digits.');
172
+	}
173 173
 
174
-    /**
175
-     * Validate Telephone number
176
-     *
177
-     * Check if the given value is numeric with or without a `+` prefix
178
-     *
179
-     * @param                $input
180
-     * @param ValidationInfo $info
181
-     *
182
-     * @return string
183
-     *
184
-     * @throws Invalid
185
-     */
186
-    public static function tel($input, ValidationInfo $info = null)
187
-    {
188
-        if (is_numeric($input) && '-' != substr($input, 0, 1)) {
189
-            return $input;
190
-        }
191
-        throw new Invalid('Expecting phone number, a numeric value ' .
192
-            'with optional `+` prefix');
193
-    }
174
+	/**
175
+	 * Validate Telephone number
176
+	 *
177
+	 * Check if the given value is numeric with or without a `+` prefix
178
+	 *
179
+	 * @param                $input
180
+	 * @param ValidationInfo $info
181
+	 *
182
+	 * @return string
183
+	 *
184
+	 * @throws Invalid
185
+	 */
186
+	public static function tel($input, ValidationInfo $info = null)
187
+	{
188
+		if (is_numeric($input) && '-' != substr($input, 0, 1)) {
189
+			return $input;
190
+		}
191
+		throw new Invalid('Expecting phone number, a numeric value ' .
192
+			'with optional `+` prefix');
193
+	}
194 194
 
195
-    /**
196
-     * Validate Email
197
-     *
198
-     * Check if the given string is a valid email
199
-     *
200
-     * @param String         $input
201
-     * @param ValidationInfo $info
202
-     *
203
-     * @return string
204
-     * @throws Invalid
205
-     */
206
-    public static function email($input, ValidationInfo $info = null)
207
-    {
208
-        $r = filter_var($input, FILTER_VALIDATE_EMAIL);
209
-        if ($r) {
210
-            return $r;
211
-        } elseif ($info && $info->fix) {
212
-            $r = filter_var($input, FILTER_SANITIZE_EMAIL);
213
-            return static::email($r);
214
-        }
215
-        throw new Invalid('Expecting email in `[email protected]` format');
216
-    }
195
+	/**
196
+	 * Validate Email
197
+	 *
198
+	 * Check if the given string is a valid email
199
+	 *
200
+	 * @param String         $input
201
+	 * @param ValidationInfo $info
202
+	 *
203
+	 * @return string
204
+	 * @throws Invalid
205
+	 */
206
+	public static function email($input, ValidationInfo $info = null)
207
+	{
208
+		$r = filter_var($input, FILTER_VALIDATE_EMAIL);
209
+		if ($r) {
210
+			return $r;
211
+		} elseif ($info && $info->fix) {
212
+			$r = filter_var($input, FILTER_SANITIZE_EMAIL);
213
+			return static::email($r);
214
+		}
215
+		throw new Invalid('Expecting email in `[email protected]` format');
216
+	}
217 217
 
218
-    /**
219
-     * Validate IP Address
220
-     *
221
-     * Check if the given string is a valid ip address
222
-     *
223
-     * @param String         $input
224
-     * @param ValidationInfo $info
225
-     *
226
-     * @return string
227
-     * @throws Invalid
228
-     */
229
-    public static function ip($input, ValidationInfo $info = null)
230
-    {
231
-        $r = filter_var($input, FILTER_VALIDATE_IP);
232
-        if ($r) {
233
-            return $r;
234
-        }
218
+	/**
219
+	 * Validate IP Address
220
+	 *
221
+	 * Check if the given string is a valid ip address
222
+	 *
223
+	 * @param String         $input
224
+	 * @param ValidationInfo $info
225
+	 *
226
+	 * @return string
227
+	 * @throws Invalid
228
+	 */
229
+	public static function ip($input, ValidationInfo $info = null)
230
+	{
231
+		$r = filter_var($input, FILTER_VALIDATE_IP);
232
+		if ($r) {
233
+			return $r;
234
+		}
235 235
 
236
-        throw new Invalid('Expecting IP address in IPV6 or IPV4 format');
237
-    }
236
+		throw new Invalid('Expecting IP address in IPV6 or IPV4 format');
237
+	}
238 238
 
239
-    /**
240
-     * Validate Url
241
-     *
242
-     * Check if the given string is a valid url
243
-     *
244
-     * @param String         $input
245
-     * @param ValidationInfo $info
246
-     *
247
-     * @return string
248
-     * @throws Invalid
249
-     */
250
-    public static function url($input, ValidationInfo $info = null)
251
-    {
252
-        $r = filter_var($input, FILTER_VALIDATE_URL);
253
-        if ($r) {
254
-            return $r;
255
-        } elseif ($info && $info->fix) {
256
-            $r = filter_var($input, FILTER_SANITIZE_URL);
257
-            return static::url($r);
258
-        }
259
-        throw new Invalid('Expecting url in `http://example.com` format');
260
-    }
239
+	/**
240
+	 * Validate Url
241
+	 *
242
+	 * Check if the given string is a valid url
243
+	 *
244
+	 * @param String         $input
245
+	 * @param ValidationInfo $info
246
+	 *
247
+	 * @return string
248
+	 * @throws Invalid
249
+	 */
250
+	public static function url($input, ValidationInfo $info = null)
251
+	{
252
+		$r = filter_var($input, FILTER_VALIDATE_URL);
253
+		if ($r) {
254
+			return $r;
255
+		} elseif ($info && $info->fix) {
256
+			$r = filter_var($input, FILTER_SANITIZE_URL);
257
+			return static::url($r);
258
+		}
259
+		throw new Invalid('Expecting url in `http://example.com` format');
260
+	}
261 261
 
262
-    /**
263
-     * MySQL Date
264
-     *
265
-     * Check if the given string is a valid date in YYYY-MM-DD format
266
-     *
267
-     * @param String         $input
268
-     * @param ValidationInfo $info
269
-     *
270
-     * @return string
271
-     * @throws Invalid
272
-     */
273
-    public static function date($input, ValidationInfo $info = null)
274
-    {
275
-        if (
276
-            preg_match(
277
-                '#^(?P<year>\d{2}|\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$#',
278
-                $input,
279
-                $date
280
-            )
281
-            && checkdate($date['month'], $date['day'], $date['year'])
282
-        ) {
283
-            return $input;
284
-        }
285
-        throw new Invalid(
286
-            'Expecting date in `YYYY-MM-DD` format, such as `'
287
-            . date("Y-m-d") . '`'
288
-        );
289
-    }
262
+	/**
263
+	 * MySQL Date
264
+	 *
265
+	 * Check if the given string is a valid date in YYYY-MM-DD format
266
+	 *
267
+	 * @param String         $input
268
+	 * @param ValidationInfo $info
269
+	 *
270
+	 * @return string
271
+	 * @throws Invalid
272
+	 */
273
+	public static function date($input, ValidationInfo $info = null)
274
+	{
275
+		if (
276
+			preg_match(
277
+				'#^(?P<year>\d{2}|\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$#',
278
+				$input,
279
+				$date
280
+			)
281
+			&& checkdate($date['month'], $date['day'], $date['year'])
282
+		) {
283
+			return $input;
284
+		}
285
+		throw new Invalid(
286
+			'Expecting date in `YYYY-MM-DD` format, such as `'
287
+			. date("Y-m-d") . '`'
288
+		);
289
+	}
290 290
 
291
-    /**
292
-     * MySQL DateTime
293
-     *
294
-     * Check if the given string is a valid date and time in YYY-MM-DD HH:MM:SS format
295
-     *
296
-     * @param String         $input
297
-     * @param ValidationInfo $info
298
-     *
299
-     * @return string
300
-     * @throws Invalid
301
-     */
302
-    public static function datetime($input, ValidationInfo $info = null)
303
-    {
304
-        if (
305
-            preg_match('/^(?P<year>19\d\d|20\d\d)\-(?P<month>0[1-9]|1[0-2])\-' .
306
-                '(?P<day>0\d|[1-2]\d|3[0-1]) (?P<h>0\d|1\d|2[0-3]' .
307
-                ')\:(?P<i>[0-5][0-9])\:(?P<s>[0-5][0-9])$/',
308
-                $input, $date)
309
-            && checkdate($date['month'], $date['day'], $date['year'])
310
-        ) {
311
-            return $input;
312
-        }
313
-        throw new Invalid(
314
-            'Expecting date and time in `YYYY-MM-DD HH:MM:SS` format, such as `'
315
-            . date("Y-m-d H:i:s") . '`'
316
-        );
317
-    }
291
+	/**
292
+	 * MySQL DateTime
293
+	 *
294
+	 * Check if the given string is a valid date and time in YYY-MM-DD HH:MM:SS format
295
+	 *
296
+	 * @param String         $input
297
+	 * @param ValidationInfo $info
298
+	 *
299
+	 * @return string
300
+	 * @throws Invalid
301
+	 */
302
+	public static function datetime($input, ValidationInfo $info = null)
303
+	{
304
+		if (
305
+			preg_match('/^(?P<year>19\d\d|20\d\d)\-(?P<month>0[1-9]|1[0-2])\-' .
306
+				'(?P<day>0\d|[1-2]\d|3[0-1]) (?P<h>0\d|1\d|2[0-3]' .
307
+				')\:(?P<i>[0-5][0-9])\:(?P<s>[0-5][0-9])$/',
308
+				$input, $date)
309
+			&& checkdate($date['month'], $date['day'], $date['year'])
310
+		) {
311
+			return $input;
312
+		}
313
+		throw new Invalid(
314
+			'Expecting date and time in `YYYY-MM-DD HH:MM:SS` format, such as `'
315
+			. date("Y-m-d H:i:s") . '`'
316
+		);
317
+	}
318 318
 
319
-    /**
320
-     * Alias for Time
321
-     *
322
-     * Check if the given string is a valid time in HH:MM:SS format
323
-     *
324
-     * @param String         $input
325
-     * @param ValidationInfo $info
326
-     *
327
-     * @return string
328
-     * @throws Invalid
329
-     */
330
-    public static function time24($input, ValidationInfo $info = null)
331
-    {
332
-        return static::time($input, $info);
333
-    }
319
+	/**
320
+	 * Alias for Time
321
+	 *
322
+	 * Check if the given string is a valid time in HH:MM:SS format
323
+	 *
324
+	 * @param String         $input
325
+	 * @param ValidationInfo $info
326
+	 *
327
+	 * @return string
328
+	 * @throws Invalid
329
+	 */
330
+	public static function time24($input, ValidationInfo $info = null)
331
+	{
332
+		return static::time($input, $info);
333
+	}
334 334
 
335
-    /**
336
-     * Time
337
-     *
338
-     * Check if the given string is a valid time in HH:MM:SS format
339
-     *
340
-     * @param String         $input
341
-     * @param ValidationInfo $info
342
-     *
343
-     * @return string
344
-     * @throws Invalid
345
-     */
346
-    public static function time($input, ValidationInfo $info = null)
347
-    {
348
-        if (preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/', $input)) {
349
-            return $input;
350
-        }
351
-        throw new Invalid(
352
-            'Expecting time in `HH:MM:SS` format, such as `'
353
-            . date("H:i:s") . '`'
354
-        );
355
-    }
335
+	/**
336
+	 * Time
337
+	 *
338
+	 * Check if the given string is a valid time in HH:MM:SS format
339
+	 *
340
+	 * @param String         $input
341
+	 * @param ValidationInfo $info
342
+	 *
343
+	 * @return string
344
+	 * @throws Invalid
345
+	 */
346
+	public static function time($input, ValidationInfo $info = null)
347
+	{
348
+		if (preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/', $input)) {
349
+			return $input;
350
+		}
351
+		throw new Invalid(
352
+			'Expecting time in `HH:MM:SS` format, such as `'
353
+			. date("H:i:s") . '`'
354
+		);
355
+	}
356 356
 
357
-    /**
358
-     * Time in 12 hour format
359
-     *
360
-     * Check if the given string is a valid time 12 hour format
361
-     *
362
-     * @param String         $input
363
-     * @param ValidationInfo $info
364
-     *
365
-     * @return string
366
-     * @throws Invalid
367
-     */
368
-    public static function time12($input, ValidationInfo $info = null)
369
-    {
370
-        if (preg_match(
371
-            '/^([1-9]|1[0-2]|0[1-9]){1}(:[0-5][0-9])?\s?([aApP][mM]{1})?$/',
372
-            $input)
373
-        ) {
374
-            return $input;
375
-        }
376
-        throw new Invalid(
377
-            'Expecting time in 12 hour format, such as `08:00AM` and `10:05:11`'
378
-        );
379
-    }
357
+	/**
358
+	 * Time in 12 hour format
359
+	 *
360
+	 * Check if the given string is a valid time 12 hour format
361
+	 *
362
+	 * @param String         $input
363
+	 * @param ValidationInfo $info
364
+	 *
365
+	 * @return string
366
+	 * @throws Invalid
367
+	 */
368
+	public static function time12($input, ValidationInfo $info = null)
369
+	{
370
+		if (preg_match(
371
+			'/^([1-9]|1[0-2]|0[1-9]){1}(:[0-5][0-9])?\s?([aApP][mM]{1})?$/',
372
+			$input)
373
+		) {
374
+			return $input;
375
+		}
376
+		throw new Invalid(
377
+			'Expecting time in 12 hour format, such as `08:00AM` and `10:05:11`'
378
+		);
379
+	}
380 380
 
381
-    /**
382
-     * Unix Timestamp
383
-     *
384
-     * Check if the given value is a valid timestamp
385
-     *
386
-     * @param String         $input
387
-     * @param ValidationInfo $info
388
-     *
389
-     * @return int
390
-     * @throws Invalid
391
-     */
392
-    public static function timestamp($input, ValidationInfo $info = null)
393
-    {
394
-        if ((string)(int)$input == $input
395
-            && ($input <= PHP_INT_MAX)
396
-            && ($input >= ~PHP_INT_MAX)
397
-        ) {
398
-            return (int)$input;
399
-        }
400
-        throw new Invalid('Expecting unix timestamp, such as ' . time());
401
-    }
381
+	/**
382
+	 * Unix Timestamp
383
+	 *
384
+	 * Check if the given value is a valid timestamp
385
+	 *
386
+	 * @param String         $input
387
+	 * @param ValidationInfo $info
388
+	 *
389
+	 * @return int
390
+	 * @throws Invalid
391
+	 */
392
+	public static function timestamp($input, ValidationInfo $info = null)
393
+	{
394
+		if ((string)(int)$input == $input
395
+			&& ($input <= PHP_INT_MAX)
396
+			&& ($input >= ~PHP_INT_MAX)
397
+		) {
398
+			return (int)$input;
399
+		}
400
+		throw new Invalid('Expecting unix timestamp, such as ' . time());
401
+	}
402 402
 
403
-    /**
404
-     * Validate the given input
405
-     *
406
-     * Validates the input and attempts to fix it when fix is requested
407
-     *
408
-     * @param mixed          $input
409
-     * @param ValidationInfo $info
410
-     * @param null           $full
411
-     *
412
-     * @throws \Exception
413
-     * @return array|bool|float|int|mixed|null|number|string
414
-     */
415
-    public static function validate($input, ValidationInfo $info, $full = null)
416
-    {
417
-        $html = Scope::get('Restler')->responseFormat instanceof HtmlFormat;
418
-        $name = $html ? "<strong>$info->label</strong>" : "`$info->name`";
419
-        if (
420
-            isset(static::$preFilters['*']) &&
421
-            is_scalar($input) &&
422
-            is_callable($func = static::$preFilters['*'])
423
-        ) {
424
-            $input = $func($input);
425
-        }
426
-        if (
427
-            isset(static::$preFilters[$info->type]) &&
428
-            (is_scalar($input) || !empty($info->children)) &&
429
-            is_callable($func = static::$preFilters[$info->type])
430
-        ) {
431
-            $input = $func($input);
432
-        }
433
-        try {
434
-            if (is_null($input)) {
435
-                if ($info->required) {
436
-                    throw new RestException (400,
437
-                        "$name is required.");
438
-                }
439
-                return null;
440
-            }
441
-            $error = isset ($info->message)
442
-                ? $info->message
443
-                : "Invalid value specified for $name";
403
+	/**
404
+	 * Validate the given input
405
+	 *
406
+	 * Validates the input and attempts to fix it when fix is requested
407
+	 *
408
+	 * @param mixed          $input
409
+	 * @param ValidationInfo $info
410
+	 * @param null           $full
411
+	 *
412
+	 * @throws \Exception
413
+	 * @return array|bool|float|int|mixed|null|number|string
414
+	 */
415
+	public static function validate($input, ValidationInfo $info, $full = null)
416
+	{
417
+		$html = Scope::get('Restler')->responseFormat instanceof HtmlFormat;
418
+		$name = $html ? "<strong>$info->label</strong>" : "`$info->name`";
419
+		if (
420
+			isset(static::$preFilters['*']) &&
421
+			is_scalar($input) &&
422
+			is_callable($func = static::$preFilters['*'])
423
+		) {
424
+			$input = $func($input);
425
+		}
426
+		if (
427
+			isset(static::$preFilters[$info->type]) &&
428
+			(is_scalar($input) || !empty($info->children)) &&
429
+			is_callable($func = static::$preFilters[$info->type])
430
+		) {
431
+			$input = $func($input);
432
+		}
433
+		try {
434
+			if (is_null($input)) {
435
+				if ($info->required) {
436
+					throw new RestException (400,
437
+						"$name is required.");
438
+				}
439
+				return null;
440
+			}
441
+			$error = isset ($info->message)
442
+				? $info->message
443
+				: "Invalid value specified for $name";
444 444
 
445
-            //if a validation method is specified
446
-            if (!empty($info->method)) {
447
-                $method = $info->method;
448
-                $info->method = '';
449
-                $r = self::validate($input, $info);
450
-                return $info->apiClassInstance->{$method} ($r);
451
-            }
445
+			//if a validation method is specified
446
+			if (!empty($info->method)) {
447
+				$method = $info->method;
448
+				$info->method = '';
449
+				$r = self::validate($input, $info);
450
+				return $info->apiClassInstance->{$method} ($r);
451
+			}
452 452
 
453
-            // when type is an array check if it passes for any type
454
-            if (is_array($info->type)) {
455
-                //trace("types are ".print_r($info->type, true));
456
-                $types = $info->type;
457
-                foreach ($types as $type) {
458
-                    $info->type = $type;
459
-                    try {
460
-                        $r = self::validate($input, $info);
461
-                        if ($r !== false) {
462
-                            return $r;
463
-                        }
464
-                    } catch (RestException $e) {
465
-                        // just continue
466
-                    }
467
-                }
468
-                throw new RestException (400, $error);
469
-            }
453
+			// when type is an array check if it passes for any type
454
+			if (is_array($info->type)) {
455
+				//trace("types are ".print_r($info->type, true));
456
+				$types = $info->type;
457
+				foreach ($types as $type) {
458
+					$info->type = $type;
459
+					try {
460
+						$r = self::validate($input, $info);
461
+						if ($r !== false) {
462
+							return $r;
463
+						}
464
+					} catch (RestException $e) {
465
+						// just continue
466
+					}
467
+				}
468
+				throw new RestException (400, $error);
469
+			}
470 470
 
471
-            //patterns are supported only for non numeric types
472
-            if (isset ($info->pattern)
473
-                && $info->type != 'int'
474
-                && $info->type != 'float'
475
-                && $info->type != 'number'
476
-            ) {
477
-                if (!preg_match($info->pattern, $input)) {
478
-                    throw new RestException (400, $error);
479
-                }
480
-            }
471
+			//patterns are supported only for non numeric types
472
+			if (isset ($info->pattern)
473
+				&& $info->type != 'int'
474
+				&& $info->type != 'float'
475
+				&& $info->type != 'number'
476
+			) {
477
+				if (!preg_match($info->pattern, $input)) {
478
+					throw new RestException (400, $error);
479
+				}
480
+			}
481 481
 
482
-            if (isset ($info->choice)) {
483
-                if (!$info->required && empty($input)) {
484
-                    //since its optional, and empty let it pass.
485
-                    $input = null;
486
-                } elseif (is_array($input)) {
487
-                    foreach ($input as $i) {
488
-                        if (!in_array($i, $info->choice)) {
489
-                            $error .= ". Expected one of (" . implode(',', $info->choice) . ").";
490
-                            throw new RestException (400, $error);
491
-                        }
492
-                    }
493
-                } elseif (!in_array($input, $info->choice)) {
494
-                    $error .= ". Expected one of (" . implode(',', $info->choice) . ").";
495
-                    throw new RestException (400, $error);
496
-                }
497
-            }
482
+			if (isset ($info->choice)) {
483
+				if (!$info->required && empty($input)) {
484
+					//since its optional, and empty let it pass.
485
+					$input = null;
486
+				} elseif (is_array($input)) {
487
+					foreach ($input as $i) {
488
+						if (!in_array($i, $info->choice)) {
489
+							$error .= ". Expected one of (" . implode(',', $info->choice) . ").";
490
+							throw new RestException (400, $error);
491
+						}
492
+					}
493
+				} elseif (!in_array($input, $info->choice)) {
494
+					$error .= ". Expected one of (" . implode(',', $info->choice) . ").";
495
+					throw new RestException (400, $error);
496
+				}
497
+			}
498 498
 
499
-            if (method_exists($class = get_called_class(), $info->type) && $info->type != 'validate') {
500
-                if (!$info->required && empty($input)) {
501
-                    //optional parameter with a empty value assume null
502
-                    return null;
503
-                }
504
-                try {
505
-                    return call_user_func("$class::$info->type", $input, $info);
506
-                } catch (Invalid $e) {
507
-                    throw new RestException(400, $error . '. ' . $e->getMessage());
508
-                }
509
-            }
499
+			if (method_exists($class = get_called_class(), $info->type) && $info->type != 'validate') {
500
+				if (!$info->required && empty($input)) {
501
+					//optional parameter with a empty value assume null
502
+					return null;
503
+				}
504
+				try {
505
+					return call_user_func("$class::$info->type", $input, $info);
506
+				} catch (Invalid $e) {
507
+					throw new RestException(400, $error . '. ' . $e->getMessage());
508
+				}
509
+			}
510 510
 
511
-            switch ($info->type) {
512
-                case 'int' :
513
-                case 'float' :
514
-                case 'number' :
515
-                    if (!is_numeric($input)) {
516
-                        $error .= '. Expecting '
517
-                            . ($info->type == 'int' ? 'integer' : 'numeric')
518
-                            . ' value';
519
-                        break;
520
-                    }
521
-                    if ($info->type == 'int' && (int)$input != $input) {
522
-                        if ($info->fix) {
523
-                            $r = (int)$input;
524
-                        } else {
525
-                            $error .= '. Expecting integer value';
526
-                            break;
527
-                        }
528
-                    } else {
529
-                        $r = $info->numericValue($input);
530
-                    }
531
-                    if (isset ($info->min) && $r < $info->min) {
532
-                        if ($info->fix) {
533
-                            $r = $info->min;
534
-                        } else {
535
-                            $error .= ". Minimum required value is $info->min.";
536
-                            break;
537
-                        }
538
-                    }
539
-                    if (isset ($info->max) && $r > $info->max) {
540
-                        if ($info->fix) {
541
-                            $r = $info->max;
542
-                        } else {
543
-                            $error .= ". Maximum allowed value is $info->max.";
544
-                            break;
545
-                        }
546
-                    }
547
-                    return $r;
511
+			switch ($info->type) {
512
+				case 'int' :
513
+				case 'float' :
514
+				case 'number' :
515
+					if (!is_numeric($input)) {
516
+						$error .= '. Expecting '
517
+							. ($info->type == 'int' ? 'integer' : 'numeric')
518
+							. ' value';
519
+						break;
520
+					}
521
+					if ($info->type == 'int' && (int)$input != $input) {
522
+						if ($info->fix) {
523
+							$r = (int)$input;
524
+						} else {
525
+							$error .= '. Expecting integer value';
526
+							break;
527
+						}
528
+					} else {
529
+						$r = $info->numericValue($input);
530
+					}
531
+					if (isset ($info->min) && $r < $info->min) {
532
+						if ($info->fix) {
533
+							$r = $info->min;
534
+						} else {
535
+							$error .= ". Minimum required value is $info->min.";
536
+							break;
537
+						}
538
+					}
539
+					if (isset ($info->max) && $r > $info->max) {
540
+						if ($info->fix) {
541
+							$r = $info->max;
542
+						} else {
543
+							$error .= ". Maximum allowed value is $info->max.";
544
+							break;
545
+						}
546
+					}
547
+					return $r;
548 548
 
549
-                case 'string' :
550
-                case 'password' : //password fields with string
551
-                case 'search' : //search field with string
552
-                    if (is_bool($input)) $input = $input ? 'true' : 'false';
553
-                    if (!is_string($input)) {
554
-                        $error .= '. Expecting alpha numeric value';
555
-                        break;
556
-                    }
557
-                    if ($info->required && $input === '') {
558
-                        $error = "$name is required.";
559
-                        break;
560
-                    }
561
-                    $r = strlen($input);
562
-                    if (isset ($info->min) && $r < $info->min) {
563
-                        if ($info->fix) {
564
-                            $input = str_pad($input, $info->min, $input);
565
-                        } else {
566
-                            $char = $info->min > 1 ? 'characters' : 'character';
567
-                            $error .= ". Minimum $info->min $char required.";
568
-                            break;
569
-                        }
570
-                    }
571
-                    if (isset ($info->max) && $r > $info->max) {
572
-                        if ($info->fix) {
573
-                            $input = substr($input, 0, $info->max);
574
-                        } else {
575
-                            $char = $info->max > 1 ? 'characters' : 'character';
576
-                            $error .= ". Maximum $info->max $char allowed.";
577
-                            break;
578
-                        }
579
-                    }
580
-                    return $input;
549
+				case 'string' :
550
+				case 'password' : //password fields with string
551
+				case 'search' : //search field with string
552
+					if (is_bool($input)) $input = $input ? 'true' : 'false';
553
+					if (!is_string($input)) {
554
+						$error .= '. Expecting alpha numeric value';
555
+						break;
556
+					}
557
+					if ($info->required && $input === '') {
558
+						$error = "$name is required.";
559
+						break;
560
+					}
561
+					$r = strlen($input);
562
+					if (isset ($info->min) && $r < $info->min) {
563
+						if ($info->fix) {
564
+							$input = str_pad($input, $info->min, $input);
565
+						} else {
566
+							$char = $info->min > 1 ? 'characters' : 'character';
567
+							$error .= ". Minimum $info->min $char required.";
568
+							break;
569
+						}
570
+					}
571
+					if (isset ($info->max) && $r > $info->max) {
572
+						if ($info->fix) {
573
+							$input = substr($input, 0, $info->max);
574
+						} else {
575
+							$char = $info->max > 1 ? 'characters' : 'character';
576
+							$error .= ". Maximum $info->max $char allowed.";
577
+							break;
578
+						}
579
+					}
580
+					return $input;
581 581
 
582
-                case 'bool':
583
-                case 'boolean':
584
-                    if (is_bool($input)) {
585
-                        return $input;
586
-                    }
587
-                    if (is_numeric($input)) {
588
-                        if ($input == 1) {
589
-                            return true;
590
-                        }
591
-                        if ($input == 0) {
592
-                            return false;
593
-                        }
594
-                    } elseif (is_string($input)) {
595
-                        switch (strtolower($input)) {
596
-                            case 'true':
597
-                                return true;
598
-                            case 'false':
599
-                                return false;
600
-                        }
601
-                    }
602
-                    if ($info->fix) {
603
-                        return $input ? true : false;
604
-                    }
605
-                    $error .= '. Expecting boolean value';
606
-                    break;
607
-                case 'array':
608
-                    if ($info->fix && is_string($input)) {
609
-                        $input = explode(CommentParser::$arrayDelimiter, $input);
610
-                    }
611
-                    if (is_array($input)) {
612
-                        $contentType =
613
-                            Util::nestedValue($info, 'contentType') ?: null;
614
-                        if ($info->fix) {
615
-                            if ($contentType == 'indexed') {
616
-                                $input = $info->filterArray($input, true);
617
-                            } elseif ($contentType == 'associative') {
618
-                                $input = $info->filterArray($input, false);
619
-                            }
620
-                        } elseif (
621
-                            $contentType == 'indexed' &&
622
-                            array_values($input) != $input
623
-                        ) {
624
-                            $error .= '. Expecting a list of items but an item is given';
625
-                            break;
626
-                        } elseif (
627
-                            $contentType == 'associative' &&
628
-                            array_values($input) == $input &&
629
-                            count($input)
630
-                        ) {
631
-                            $error .= '. Expecting an item but a list is given';
632
-                            break;
633
-                        }
634
-                        $r = count($input);
635
-                        if (isset ($info->min) && $r < $info->min) {
636
-                            $item = $info->max > 1 ? 'items' : 'item';
637
-                            $error .= ". Minimum $info->min $item required.";
638
-                            break;
639
-                        }
640
-                        if (isset ($info->max) && $r > $info->max) {
641
-                            if ($info->fix) {
642
-                                $input = array_slice($input, 0, $info->max);
643
-                            } else {
644
-                                $item = $info->max > 1 ? 'items' : 'item';
645
-                                $error .= ". Maximum $info->max $item allowed.";
646
-                                break;
647
-                            }
648
-                        }
649
-                        if (
650
-                            isset($contentType) &&
651
-                            $contentType != 'associative' &&
652
-                            $contentType != 'indexed'
653
-                        ) {
654
-                            $name = $info->name;
655
-                            $info->type = $contentType;
656
-                            unset($info->contentType);
657
-                            unset($info->min);
658
-                            unset($info->max);
659
-                            foreach ($input as $key => $chinput) {
660
-                                $info->name = "{$name}[$key]";
661
-                                $input[$key] = static::validate($chinput, $info);
662
-                            }
663
-                        }
664
-                        return $input;
665
-                    } elseif (isset($contentType)) {
666
-                        $error .= '. Expecting items of type ' .
667
-                            ($html ? "<strong>$contentType</strong>" : "`$contentType`");
668
-                        break;
669
-                    }
670
-                    break;
671
-                case 'mixed':
672
-                case 'unknown_type':
673
-                case 'unknown':
674
-                case null: //treat as unknown
675
-                    return $input;
676
-                default :
677
-                    if (!is_array($input)) {
678
-                        break;
679
-                    }
680
-                    //do type conversion
681
-                    if (class_exists($info->type)) {
682
-                        $input = $info->filterArray($input, false);
683
-                        $implements = class_implements($info->type);
684
-                        if (
685
-                            is_array($implements) &&
686
-                            in_array('Luracast\\Restler\\Data\\iValueObject', $implements)
687
-                        ) {
688
-                            return call_user_func(
689
-                                "{$info->type}::__set_state", $input
690
-                            );
691
-                        }
692
-                        $class = $info->type;
693
-                        $instance = new $class();
694
-                        if (is_array($info->children)) {
695
-                            if (
696
-                                empty($input) ||
697
-                                !is_array($input) ||
698
-                                $input === array_values($input)
699
-                            ) {
700
-                                $error .= '. Expecting an item of type ' .
701
-                                    ($html ? "<strong>$info->type</strong>" : "`$info->type`");
702
-                                break;
703
-                            }
704
-                            foreach ($info->children as $key => $value) {
705
-                                $cv = new ValidationInfo($value);
706
-                                $cv->name = "{$info->name}[$key]";
707
-                                if (array_key_exists($key, $input) || $cv->required) {
708
-                                    $instance->{$key} = static::validate(
709
-                                        Util::nestedValue($input, $key),
710
-                                        $cv
711
-                                    );
712
-                                }
713
-                            }
714
-                        }
715
-                        return $instance;
716
-                    }
717
-            }
718
-            throw new RestException (400, $error);
719
-        } catch (\Exception $e) {
720
-            static::$exceptions[$info->name] = $e;
721
-            if (static::$holdException) {
722
-                return null;
723
-            }
724
-            throw $e;
725
-        }
726
-    }
582
+				case 'bool':
583
+				case 'boolean':
584
+					if (is_bool($input)) {
585
+						return $input;
586
+					}
587
+					if (is_numeric($input)) {
588
+						if ($input == 1) {
589
+							return true;
590
+						}
591
+						if ($input == 0) {
592
+							return false;
593
+						}
594
+					} elseif (is_string($input)) {
595
+						switch (strtolower($input)) {
596
+							case 'true':
597
+								return true;
598
+							case 'false':
599
+								return false;
600
+						}
601
+					}
602
+					if ($info->fix) {
603
+						return $input ? true : false;
604
+					}
605
+					$error .= '. Expecting boolean value';
606
+					break;
607
+				case 'array':
608
+					if ($info->fix && is_string($input)) {
609
+						$input = explode(CommentParser::$arrayDelimiter, $input);
610
+					}
611
+					if (is_array($input)) {
612
+						$contentType =
613
+							Util::nestedValue($info, 'contentType') ?: null;
614
+						if ($info->fix) {
615
+							if ($contentType == 'indexed') {
616
+								$input = $info->filterArray($input, true);
617
+							} elseif ($contentType == 'associative') {
618
+								$input = $info->filterArray($input, false);
619
+							}
620
+						} elseif (
621
+							$contentType == 'indexed' &&
622
+							array_values($input) != $input
623
+						) {
624
+							$error .= '. Expecting a list of items but an item is given';
625
+							break;
626
+						} elseif (
627
+							$contentType == 'associative' &&
628
+							array_values($input) == $input &&
629
+							count($input)
630
+						) {
631
+							$error .= '. Expecting an item but a list is given';
632
+							break;
633
+						}
634
+						$r = count($input);
635
+						if (isset ($info->min) && $r < $info->min) {
636
+							$item = $info->max > 1 ? 'items' : 'item';
637
+							$error .= ". Minimum $info->min $item required.";
638
+							break;
639
+						}
640
+						if (isset ($info->max) && $r > $info->max) {
641
+							if ($info->fix) {
642
+								$input = array_slice($input, 0, $info->max);
643
+							} else {
644
+								$item = $info->max > 1 ? 'items' : 'item';
645
+								$error .= ". Maximum $info->max $item allowed.";
646
+								break;
647
+							}
648
+						}
649
+						if (
650
+							isset($contentType) &&
651
+							$contentType != 'associative' &&
652
+							$contentType != 'indexed'
653
+						) {
654
+							$name = $info->name;
655
+							$info->type = $contentType;
656
+							unset($info->contentType);
657
+							unset($info->min);
658
+							unset($info->max);
659
+							foreach ($input as $key => $chinput) {
660
+								$info->name = "{$name}[$key]";
661
+								$input[$key] = static::validate($chinput, $info);
662
+							}
663
+						}
664
+						return $input;
665
+					} elseif (isset($contentType)) {
666
+						$error .= '. Expecting items of type ' .
667
+							($html ? "<strong>$contentType</strong>" : "`$contentType`");
668
+						break;
669
+					}
670
+					break;
671
+				case 'mixed':
672
+				case 'unknown_type':
673
+				case 'unknown':
674
+				case null: //treat as unknown
675
+					return $input;
676
+				default :
677
+					if (!is_array($input)) {
678
+						break;
679
+					}
680
+					//do type conversion
681
+					if (class_exists($info->type)) {
682
+						$input = $info->filterArray($input, false);
683
+						$implements = class_implements($info->type);
684
+						if (
685
+							is_array($implements) &&
686
+							in_array('Luracast\\Restler\\Data\\iValueObject', $implements)
687
+						) {
688
+							return call_user_func(
689
+								"{$info->type}::__set_state", $input
690
+							);
691
+						}
692
+						$class = $info->type;
693
+						$instance = new $class();
694
+						if (is_array($info->children)) {
695
+							if (
696
+								empty($input) ||
697
+								!is_array($input) ||
698
+								$input === array_values($input)
699
+							) {
700
+								$error .= '. Expecting an item of type ' .
701
+									($html ? "<strong>$info->type</strong>" : "`$info->type`");
702
+								break;
703
+							}
704
+							foreach ($info->children as $key => $value) {
705
+								$cv = new ValidationInfo($value);
706
+								$cv->name = "{$info->name}[$key]";
707
+								if (array_key_exists($key, $input) || $cv->required) {
708
+									$instance->{$key} = static::validate(
709
+										Util::nestedValue($input, $key),
710
+										$cv
711
+									);
712
+								}
713
+							}
714
+						}
715
+						return $instance;
716
+					}
717
+			}
718
+			throw new RestException (400, $error);
719
+		} catch (\Exception $e) {
720
+			static::$exceptions[$info->name] = $e;
721
+			if (static::$holdException) {
722
+				return null;
723
+			}
724
+			throw $e;
725
+		}
726
+	}
727 727
 }
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/Data/ValidationInfo.php 1 patch
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.
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 1 patch
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.