2016-11-01 14:12:11 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace NoccyLabs\Shell;
|
|
|
|
|
|
|
|
class Context
|
|
|
|
{
|
|
|
|
protected $name;
|
|
|
|
|
|
|
|
protected $commands = [];
|
|
|
|
|
2016-11-01 15:10:35 +00:00
|
|
|
protected $commandInfo = [];
|
|
|
|
|
2016-11-01 14:12:11 +00:00
|
|
|
protected $data = [];
|
|
|
|
|
2016-11-02 12:53:56 +00:00
|
|
|
protected $parent;
|
|
|
|
|
|
|
|
protected $shell;
|
2016-11-01 14:12:11 +00:00
|
|
|
|
|
|
|
public function __construct($name=null, array $data=[])
|
|
|
|
{
|
|
|
|
$this->name = $name;
|
|
|
|
$this->data = $data;
|
|
|
|
$this->configure();
|
|
|
|
}
|
|
|
|
|
2016-11-15 02:29:00 +00:00
|
|
|
public function getContextInfo()
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-11-02 12:57:12 +00:00
|
|
|
public function setShell(Shell $shell)
|
|
|
|
{
|
|
|
|
$this->shell = $shell;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getShell()
|
|
|
|
{
|
|
|
|
return $this->shell;
|
|
|
|
}
|
|
|
|
|
2016-11-02 12:53:56 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-01 14:12:11 +00:00
|
|
|
protected function configure()
|
|
|
|
{
|
|
|
|
// Override this to do setup stuff
|
2016-11-01 15:10:35 +00:00
|
|
|
$this->findCommands();
|
2016-11-01 14:12:11 +00:00
|
|
|
}
|
|
|
|
|
2016-11-01 15:10:35 +00:00
|
|
|
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) {
|
2016-11-02 21:49:19 +00:00
|
|
|
if (preg_match("/^@(command|help|args|global)\\s*(.*)$/", $line, $match)) {
|
2016-11-01 15:10:35 +00:00
|
|
|
list($void,$key,$value) = $match;
|
|
|
|
$info[$key] = $value;
|
|
|
|
}
|
|
|
|
if (count($info)>0) {
|
2016-11-01 15:19:38 +00:00
|
|
|
$cmdName = array_key_exists("command",$info)?$info["command"]:$method->getName();
|
|
|
|
$this->addCommand($cmdName, [$this, $method->getName()], $info);
|
2016-11-01 15:10:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addCommand($command, callable $handler, array $info=[])
|
2016-11-01 14:12:11 +00:00
|
|
|
{
|
|
|
|
$this->commands[$command] = $handler;
|
2016-11-01 15:10:35 +00:00
|
|
|
$this->commandInfo[$command] = $info;
|
2016-11-02 12:53:56 +00:00
|
|
|
ksort($this->commands);
|
2016-11-01 15:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function setCommandHelp($command, $help)
|
|
|
|
{
|
|
|
|
if (!array_key_exists($command, $this->commandInfo)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$this->commandInfo[$command]['help'] = $help;
|
2016-11-01 14:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2016-11-01 14:28:03 +00:00
|
|
|
$this->addCommand($command, $handler);
|
2016-11-01 14:12:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasCommand($command)
|
|
|
|
{
|
|
|
|
return array_key_exists($command, $this->commands);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCommand($command)
|
|
|
|
{
|
|
|
|
return $this->commands[$command];
|
|
|
|
}
|
|
|
|
|
2016-11-01 15:10:35 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-02 21:49:19 +00:00
|
|
|
public function isCommandGlobal($command)
|
|
|
|
{
|
2016-11-04 01:23:10 +00:00
|
|
|
if (strpos($command," ")!==false) {
|
|
|
|
list($command, $void) = explode(" ",$command,2);
|
|
|
|
}
|
2016-11-02 21:49:19 +00:00
|
|
|
$info = $this->commandInfo[$command];
|
|
|
|
return array_key_exists('global', $info);
|
|
|
|
}
|
|
|
|
|
2016-11-19 13:18:53 +00:00
|
|
|
/**
|
|
|
|
* Catch-all handler for commands not defined in context, globally or builtin.
|
|
|
|
* Override this function and return true if the command is handled ok.
|
|
|
|
*
|
|
|
|
* @param string $command The command to execute
|
|
|
|
* @param string[] $args The arguments to the command
|
|
|
|
* @return bool True if the command was handled
|
|
|
|
*/
|
|
|
|
public function execute($command, ...$args)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the name of the context
|
|
|
|
*
|
|
|
|
*/
|
2016-11-01 14:12:11 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-01 15:19:38 +00:00
|
|
|
}
|