Merge branch 'fadrian06-master'

pull/498/head
n0nag0n 1 year ago
commit f63f266134

@ -0,0 +1,12 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_size = 2

1
.gitignore vendored

@ -5,3 +5,4 @@ composer.lock
.phpunit.result.cache .phpunit.result.cache
coverage/ coverage/
.vscode/settings.json .vscode/settings.json
*.sublime-workspace

@ -1,13 +1,16 @@
# What is Flight? # What is Flight?
Flight is a fast, simple, extensible framework for PHP. Flight enables you to ![](https://user-images.githubusercontent.com/104888/50957476-9c4acb80-14be-11e9-88ce-6447364dc1bb.png)
![](https://img.shields.io/badge/PHPStan-level%206-brightgreen.svg?style=flat)
Flight is a fast, simple, extensible framework for PHP. Flight enables you to
quickly and easily build RESTful web applications. quickly and easily build RESTful web applications.
```php ```php
require 'flight/Flight.php'; require 'flight/Flight.php';
Flight::route('/', function(){ Flight::route('/', function() {
echo 'hello world!'; echo 'hello world!';
}); });
Flight::start(); Flight::start();
@ -27,14 +30,15 @@ Flight is released under the [MIT](http://flightphp.com/license) license.
1\. Download the files. 1\. Download the files.
If you're using [Composer](https://getcomposer.org/), you can run the following command: If you're using [Composer](https://getcomposer.org/), you can run the following
command:
``` ```bash
composer require mikecao/flight composer require mikecao/flight
``` ```
OR you can [download](https://github.com/mikecao/flight/archive/master.zip) them directly OR you can [download](https://github.com/mikecao/flight/archive/master.zip)
and extract them to your web directory. them directly and extract them to your web directory.
2\. Configure your webserver. 2\. Configure your webserver.
@ -47,15 +51,16 @@ RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L] RewriteRule ^(.*)$ index.php [QSA,L]
``` ```
**Note**: If you need to use flight in a subdirectory add the line `RewriteBase /subdir/` just after `RewriteEngine On`. **Note**: If you need to use flight in a subdirectory add the line
`RewriteBase /subdir/` just after `RewriteEngine On`.
For *Nginx*, add the following to your server declaration: For *Nginx*, add the following to your server declaration:
``` ```
server { server {
location / { location / {
try_files $uri $uri/ /index.php; try_files $uri $uri/ /index.php;
} }
} }
``` ```
3\. Create your `index.php` file. 3\. Create your `index.php` file.
@ -75,8 +80,8 @@ require 'vendor/autoload.php';
Then define a route and assign a function to handle the request. Then define a route and assign a function to handle the request.
```php ```php
Flight::route('/', function(){ Flight::route('/', function () {
echo 'hello world!'; echo 'hello world!';
}); });
``` ```
@ -91,16 +96,16 @@ Flight::start();
Routing in Flight is done by matching a URL pattern with a callback function. Routing in Flight is done by matching a URL pattern with a callback function.
```php ```php
Flight::route('/', function(){ Flight::route('/', function () {
echo 'hello world!'; echo 'hello world!';
}); });
``` ```
The callback can be any object that is callable. So you can use a regular function: The callback can be any object that is callable. So you can use a regular function:
```php ```php
function hello(){ function hello() {
echo 'hello world!'; echo 'hello world!';
} }
Flight::route('/', 'hello'); Flight::route('/', 'hello');
@ -110,9 +115,9 @@ Or a class method:
```php ```php
class Greeting { class Greeting {
public static function hello() { public static function hello() {
echo 'hello world!'; echo 'hello world!';
} }
} }
Flight::route('/', array('Greeting', 'hello')); Flight::route('/', array('Greeting', 'hello'));
@ -123,18 +128,18 @@ Or an object method:
```php ```php
class Greeting class Greeting
{ {
public function __construct() { public function __construct() {
$this->name = 'John Doe'; $this->name = 'John Doe';
} }
public function hello() { public function hello() {
echo "Hello, {$this->name}!"; echo "Hello, {$this->name}!";
} }
} }
$greeting = new Greeting(); $greeting = new Greeting();
Flight::route('/', array($greeting, 'hello')); Flight::route('/', array($greeting, 'hello'));
``` ```
Routes are matched in the order they are defined. The first route to match a Routes are matched in the order they are defined. The first route to match a
@ -146,20 +151,20 @@ By default, route patterns are matched against all request methods. You can resp
to specific methods by placing an identifier before the URL. to specific methods by placing an identifier before the URL.
```php ```php
Flight::route('GET /', function(){ Flight::route('GET /', function () {
echo 'I received a GET request.'; echo 'I received a GET request.';
}); });
Flight::route('POST /', function(){ Flight::route('POST /', function () {
echo 'I received a POST request.'; echo 'I received a POST request.';
}); });
``` ```
You can also map multiple methods to a single callback by using a `|` delimiter: You can also map multiple methods to a single callback by using a `|` delimiter:
```php ```php
Flight::route('GET|POST /', function(){ Flight::route('GET|POST /', function () {
echo 'I received either a GET or a POST request.'; echo 'I received either a GET or a POST request.';
}); });
``` ```
@ -168,8 +173,8 @@ Flight::route('GET|POST /', function(){
You can use regular expressions in your routes: You can use regular expressions in your routes:
```php ```php
Flight::route('/user/[0-9]+', function(){ Flight::route('/user/[0-9]+', function () {
// This will match /user/1234 // This will match /user/1234
}); });
``` ```
@ -179,8 +184,8 @@ You can specify named parameters in your routes which will be passed along to
your callback function. your callback function.
```php ```php
Flight::route('/@name/@id', function($name, $id){ Flight::route('/@name/@id', function(string $name, string $id) {
echo "hello, $name ($id)!"; echo "hello, $name ($id)!";
}); });
``` ```
@ -188,9 +193,9 @@ You can also include regular expressions with your named parameters by using
the `:` delimiter: the `:` delimiter:
```php ```php
Flight::route('/@name/@id:[0-9]{3}', function($name, $id){ Flight::route('/@name/@id:[0-9]{3}', function(string $name, string $id) {
// This will match /bob/123 // This will match /bob/123
// But will not match /bob/12345 // But will not match /bob/12345
}); });
``` ```
@ -202,13 +207,16 @@ You can specify named parameters that are optional for matching by wrapping
segments in parentheses. segments in parentheses.
```php ```php
Flight::route('/blog(/@year(/@month(/@day)))', function($year, $month, $day){ Flight::route(
'/blog(/@year(/@month(/@day)))',
function(?string $year, ?string $month, ?string $day) {
// This will match the following URLS: // This will match the following URLS:
// /blog/2012/12/10 // /blog/2012/12/10
// /blog/2012/12 // /blog/2012/12
// /blog/2012 // /blog/2012
// /blog // /blog
}); }
);
``` ```
Any optional parameters that are not matched will be passed in as NULL. Any optional parameters that are not matched will be passed in as NULL.
@ -219,16 +227,16 @@ Matching is only done on individual URL segments. If you want to match multiple
segments you can use the `*` wildcard. segments you can use the `*` wildcard.
```php ```php
Flight::route('/blog/*', function(){ Flight::route('/blog/*', function () {
// This will match /blog/2000/02/01 // This will match /blog/2000/02/01
}); });
``` ```
To route all requests to a single callback, you can do: To route all requests to a single callback, you can do:
```php ```php
Flight::route('*', function(){ Flight::route('*', function () {
// Do something // Do something
}); });
``` ```
@ -238,16 +246,16 @@ You can pass execution on to the next matching route by returning `true` from
your callback function. your callback function.
```php ```php
Flight::route('/user/@name', function($name){ Flight::route('/user/@name', function (string $name) {
// Check some condition // Check some condition
if ($name != "Bob") { if ($name != "Bob") {
// Continue to next route // Continue to next route
return true; return true;
} }
}); });
Flight::route('/user/*', function(){ Flight::route('/user/*', function () {
// This will get called // This will get called
}); });
``` ```
@ -259,18 +267,18 @@ the route method. The route object will always be the last parameter passed to y
callback function. callback function.
```php ```php
Flight::route('/', function($route){ Flight::route('/', function(\flight\net\Route $route) {
// Array of HTTP methods matched against // Array of HTTP methods matched against
$route->methods; $route->methods;
// Array of named parameters // Array of named parameters
$route->params; $route->params;
// Matching regular expression // Matching regular expression
$route->regex; $route->regex;
// Contains the contents of any '*' used in the URL pattern // Contains the contents of any '*' used in the URL pattern
$route->splat; $route->splat;
}, true); }, true);
``` ```
@ -286,8 +294,8 @@ To map your own custom method, you use the `map` function:
```php ```php
// Map your method // Map your method
Flight::map('hello', function($name){ Flight::map('hello', function ($name) {
echo "hello $name!"; echo "hello $name!";
}); });
// Call your custom method // Call your custom method
@ -318,7 +326,7 @@ Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','p
// Get an instance of your class // Get an instance of your class
// This will create an object with the defined parameters // This will create an object with the defined parameters
// //
// new PDO('mysql:host=localhost;dbname=test','user','pass'); // new PDO('mysql:host=localhost;dbname=test','user','pass');
// //
$db = Flight::db(); $db = Flight::db();
``` ```
@ -329,8 +337,8 @@ new object. The callback function takes one parameter, an instance of the new ob
```php ```php
// The callback will be passed the object that was constructed // The callback will be passed the object that was constructed
Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass'), function($db){ Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass'), function (PDO $db): void {
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}); });
``` ```
@ -359,8 +367,8 @@ by using the `map` method:
```php ```php
Flight::map('notFound', function(){ Flight::map('notFound', function(){
// Display custom 404 page // Display custom 404 page
include 'errors/404.html'; include 'errors/404.html';
}); });
``` ```
@ -387,8 +395,8 @@ methods as well as any custom methods that you've mapped.
A filter function looks like this: A filter function looks like this:
```php ```php
function(&$params, &$output) { function (array &$params, string &$output) {
// Filter code // Filter code
} }
``` ```
@ -397,16 +405,16 @@ Using the passed in variables you can manipulate the input parameters and/or the
You can have a filter run before a method by doing: You can have a filter run before a method by doing:
```php ```php
Flight::before('start', function(&$params, &$output){ Flight::before('start', function (array &$params, string &$output) {
// Do something // Do something
}); });
``` ```
You can have a filter run after a method by doing: You can have a filter run after a method by doing:
```php ```php
Flight::after('start', function(&$params, &$output){ Flight::after('start', function (array &$params, string &$output) {
// Do something // Do something
}); });
``` ```
@ -417,20 +425,20 @@ Here's an example of the filtering process:
```php ```php
// Map a custom method // Map a custom method
Flight::map('hello', function($name){ Flight::map('hello', function ($name) {
return "Hello, $name!"; return "Hello, $name!";
}); });
// Add a before filter // Add a before filter
Flight::before('hello', function(&$params, &$output){ Flight::before('hello', function (array &$params, string &$output) {
// Manipulate the parameter // Manipulate the parameter
$params[0] = 'Fred'; $params[0] = 'Fred';
}); });
// Add an after filter // Add an after filter
Flight::after('hello', function(&$params, &$output){ Flight::after('hello', function (array &$params, string &$output) {
// Manipulate the output // Manipulate the output
$output .= " Have a nice day!"; $output .= " Have a nice day!";
}); });
// Invoke the custom method // Invoke the custom method
@ -439,26 +447,28 @@ echo Flight::hello('Bob');
This should display: This should display:
Hello Fred! Have a nice day! ```
Hello Fred! Have a nice day!
```
If you have defined multiple filters, you can break the chain by returning `false` If you have defined multiple filters, you can break the chain by returning `false`
in any of your filter functions: in any of your filter functions:
```php ```php
Flight::before('start', function(&$params, &$output){ Flight::before('start', function (array &$params, string &$output){
echo 'one'; echo 'one';
}); });
Flight::before('start', function(&$params, &$output){ Flight::before('start', function (array &$params, string &$output): bool {
echo 'two'; echo 'two';
// This will end the chain // This will end the chain
return false; return false;
}); });
// This will not get called // This will not get called
Flight::before('start', function(&$params, &$output){ Flight::before('start', function (array &$params, string &$output){
echo 'three'; echo 'three';
}); });
``` ```
@ -480,7 +490,7 @@ To see if a variable has been set you can do:
```php ```php
if (Flight::has('id')) { if (Flight::has('id')) {
// Do something // Do something
} }
``` ```
@ -515,12 +525,14 @@ be reference like a local variable. Template files are simply PHP files. If the
content of the `hello.php` template file is: content of the `hello.php` template file is:
```php ```php
Hello, '<?php echo $name; ?>'! Hello, <?php echo $name; ?>!
``` ```
The output would be: The output would be:
Hello, Bob! ```
Hello, Bob!
```
You can also manually set view variables by using the set method: You can also manually set view variables by using the set method:
@ -580,26 +592,26 @@ If the template files looks like this:
```php ```php
<html> <html>
<head> <head>
<title><?php echo $title; ?></title> <title><?php echo $title; ?></title>
</head> </head>
<body> <body>
<?php echo $header_content; ?> <?php echo $header_content; ?>
<?php echo $body_content; ?> <?php echo $body_content; ?>
</body> </body>
</html> </html>
``` ```
The output would be: The output would be:
```html ```html
<html> <html>
<head> <head>
<title>Home Page</title> <title>Home Page</title>
</head> </head>
<body> <body>
<h1>Hello</h1> <h1>Hello</h1>
<div>World</div> <div>World</div>
</body> </body>
</html> </html>
``` ```
@ -615,11 +627,11 @@ require './Smarty/libs/Smarty.class.php';
// Register Smarty as the view class // Register Smarty as the view class
// Also pass a callback function to configure Smarty on load // Also pass a callback function to configure Smarty on load
Flight::register('view', 'Smarty', array(), function($smarty){ Flight::register('view', 'Smarty', array(), function (Smarty $smarty) {
$smarty->template_dir = './templates/'; $smarty->setTemplateDir() = './templates/';
$smarty->compile_dir = './templates_c/'; $smarty->setCompileDir() = './templates_c/';
$smarty->config_dir = './config/'; $smarty->setConfigDir() = './config/';
$smarty->cache_dir = './cache/'; $smarty->setCacheDir() = './cache/';
}); });
// Assign template data // Assign template data
@ -633,8 +645,8 @@ For completeness, you should also override Flight's default render method:
```php ```php
Flight::map('render', function($template, $data){ Flight::map('render', function($template, $data){
Flight::view()->assign($data); Flight::view()->assign($data);
Flight::view()->display($template); Flight::view()->display($template);
}); });
``` ```
# Error Handling # Error Handling
@ -648,9 +660,9 @@ response with some error information.
You can override this behavior for your own needs: You can override this behavior for your own needs:
```php ```php
Flight::map('error', function(Exception $ex){ Flight::map('error', function(Throwable $ex){
// Handle error // Handle error
echo $ex->getTraceAsString(); echo $ex->getTraceAsString();
}); });
``` ```
@ -669,8 +681,8 @@ behavior is to send an `HTTP 404 Not Found` response with a simple message.
You can override this behavior for your own needs: You can override this behavior for your own needs:
```php ```php
Flight::map('notFound', function(){ Flight::map('notFound', function () {
// Handle not found // Handle not found
}); });
``` ```
@ -701,26 +713,24 @@ $request = Flight::request();
The request object provides the following properties: The request object provides the following properties:
``` - **url** - The URL being requested
url - The URL being requested - **base** - The parent subdirectory of the URL
base - The parent subdirectory of the URL - **method** - The request method (GET, POST, PUT, DELETE)
method - The request method (GET, POST, PUT, DELETE) - **referrer** - The referrer URL
referrer - The referrer URL - **ip** - IP address of the client
ip - IP address of the client - **ajax** - Whether the request is an AJAX request
ajax - Whether the request is an AJAX request - **scheme** - The server protocol (http, https)
scheme - The server protocol (http, https) - **user_agent** - Browser information
user_agent - Browser information - **type** - The content type
type - The content type - **length** - The content length
length - The content length - **query** - Query string parameters
query - Query string parameters - **data** - Post data or JSON data
data - Post data or JSON data - **cookies** - Cookie data
cookies - Cookie data - **files** - Uploaded files
files - Uploaded files - **secure** - Whether the connection is secure
secure - Whether the connection is secure - **accept** - HTTP accept parameters
accept - HTTP accept parameters - **proxy_ip** - Proxy IP address of the client
proxy_ip - Proxy IP address of the client - **host** - The request host name
host - The request host name
```
You can access the `query`, `data`, `cookies`, and `files` properties You can access the `query`, `data`, `cookies`, and `files` properties
as arrays or objects. as arrays or objects.
@ -739,7 +749,8 @@ $id = Flight::request()->query->id;
## RAW Request Body ## RAW Request Body
To get the raw HTTP request body, for example when dealing with PUT requests, you can do: To get the raw HTTP request body, for example when dealing with PUT requests,
you can do:
```php ```php
$body = Flight::request()->getBody(); $body = Flight::request()->getBody();
@ -747,8 +758,8 @@ $body = Flight::request()->getBody();
## JSON Input ## JSON Input
If you send a request with the type `application/json` and the data `{"id": 123}` it will be available If you send a request with the type `application/json` and the data `{"id": 123}`
from the `data` property: it will be available from the `data` property:
```php ```php
$id = Flight::request()->data->id; $id = Flight::request()->data->id;
@ -768,9 +779,9 @@ and time a page was last modified. The client will continue to use their cache u
the last modified value is changed. the last modified value is changed.
```php ```php
Flight::route('/news', function(){ Flight::route('/news', function () {
Flight::lastModified(1234567890); Flight::lastModified(1234567890);
echo 'This content will be cached.'; echo 'This content will be cached.';
}); });
``` ```
@ -780,9 +791,9 @@ Flight::route('/news', function(){
want for the resource: want for the resource:
```php ```php
Flight::route('/news', function(){ Flight::route('/news', function () {
Flight::etag('my-unique-id'); Flight::etag('my-unique-id');
echo 'This content will be cached.'; echo 'This content will be cached.';
}); });
``` ```
@ -847,12 +858,12 @@ Flight::set('flight.log_errors', true);
The following is a list of all the available configuration settings: The following is a list of all the available configuration settings:
flight.base_url - Override the base url of the request. (default: null) - **flight.base_url** - Override the base url of the request. (default: null)
flight.case_sensitive - Case sensitive matching for URLs. (default: false) - **flight.case_sensitive** - Case sensitive matching for URLs. (default: false)
flight.handle_errors - Allow Flight to handle all errors internally. (default: true) - **flight.handle_errors** - Allow Flight to handle all errors internally. (default: true)
flight.log_errors - Log errors to the web server's error log file. (default: false) - **flight.log_errors** - Log errors to the web server's error log file. (default: false)
flight.views.path - Directory containing view template files. (default: ./views) - **flight.views.path** - Directory containing view template files. (default: ./views)
flight.views.extension - View template file extension. (default: .php) - **flight.views.extension** - View template file extension. (default: .php)
# Framework Methods # Framework Methods
@ -864,15 +875,15 @@ or overridden.
## Core Methods ## Core Methods
```php ```php
Flight::map($name, $callback) // Creates a custom framework method. Flight::map(string $name, callable $callback, bool $pass_route = false) // Creates a custom framework method.
Flight::register($name, $class, [$params], [$callback]) // Registers a class to a framework method. Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Registers a class to a framework method.
Flight::before($name, $callback) // Adds a filter before a framework method. Flight::before(string $name, callable $callback) // Adds a filter before a framework method.
Flight::after($name, $callback) // Adds a filter after a framework method. Flight::after(string $name, callable $callback) // Adds a filter after a framework method.
Flight::path($path) // Adds a path for autoloading classes. Flight::path(string $path) // Adds a path for autoloading classes.
Flight::get($key) // Gets a variable. Flight::get(string $key) // Gets a variable.
Flight::set($key, $value) // Sets a variable. Flight::set(string $key, mixed $value) // Sets a variable.
Flight::has($key) // Checks if a variable is set. Flight::has(string $key) // Checks if a variable is set.
Flight::clear([$key]) // Clears a variable. Flight::clear(array|string $key = []) // Clears a variable.
Flight::init() // Initializes the framework to its default settings. Flight::init() // Initializes the framework to its default settings.
Flight::app() // Gets the application object instance Flight::app() // Gets the application object instance
``` ```
@ -882,16 +893,16 @@ Flight::app() // Gets the application object instance
```php ```php
Flight::start() // Starts the framework. Flight::start() // Starts the framework.
Flight::stop() // Stops the framework and sends a response. Flight::stop() // Stops the framework and sends a response.
Flight::halt([$code], [$message]) // Stop the framework with an optional status code and message. Flight::halt(int $code = 200, string $message = '') // Stop the framework with an optional status code and message.
Flight::route($pattern, $callback) // Maps a URL pattern to a callback. Flight::route(string $pattern, callable $callback, bool $pass_route = false) // Maps a URL pattern to a callback.
Flight::redirect($url, [$code]) // Redirects to another URL. Flight::redirect(string $url, int $code) // Redirects to another URL.
Flight::render($file, [$data], [$key]) // Renders a template file. Flight::render(string $file, array $data, ?string $key = null) // Renders a template file.
Flight::error($exception) // Sends an HTTP 500 response. Flight::error(Throwable $exception) // Sends an HTTP 500 response.
Flight::notFound() // Sends an HTTP 404 response. Flight::notFound() // Sends an HTTP 404 response.
Flight::etag($id, [$type]) // Performs ETag HTTP caching. Flight::etag(string $id, string $type = 'string') // Performs ETag HTTP caching.
Flight::lastModified($time) // Performs last modified HTTP caching. Flight::lastModified(int $time) // Performs last modified HTTP caching.
Flight::json($data, [$code], [$encode], [$charset], [$option]) // Sends a JSON response. Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sends a JSON response.
Flight::jsonp($data, [$param], [$code], [$encode], [$charset], [$option]) // Sends a JSONP response. Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sends a JSONP response.
``` ```
Any custom methods added with `map` and `register` can also be filtered. Any custom methods added with `map` and `register` can also be filtered.
@ -905,12 +916,10 @@ as an object instance.
```php ```php
require 'flight/autoload.php'; require 'flight/autoload.php';
use flight\Engine; $app = new flight\Engine();
$app = new Engine(); $app->route('/', function () {
echo 'hello world!';
$app->route('/', function(){
echo 'hello world!';
}); });
$app->start(); $app->start();

@ -1 +1 @@
2.0.1 2.0.2

@ -1,5 +1,5 @@
{ {
"name": "mikecao/flight", "name": "faslatam/flight",
"description": "Flight is a fast, simple, extensible framework for PHP. Flight enables you to quickly and easily build RESTful web applications.", "description": "Flight is a fast, simple, extensible framework for PHP. Flight enables you to quickly and easily build RESTful web applications.",
"homepage": "http://flightphp.com", "homepage": "http://flightphp.com",
"license": "MIT", "license": "MIT",
@ -9,16 +9,39 @@
"email": "mike@mikecao.com", "email": "mike@mikecao.com",
"homepage": "http://www.mikecao.com/", "homepage": "http://www.mikecao.com/",
"role": "Original Developer" "role": "Original Developer"
},
{
"name": "Franyer Sánchez",
"email": "franyeradriansanchez@gmail.com",
"homepage": "https://faslatam.000webhostapp.com",
"role": "Maintainer"
} }
], ],
"require": { "require": {
"php": "^7.4|^8.0|^8.1", "php": "^7.4|^8.0|^8.1|^8.2",
"ext-json": "*" "ext-json": "*"
}, },
"autoload": { "autoload": {
"files": [ "flight/autoload.php", "flight/Flight.php" ] "files": [
"flight/autoload.php",
"flight/Flight.php"
]
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5" "phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^1.10",
"phpstan/extension-installer": "^1.3"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
}
},
"scripts": {
"test": "phpunit tests",
"lint": "phpstan --no-progress -cphpstan.neon"
},
"suggest": {
"phpstan/phpstan": "PHP Static Analysis Tool"
} }
} }

@ -0,0 +1,21 @@
{
"folders": [
{
"path": ".",
}
],
"settings": {
"LSP": {
"LSP-intelephense": {
"settings": {
"intelephense.environment.phpVersion": "7.4.0",
"intelephense.format.braces": "psr12",
},
},
"formatters":
{
"embedding.php": "LSP-intelephense"
},
},
},
}

@ -40,7 +40,7 @@ use Throwable;
* Request-response * Request-response
* @method Request request() Gets current request * @method Request request() Gets current request
* @method Response response() Gets current response * @method Response response() Gets current response
* @method void error(Exception $e) Sends an HTTP 500 response for any errors. * @method void error(Throwable $e) Sends an HTTP 500 response for any errors.
* @method void notFound() Sends an HTTP 404 response when a URL is not found. * @method void notFound() Sends an HTTP 404 response when a URL is not found.
* @method void redirect(string $url, int $code = 303) Redirects the current request to another URL. * @method void redirect(string $url, int $code = 303) Redirects the current request to another URL.
* @method void json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) Sends a JSON response. * @method void json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) Sends a JSON response.
@ -54,6 +54,7 @@ class Engine
{ {
/** /**
* Stored variables. * Stored variables.
* @var array<string, mixed>
*/ */
protected array $vars; protected array $vars;
@ -84,7 +85,7 @@ class Engine
* Handles calls to class methods. * Handles calls to class methods.
* *
* @param string $name Method name * @param string $name Method name
* @param array $params Method parameters * @param array<int, mixed> $params Method parameters
* *
* @throws Exception * @throws Exception
* *
@ -155,8 +156,8 @@ class Engine
$this->before('start', function () use ($self) { $this->before('start', function () use ($self) {
// Enable error handling // Enable error handling
if ($self->get('flight.handle_errors')) { if ($self->get('flight.handle_errors')) {
set_error_handler([$self, 'handleError']); set_error_handler(array($self, 'handleError'));
set_exception_handler([$self, 'handleException']); set_exception_handler(array($self, 'handleException'));
} }
// Set case-sensitivity // Set case-sensitivity
@ -177,18 +178,21 @@ class Engine
* @param int $errline Error file line number * @param int $errline Error file line number
* *
* @throws ErrorException * @throws ErrorException
* @return bool
*/ */
public function handleError(int $errno, string $errstr, string $errfile, int $errline) public function handleError(int $errno, string $errstr, string $errfile, int $errline)
{ {
if ($errno & error_reporting()) { if ($errno & error_reporting()) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline); throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
} }
return false;
} }
/** /**
* Custom exception handler. Logs exceptions. * Custom exception handler. Logs exceptions.
* *
* @param Exception $e Thrown exception * @param Throwable $e Thrown exception
*/ */
public function handleException($e): void public function handleException($e): void
{ {
@ -203,7 +207,7 @@ class Engine
* Maps a callback to a framework method. * Maps a callback to a framework method.
* *
* @param string $name Method name * @param string $name Method name
* @param callback $callback Callback function * @param callable $callback Callback function
* *
* @throws Exception If trying to map over a framework method * @throws Exception If trying to map over a framework method
*/ */
@ -218,11 +222,12 @@ class Engine
/** /**
* Registers a class to a framework method. * Registers a class to a framework method.
* @template T of object
* *
* @param string $name Method name * @param string $name Method name
* @param string $class Class name * @param class-string<T> $class Class name
* @param array $params Class initialization parameters * @param array<int, mixed> $params Class initialization parameters
* @param callable|null $callback $callback Function to call after object instantiation * @param ?callable(T $instance): void $callback Function to call after object instantiation
* *
* @throws Exception If trying to map over a framework method * @throws Exception If trying to map over a framework method
*/ */
@ -239,7 +244,7 @@ class Engine
* Adds a pre-filter to a method. * Adds a pre-filter to a method.
* *
* @param string $name Method name * @param string $name Method name
* @param callback $callback Callback function * @param callable $callback Callback function
*/ */
public function before(string $name, callable $callback): void public function before(string $name, callable $callback): void
{ {
@ -250,7 +255,7 @@ class Engine
* Adds a post-filter to a method. * Adds a post-filter to a method.
* *
* @param string $name Method name * @param string $name Method name
* @param callback $callback Callback function * @param callable $callback Callback function
*/ */
public function after(string $name, callable $callback): void public function after(string $name, callable $callback): void
{ {
@ -392,9 +397,10 @@ class Engine
*/ */
public function _error($e): void public function _error($e): void
{ {
$msg = sprintf('<h1>500 Internal Server Error</h1>' . $msg = sprintf(
'<h3>%s (%s)</h3>' . '<h1>500 Internal Server Error</h1>' .
'<pre>%s</pre>', '<h3>%s (%s)</h3>' .
'<pre>%s</pre>',
$e->getMessage(), $e->getMessage(),
$e->getCode(), $e->getCode(),
$e->getTraceAsString() $e->getTraceAsString()
@ -437,7 +443,7 @@ class Engine
* Routes a URL to a callback function. * Routes a URL to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @param bool $pass_route Pass the matching route object to the callback
*/ */
public function _route(string $pattern, callable $callback, bool $pass_route = false): void public function _route(string $pattern, callable $callback, bool $pass_route = false): void
@ -449,7 +455,7 @@ class Engine
* Routes a URL to a callback function. * Routes a URL to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @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): void
@ -461,7 +467,7 @@ class Engine
* Routes a URL to a callback function. * Routes a URL to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @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): void
@ -473,7 +479,7 @@ class Engine
* Routes a URL to a callback function. * Routes a URL to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @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): void
@ -485,7 +491,7 @@ class Engine
* Routes a URL to a callback function. * Routes a URL to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @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): void
@ -519,8 +525,8 @@ class Engine
->status(404) ->status(404)
->write( ->write(
'<h1>404 Not Found</h1>' . '<h1>404 Not Found</h1>' .
'<h3>The page you have requested could not be found.</h3>' . '<h3>The page you have requested could not be found.</h3>' .
str_repeat(' ', 512) str_repeat(' ', 512)
) )
->send(); ->send();
} }
@ -555,7 +561,7 @@ class Engine
* Renders a template. * Renders a template.
* *
* @param string $file Template file * @param string $file Template file
* @param array|null $data Template data * @param ?array<string, mixed> $data Template data
* @param string|null $key View variable name * @param string|null $key View variable name
* *
* @throws Exception * @throws Exception
@ -639,8 +645,10 @@ class Engine
$this->response()->header('ETag', $id); $this->response()->header('ETag', $id);
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && if (
$_SERVER['HTTP_IF_NONE_MATCH'] === $id) { isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
$_SERVER['HTTP_IF_NONE_MATCH'] === $id
) {
$this->halt(304); $this->halt(304);
} }
} }
@ -654,8 +662,10 @@ class Engine
{ {
$this->response()->header('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $time)); $this->response()->header('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $time));
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && if (
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $time) { isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $time
) {
$this->halt(304); $this->halt(304);
} }
} }

@ -18,36 +18,27 @@ use flight\template\View;
/** /**
* The Flight class is a static representation of the framework. * The Flight class is a static representation of the framework.
* *
* Core.
*
* @method static void start() Starts the framework. * @method static void start() Starts the framework.
* @method static void path($path) Adds a path for autoloading classes. * @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() Stops the framework and sends a response.
* @method static void halt($code = 200, $message = '') Stop the framework with an optional status code and message. * @method static void halt(int $code = 200, string $message = '') Stop the framework with an optional status code and message.
* *
* Routing. * @method static void route(string $pattern, callable $callback, bool $pass_route = false) Maps a URL pattern to a callback.
* @method static void route($pattern, $callback) Maps a URL pattern to a callback.
* @method static Router router() Returns Router instance. * @method static Router router() Returns Router instance.
* *
* Extending & Overriding. * @method static void map(string $name, callable $callback) Creates a custom framework method.
* @method static void map($name, $callback) Creates a custom framework method.
* @method static void register($name, $class, array $params = array(), $callback = null) Registers a class to a framework method.
* *
* Filtering.
* @method static void before($name, $callback) Adds a filter before a 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 after($name, $callback) Adds a filter after a framework method.
* *
* Variables.
* @method static void set($key, $value) Sets a variable. * @method static void set($key, $value) Sets a variable.
* @method static mixed get($key) Gets a variable. * @method static mixed get($key) Gets a variable.
* @method static bool has($key) Checks if a variable is set. * @method static bool has($key) Checks if a variable is set.
* @method static void clear($key = null) Clears a variable. * @method static void clear($key = null) Clears a variable.
* *
* Views.
* @method static void render($file, array $data = null, $key = null) Renders a template file. * @method static void render($file, array $data = null, $key = null) Renders a template file.
* @method static View view() Returns View instance. * @method static View view() Returns View instance.
* *
* Request & Response.
* @method static Request request() Returns Request instance. * @method static Request request() Returns Request instance.
* @method static Response response() Returns Response instance. * @method static Response response() Returns Response instance.
* @method static void redirect($url, $code = 303) Redirects to another URL. * @method static void redirect($url, $code = 303) Redirects to another URL.
@ -56,7 +47,6 @@ use flight\template\View;
* @method static void error($exception) Sends an HTTP 500 response. * @method static void error($exception) Sends an HTTP 500 response.
* @method static void notFound() Sends an HTTP 404 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 etag($id, $type = 'strong') Performs ETag HTTP caching.
* @method static void lastModified($time) Performs last modified HTTP caching. * @method static void lastModified($time) Performs last modified HTTP caching.
*/ */
@ -72,19 +62,34 @@ class Flight
{ {
} }
private function __destruct() private function __clone()
{ {
} }
private function __clone() /**
* Registers a class to a framework method.
* @template T of object
* @param string $name Static method name
* ```
* Flight::register('user', User::class);
*
* Flight::user(); # <- Return a User instance
* ```
* @param class-string<T> $class Fully Qualified Class Name
* @param array<int, mixed> $params Class constructor params
* @param ?Closure(T $instance): void $callback Perform actions with the instance
* @return void
*/
static function register($name, $class, $params = array(), $callback = null)
{ {
static::__callStatic('register', func_get_args());
} }
/** /**
* Handles calls to static methods. * Handles calls to static methods.
* *
* @param string $name Method name * @param string $name Method name
* @param array $params Method parameters * @param array<int, mixed> $params Method parameters
* *
* @throws Exception * @throws Exception
* *

@ -23,11 +23,13 @@ class Dispatcher
{ {
/** /**
* Mapped events. * Mapped events.
* @var array<string, callable>
*/ */
protected array $events = []; protected array $events = [];
/** /**
* Method filters. * Method filters.
* @var array<string, array<'before'|'after', array<int, callable>>>
*/ */
protected array $filters = []; protected array $filters = [];
@ -35,9 +37,9 @@ class Dispatcher
* Dispatches an event. * Dispatches an event.
* *
* @param string $name Event name * @param string $name Event name
* @param array $params Callback parameters * @param array<int, mixed> $params Callback parameters
* *
*@throws Exception * @throws Exception
* *
* @return mixed|null Output of callback * @return mixed|null Output of callback
*/ */
@ -65,7 +67,7 @@ class Dispatcher
* Assigns a callback to an event. * Assigns a callback to an event.
* *
* @param string $name Event name * @param string $name Event name
* @param callback $callback Callback function * @param callable $callback Callback function
*/ */
final public function set(string $name, callable $callback): void final public function set(string $name, callable $callback): void
{ {
@ -77,7 +79,7 @@ class Dispatcher
* *
* @param string $name Event name * @param string $name Event name
* *
* @return callback $callback Callback function * @return callable $callback Callback function
*/ */
final public function get(string $name): ?callable final public function get(string $name): ?callable
{ {
@ -118,7 +120,7 @@ class Dispatcher
* *
* @param string $name Event name * @param string $name Event name
* @param string $type Filter type * @param string $type Filter type
* @param callback $callback Callback function * @param callable $callback Callback function
*/ */
final public function hook(string $name, string $type, callable $callback): void final public function hook(string $name, string $type, callable $callback): void
{ {
@ -128,8 +130,8 @@ class Dispatcher
/** /**
* Executes a chain of method filters. * Executes a chain of method filters.
* *
* @param array $filters Chain of filters * @param array<int, callable> $filters Chain of filters
* @param array $params Method parameters * @param array<int, mixed> $params Method parameters
* @param mixed $output Method output * @param mixed $output Method output
* *
* @throws Exception * @throws Exception
@ -148,10 +150,10 @@ class Dispatcher
/** /**
* Executes a callback function. * Executes a callback function.
* *
* @param array|callback $callback Callback function * @param callable|array<class-string|object, string> $callback Callback function
* @param array $params Function parameters * @param array<int, mixed> $params Function parameters
* *
*@throws Exception * @throws Exception
* *
* @return mixed Function results * @return mixed Function results
*/ */
@ -170,7 +172,7 @@ class Dispatcher
* Calls a function. * Calls a function.
* *
* @param callable|string $func Name of function to call * @param callable|string $func Name of function to call
* @param array $params Function parameters * @param array<int, mixed> $params Function parameters
* *
* @return mixed Function results * @return mixed Function results
*/ */
@ -203,7 +205,7 @@ class Dispatcher
* Invokes a method. * Invokes a method.
* *
* @param mixed $func Class method * @param mixed $func Class method
* @param array $params Class method parameters * @param array<int, mixed> $params Class method parameters
* *
* @return mixed Function results * @return mixed Function results
*/ */

@ -10,6 +10,7 @@ declare(strict_types=1);
namespace flight\core; namespace flight\core;
use Closure;
use Exception; use Exception;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
@ -24,26 +25,30 @@ class Loader
{ {
/** /**
* Registered classes. * Registered classes.
* @var array<string, array{class-string, array<int, mixed>, ?callable}> $classes
*/ */
protected array $classes = []; protected array $classes = [];
/** /**
* Class instances. * Class instances.
* @var array<string, object>
*/ */
protected array $instances = []; protected array $instances = [];
/** /**
* Autoload directories. * Autoload directories.
* @var array<int, string>
*/ */
protected static array $dirs = []; protected static array $dirs = [];
/** /**
* Registers a class. * Registers a class.
* @template T of object
* *
* @param string $name Registry name * @param string $name Registry name
* @param callable|string $class Class name or function to instantiate class * @param class-string<T> $class Class name or function to instantiate class
* @param array $params Class initialization parameters * @param array<int, mixed> $params Class initialization parameters
* @param callable|null $callback $callback Function to call after object instantiation * @param ?callable(T $instance): void $callback $callback Function to call after object instantiation
*/ */
public function register(string $name, $class, array $params = [], ?callable $callback = null): void public function register(string $name, $class, array $params = [], ?callable $callback = null): void
{ {
@ -77,7 +82,7 @@ class Loader
$obj = null; $obj = null;
if (isset($this->classes[$name])) { if (isset($this->classes[$name])) {
[$class, $params, $callback] = $this->classes[$name]; [0 => $class, 1 => $params, 2 => $callback] = $this->classes[$name];
$exists = isset($this->instances[$name]); $exists = isset($this->instances[$name]);
@ -116,15 +121,16 @@ class Loader
/** /**
* Gets a new instance of a class. * Gets a new instance of a class.
* @template T of object
* *
* @param callable|string $class Class name or callback function to instantiate class * @param class-string<T>|Closure(): class-string<T> $class Class name or callback function to instantiate class
* @param array $params Class initialization parameters * @param array<int, string> $params Class initialization parameters
* *
* @throws Exception * @throws Exception
* *
* @return object Class instance * @return T Class instance
*/ */
public function newInstance($class, array $params = []): object public function newInstance($class, array $params = [])
{ {
if (\is_callable($class)) { if (\is_callable($class)) {
return \call_user_func_array($class, $params); return \call_user_func_array($class, $params);
@ -179,7 +185,7 @@ class Loader
* Starts/stops autoloader. * Starts/stops autoloader.
* *
* @param bool $enabled Enable/disable autoloading * @param bool $enabled Enable/disable autoloading
* @param mixed $dirs Autoload directories * @param string|iterable<int, string> $dirs Autoload directories
*/ */
public static function autoload(bool $enabled = true, $dirs = []): void public static function autoload(bool $enabled = true, $dirs = []): void
{ {
@ -216,7 +222,7 @@ class Loader
/** /**
* Adds a directory for autoloading classes. * Adds a directory for autoloading classes.
* *
* @param mixed $dir Directory path * @param string|iterable<int, string> $dir Directory path
*/ */
public static function addDirectory($dir): void public static function addDirectory($dir): void
{ {

@ -18,23 +18,24 @@ use flight\util\Collection;
* are stored and accessible via the Request object. * are stored and accessible via the Request object.
* *
* The default request properties are: * The default request properties are:
* url - The URL being requested *
* base - The parent subdirectory of the URL * - **url** - The URL being requested
* method - The request method (GET, POST, PUT, DELETE) * - **base** - The parent subdirectory of the URL
* referrer - The referrer URL * - **method** - The request method (GET, POST, PUT, DELETE)
* ip - IP address of the client * - **referrer** - The referrer URL
* ajax - Whether the request is an AJAX request * - **ip** - IP address of the client
* scheme - The server protocol (http, https) * - **ajax** - Whether the request is an AJAX request
* user_agent - Browser information * - **scheme** - The server protocol (http, https)
* type - The content type * - **user_agent** - Browser information
* length - The content length * - **type** - The content type
* query - Query string parameters * - **length** - The content length
* data - Post parameters * - **query** - Query string parameters
* cookies - Cookie parameters * - **data** - Post parameters
* files - Uploaded files * - **cookies** - Cookie parameters
* secure - Connection is secure * - **files** - Uploaded files
* accept - HTTP accept parameters * - **secure** - Connection is secure
* proxy_ip - Proxy IP address of the client * - **accept** - HTTP accept parameters
* - **proxy_ip** - Proxy IP address of the client
*/ */
final class Request final class Request
{ {
@ -131,9 +132,9 @@ final class Request
/** /**
* Constructor. * Constructor.
* *
* @param array $config Request configuration * @param array<string, mixed> $config Request configuration
*/ */
public function __construct(array $config = []) public function __construct($config = array())
{ {
// Default properties // Default properties
if (empty($config)) { if (empty($config)) {
@ -165,7 +166,8 @@ final class Request
/** /**
* Initialize request properties. * Initialize request properties.
* *
* @param array $properties Array of request properties * @param array<string, mixed> $properties Array of request properties
* @return static
*/ */
public function init(array $properties = []) public function init(array $properties = [])
{ {
@ -199,6 +201,8 @@ final class Request
} }
} }
} }
return $this;
} }
/** /**
@ -287,11 +291,11 @@ final class Request
* *
* @param string $url URL string * @param string $url URL string
* *
* @return array Query parameters * @return array<string, int|string|array<int|string, int|string>>
*/ */
public static function parseQuery(string $url): array public static function parseQuery(string $url): array
{ {
$params = []; $params = array();
$args = parse_url($url); $args = parse_url($url);
if (isset($args['query'])) { if (isset($args['query'])) {

@ -25,7 +25,7 @@ class Response
public bool $content_length = true; public bool $content_length = true;
/** /**
* @var array HTTP status codes * @var array<int, ?string> HTTP status codes
*/ */
public static array $codes = [ public static array $codes = [
100 => 'Continue', 100 => 'Continue',
@ -103,7 +103,7 @@ class Response
protected int $status = 200; protected int $status = 200;
/** /**
* @var array HTTP headers * @var array<string, int|string|array<int, string>> HTTP headers
*/ */
protected array $headers = []; protected array $headers = [];
@ -124,7 +124,7 @@ class Response
* *
* @throws Exception If invalid status code * @throws Exception If invalid status code
* *
* @return int|object Self reference * @return int|static Self reference
*/ */
public function status(?int $code = null) public function status(?int $code = null)
{ {
@ -144,10 +144,10 @@ class Response
/** /**
* Adds a header to the response. * Adds a header to the response.
* *
* @param array|string $name Header name or array of names and values * @param array<string, int|string>|string $name Header name or array of names and values
* @param string|null $value Header value * @param string|null $value Header value
* *
* @return object Self reference * @return static Self reference
*/ */
public function header($name, ?string $value = null) public function header($name, ?string $value = null)
{ {
@ -164,8 +164,7 @@ class Response
/** /**
* Returns the headers from the response. * Returns the headers from the response.
* * @return array<string, int|string|array<int, string>>
* @return array
*/ */
public function headers() public function headers()
{ {
@ -203,7 +202,7 @@ class Response
/** /**
* Sets caching headers for the response. * Sets caching headers for the response.
* *
* @param int|string $expires Expiration time * @param int|string|false $expires Expiration time
* *
* @return Response Self reference * @return Response Self reference
*/ */
@ -252,7 +251,8 @@ class Response
'%s %d %s', '%s %d %s',
$_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1', $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1',
$this->status, $this->status,
self::$codes[$this->status]), self::$codes[$this->status]
),
true, true,
$this->status $this->status
); );

@ -28,12 +28,12 @@ final class Route
public $callback; public $callback;
/** /**
* @var array HTTP methods * @var array<int, string> HTTP methods
*/ */
public array $methods = []; public array $methods = [];
/** /**
* @var array Route parameters * @var array<int, ?string> Route parameters
*/ */
public array $params = []; public array $params = [];
@ -56,8 +56,8 @@ final class Route
* Constructor. * Constructor.
* *
* @param string $pattern URL pattern * @param string $pattern URL pattern
* @param mixed $callback Callback function * @param callable $callback Callback function
* @param array $methods HTTP methods * @param array<int, string> $methods HTTP methods
* @param bool $pass Pass self in callback parameters * @param bool $pass Pass self in callback parameters
*/ */
public function __construct(string $pattern, $callback, array $methods, bool $pass) public function __construct(string $pattern, $callback, array $methods, bool $pass)

@ -23,6 +23,7 @@ class Router
public bool $case_sensitive = false; public bool $case_sensitive = false;
/** /**
* Mapped routes. * Mapped routes.
* @var array<int, Route>
*/ */
protected array $routes = []; protected array $routes = [];
@ -34,7 +35,7 @@ class Router
/** /**
* Gets mapped routes. * Gets mapped routes.
* *
* @return array Array of routes * @return array<int, Route> Array of routes
*/ */
public function getRoutes(): array public function getRoutes(): array
{ {
@ -53,7 +54,7 @@ class Router
* Maps a URL pattern to a callback function. * Maps a URL pattern to a callback function.
* *
* @param string $pattern URL pattern to match * @param string $pattern URL pattern to match
* @param callback $callback Callback function * @param callable $callback Callback function
* @param bool $pass_route Pass the matching route object to the callback * @param bool $pass_route Pass the matching route object to the callback
*/ */
public function map(string $pattern, callable $callback, bool $pass_route = false): void public function map(string $pattern, callable $callback, bool $pass_route = false): void
@ -81,7 +82,7 @@ class Router
{ {
$url_decoded = urldecode($request->url); $url_decoded = urldecode($request->url);
while ($route = $this->current()) { while ($route = $this->current()) {
if (false !== $route && $route->matchMethod($request->method) && $route->matchUrl($url_decoded, $this->case_sensitive)) { if ($route->matchMethod($request->method) && $route->matchUrl($url_decoded, $this->case_sensitive)) {
return $route; return $route;
} }
$this->next(); $this->next();

@ -34,7 +34,7 @@ class View
/** /**
* View variables. * View variables.
* *
* @var array * @var array<string, mixed>
*/ */
protected $vars = []; protected $vars = [];
@ -70,8 +70,9 @@ class View
/** /**
* Sets a template variable. * Sets a template variable.
* *
* @param mixed $key Key * @param string|iterable<string, mixed> $key Key
* @param string $value Value * @param mixed $value Value
* @return static
*/ */
public function set($key, $value = null) public function set($key, $value = null)
{ {
@ -82,6 +83,8 @@ class View
} else { } else {
$this->vars[$key] = $value; $this->vars[$key] = $value;
} }
return $this;
} }
/** /**
@ -100,6 +103,7 @@ class View
* Unsets a template variable. If no key is passed in, clear all variables. * Unsets a template variable. If no key is passed in, clear all variables.
* *
* @param string $key Key * @param string $key Key
* @return static
*/ */
public function clear($key = null) public function clear($key = null)
{ {
@ -108,15 +112,18 @@ class View
} else { } else {
unset($this->vars[$key]); unset($this->vars[$key]);
} }
return $this;
} }
/** /**
* Renders a template. * Renders a template.
* *
* @param string $file Template file * @param string $file Template file
* @param array $data Template data * @param array<string, mixed> $data Template data
* *
* @throws \Exception If template not found * @throws \Exception If template not found
* @return void
*/ */
public function render($file, $data = null) public function render($file, $data = null)
{ {
@ -139,7 +146,7 @@ class View
* Gets the output of a template. * Gets the output of a template.
* *
* @param string $file Template file * @param string $file Template file
* @param array $data Template data * @param array<string, mixed> $data Template data
* *
* @return string Output of template * @return string Output of template
*/ */
@ -196,5 +203,6 @@ class View
public function e($str) public function e($str)
{ {
echo htmlentities($str); echo htmlentities($str);
return htmlentities($str);
} }
} }

@ -11,7 +11,6 @@ declare(strict_types=1);
namespace flight\util; namespace flight\util;
use ArrayAccess; use ArrayAccess;
use function count;
use Countable; use Countable;
use Iterator; use Iterator;
use JsonSerializable; use JsonSerializable;
@ -23,18 +22,21 @@ if (!interface_exists('JsonSerializable')) {
/** /**
* The Collection class allows you to access a set of data * The Collection class allows you to access a set of data
* using both array and object notation. * using both array and object notation.
* @implements ArrayAccess<string, mixed>
* @implements Iterator<string, mixed>
*/ */
final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializable final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializable
{ {
/** /**
* Collection data. * Collection data.
* @var array<string, mixed>
*/ */
private array $data; private array $data;
/** /**
* Constructor. * Constructor.
* *
* @param array $data Initial data * @param array<string, mixed> $data Initial data
*/ */
public function __construct(array $data = []) public function __construct(array $data = [])
{ {
@ -102,11 +104,11 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
/** /**
* Sets an item at the offset. * Sets an item at the offset.
* *
* @param string $offset Offset * @param ?string $offset Offset
* @param mixed $value Value * @param mixed $value Value
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetSet($offset, $value) public function offsetSet($offset, $value): void
{ {
if (null === $offset) { if (null === $offset) {
$this->data[] = $value; $this->data[] = $value;
@ -169,13 +171,11 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
/** /**
* Gets the next collection value. * Gets the next collection value.
*
* @return mixed Value
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function next() public function next(): void
{ {
return next($this->data); next($this->data);
} }
/** /**
@ -187,7 +187,7 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
{ {
$key = key($this->data); $key = key($this->data);
return null !== $key && false !== $key; return null !== $key;
} }
/** /**
@ -203,7 +203,7 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
/** /**
* Gets the item keys. * Gets the item keys.
* *
* @return array Collection keys * @return array<int, string> Collection keys
*/ */
public function keys(): array public function keys(): array
{ {
@ -213,7 +213,7 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
/** /**
* Gets the collection data. * Gets the collection data.
* *
* @return array Collection data * @return array<string, mixed> Collection data
*/ */
public function getData(): array public function getData(): array
{ {
@ -223,19 +223,15 @@ final class Collection implements ArrayAccess, Iterator, Countable, JsonSerializ
/** /**
* Sets the collection data. * Sets the collection data.
* *
* @param array $data New collection data * @param array<string, mixed> $data New collection data
*/ */
public function setData(array $data): void public function setData(array $data): void
{ {
$this->data = $data; $this->data = $data;
} }
/** #[\ReturnTypeWillChange]
* Gets the collection data which can be serialized to JSON. public function jsonSerialize()
*
* @return array Collection data which can be serialized by <b>json_encode</b>
*/
public function jsonSerialize(): array
{ {
return $this->data; return $this->data;
} }

@ -9,5 +9,9 @@ declare(strict_types=1);
*/ */
interface LegacyJsonSerializable interface LegacyJsonSerializable
{ {
/**
* Gets the collection data which can be serialized to JSON.
* @return mixed Collection data which can be serialized by <b>json_encode</b>
*/
public function jsonSerialize(); public function jsonSerialize();
} }

@ -0,0 +1,3 @@
<?php
class ReturnTypeWillChange {}

@ -0,0 +1,10 @@
includes:
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
parameters:
level: 6
excludePaths:
- vendor
paths:
- flight
- index.php
Loading…
Cancel
Save