Framework Update

This commit is contained in:
2024-01-31 22:15:08 +08:00
parent b5ff5e8b5f
commit 20678a6a0c
1459 changed files with 25954 additions and 16153 deletions
+15 -1
View File
@@ -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
View File
@@ -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;
}
}
+149
View File
@@ -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;
}
}
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
',
];
+14 -2
View File
@@ -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);
}
}
}