Remove service_charge_percentage alias and config/fee.php fallback (empty → 0). Move code-managed Montzar/price runtime keys to can_edit=1 in deploy SQL. Add settings:deploy and deploy:tenant artisan commands for server deploy. Advanced admin settings merge runtime keys from local DB; block manual edits. Co-authored-by: Cursor <cursoragent@cursor.com>
152 lines
4.5 KiB
PHP
152 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class DeploySettingsConstCommand extends Command
|
|
{
|
|
protected $signature = 'settings:deploy
|
|
{database?* : نام دیتابیس (اختیاری؛ پیشفرض DB_DATABASE)}
|
|
{--file= : مسیر SQL (پیشفرض database/sql/deploy_settings_const.sql)}
|
|
{--preserve : deploy_settings_const_preserve_value_sync_can_edit.sql}';
|
|
|
|
protected $description = 'اجرای deploy_settings_const.sql روی DB tenant با اتصال .env';
|
|
|
|
public function handle(): int
|
|
{
|
|
$path = $this->resolveSqlPath();
|
|
if ($path === null) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$cfg = config('database.connections.'.config('database.default'));
|
|
if (($cfg['driver'] ?? '') !== 'mysql') {
|
|
$this->error('فقط mysql پشتیبانی میشود.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$host = (string) ($cfg['host'] ?? '127.0.0.1');
|
|
$port = (string) ($cfg['port'] ?? '3306');
|
|
$user = (string) ($cfg['username'] ?? '');
|
|
$pass = (string) ($cfg['password'] ?? '');
|
|
$defaultDb = (string) ($cfg['database'] ?? '');
|
|
|
|
if ($user === '') {
|
|
$this->error('DB_USERNAME در .env خالی است.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$databases = $this->argument('database');
|
|
if ($databases === [] || $databases === null) {
|
|
if ($defaultDb === '') {
|
|
$this->error('نام DB ندهید → DB_DATABASE را در .env بگذارید یا آرگومان بدهید.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
$databases = [$defaultDb];
|
|
}
|
|
|
|
$mysql = $this->findMysqlBinary();
|
|
if ($mysql === null) {
|
|
$this->error('mysql client پیدا نشد. نصب کنید یا اجرا کنید: bash database/sql/run_deploy_settings.sh');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$sql = file_get_contents($path);
|
|
if ($sql === false || trim($sql) === '') {
|
|
$this->error("فایل SQL خالی یا غیرقابل خواندن: {$path}");
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
foreach ($databases as $db) {
|
|
$db = trim((string) $db);
|
|
if ($db === '') {
|
|
continue;
|
|
}
|
|
|
|
$this->info("==> {$path} → {$db} @ {$host}:{$port}");
|
|
|
|
$process = new Process([
|
|
$mysql,
|
|
'-h', $host,
|
|
'-P', $port,
|
|
'-u', $user,
|
|
'--default-character-set=utf8mb4',
|
|
$db,
|
|
], null, ['MYSQL_PWD' => $pass]);
|
|
$process->setInput($sql);
|
|
$process->setTimeout(null);
|
|
$process->run(function ($type, $buffer) {
|
|
$line = trim($buffer);
|
|
if ($line === '') {
|
|
return;
|
|
}
|
|
if ($type === Process::ERR) {
|
|
$this->error($line);
|
|
} else {
|
|
$this->line($line);
|
|
}
|
|
});
|
|
|
|
if (! $process->isSuccessful()) {
|
|
$this->error("خطا روی دیتابیس: {$db}");
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$this->info(" done: {$db}");
|
|
}
|
|
|
|
$this->info('==> all done');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function resolveSqlPath(): ?string
|
|
{
|
|
if ($this->option('preserve')) {
|
|
$relative = 'database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql';
|
|
} else {
|
|
$relative = $this->option('file') ?: 'database/sql/deploy_settings_const.sql';
|
|
}
|
|
|
|
$path = str_starts_with($relative, '/')
|
|
? $relative
|
|
: base_path($relative);
|
|
|
|
if (! is_file($path)) {
|
|
$this->error("فایل SQL پیدا نشد: {$path}");
|
|
|
|
return null;
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
private function findMysqlBinary(): ?string
|
|
{
|
|
$process = new Process(['command', '-v', 'mysql']);
|
|
$process->run();
|
|
if ($process->isSuccessful()) {
|
|
$bin = trim($process->getOutput());
|
|
if ($bin !== '') {
|
|
return $bin;
|
|
}
|
|
}
|
|
|
|
foreach (['/usr/bin/mysql', '/usr/local/bin/mysql'] as $candidate) {
|
|
if (is_executable($candidate)) {
|
|
return $candidate;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|