Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,13 @@ parameters:
level: 8
paths:
- src
ignoreErrors:
- message: "#Cannot cast array\\<string\\>\\|string\\|null to string\\.#"
path: src/Controller/Cli/WhyBlockCliCommand.php
count: 1
- message: "#Cannot cast array\\<string\\>\\|string\\|null to string\\.#"
path: src/Controller/Common/WhyBlockUtility/OptionValuesBuilder.php
count: 2
- message: "#Cannot cast array\\<string\\>\\|bool\\|string\\|null to string\\.#"
path: src/Controller/Common/WhyBlockUtility/OptionValuesBuilder.php
count: 1
69 changes: 69 additions & 0 deletions src/Controller/Cli/WhyBlockCliCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/**
* @copyright 2021 Navarr Barnier. All Rights Reserved.
*/

declare(strict_types=1);

namespace Navarr\Depends\Controller\Cli;

use InvalidArgumentException;
use Navarr\Attribute\Dependency;
use Navarr\Depends\Command\WhyBlockCommand;
use Navarr\Depends\Controller\Common\WhyBlockUtility;
use Navarr\Depends\Controller\Di\AddDefaultDefinitions;
use Navarr\Depends\ScopeDeterminer\DirectoryScopeDeterminer;
use Navarr\Depends\ScopeDeterminer\PhpFileFinder;
use Navarr\Depends\ScopeDeterminer\ScopeDeterminerInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class WhyBlockCliCommand extends Command
{
private const ARGUMENT_DIR = 'directory';

// phpcs:disable Generic.Files.LineLength.TooLong -- Attribute support pre PHP 8
#[Dependency('symfony/console', '^5', 'Command\'s setName, addArgument and addOption methods as well as InputArgument\'s constants of REQUIRED and VALUE_NONE')]
#[Dependency('php-di/php-di', '^6', 'DI\ContainerBuilder::addDefinitions and the existence of the DI\autowire function')]
// phpcs:enable Generic.Files.LineLength.TooLong
protected function configure(): void
{
WhyBlockUtility::addCommongArguments($this)
->addArgument('directory', InputArgument::REQUIRED, 'Directory to search in');
}

#[Dependency('symfony/console', '^5', 'InputInterface::getOption and OutputInterface::writeln')]
protected function execute(
InputInterface $input,
OutputInterface $output
): int {
$optionValuesBuilder = new WhyBlockUtility\OptionValuesBuilder();
$optionValues = $optionValuesBuilder->buildFromInput($input);
$directory = (string)$input->getArgument('directory');

$containerBuilder = AddDefaultDefinitions::execute();
WhyBlockUtility::addBaseDiDefinitions($containerBuilder, $input, $output, $optionValues);
$containerBuilder->addDefinitions(
[
ScopeDeterminerInterface::class => static function (ContainerInterface $container) use ($directory) {
return new DirectoryScopeDeterminer(
$container->get(PhpFileFinder::class),
$directory
);
},
]
);
$container = $containerBuilder->build();

/** @var WhyBlockCommand $command */
$command = $container->get(WhyBlockCommand::class);
return $command->execute(
$optionValues->getPackageToSearchFor(),
$optionValues->getVersionToCompareTo()
);
}
}
3 changes: 2 additions & 1 deletion src/Controller/CliApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Navarr\Depends\Controller;

use Navarr\Attribute\Dependency;
use Navarr\Depends\Controller\Cli\WhyBlockCliCommand;
use Symfony\Component\Console\Application;

#[Dependency('symfony/console', '^5', 'Creates a Symfony Application')]
Expand All @@ -19,7 +20,7 @@ class CliApplication
public static function execute(): int
{
$application = new Application('DepAnno', static::VERSION);
$application->add(new WhyBlockCommandController());
$application->add(new WhyBlockCliCommand());
return $application->run();
}
}
126 changes: 126 additions & 0 deletions src/Controller/Common/WhyBlockUtility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

/**
* @copyright 2021 Navarr Barnier. All Rights Reserved.
*/

declare(strict_types=1);

namespace Navarr\Depends\Controller\Common;

use DI\ContainerBuilder;
use Navarr\Attribute\Dependency;
use Navarr\Depends\Command\WhyBlockCommand\CsvOutputHandler;
use Navarr\Depends\Command\WhyBlockCommand\JsonOutputHandler;
use Navarr\Depends\Command\WhyBlockCommand\OutputHandlerInterface;
use Navarr\Depends\Command\WhyBlockCommand\StandardOutputHandler;
use Navarr\Depends\Command\WhyBlockCommand\XmlOutputHandler;
use Navarr\Depends\Controller\Common\WhyBlockUtility\OptionValues;
use Navarr\Depends\IssueHandler\FailOnIssueHandler;
use Navarr\Depends\IssueHandler\IssueHandlerInterface;
use Navarr\Depends\IssueHandler\NotifyOnIssueHandler;
use Navarr\Depends\Parser\AstParser;
use Navarr\Depends\Parser\LegacyParser;
use Navarr\Depends\Parser\ParserInterface;
use Navarr\Depends\Parser\ParserPool;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

use function DI\autowire;

class WhyBlockUtility
{
public const ARGUMENT_PACKAGE = 'package';
public const ARGUMENT_VERSION = 'version';

public const OPTION_OUTPUT_FORMAT = 'format';
public const OPTION_FAIL_ON_ERROR = 'fail-on-error';
public const OPTION_INCLUDE_ANNOTATIONS = 'include-legacy-annotations';

public const FORMAT_TEXT = 'text';
public const FORMAT_CSV = 'csv';
public const FORMAT_JSON = 'json';
public const FORMAT_XML = 'xml';

public const ACCEPTABLE_FORMATS = [
self::FORMAT_CSV,
self::FORMAT_TEXT,
self::FORMAT_JSON,
self::FORMAT_XML,
];

public const FORMAT_MAPPER = [
self::FORMAT_CSV => CsvOutputHandler::class,
self::FORMAT_TEXT => StandardOutputHandler::class,
self::FORMAT_JSON => JsonOutputHandler::class,
self::FORMAT_XML => XmlOutputHandler::class,
];

// phpcs:ignore Generic.Files.LineLength.TooLong -- Attribute support pre PHP 8
#[Dependency('symfony/console', '^5', 'Command\'s setName, addArgument and addOption methods as well as InputArgument\'s constants of REQUIRED and VALUE_NONE')]
public static function addCommongArguments(
Command $command
): Command {
return $command->setName('why-block')
->addArgument(
static::ARGUMENT_PACKAGE,
InputArgument::REQUIRED,
'Package to search dependency attributes for'
)
->addArgument(
static::ARGUMENT_VERSION,
InputArgument::REQUIRED,
'Version you want to update the package to'
)
->addOption(
static::OPTION_OUTPUT_FORMAT,
['f'],
InputOption::VALUE_OPTIONAL,
'Format to put results in. Accepted values: text, csv, json, xml',
'text'
)
->addOption(
static::OPTION_FAIL_ON_ERROR,
['e'],
InputOption::VALUE_NONE,
'Immediately fail on parsing errors'
)
->addOption(
static::OPTION_INCLUDE_ANNOTATIONS,
['l'],
InputOption::VALUE_NONE,
'Include old @dependency/@composerDependency annotations in search'
);
}

public static function addBaseDiDefinitions(
ContainerBuilder $containerBuilder,
InputInterface $input,
OutputInterface $output,
OptionValues $optionValues
): ContainerBuilder {
$formatMapper = WhyBlockUtility::FORMAT_MAPPER[$optionValues->getOutputFormat()];
$containerBuilder->addDefinitions(
[
InputInterface::class => $input,
OutputInterface::class => $output,
IssueHandlerInterface::class => $optionValues->shouldFailOnParseError()
? FailOnIssueHandler::class
: NotifyOnIssueHandler::class,
ParserInterface::class => static function (ContainerInterface $container) use ($optionValues) {
$parsers = [$container->get(AstParser::class)];
if ($optionValues->shouldIncludeAnnotationsInSearch()) {
$parsers[] = $container->get(LegacyParser::class);
}
return new ParserPool($parsers);
},
OutputHandlerInterface::class => autowire($formatMapper),
]
);
return $containerBuilder;
}
}
69 changes: 69 additions & 0 deletions src/Controller/Common/WhyBlockUtility/OptionValues.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/**
* @copyright 2021 Navarr Barnier. All Rights Reserved.
*/

declare(strict_types=1);

namespace Navarr\Depends\Controller\Common\WhyBlockUtility;

use JetBrains\PhpStorm\Immutable;

#[Immutable(Immutable::CONSTRUCTOR_WRITE_SCOPE)]
class OptionValues
{
/** @var bool */
private $failOnError;

/** @var string */
private $format;

/** @var bool */
private $includeLegacy;

/** @var string */
private $package;

/** @var string */
private $version;

public function __construct(
string $package,
string $version,
string $format,
bool $includeLegacy = true,
bool $failOnError = false
) {
$this->package = $package;
$this->version = $version;
$this->format = $format;
$this->includeLegacy = $includeLegacy;
$this->failOnError = $failOnError;
}

public function getPackageToSearchFor(): string
{
return $this->package;
}

public function getVersionToCompareTo(): string
{
return $this->version;
}

public function getOutputFormat(): string
{
return $this->format;
}

public function shouldIncludeAnnotationsInSearch(): bool
{
return $this->includeLegacy;
}

public function shouldFailOnParseError(): bool
{
return $this->failOnError;
}
}
37 changes: 37 additions & 0 deletions src/Controller/Common/WhyBlockUtility/OptionValuesBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/**
* @copyright 2021 Navarr Barnier. All Rights Reserved.
*/

declare(strict_types=1);

namespace Navarr\Depends\Controller\Common\WhyBlockUtility;

use Navarr\Depends\Controller\Common\WhyBlockUtility;
use Symfony\Component\Console\Input\InputInterface;

class OptionValuesBuilder
{
public function buildFromInput(InputInterface $input): OptionValues
{
$packageToSearchFor = (string)$input->getArgument(WhyBlockUtility::ARGUMENT_PACKAGE);
$versionToCompareTo = (string)$input->getArgument(WhyBlockUtility::ARGUMENT_VERSION);
$outputFormat = (string)$input->getOption(WhyBlockUtility::OPTION_OUTPUT_FORMAT);

if (!in_array($outputFormat, WhyBlockUtility::ACCEPTABLE_FORMATS)) {
$outputFormat = 'text';
}

$failOnError = (bool)$input->getOption(WhyBlockUtility::OPTION_FAIL_ON_ERROR);
$includeAnnotations = (bool)$input->getOption(WhyBlockUtility::OPTION_INCLUDE_ANNOTATIONS);

return new OptionValues(
$packageToSearchFor,
$versionToCompareTo,
$outputFormat,
$includeAnnotations,
$failOnError
);
}
}
Loading