Framework Update
This commit is contained in:
+15
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Webman\Console;
|
||||
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command as Commands;
|
||||
use support\Container;
|
||||
@@ -29,12 +30,25 @@ class Command extends Application
|
||||
$relativePath = str_replace(str_replace('/', '\\', $path . '\\'), '', str_replace('/', '\\', $file->getRealPath()));
|
||||
// app\command\abc
|
||||
$realNamespace = trim($namspace . '\\' . trim(dirname(str_replace('\\', DIRECTORY_SEPARATOR, $relativePath)), '.'), '\\');
|
||||
$realNamespace = str_replace('/', '\\', $realNamespace);
|
||||
// app\command\doc\def
|
||||
$class_name = trim($realNamespace . '\\' . $file->getBasename('.php'), '\\');
|
||||
if (!class_exists($class_name) || !is_a($class_name, Commands::class, true)) {
|
||||
continue;
|
||||
}
|
||||
$this->add(Container::get($class_name));
|
||||
$reflection = new \ReflectionClass($class_name);
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$properties = $reflection->getStaticProperties();
|
||||
$name = $properties['defaultName'];
|
||||
if (!$name) {
|
||||
throw new RuntimeException("Command {$class_name} has no defaultName");
|
||||
}
|
||||
$description = $properties['defaultDescription'] ?? '';
|
||||
$command = Container::get($class_name);
|
||||
$command->setName($name)->setDescription($description);
|
||||
$this->add($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-45
@@ -56,7 +56,6 @@ class AppPluginCreateCommand extends Command
|
||||
{
|
||||
$base_path = base_path();
|
||||
$this->mkdir("$base_path/plugin/$name/app/controller", 0777, true);
|
||||
$this->mkdir("$base_path/plugin/$name/app/exception", 0777, true);
|
||||
$this->mkdir("$base_path/plugin/$name/app/model", 0777, true);
|
||||
$this->mkdir("$base_path/plugin/$name/app/middleware", 0777, true);
|
||||
$this->mkdir("$base_path/plugin/$name/app/view/index", 0777, true);
|
||||
@@ -66,7 +65,6 @@ class AppPluginCreateCommand extends Command
|
||||
$this->createFunctionsFile("$base_path/plugin/$name/app/functions.php");
|
||||
$this->createControllerFile("$base_path/plugin/$name/app/controller/IndexController.php", $name);
|
||||
$this->createViewFile("$base_path/plugin/$name/app/view/index/index.html");
|
||||
$this->createExceptionFile("$base_path/plugin/$name/app/exception/Handler.php", $name);
|
||||
$this->createConfigFiles("$base_path/plugin/$name/config", $name);
|
||||
$this->createApiFiles("$base_path/plugin/$name/api", $name);
|
||||
}
|
||||
@@ -141,44 +139,6 @@ EOF;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return void
|
||||
*/
|
||||
protected function createExceptionFile($path, $name)
|
||||
{
|
||||
$content = <<<EOF
|
||||
<?php
|
||||
namespace plugin\\$name\\app\\exception;
|
||||
|
||||
use Throwable;
|
||||
use Webman\\Http\\Request;
|
||||
use Webman\\Http\\Response;
|
||||
|
||||
/**
|
||||
* Class Handler
|
||||
* @package Support\Exception
|
||||
*/
|
||||
class Handler extends \\support\\exception\\Handler
|
||||
{
|
||||
public function render(Request \$request, Throwable \$exception): Response
|
||||
{
|
||||
\$code = \$exception->getCode();
|
||||
if (\$request->expectsJson()) {
|
||||
\$json = ['code' => \$code ? \$code : 500, 'message' => \$this->_debug ? \$exception->getMessage() : 'Server internal error', 'type' => 'failed'];
|
||||
\$this->_debug && \$json['traces'] = (string)\$exception;
|
||||
return new Response(200, ['Content-Type' => 'application/json'],
|
||||
\json_encode(\$json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
\$error = \$this->_debug ? \\nl2br((string)\$exception) : 'Server internal error';
|
||||
return new Response(500, [], \$error);
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
file_put_contents($path, $content);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
@@ -223,7 +183,9 @@ class Install
|
||||
public static function install(\$version)
|
||||
{
|
||||
// 导入菜单
|
||||
Menu::import(static::getMenus());
|
||||
if(\$menus = static::getMenus()) {
|
||||
Menu::import(\$menus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +198,7 @@ class Install
|
||||
{
|
||||
// 删除菜单
|
||||
foreach (static::getMenus() as \$menu) {
|
||||
Menu::delete(\$menu['name']);
|
||||
Menu::delete(\$menu['key']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +217,9 @@ class Install
|
||||
static::removeUnnecessaryMenus(\$context['previous_menus']);
|
||||
}
|
||||
// 导入新菜单
|
||||
Menu::import(static::getMenus());
|
||||
if (\$menus = static::getMenus()) {
|
||||
Menu::import(\$menus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,6 +288,7 @@ return [
|
||||
'debug' => true,
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
'version' => '1.0.0'
|
||||
];
|
||||
|
||||
EOF;
|
||||
@@ -371,7 +336,7 @@ EOF;
|
||||
<?php
|
||||
|
||||
return [
|
||||
'' => \\plugin\\$name\\app\\exception\\Handler::class,
|
||||
'' => support\\exception\\Handler::class,
|
||||
];
|
||||
|
||||
EOF;
|
||||
@@ -471,7 +436,7 @@ return [
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => "$base/resource/translations",
|
||||
'path' => base_path() . "/plugin/$name/resource/translations",
|
||||
];
|
||||
|
||||
EOF;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Webman\Console\Util;
|
||||
|
||||
class AppPluginInstallCommand extends Command
|
||||
{
|
||||
|
||||
protected static $defaultName = 'app-plugin:install';
|
||||
protected static $defaultDescription = 'App Plugin Install';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName(static::$defaultName)->setDescription(static::$defaultDescription);
|
||||
$this->addArgument('name', InputArgument::REQUIRED, 'App plugin name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$output->writeln("Install App Plugin $name");
|
||||
$class = "\\plugin\\$name\\api\\Install";
|
||||
if (!method_exists($class, 'install')) {
|
||||
throw new \RuntimeException("Method $class::install not exists");
|
||||
}
|
||||
call_user_func([$class, 'install'], config("plugin.$name.app.version"));
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Webman\Console\Util;
|
||||
|
||||
class AppPluginUninstallCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'app-plugin:uninstall';
|
||||
protected static $defaultDescription = 'App Plugin Uninstall';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addArgument('name', InputArgument::REQUIRED, 'App plugin name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$output->writeln("Uninstall App Plugin $name");
|
||||
$class = "\\plugin\\$name\\api\\Install";
|
||||
if (!method_exists($class, 'uninstall')) {
|
||||
throw new \RuntimeException("Method $class::uninstall not exists");
|
||||
}
|
||||
call_user_func([$class, 'uninstall'], config("plugin.$name.app.version"));
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Phar;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use ZipArchive;
|
||||
|
||||
|
||||
class BuildBinCommand extends BuildPharCommand
|
||||
{
|
||||
protected static $defaultName = 'build:bin';
|
||||
protected static $defaultDescription = 'build bin';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addArgument('version', InputArgument::OPTIONAL, 'PHP version');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$this->checkEnv();
|
||||
|
||||
$output->writeln('Phar packing...');
|
||||
|
||||
$version = $input->getArgument('version');
|
||||
if (!$version) {
|
||||
$version = (float)PHP_VERSION;
|
||||
}
|
||||
$version = $version >= 8.0 ? $version : 8.1;
|
||||
$supportZip = class_exists(ZipArchive::class);
|
||||
$microZipFileName = $supportZip ? "php$version.micro.sfx.zip" : "php$version.micro.sfx";
|
||||
$pharFileName = config('plugin.webman.console.app.phar_filename', 'webman.phar');
|
||||
$binFileName = config('plugin.webman.console.app.bin_filename', 'webman.bin');
|
||||
$this->buildDir = config('plugin.webman.console.app.build_dir', base_path() . '/build');
|
||||
$customIni = config('plugin.webman.console.app.custom_ini', '');
|
||||
|
||||
$binFile = "$this->buildDir/$binFileName";
|
||||
$pharFile = "$this->buildDir/$pharFileName";
|
||||
$zipFile = "$this->buildDir/$microZipFileName";
|
||||
$sfxFile = "$this->buildDir/php$version.micro.sfx";
|
||||
$customIniHeaderFile = "$this->buildDir/custominiheader.bin";
|
||||
|
||||
// 打包
|
||||
$command = new BuildPharCommand();
|
||||
$command->execute($input, $output);
|
||||
|
||||
// 下载 micro.sfx.zip
|
||||
if (!is_file($sfxFile) && !is_file($zipFile)) {
|
||||
$domain = 'download.workerman.net';
|
||||
$output->writeln("\r\nDownloading PHP$version ...");
|
||||
if (extension_loaded('openssl')) {
|
||||
$context = stream_context_create([
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
]
|
||||
]);
|
||||
$client = stream_socket_client("ssl://$domain:443", $context);
|
||||
} else {
|
||||
$client = stream_socket_client("tcp://$domain:80");
|
||||
}
|
||||
|
||||
fwrite($client, "GET /php/$microZipFileName HTTP/1.0\r\nAccept: text/html\r\nHost: $domain\r\nUser-Agent: webman/console\r\n\r\n");
|
||||
$bodyLength = 0;
|
||||
$bodyBuffer = '';
|
||||
$lastPercent = 0;
|
||||
while (true) {
|
||||
$buffer = fread($client, 65535);
|
||||
if ($buffer !== false) {
|
||||
$bodyBuffer .= $buffer;
|
||||
if (!$bodyLength && $pos = strpos($bodyBuffer, "\r\n\r\n")) {
|
||||
if (!preg_match('/Content-Length: (\d+)\r\n/', $bodyBuffer, $match)) {
|
||||
$output->writeln("Download php$version.micro.sfx.zip failed");
|
||||
return self::FAILURE;
|
||||
}
|
||||
$firstLine = substr($bodyBuffer, 9, strpos($bodyBuffer, "\r\n") - 9);
|
||||
if (!preg_match('/200 /', $bodyBuffer)) {
|
||||
$output->writeln("Download php$version.micro.sfx.zip failed, $firstLine");
|
||||
return self::FAILURE;
|
||||
}
|
||||
$bodyLength = (int)$match[1];
|
||||
$bodyBuffer = substr($bodyBuffer, $pos + 4);
|
||||
}
|
||||
}
|
||||
$receiveLength = strlen($bodyBuffer);
|
||||
$percent = ceil($receiveLength * 100 / $bodyLength);
|
||||
if ($percent != $lastPercent) {
|
||||
echo '[' . str_pad('', $percent, '=') . '>' . str_pad('', 100 - $percent) . "$percent%]";
|
||||
echo $percent < 100 ? "\r" : "\n";
|
||||
}
|
||||
$lastPercent = $percent;
|
||||
if ($bodyLength && $receiveLength >= $bodyLength) {
|
||||
file_put_contents($zipFile, $bodyBuffer);
|
||||
break;
|
||||
}
|
||||
if ($buffer === false || !is_resource($client) || feof($client)) {
|
||||
$output->writeln("Fail donwload PHP$version ...");
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$output->writeln("\r\nUse PHP$version ...");
|
||||
}
|
||||
|
||||
// 解压
|
||||
if (!is_file($sfxFile) && $supportZip) {
|
||||
$zip = new ZipArchive;
|
||||
$zip->open($zipFile, ZipArchive::CHECKCONS);
|
||||
$zip->extractTo($this->buildDir);
|
||||
}
|
||||
|
||||
// 生成二进制文件
|
||||
file_put_contents($binFile, file_get_contents($sfxFile));
|
||||
// 自定义INI
|
||||
if (!empty($customIni)) {
|
||||
if (file_exists($customIniHeaderFile)) {
|
||||
unlink($customIniHeaderFile);
|
||||
}
|
||||
$f = fopen($customIniHeaderFile, 'wb');
|
||||
fwrite($f, "\xfd\xf6\x69\xe6");
|
||||
fwrite($f, pack('N', strlen($customIni)));
|
||||
fwrite($f, $customIni);
|
||||
fclose($f);
|
||||
file_put_contents($binFile, file_get_contents($customIniHeaderFile),FILE_APPEND);
|
||||
unlink($customIniHeaderFile);
|
||||
}
|
||||
file_put_contents($binFile, file_get_contents($pharFile), FILE_APPEND);
|
||||
|
||||
// 添加执行权限
|
||||
chmod($binFile, 0755);
|
||||
|
||||
$output->writeln("\r\nSaved $binFileName to $binFile\r\nBuild Success!\r\n");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
+55
-16
@@ -2,17 +2,37 @@
|
||||
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Phar;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Phar;
|
||||
use RuntimeException;
|
||||
|
||||
class PharPackCommand extends Command
|
||||
class BuildPharCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'phar:pack';
|
||||
protected static $defaultName = 'build:phar';
|
||||
protected static $defaultDescription = 'Can be easily packaged a project into phar files. Easy to distribute and use.';
|
||||
|
||||
protected $buildDir = '';
|
||||
|
||||
public function __construct(string $name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->buildDir = config('plugin.webman.console.app.build_dir', base_path() . '/build');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @deprecated 暂时保留 phar:pack 命令,下一个版本再取消
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setAliases([
|
||||
'phar:pack',
|
||||
]);
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
@@ -21,28 +41,24 @@ class PharPackCommand extends Command
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$this->checkEnv();
|
||||
|
||||
$phar_file_output_dir = config('plugin.webman.console.app.phar_file_output_dir');
|
||||
if (empty($phar_file_output_dir)) {
|
||||
throw new RuntimeException('Please set the phar file output directory.');
|
||||
}
|
||||
if (!file_exists($phar_file_output_dir) && !is_dir($phar_file_output_dir)) {
|
||||
if (!mkdir($phar_file_output_dir,0777,true)) {
|
||||
if (!file_exists($this->buildDir) && !is_dir($this->buildDir)) {
|
||||
if (!mkdir($this->buildDir,0777,true)) {
|
||||
throw new RuntimeException("Failed to create phar file output directory. Please check the permission.");
|
||||
}
|
||||
}
|
||||
|
||||
$phar_filename = config('plugin.webman.console.app.phar_filename');
|
||||
$phar_filename = config('plugin.webman.console.app.phar_filename', 'webman.phar');
|
||||
if (empty($phar_filename)) {
|
||||
throw new RuntimeException('Please set the phar filename.');
|
||||
}
|
||||
|
||||
$phar_file = rtrim($phar_file_output_dir,DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $phar_filename;
|
||||
$phar_file = rtrim($this->buildDir,DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $phar_filename;
|
||||
if (file_exists($phar_file)) {
|
||||
unlink($phar_file);
|
||||
}
|
||||
|
||||
$exclude_pattern = config('plugin.webman.console.app.exclude_pattern','');
|
||||
|
||||
$phar = new Phar($phar_file,0,'webman');
|
||||
|
||||
$phar->startBuffering();
|
||||
@@ -66,8 +82,29 @@ class PharPackCommand extends Command
|
||||
|
||||
$phar->buildFromDirectory(BASE_PATH,$exclude_pattern);
|
||||
|
||||
$exclude_files = config('plugin.webman.console.app.exclude_files');
|
||||
|
||||
$exclude_files = config('plugin.webman.console.app.exclude_files',[]);
|
||||
// 打包生成的phar和bin文件是面向生产环境的,所以以下这些命令没有任何意义,执行的话甚至会出错,需要排除在外。
|
||||
$exclude_command_files = [
|
||||
'AppPluginCreateCommand.php',
|
||||
'BuildBinCommand.php',
|
||||
'BuildPharCommand.php',
|
||||
'MakeBootstrapCommand.php',
|
||||
'MakeCommandCommand.php',
|
||||
'MakeControllerCommand.php',
|
||||
'MakeMiddlewareCommand.php',
|
||||
'MakeModelCommand.php',
|
||||
'PluginCreateCommand.php',
|
||||
'PluginDisableCommand.php',
|
||||
'PluginEnableCommand.php',
|
||||
'PluginExportCommand.php',
|
||||
'PluginInstallCommand.php',
|
||||
'PluginUninstallCommand.php'
|
||||
];
|
||||
$exclude_command_files = array_map(function ($cmd_file) {
|
||||
return 'vendor/webman/console/src/Commands/'.$cmd_file;
|
||||
},$exclude_command_files);
|
||||
$exclude_files = array_unique(array_merge($exclude_command_files,$exclude_files));
|
||||
foreach ($exclude_files as $file) {
|
||||
if($phar->offsetExists($file)){
|
||||
$phar->delete($file);
|
||||
@@ -94,16 +131,18 @@ __HALT_COMPILER();
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private function checkEnv(): void
|
||||
public function checkEnv(): void
|
||||
{
|
||||
if (!class_exists(Phar::class, false)) {
|
||||
throw new RuntimeException("The 'phar' extension is required for build phar package");
|
||||
}
|
||||
|
||||
if (ini_get('phar.readonly')) {
|
||||
$command = static::$defaultName;
|
||||
throw new RuntimeException(
|
||||
"The 'phar.readonly' is 'On', build phar must setting it 'Off' or exec with 'php -d phar.readonly=0 ./webman phar:pack'"
|
||||
"The 'phar.readonly' is 'On', build phar must setting it 'Off' or exec with 'php -d phar.readonly=0 ./webman $command'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
|
||||
class FixDisbaleFunctionsCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'fix-disable-functions';
|
||||
protected static $defaultDescription = 'Fix disbale_functions in php.ini';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$php_ini_file = php_ini_loaded_file();
|
||||
if (!$php_ini_file) {
|
||||
$output->writeln('<error>Can not find php.ini</error>');
|
||||
return self::FAILURE;
|
||||
}
|
||||
$output->writeln("Location $php_ini_file");
|
||||
$disable_functions_str = ini_get("disable_functions");
|
||||
if (!$disable_functions_str) {
|
||||
$output->writeln('<success>Ok</success>');
|
||||
}
|
||||
|
||||
$functions_required = [
|
||||
"stream_socket_server",
|
||||
"stream_socket_accept",
|
||||
"stream_socket_client",
|
||||
"pcntl_signal_dispatch",
|
||||
"pcntl_signal",
|
||||
"pcntl_alarm",
|
||||
"pcntl_fork",
|
||||
"posix_getuid",
|
||||
"posix_getpwuid",
|
||||
"posix_kill",
|
||||
"posix_setsid",
|
||||
"posix_getpid",
|
||||
"posix_getpwnam",
|
||||
"posix_getgrnam",
|
||||
"posix_getgid",
|
||||
"posix_setgid",
|
||||
"posix_initgroups",
|
||||
"posix_setuid",
|
||||
"posix_isatty",
|
||||
"proc_open",
|
||||
"proc_get_status",
|
||||
"proc_close",
|
||||
"shell_exec",
|
||||
"exec",
|
||||
];
|
||||
|
||||
$has_disbaled_functions = false;
|
||||
foreach ($functions_required as $func) {
|
||||
if (strpos($disable_functions_str, $func) !== false) {
|
||||
$has_disbaled_functions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$disable_functions = explode(",", $disable_functions_str);
|
||||
$disable_functions_removed = [];
|
||||
foreach ($disable_functions as $index => $func) {
|
||||
$func = trim($func);
|
||||
foreach ($functions_required as $func_prefix) {
|
||||
if (strpos($func, $func_prefix) === 0) {
|
||||
$disable_functions_removed[$func] = $func;
|
||||
unset($disable_functions[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$php_ini_content = file_get_contents($php_ini_file);
|
||||
if (!$php_ini_content) {
|
||||
$output->writeln("<error>$php_ini_file content empty</error>");
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$new_disable_functions_str = implode(",", $disable_functions);
|
||||
$php_ini_content = preg_replace("/\ndisable_functions *?=[^\n]+/", "\ndisable_functions = $new_disable_functions_str", $php_ini_content);
|
||||
|
||||
file_put_contents($php_ini_file, $php_ini_content);
|
||||
|
||||
foreach ($disable_functions_removed as $func) {
|
||||
$output->write(str_pad($func, 30));
|
||||
$output->writeln('<info>enabled</info>');
|
||||
}
|
||||
|
||||
$output->writeln('<info>Succes</info>');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class MakeBootstrapCommand extends Command
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$enable = in_array($input->getArgument('enable'), ['no', '0', 'false', 'n']) ? false : true;
|
||||
|
||||
@@ -100,7 +100,7 @@ class $name extends Command
|
||||
* @param OutputInterface \$output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface \$input, OutputInterface \$output)
|
||||
protected function execute(InputInterface \$input, OutputInterface \$output): int
|
||||
{
|
||||
\$name = \$input->getArgument('name');
|
||||
\$output->writeln('Hello $command');
|
||||
|
||||
+55
-17
@@ -3,6 +3,7 @@
|
||||
namespace Webman\Console\Commands;
|
||||
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use support\Db;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@@ -23,6 +24,7 @@ class MakeModelCommand extends Command
|
||||
{
|
||||
$this->addArgument('name', InputArgument::REQUIRED, 'Model name');
|
||||
$this->addArgument('type', InputArgument::OPTIONAL, 'Type');
|
||||
$this->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'Select database connection. ');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,6 +37,7 @@ class MakeModelCommand extends Command
|
||||
$name = $input->getArgument('name');
|
||||
$name = Util::nameToClass($name);
|
||||
$type = $input->getArgument('type');
|
||||
$connection = $input->getOption('connection');
|
||||
$output->writeln("Make model $name");
|
||||
if (!($pos = strrpos($name, '/'))) {
|
||||
$name = ucfirst($name);
|
||||
@@ -73,9 +76,9 @@ class MakeModelCommand extends Command
|
||||
$type = !$database && $thinkorm ? 'tp' : 'laravel';
|
||||
}
|
||||
if ($type == 'tp') {
|
||||
$this->createTpModel($name, $namespace, $file);
|
||||
$this->createTpModel($name, $namespace, $file, $connection);
|
||||
} else {
|
||||
$this->createModel($name, $namespace, $file);
|
||||
$this->createModel($name, $namespace, $file, $connection);
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
@@ -85,9 +88,10 @@ class MakeModelCommand extends Command
|
||||
* @param $class
|
||||
* @param $namespace
|
||||
* @param $file
|
||||
* @param string|null $connection
|
||||
* @return void
|
||||
*/
|
||||
protected function createModel($class, $namespace, $file)
|
||||
protected function createModel($class, $namespace, $file, $connection = null)
|
||||
{
|
||||
$path = pathinfo($file, PATHINFO_DIRNAME);
|
||||
if (!is_dir($path)) {
|
||||
@@ -97,18 +101,26 @@ class MakeModelCommand extends Command
|
||||
$table_val = 'null';
|
||||
$pk = 'id';
|
||||
$properties = '';
|
||||
$connection = $connection ?: 'mysql';
|
||||
try {
|
||||
$prefix = config('database.connections.mysql.prefix') ?? '';
|
||||
$database = config('database.connections.mysql.database');
|
||||
$prefix = config("database.connections.$connection.prefix") ?? '';
|
||||
$database = config("database.connections.$connection.database");
|
||||
$inflector = InflectorFactory::create()->build();
|
||||
$table_plura = $inflector->pluralize($inflector->tableize($class));
|
||||
if (\support\Db::select("show tables like '{$prefix}{$table_plura}'")) {
|
||||
$con = Db::connection($connection);
|
||||
if ($con->select("show tables like '{$prefix}{$table_plura}'")) {
|
||||
$table_val = "'$table'";
|
||||
$table = "{$prefix}{$table_plura}";
|
||||
} else if (\support\Db::select("show tables like '{$prefix}{$table}'")) {
|
||||
} else if ($con->select("show tables like '{$prefix}{$table}'")) {
|
||||
$table_val = "'$table'";
|
||||
$table = "{$prefix}{$table}";
|
||||
}
|
||||
foreach (\support\Db::select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database'") as $item) {
|
||||
$tableComment = $con->select('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
|
||||
if (!empty($tableComment)) {
|
||||
$comments = $tableComment[0]->table_comment ?? $tableComment[0]->TABLE_COMMENT;
|
||||
$properties .= " * {$table} {$comments}" . PHP_EOL;
|
||||
}
|
||||
foreach ($con->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
|
||||
if ($item->COLUMN_KEY === 'PRI') {
|
||||
$pk = $item->COLUMN_NAME;
|
||||
$item->COLUMN_COMMENT .= "(主键)";
|
||||
@@ -116,7 +128,9 @@ class MakeModelCommand extends Command
|
||||
$type = $this->getType($item->DATA_TYPE);
|
||||
$properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n";
|
||||
}
|
||||
} catch (\Throwable $e) {}
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
$properties = rtrim($properties) ?: ' *';
|
||||
$model_content = <<<EOF
|
||||
<?php
|
||||
@@ -130,6 +144,13 @@ $properties
|
||||
*/
|
||||
class $class extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected \$connection = '$connection';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
@@ -162,10 +183,11 @@ EOF;
|
||||
/**
|
||||
* @param $class
|
||||
* @param $namespace
|
||||
* @param $path
|
||||
* @param $file
|
||||
* @param string|null $connection
|
||||
* @return void
|
||||
*/
|
||||
protected function createTpModel($class, $namespace, $file)
|
||||
protected function createTpModel($class, $namespace, $file, $connection = null)
|
||||
{
|
||||
$path = pathinfo($file, PATHINFO_DIRNAME);
|
||||
if (!is_dir($path)) {
|
||||
@@ -175,17 +197,24 @@ EOF;
|
||||
$table_val = 'null';
|
||||
$pk = 'id';
|
||||
$properties = '';
|
||||
$connection = $connection ?: 'mysql';
|
||||
try {
|
||||
$prefix = config('thinkorm.connections.mysql.prefix') ?? '';
|
||||
$database = config('thinkorm.connections.mysql.database');
|
||||
if (\think\facade\Db::query("show tables like '{$prefix}{$table}'")) {
|
||||
$prefix = config("thinkorm.connections.$connection.prefix") ?? '';
|
||||
$database = config("thinkorm.connections.$connection.database");
|
||||
$con = \think\facade\Db::connect($connection);
|
||||
if ($con->query("show tables like '{$prefix}{$table}'")) {
|
||||
$table = "{$prefix}{$table}";
|
||||
$table_val = "'$table'";
|
||||
} else if (\think\facade\Db::query("show tables like '{$prefix}{$table}s'")) {
|
||||
} else if ($con->query("show tables like '{$prefix}{$table}s'")) {
|
||||
$table = "{$prefix}{$table}s";
|
||||
$table_val = "'$table'";
|
||||
}
|
||||
foreach (\think\facade\Db::query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database'") as $item) {
|
||||
$tableComment = $con->query('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
|
||||
if (!empty($tableComment)) {
|
||||
$comments = $tableComment[0]['table_comment'] ?? $tableComment[0]['TABLE_COMMENT'];
|
||||
$properties .= " * {$table} {$comments}" . PHP_EOL;
|
||||
}
|
||||
foreach ($con->query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
|
||||
if ($item['COLUMN_KEY'] === 'PRI') {
|
||||
$pk = $item['COLUMN_NAME'];
|
||||
$item['COLUMN_COMMENT'] .= "(主键)";
|
||||
@@ -193,7 +222,9 @@ EOF;
|
||||
$type = $this->getType($item['DATA_TYPE']);
|
||||
$properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n";
|
||||
}
|
||||
} catch (\Throwable $e) {}
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
$properties = rtrim($properties) ?: ' *';
|
||||
$model_content = <<<EOF
|
||||
<?php
|
||||
@@ -207,6 +238,13 @@ $properties
|
||||
*/
|
||||
class $class extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected \$connection = '$connection';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
|
||||
@@ -26,7 +26,7 @@ class PluginDisableCommand extends Command
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$output->writeln("Disable plugin $name");
|
||||
|
||||
+10
-10
@@ -8,9 +8,9 @@ class Install
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $pathRelation = array (
|
||||
'config/plugin/webman/console' => 'config/plugin/webman/console',
|
||||
);
|
||||
protected static $pathRelation = [
|
||||
'config/plugin/webman/console' => 'config/plugin/webman/console',
|
||||
];
|
||||
|
||||
/**
|
||||
* Install
|
||||
@@ -18,8 +18,13 @@ class Install
|
||||
*/
|
||||
public static function install()
|
||||
{
|
||||
copy(__DIR__ . "/webman", base_path()."/webman");
|
||||
chmod(base_path()."/webman", 0755);
|
||||
$dest = base_path() . "/webman";
|
||||
if (is_dir($dest)) {
|
||||
echo "Installation failed, please remove directory $dest\n";
|
||||
return;
|
||||
}
|
||||
copy(__DIR__ . "/webman", $dest);
|
||||
chmod(base_path() . "/webman", 0755);
|
||||
|
||||
static::installByRelation();
|
||||
}
|
||||
@@ -33,7 +38,6 @@ class Install
|
||||
if (is_file(base_path()."/webman")) {
|
||||
unlink(base_path() . "/webman");
|
||||
}
|
||||
|
||||
self::uninstallByRelation();
|
||||
}
|
||||
|
||||
@@ -50,7 +54,6 @@ class Install
|
||||
mkdir($parent_dir, 0777, true);
|
||||
}
|
||||
}
|
||||
//symlink(__DIR__ . "/$source", base_path()."/$dest");
|
||||
copy_dir(__DIR__ . "/$source", base_path()."/$dest");
|
||||
}
|
||||
}
|
||||
@@ -66,9 +69,6 @@ class Install
|
||||
if (!is_dir($path) && !is_file($path)) {
|
||||
continue;
|
||||
}
|
||||
/*if (is_link($path) {
|
||||
unlink($path);
|
||||
}*/
|
||||
remove_dir($path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
<?php
|
||||
return [
|
||||
'enable' => true,
|
||||
'enable' => true,
|
||||
|
||||
'phar_file_output_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
|
||||
'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
|
||||
|
||||
'phar_filename' => 'webman.phar',
|
||||
'phar_filename' => 'webman.phar',
|
||||
|
||||
'bin_filename' => 'webman.bin',
|
||||
|
||||
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
|
||||
|
||||
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
|
||||
|
||||
//'exclude_pattern' => '#^(?!.*(config/plugin/webman/console/app.php|webman/console/src/Commands/(PharPackCommand.php|ReloadCommand.php)|LICENSE|composer.json|.github|.idea|doc|docs|.git|.setting|runtime|test|test_old|tests|Tests|vendor-bin|.md))(.*)$#',
|
||||
'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
|
||||
|
||||
'exclude_files' => [
|
||||
'.env', 'LICENSE', 'composer.json', 'composer.lock','start.php'
|
||||
]
|
||||
'.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
|
||||
],
|
||||
|
||||
'custom_ini' => '
|
||||
memory_limit = 256M
|
||||
',
|
||||
];
|
||||
|
||||
Vendored
+14
-2
@@ -36,8 +36,20 @@ foreach (config('plugin', []) as $firm => $projects) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['command'] ?? [] as $command) {
|
||||
$cli->add(Container::get($command));
|
||||
foreach ($project['command'] ?? [] as $class_name) {
|
||||
$reflection = new \ReflectionClass($class_name);
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$properties = $reflection->getStaticProperties();
|
||||
$name = $properties['defaultName'];
|
||||
if (!$name) {
|
||||
throw new RuntimeException("Command {$class_name} has no defaultName");
|
||||
}
|
||||
$description = $properties['defaultDescription'] ?? '';
|
||||
$command = Container::get($class_name);
|
||||
$command->setName($name)->setDescription($description);
|
||||
$cli->add($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user