Files
cacti/lib/Console/Input/RawArgvInput.php
Thomas Vincent 1ae479d4f5 feat(cli): add unified command frontend and normalize legacy failures (#7903)
* feat(cli): add unified command frontend and normalize legacy failures

Add the Symfony-backed bin/cacti entry point while preserving legacy argument, terminal, signal, and exit-status behavior. Fold in the focused legacy CLI correctness fixes from #7906 without adding its unused parser abstraction.

Keep path containment and the PHP 8.3 floor out of this review; the latter remains in #7939.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(cli): enforce PHP floor and deny web dispatch

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-09-07 18:36:55 -07:00

62 lines
2.4 KiB
PHP

<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
*/
declare(strict_types = 1);
namespace Cacti\Console\Input;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
final class RawArgvInput extends ArgvInput {
/** @var list<string> */
private readonly array $rawTokens;
/** @param list<string>|null $argv */
public function __construct(?array $argv = null, ?InputDefinition $definition = null) {
$argv ??= $_SERVER['argv'] ?? [];
$this->rawTokens = array_values(array_slice($argv, 1));
parent::__construct($argv, $definition);
}
/**
* @param list<string|null> $names
* @return list<string>
*/
public function argumentsAfterCommand(array $names): array {
/* Symfony resolves abbreviated command names, so the typed token is
* often neither the registered name nor an alias. Without the token it
* actually consumed, an abbreviation matches nothing and the legacy
* script is spawned with an empty argv, silently taking its
* no-argument path. */
$names[] = $this->getFirstArgument();
foreach ($this->rawTokens as $offset => $token) {
if (in_array($token, $names, true)) {
/* Drop the command token, keep everything else. getFirstArgument()
* skips leading options, so 'bin/cacti --help poller:rebuild-cache'
* dispatches with the flag ahead of the name; slicing only forward
* handed the script an empty argv and it rebuilt every cache. */
return array_merge(
array_slice($this->rawTokens, 0, $offset),
array_slice($this->rawTokens, $offset + 1)
);
}
}
throw new \LogicException('The resolved command token is missing from the raw argument vector.');
}
}