Skip to content

Commit

Permalink
Config: display user-friendly message when invalid generator is passed (
Browse files Browse the repository at this point in the history
#771)

This commit improves how `Config::processLongArgument()` handles the
`--generator` parameter. Now it will show a user-friendly message if an
invalid generator name is passed. Before, an invalid generator name
caused a fatal error.

The commit also ensures that the value for the `generator` CLI parameter is handled case-insensitively.
  • Loading branch information
rodrigoprimo authored Feb 15, 2025
1 parent 6b11ef6 commit e53a925
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 14 deletions.
32 changes: 31 additions & 1 deletion src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,21 @@ class Config
*/
private $cliArgs = [];

/**
* A list of valid generators.
*
* {@internal Once support for PHP < 5.6 is dropped, this property should be refactored into a
* class constant.}
*
* @var array<string, string> Keys are the lowercase version of the generator name, while values
* are the associated PHP generator class.
*/
private $validGenerators = [
'text' => 'Text',
'html' => 'HTML',
'markdown' => 'Markdown',
];

/**
* Command line values that the user has supplied directly.
*
Expand Down Expand Up @@ -1215,7 +1230,22 @@ public function processLongArgument($arg, $pos)
break;
}

$this->generator = substr($arg, 10);
$generatorName = substr($arg, 10);
$lowerCaseGeneratorName = strtolower($generatorName);

if (isset($this->validGenerators[$lowerCaseGeneratorName]) === false) {
$validOptions = implode(', ', $this->validGenerators);
$validOptions = substr_replace($validOptions, ' and', strrpos($validOptions, ','), 1);
$error = sprintf(
'ERROR: "%s" is not a valid generator. The following generators are supported: %s.'.PHP_EOL.PHP_EOL,
$generatorName,
$validOptions
);
$error .= $this->printShortUsage(true);
throw new DeepExitException($error, 3);
}

$this->generator = $this->validGenerators[$lowerCaseGeneratorName];
self::$overriddenDefaults['generator'] = true;
} else if (substr($arg, 0, 9) === 'encoding=') {
if (isset(self::$overriddenDefaults['encoding']) === true) {
Expand Down
94 changes: 81 additions & 13 deletions tests/Core/Config/GeneratorArgTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,59 @@ final class GeneratorArgTest extends TestCase
/**
* Ensure that the generator property is set when the parameter is passed a valid value.
*
* @param string $generatorName Generator name.
* @param string $argumentValue Generator name passed on the command line.
* @param string $expectedPropertyValue Expected value of the generator property.
*
* @dataProvider dataGeneratorNames
* @dataProvider dataValidGeneratorNames
*
* @return void
*/
public function testGenerators($generatorName)
public function testValidGenerators($argumentValue, $expectedPropertyValue)
{
$config = new ConfigDouble(["--generator=$generatorName"]);
$config = new ConfigDouble(["--generator=$argumentValue"]);

$this->assertSame($generatorName, $config->generator);
$this->assertSame($expectedPropertyValue, $config->generator);

}//end testGenerators()
}//end testValidGenerators()


/**
* Data provider for testGenerators().
* Data provider for testValidGenerators().
*
* @see self::testGenerators()
* @see self::testValidGenerators()
*
* @return array<int, array<string>>
*/
public static function dataGeneratorNames()
public static function dataValidGeneratorNames()
{
return [
['Text'],
['HTML'],
['Markdown'],
'Text generator passed' => [
'argumentValue' => 'Text',
'expectedPropertyValue' => 'Text',
],
'HTML generator passed' => [
'argumentValue' => 'HTML',
'expectedPropertyValue' => 'HTML',
],
'Markdown generator passed' => [
'argumentValue' => 'Markdown',
'expectedPropertyValue' => 'Markdown',
],
'Uppercase Text generator passed' => [
'argumentValue' => 'TEXT',
'expectedPropertyValue' => 'Text',
],
'Mixed case Text generator passed' => [
'argumentValue' => 'tEXt',
'expectedPropertyValue' => 'Text',
],
'Lowercase HTML generator passed' => [
'argumentValue' => 'html',
'expectedPropertyValue' => 'HTML',
],
];

}//end dataGeneratorNames()
}//end dataValidGeneratorNames()


/**
Expand All @@ -76,4 +98,50 @@ public function testOnlySetOnce()
}//end testOnlySetOnce()


/**
* Ensure that an exception is thrown for an invalid generator.
*
* @param string $generatorName Generator name.
*
* @dataProvider dataInvalidGeneratorNames
*
* @return void
*/
public function testInvalidGenerator($generatorName)
{
$exception = 'PHP_CodeSniffer\Exceptions\DeepExitException';
$message = 'ERROR: "'.$generatorName.'" is not a valid generator. The following generators are supported: Text, HTML and Markdown.';

if (method_exists($this, 'expectException') === true) {
// PHPUnit 5+.
$this->expectException($exception);
$this->expectExceptionMessage($message);
} else {
// PHPUnit 4.
$this->setExpectedException($exception, $message);
}

new ConfigDouble(["--generator={$generatorName}"]);

}//end testInvalidGenerator()


/**
* Data provider for testInvalidGenerator().
*
* @see self::testInvalidGenerator()
*
* @return array<int, array<string>>
*/
public static function dataInvalidGeneratorNames()
{
return [
['InvalidGenerator'],
['Text,HTML'],
[''],
];

}//end dataInvalidGeneratorNames()


}//end class

0 comments on commit e53a925

Please sign in to comment.