- Work done on CLI package
This commit is contained in:
		
							parent
							
								
									6d771ed88f
								
							
						
					
					
						commit
						d08d1f0fe7
					
				@ -56,7 +56,9 @@ class CliMiddleware implements MiddlewareInterface
 | 
			
		||||
                        $request = $request->withAttribute('cli.command', $command)
 | 
			
		||||
                            ->withAttribute('cli.request', $cliRequest);
 | 
			
		||||
 | 
			
		||||
                        return $this->container->make($class)->{$method}($request, []);
 | 
			
		||||
                        $cliRequest->parseOptions($command);
 | 
			
		||||
 | 
			
		||||
                        return $this->container->make($class)->{$method}($request, $this->commands->arguments, $command->options, $cliRequest->rest);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
@ -79,6 +81,7 @@ class CliMiddleware implements MiddlewareInterface
 | 
			
		||||
 | 
			
		||||
    private function printCommand(Command $command) : ResponseInterface
 | 
			
		||||
    {
 | 
			
		||||
        # @TODO !
 | 
			
		||||
        $text = [
 | 
			
		||||
            $command->description, "",
 | 
			
		||||
            "#[color: rgb(145;130;195), format: bold]Usage:[#]",
 | 
			
		||||
@ -93,6 +96,7 @@ class CliMiddleware implements MiddlewareInterface
 | 
			
		||||
            $text = ( new AsciiFormatter() )->parse($text);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # @TODO => plug httpfactory here !
 | 
			
		||||
        return new TextResponse( implode(PHP_EOL, $text) );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,9 +10,9 @@ class CliRequest
 | 
			
		||||
 | 
			
		||||
    public array $options = [];
 | 
			
		||||
 | 
			
		||||
    protected string $shortOptions;
 | 
			
		||||
    public mixed $rest = "";
 | 
			
		||||
 | 
			
		||||
    protected array $longOptions;
 | 
			
		||||
    protected array $unparsedOptions;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public ServerRequestInterface $request
 | 
			
		||||
@ -20,22 +20,6 @@ class CliRequest
 | 
			
		||||
        $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();
 | 
			
		||||
@ -43,11 +27,67 @@ class CliRequest
 | 
			
		||||
        # Removing execution's path
 | 
			
		||||
        array_shift($executionString);
 | 
			
		||||
 | 
			
		||||
        foreach($executionString as $cmd) {
 | 
			
		||||
        while ( $cmd = array_shift($executionString) ) {
 | 
			
		||||
            if (str_starts_with($cmd, '-')) {
 | 
			
		||||
                array_unshift($executionString, $cmd);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->command[] = $cmd;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->command = $executionString;
 | 
			
		||||
        $this->unparsedOptions = $executionString;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Replaces the limited getopt() method which do not allow for parameters to be passed after multiple command arguments
 | 
			
		||||
     *
 | 
			
		||||
     * @param Command $command  Matched command found using parseCommandLine
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function parseOptions(Command $command) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->getopt($command->options);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
        if ( false !== $options ) {
 | 
			
		||||
            if ($restIndex !== null) {
 | 
			
		||||
                $this->rest = $this->argv()[$restIndex];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->options = $options;
 | 
			
		||||
        }*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getopt(OptionStack $options) :void
 | 
			
		||||
    {
 | 
			
		||||
        $currentOption = false;
 | 
			
		||||
 | 
			
		||||
        while ( $argument = array_shift($this->unparsedOptions) ) {
 | 
			
		||||
            #if ($currentOption !== false) {
 | 
			
		||||
                $currentOption = $options->matchOption($argument);
 | 
			
		||||
 | 
			
		||||
                if ($currentOption === false) {
 | 
			
		||||
                    $this->rest = implode(' ', $this->unparsedOptions);
 | 
			
		||||
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /*elseif (is_array($currentOption)) {
 | 
			
		||||
                    foreach($currentOption as $matchingOption) {
 | 
			
		||||
                        $matchingOption->handle();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
 | 
			
		||||
                }*/
 | 
			
		||||
           # }
 | 
			
		||||
            #else {
 | 
			
		||||
 | 
			
		||||
           # }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # dump($options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function argv() : array
 | 
			
		||||
 | 
			
		||||
@ -4,17 +4,33 @@ namespace Mcnd\CLI;
 | 
			
		||||
 | 
			
		||||
class Command
 | 
			
		||||
{
 | 
			
		||||
    public array $arguments;
 | 
			
		||||
 | 
			
		||||
    public readonly OptionStack $options;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public readonly string $name,
 | 
			
		||||
        public string $description,
 | 
			
		||||
        public array $options = [],
 | 
			
		||||
        array $options = [],
 | 
			
		||||
        public null|Command $parent = null,
 | 
			
		||||
        public \Closure|string|null $callback = null,
 | 
			
		||||
        public bool $isRoot = false,
 | 
			
		||||
    ) {}
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->options = new OptionStack($options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function pushOption(Option|array $option) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->options[] = array_merge($this->options, $option);
 | 
			
		||||
        if (is_array($option)) {
 | 
			
		||||
            $this->options->merge($option);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            $this->options->append($option);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setArguments(array $arguments) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->arguments = $arguments;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -4,10 +4,10 @@ namespace Mcnd\CLI;
 | 
			
		||||
 | 
			
		||||
class CommandStack
 | 
			
		||||
{
 | 
			
		||||
    public array $commands = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {}
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public array $commands = [],
 | 
			
		||||
        public array $arguments = []
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function merge(CommandStack $stack) : void
 | 
			
		||||
    {
 | 
			
		||||
@ -28,16 +28,20 @@ class CommandStack
 | 
			
		||||
     */
 | 
			
		||||
    public function matchCommand(array $commands) : null|Command
 | 
			
		||||
    {
 | 
			
		||||
        $arguments = [];
 | 
			
		||||
 | 
			
		||||
        while ($commands) {
 | 
			
		||||
            $cmd = implode(' ', $commands);
 | 
			
		||||
 | 
			
		||||
            foreach ($this->commands as $command) {
 | 
			
		||||
                if ($command->name === $cmd) {
 | 
			
		||||
                    $this->arguments = array_reverse($arguments);
 | 
			
		||||
 | 
			
		||||
                    return $command;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            array_pop($commands);
 | 
			
		||||
            $arguments[] = array_pop($commands);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										109
									
								
								src/Option.php
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								src/Option.php
									
									
									
									
									
								
							@ -2,20 +2,113 @@
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI;
 | 
			
		||||
 | 
			
		||||
use Mcnd\CLI\Option\{CountOption, ParsedOption, ToggleOption, ValueOption, KeyValueOption};
 | 
			
		||||
 | 
			
		||||
class Option
 | 
			
		||||
{
 | 
			
		||||
    public const ARGUMENT_NONE = 0;
 | 
			
		||||
 | 
			
		||||
    public const ARGUMENT_OPTIONAL = 1;
 | 
			
		||||
 | 
			
		||||
    public const ARGUMENT_REQUIRED = 2;
 | 
			
		||||
    protected ParsedOption $parsed;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public array|string $toggle,
 | 
			
		||||
        public array|string $switch,
 | 
			
		||||
        public string $description = "",
 | 
			
		||||
        public int $argument = self::ARGUMENT_NONE,
 | 
			
		||||
        public mixed $default = null,
 | 
			
		||||
        public mixed $awaiting = null,
 | 
			
		||||
    ) {}
 | 
			
		||||
        public OptionValueTypeEnum $value = OptionValueTypeEnum::NoValue,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->setParsedOption();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getParsedOption() : ParsedOption
 | 
			
		||||
    {
 | 
			
		||||
        return $this->parsed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setParsedOption() : void
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->value === OptionValueTypeEnum::NoValue) {
 | 
			
		||||
            $this->parsed = new ToggleOption($this);
 | 
			
		||||
        }
 | 
			
		||||
        elseif ($this->value === OptionValueTypeEnum::OptionalValue || $this->value === OptionValueTypeEnum::RequiredValue ) {
 | 
			
		||||
            $this->parsed = new ValueOption($this);
 | 
			
		||||
        }
 | 
			
		||||
        elseif ($this->value === OptionValueTypeEnum::KeyValue) {
 | 
			
		||||
            $this->parsed = new KeyValueOption($this);
 | 
			
		||||
        }
 | 
			
		||||
        elseif ($this->value === OptionValueTypeEnum::CountValue) {
 | 
			
		||||
            $this->parsed = new CountOption($this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function awaitingValue() : bool
 | 
			
		||||
    {
 | 
			
		||||
        return match($this->value) {
 | 
			
		||||
            OptionValueTypeEnum::NoValue => false,
 | 
			
		||||
            OptionValueTypeEnum::CountValue => false,
 | 
			
		||||
            OptionValueTypeEnum::RequiredValue => $this->parsed->getValue() === null,
 | 
			
		||||
            OptionValueTypeEnum::OptionalValue => $this->parsed->getValue() === null,
 | 
			
		||||
            OptionValueTypeEnum::MultipleValue => true,
 | 
			
		||||
            OptionValueTypeEnum::KeyValue => true,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function matchShortSwitch(string $switch) : bool
 | 
			
		||||
    {
 | 
			
		||||
        $switch = strtolower($switch);
 | 
			
		||||
 | 
			
		||||
        foreach((array) $this->switch as $item) {
 | 
			
		||||
            if ( ! str_starts_with($item, '--') && substr($item, 0, 1) === '-' ) {
 | 
			
		||||
                $singleItem = substr($item, 1, 1);
 | 
			
		||||
 | 
			
		||||
                if (substr($item, 1, 1) === $switch) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function matchLongSwitch(string $switch) : bool
 | 
			
		||||
    {
 | 
			
		||||
        list($key, $value) = array_pad(explode('=', $switch, 2), 2, null);
 | 
			
		||||
 | 
			
		||||
        foreach((array) $this->switch as $item) {
 | 
			
		||||
            if ( str_starts_with($item, '--') ) {
 | 
			
		||||
                if (strtolower(substr($item, 2)) === strtolower($key)) {
 | 
			
		||||
                    if ($value !== null) {
 | 
			
		||||
                        $this->value($value);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function toggle() : void
 | 
			
		||||
    {
 | 
			
		||||
        match ($this->value) {
 | 
			
		||||
            OptionValueTypeEnum::NoValue => $this->parsed->toggle(),
 | 
			
		||||
            OptionValueTypeEnum::CountValue => $this->parsed->toggle(),
 | 
			
		||||
            OptionValueTypeEnum::OptionalValue => $this->parsed->setValue(true),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function value(mixed $value = null) : mixed
 | 
			
		||||
    {
 | 
			
		||||
        if ($value === null) {
 | 
			
		||||
            return $this->parsed->getValue();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return match ($this->value) {
 | 
			
		||||
            OptionValueTypeEnum::MultipleValue => $this->parsed->addValue($value),
 | 
			
		||||
            OptionValueTypeEnum::RequiredValue => $this->parsed->setValue($value),
 | 
			
		||||
            OptionValueTypeEnum::OptionalValue => $this->parsed->setValue($value),
 | 
			
		||||
            OptionValueTypeEnum::KeyValue => $this->parsed->setRawValue($value),
 | 
			
		||||
            OptionValueTypeEnum::NoValue => throw new \RuntimeException(sprintf("A value was given to an option (%s) which was not awaiting any", implode(', ', (array) $this->switch))),
 | 
			
		||||
            OptionValueTypeEnum::CountValue => is_numeric($value) ? $this->parsed->setValue($value) : throw new \RuntimeException(sprintf("A value was given to an option (%s) which is countable", implode(', ', (array) $this->switch))),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/Option/CountOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Option/CountOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class CountOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected int $count = 0;
 | 
			
		||||
 | 
			
		||||
    public function toggle() : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->count++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->count ?: null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setValue(int $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->count = $value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								src/Option/CountOption.php~
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/Option/CountOption.php~
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class CountOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected int $count = 0;
 | 
			
		||||
 | 
			
		||||
    public function toggle() : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->count++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->count ?: null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setValue(mixed $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        if ( ! is_int($value) ) {
 | 
			
		||||
            throw new \RuntimeException("A value was given to an option (%s) which is countable");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->count = $value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/Option/KeyValueOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Option/KeyValueOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class KeyValueOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected array $values = [];
 | 
			
		||||
 | 
			
		||||
    public function setValue(string $key, string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->values[$key] = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setRawValue(string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        if (! str_contains($value, '=')) {
 | 
			
		||||
            throw new \RuntimeException(sprintf("A key=value notation was awaited, received %s instead", $value));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        list($key, $value) = explode('=', trim($value), 2);
 | 
			
		||||
 | 
			
		||||
        $this->setValue($key, $value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->values ?: null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/Option/KeyValueOption.php~
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Option/KeyValueOption.php~
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class KeyValueOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected array $values = [];
 | 
			
		||||
 | 
			
		||||
    public function setValue(string $key, string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->values[$key] = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setRawValue(string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        list($key, $value) = explode('=', trim($value), 2);
 | 
			
		||||
 | 
			
		||||
        $this->setValue($key, $value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->values ?: null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/Option/MultipleValueOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Option/MultipleValueOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class MultipleValueOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected array $value;
 | 
			
		||||
 | 
			
		||||
    public function addValue(string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->value[] = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setValue(array $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->value = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->value ?? null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								src/Option/ParsedOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Option/ParsedOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
use Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
abstract class ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public readonly Option $attribute,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public abstract function getValue() : mixed;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/Option/ToggleOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Option/ToggleOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class ToggleOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected bool $value = false;
 | 
			
		||||
 | 
			
		||||
    public function toggle() : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->value = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|true
 | 
			
		||||
    {
 | 
			
		||||
        return $this->value ?: null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function toggled() : bool
 | 
			
		||||
    {
 | 
			
		||||
        return (bool) $this->getValue();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/Option/ValueOption.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Option/ValueOption.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI\Option;
 | 
			
		||||
 | 
			
		||||
class ValueOption extends ParsedOption
 | 
			
		||||
{
 | 
			
		||||
    protected string $value;
 | 
			
		||||
 | 
			
		||||
    public function setValue(string $value) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->value = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue() : null|string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->value ?? null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										92
									
								
								src/OptionStack.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/OptionStack.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI;
 | 
			
		||||
 | 
			
		||||
class OptionStack
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public array $options = []
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function merge(OptionStack|array $stack) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->options = array_merge($this->options, is_array($stack) ? $stack : $stack->options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function append(Option $option) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->options[] = $option;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function get(string $switch) : Option|false
 | 
			
		||||
    {
 | 
			
		||||
        foreach($this->options as $option) {
 | 
			
		||||
            if ($option->matchShortSwitch($switch) || $option->matchLongSwitch($switch)) {
 | 
			
		||||
                return $option;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Matches the exact option (short or long switch) found from the stack
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $switch
 | 
			
		||||
     * @return Option|null
 | 
			
		||||
     */
 | 
			
		||||
    public function matchOption(string $switch) : bool|Option
 | 
			
		||||
    {
 | 
			
		||||
        $matched = false;
 | 
			
		||||
 | 
			
		||||
        # Long switch
 | 
			
		||||
        if (str_starts_with($switch, '--')) {
 | 
			
		||||
            $switch = substr($switch, 2);
 | 
			
		||||
 | 
			
		||||
            foreach($this->options as $option) {
 | 
			
		||||
                if ( $option->matchLongSwitch($switch) ) {
 | 
			
		||||
                    $matched = true;
 | 
			
		||||
 | 
			
		||||
                    if ( $option->awaitingValue() ) {
 | 
			
		||||
                        return $option;
 | 
			
		||||
                    }
 | 
			
		||||
                    # matching --switch
 | 
			
		||||
                    else {
 | 
			
		||||
                        $option->toggle();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } # Short switch
 | 
			
		||||
        elseif (substr($switch, 0, 1) === '-') {
 | 
			
		||||
            $switch = substr($switch, 1);
 | 
			
		||||
            $split = str_split($switch);
 | 
			
		||||
 | 
			
		||||
            foreach($split as $index => $singleSwitch) {
 | 
			
		||||
                foreach ($this->options as $option) {
 | 
			
		||||
                    if ( $option->matchShortSwitch($singleSwitch) ) {
 | 
			
		||||
                        $matched = true;
 | 
			
		||||
 | 
			
		||||
                        if ( $option->awaitingValue() ) {
 | 
			
		||||
                            # matching -abcValueOfC
 | 
			
		||||
                            if ( $index < count($split) - 1 ) {
 | 
			
		||||
                                $option->value(substr($switch, $index + 1));
 | 
			
		||||
 | 
			
		||||
                                return false;
 | 
			
		||||
                            }
 | 
			
		||||
                            # matching -abc
 | 
			
		||||
                            else {
 | 
			
		||||
                                return $option;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            $option->toggle();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $matched;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/OptionValueTypeEnum.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/OptionValueTypeEnum.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mcnd\CLI;
 | 
			
		||||
 | 
			
		||||
enum OptionValueTypeEnum
 | 
			
		||||
{
 | 
			
		||||
    case NoValue;         # -s
 | 
			
		||||
    case RequiredValue;   # -s value / -svalue
 | 
			
		||||
    case OptionalValue;   # -s value / -svalue
 | 
			
		||||
    case MultipleValue;   # -s value1 -s value2 -svalue3 -sothervalue4 / --var value1 --var value2
 | 
			
		||||
    case KeyValue;        # -s key=value / --var key=value
 | 
			
		||||
    case CountValue;      # -ssss / -s 4 / --var 4
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user