Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like WebRequest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WebRequest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
39 | class WebRequest extends Request |
||
40 | { |
||
41 | /** |
||
42 | * @var string The protocol information of this request. |
||
43 | */ |
||
44 | protected $protocol = null; |
||
45 | |||
46 | /** |
||
47 | * @var string The current URL scheme. |
||
48 | */ |
||
49 | protected $urlScheme = ''; |
||
50 | |||
51 | /** |
||
52 | * @var string The current URL authority. |
||
53 | */ |
||
54 | protected $urlHost = ''; |
||
55 | |||
56 | /** |
||
57 | * @var string The current URL authority. |
||
58 | */ |
||
59 | protected $urlPort = 0; |
||
60 | |||
61 | /** |
||
62 | * @var string The current URL path. |
||
63 | */ |
||
64 | protected $urlPath = ''; |
||
65 | |||
66 | /** |
||
67 | * @var string The current URL query. |
||
68 | */ |
||
69 | protected $urlQuery = ''; |
||
70 | |||
71 | /** |
||
72 | * @var string The current request URL (path and query). |
||
73 | */ |
||
74 | protected $requestUri = ''; |
||
75 | |||
76 | /** |
||
77 | * @var string The current URL. |
||
78 | */ |
||
79 | protected $url = ''; |
||
80 | |||
81 | /** |
||
82 | * Get the request protocol information, e.g. "HTTP/1.1". |
||
83 | * |
||
84 | * @return string The protocol information. |
||
85 | * |
||
86 | * @author David Zülke <[email protected]> |
||
87 | * @since 0.11.0 |
||
88 | */ |
||
89 | public function getProtocol() |
||
90 | { |
||
91 | return $this->protocol; |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Retrieve the scheme part of a request URL, typically the protocol. |
||
96 | * Example: "http". |
||
97 | * |
||
98 | * @return string The request URL scheme. |
||
99 | * |
||
100 | * @author David Zülke <[email protected]> |
||
101 | * @since 0.11.0 |
||
102 | */ |
||
103 | public function getUrlScheme() |
||
104 | { |
||
105 | return $this->urlScheme; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Retrieve the hostname part of a request URL. |
||
110 | * |
||
111 | * @return string The request URL hostname. |
||
112 | * |
||
113 | * @author David Zülke <[email protected]> |
||
114 | * @since 0.11.0 |
||
115 | */ |
||
116 | public function getUrlHost() |
||
117 | { |
||
118 | return $this->urlHost; |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Retrieve the hostname part of a request URL. |
||
123 | * |
||
124 | * @return string The request URL hostname. |
||
125 | * |
||
126 | * @author David Zülke <[email protected]> |
||
127 | * @since 0.11.0 |
||
128 | */ |
||
129 | public function getUrlPort() |
||
130 | { |
||
131 | return $this->urlPort; |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Retrieve the request URL authority, typically host and port. |
||
136 | * Example: "foo.example.com:8080". |
||
137 | * |
||
138 | * @param bool $forcePort Whether or not ports 80 (for HTTP) and 433 (for HTTPS) |
||
139 | * should be included in the return string. |
||
140 | * |
||
141 | * @return string The request URL authority. |
||
142 | * |
||
143 | * @author David Zülke <[email protected]> |
||
144 | * @since 0.11.0 |
||
145 | */ |
||
146 | public function getUrlAuthority($forcePort = false) |
||
147 | { |
||
148 | $port = $this->getUrlPort(); |
||
149 | $scheme = $this->getUrlScheme(); |
||
150 | return $this->getUrlHost() . ($forcePort || Toolkit::isPortNecessary($scheme, $port) ? ':' . $port : ''); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Retrieve the relative part of the request URL, i.e. path and query. |
||
155 | * Example: "/foo/bar/baz?id=4815162342". |
||
156 | * |
||
157 | * @return string The relative URL of the current request. |
||
158 | * |
||
159 | * @author David Zülke <[email protected]> |
||
160 | * @since 0.11.0 |
||
161 | */ |
||
162 | public function getRequestUri() |
||
163 | { |
||
164 | return $this->requestUri; |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Retrieve the path part of the URL. |
||
169 | * Example: "/foo/bar/baz". |
||
170 | * |
||
171 | * @return string The path part of the URL. |
||
172 | * |
||
173 | * @author David Zülke <[email protected]> |
||
174 | * @since 0.11.0 |
||
175 | */ |
||
176 | public function getUrlPath() |
||
177 | { |
||
178 | return $this->urlPath; |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Retrieve the query part of the URL. |
||
183 | * Example: "id=4815162342". |
||
184 | * |
||
185 | * @return string The query part of the URL, or an empty string. |
||
186 | * |
||
187 | * @author David Zülke <[email protected]> |
||
188 | * @since 0.11.0 |
||
189 | */ |
||
190 | public function getUrlQuery() |
||
191 | { |
||
192 | return $this->urlQuery; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Retrieve the full request URL, including protocol, server name, port (if |
||
197 | * necessary), and request URI. |
||
198 | * Example: "http://foo.example.com:8080/foo/bar/baz?id=4815162342". |
||
199 | * |
||
200 | * @return string The URL of the current request. |
||
201 | * |
||
202 | * @author David Zülke <[email protected]> |
||
203 | * @since 0.11.0 |
||
204 | */ |
||
205 | public function getUrl() |
||
206 | { |
||
207 | return |
||
208 | $this->getUrlScheme() . '://' . |
||
209 | $this->getUrlAuthority() . |
||
210 | $this->getRequestUri(); |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Whether or not HTTPS was used for this request. |
||
215 | * |
||
216 | * @return bool True, if it's an HTTPS request, false otherwise. |
||
217 | * |
||
218 | * @author David Zülke <[email protected]> |
||
219 | * @since 0.11.6 |
||
220 | */ |
||
221 | public function isHttps() |
||
222 | { |
||
223 | return $this->getUrlScheme() == 'https'; |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * Constructor. |
||
228 | * |
||
229 | * @author David Zülke <[email protected]> |
||
230 | * @since 0.11.0 |
||
231 | */ |
||
232 | public function __construct() |
||
233 | { |
||
234 | parent::__construct(); |
||
235 | $this->setParameters(array( |
||
236 | 'request_data_holder_class' => 'Agavi\\Request\\WebRequestDataHolder', |
||
237 | )); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Clear magic quotes. Properly. That means keys are cleared, too. |
||
242 | * |
||
243 | * @param array $input An array of data to be put out of it's misery. |
||
244 | * |
||
245 | * @return array An array delivered from magic quotes. |
||
246 | * |
||
247 | * @author David Zülke <[email protected]> |
||
248 | * @since 0.11.0 |
||
249 | */ |
||
250 | final public static function clearMagicQuotes($input) |
||
251 | { |
||
252 | // this method only works with PHP 5.2.7+ |
||
253 | // there used to be special code for versions < 5.2.2 |
||
254 | // http://bugs.php.net/bug.php?id=41093 |
||
255 | // but we now require 5.2.8 anyway in combination with magic_quotes_gpc, see initialize() |
||
256 | // http://trac.agavi.org/ticket/953 |
||
257 | // http://trac.agavi.org/ticket/944 |
||
258 | // http://bugs.php.net/bug.php?id=41093 |
||
259 | |||
260 | $retval = array(); |
||
261 | |||
262 | foreach ($input as $key => $value) { |
||
263 | $key = stripslashes($key); |
||
264 | |||
265 | if (is_array($value)) { |
||
266 | $retval[$key] = self::clearMagicQuotes($value); |
||
267 | } elseif (is_string($value)) { |
||
268 | $retval[$key] = stripslashes($value); |
||
269 | } else { |
||
270 | $retval[$key] = $value; |
||
271 | } |
||
272 | } |
||
273 | |||
274 | return $retval; |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Initialize this Request. |
||
279 | * |
||
280 | * @param Context $context An Context instance. |
||
281 | * @param array $parameters An associative array of initialization parameters. |
||
282 | * |
||
283 | * @throws <b>AgaviInitializationException</b> If an error occurs while |
||
284 | * initializing this Request. |
||
285 | * |
||
286 | * @author Veikko Mäkinen <[email protected]> |
||
287 | * @author David Zülke <[email protected]> |
||
288 | * @since 0.9.0 |
||
289 | */ |
||
290 | public function initialize(Context $context, array $parameters = array()) |
||
291 | { |
||
292 | parent::initialize($context, $parameters); |
||
293 | |||
294 | $rla = ini_get('register_long_arrays'); |
||
295 | |||
296 | // very first thing to do: remove magic quotes |
||
297 | if (get_magic_quotes_gpc()) { |
||
298 | trigger_error('Support for php.ini directive "magic_quotes_gpc" is deprecated and will be dropped in Agavi 1.2. The setting is deprecated in PHP 5.3 and will be removed in PHP 5.4. Please refer to the PHP manual for details.', E_USER_DEPRECATED); |
||
299 | $_GET = self::clearMagicQuotes($_GET); |
||
300 | $_POST = self::clearMagicQuotes($_POST); |
||
301 | $_COOKIE = self::clearMagicQuotes($_COOKIE); |
||
302 | $_REQUEST = self::clearMagicQuotes($_REQUEST); |
||
303 | $_FILES = self::clearMagicQuotes($_FILES); |
||
304 | if ($rla) { |
||
305 | $GLOBALS['HTTP_GET_VARS'] = $_GET; |
||
306 | $GLOBALS['HTTP_POST_VARS'] = $_POST; |
||
307 | $GLOBALS['HTTP_COOKIE_VARS'] = $_COOKIE; |
||
308 | $GLOBALS['HTTP_POST_FILES'] = $_FILES; |
||
309 | } |
||
310 | } |
||
311 | |||
312 | $sources = array_merge(array( |
||
313 | 'HTTPS' => 'HTTPS', |
||
314 | 'REQUEST_METHOD' => 'REQUEST_METHOD', |
||
315 | 'SERVER_NAME' => 'SERVER_NAME', |
||
316 | 'SERVER_PORT' => 'SERVER_PORT', |
||
317 | 'SERVER_PROTOCOL' => 'SERVER_PROTOCOL', |
||
318 | 'SERVER_SOFTWARE' => 'SERVER_SOFTWARE', |
||
319 | ), (array)$this->getParameter('sources')); |
||
320 | $this->setParameter('sources', $sources); |
||
321 | |||
322 | // this is correct: if a user-supplied parameter was set, then null is used as the default return value, which means getSourceValue() returns the user-supplied parameter as a last resort if a key of the same name could not be found. allows setting of static values for any of those below |
||
323 | $sourceDefaults = array( |
||
324 | 'HTTPS' => isset($parameters['sources']['HTTPS']) ? null : 'off', |
||
325 | 'REQUEST_METHOD' => isset($parameters['sources']['REQUEST_METHOD']) ? null : 'GET', |
||
326 | 'SERVER_NAME' => null, |
||
327 | 'SERVER_PORT' => isset($parameters['sources']['SERVER_PORT']) ? null : $this->urlPort, |
||
328 | 'SERVER_PROTOCOL' => isset($parameters['sources']['SERVER_PROTOCOL']) ? null : 'HTTP/1.0', |
||
329 | 'SERVER_SOFTWARE' => null, |
||
330 | ); |
||
331 | |||
332 | $methods = array_merge(array( |
||
333 | 'GET' => 'read', |
||
334 | 'POST' => 'write', |
||
335 | 'PUT' => 'create', |
||
336 | 'DELETE' => 'remove', |
||
337 | ), (array)$this->getParameter('method_names')); |
||
338 | $this->setParameter('method_names', $methods); |
||
339 | |||
340 | $REQUEST_METHOD = self::getSourceValue($sources['REQUEST_METHOD'], $sourceDefaults['REQUEST_METHOD']); |
||
341 | |||
342 | // map REQUEST_METHOD value to a method name, or fall back to the default in $sourceDefaults. |
||
343 | // if someone set a static value as default for a source that does not have a mapping, then he's really asking for it, and thus out of luck |
||
344 | $this->setMethod($this->getParameter(sprintf('method_names[%s]', $REQUEST_METHOD), $this->getParameter(sprintf('method_names[%s]', $sourceDefaults['REQUEST_METHOD'])))); |
||
345 | |||
346 | $this->protocol = self::getSourceValue($sources['SERVER_PROTOCOL'], $sourceDefaults['SERVER_PROTOCOL']); |
||
347 | |||
348 | // "on" (e.g. Apache or IIS) or "https" (e.g. Amazon EC2 Elastic Load Balancer) or "1" or integer 1 or true (e.g. statically set from a config file) |
||
349 | $HTTPS = (bool)preg_match('/^(on|https|1)$/i', self::getSourceValue($sources['HTTPS'], $sourceDefaults['HTTPS'])); |
||
350 | |||
351 | $this->urlScheme = 'http' . ($HTTPS ? 's' : ''); |
||
352 | |||
353 | $this->urlPort = (int)self::getSourceValue($sources['SERVER_PORT'], $sourceDefaults['SERVER_PORT']); |
||
354 | |||
355 | $SERVER_NAME = self::getSourceValue($sources['SERVER_NAME'], $sourceDefaults['SERVER_NAME']); |
||
356 | $port = $this->getUrlPort(); |
||
357 | if (preg_match_all('/\:/', $SERVER_NAME, $m) > 1) { |
||
358 | $this->urlHost = preg_replace('/\]\:' . preg_quote($port, '/') . '$/', '', $SERVER_NAME); |
||
359 | } else { |
||
360 | $this->urlHost = preg_replace('/\:' . preg_quote($port, '/') . '$/', '', $SERVER_NAME); |
||
361 | } |
||
362 | |||
363 | $_SERVER['SERVER_SOFTWARE'] = self::getSourceValue($sources['SERVER_SOFTWARE'], $sourceDefaults['SERVER_SOFTWARE']); |
||
364 | |||
365 | if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('#^Apache(/\d+(\.\d+)?)?\.?$#', $_SERVER['SERVER_SOFTWARE'])) { |
||
366 | throw new AgaviException( |
||
367 | "You are running the Apache HTTP Server with a 'ServerTokens' configuration directive value of 'Minor' or lower.\n" . |
||
368 | "This directive controls the amount of version information Apache exposes about itself.\n" . |
||
369 | "Agavi needs detailed Apache version information to apply URL decoding and parsing workarounds specific to certain versions of Apache that exhibit buggy behavior.\n\n" . |
||
370 | "Please take one of the following measures to fix this problem:\n" . |
||
371 | "- raise your 'ServerTokens' level to 'Min' or higher in httpd.conf\n" . |
||
372 | "- set a static value for the request source 'SERVER_SOFTWARE' in factories.xml (for your environment)\n" . |
||
373 | "- set a value for \$_SERVER['SERVER_SOFTWARE'], e.g. in your pub/index.php\n\n" . |
||
374 | "For detailed instructions and examples on fixing this problem, especially for the factories.xml method which is recommended in case you do not have control over your server's httpd.conf, please refer to:\n" . |
||
375 | "http://trac.agavi.org/ticket/1029\n\n" . |
||
376 | "For more information on the 'ServerTokens' directive, please refer to:\n" . |
||
377 | "http://httpd.apache.org/docs/2.2/en/mod/core.html#servertokens\n\n" . |
||
378 | "For your reference, your SERVER_SOFTWARE string is currently '$_SERVER[SERVER_SOFTWARE]'." |
||
379 | ); |
||
380 | } |
||
381 | |||
382 | if (isset($_SERVER['UNENCODED_URL']) && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) { |
||
383 | // Microsoft IIS 7 with URL Rewrite Module |
||
384 | $this->requestUri = $_SERVER['UNENCODED_URL']; |
||
385 | } elseif (isset($_SERVER['HTTP_X_REWRITE_URL']) && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) { |
||
386 | // Microsoft IIS with ISAPI_Rewrite |
||
387 | $this->requestUri = $_SERVER['HTTP_X_REWRITE_URL']; |
||
388 | } elseif (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) { |
||
389 | // Microsoft IIS with PHP in CGI mode |
||
390 | $this->requestUri = $_SERVER['ORIG_PATH_INFO'] . (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' ? '?' . $_SERVER['QUERY_STRING'] : ''); |
||
391 | } elseif (isset($_SERVER['REQUEST_URI'])) { |
||
392 | $this->requestUri = $_SERVER['REQUEST_URI']; |
||
393 | } |
||
394 | |||
395 | // Microsoft IIS with PHP in CGI mode |
||
396 | if (!isset($_SERVER['QUERY_STRING'])) { |
||
397 | $_SERVER['QUERY_STRING'] = ''; |
||
398 | } |
||
399 | if (!isset($_SERVER['REQUEST_URI'])) { |
||
400 | $_SERVER['REQUEST_URI'] = $this->getRequestUri(); |
||
401 | } |
||
402 | |||
403 | // okay, this is really bad |
||
404 | // Internet Explorer (many versions, many OSes) seem to be sending improperly urlencoded URLs to the server, in violation of the HTTP RFC |
||
405 | // this can cause a number of problems, most notably html special chars not being escaped and potentially ending up this way in the output |
||
406 | // the result is an XSS attack vector, e.g. on WebRouting::gen(null) |
||
407 | // so we escape those. but not the ampersand, or the query string gets messed up |
||
408 | // we also encode the backtick (Suhosin does this, too), and the space character |
||
409 | // in theory, we shouldn't encode the single quote either, since it's a reserved sub-delimiter as per RFC 3986 - however, that would allow injection again in documents that use single quotes as attribute delimiters, and it's up to implementations to encode sub-delimiters if they deem it necessary |
||
410 | // great, huh? |
||
411 | // more details: |
||
412 | // http://trac.agavi.org/ticket/1019 |
||
413 | // http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0417 |
||
414 | list($this->requestUri, $_SERVER['REQUEST_URI']) = str_replace( |
||
415 | array(' ', '"', '\'', '<', '>', '`', /*'&'*/), |
||
416 | array('%20', '%22', '%27', '%3C', '%3E', '%60', /*'%26'*/), |
||
417 | array($this->requestUri, $_SERVER['REQUEST_URI']) |
||
418 | ); |
||
419 | if ($rla) { |
||
420 | $GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI'] = $this->getRequestUri(); |
||
421 | } |
||
422 | |||
423 | // 'scheme://authority' is necessary so parse_url doesn't stumble over '://' in the request URI |
||
424 | $parts = array_merge(array('path' => '', 'query' => ''), parse_url('scheme://authority' . $this->getRequestUri())); |
||
425 | $this->urlPath = $parts['path']; |
||
426 | $this->urlQuery = $parts['query']; |
||
427 | unset($parts); |
||
428 | |||
429 | $files = array(); |
||
430 | $ufc = $this->getParameter('uploaded_file_class', 'Agavi\Request\UploadedFile'); |
||
431 | |||
432 | if ($this->getMethod() == $methods['PUT']) { |
||
433 | if (isset($_SERVER['CONTENT_TYPE']) && $this->getParameter('http_put_decode_urlencoded', true) && preg_match('#^application/x-www-form-urlencoded(;[^;]+)*?$#', $_SERVER['CONTENT_TYPE'])) { |
||
434 | // urlencoded data was sent, we can decode that |
||
435 | parse_str(file_get_contents('php://input'), $_POST); |
||
436 | if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { |
||
437 | $_POST = self::clearMagicQuotes($_POST); |
||
438 | } |
||
439 | } else { |
||
440 | // some other data via PUT. we need to populate $_FILES manually |
||
441 | $httpBody = file_get_contents('php://input'); |
||
442 | |||
443 | $files = array( |
||
444 | $this->getParameter('http_put_file_name', 'put_file') => new $ufc(array( |
||
445 | 'name' => $this->getMethod(), |
||
446 | 'type' => isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : 'application/octet-stream', |
||
447 | 'size' => strlen($httpBody), |
||
448 | 'contents' => $httpBody, |
||
449 | 'error' => UPLOAD_ERR_OK, |
||
450 | 'is_uploaded_file' => false, |
||
451 | )) |
||
452 | ); |
||
453 | } |
||
454 | } elseif ($this->getMethod() == $methods['POST'] && (!isset($_SERVER['CONTENT_TYPE']) || (isset($_SERVER['CONTENT_TYPE']) && !preg_match('#^(application/x-www-form-urlencoded|multipart/form-data)(;[^;]+)*?$#', $_SERVER['CONTENT_TYPE'])))) { |
||
455 | // POST, but no regular urlencoded data or file upload. lets put the request payload into a file |
||
456 | $httpBody = file_get_contents('php://input'); |
||
457 | |||
458 | $files = array( |
||
459 | $this->getParameter('http_post_file_name', 'post_file') => new $ufc(array( |
||
460 | 'name' => $this->getMethod(), |
||
461 | 'type' => isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : 'application/octet-stream', |
||
462 | 'size' => strlen($httpBody), |
||
463 | 'contents' => $httpBody, |
||
464 | 'error' => UPLOAD_ERR_OK, |
||
465 | 'is_uploaded_file' => false, |
||
466 | )) |
||
467 | ); |
||
468 | } elseif ($this->getMethod() == $methods['POST'] && isset($_SERVER['CONTENT_TYPE']) && preg_match('#^multipart/form-data(;[^;]+)*?$#', $_SERVER['CONTENT_TYPE'])) { |
||
469 | $files = static::fixFilesArray($_FILES, $ufc); |
||
470 | } |
||
471 | |||
472 | $headers = array(); |
||
473 | foreach ($_SERVER as $key => $value) { |
||
474 | if (substr($key, 0, 5) == 'HTTP_') { |
||
475 | $headers[substr($key, 5)] = $value; |
||
476 | } elseif ($key == 'CONTENT_TYPE' || $key == 'CONTENT_LENGTH') { |
||
477 | // yeah, whatever, PHP... |
||
478 | $headers[$key] = $value; |
||
479 | } |
||
480 | } |
||
481 | |||
482 | $rdhc = $this->getParameter('request_data_holder_class'); |
||
483 | $this->setRequestData(new $rdhc(array( |
||
484 | constant("$rdhc::SOURCE_PARAMETERS") => array_merge($_GET, $_POST), |
||
485 | constant("$rdhc::SOURCE_COOKIES") => $_COOKIE, |
||
486 | constant("$rdhc::SOURCE_FILES") => $files, |
||
487 | constant("$rdhc::SOURCE_HEADERS") => $headers, |
||
488 | ))); |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Corrects the order of $_FILES for arrays of files. |
||
493 | * The cleaned up array of AgaviUploadedFile objects is returned. |
||
494 | * |
||
495 | * @param array $input The array to work on. |
||
496 | * @param string $uploadedFileClass Name of the wrapper uploaded file class to instantiate. |
||
497 | * @param array $input Array of indices used during recursion, initially empty. |
||
498 | * @param array $output Output buffer used during recursion, initially empty. |
||
499 | * |
||
500 | * @author David Zülke <[email protected]> |
||
501 | * @since 1.1.0 |
||
502 | */ |
||
503 | protected static function fixFilesArray($input, $uploadedFileClass = 'UploadedFile', $index = array(), &$output = array()) |
||
544 | |||
545 | /** |
||
546 | * Do any necessary startup work after initialization. |
||
547 | * |
||
548 | * This method is not called directly after initialize(). |
||
549 | * |
||
550 | * @author David Zülke <[email protected]> |
||
551 | * @since 0.11.0 |
||
552 | */ |
||
553 | public function startup() |
||
578 | } |
||
579 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: