First working version with non working routes
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| vendor/ | ||||
							
								
								
									
										9
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| Todos: | ||||
| - [ ] Collect routes properly | ||||
| - [ ] Process routes correctly | ||||
|  | ||||
|  | ||||
|  | ||||
| Routing: | ||||
| Currently the routes are hardcoded, we need we way to process | ||||
| all classes maybe and sort them into a list of routes. | ||||
							
								
								
									
										14
									
								
								app/Controller/BaseController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/Controller/BaseController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Controller; | ||||
|  | ||||
| use Ardent\Undercurrent\Attribute\Route; | ||||
|  | ||||
| class BaseController | ||||
| { | ||||
|     #[Route('/hello')] | ||||
|     public function HelloWorld(): string | ||||
|     { | ||||
|         return 'Hello, World!'; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								app/Kernel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/Kernel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App; | ||||
|  | ||||
| use Ardent\Undercurrent\Kernel\BaseKernel; | ||||
|  | ||||
| class Kernel extends BaseKernel | ||||
| { | ||||
| } | ||||
							
								
								
									
										9
									
								
								app/public/index.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/public/index.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| use App\Kernel; | ||||
|  | ||||
| require_once dirname(__DIR__).'/../vendor/autoload.php'; | ||||
|  | ||||
| $kernel = new Kernel(); | ||||
|  | ||||
| $kernel(); | ||||
							
								
								
									
										15
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| { | ||||
|     "name": "ardent/undercurrent", | ||||
|     "description": "A tiny no nonsense php framework", | ||||
|     "type": "library", | ||||
|     "require": { | ||||
|         "php": "^8.1" | ||||
|     }, | ||||
|     "autoload": { | ||||
|         "psr-4": { | ||||
|             "Ardent\\Undercurrent\\": "src/", | ||||
|             "App\\": "app/" | ||||
|         } | ||||
|     }, | ||||
|     "license": "GPL-3.0-only" | ||||
| } | ||||
							
								
								
									
										20
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| { | ||||
|     "_readme": [ | ||||
|         "This file locks the dependencies of your project to a known state", | ||||
|         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||
|         "This file is @generated automatically" | ||||
|     ], | ||||
|     "content-hash": "04c6989f1bd672a6accd35142e2adac1", | ||||
|     "packages": [], | ||||
|     "packages-dev": [], | ||||
|     "aliases": [], | ||||
|     "minimum-stability": "stable", | ||||
|     "stability-flags": [], | ||||
|     "prefer-stable": false, | ||||
|     "prefer-lowest": false, | ||||
|     "platform": { | ||||
|         "php": "^8.1" | ||||
|     }, | ||||
|     "platform-dev": [], | ||||
|     "plugin-api-version": "2.2.0" | ||||
| } | ||||
							
								
								
									
										15
									
								
								src/Attribute/Route.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Attribute/Route.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Ardent\Undercurrent\Attribute; | ||||
|  | ||||
| use Attribute; | ||||
|  | ||||
| #[Attribute] | ||||
| class Route | ||||
| { | ||||
|     public function __construct( | ||||
|         public string $path, | ||||
|     ) | ||||
|     { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								src/Collector/ClassAttributeCollector.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/Collector/ClassAttributeCollector.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Ardent\Undercurrent\Collector; | ||||
|  | ||||
| use RecursiveDirectoryIterator; | ||||
| use RecursiveIteratorIterator; | ||||
| use ReflectionClass; | ||||
|  | ||||
| class ClassAttributeCollector | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly string $path, | ||||
|         private readonly string $attribute, | ||||
|     ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function collect(): array | ||||
|     { | ||||
|         $classes = []; | ||||
|         $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path)); | ||||
|         foreach ($files as $file) { | ||||
|             if ($file->getExtension() !== 'php') { | ||||
|                 continue; | ||||
|             } | ||||
|             $class = $this->getClassFromFile($file); | ||||
|             if (!$class) { | ||||
|                 continue; | ||||
|             } | ||||
|             $classes[] = $class; | ||||
|         } | ||||
|         return $classes; | ||||
|     } | ||||
|  | ||||
|     private function getClassFromFile(mixed $file) | ||||
|     { | ||||
|         $contents = file_get_contents($file->getPathname()); | ||||
|         $tokens = token_get_all($contents); | ||||
|         $namespace = ''; | ||||
|         $class = ''; | ||||
|         $classFound = false; | ||||
|         $namespaceFound = false; | ||||
|         foreach ($tokens as $token) { | ||||
|             if (is_array($token)) { | ||||
|                 if ($token[0] === T_NAMESPACE) { | ||||
|                     $namespaceFound = true; | ||||
|                     continue; | ||||
|                 } | ||||
|                 if ($token[0] === T_CLASS) { | ||||
|                     $classFound = true; | ||||
|                     continue; | ||||
|                 } | ||||
|                 if ($namespaceFound && $token[0] === T_STRING) { | ||||
|                     $namespace .= $token[1] . '\\'; | ||||
|                     continue; | ||||
|                 } | ||||
|                 if ($classFound && $token[0] === T_STRING) { | ||||
|                     $class = $token[1]; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (!$class) { | ||||
|             return null; | ||||
|         } | ||||
|         $class = $namespace . $class; | ||||
|         $attributes = $this->getClassAttributes($class); | ||||
|         if (!in_array($this->attribute, $attributes)) { | ||||
|             return null; | ||||
|         } | ||||
|         return $class; | ||||
|     } | ||||
|  | ||||
|     private function getClassAttributes(string $class): array | ||||
|     { | ||||
|         $attributes = []; | ||||
|         $reflection = new ReflectionClass($class); | ||||
|         foreach ($reflection->getAttributes() as $attribute) { | ||||
|             $attributes[] = $attribute->getName(); | ||||
|         } | ||||
|         return $attributes; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/Container/GenericContainer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Container/GenericContainer.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Ardent\Undercurrent\Container; | ||||
|  | ||||
| use Exception; | ||||
|  | ||||
| class GenericContainer | ||||
| { | ||||
|     private array $definitions = []; | ||||
|  | ||||
|     private array $instances = []; | ||||
|  | ||||
|     public function add(string $className, ?callable $definition = null, bool $singleton = true): self | ||||
|     { | ||||
|         if (!$definition) { | ||||
|             $definition = function () use ($className) { | ||||
|                 return new $className(); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         $this->definitions[$className] = [ | ||||
|             'definition' => $definition, | ||||
|             'singleton' => $singleton, | ||||
|         ]; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @template TClassName | ||||
|      * @param class-string<TClassName> $className | ||||
|      * @return TClassName | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function get(string $className): object | ||||
|     { | ||||
|         if (!isset($this->definitions[$className])) { | ||||
|             throw new Exception("Class $className not found in container"); | ||||
|         } | ||||
|  | ||||
|         $definition = $this->definitions[$className]['definition']; | ||||
|         if ($this->definitions[$className]['singleton']) { | ||||
|             if (isset($this->instances[$className])) { | ||||
|                 return $this->instances[$className]; | ||||
|             } | ||||
|             $instance = $definition(); | ||||
|             $this->instances[$className] = $instance; | ||||
|         } else { | ||||
|             $instance = $definition(); | ||||
|         } | ||||
|  | ||||
|         return $instance; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/Controller/GenericRouter.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Controller/GenericRouter.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Ardent\Undercurrent\Controller; | ||||
|  | ||||
| use App\Controller\BaseController; | ||||
| use Ardent\Undercurrent\Attribute\Route; | ||||
| use Ardent\Undercurrent\Collector\ClassAttributeCollector; | ||||
|  | ||||
| class GenericRouter | ||||
| { | ||||
|     private array $routes = []; | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         $collector = new ClassAttributeCollector( | ||||
|             __DIR__ . '/../../app/Controller', | ||||
|             Route::class, | ||||
|         ); | ||||
|  | ||||
|         $this->routes = $collector->collect(); | ||||
|     } | ||||
|  | ||||
|     public function getRoute(string $route): array | ||||
|     { | ||||
| //        return $this->routes[0]; | ||||
|         return [ | ||||
|             'controller' => BaseController::class, | ||||
|             'method' => 'HelloWorld', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/Kernel/BaseKernel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Kernel/BaseKernel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Ardent\Undercurrent\Kernel; | ||||
|  | ||||
| use App\Controller\BaseController; | ||||
| use Ardent\Undercurrent\Container\GenericContainer; | ||||
| use Ardent\Undercurrent\Controller\GenericRouter; | ||||
|  | ||||
| class BaseKernel | ||||
| { | ||||
|     public function __invoke() | ||||
|     { | ||||
|         $container = new GenericContainer(); | ||||
|         $container->add(GenericRouter::class); | ||||
|         $container->add(BaseController::class); | ||||
|  | ||||
|         $this->render($container); | ||||
|     } | ||||
|  | ||||
|     private function render(GenericContainer $container): void | ||||
|     { | ||||
|         $router = $container->get(GenericRouter::class); | ||||
|         $route = $router->getRoute($_SERVER['REQUEST_URI']); | ||||
|         $controller = $container->get($route['controller']); | ||||
|         $method = $route['method']; | ||||
|         echo $controller->$method(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user