diff --git a/.gitignore b/.gitignore
index d4933c3..9cbcfba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,5 +11,6 @@ composer.lock
*.swp
*.swo
*.zip
+*.phar
.DS_Store
.interactive_history
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE
similarity index 100%
rename from LICENSE.md
rename to LICENSE
diff --git a/examples/liteApp b/examples/liteApp
index 5147bfd..e988fc2 100644
--- a/examples/liteApp
+++ b/examples/liteApp
@@ -1,7 +1,7 @@
#!/usr/bin/env php
controller('home', HomeController::class);
+$app->controller(PharController::class);
diff --git a/examples/tests/phar.php b/examples/tests/phar.php
new file mode 100644
index 0000000..deeadc8
--- /dev/null
+++ b/examples/tests/phar.php
@@ -0,0 +1,28 @@
+setSignatureAlgorithm(Phar::SHA1);
+
+// 开始打包
+$phar->startBuffering();
+
+// add all files in the project, only include php files
+$phar->buildFromDirectory($srcDir, '/[\.php|app]$/');
+$phar->setStub($phar::createDefaultStub('examples/app'));
+//$phar->setStub($phar::createDefaultStub('examples/app', 'www/index.php'));
+
+$phar->stopBuffering();
+
+// 打包完成
+echo "Finished {$pharFile}\n";
diff --git a/src/Application.php b/src/Application.php
index 0caf087..177c270 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -9,7 +9,6 @@
namespace Inhere\Console;
use Inhere\Console\Base\AbstractApplication;
-use LightCms\Web\App;
/**
* Class App
@@ -17,6 +16,16 @@
*/
class Application extends AbstractApplication
{
+ /**
+ * @var string|null
+ */
+ protected $commandsNamespace;
+
+ /**
+ * @var string|null
+ */
+ protected $controllersNamespace;
+
/**********************************************************
* register console controller/command
**********************************************************/
@@ -266,4 +275,36 @@ public function runAction($name, $action, $believable = false, $standAlone = fal
return $object->run($action);
}
+ /**
+ * @return null|string
+ */
+ public function getCommandsNamespace()
+ {
+ return $this->commandsNamespace;
+ }
+
+ /**
+ * @param null|string $commandsNamespace
+ */
+ public function setCommandsNamespace($commandsNamespace)
+ {
+ $this->commandsNamespace = $commandsNamespace;
+ }
+
+ /**
+ * @return null|string
+ */
+ public function getControllersNamespace()
+ {
+ return $this->controllersNamespace;
+ }
+
+ /**
+ * @param null|string $controllersNamespace
+ */
+ public function setControllersNamespace($controllersNamespace)
+ {
+ $this->controllersNamespace = $controllersNamespace;
+ }
+
}
diff --git a/src/Base/ApplicationInterface.php b/src/Base/ApplicationInterface.php
index 82578f8..6590d08 100644
--- a/src/Base/ApplicationInterface.php
+++ b/src/Base/ApplicationInterface.php
@@ -23,7 +23,6 @@ interface ApplicationInterface
/**
* @param bool $exit
- * @return int
*/
public function run($exit = true);
diff --git a/src/BuiltIn/PharController.php b/src/BuiltIn/PharController.php
new file mode 100644
index 0000000..8a67a1d
--- /dev/null
+++ b/src/BuiltIn/PharController.php
@@ -0,0 +1,57 @@
+*
+ * phar The output phar file path
+ *
+ * @options
+ * -c,--compress Want compress php file.
+ * --file-include Append file include
+ *
+ */
+ public function packCommand()
+ {
+ $pcr = new PharCompiler(BASE_PATH);
+ $pcr->setOptions([
+ 'cliIndex' => 'examples/app',
+ 'webIndex' => null,
+
+ 'compress' => $this->getSameOpt(['c', 'compress'], false),
+
+ 'dirExclude' => '#[\.git|tests]#',
+
+ 'fileInclude' => ['LICENSE', 'app', 'liteApp'],
+ 'fileMatch' => '#\.php#',
+ ]);
+
+ $pharFile = BASE_PATH . '/test.phar';
+ $count = $pcr->pack($pharFile);
+
+ $this->output->json([
+ 'count' => $count,
+ 'size' => round(filesize($pharFile) / 1000, 2) . ' kb',
+ ]);
+ }
+}
\ No newline at end of file
diff --git a/src/LiteApplication.php b/src/LiteApplication.php
index 3fe47f2..f81921a 100644
--- a/src/LiteApplication.php
+++ b/src/LiteApplication.php
@@ -8,6 +8,8 @@
namespace Inhere\Console;
+use Inhere\Console\Style\LiteStyle;
+
/**
* Class LiteApplication
* @package Inhere\Console
@@ -227,11 +229,11 @@ public function commands(array $commands)
public function showCommands($err = '')
{
if ($err) {
- echo "ERROR: $err\n\n";
+ echo LiteStyle::color("ERROR: $err\n\n");
}
$commandWidth = 12;
- $help = "Welcome to the Lite Console Application.\n\nAvailable Commands:\n";
+ $help = "Welcome to the Lite Console Application.\n\nAvailable Commands:\n";
foreach ($this->messages as $command => $desc) {
$command = str_pad($command, $commandWidth, ' ');
@@ -239,7 +241,7 @@ public function showCommands($err = '')
$help .= " $command $desc\n";
}
- echo $help . PHP_EOL;
+ echo LiteStyle::color($help) . PHP_EOL;
exit(0);
}
diff --git a/src/_resources/art-fonts/404.txt b/src/Resources/art-fonts/404.txt
similarity index 100%
rename from src/_resources/art-fonts/404.txt
rename to src/Resources/art-fonts/404.txt
diff --git a/src/Style/Style.php b/src/Style/Style.php
index c1340ac..4b27476 100644
--- a/src/Style/Style.php
+++ b/src/Style/Style.php
@@ -10,6 +10,7 @@
namespace Inhere\Console\Style;
+use Inhere\Console\Application;
use Inhere\Console\Utils\Helper;
/**
@@ -146,7 +147,7 @@ public function format($text)
}
// if don't support output color text, clear color tag.
- if (!Helper::isSupportColor()) {
+ if (!Helper::isSupportColor() || Application::isNoColor()) {
return static::stripColor($text);
}
diff --git a/src/Traits/FormatOutputTrait.php b/src/Traits/FormatOutputTrait.php
index ec5cf70..2b5a644 100644
--- a/src/Traits/FormatOutputTrait.php
+++ b/src/Traits/FormatOutputTrait.php
@@ -8,6 +8,7 @@
namespace Inhere\Console\Traits;
+use Inhere\Console\Application;
use Inhere\Console\Style\Style;
use Inhere\Console\Utils\Helper;
use Inhere\Console\Utils\Show;
diff --git a/src/Traits/InputOutputTrait.php b/src/Traits/InputOutputTrait.php
index 60d49f2..57e77f3 100644
--- a/src/Traits/InputOutputTrait.php
+++ b/src/Traits/InputOutputTrait.php
@@ -57,9 +57,9 @@ public function getRequiredArg($name)
* @see Input::getSameArg()
* {@inheritdoc}
*/
- public function getSameArg($name, $default = null)
+ public function getSameArg(array $names, $default = null)
{
- return $this->input->getSameArg($name, $default);
+ return $this->input->getSameArg($names, $default);
}
/**
@@ -75,9 +75,9 @@ public function getOpt($name, $default = null)
* @see Input::getSameOpt()
* {@inheritdoc}
*/
- public function getSameOpt($name, $default = null)
+ public function getSameOpt(array $names, $default = null)
{
- return $this->input->getSameOpt($name, $default);
+ return $this->input->getSameOpt($names, $default);
}
/**
diff --git a/src/Utils/Helper.php b/src/Utils/Helper.php
index 8a7edd4..4bd175b 100644
--- a/src/Utils/Helper.php
+++ b/src/Utils/Helper.php
@@ -88,6 +88,23 @@ public static function init($object, array $options)
}
}
+ /**
+ * @param string $srcDir
+ * @param callable $filter
+ * @return \RecursiveIteratorIterator
+ */
+ public static function recursiveDirectoryIterator(string $srcDir, callable $filter)
+ {
+ if (!$srcDir || !file_exists($srcDir)) {
+ throw new \LogicException('Please provide a exists source directory.');
+ }
+
+ $directory = new \RecursiveDirectoryIterator($srcDir);
+ $filterIterator = new \RecursiveCallbackFilterIterator($directory, $filter);
+
+ return new \RecursiveIteratorIterator($filterIterator);
+ }
+
/**
* wrap a style tag
* @param string $string
diff --git a/src/Utils/PharCompiler.php b/src/Utils/PharCompiler.php
new file mode 100644
index 0000000..f1be123
--- /dev/null
+++ b/src/Utils/PharCompiler.php
@@ -0,0 +1,341 @@
+ null,
+ 'webIndex' => null,
+
+ // compress php code
+ 'compress' => false,
+
+ 'dirExclude' => '#[\.git|tests]#',
+
+ 'fileInclude' => [],
+ 'fileMatch' => '#\.php#',
+ ];
+
+ /** @var array */
+ private $srcDirs;
+
+ /** @var array */
+ private $appendFiles;
+
+ /** @var string */
+ private $dstDir;
+
+ /**
+ * PharCompiler constructor.
+ * @param null|string|array $srcDirs
+ * @param null $dstDir
+ * @param array $options
+ */
+ public function __construct($srcDirs = null, $dstDir = null, array $options = [])
+ {
+ $this->srcDirs = $srcDirs ? (array)$srcDirs : [];
+ $this->dstDir = $dstDir;
+
+ $this->setOptions($options);
+ }
+
+ /**
+ * Compiles some dirs into a single phar file.
+ * @param string $pharFile The full path to the file to create
+ * @param string $version
+ * @return int
+ */
+ public function pack($pharFile = 'your.phar', $version = '0.0.1')
+ {
+ if (file_exists($pharFile)) {
+ unlink($pharFile);
+ }
+
+ $pharName = basename($pharFile);
+ $this->version = $version;
+
+ if (!$this->srcDirs) {
+ throw new \LogicException('Please setting the source directory for pack');
+ }
+
+ $phar = new Phar($pharFile, 0, $pharName);
+// $phar = new Phar($pharFile, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, $pharName);
+ $phar->setMetadata(['author' => 'inhere']);
+ $phar->setSignatureAlgorithm(Phar::SHA1);
+
+ // begin
+ $phar->startBuffering();
+
+ foreach ($this->srcDirs as $srcDir) {
+ $this->collectFiles($phar, $srcDir);
+ }
+
+ // Stubs
+// $phar->setStub($this->getStub());
+// $stub = Phar::createDefaultStub($this->options['cliIndex'], $this->options['webIndex']);
+// $phar->setStub($stub);
+
+ // 设置入口
+ $phar->setStub("");
+
+ $phar->stopBuffering();
+ $count = $phar->count();
+ unset($phar);
+
+ return $count;
+ }
+
+ /**
+ * @param string $file
+ * @param string|null $distDir
+ */
+ public function unpack(string $file, string $distDir = null)
+ {
+ if (!$distDir = $distDir ?: $this->dstDir) {
+ throw new \LogicException('Please setting the dist directory for unpack');
+ }
+ }
+
+ protected function collectFiles(Phar $phar, $srcDir)
+ {
+ $iterator = Helper::recursiveDirectoryIterator($srcDir, function ($file) {
+ /** @var \SplFileInfo $file */
+ $name = $file->getFilename();
+
+ // Skip hidden files and directories.
+ if ($name[0] === '.') {
+ return false;
+ }
+
+ if ($file->isDir()) {
+ // Only recurse into intended subdirectories.
+ return preg_match($this->options['dirExclude'], $name);
+ }
+
+ if (in_array($name, $this->options['fileInclude'], true)) {
+ return true;
+ }
+
+ // Only consume files of interest.
+ return preg_match($this->options['fileMatch'], $name);
+ });
+
+ $phar->buildFromIterator($iterator, $srcDir);
+// $phar->buildFromDirectory($srcDir, '/[\.php|app]$/');
+
+// foreach ($iterator as $file) {
+// $this->addFileToPhar($phar, $file, $srcDir);
+// }
+ }
+
+ /**
+ * Add a file to the Phar.
+ * @param Phar $phar
+ * @param \SplFileInfo $file
+ * @param string $basePath
+ */
+ private function addFileToPhar($phar, \SplFileInfo $file, $basePath)
+ {
+ $isPhp = $file->getExtension() === 'php';
+ // $path = str_replace($basePath . DIRECTORY_SEPARATOR, '', $file->getRealPath());
+ $path = substr($file->getRealPath(), strlen($basePath) + 1);
+
+ if ($isPhp && $this->options['compress']) {
+ $content = php_strip_whitespace($file);
+ } elseif ('LICENSE' === basename($file)) {
+ $content = file_get_contents($file);
+ $content = "\n" . $content . "\n";
+ } else {
+ $content = file_get_contents($file);
+ }
+
+ $phar->addFromString($path, $content);
+ }
+
+ const STUB_AUTOLOAD = <<>> \*/}sm', self::STUB_AUTOLOAD, $content);
+ $content = preg_replace('/\\(c\\) .*?with this source code./sm', self::getStubLicense(), $content);
+
+ $content .= '__HALT_COMPILER();';
+
+ return $content;
+ }
+
+ private static function getStubLicense()
+ {
+ $license = file_get_contents(__DIR__ . '/../../LICENSE');
+ $license = str_replace('The MIT License (MIT)', '', $license);
+ $license = str_replace("\n", "\n * ", trim($license));
+
+ return $license;
+ }
+
+ /**
+ * @param string $file
+ * @return $this
+ */
+ public function setCliIndex(string $file)
+ {
+ $this->options['cliIndex'] = $file;
+
+ return $this;
+ }
+
+ /**
+ * @param string $file
+ * @return $this
+ */
+ public function setWebIndex(string $file)
+ {
+ $this->options['webIndex'] = $file;
+
+ return $this;
+ }
+
+ /**
+ * @param string|array $name
+ * @return $this
+ */
+ public function addFileInclude($name)
+ {
+ $this->options['fileInclude'] = array_merge($this->options['fileInclude'], (array)$name);
+
+ return $this;
+ }
+
+ /**
+ * @param string $regex
+ * @return $this
+ */
+ public function setDirExclude(string $regex)
+ {
+ $this->options['dirExclude'] = $regex;
+
+ return $this;
+ }
+
+ /**
+ * @param string $regex
+ * @return $this
+ */
+ public function setFileMatch(string $regex)
+ {
+ $this->options['fileMatch'] = $regex;
+
+ return $this;
+ }
+
+ /**
+ * @param string $srcDir
+ * @return $this
+ */
+ public function addSrcDir(string $srcDir)
+ {
+ $this->srcDirs[] = $srcDir;
+
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAppendFiles(): array
+ {
+ return $this->appendFiles;
+ }
+
+ /**
+ * @param array $appendFiles
+ * @return PharCompiler
+ */
+ public function setAppendFiles(array $appendFiles): PharCompiler
+ {
+ $this->appendFiles = $appendFiles;
+
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getSrcDirs(): array
+ {
+ return $this->srcDirs;
+ }
+
+ /**
+ * @param string|array $srcDirs
+ */
+ public function setSrcDirs($srcDirs)
+ {
+ $this->srcDirs = (array)$srcDirs;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDstDir(): ?string
+ {
+ return $this->dstDir;
+ }
+
+ /**
+ * @param string $dstDir
+ */
+ public function setDstDir(string $dstDir)
+ {
+ $this->dstDir = $dstDir;
+ }
+
+ /**
+ * @return array
+ */
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+
+ /**
+ * @param array $options
+ */
+ public function setOptions(array $options)
+ {
+ $this->options = array_merge($this->options, $options);
+ }
+}
diff --git a/src/Utils/Show.php b/src/Utils/Show.php
index 8a646ed..b72072e 100644
--- a/src/Utils/Show.php
+++ b/src/Utils/Show.php
@@ -8,6 +8,7 @@
namespace Inhere\Console\Utils;
+use Inhere\Console\Application;
use Inhere\Console\Style\Style;
/**