diff --git a/flight.sublime-project b/flight.sublime-project index 2040dbf..536f644 100644 --- a/flight.sublime-project +++ b/flight.sublime-project @@ -6,6 +6,7 @@ } ], "settings": { + "SublimeLinter.linters.phpstan.executable": "${project_path}/vendor/bin/phpstan.bat", "LSP": { "LSP-intelephense": { "settings": { diff --git a/flight/Engine.php b/flight/Engine.php index 32a1a70..543dbb6 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -63,7 +63,6 @@ use flight\net\Route; * @method void etag($id, string $type = 'strong') Handles ETag HTTP caching. * @method void lastModified(int $time) Handles last modified HTTP caching. */ -// phpcs:ignoreFile Generic.Files.LineLength.TooLong, PSR2.Methods.MethodDeclaration.Underscore class Engine { /** @@ -243,13 +242,21 @@ class Engine /** * Registers a class to a framework method. - * @template T of object * - * @param string $name Method name - * @param class-string $class Class name - * @param array $params Class initialization parameters - * @param ?callable(T $instance): void $callback Function to call after object instantiation + * # Usage example: + * ``` + * $app = new Engine; + * $app->register('user', User::class); + * + * $app->user(); # <- Return a User instance + * ``` + * + * @param string $name Method name + * @param class-string $class Class name + * @param array $params Class initialization parameters + * @param ?Closure(T $instance): void $callback Function to call after object instantiation * + * @template T of object * @throws Exception If trying to map over a framework method */ public function register(string $name, string $class, array $params = [], ?callable $callback = null): void @@ -270,8 +277,8 @@ class Engine /** * Adds a pre-filter to a method. * - * @param string $name Method name - * @param callable $callback Callback function + * @param string $name Method name + * @param Closure(array &$params, string &$output): (void|false) $callback */ public function before(string $name, callable $callback): void { @@ -281,8 +288,8 @@ class Engine /** * Adds a post-filter to a method. * - * @param string $name Method name - * @param callable $callback Callback function + * @param string $name Method name + * @param Closure(array &$params, string &$output): (void|false) $callback */ public function after(string $name, callable $callback): void { @@ -292,9 +299,9 @@ class Engine /** * Gets a variable. * - * @param string|null $key Key + * @param ?string $key Variable name * - * @return array|mixed|null + * @return mixed Variable value or `null` if `$key` doesn't exists. */ public function get(?string $key = null) { @@ -308,24 +315,27 @@ class Engine /** * Sets a variable. * - * @param mixed $key Key - * @param mixed|null $value Value + * @param string|iterable $key + * Variable name as `string` or an iterable of `'varName' => $varValue` + * @param mixed $value Ignored if `$key` is an `iterable` */ public function set($key, $value = null): void { - if (\is_array($key) || \is_object($key)) { + if (\is_iterable($key)) { foreach ($key as $k => $v) { $this->vars[$k] = $v; } - } else { - $this->vars[$key] = $value; + + return; } + + $this->vars[$key] = $value; } /** * Checks if a variable has been set. * - * @param string $key Key + * @param string $key Variable name * * @return bool Variable status */ @@ -337,15 +347,16 @@ class Engine /** * Unsets a variable. If no key is passed in, clear all variables. * - * @param string|null $key Key + * @param ?string $key Variable name, if `$key` isn't provided, it clear all variables. */ public function clear(?string $key = null): void { if (null === $key) { $this->vars = []; - } else { - unset($this->vars[$key]); + return; } + + unset($this->vars[$key]); } /** @@ -478,7 +489,7 @@ class Engine * * @param Throwable $e Thrown exception */ - public function _error($e): void + public function _error(Throwable $e): void { $msg = sprintf( '

500 Internal Server Error

' . @@ -505,7 +516,7 @@ class Engine /** * Stops the framework and outputs the current response. * - * @param int|null $code HTTP status code + * @param ?int $code HTTP status code * * @throws Exception */ @@ -558,9 +569,9 @@ class Engine * @param callable $callback Callback function * @param bool $pass_route Pass the matching route object to the callback */ - public function _post(string $pattern, callable $callback, bool $pass_route = false): void + public function _post(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void { - $this->router()->map('POST ' . $pattern, $callback, $pass_route); + $this->router()->map('POST ' . $pattern, $callback, $pass_route, $route_alias); } /** @@ -570,9 +581,9 @@ class Engine * @param callable $callback Callback function * @param bool $pass_route Pass the matching route object to the callback */ - public function _put(string $pattern, callable $callback, bool $pass_route = false): void + public function _put(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void { - $this->router()->map('PUT ' . $pattern, $callback, $pass_route); + $this->router()->map('PUT ' . $pattern, $callback, $pass_route, $route_alias); } /** @@ -582,9 +593,9 @@ 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): void + public function _patch(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void { - $this->router()->map('PATCH ' . $pattern, $callback, $pass_route); + $this->router()->map('PATCH ' . $pattern, $callback, $pass_route, $route_alias); } /** @@ -594,9 +605,9 @@ 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): void + public function _delete(string $pattern, callable $callback, bool $pass_route = false, string $route_alias = ''): void { - $this->router()->map('DELETE ' . $pattern, $callback, $pass_route); + $this->router()->map('DELETE ' . $pattern, $callback, $pass_route, $route_alias); } /** @@ -618,9 +629,7 @@ class Engine } } - /** - * Sends an HTTP 404 response when a URL is not found. - */ + /** Sends an HTTP 404 response when a URL is not found. */ public function _notFound(): void { $this->response() @@ -637,7 +646,7 @@ class Engine * Redirects the current request to another URL. * * @param string $url URL - * @param int $code HTTP status code + * @param int $code HTTP status code */ public function _redirect(string $url, int $code = 303): void { @@ -662,29 +671,30 @@ class Engine /** * Renders a template. * - * @param string $file Template file + * @param string $file Template file * @param ?array $data Template data - * @param string|null $key View variable name + * @param ?string $key View variable name * - * @throws Exception + * @throws Exception If template file wasn't found */ public function _render(string $file, ?array $data = null, ?string $key = null): void { if (null !== $key) { $this->view()->set($key, $this->view()->fetch($file, $data)); - } else { - $this->view()->render($file, $data); + return; } + + $this->view()->render($file, $data); } /** * Sends a JSON response. * - * @param mixed $data JSON data - * @param int $code HTTP status code - * @param bool $encode Whether to perform JSON encoding + * @param mixed $data JSON data + * @param int $code HTTP status code + * @param bool $encode Whether to perform JSON encoding * @param string $charset Charset - * @param int $option Bitmask Json constant such as JSON_HEX_QUOT + * @param int $option Bitmask Json constant such as JSON_HEX_QUOT * * @throws Exception */ @@ -707,12 +717,12 @@ class Engine /** * Sends a JSONP response. * - * @param mixed $data JSON data - * @param string $param Query parameter that specifies the callback name. - * @param int $code HTTP status code - * @param bool $encode Whether to perform JSON encoding + * @param mixed $data JSON data + * @param string $param Query parameter that specifies the callback name. + * @param int $code HTTP status code + * @param bool $encode Whether to perform JSON encoding * @param string $charset Charset - * @param int $option Bitmask Json constant such as JSON_HEX_QUOT + * @param int $option Bitmask Json constant such as JSON_HEX_QUOT * * @throws Exception */ @@ -725,7 +735,6 @@ class Engine int $option = 0 ): void { $json = $encode ? json_encode($data, $option) : $data; - $callback = $this->request()->query[$param]; $this->response() @@ -738,8 +747,8 @@ class Engine /** * Handles ETag HTTP caching. * - * @param string $id ETag identifier - * @param string $type ETag type + * @param string $id ETag identifier + * @param 'strong'|'weak' $type ETag type */ public function _etag(string $id, string $type = 'strong'): void { diff --git a/flight/Flight.php b/flight/Flight.php index 1f1d2ae..c2bcf28 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -12,74 +12,71 @@ use flight\net\Route; /** * The Flight class is a static representation of the framework. + * * @license MIT, http://flightphp.com/license * @copyright Copyright (c) 2011, Mike Cao * * # Core methods * @method static void start() Starts the framework. * @method static void path(string $path) Adds a path for autoloading classes. - * @method static void stop() Stops the framework and sends a response. + * @method static void stop(?int $code = null) Stops the framework and sends a response. * @method static void halt(int $code = 200, string $message = '') * Stop the framework with an optional status code and message. * * # Routing - * @method static Route route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') + * @method static Route route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') * Maps a URL pattern to a callback with all applicable methods. - * @method static void group(string $pattern, callable $callback, array $group_middlewares = []) + * @method static void group(string $pattern, callable $callback, callable[] $group_middlewares = []) * Groups a set of routes together under a common prefix. - * @method static Route post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') + * @method static Route post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') * Routes a POST URL to a callback function. - * @method static Route put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') + * @method static Route put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') * Routes a PUT URL to a callback function. - * @method static Route patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') + * @method static Route patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') * Routes a PATCH URL to a callback function. - * @method static Route delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') + * @method static Route delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') * Routes a DELETE URL to a callback function. - * @method static Router router() Returns Router instance. - * @method static string getUrl(string $alias) Gets a url from an alias + * @method static Router router() Returns Router instance. + * @method static string getUrl(string $alias, array $params = []) Gets a url from an alias * - * @method static void map(string $name, callable $callback) Creates a custom framework method. + * @method static void map(string $name, callable $callback) Creates a custom framework method. * - * @method static void before($name, $callback) Adds a filter before a framework method. - * @method static void after($name, $callback) Adds a filter after a framework method. + * @method static void before(string $name, Closure(array &$params, string &$output): (void|false) $callback) + * Adds a filter before a framework method. + * @method static void after(string $name, Closure(array &$params, string &$output): (void|false) $callback) + * Adds a filter after a framework method. * - * @method static void set($key, $value) Sets a variable. - * @method static mixed get($key) Gets a variable. - * @method static bool has($key) Checks if a variable is set. - * @method static void clear($key = null) Clears a variable. + * @method static void set(string|iterable $key, mixed $value) Sets a variable. + * @method static mixed get(?string $key) Gets a variable. + * @method static bool has(string $key) Checks if a variable is set. + * @method static void clear(?string $key = null) Clears a variable. * * # Views - * @method static void render($file, array $data = null, $key = null) Renders a template file. - * @method static View view() Returns View instance. + * @method static void render(string $file, ?array $data = null, ?string $key = null) + * Renders a template file. + * @method static View view() Returns View instance. * * # Request-Response - * @method static Request request() Returns Request instance. - * @method static Response response() Returns Response instance. - * @method static void redirect($url, $code = 303) Redirects to another URL. - * @method static void json($data, $code = 200, $encode = true, $charset = "utf8", $encodeOption = 0, $encodeDepth = 512) Sends a JSON response. - * @method static void jsonp($data, $param = 'jsonp', $code = 200, $encode = true, $charset = "utf8", $encodeOption = 0, $encodeDepth = 512) Sends a JSONP response. - * @method static void error($exception) Sends an HTTP 500 response. - * @method static void notFound() Sends an HTTP 404 response. + * @method static Request request() Returns Request instance. + * @method static Response response() Returns Response instance. + * @method static void redirect(string $url, int $code = 303) Redirects to another URL. + * @method static void json(mixed $data, int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512) + * Sends a JSON response. + * @method static void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512) + * Sends a JSONP response. + * @method static void error(Throwable $exception) Sends an HTTP 500 response. + * @method static void notFound() Sends an HTTP 404 response. * * # HTTP caching - * @method static void etag($id, $type = 'strong') Performs ETag HTTP caching. - * @method static void lastModified($time) Performs last modified HTTP caching. + * @method static void etag(string $id, 'strong'|'weak' $type = 'strong') Performs ETag HTTP caching. + * @method static void lastModified(int $time) Performs last modified HTTP caching. */ -// phpcs:ignoreFile Generic.Files.LineLength.TooLong, PSR1.Classes.ClassDeclaration.MissingNamespace -class Flight +class Flight { - /** - * Framework engine. - * - * @var Engine $engine - */ + /** Framework engine. */ private static Engine $engine; - /** - * Whether or not the app has been initialized - * - * @var boolean - */ + /** Whether or not the app has been initialized. */ private static bool $initialized = false; /** @@ -104,56 +101,53 @@ class Flight /** * Registers a class to a framework method. - * @template T of object - * @param string $name Static method name + * + * # Usage example: * ``` * Flight::register('user', User::class); * * Flight::user(); # <- Return a User instance * ``` - * @param class-string $class Fully Qualified Class Name - * @param array $params Class constructor params - * @param ?Closure(T $instance): void $callback Perform actions with the instance - * @return void + * + * @param string $name Static method name + * @param class-string $class Fully Qualified Class Name + * @param array $params Class constructor params + * @param ?Closure(T $instance): void $callback Perform actions with the instance + * + * @template T of object */ - public static function register($name, $class, $params = [], $callback = null) + public static function register($name, $class, $params = [], $callback = null): void { - static::__callStatic('register', func_get_args()); + static::__callStatic('register', [$name, $class, $params, $callback]); } /** Unregisters a class. */ public static function unregister(string $methodName): void { - static::__callStatic('unregister', func_get_args()); + static::__callStatic('unregister', [$methodName]); } /** * Handles calls to static methods. * - * @param string $name Method name - * @param array $params Method parameters - * - * @throws Exception + * @param string $name Method name + * @param array $params Method parameters * * @return mixed Callback results + * @throws Exception */ public static function __callStatic(string $name, array $params) { - $app = self::app(); - - return Dispatcher::invokeMethod([$app, $name], $params); + return Dispatcher::invokeMethod([self::app(), $name], $params); } - /** - * @return Engine Application instance - */ + /** @return Engine Application instance */ public static function app(): Engine { if (!self::$initialized) { require_once __DIR__ . '/autoload.php'; self::setEngine(new Engine()); - self::$initialized = true; } diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index ff9c9ec..fe7ca2f 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace flight\core; +use Closure; use Exception; use InvalidArgumentException; @@ -117,9 +118,9 @@ class Dispatcher /** * Hooks a callback to an event. * - * @param string $name Event name - * @param string $type Filter type - * @param callable $callback Callback function + * @param string $name Event name + * @param 'before'|'after' $type Filter type + * @param Closure(array &$params, string &$output): (void|false) $callback */ public function hook(string $name, string $type, callable $callback): void { diff --git a/flight/core/Loader.php b/flight/core/Loader.php index bf83e3f..3bd3696 100644 --- a/flight/core/Loader.php +++ b/flight/core/Loader.php @@ -42,14 +42,12 @@ class Loader /** * Registers a class. * - * @param string $name Registry name - * @param class-string|Closure(): T $class Class name or function to instantiate class - * @param array $params Class initialization parameters - * @param ?callable(T $instance): void $callback $callback Function to call after object instantiation + * @param string $name Registry name + * @param class-string|Closure(): T $class Class name or function to instantiate class + * @param array $params Class initialization parameters + * @param ?Closure(T $instance): void $callback $callback Function to call after object instantiation * * @template T of object - * - * @return void */ public function register(string $name, $class, array $params = [], ?callable $callback = null): void { diff --git a/phpcs.xml b/phpcs.xml index 22b3fdd..ad8cc88 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -34,6 +34,7 @@ + flight/ tests/ diff --git a/tests/FlightTest.php b/tests/FlightTest.php index 2018d53..c37a8fa 100644 --- a/tests/FlightTest.php +++ b/tests/FlightTest.php @@ -164,7 +164,6 @@ class FlightTest extends TestCase public function testStaticRoutePut() { - Flight::put('/test', function () { echo 'test put'; });