169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace NoccyLabs\Shell;
 | 
						|
 | 
						|
class Context
 | 
						|
{
 | 
						|
    protected $name;
 | 
						|
 | 
						|
    protected $commands = [];
 | 
						|
 | 
						|
    protected $commandInfo = [];
 | 
						|
 | 
						|
    protected $data = [];
 | 
						|
 | 
						|
    protected $parent;
 | 
						|
 | 
						|
    protected $shell;
 | 
						|
 | 
						|
    public function __construct($name=null, array $data=[])
 | 
						|
    {
 | 
						|
        $this->name = $name;
 | 
						|
        $this->data = $data;
 | 
						|
        $this->configure();
 | 
						|
    }
 | 
						|
 | 
						|
    public function setShell(Shell $shell)
 | 
						|
    {
 | 
						|
        $this->shell = $shell;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getShell()
 | 
						|
    {
 | 
						|
        return $this->shell;
 | 
						|
    }
 | 
						|
 | 
						|
    public function setParent(Context $parent=null)
 | 
						|
    {
 | 
						|
        $this->parent = $parent;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getParent()
 | 
						|
    {
 | 
						|
        return $this->parent;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getRoot()
 | 
						|
    {
 | 
						|
        if (!$this->parent) {
 | 
						|
            return $this;
 | 
						|
        }
 | 
						|
        $node = $this;
 | 
						|
        while ($parent = $node->getParent()) {
 | 
						|
            $node = $parent;
 | 
						|
        }
 | 
						|
        return $parent;
 | 
						|
    }
 | 
						|
 | 
						|
    protected function configure()
 | 
						|
    {
 | 
						|
        // Override this to do setup stuff
 | 
						|
        $this->findCommands();
 | 
						|
    }
 | 
						|
 | 
						|
    protected function findCommands()
 | 
						|
    {
 | 
						|
        $refl = new \ReflectionClass(get_called_class());
 | 
						|
        foreach ($refl->getMethods() as $method) {
 | 
						|
            $docblock = $method->getDocComment();
 | 
						|
            $lines = array_map(function ($line) {
 | 
						|
                return trim($line, "*/ \t");
 | 
						|
            }, explode("\n", $docblock));
 | 
						|
            $info = [];
 | 
						|
            foreach ($lines as $line) {
 | 
						|
                if (preg_match("/^@(command|help|args) (.+?)$/", $line, $match)) {
 | 
						|
                    list($void,$key,$value) = $match;
 | 
						|
                    $info[$key] = $value; 
 | 
						|
                }
 | 
						|
                if (count($info)>0) {
 | 
						|
                    $cmdName = array_key_exists("command",$info)?$info["command"]:$method->getName();
 | 
						|
                    $this->addCommand($cmdName, [$this, $method->getName()], $info);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function addCommand($command, callable $handler, array $info=[])
 | 
						|
    {
 | 
						|
        $this->commands[$command] = $handler;
 | 
						|
        $this->commandInfo[$command] = $info;
 | 
						|
        ksort($this->commands);
 | 
						|
    }
 | 
						|
 | 
						|
    public function setCommandHelp($command, $help)
 | 
						|
    {
 | 
						|
        if (!array_key_exists($command, $this->commandInfo)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        $this->commandInfo[$command]['help'] = $help;
 | 
						|
    }
 | 
						|
 | 
						|
    public function addCommands(array $commands)
 | 
						|
    {
 | 
						|
        foreach ($commands as $command=>$handler) {
 | 
						|
            // Make it easier to connect commands direct to local functions
 | 
						|
            if (is_string($handler) && is_callable([$this,$handler])) {
 | 
						|
                $handler = [ $this,$handler ];
 | 
						|
            }
 | 
						|
            // Add the command to the command list
 | 
						|
            $this->addCommand($command, $handler);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function hasCommand($command)
 | 
						|
    {
 | 
						|
        return array_key_exists($command, $this->commands);
 | 
						|
    }
 | 
						|
 | 
						|
    public function getCommand($command)
 | 
						|
    {
 | 
						|
        return $this->commands[$command];
 | 
						|
    }
 | 
						|
 | 
						|
    public function getCommandHelp()
 | 
						|
    {
 | 
						|
        $ret = [];
 | 
						|
        foreach ($this->commands as $command=>$handler) {
 | 
						|
            $info = $this->commandInfo[$command];
 | 
						|
            $args = array_key_exists("args",$info)?$info['args']:"";
 | 
						|
            $help = array_key_exists("help",$info)?$info['help']:"";
 | 
						|
            $ret[trim("{$command} {$args}")] = $help;
 | 
						|
        }
 | 
						|
        return $ret;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getName()
 | 
						|
    {
 | 
						|
        return $this->name;
 | 
						|
    }
 | 
						|
 | 
						|
    public function __get($key)
 | 
						|
    {
 | 
						|
        if (!array_key_exists($key,$this->data)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        return $this->data[$key];
 | 
						|
    }
 | 
						|
 | 
						|
    public function __set($key,$value)
 | 
						|
    {
 | 
						|
        $this->data[$key] = $value;
 | 
						|
    }
 | 
						|
 | 
						|
    public function __isset($key)
 | 
						|
    {
 | 
						|
        return array_key_exists($key);
 | 
						|
    }
 | 
						|
 | 
						|
    public function __unset($key)
 | 
						|
    {
 | 
						|
        unset($this->data[$key]);
 | 
						|
    }
 | 
						|
 | 
						|
    public function getData()
 | 
						|
    {
 | 
						|
        return $this->data;
 | 
						|
    }
 | 
						|
 | 
						|
}
 |