Conversation
There was a problem hiding this comment.
Pull request overview
Evolution CMS JP Edition に最小限の CLI エントリポイントとブートストラップを追加し、DB/設定/キャッシュ操作などの初期コマンドを CLI 経由で実行可能にする変更。
- ルート
evoとmanager/includes/cli/bootstrap.phpにより CLI 実行・初期化・コマンドルーティングを追加 manager/includes/cli/commands/*に DB 操作、設定表示、キャッシュクリア、ヘルプ、コマンド雛形生成を追加- CLI 安定化のためにセッション開始抑止と
mb_internal_encoding呼び出しガードを追加
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| manager/includes/initialize.inc.php | CLI 実行時のセッション開始を抑止 |
| manager/includes/document.parser.class.inc.php | mb_internal_encoding を存在チェック付きで呼ぶ |
| manager/includes/cli/commands/make-command.php | コマンド雛形生成コマンドを追加 |
| manager/includes/cli/commands/help.php | コマンド一覧表示を追加 |
| manager/includes/cli/commands/db-tables.php | テーブル一覧表示を追加 |
| manager/includes/cli/commands/db-query.php | 任意 SQL 実行を追加 |
| manager/includes/cli/commands/db-import.php | SQL インポートを追加(確認フラグあり) |
| manager/includes/cli/commands/db-export.php | SQL エクスポートを追加 |
| manager/includes/cli/commands/db-describe.php | テーブル定義表示を追加 |
| manager/includes/cli/commands/db-count.php | 件数カウントを追加 |
| manager/includes/cli/commands/db-console.php | MySQL クライアント起動を追加 |
| manager/includes/cli/commands/config-show.php | 設定表示を追加 |
| manager/includes/cli/commands/cache-clear.php | キャッシュクリアを追加 |
| manager/includes/cli/cli-helpers.php | CLI 出力・終了・テーブル名補助を追加 |
| manager/includes/cli/bootstrap.php | CLI 用の CMS 初期化を追加 |
| manager/includes/cli/README.md | CLI の使い方を追加 |
| evo | CLI エントリポイントを追加 |
| .claude/skills/exec-plan/SKILL.md | 調査フェーズでの CLI 活用を追記 |
| .agent/plans/2026-02-07-evo-cli-self-bootstrap.md | 実行計画ドキュメントを追加 |
| if (!$args) { | ||
| $all = config(); | ||
| if (!is_array($all)) { | ||
| cli_usage('No config available.'); | ||
| } | ||
| ksort($all); |
There was a problem hiding this comment.
config() ヘルパーは必須引数 $key を要求する定義なので、引数なし呼び出しは ArgumentCountError で落ちる。全設定を取得したいなら evo()->config(null)(または evo()->config())を呼ぶか、ヘルパー config() 側のシグネチャを $key = null に変更して引数なしを許容する必要がある。
| $fileName = str_replace(':', '-', $commandName) . '.php'; | ||
| $filePath = EVO_CLI_COMMANDS_PATH . $fileName; | ||
|
|
There was a problem hiding this comment.
$commandName をそのままファイル名に変換しているため、"../" や "/" を含む入力で commands/ 配下以外へ書き込みできる。コマンド名を許可パターン(例: 英小文字/数字/コロンのみ等)で検証し、生成後のパスが EVO_CLI_COMMANDS_PATH 配下に収まることを realpath 等で確認してから書き込むようにするべき。
| $fileName = str_replace(':', '-', $commandName) . '.php'; | |
| $filePath = EVO_CLI_COMMANDS_PATH . $fileName; | |
| // コマンド名は英小文字・数字・コロンのみ許可する | |
| if (!preg_match('/^[a-z0-9:]+$/', $commandName)) { | |
| fwrite(STDERR, "Invalid command name: {$commandName}\n"); | |
| exit(1); | |
| } | |
| $fileName = str_replace(':', '-', $commandName) . '.php'; | |
| // ベースディレクトリを正規化し、EVO_CLI_COMMANDS_PATH 配下への書き込みに限定する | |
| $baseDir = rtrim(EVO_CLI_COMMANDS_PATH, DIRECTORY_SEPARATOR); | |
| $baseRealPath = realpath($baseDir); | |
| if ($baseRealPath === false) { | |
| fwrite(STDERR, "Invalid commands base path: " . EVO_CLI_COMMANDS_PATH . "\n"); | |
| exit(1); | |
| } | |
| $filePath = $baseRealPath . DIRECTORY_SEPARATOR . $fileName; | |
| $targetDirRealPath = realpath(dirname($filePath)); | |
| if ($targetDirRealPath === false || strpos($targetDirRealPath, $baseRealPath) !== 0) { | |
| fwrite(STDERR, "Refusing to write outside commands path: {$filePath}\n"); | |
| exit(1); | |
| } |
| $commandFile = EVO_CLI_COMMANDS_PATH . str_replace(':', '-', $command) . '.php'; | ||
| if (is_file($commandFile)) { | ||
| require $commandFile; | ||
| exit(0); | ||
| } | ||
|
|
||
| fwrite(STDERR, "Unknown command: {$command}\n"); | ||
| $helpFile = EVO_CLI_COMMANDS_PATH . 'help.php'; |
There was a problem hiding this comment.
コマンド名を検証せずにファイルパスへ連結しているため、"../" や "/" を含む入力で commands/ 配下以外の PHP を require できる。許可パターンで $command を検証し、解決後パスが EVO_CLI_COMMANDS_PATH 配下に収まる場合のみ読み込むように制限する必要がある。
| $commandFile = EVO_CLI_COMMANDS_PATH . str_replace(':', '-', $command) . '.php'; | |
| if (is_file($commandFile)) { | |
| require $commandFile; | |
| exit(0); | |
| } | |
| fwrite(STDERR, "Unknown command: {$command}\n"); | |
| $helpFile = EVO_CLI_COMMANDS_PATH . 'help.php'; | |
| $baseDir = rtrim(EVO_CLI_COMMANDS_PATH, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; | |
| if (preg_match('/^[a-zA-Z0-9:-]+$/', $command)) { | |
| $relativeCommandPath = str_replace(':', '-', $command) . '.php'; | |
| $commandFile = $baseDir . $relativeCommandPath; | |
| $realBaseDir = realpath($baseDir); | |
| $realCommandFile = $realBaseDir !== false ? realpath($commandFile) : false; | |
| if ( | |
| $realBaseDir !== false && | |
| $realCommandFile !== false && | |
| strpos($realCommandFile, $realBaseDir . DIRECTORY_SEPARATOR) === 0 && | |
| is_file($realCommandFile) | |
| ) { | |
| require $realCommandFile; | |
| exit(0); | |
| } | |
| } | |
| fwrite(STDERR, "Unknown command: {$command}\n"); | |
| $helpFile = $baseDir . 'help.php'; |
| $configContent = sprintf( | ||
| "[client]\nhost=%s\nuser=%s\npassword=%s\ndatabase=%s\n", | ||
| db()->config['host'], | ||
| db()->config['user'], | ||
| db()->config['pass'], | ||
| db()->config['dbase'] | ||
| ); | ||
|
|
||
| file_put_contents($tmpConfig, $configContent); |
There was a problem hiding this comment.
DB 設定値をそのままテンポラリ設定ファイルへ埋め込んでいるため、パスワード等に改行が含まれると設定ファイルの構造が壊れる。値の改行除去/エスケープを行い、file_put_contents の戻り値を確認して失敗時は終了するようにした方が安全。
| $configContent = sprintf( | |
| "[client]\nhost=%s\nuser=%s\npassword=%s\ndatabase=%s\n", | |
| db()->config['host'], | |
| db()->config['user'], | |
| db()->config['pass'], | |
| db()->config['dbase'] | |
| ); | |
| file_put_contents($tmpConfig, $configContent); | |
| $host = str_replace(["\r", "\n"], '', (string) db()->config['host']); | |
| $user = str_replace(["\r", "\n"], '', (string) db()->config['user']); | |
| $pass = str_replace(["\r", "\n"], '', (string) db()->config['pass']); | |
| $dbase = str_replace(["\r", "\n"], '', (string) db()->config['dbase']); | |
| $configContent = sprintf( | |
| "[client]\nhost=%s\nuser=%s\npassword=%s\ndatabase=%s\n", | |
| $host, | |
| $user, | |
| $pass, | |
| $dbase | |
| ); | |
| $bytesWritten = file_put_contents($tmpConfig, $configContent); | |
| if ($bytesWritten === false) { | |
| fwrite(STDERR, "Failed to write temp config file.\n"); | |
| exit(1); | |
| } |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90b6621b17
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <?php | ||
|
|
||
| if (!$args) { | ||
| $all = config(); |
There was a problem hiding this comment.
Avoid calling config() without required key
config:show calls config() with no arguments, but the global helper is declared as function config($key, $default = null) in manager/includes/helpers.php, so this triggers ArgumentCountError on PHP 8+ and the documented php evo config:show path cannot run. Use evo()->config() (which accepts a null key) or pass an explicit key to the helper.
Useful? React with 👍 / 👎.
| $fileName = str_replace(':', '-', $commandName) . '.php'; | ||
| $filePath = EVO_CLI_COMMANDS_PATH . $fileName; |
There was a problem hiding this comment.
Reject path separators in generated command names
make:command builds $filePath directly from user input after only replacing : with -, so names containing ../ or / can escape EVO_CLI_COMMANDS_PATH and overwrite arbitrary files (for example, php evo make:command ../../tmp/pwn). Restrict command names to a safe pattern (e.g. alnum, _, -, :) before writing.
Useful? React with 👍 / 👎.
… コンテキストの初期化チェックを追加
…に設定。CLI README を更新。
This pull request introduces a minimal CLI framework for Evolution CMS JP Edition, enabling command-line management and development tasks. It establishes a robust foundation for further CLI expansion, including database operations, configuration inspection, cache management, and command generation. The implementation includes a bootstrap process, command routing, helper utilities, and several initial commands, all documented for ease of use.
Core CLI Framework and Bootstrap:
evoentrypoint script, which defines CLI mode, loads the bootstrap, routes commands, and handles unknown commands gracefully (evo, evoR1-R30).manager/includes/cli/bootstrap.php, manager/includes/cli/bootstrap.phpR1-R77).manager/includes/cli/cli-helpers.php, manager/includes/cli/cli-helpers.phpR1-R44).Database Management Commands:
db-query.php, [1] exporting (db-export.php, [2] importing (db-import.php, [3] listing tables (db-tables.php, [4] describing table structure (db-describe.php, [5] and counting rows with conditions (db-count.php, [6].db-import.php, manager/includes/cli/commands/db-import.phpR1-R125).Configuration and Cache Commands:
config-show.php, [1] and clear cache (cache-clear.php, [2].Command Generation and Help:
make-command) and a help command that lists available commands (help.php, manager/includes/cli/commands/help.phpR1-R20).Documentation and Integration:
manager/includes/cli/README.md, manager/includes/cli/README.mdR1-R33)..agent/plans/2026-02-07-evo-cli-self-bootstrap.md, [1];.claude/skills/exec-plan/SKILL.md, [2].References:
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]