diff --git a/composer.json b/composer.json index ee5efa70..49bafaf7 100644 --- a/composer.json +++ b/composer.json @@ -27,21 +27,16 @@ "ext-json": "*" }, "autoload": { - "files": [ - "flight/autoload.php" - ] - }, - "autoload-dev": { "classmap": [ - "tests/classes/" + "flight/Flight.php" ], "psr-4": { - "Tests\\PHP8\\": [ - "tests/named-arguments" - ], - "Tests\\Server\\": "tests/server", - "Tests\\ServerV2\\": "tests/server-v2", - "tests\\groupcompactsyntax\\": "tests/groupcompactsyntax" + "flight\\": "flight" + } + }, + "autoload-dev": { + "psr-4": { + "tests\\": "tests" } }, "require-dev": { @@ -80,7 +75,7 @@ ], "test-server-v2": [ "echo \"Running Test Server\"", - "@php -S localhost:8000 -t tests/server-v2" + "@php -S localhost:8000 -t tests/server_v2" ], "test-performance": [ "echo \"Running Performance Tests...\"", diff --git a/flight/Flight.php b/flight/Flight.php index c2e9a012..ddb536f3 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -11,8 +11,6 @@ use flight\core\EventDispatcher; use Psr\Container\ContainerInterface; -require_once __DIR__ . '/autoload.php'; - /** * The Flight class is a static representation of the framework. * diff --git a/flight/autoload.php b/flight/autoload.php index 0a31c864..e4017284 100644 --- a/flight/autoload.php +++ b/flight/autoload.php @@ -7,4 +7,8 @@ require_once __DIR__ . '/Flight.php'; require_once __DIR__ . '/core/Loader.php'; -Loader::autoload(true, [dirname(__DIR__)]); +if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + return require_once __DIR__ . '/../vendor/autoload.php'; +} + +Loader::autoload(true, dirname(__DIR__)); diff --git a/flight/core/Loader.php b/flight/core/Loader.php index 1824b9c7..36093cb6 100644 --- a/flight/core/Loader.php +++ b/flight/core/Loader.php @@ -48,10 +48,9 @@ class Loader * Registers a class. * * @param string $name Registry name - * @param class-string|Closure(): T $class Class name or function to instantiate class + * @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 - * + * @param null|(Closure(T $instance): void) $callback $callback Function to call after object instantiation * @template T of object */ public function register(string $name, $class, array $params = [], ?callable $callback = null): void @@ -215,12 +214,14 @@ public static function loadClass(string $class): void */ public static function addDirectory($dir): void { - if (\is_array($dir) || \is_object($dir)) { + if (is_iterable($dir)) { foreach ($dir as $value) { self::addDirectory($value); } - } elseif (\is_string($dir)) { - if (!\in_array($dir, self::$dirs, true)) { + } elseif (is_string($dir)) { + $dir = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $dir); + + if (!in_array($dir, self::$dirs, true)) { self::$dirs[] = $dir; } } diff --git a/index.php b/index.php index 0db24be2..e9af83f1 100644 --- a/index.php +++ b/index.php @@ -2,8 +2,7 @@ declare(strict_types=1); -require_once 'flight/Flight.php'; -// require 'flight/autoload.php'; +require_once __DIR__ . '/flight/autoload.php'; Flight::route('/', function () { echo 'hello world!'; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b890bb7f..b4b2ed2a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,7 +2,6 @@ flight/ - - flight/autoload.php - tests/ - tests/named-arguments/ + tests/named_arguments/ diff --git a/tests/EventSystemTest.php b/tests/EventSystemTest.php index 9a229b6e..7af48f4f 100644 --- a/tests/EventSystemTest.php +++ b/tests/EventSystemTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace flight\tests; +namespace tests; use Flight; use PHPUnit\Framework\TestCase; diff --git a/tests/LoaderTest.php b/tests/LoaderTest.php index de37efa8..cbb916a5 100644 --- a/tests/LoaderTest.php +++ b/tests/LoaderTest.php @@ -4,10 +4,12 @@ namespace tests; +use Closure; use flight\core\Loader; use tests\classes\Factory; use tests\classes\User; use PHPUnit\Framework\TestCase; +use ReflectionClass; use tests\classes\TesterClass; class LoaderTest extends TestCase @@ -17,7 +19,11 @@ class LoaderTest extends TestCase protected function setUp(): void { $this->loader = new Loader(); - $this->loader->autoload(true, __DIR__ . '/classes'); + } + + protected function tearDown(): void + { + Loader::setV2ClassLoading(true); } // Autoload a class @@ -85,7 +91,7 @@ public function testSharedInstance(): void // Gets an object from a factory method public function testRegisterUsingCallable(): void { - $this->loader->register('e', ['\tests\classes\Factory', 'create']); + $this->loader->register('e', Closure::fromCallable([Factory::class, 'create'])); $obj = $this->loader->load('e'); @@ -140,29 +146,32 @@ public function testNewInstance6Params(): void public function testAddDirectoryAsArray(): void { - $loader = new class extends Loader { - public function getDirectories() - { - return self::$dirs; - } - }; - $loader->addDirectory([__DIR__ . '/classes']); - self::assertEquals([ - dirname(__DIR__), - __DIR__ . '/classes' - ], $loader->getDirectories()); + $loader = new Loader(); + $loader::addDirectory([__DIR__ . '/classes']); + + $dirsProperty = (new ReflectionClass(Loader::class))->getProperty('dirs'); + + if (PHP_VERSION_ID < 80100) { + $dirsProperty->setAccessible(true); + } + + $dirs = $dirsProperty->getValue($loader); + + self::assertEquals([__DIR__ . DIRECTORY_SEPARATOR . 'classes'], $dirs); } public function testV2ClassLoading(): void { - $loader = new class extends Loader { - public static function getV2ClassLoading() - { - return self::$v2ClassLoading; - } - }; - $this->assertTrue($loader::getV2ClassLoading()); + $loader = new Loader(); + + $v2ClassLoadingProperty = (new ReflectionClass(Loader::class))->getProperty('v2ClassLoading'); + + if (PHP_VERSION_ID < 80100) { + $v2ClassLoadingProperty->setAccessible(true); + } + + $this->assertTrue($v2ClassLoadingProperty->getValue($loader)); $loader::setV2ClassLoading(false); - $this->assertFalse($loader::getV2ClassLoading()); + $this->assertFalse($v2ClassLoadingProperty->getValue($loader)); } } diff --git a/tests/named-arguments/ExampleClass.php b/tests/named_arguments/ExampleClass.php similarity index 78% rename from tests/named-arguments/ExampleClass.php rename to tests/named_arguments/ExampleClass.php index 508068c1..95550476 100644 --- a/tests/named-arguments/ExampleClass.php +++ b/tests/named_arguments/ExampleClass.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace tests\named_arguments; + // phpcs:ignore PSR1.Classes.ClassDeclaration.MissingNamespace class ExampleClass { diff --git a/tests/named-arguments/FlightTest.php b/tests/named_arguments/FlightTest.php similarity index 98% rename from tests/named-arguments/FlightTest.php rename to tests/named_arguments/FlightTest.php index 0d5abff1..26cd46fa 100644 --- a/tests/named-arguments/FlightTest.php +++ b/tests/named_arguments/FlightTest.php @@ -2,10 +2,9 @@ declare(strict_types=1); -namespace Tests\PHP8; +namespace tests\named_arguments; use DateTimeImmutable; -use ExampleClass; use Flight; use flight\Container; use flight\Engine; diff --git a/tests/phpunit_autoload.php b/tests/phpunit_autoload.php deleted file mode 100644 index 5bf47dad..00000000 --- a/tests/phpunit_autoload.php +++ /dev/null @@ -1,9 +0,0 @@ -Middleware text: You are not authorized to access this route!'; - } - } - } -} - -namespace { - - use Tests\ServerV2\AuthCheck; - - require_once __DIR__ . '/../phpunit_autoload.php'; - - Flight::set('flight.content_length', false); - Flight::set('flight.views.path', './'); - Flight::set('flight.views.extension', '.phtml'); - // This enables the old functionality of Flight output buffering - Flight::set('flight.v2.output_buffering', true); - - // Test 1: Root route - Flight::route('/', function () { - echo 'Route text: Root route works!'; - - if (Flight::request()->query['redirected']) { - echo '
Redirected from /redirect route successfully!'; - } - }); - - Flight::route('/querytestpath', function () { - echo 'Route text: This ir query route
'; - echo 'I got such query parameters:
';
-        print_r(Flight::request()->query);
-        echo '
'; - }, false, 'querytestpath'); - - // Test 2: Simple route - Flight::route('/test', function () { - echo 'Route text: Test route works!'; - }); - - // Test 3: Route with parameter - Flight::route('/user/@name', function ($name) { - echo "Route text: Hello, $name!"; - }); - - Flight::route('POST /postpage', function () { - echo 'Route text: THIS IS POST METHOD PAGE'; - }, false, 'postpage'); - - // Test 4: Grouped routes - Flight::group('/group', function () { - Flight::route('/test', function () { - echo 'Route text: Group test route works!'; - }); - - Flight::route('/user/@name', function ($name) { - echo "Route text: There is variable called name and it is $name"; - }); - - Flight::group('/group1', function () { - Flight::group('/group2', function () { - Flight::group('/group3', function () { - Flight::group('/group4', function () { - Flight::group('/group5', function () { - Flight::group('/group6', function () { - Flight::group('/group7', function () { - Flight::group('/group8', function () { - Flight::route('/final_group', function () { - echo 'Mega Group test route works!'; - }, false, 'final_group'); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - // Test 5: Route alias - Flight::route('/alias', function () { - echo 'Route text: Alias route works!'; - }, false, 'aliasroute'); - - $middle = new AuthCheck(); - - // Test 6: Route with middleware - Flight::route('/protected', function () { - echo 'Route text: Protected route works!'; - })->addMiddleware([$middle]); - - // Test 7: Route with template - Flight::route('/template/@name', function ($name) { - Flight::render('template.phtml', ['name' => $name]); - }); - - // Test 8: Throw an error - Flight::route('/error', function () { - trigger_error('This is a successful error'); - }); - - // Test 9: JSON output (should not output any other html) - Flight::route('/json', function () { - echo "\n\n\n\n\n"; - Flight::json(['message' => 'JSON renders successfully!']); - echo "\n\n\n\n\n"; - }); - - // Test 13: JSONP output (should not output any other html) - Flight::route('/jsonp', function () { - echo "\n\n\n\n\n"; - Flight::jsonp(['message' => 'JSONP renders successfully!'], 'jsonp'); - echo "\n\n\n\n\n"; - }); - - Flight::route('/json-halt', function () { - Flight::jsonHalt(['message' => 'JSON rendered and halted successfully with no other body content!']); - }); - - // Test 10: Halt - Flight::route('/halt', function () { - Flight::halt(400, 'Halt worked successfully'); - }); - - // Test 11: Redirect - Flight::route('/redirect', function () { - Flight::redirect('/?redirected=1'); - }); - - Flight::set('flight.views.path', './'); - - Flight::map('error', function (Throwable $error) { - echo "

An error occurred, mapped error method worked, error below

"; - echo '
';
-        echo str_replace(getenv('PWD'), "***CLASSIFIED*****", $error->getTraceAsString());
-        echo "
"; - echo "Go back"; - }); - - Flight::map('notFound', function () { - echo 'Route text: The requested URL was not found'; - echo "Go back"; - }); - - echo ' - - '; - - Flight::before('start', function () { - echo '
'; - }); - - Flight::after('start', function () { - echo '
'; - echo '
'; - echo "Request information
";
-        print_r(Flight::request());
-        echo "
"; - echo "
"; - }); - - Flight::start(); -} diff --git a/tests/server/AuthCheck.php b/tests/server/AuthCheck.php index 79e8f677..c042c1b3 100644 --- a/tests/server/AuthCheck.php +++ b/tests/server/AuthCheck.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Server; +namespace tests\server; class AuthCheck { diff --git a/tests/server/LayoutMiddleware.php b/tests/server/LayoutMiddleware.php index 150985bd..01058c0b 100644 --- a/tests/server/LayoutMiddleware.php +++ b/tests/server/LayoutMiddleware.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Server; +namespace tests\server; use Flight; diff --git a/tests/server/OverwriteBodyMiddleware.php b/tests/server/OverwriteBodyMiddleware.php index 98e84685..6a3dfa8a 100644 --- a/tests/server/OverwriteBodyMiddleware.php +++ b/tests/server/OverwriteBodyMiddleware.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Server; +namespace tests\server; use Flight; diff --git a/tests/server/Pascal_Snake_Case.php b/tests/server/Pascal_Snake_Case.php index d80ed416..df9a66ff 100644 --- a/tests/server/Pascal_Snake_Case.php +++ b/tests/server/Pascal_Snake_Case.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Server; +namespace tests\server; class Pascal_Snake_Case // phpcs:ignore { diff --git a/tests/server/index.php b/tests/server/index.php index 6bb9dcac..c34822ef 100644 --- a/tests/server/index.php +++ b/tests/server/index.php @@ -7,10 +7,12 @@ use flight\database\PdoWrapper; use tests\classes\Container; use tests\classes\ContainerDefault; -use Tests\Server\AuthCheck; -use Tests\Server\LayoutMiddleware; -use Tests\Server\OverwriteBodyMiddleware; -use Tests\Server\Pascal_Snake_Case; +use tests\server\AuthCheck; +use tests\server\LayoutMiddleware; +use tests\server\OverwriteBodyMiddleware; +use tests\server\Pascal_Snake_Case; + +require_once __DIR__ . '/../../vendor/autoload.php'; /* * This is the test file where we can open up a quick test server and make @@ -19,8 +21,6 @@ * @author Kristaps Muižnieks https://github.com/krmu */ -require_once __DIR__ . '/../phpunit_autoload.php'; - Flight::set('flight.content_length', false); Flight::set('flight.views.path', './'); Flight::set('flight.views.extension', '.phtml'); diff --git a/tests/server_v2/AuthCheck.php b/tests/server_v2/AuthCheck.php new file mode 100644 index 00000000..6ae651de --- /dev/null +++ b/tests/server_v2/AuthCheck.php @@ -0,0 +1,15 @@ +Middleware text: You are not authorized to access this route!'; + } + } +} diff --git a/tests/server_v2/index.php b/tests/server_v2/index.php new file mode 100644 index 00000000..63bd73a8 --- /dev/null +++ b/tests/server_v2/index.php @@ -0,0 +1,228 @@ +Route text: Root route works!'; + + if (Flight::request()->query['redirected']) { + echo '
Redirected from /redirect route successfully!'; + } +}); + +Flight::route('/querytestpath', function () { + echo 'Route text: This is query route
'; + echo 'I got such query parameters:
';
+    print_r(Flight::request()->query);
+    echo '
'; +}, false, 'querytestpath'); + +// Test 2: Simple route +Flight::route('/test', function () { + echo 'Route text: Test route works!'; +}); + +// Test 3: Route with parameter +Flight::route('/user/@name', function ($name) { + echo "Route text: Hello, $name!"; +}); + +Flight::route('POST /postpage', function () { + echo 'Route text: THIS IS POST METHOD PAGE'; +}, false, 'postpage'); + +// Test 4: Grouped routes +Flight::group('/group', function () { + Flight::route('/test', function () { + echo 'Route text: Group test route works!'; + }); + + Flight::route('/user/@name', function ($name) { + echo "Route text: There is variable called name and it is $name"; + }); + + Flight::group('/group1', function () { + Flight::group('/group2', function () { + Flight::group('/group3', function () { + Flight::group('/group4', function () { + Flight::group('/group5', function () { + Flight::group('/group6', function () { + Flight::group('/group7', function () { + Flight::group('/group8', function () { + Flight::route('/final_group', function () { + echo 'Mega Group test route works!'; + }, false, 'final_group'); + }); + }); + }); + }); + }); + }); + }); + }); +}); + +// Test 5: Route alias +Flight::route('/alias', function () { + echo 'Route text: Alias route works!'; +}, false, 'aliasroute'); + +$middle = new AuthCheck(); + +// Test 6: Route with middleware +Flight::route('/protected', function () { + echo 'Route text: Protected route works!'; +})->addMiddleware([$middle]); + +// Test 7: Route with template +Flight::route('/template/@name', function ($name) { + Flight::render('template.phtml', ['name' => $name]); +}); + +// Test 8: Throw an error +Flight::route('/error', function () { + trigger_error('This is a successful error'); +}); + +// Test 9: JSON output (should not output any other html) +Flight::route('/json', function () { + echo "\n\n\n\n\n"; + Flight::json(['message' => 'JSON renders successfully!']); + echo "\n\n\n\n\n"; +}); + +// Test 13: JSONP output (should not output any other html) +Flight::route('/jsonp', function () { + echo "\n\n\n\n\n"; + Flight::jsonp(['message' => 'JSONP renders successfully!'], 'jsonp'); + echo "\n\n\n\n\n"; +}); + +Flight::route('/json-halt', function () { + Flight::jsonHalt(['message' => 'JSON rendered and halted successfully with no other body content!']); +}); + +// Test 10: Halt +Flight::route('/halt', function () { + Flight::halt(400, 'Halt worked successfully'); +}); + +// Test 11: Redirect +Flight::route('/redirect', function () { + Flight::redirect('/?redirected=1'); +}); + +Flight::set('flight.views.path', './'); + +Flight::map('error', function (Throwable $error) { + echo "

An error occurred, mapped error method worked, error below

"; + echo '
';
+    echo str_replace(getenv('PWD'), "***CLASSIFIED*****", $error->getTraceAsString());
+    echo "
"; + echo "Go back"; +}); + +Flight::map('notFound', function () { + echo 'Route text: The requested URL was not found'; + echo "Go back"; +}); + +echo ' + +'; + +Flight::before('start', function () { + echo '
'; +}); + +Flight::after('start', function () { + echo '
'; + echo '
'; + echo "Request information
";
+    print_r(Flight::request());
+    echo "
"; + echo "
"; +}); + +Flight::start(); diff --git a/tests/server-v2/template.phtml b/tests/server_v2/template.phtml similarity index 100% rename from tests/server-v2/template.phtml rename to tests/server_v2/template.phtml