- First commit
This commit is contained in:
		
						commit
						19aa25df1b
					
				
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2019 Dave Mc Nicoll | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										18
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
|     "name": "mcnd/cli", | ||||
|     "description": "A middleware which captures CLI commands and executes them based on a preset definition.", | ||||
|     "type": "library", | ||||
|     "license": "MIT", | ||||
|     "authors": [ | ||||
|         { | ||||
|             "name": "Dave Mc Nicoll", | ||||
|             "email": "info@mcnd.ca" | ||||
|         } | ||||
|     ], | ||||
|     "require": {}, | ||||
|     "autoload": { | ||||
|         "psr-4": { | ||||
|             "Mcnd\\CLI\\": "src/" | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								src/CliMiddleware.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/CliMiddleware.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Mcnd\CLI; | ||||
| 
 | ||||
| use Laminas\Diactoros\Response\TextResponse; | ||||
| use Notes\CLI\CommandFetcher; | ||||
| 
 | ||||
| use Psr\Http\Message\ResponseFactoryInterface, | ||||
|     Psr\Container\ContainerInterface, | ||||
|     Psr\Http\Message\ResponseInterface, | ||||
|     Psr\Http\Message\ServerRequestInterface, | ||||
|     Psr\Http\Server\MiddlewareInterface, | ||||
|     Psr\Http\Server\RequestHandlerInterface; | ||||
| 
 | ||||
| class CliMiddleware implements MiddlewareInterface | ||||
| { | ||||
|     public \Closure $defaultResponse; | ||||
|      | ||||
|     public ContainerInterface $container; | ||||
| 
 | ||||
|     public null|CommandFetcher $fetcher; | ||||
| 
 | ||||
|     public CommandStack $commands; | ||||
| 
 | ||||
|     protected array $receivedCommandArgv; | ||||
| 
 | ||||
|     protected array $parsedCommandArgv; | ||||
| 
 | ||||
|     protected array $parsedOptions = []; | ||||
| 
 | ||||
|     public function __construct(ContainerInterface $container, callable $defaultResponseInterface = null, null|CommandFetcher $fetcher = null, null|CommandStack $stack = null) { | ||||
|         $this->defaultResponse = $defaultResponseInterface; | ||||
|         $this->container = $container; | ||||
|         $this->fetcher = $fetcher; | ||||
|         $this->commands = $stack ?? new CommandStack(); | ||||
|     } | ||||
| 
 | ||||
|     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface | ||||
|     { | ||||
|         if (php_sapi_name() === 'cli' OR defined('STDIN')) { | ||||
|             if ($this->fetcher) { | ||||
|                 $this->getCommandsFromAttributes(); | ||||
|             } | ||||
| 
 | ||||
|             $cliRequest = new CliRequest($request); | ||||
| 
 | ||||
|             # $cliRequest->setOptions($commands->getOptions());
 | ||||
| 
 | ||||
|             if ( $command = $this->commands->matchCommand($cliRequest->command, $cliRequest->options) ) { | ||||
|                 if ($command->callback) { | ||||
|                     if (is_string($command->callback)) { | ||||
|                         list($class, $method) = explode('::', $command->callback); | ||||
| 
 | ||||
|                         return $this->container->make($class)->{$method}($request->withAttribute('cli.command', $command)->withAttribute('cli.request', $cliRequest), []); | ||||
|                     } | ||||
|                 } | ||||
|                 else { | ||||
|                     return $this->printCommand($command); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             return call_user_func($this->defaultResponse); | ||||
|         } | ||||
| 
 | ||||
|         return $handler->handle($request); | ||||
|     } | ||||
| 
 | ||||
|     public function getCommandsFromAttributes() : self | ||||
|     { | ||||
|         $this->commands->merge($this->fetcher->compile()); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     private function printCommand(Command $command) : ResponseInterface | ||||
|     { | ||||
|         $text = [ | ||||
|             $command->description, "", | ||||
|             "Usage:", | ||||
|             "  command [options] [arguments]", "", | ||||
|             "Options:", | ||||
|             "  OPTIONS HERE", "", | ||||
|             "Available commands:", | ||||
|             "  COMMANDS HERE", "", | ||||
|         ]; | ||||
| 
 | ||||
|         return new TextResponse( implode(PHP_EOL, $text) ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										59
									
								
								src/CliRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/CliRequest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Mcnd\CLI; | ||||
| 
 | ||||
| use Psr\Http\Message\ServerRequestInterface; | ||||
| 
 | ||||
| class CliRequest | ||||
| { | ||||
|     public array $command = []; | ||||
| 
 | ||||
|     public array $options = []; | ||||
| 
 | ||||
|     protected string $shortOptions; | ||||
| 
 | ||||
|     protected array $longOptions; | ||||
| 
 | ||||
|     public function __construct( | ||||
|         public ServerRequestInterface $request | ||||
|     ) { | ||||
|         $this->parseCommandLine(); | ||||
|     } | ||||
| 
 | ||||
|     public function matchOptions(string ... $options) : bool | ||||
|     { | ||||
|         foreach($options as $opt) { | ||||
|             if ( $this->matchOption($opt) ) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public function matchOption(string $option) : bool | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     protected function parseCommandLine() : void | ||||
|     { | ||||
|         $executionString = $this->argv(); | ||||
| 
 | ||||
|         # Removing execution's path
 | ||||
|         array_shift($executionString); | ||||
| 
 | ||||
|         foreach($executionString as $cmd) { | ||||
|             $this->command[] = $cmd; | ||||
|         } | ||||
| 
 | ||||
|         dump($executionString); | ||||
| 
 | ||||
|         $this->command = $executionString; | ||||
|     } | ||||
| 
 | ||||
|     protected function argv() : array | ||||
|     { | ||||
|         return $this->request->getServerParams()['argv']; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								src/Command.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/Command.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Mcnd\CLI; | ||||
| 
 | ||||
| class Command | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly string $name, | ||||
|         public string $description, | ||||
|         public array $options = [], | ||||
|         public null|Command $parent = null, | ||||
|         public \Closure|string|null $callback = null, | ||||
|         public bool $isRoot = false, | ||||
|     ) {} | ||||
| 
 | ||||
|     public function pushOption(Option|array $option) : void | ||||
|     { | ||||
|         $this->options[] = array_merge($this->options, $option); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/CommandStack.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/CommandStack.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Mcnd\CLI; | ||||
| 
 | ||||
| class CommandStack | ||||
| { | ||||
|     public array $commands = []; | ||||
| 
 | ||||
|     public function __construct() | ||||
|     {} | ||||
| 
 | ||||
|     public function merge(CommandStack $stack) : void | ||||
|     { | ||||
|         $this->commands = array_merge($this->commands, $stack->commands); | ||||
|     } | ||||
| 
 | ||||
|     public function append(Command $command) : void | ||||
|     { | ||||
|         $this->commands[] = $command; | ||||
|     } | ||||
| 
 | ||||
|     public function matchCommand(array $commands, array $options) : null|Command | ||||
|     { | ||||
|         $cmd = implode(' ', $commands); | ||||
| 
 | ||||
|         foreach($this->commands as $command) { | ||||
|             if ($command->name === $cmd) { | ||||
|                 return $command; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/Option.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/Option.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Mcnd\CLI; | ||||
| 
 | ||||
| class Option | ||||
| { | ||||
|     public const ARGUMENT_NONE = 0; | ||||
| 
 | ||||
|     public const ARGUMENT_OPTIONAL = 1; | ||||
| 
 | ||||
|     public const ARGUMENT_REQUIRED = 2; | ||||
| 
 | ||||
|     public function __construct( | ||||
|         public array|string $toggle, | ||||
|         public string $description = "", | ||||
|         public int $argument = self::ARGUMENT_NONE, | ||||
|         public mixed $default = null, | ||||
|         public mixed $awaiting = null, | ||||
|     ) {} | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user