class

Analyzer::Php::Cli

Inherits CliEndpointSupport < Analyzer < FileHelper < Reference < Object

Surfaces the command-line attack surface of PHP programs as cli:// endpoints: one endpoint per (sub)command with named options (param_type "flag"), positional arguments ("argument") and consumed environment variables ("env"). Covers Symfony Console, Laravel Artisan ($signature), Robo (@command docblocks) and WP-CLI, plus builtin getopt / $argv / $_ENV / getenv.

Line-scan analyzer (Go/Ruby/Rust CLI house style) merging endpoints by URL. Subclasses Analyzer directly (PhpEngine is abstract) and reuses PhpEngine.test_path? to skip tests.

Constants

ADD_ARGUMENT = /->\s*addArgument\s*\(\s*['"]([^'"]+)['"]/
ADD_OPTION = /->\s*addOption\s*\(\s*['"]([^'"]+)['"]/
ARGV_INDEX = /\$argv\s*\[\s*(\d+)\s*\]/
ARTISAN_SIGNATURE = /protected\s+(?:static\s+)?\$signature\s*=\s*(['"])((?:\\.|(?!\1).)*)\1/

Laravel Artisan: protected $signature = '...'. The value is the Symfony-Console-flavored mini-grammar Artisan parses itself: name {arg} {arg? : desc} {arg=default} {--flag} {--flag=default : desc}.

ARTISAN_TOKEN = /\{\s*([^{}]*?)\s*\}/
AS_COMMAND = /#\[\s*AsCommand\s*\(\s*name\s*:\s*['"]([^'"]+)['"]/
CLI_HINT_RE = Regex.union("Symfony\\Component\\Console", /extends\s+Command/, "AsCommand", "getopt", "$argv", "League\\CLImate", "Minicli\\", "$signature", "Robo\\Tasks", "WP_CLI")

Cheap file-level reject before the precise multi-regex evidence check. Every accepted CLI shape contains at least one of these literals.

DEFAULT_NAME = /protected\s+(?:static\s+)?\$defaultName\s*=\s*['"]([^'"]+)['"]/
ENV_BRACKET = /\$_ENV\s*\[\s*['"]([^'"]+)['"]\s*\]/
GET_ARGUMENT = /\$input->getArgument\s*\(\s*['"]([^'"]+)['"]/
GET_OPTION = /\$input->getOption\s*\(\s*['"]([^'"]+)['"]/
GETENV = /\bgetenv\s*\(\s*['"]([^'"]+)['"]/
GETOPT = /\bgetopt\s*\(\s*(['"])([^'"]*)\1\s*(?:,\s*\[([^\]]*)\])?/
ROBO_COMMAND_TAG = /@command\s+(\S+)/
ROBO_FUNCTION_LINE = /\bfunction\s+\w+\s*\(([^)]*)\)/
ROBO_MARKER = /Robo\\Tasks\b/

Robo (consolidation/Robo task runner): a @command <name> docblock tag binds to the very next method signature only — never sticky.

SET_NAME = /\$this->setName\s*\(\s*['"]([^'"]+)['"]/
WEB_FRAMEWORK_RE = /\buse\s+(?:Illuminate\\(?:Foundation|Http|Routing)|Symfony\\Bundle\\FrameworkBundle|Symfony\\Component\\HttpFoundation|Symfony\\Component\\HttpKernel|Slim\\(?:App|Factory)|Laminas\\(?:Mvc|Mezzio)|Mezzio\\|Cake\\(?:Routing|Http)|Hyperf\\HttpServer)\b|extends\s+AbstractController\b/
WP_ADD_COMMAND = /WP_CLI::add_command\s*\(\s*(['"])((?:\\.|(?!\1).)*)\1\s*,\s*(?:new\s+)?['"]?(\w+)/
WP_ARGS_INDEX = /\$args\s*\[\s*(\d+)\s*\]/
WP_ASSOC_ARG_BRACKET = /\$assoc_args\s*\[\s*['"]([^'"]+)['"]\s*\]/
WP_CLASS_LINE = /\bclass\s+(\w+)/
WP_FLAG_VALUE = /get_flag_value\s*\(\s*\$assoc_args\s*,\s*['"]([^'"]+)['"]/
WP_MARKER = /WP_CLI(?:_Command)?\b/

WP-CLI: WP_CLI::add_command('foo bar', 'Foo_Bar_Command') registers a class as a command. Only the method whose OWN signature is the conventional ($args, $assoc_args) callback is scanned for params — never the whole class body.

WP_METHOD_LINE = /\bfunction\s+\w+\s*\((?=[^)]*\$args\b)(?=[^)]*\$assoc_args\b)[^)]*\)/

Class methods

tech_name
Source

Instance methods

analyze
Source
tech

Instance-side view of the same declaration. The per-file rescues live on this base class, which has no way to name the analyzer that is running inside them, so a skipped file could not be attributed to a tech. Deriving it from analyzer_for keeps the name written exactly once.

Source