diff --git a/flight/Engine.php b/flight/Engine.php index 89b6b72..e3af4a1 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -67,9 +67,7 @@ use flight\net\Route; */ class Engine { - /** - * @var array List of methods that can be extended in the Engine class. - */ + /** @var array List of methods that can be extended in the Engine class. */ private const MAPPABLE_METHODS = [ 'start', 'stop', 'route', 'halt', 'error', 'notFound', 'render', 'redirect', 'etag', 'lastModified', 'json', 'jsonp', @@ -298,7 +296,7 @@ class Engine */ public function get(?string $key = null) { - if (null === $key) { + if ($key === null) { return $this->vars; } @@ -344,8 +342,9 @@ class Engine */ public function clear(?string $key = null): void { - if (null === $key) { + if ($key === null) { $this->vars = []; + return; } @@ -367,7 +366,7 @@ class Engine * * @param array $middleware Middleware attached to the route. * @param array $params `$route->params`. - * @param string $event_name If this is the before or after method. + * @param 'before'|'after' $event_name If this is the before or after method. */ protected function processMiddleware(array $middleware, array $params, string $event_name): bool { @@ -376,23 +375,23 @@ class Engine foreach ($middleware as $middleware) { $middleware_object = false; - if ($event_name === 'before') { + if ($event_name === $this->dispatcher::FILTER_BEFORE) { // can be a callable or a class $middleware_object = (is_callable($middleware) === true ? $middleware - : (method_exists($middleware, 'before') === true - ? [$middleware, 'before'] + : (method_exists($middleware, $this->dispatcher::FILTER_BEFORE) === true + ? [$middleware, $this->dispatcher::FILTER_BEFORE] : false ) ); - } elseif ($event_name === 'after') { + } elseif ($event_name === $this->dispatcher::FILTER_AFTER) { // must be an object. No functions allowed here if ( is_object($middleware) === true && !($middleware instanceof Closure) - && method_exists($middleware, 'after') === true + && method_exists($middleware, $this->dispatcher::FILTER_AFTER) === true ) { - $middleware_object = [$middleware, 'after']; + $middleware_object = [$middleware, $this->dispatcher::FILTER_AFTER]; } } @@ -532,9 +531,7 @@ class Engine public function _error(Throwable $e): void { $msg = sprintf( - '

500 Internal Server Error

' . - '

%s (%s)

' . - '
%s
', + '

500 Internal Server Error

%s (%s)

%s
', $e->getMessage(), $e->getCode(), $e->getTraceAsString() @@ -565,7 +562,7 @@ class Engine $response = $this->response(); if (!$response->sent()) { - if (null !== $code) { + if ($code !== null) { $response->status($code); } @@ -633,8 +630,12 @@ class Engine * @param callable $callback Callback function * @param bool $pass_route Pass the matching route object to the callback */ - public function _patch(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void - { + public function _patch( + string $pattern, + callable $callback, + bool $pass_route = false, + string $route_alias = '' + ): void { $this->router()->map('PATCH ' . $pattern, $callback, $pass_route, $route_alias); } @@ -645,8 +646,12 @@ class Engine * @param callable $callback Callback function * @param bool $pass_route Pass the matching route object to the callback */ - public function _delete(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void - { + public function _delete( + string $pattern, + callable $callback, + bool $pass_route = false, + string $route_alias = '' + ): void { $this->router()->map('DELETE ' . $pattern, $callback, $pass_route, $route_alias); } @@ -688,14 +693,10 @@ class Engine */ public function _redirect(string $url, int $code = 303): void { - $base = $this->get('flight.base_url'); - - if (null === $base) { - $base = $this->request()->base; - } + $base = $this->get('flight.base_url') ?? $this->request()->base; // Append base url to redirect url - if ('/' !== $base && false === strpos($url, '://')) { + if ($base !== '/' && strpos($url, '://') === false) { $url = $base . preg_replace('#/+#', '/', '/' . $url); } @@ -717,8 +718,9 @@ class Engine */ public function _render(string $file, ?array $data = null, ?string $key = null): void { - if (null !== $key) { + if ($key !== null) { $this->view()->set($key, $this->view()->fetch($file, $data)); + return; } @@ -790,7 +792,7 @@ class Engine */ public function _etag(string $id, string $type = 'strong'): void { - $id = (('weak' === $type) ? 'W/' : '') . $id; + $id = (($type === 'weak') ? 'W/' : '') . $id; $this->response()->header('ETag', '"' . str_replace('"', '\"', $id) . '"'); diff --git a/flight/net/Request.php b/flight/net/Request.php index eb932c0..b322ae3 100644 --- a/flight/net/Request.php +++ b/flight/net/Request.php @@ -151,7 +151,7 @@ class Request 'method' => self::getMethod(), 'referrer' => self::getVar('HTTP_REFERER'), 'ip' => self::getVar('REMOTE_ADDR'), - 'ajax' => 'XMLHttpRequest' === self::getVar('HTTP_X_REQUESTED_WITH'), + 'ajax' => self::getVar('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest', 'scheme' => self::getScheme(), 'user_agent' => self::getVar('HTTP_USER_AGENT'), 'type' => self::getVar('CONTENT_TYPE'), @@ -160,7 +160,7 @@ class Request 'data' => new Collection($_POST), 'cookies' => new Collection($_COOKIE), 'files' => new Collection($_FILES), - 'secure' => 'https' === self::getScheme(), + 'secure' => self::getScheme() === 'https', 'accept' => self::getVar('HTTP_ACCEPT'), 'proxy_ip' => self::getProxyIpAddress(), 'host' => self::getVar('HTTP_HOST'), @@ -188,7 +188,7 @@ class Request // This rewrites the url in case the public url and base directories match // (such as installing on a subdirectory in a web server) // @see testInitUrlSameAsBaseDirectory - if ('/' !== $this->base && '' !== $this->base && 0 === strpos($this->url, $this->base)) { + if ($this->base !== '/' && $this->base !== '' && strpos($this->url, $this->base) === 0) { $this->url = substr($this->url, \strlen($this->base)); } @@ -203,9 +203,10 @@ class Request } // Check for JSON input - if (0 === strpos($this->type, 'application/json')) { + if (strpos($this->type, 'application/json') === 0) { $body = $this->getBody(); - if ('' !== $body) { + + if ($body !== '') { $data = json_decode($body, true); if (is_array($data)) { $this->data->setData($data); @@ -225,14 +226,17 @@ class Request { $body = $this->body; - if ('' !== $body) { + if ($body !== '') { return $body; } - $method = self::getMethod(); - - if ('POST' === $method || 'PUT' === $method || 'DELETE' === $method || 'PATCH' === $method) { - $body = file_get_contents($this->stream_path); + switch (self::getMethod()) { + case 'POST': + case 'PUT': + case 'DELETE': + case 'PATCH': + $body = file_get_contents($this->stream_path); + break; } $this->body = $body; @@ -277,7 +281,8 @@ class Request foreach ($forwarded as $key) { if (\array_key_exists($key, $_SERVER)) { sscanf($_SERVER[$key], '%[^,]', $ip); - if (false !== filter_var($ip, \FILTER_VALIDATE_IP, $flags)) { + + if (filter_var($ip, \FILTER_VALIDATE_IP, $flags) !== false) { return $ip; } } @@ -321,13 +326,15 @@ class Request public static function getHeaders(): array { $headers = []; + foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, 'HTTP_')) { + if (strpos($key, 'HTTP_') === 0) { // converts headers like HTTP_CUSTOM_HEADER to Custom-Header $key = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5))))); $headers[$key] = $value; } } + return $headers; } @@ -336,10 +343,8 @@ class Request * * @param string $header Header name. Can be caps, lowercase, or mixed. * @param string $default Default value if the header does not exist - * - * @return string */ - public static function header(string $header, $default = '') + public static function header(string $header, $default = ''): string { return self::getHeader($header, $default); } @@ -354,21 +359,13 @@ class Request return self::getHeaders(); } - /** - * Gets the full request URL. - * - * @return string URL - */ + /** Gets the full request URL. */ public function getFullUrl(): string { return $this->scheme . '://' . $this->host . $this->url; } - /** - * Grabs the scheme and host. Does not end with a / - * - * @return string - */ + /** Grabs the scheme and host. Does not end with a / */ public function getBaseUrl(): string { return $this->scheme . '://' . $this->host; @@ -396,18 +393,18 @@ class Request /** * Gets the URL Scheme * - * @return string 'http'|'https' + * @return 'http'|'https' */ public static function getScheme(): string { if ( - (isset($_SERVER['HTTPS']) && 'on' === strtolower($_SERVER['HTTPS'])) + (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on') || - (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO']) + (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') || - (isset($_SERVER['HTTP_FRONT_END_HTTPS']) && 'on' === $_SERVER['HTTP_FRONT_END_HTTPS']) + (isset($_SERVER['HTTP_FRONT_END_HTTPS']) && $_SERVER['HTTP_FRONT_END_HTTPS'] === 'on') || - (isset($_SERVER['REQUEST_SCHEME']) && 'https' === $_SERVER['REQUEST_SCHEME']) + (isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] === 'https') ) { return 'https'; } diff --git a/flight/net/Response.php b/flight/net/Response.php index 761d1a6..291e84e 100644 --- a/flight/net/Response.php +++ b/flight/net/Response.php @@ -139,7 +139,7 @@ class Response */ public function status(?int $code = null) { - if (null === $code) { + if ($code === null) { return $this->status; } @@ -263,19 +263,22 @@ class Response */ public function cache($expires): self { - if (false === $expires) { + if ($expires === false) { $this->headers['Expires'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; + $this->headers['Cache-Control'] = [ 'no-store, no-cache, must-revalidate', 'post-check=0, pre-check=0', 'max-age=0', ]; + $this->headers['Pragma'] = 'no-cache'; } else { $expires = \is_int($expires) ? $expires : strtotime($expires); $this->headers['Expires'] = gmdate('D, d M Y H:i:s', $expires) . ' GMT'; $this->headers['Cache-Control'] = 'max-age=' . ($expires - time()); - if (isset($this->headers['Pragma']) && 'no-cache' == $this->headers['Pragma']) { + + if (isset($this->headers['Pragma']) && $this->headers['Pragma'] === 'no-cache') { unset($this->headers['Pragma']); } } @@ -291,7 +294,7 @@ class Response public function sendHeaders(): self { // Send status code header - if (false !== strpos(\PHP_SAPI, 'cgi')) { + if (strpos(\PHP_SAPI, 'cgi') !== false) { // @codeCoverageIgnoreStart $this->setRealHeader( sprintf( diff --git a/flight/net/Route.php b/flight/net/Route.php index 2070cc6..e73906b 100644 --- a/flight/net/Route.php +++ b/flight/net/Route.php @@ -95,7 +95,7 @@ class Route public function matchUrl(string $url, bool $case_sensitive = false): bool { // Wildcard or exact match - if ('*' === $this->pattern || $this->pattern === $url) { + if ($this->pattern === '*' || $this->pattern === $url) { return true; } @@ -110,8 +110,9 @@ class Route for ($i = 0; $i < $len; $i++) { if ($url[$i] === '/') { - $n++; + ++$n; } + if ($n === $count) { break; } @@ -136,24 +137,20 @@ class Route $regex ); - if ('/' === $last_char) { // Fix trailing slash - $regex .= '?'; - } else { // Allow trailing slash - $regex .= '/?'; - } + $regex .= $last_char === '/' ? '?' : '/?'; // Attempt to match route and named parameters - if (preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($case_sensitive) ? '' : 'i'), $url, $matches)) { - foreach ($ids as $k => $v) { - $this->params[$k] = (\array_key_exists($k, $matches)) ? urldecode($matches[$k]) : null; - } - - $this->regex = $regex; + if (!preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($case_sensitive) ? '' : 'i'), $url, $matches)) { + return false; + } - return true; + foreach (array_keys($ids) as $k) { + $this->params[$k] = (\array_key_exists($k, $matches)) ? urldecode($matches[$k]) : null; } - return false; + $this->regex = $regex; + + return true; } /** diff --git a/flight/net/Router.php b/flight/net/Router.php index 895b337..2387baa 100644 --- a/flight/net/Router.php +++ b/flight/net/Router.php @@ -96,7 +96,7 @@ class Router $methods = ['*']; - if (false !== strpos($url, ' ')) { + if (strpos($url, ' ') !== false) { [$method, $url] = explode(' ', $url, 2); $url = trim($url); $methods = explode('|', $method); @@ -211,10 +211,12 @@ class Router public function route(Request $request) { $url_decoded = urldecode($request->url); + while ($route = $this->current()) { if ($route->matchMethod($request->method) && $route->matchUrl($url_decoded, $this->case_sensitive)) { return $route; } + $this->next(); } diff --git a/flight/template/View.php b/flight/template/View.php index d1bc07f..c43a35f 100644 --- a/flight/template/View.php +++ b/flight/template/View.php @@ -88,7 +88,7 @@ class View */ public function clear(?string $key = null): self { - if (null === $key) { + if ($key === null) { $this->vars = []; } else { unset($this->vars[$key]); @@ -169,7 +169,7 @@ class View $is_windows = \strtoupper(\substr(PHP_OS, 0, 3)) === 'WIN'; - if (('/' == \substr($file, 0, 1)) || ($is_windows === true && ':' == \substr($file, 1, 1))) { + if ((\substr($file, 0, 1) === '/') || ($is_windows && \substr($file, 1, 1) === ':')) { return $file; } diff --git a/flight/util/Collection.php b/flight/util/Collection.php index 6ffe0b5..e17ed37 100644 --- a/flight/util/Collection.php +++ b/flight/util/Collection.php @@ -95,7 +95,7 @@ class Collection implements ArrayAccess, Iterator, Countable, JsonSerializable #[\ReturnTypeWillChange] public function offsetSet($offset, $value): void { - if (null === $offset) { + if ($offset === null) { $this->data[] = $value; } else { $this->data[$offset] = $value; @@ -166,9 +166,7 @@ class Collection implements ArrayAccess, Iterator, Countable, JsonSerializable */ public function valid(): bool { - $key = key($this->data); - - return null !== $key; + return key($this->data) !== null; } /** diff --git a/flight/util/ReturnTypeWillChange.php b/flight/util/ReturnTypeWillChange.php index 31a929b..1eba39e 100644 --- a/flight/util/ReturnTypeWillChange.php +++ b/flight/util/ReturnTypeWillChange.php @@ -3,7 +3,6 @@ declare(strict_types=1); // This file is only here so that the PHP8 attribute for doesn't throw an error in files -// phpcs:ignoreFile PSR1.Classes.ClassDeclaration.MissingNamespace class ReturnTypeWillChange { } diff --git a/phpcs.xml b/phpcs.xml index 8f8acb6..bafe06d 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -18,31 +18,34 @@ + - + + + + - - - - - - - - - - - + + + + + + + + + + flight/ tests/ tests/views/* diff --git a/tests/RedirectTest.php b/tests/RedirectTest.php index e44186e..07698eb 100644 --- a/tests/RedirectTest.php +++ b/tests/RedirectTest.php @@ -21,7 +21,7 @@ class RedirectTest extends TestCase public function getBaseUrl($base, $url) { - if ('/' !== $base && false === strpos($url, '://')) { + if ($base !== '/' && strpos($url, '://') === false) { $url = preg_replace('#/+#', '/', $base . '/' . $url); } @@ -67,11 +67,7 @@ class RedirectTest extends TestCase public function testBaseOverride() { $url = 'login'; - if (null !== $this->app->get('flight.base_url')) { - $base = $this->app->get('flight.base_url'); - } else { - $base = $this->app->request()->base; - } + $base = $this->app->get('flight.base_url') ?? $this->app->request()->base; self::assertEquals('/testdir/login', $this->getBaseUrl($base, $url)); }