PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.20
Booking for Appointments and Events Calendar – Amelia v1.2.20
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / guzzlehttp / guzzle / src / UriTemplate.php
ameliabooking / vendor / guzzlehttp / guzzle / src Last commit date
Cookie 2 years ago Exception 3 years ago Handler 3 years ago Client.php 3 years ago ClientInterface.php 3 years ago HandlerStack.php 3 years ago MessageFormatter.php 3 years ago Middleware.php 3 years ago Pool.php 3 years ago PrepareBodyMiddleware.php 3 years ago RedirectMiddleware.php 2 years ago RequestOptions.php 5 years ago RetryMiddleware.php 3 years ago TransferStats.php 3 years ago UriTemplate.php 5 years ago Utils.php 3 years ago functions.php 5 years ago functions_include.php 5 years ago
UriTemplate.php
238 lines
1 <?php
2 namespace AmeliaGuzzleHttp;
3
4 /**
5 * Expands URI templates. Userland implementation of PECL uri_template.
6 *
7 * @link http://tools.ietf.org/html/rfc6570
8 */
9 class UriTemplate
10 {
11 /** @var string URI template */
12 private $template;
13
14 /** @var array Variables to use in the template expansion */
15 private $variables;
16
17 /** @var array Hash for quick operator lookups */
18 private static $operatorHash = [
19 '' => ['prefix' => '', 'joiner' => ',', 'query' => false],
20 '+' => ['prefix' => '', 'joiner' => ',', 'query' => false],
21 '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
22 '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
23 '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
24 ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
25 '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
26 '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
27 ];
28
29 /** @var array Delimiters */
30 private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
31 '&', '\'', '(', ')', '*', '+', ',', ';', '='];
32
33 /** @var array Percent encoded delimiters */
34 private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
35 '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
36 '%3B', '%3D'];
37
38 public function expand($template, array $variables)
39 {
40 if (false === strpos($template, '{')) {
41 return $template;
42 }
43
44 $this->template = $template;
45 $this->variables = $variables;
46
47 return preg_replace_callback(
48 '/\{([^\}]+)\}/',
49 [$this, 'expandMatch'],
50 $this->template
51 );
52 }
53
54 /**
55 * Parse an expression into parts
56 *
57 * @param string $expression Expression to parse
58 *
59 * @return array Returns an associative array of parts
60 */
61 private function parseExpression($expression)
62 {
63 $result = [];
64
65 if (isset(self::$operatorHash[$expression[0]])) {
66 $result['operator'] = $expression[0];
67 $expression = substr($expression, 1);
68 } else {
69 $result['operator'] = '';
70 }
71
72 foreach (explode(',', $expression) as $value) {
73 $value = trim($value);
74 $varspec = [];
75 if ($colonPos = strpos($value, ':')) {
76 $varspec['value'] = substr($value, 0, $colonPos);
77 $varspec['modifier'] = ':';
78 $varspec['position'] = (int) substr($value, $colonPos + 1);
79 } elseif (substr($value, -1) === '*') {
80 $varspec['modifier'] = '*';
81 $varspec['value'] = substr($value, 0, -1);
82 } else {
83 $varspec['value'] = (string) $value;
84 $varspec['modifier'] = '';
85 }
86 $result['values'][] = $varspec;
87 }
88
89 return $result;
90 }
91
92 /**
93 * Process an expansion
94 *
95 * @param array $matches Matches met in the preg_replace_callback
96 *
97 * @return string Returns the replacement string
98 */
99 private function expandMatch(array $matches)
100 {
101 static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
102
103 $replacements = [];
104 $parsed = self::parseExpression($matches[1]);
105 $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
106 $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
107 $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
109 foreach ($parsed['values'] as $value) {
110 if (!isset($this->variables[$value['value']])) {
111 continue;
112 }
113
114 $variable = $this->variables[$value['value']];
115 $actuallyUseQuery = $useQuery;
116 $expanded = '';
117
118 if (is_array($variable)) {
119 $isAssoc = $this->isAssoc($variable);
120 $kvp = [];
121 foreach ($variable as $key => $var) {
122 if ($isAssoc) {
123 $key = rawurlencode($key);
124 $isNestedArray = is_array($var);
125 } else {
126 $isNestedArray = false;
127 }
128
129 if (!$isNestedArray) {
130 $var = rawurlencode($var);
131 if ($parsed['operator'] === '+' ||
132 $parsed['operator'] === '#'
133 ) {
134 $var = $this->decodeReserved($var);
135 }
136 }
137
138 if ($value['modifier'] === '*') {
139 if ($isAssoc) {
140 if ($isNestedArray) {
141 // Nested arrays must allow for deeply nested
142 // structures.
143 $var = strtr(
144 http_build_query([$key => $var]),
145 $rfc1738to3986
146 );
147 } else {
148 $var = $key . '=' . $var;
149 }
150 } elseif ($key > 0 && $actuallyUseQuery) {
151 $var = $value['value'] . '=' . $var;
152 }
153 }
154
155 $kvp[$key] = $var;
156 }
157
158 if (empty($variable)) {
159 $actuallyUseQuery = false;
160 } elseif ($value['modifier'] === '*') {
161 $expanded = implode($joiner, $kvp);
162 if ($isAssoc) {
163 // Don't prepend the value name when using the explode
164 // modifier with an associative array.
165 $actuallyUseQuery = false;
166 }
167 } else {
168 if ($isAssoc) {
169 // When an associative array is encountered and the
170 // explode modifier is not set, then the result must be
171 // a comma separated list of keys followed by their
172 // respective values.
173 foreach ($kvp as $k => &$v) {
174 $v = $k . ',' . $v;
175 }
176 }
177 $expanded = implode(',', $kvp);
178 }
179 } else {
180 if ($value['modifier'] === ':') {
181 $variable = substr($variable, 0, $value['position']);
182 }
183 $expanded = rawurlencode($variable);
184 if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
185 $expanded = $this->decodeReserved($expanded);
186 }
187 }
188
189 if ($actuallyUseQuery) {
190 if (!$expanded && $joiner !== '&') {
191 $expanded = $value['value'];
192 } else {
193 $expanded = $value['value'] . '=' . $expanded;
194 }
195 }
196
197 $replacements[] = $expanded;
198 }
199
200 $ret = implode($joiner, $replacements);
201 if ($ret && $prefix) {
202 return $prefix . $ret;
203 }
204
205 return $ret;
206 }
207
208 /**
209 * Determines if an array is associative.
210 *
211 * This makes the assumption that input arrays are sequences or hashes.
212 * This assumption is a tradeoff for accuracy in favor of speed, but it
213 * should work in almost every case where input is supplied for a URI
214 * template.
215 *
216 * @param array $array Array to check
217 *
218 * @return bool
219 */
220 private function isAssoc(array $array)
221 {
222 return $array && array_keys($array)[0] !== 0;
223 }
224
225 /**
226 * Removes percent encoding on reserved characters (used with + and #
227 * modifiers).
228 *
229 * @param string $string String to fix
230 *
231 * @return string
232 */
233 private function decodeReserved($string)
234 {
235 return str_replace(self::$delimsPct, self::$delims, $string);
236 }
237 }
238