Skip to content

Commit cb27287

Browse files
authored
Merge branch 'master' into replace-table-with-chart-in-readme
2 parents 31cd1b0 + 5372672 commit cb27287

18 files changed

Lines changed: 304 additions & 128 deletions

.gemini/GEMINI.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ This is the main FlightPHP core library for building fast, simple, and extensibl
1616
- Run tests: `composer test` (uses phpunit/phpunit and spatie/phpunit-watcher)
1717
- Run test server: `composer test-server` or `composer test-server-v2`
1818
- Lint code & Check code style: `composer lint` (uses phpstan/phpstan, level 6)
19-
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR1)
19+
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR12)
2020
- Test coverage: `composer test-coverage`
2121

2222
## Coding Standards
23-
- Follow PSR1 coding standards (enforced by PHPCS)
23+
- Follow PSR12 coding standards (enforced by PHPCS)
2424
- Use strict comparisons (`===`, `!==`)
2525
- PHPStan level 6 compliance
2626
- Focus on PHP 7.4 compatibility (avoid PHP 8+ only features)

.github/copilot-instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ This is the main FlightPHP core library for building fast, simple, and extensibl
1616
- Run tests: `composer test` (uses phpunit/phpunit and spatie/phpunit-watcher)
1717
- Run test server: `composer test-server` or `composer test-server-v2`
1818
- Lint code & Check code style: `composer lint` (uses phpstan/phpstan, level 6)
19-
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR1)
19+
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR12)
2020
- Test coverage: `composer test-coverage`
2121

2222
## Coding Standards
23-
- Follow PSR1 coding standards (enforced by PHPCS)
23+
- Follow PSR12 coding standards (enforced by PHPCS)
2424
- Use strict comparisons (`===`, `!==`)
2525
- PHPStan level 6 compliance
2626
- Focus on PHP 7.4 compatibility (avoid PHP 8+ only features)

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ This is the main FlightPHP core library for building fast, simple, and extensibl
1616
- Run tests: `composer test` (uses phpunit/phpunit and spatie/phpunit-watcher)
1717
- Run test server: `composer test-server` or `composer test-server-v2`
1818
- Lint code & Check code style: `composer lint` (uses phpstan/phpstan, level 6)
19-
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR1)
19+
- Beautify code: `composer format` (uses squizlabs/php_codesniffer, PSR12)
2020
- Test coverage: `composer test-coverage`
2121

2222
## Coding Standards
23-
- Follow PSR1 coding standards (enforced by PHPCS)
23+
- Follow PSR12 coding standards (enforced by PHPCS)
2424
- Use strict comparisons (`===`, `!==`)
2525
- PHPStan level 6 compliance
2626
- Focus on PHP 7.4 compatibility (avoid PHP 8+ only features)

CONTRIBUTING.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ Flight aims to be simple and fast. Anything that compromises either of those two
99

1010
* **Dependencies** - We strive to be dependency free in Flight. Yes even polyfills, yes even `Interface` only repos like `psr/container`. The fewer dependencies, the fewer your exposed attack vectors.
1111

12-
* **Coding Standards** - We use PSR1 coding standards enforced by PHPCS. Some standards that either need additional configuration or need to be manually done are:
12+
* **Coding Standards** - We use PSR-12 coding standards enforced by PHPCS. Some standards that either need additional configuration or need to be manually done are:
1313
* PHPStan is at level 6.
14-
* `===` instead of truthy or falsey statements like `==` or `!is_array()`.
15-
14+
* `===` instead of truthy or falsy statements like `==`.
15+
1616
* **PHP 7.4 Focused** - We do not make PHP 8+ focused enhancements on the framework as the focus is maintaining PHP 7.4.
1717

1818
* **Core functionality vs Plugin** - Have a conversation with us in the [chatroom](https://matrix.to/#/!cTfwPXhpkTXPXwVmxY:matrix.org?via=matrix.org&via=leitstelle511.net&via=integrations.ems.host) to know if your idea is worth makes sense in the framework or in a plugin.
1919

20-
* **Testing** - Until automated testing is put into place, any PRs must pass unit testing in PHP 7.4 and PHP 8.2+. Additionally you need to run `composer test-server` and `composer test-server-v2` and ensure all the header links work correctly.
20+
* **Testing** - PRs must pass unit tests on PHP 7.4 through PHP 8.5+. Additionally you need to run `composer test-server` and `composer test-server-v2` and ensure all the header links work correctly.
2121

2222
#### **Did you find a bug?**
2323

24-
* **Do not open up a GitHub issue if the bug is a security vulnerability**. Instead contact maintainers directly via email to safely pass in the information related to the security vuln.
24+
* **Do not open up a GitHub issue if the bug is a security vulnerability**. Instead contact maintainers directly via email to safely share details about the security vulnerability.
2525

2626
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/flightphp/core/issues).
2727

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,10 @@ composer require flightphp/core
2222
or you can download a zip of this repo. Then you would have a basic `index.php` file like the following:
2323

2424
```php
25-
// if installed with composer
26-
require 'vendor/autoload.php';
27-
// or if installed manually by zip file
28-
// require 'flight/Flight.php';
25+
require 'flight/autoload.php';
2926

3027
Flight::route('/', function () {
31-
echo 'hello world!';
28+
echo 'hello world!';
3229
});
3330

3431
Flight::start();
@@ -38,7 +35,7 @@ Flight::start();
3835

3936
Yes! Flight is fast. It is one of the fastest PHP frameworks available. You can see all the benchmarks at [TechEmpower](https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=frameworks)
4037

41-
See the benchmark below with some other popular PHP frameworks. This is measured in requests processed within the same timeframe.
38+
See the benchmark below with some other popular PHP frameworks. This is measured in requests processed within the same timeframe.
4239

4340
```mermaid
4441
---
@@ -78,9 +75,10 @@ If you have a current project on v2, you should be able to upgrade to v3 with no
7875
> [!IMPORTANT]
7976
> Flight requires `PHP 7.4` or greater.
8077
81-
**Note:** PHP 7.4 is supported because at the current time of writing (2024) PHP 7.4 is the default version for some LTS Linux distributions. Forcing a move to PHP >8 would cause a lot of heartburn for those users.
82-
83-
The framework also supports PHP >8.
78+
> [!NOTE]
79+
> PHP 7.4 is supported because at the current time of writing (2024) PHP 7.4 is the default version for some LTS Linux distributions.
80+
> Forcing a move to PHP 8 would cause a lot of heartburn for those users.
81+
> The framework also supports PHP 8.
8482
8583
# Roadmap
8684

flight/Engine.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
* It is responsible for loading an HTTP request, running the assigned services,
2525
* and generating an HTTP response.
2626
*
27-
* @license MIT, https://docs.flightphp.com/license
28-
* @copyright Copyright (c) 2011-2025, Mike Cao <mike@mikecao.com>, n0nag0n <n0nag0n@sky-9.com>
27+
* @copyright 2011-2026, Mike Cao https://mikecao.com, n0nag0n <n0nag0n@sky-9.com>
2928
*
3029
* @method void start()
3130
* @method void stop()
@@ -75,10 +74,7 @@
7574
* @phpstan-method void json(mixed $data, int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512)
7675
* @phpstan-method void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0)
7776
* @phpstan-method void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512)
78-
*
79-
* Note: IDEs will use standard @method tags for autocompletion, while PHPStan will use @phpstan-* tags for advanced type checking.
80-
*
81-
* phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
77+
* @license https://docs.flightphp.com/license MIT
8278
*/
8379
class Engine
8480
{
@@ -227,8 +223,24 @@ public function init(): void
227223
// which causes a lot of problems. This will be removed
228224
// in v4
229225
$self->response()->v2_output_buffering = $this->get('flight.v2.output_buffering');
230-
// Propagate method override setting to Request
231-
$self->request()::$allowMethodOverride = (bool) $self->get('flight.allow_method_override');
226+
227+
// Propagate method override setting to Request.
228+
// Assign the static on the class first — do not call request() before this,
229+
// or Request's constructor caches the method while the flag is still the default (true).
230+
Request::$allowMethodOverride = (bool) $self->get('flight.allow_method_override');
231+
232+
// If a Request was already built earlier (common: apps touch request() before start)
233+
// while override was still enabled, refresh the cached verb when override is off
234+
// and an override input is present. When no override input exists, leave any
235+
// intentional manual method assignment alone.
236+
if (Request::$allowMethodOverride === false) {
237+
$hasOverrideInput = Request::getVar('HTTP_X_HTTP_METHOD_OVERRIDE') !== ''
238+
|| isset($_REQUEST['_method']);
239+
if ($hasOverrideInput === true) {
240+
$request = $self->request();
241+
$request->method = Request::getMethod();
242+
}
243+
}
232244
});
233245

234246
$this->initialized = true;

flight/Flight.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* The Flight class is a static representation of the framework.
1616
*
1717
* @license MIT, https://docs.flightphp.com/license
18-
* @copyright Copyright (c) 2011-2025, Mike Cao <mike@mikecao.com>, n0nag0n <n0nag0n@sky-9.com>
18+
* @copyright 2011-2026, Mike Cao https://mikecao.com, n0nag0n <n0nag0n@sky-9.com>
1919
*
2020
* @method static void start()
2121
* @method static void path(string $dir)
@@ -77,11 +77,8 @@
7777
* @phpstan-method static void json(mixed $data, int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512)
7878
* @phpstan-method static void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0)
7979
* @phpstan-method static void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512)
80-
*
81-
* Note: IDEs will use standard @method tags for autocompletion,
82-
* while PHPStan will use @phpstan-* tags for advanced type checking.
80+
* @license https://docs.flightphp.com/license MIT
8381
*/
84-
// phpcs:ignore PSR1.Classes.ClassDeclaration.MissingNamespace
8582
class Flight
8683
{
8784
/**

flight/core/Dispatcher.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
* allows you to hook other functions to an event that can modify the
1919
* input parameters and/or the output.
2020
*
21-
* @license MIT, http://flightphp.com/license
22-
* @copyright Copyright (c) 2011, Mike Cao <mike@mikecao.com>
21+
* @copyright 2011 Mike Cao https://mikecao.com
22+
* @license https://docs.flightphp.com/license MIT
2323
* @phpstan-template EngineTemplate of object
2424
*/
2525
class Dispatcher

flight/core/EventDispatcher.php

Lines changed: 28 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -6,134 +6,83 @@
66

77
class EventDispatcher
88
{
9-
/** @var self|null Singleton instance of the EventDispatcher */
109
private static ?self $instance = null;
1110

12-
/** @var array<string, array<int, callable>> */
11+
/** @var array<string, callable[]> */
1312
protected array $listeners = [];
1413

15-
/**
16-
* Singleton instance of the EventDispatcher.
17-
*
18-
* @return self
19-
*/
2014
public static function getInstance(): self
2115
{
2216
if (self::$instance === null) {
2317
self::$instance = new self();
2418
}
19+
2520
return self::$instance;
2621
}
2722

28-
/**
29-
* Register a callback for an event.
30-
*
31-
* @param string $event Event name
32-
* @param callable $callback Callback function
33-
*/
3423
public function on(string $event, callable $callback): void
3524
{
36-
if (isset($this->listeners[$event]) === false) {
37-
$this->listeners[$event] = [];
38-
}
25+
$this->listeners[$event] ??= [];
3926
$this->listeners[$event][] = $callback;
4027
}
4128

4229
/**
43-
* Trigger an event with optional arguments.
44-
*
45-
* @param string $event Event name
46-
* @param mixed ...$args Arguments to pass to the callbacks
47-
*
30+
* @param mixed ...$args Arguments to pass to the listeners.
4831
* @return mixed
4932
*/
5033
public function trigger(string $event, ...$args)
5134
{
52-
$result = null;
53-
if (isset($this->listeners[$event]) === true) {
54-
foreach ($this->listeners[$event] as $callback) {
55-
$result = call_user_func_array($callback, $args);
56-
57-
// If you return false, it will break the loop and stop the other event listeners.
58-
if ($result === false) {
59-
break; // Stop executing further listeners
60-
}
35+
$listenerReturnValue = null;
36+
37+
foreach ($this->getListeners($event) as $listener) {
38+
$listenerReturnValue = $listener(...$args);
39+
40+
if ($listenerReturnValue === false) {
41+
break;
6142
}
6243
}
63-
return $result;
44+
45+
return $listenerReturnValue;
6446
}
6547

66-
/**
67-
* Check if an event has any registered listeners.
68-
*
69-
* @param string $event Event name
70-
*
71-
* @return bool True if the event has listeners, false otherwise
72-
*/
7348
public function hasListeners(string $event): bool
7449
{
75-
return isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0;
50+
return (
51+
isset($this->listeners[$event])
52+
&& is_array($this->listeners[$event])
53+
&& count($this->listeners[$event])
54+
);
7655
}
7756

78-
/**
79-
* Get all listeners registered for a specific event.
80-
*
81-
* @param string $event Event name
82-
*
83-
* @return array<int, callable> Array of callbacks registered for the event
84-
*/
57+
/** @return callable[] */
8558
public function getListeners(string $event): array
8659
{
8760
return $this->listeners[$event] ?? [];
8861
}
8962

90-
/**
91-
* Get a list of all events that have registered listeners.
92-
*
93-
* @return array<int, string> Array of event names
94-
*/
63+
/** @return string[] */
9564
public function getAllRegisteredEvents(): array
9665
{
9766
return array_keys($this->listeners);
9867
}
9968

100-
/**
101-
* Remove a specific listener for an event.
102-
*
103-
* @param string $event the event name
104-
* @param callable $callback the exact callback to remove
105-
*
106-
* @return void
107-
*/
10869
public function removeListener(string $event, callable $callback): void
10970
{
110-
if (isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0) {
111-
$this->listeners[$event] = array_filter($this->listeners[$event], function ($listener) use ($callback) {
112-
return $listener !== $callback;
113-
});
114-
$this->listeners[$event] = array_values($this->listeners[$event]); // Re-index the array
71+
if (!$this->hasListeners($event)) {
72+
return;
11573
}
74+
75+
$this->listeners[$event] = array_values(array_filter(
76+
$this->getListeners($event),
77+
static fn(callable $listener): bool => $listener !== $callback,
78+
));
11679
}
11780

118-
/**
119-
* Remove all listeners for a specific event.
120-
*
121-
* @param string $event the event name
122-
*
123-
* @return void
124-
*/
12581
public function removeAllListeners(string $event): void
12682
{
127-
if (isset($this->listeners[$event]) === true) {
128-
unset($this->listeners[$event]);
129-
}
83+
unset($this->listeners[$event]);
13084
}
13185

132-
/**
133-
* Remove the current singleton instance of the EventDispatcher.
134-
*
135-
* @return void
136-
*/
13786
public static function resetInstance(): void
13887
{
13988
self::$instance = null;

flight/core/Loader.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
* instances with custom initialization parameters. It also performs
1414
* class autoloading.
1515
*
16-
* @license MIT, http://flightphp.com/license
17-
* @copyright Copyright (c) 2011, Mike Cao <mike@mikecao.com>
16+
* @copyright 2011 Mike Cao https://mikecao.com
17+
* @license https://docs.flightphp.com/license MIT
1818
*/
1919
class Loader
2020
{

0 commit comments

Comments
 (0)