Add PHPCS & PHPStan
This commit is contained in:
parent
3982e7aa95
commit
7f2305ec04
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
|
/tmp/
|
||||||
/vendor/
|
/vendor/
|
||||||
*.phar
|
*.phar
|
||||||
|
cs-check.json
|
@ -1,18 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Fbrinker\ExtensionCheck\Command\CheckCommand;
|
use Fbrinker\ExtensionCheck\Command\CheckCommand;
|
||||||
use Fbrinker\ExtensionCheck\Command\CheckCommandFactory;
|
use Fbrinker\ExtensionCheck\Command\CheckCommandFactory;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionCheckFactory;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionCheckFactory;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
||||||
|
use Fbrinker\ExtensionCheck\Output\SymfonyStyleFactory;
|
||||||
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
||||||
use Fbrinker\ExtensionCheck\Parser\FileParserFactory;
|
use Fbrinker\ExtensionCheck\Parser\FileParserFactory;
|
||||||
use Laminas\ServiceManager\Factory\InvokableFactory;
|
use Laminas\ServiceManager\Factory\InvokableFactory;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
CheckCommand::class =>CheckCommandFactory::class,
|
CheckCommand::class => CheckCommandFactory::class,
|
||||||
ExtensionCheck::class => ExtensionCheckFactory::class,
|
ExtensionCheck::class => ExtensionCheckFactory::class,
|
||||||
ExtensionDetails::class => InvokableFactory::class,
|
ExtensionDetails::class => InvokableFactory::class,
|
||||||
FileParser::class => FileParserFactory::class,
|
FileParser::class => FileParserFactory::class,
|
||||||
|
SymfonyStyleFactory::class => InvokableFactory::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
24
phpcs.xml
Normal file
24
phpcs.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Skeleton coding standard">
|
||||||
|
<description>Skeleton coding standard</description>
|
||||||
|
|
||||||
|
<arg value="p"/>
|
||||||
|
<arg name="colors"/>
|
||||||
|
<arg name="cache" value="cs-check.json"/>
|
||||||
|
<arg name="parallel" value="8" />
|
||||||
|
<arg name="ignore" value="tests/assets"/>
|
||||||
|
|
||||||
|
<rule ref="PSR12">
|
||||||
|
<exclude name="Generic.Files.LineLength"/>
|
||||||
|
</rule>
|
||||||
|
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||||
|
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
|
||||||
|
<properties>
|
||||||
|
<property name="ignoreBlankLines" value="false"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
|
<file>config</file>
|
||||||
|
</ruleset>
|
9
phpstan.neon
Normal file
9
phpstan.neon
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
parameters:
|
||||||
|
level: max
|
||||||
|
inferPrivatePropertyTypeFromConstructor: true
|
||||||
|
paths:
|
||||||
|
- src/
|
||||||
|
- tests/
|
||||||
|
excludes_analyse:
|
||||||
|
- %currentWorkingDirectory%/src/TEST
|
||||||
|
tmpDir: tmp/phpstan
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Command;
|
namespace Fbrinker\ExtensionCheck\Command;
|
||||||
@ -6,24 +7,27 @@ namespace Fbrinker\ExtensionCheck\Command;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
||||||
|
use Fbrinker\ExtensionCheck\Output\SymfonyStyleFactory;
|
||||||
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputDefinition;
|
use Symfony\Component\Console\Input\InputDefinition;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
class CheckCommand extends Command
|
class CheckCommand extends Command
|
||||||
{
|
{
|
||||||
|
private const ARG_DIRECTORY = 'directory';
|
||||||
|
|
||||||
protected static $defaultName = 'check';
|
protected static $defaultName = 'check';
|
||||||
|
private $symfonyStyleFactory;
|
||||||
private $fileParser;
|
private $fileParser;
|
||||||
private $extensionDetails;
|
private $extensionDetails;
|
||||||
private $extensionCheck;
|
private $extensionCheck;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
$symfonyStyleFactory,
|
SymfonyStyleFactory $symfonyStyleFactory,
|
||||||
FileParser $fileParser,
|
FileParser $fileParser,
|
||||||
ExtensionDetails $extensionDetails,
|
ExtensionDetails $extensionDetails,
|
||||||
ExtensionCheck $extensionCheck
|
ExtensionCheck $extensionCheck
|
||||||
@ -42,7 +46,7 @@ class CheckCommand extends Command
|
|||||||
->setHelp('This command allows you to check your extensions...')
|
->setHelp('This command allows you to check your extensions...')
|
||||||
->setDefinition(
|
->setDefinition(
|
||||||
new InputDefinition([
|
new InputDefinition([
|
||||||
new InputArgument('directory', InputArgument::OPTIONAL, "The directory to scan", "./"),
|
new InputArgument(self::ARG_DIRECTORY, InputArgument::OPTIONAL, "The directory to scan", "./"),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -52,7 +56,13 @@ class CheckCommand extends Command
|
|||||||
$io = ($this->symfonyStyleFactory)($input, $output);
|
$io = ($this->symfonyStyleFactory)($input, $output);
|
||||||
|
|
||||||
$io->section("Analyzing Files");
|
$io->section("Analyzing Files");
|
||||||
$this->fileParser->scanForFiles($input->getArgument('directory'));
|
|
||||||
|
$scanDir = $input->getArgument(self::ARG_DIRECTORY);
|
||||||
|
if (empty($scanDir) || !\is_string($scanDir)) {
|
||||||
|
$scanDir = './';
|
||||||
|
}
|
||||||
|
$this->fileParser->scanForFiles($scanDir);
|
||||||
|
|
||||||
$fileCount = $this->fileParser->getFileCount();
|
$fileCount = $this->fileParser->getFileCount();
|
||||||
$io->text(sprintf('Files: %d', $fileCount));
|
$io->text(sprintf('Files: %d', $fileCount));
|
||||||
$io->newLine();
|
$io->newLine();
|
||||||
@ -66,7 +76,7 @@ class CheckCommand extends Command
|
|||||||
|
|
||||||
$progressBar->finish();
|
$progressBar->finish();
|
||||||
$io->newLine(2);
|
$io->newLine(2);
|
||||||
$io->text(sprintf("Calls to check:", count($classes)));
|
$io->text("Calls to check:");
|
||||||
$io->text(sprintf(
|
$io->text(sprintf(
|
||||||
"%d Classes, %d Functions, %d Constants",
|
"%d Classes, %d Functions, %d Constants",
|
||||||
count($classes),
|
count($classes),
|
||||||
@ -95,16 +105,17 @@ class CheckCommand extends Command
|
|||||||
$io->text(sprintf(
|
$io->text(sprintf(
|
||||||
"<fg=green>%d</> Used, <fg=red>%d</> Unused",
|
"<fg=green>%d</> Used, <fg=red>%d</> Unused",
|
||||||
count($usedExtensions),
|
count($usedExtensions),
|
||||||
count($unusedExtensions),
|
count($unusedExtensions)
|
||||||
));
|
));
|
||||||
|
|
||||||
$io->section("Result");
|
$io->section("Result");
|
||||||
$io->text("Used Extensions:");
|
$io->text("Used Extensions:");
|
||||||
$tmp = array_keys($usedExtensions);
|
$tmp = array_keys($usedExtensions);
|
||||||
natcasesort($tmp);
|
natcasesort($tmp);
|
||||||
foreach($tmp as $usedExtension) {
|
foreach ($tmp as $usedExtension) {
|
||||||
$reason = $usedExtensions[$usedExtension];
|
$reason = $usedExtensions[$usedExtension];
|
||||||
$io->text(sprintf(' <fg=green>%s</> %s <comment>[Usage: %s]</>',
|
$io->text(sprintf(
|
||||||
|
' <fg=green>%s</> %s <comment>[Usage: %s]</>',
|
||||||
"\u{2713}",
|
"\u{2713}",
|
||||||
$usedExtension,
|
$usedExtension,
|
||||||
implode(", ", array_keys($reason))
|
implode(", ", array_keys($reason))
|
||||||
@ -114,8 +125,9 @@ class CheckCommand extends Command
|
|||||||
$io->newLine();
|
$io->newLine();
|
||||||
|
|
||||||
$io->text("Unused Extensions:");
|
$io->text("Unused Extensions:");
|
||||||
foreach($unusedExtensions as $unusedExtension) {
|
foreach ($unusedExtensions as $unusedExtension) {
|
||||||
$io->text(sprintf(' <fg=red>%s</> %s',
|
$io->text(sprintf(
|
||||||
|
' <fg=red>%s</> %s',
|
||||||
"\u{2717}",
|
"\u{2717}",
|
||||||
$unusedExtension
|
$unusedExtension
|
||||||
));
|
));
|
||||||
@ -124,13 +136,15 @@ class CheckCommand extends Command
|
|||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getProgressBarClosure(&$progressBar): Closure {
|
private function getProgressBarClosure(ProgressBar $progressBar): Closure
|
||||||
return function() use ($progressBar) {
|
{
|
||||||
|
return function () use ($progressBar) {
|
||||||
$progressBar->advance();
|
$progressBar->advance();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getStyledProgressBar(OutputInterface $output, int $maxValue): ProgressBar {
|
private function getStyledProgressBar(OutputInterface $output, int $maxValue): ProgressBar
|
||||||
|
{
|
||||||
$progressBar = new ProgressBar($output, $maxValue);
|
$progressBar = new ProgressBar($output, $maxValue);
|
||||||
$progressBar->setBarCharacter('<info>=</info>');
|
$progressBar->setBarCharacter('<info>=</info>');
|
||||||
$progressBar->setEmptyBarCharacter(' ');
|
$progressBar->setEmptyBarCharacter(' ');
|
||||||
|
@ -1,23 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Command;
|
namespace Fbrinker\ExtensionCheck\Command;
|
||||||
|
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionCheck;
|
||||||
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
use Fbrinker\ExtensionCheck\Extension\ExtensionDetails;
|
||||||
|
use Fbrinker\ExtensionCheck\Output\SymfonyStyleFactory;
|
||||||
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
use Fbrinker\ExtensionCheck\Parser\FileParser;
|
||||||
use Interop\Container\ContainerInterface;
|
use Interop\Container\ContainerInterface;
|
||||||
use Laminas\ServiceManager\Factory\FactoryInterface;
|
use Laminas\ServiceManager\Factory\FactoryInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
||||||
|
|
||||||
class CheckCommandFactory implements FactoryInterface
|
class CheckCommandFactory implements FactoryInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param array<mixed> $options
|
||||||
|
*/
|
||||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||||
{
|
{
|
||||||
return new CheckCommand(
|
return new CheckCommand(
|
||||||
new class { public function __invoke($input, $output) { return new SymfonyStyle($input, $output); } },
|
$container->get(SymfonyStyleFactory::class),
|
||||||
$container->get(FileParser::class),
|
$container->get(FileParser::class),
|
||||||
$container->get(ExtensionDetails::class),
|
$container->get(ExtensionDetails::class),
|
||||||
$container->get(ExtensionCheck::class),
|
$container->get(ExtensionCheck::class)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Extension;
|
namespace Fbrinker\ExtensionCheck\Extension;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
|
||||||
class ExtensionCheck {
|
class ExtensionCheck
|
||||||
|
{
|
||||||
|
|
||||||
private $extensionDetails;
|
private $extensionDetails;
|
||||||
|
|
||||||
@ -13,17 +16,29 @@ class ExtensionCheck {
|
|||||||
$this->extensionDetails = $extensionDetails;
|
$this->extensionDetails = $extensionDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUnused(array $usedExtensions) {
|
/**
|
||||||
|
* @param string[] $usedExtensions
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getUnused(array $usedExtensions): array
|
||||||
|
{
|
||||||
return array_diff(
|
return array_diff(
|
||||||
$this->extensionDetails->getLoadedExtensions(),
|
$this->extensionDetails->getLoadedExtensions(),
|
||||||
$usedExtensions
|
$usedExtensions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkUsages(array $classes, array $functions, array $constants, Closure $callback) {
|
/**
|
||||||
|
* @param string[] $classes
|
||||||
|
* @param string[] $functions
|
||||||
|
* @param string[] $constants
|
||||||
|
* @return array<string,array<string,bool>>
|
||||||
|
*/
|
||||||
|
public function checkUsages(array $classes, array $functions, array $constants, Closure $callback)
|
||||||
|
{
|
||||||
$usedExtensions = [];
|
$usedExtensions = [];
|
||||||
|
|
||||||
foreach($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$extension = $this->checkClass($class);
|
$extension = $this->checkClass($class);
|
||||||
|
|
||||||
if (!empty($extension)) {
|
if (!empty($extension)) {
|
||||||
@ -33,7 +48,7 @@ class ExtensionCheck {
|
|||||||
$callback();
|
$callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($functions as $function) {
|
foreach ($functions as $function) {
|
||||||
$extension = $this->checkFunction($function);
|
$extension = $this->checkFunction($function);
|
||||||
|
|
||||||
if (!empty($extension)) {
|
if (!empty($extension)) {
|
||||||
@ -43,7 +58,7 @@ class ExtensionCheck {
|
|||||||
$callback();
|
$callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($constants as $constant) {
|
foreach ($constants as $constant) {
|
||||||
$extension = $this->checkConstant($constant);
|
$extension = $this->checkConstant($constant);
|
||||||
|
|
||||||
if (!empty($extension)) {
|
if (!empty($extension)) {
|
||||||
@ -54,11 +69,11 @@ class ExtensionCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tmp = array_keys($usedExtensions);
|
$tmp = array_keys($usedExtensions);
|
||||||
foreach($tmp as $usedExtension) {
|
foreach ($tmp as $usedExtension) {
|
||||||
$requiredExtensions = $this->checkRequiredDependency($usedExtension);
|
$requiredExtensions = $this->checkRequiredDependency($usedExtension);
|
||||||
|
|
||||||
if (!empty($requiredExtensions)) {
|
if (!empty($requiredExtensions)) {
|
||||||
foreach($requiredExtensions as $requiredExtension) {
|
foreach ($requiredExtensions as $requiredExtension) {
|
||||||
$usedExtensions[$requiredExtension]['dependency'] = true;
|
$usedExtensions[$requiredExtension]['dependency'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +84,8 @@ class ExtensionCheck {
|
|||||||
return $usedExtensions;
|
return $usedExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkClass($class): ?string {
|
private function checkClass(string $class): ?string
|
||||||
|
{
|
||||||
$classMap = $this->extensionDetails->getExtensionClassMap();
|
$classMap = $this->extensionDetails->getExtensionClassMap();
|
||||||
|
|
||||||
if (!isset($classMap[$class])) {
|
if (!isset($classMap[$class])) {
|
||||||
@ -79,7 +95,8 @@ class ExtensionCheck {
|
|||||||
return $classMap[$class];
|
return $classMap[$class];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkFunction($function): ?string {
|
private function checkFunction(string $function): ?string
|
||||||
|
{
|
||||||
$functionMap = $this->extensionDetails->getExtensionFunctionMap();
|
$functionMap = $this->extensionDetails->getExtensionFunctionMap();
|
||||||
|
|
||||||
if (!isset($functionMap[$function])) {
|
if (!isset($functionMap[$function])) {
|
||||||
@ -89,7 +106,8 @@ class ExtensionCheck {
|
|||||||
return $functionMap[$function];
|
return $functionMap[$function];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkConstant($function): ?string {
|
private function checkConstant(string $function): ?string
|
||||||
|
{
|
||||||
$constantMap = $this->extensionDetails->getExtensionConstantMap();
|
$constantMap = $this->extensionDetails->getExtensionConstantMap();
|
||||||
|
|
||||||
if (!isset($constantMap[$function])) {
|
if (!isset($constantMap[$function])) {
|
||||||
@ -99,7 +117,11 @@ class ExtensionCheck {
|
|||||||
return $constantMap[$function];
|
return $constantMap[$function];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkRequiredDependency($extension): array {
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function checkRequiredDependency(string $extension): array
|
||||||
|
{
|
||||||
$dependencyMap = $this->extensionDetails->getExtensionDependencyMap();
|
$dependencyMap = $this->extensionDetails->getExtensionDependencyMap();
|
||||||
|
|
||||||
if (!isset($dependencyMap[$extension]['required'])) {
|
if (!isset($dependencyMap[$extension]['required'])) {
|
||||||
@ -108,5 +130,4 @@ class ExtensionCheck {
|
|||||||
|
|
||||||
return $dependencyMap[$extension]['required'];
|
return $dependencyMap[$extension]['required'];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Extension;
|
namespace Fbrinker\ExtensionCheck\Extension;
|
||||||
|
|
||||||
use Interop\Container\ContainerInterface;
|
use Interop\Container\ContainerInterface;
|
||||||
@ -7,6 +9,9 @@ use Laminas\ServiceManager\Factory\FactoryInterface;
|
|||||||
|
|
||||||
class ExtensionCheckFactory implements FactoryInterface
|
class ExtensionCheckFactory implements FactoryInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param array<mixed> $options
|
||||||
|
*/
|
||||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||||
{
|
{
|
||||||
return new ExtensionCheck(
|
return new ExtensionCheck(
|
||||||
|
@ -1,60 +1,90 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Extension;
|
namespace Fbrinker\ExtensionCheck\Extension;
|
||||||
|
|
||||||
use ReflectionExtension;
|
use ReflectionExtension;
|
||||||
|
|
||||||
class ExtensionDetails {
|
class ExtensionDetails
|
||||||
|
{
|
||||||
private $loadedExtensions;
|
private $loadedExtensions;
|
||||||
private $extensionMap = [];
|
|
||||||
|
/** @var ExtensionMap|null */
|
||||||
|
private $extensionMap;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->loadedExtensions = array_map('strtolower', get_loaded_extensions());
|
$this->loadedExtensions = array_map('strtolower', get_loaded_extensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoadedExtensions(): array {
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getLoadedExtensions(): array
|
||||||
|
{
|
||||||
natcasesort($this->loadedExtensions);
|
natcasesort($this->loadedExtensions);
|
||||||
return $this->loadedExtensions;
|
return $this->loadedExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoadedExtensionsCount(): int {
|
public function getLoadedExtensionsCount(): int
|
||||||
|
{
|
||||||
return count($this->loadedExtensions);
|
return count($this->loadedExtensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtensionClassMap(): array {
|
/**
|
||||||
|
* @return array<string,string>
|
||||||
|
*/
|
||||||
|
public function getExtensionClassMap(): array
|
||||||
|
{
|
||||||
if (empty($this->extensionMap)) {
|
if (empty($this->extensionMap)) {
|
||||||
$this->buildExtensionMaps();
|
$this->buildExtensionMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->extensionMap['classes'] ?? [];
|
return $this->extensionMap->classes ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtensionFunctionMap(): array {
|
/**
|
||||||
|
* @return array<string,string>
|
||||||
|
*/
|
||||||
|
public function getExtensionFunctionMap(): array
|
||||||
|
{
|
||||||
if (empty($this->extensionMap)) {
|
if (empty($this->extensionMap)) {
|
||||||
$this->buildExtensionMaps();
|
$this->buildExtensionMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->extensionMap['functions'] ?? [];
|
return $this->extensionMap->functions ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtensionConstantMap(): array {
|
/**
|
||||||
|
* @return array<string,string>
|
||||||
|
*/
|
||||||
|
public function getExtensionConstantMap(): array
|
||||||
|
{
|
||||||
if (empty($this->extensionMap)) {
|
if (empty($this->extensionMap)) {
|
||||||
$this->buildExtensionMaps();
|
$this->buildExtensionMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->extensionMap['constants'] ?? [];
|
return $this->extensionMap->constants ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtensionDependencyMap(): array {
|
/**
|
||||||
|
* @return array<string,array<string,string[]>>
|
||||||
|
*/
|
||||||
|
public function getExtensionDependencyMap(): array
|
||||||
|
{
|
||||||
if (empty($this->extensionMap)) {
|
if (empty($this->extensionMap)) {
|
||||||
$this->buildExtensionMaps();
|
$this->buildExtensionMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->extensionMap['dependencies'] ?? [];
|
return $this->extensionMap->dependencies ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildExtensionMaps(array $extensionsToExclude = []) {
|
/**
|
||||||
|
* @param string[] $extensionsToExclude
|
||||||
|
*/
|
||||||
|
private function buildExtensionMaps(array $extensionsToExclude = []): void
|
||||||
|
{
|
||||||
$extensionClasses = $extensionFunctions = $extensionConstants = $extensionDependencies = $uncheckedExtensions = [];
|
$extensionClasses = $extensionFunctions = $extensionConstants = $extensionDependencies = $uncheckedExtensions = [];
|
||||||
foreach ($this->loadedExtensions as $loadedExtension) {
|
foreach ($this->loadedExtensions as $loadedExtension) {
|
||||||
if (in_array(strtolower($loadedExtension), array_map('strtolower', $extensionsToExclude))) {
|
if (in_array(strtolower($loadedExtension), array_map('strtolower', $extensionsToExclude))) {
|
||||||
@ -106,13 +136,12 @@ class ExtensionDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extensionMap = [
|
$this->extensionMap = new ExtensionMap(
|
||||||
'classes' => $extensionClasses,
|
$extensionClasses,
|
||||||
'functions' => $extensionFunctions,
|
$extensionFunctions,
|
||||||
'constants' => $extensionConstants,
|
$extensionConstants,
|
||||||
'dependencies' => $extensionDependencies,
|
$extensionDependencies,
|
||||||
'unchecked' => $uncheckedExtensions
|
$uncheckedExtensions
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
42
src/Extension/ExtensionMap.php
Normal file
42
src/Extension/ExtensionMap.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Fbrinker\ExtensionCheck\Extension;
|
||||||
|
|
||||||
|
class ExtensionMap
|
||||||
|
{
|
||||||
|
/** @var array<string,string> */
|
||||||
|
public $classes;
|
||||||
|
|
||||||
|
/** @var array<string,string> */
|
||||||
|
public $functions;
|
||||||
|
|
||||||
|
/** @var array<string,string> */
|
||||||
|
public $constants;
|
||||||
|
|
||||||
|
/** @var array<string,array<string,string[]>> */
|
||||||
|
public $dependencies;
|
||||||
|
|
||||||
|
/** @var string[] */
|
||||||
|
public $unchecked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string,string> $classes
|
||||||
|
* @param array<string,string> $functions
|
||||||
|
* @param array<string,string> $constants
|
||||||
|
* @param array<string,array<string,string[]>> $dependencies
|
||||||
|
* @param string[] $unchecked
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
array $classes = [],
|
||||||
|
array $functions = [],
|
||||||
|
array $constants = [],
|
||||||
|
array $dependencies = [],
|
||||||
|
array $unchecked = []
|
||||||
|
) {
|
||||||
|
$this->classes = $classes;
|
||||||
|
$this->functions = $functions;
|
||||||
|
$this->constants = $constants;
|
||||||
|
$this->dependencies = $dependencies;
|
||||||
|
$this->unchecked = $unchecked;
|
||||||
|
}
|
||||||
|
}
|
15
src/Output/SymfonyStyleFactory.php
Normal file
15
src/Output/SymfonyStyleFactory.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Fbrinker\ExtensionCheck\Output;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class SymfonyStyleFactory
|
||||||
|
{
|
||||||
|
public function __invoke(InputInterface $input, OutputInterface $output): SymfonyStyle
|
||||||
|
{
|
||||||
|
return new SymfonyStyle($input, $output);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser;
|
namespace Fbrinker\ExtensionCheck\Parser;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Error;
|
||||||
use Fbrinker\ExtensionCheck\Parser\Visitors\ClassCollector;
|
use Fbrinker\ExtensionCheck\Parser\Visitors\ClassCollector;
|
||||||
use Fbrinker\ExtensionCheck\Parser\Visitors\ConstantCollector;
|
use Fbrinker\ExtensionCheck\Parser\Visitors\ConstantCollector;
|
||||||
use Fbrinker\ExtensionCheck\Parser\Visitors\FunctionCollector;
|
use Fbrinker\ExtensionCheck\Parser\Visitors\FunctionCollector;
|
||||||
use PhpParser\NodeTraverser;
|
use PhpParser\NodeTraverser;
|
||||||
use PhpParser\ParserFactory;
|
use PhpParser\ParserFactory;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class FileParser {
|
class FileParser
|
||||||
|
{
|
||||||
private $finder;
|
private $finder;
|
||||||
|
|
||||||
public function __construct(Finder $finder)
|
public function __construct(Finder $finder)
|
||||||
@ -18,7 +23,8 @@ class FileParser {
|
|||||||
$this->finder = $finder;
|
$this->finder = $finder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scanForFiles(string $directory): void {
|
public function scanForFiles(string $directory): void
|
||||||
|
{
|
||||||
$this->finder->files()->name('*.php')->in($directory);
|
$this->finder->files()->name('*.php')->in($directory);
|
||||||
$this->finder->sortByName();
|
$this->finder->sortByName();
|
||||||
}
|
}
|
||||||
@ -28,8 +34,12 @@ class FileParser {
|
|||||||
return $this->finder->count();
|
return $this->finder->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parseFiles(Closure $callback) {
|
/**
|
||||||
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
* @return array<int,string[]>
|
||||||
|
*/
|
||||||
|
public function parseFiles(Closure $callback): array
|
||||||
|
{
|
||||||
|
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
|
||||||
|
|
||||||
$traverser = new NodeTraverser();
|
$traverser = new NodeTraverser();
|
||||||
|
|
||||||
@ -42,9 +52,19 @@ class FileParser {
|
|||||||
$constantCollector = new ConstantCollector();
|
$constantCollector = new ConstantCollector();
|
||||||
$traverser->addVisitor($constantCollector);
|
$traverser->addVisitor($constantCollector);
|
||||||
|
|
||||||
foreach($this->finder as $file) {
|
foreach ($this->finder as $file) {
|
||||||
$content = $file->getContents();
|
$content = $file->getContents();
|
||||||
$stmts = $parser->parse($content);
|
$stmts = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmts = $parser->parse($content);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($stmts)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$traverser->traverse($stmts);
|
$traverser->traverse($stmts);
|
||||||
$callback();
|
$callback();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser;
|
namespace Fbrinker\ExtensionCheck\Parser;
|
||||||
|
|
||||||
use Interop\Container\ContainerInterface;
|
use Interop\Container\ContainerInterface;
|
||||||
@ -8,6 +10,9 @@ use Symfony\Component\Finder\Finder;
|
|||||||
|
|
||||||
class FileParserFactory implements FactoryInterface
|
class FileParserFactory implements FactoryInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param array<mixed> $options
|
||||||
|
*/
|
||||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||||
{
|
{
|
||||||
return new FileParser(
|
return new FileParser(
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\NodeVisitorAbstract;
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
class ClassCollector extends NodeVisitorAbstract implements CollectorInferface {
|
class ClassCollector extends NodeVisitorAbstract implements CollectorInferface
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string,bool> $classes
|
||||||
|
*/
|
||||||
private $classes = [];
|
private $classes = [];
|
||||||
|
|
||||||
public function getCollected(): array {
|
public function getCollected(): array
|
||||||
|
{
|
||||||
$list = array_keys($this->classes);
|
$list = array_keys($this->classes);
|
||||||
natcasesort($list);
|
natcasesort($list);
|
||||||
|
|
||||||
return array_values($list);
|
return array_values($list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enterNode(Node $node) {
|
public function enterNode(Node $node)
|
||||||
|
{
|
||||||
if ($node instanceof Node\Stmt\Class_) {
|
if ($node instanceof Node\Stmt\Class_) {
|
||||||
if (!empty($node->extends)) {
|
if (!empty($node->extends)) {
|
||||||
$this->classes[$node->extends->toString()] = true;
|
$this->classes[$node->extends->toString()] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($node->implements)) {
|
if (!empty($node->implements)) {
|
||||||
foreach($node->implements as $implement) {
|
foreach ($node->implements as $implement) {
|
||||||
$this->classes[$implement->toString()] = true;
|
$this->classes[$implement->toString()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +44,7 @@ class ClassCollector extends NodeVisitorAbstract implements CollectorInferface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($node instanceof Node\Expr\New_) {
|
if ($node instanceof Node\Expr\New_) {
|
||||||
if (!empty($node->class) && $node->class->name instanceof Node\Name) {
|
if (!empty($node->class) && $node->class instanceof Node\Name) {
|
||||||
$this->classes[$node->class->toString()] = true;
|
$this->classes[$node->class->toString()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,5 +54,7 @@ class ClassCollector extends NodeVisitorAbstract implements CollectorInferface {
|
|||||||
$this->classes[$node->class->toString()] = true;
|
$this->classes[$node->class->toString()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
||||||
|
|
||||||
interface CollectorInferface {
|
interface CollectorInferface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
public function getCollected(): array;
|
public function getCollected(): array;
|
||||||
}
|
}
|
@ -1,25 +1,35 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\NodeVisitorAbstract;
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
class ConstantCollector extends NodeVisitorAbstract implements CollectorInferface {
|
class ConstantCollector extends NodeVisitorAbstract implements CollectorInferface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<string,bool> $constants
|
||||||
|
*/
|
||||||
private $constants = [];
|
private $constants = [];
|
||||||
|
|
||||||
public function getCollected(): array {
|
public function getCollected(): array
|
||||||
|
{
|
||||||
$list = array_keys($this->constants);
|
$list = array_keys($this->constants);
|
||||||
natcasesort($list);
|
natcasesort($list);
|
||||||
|
|
||||||
return array_values($list);
|
return array_values($list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enterNode(Node $node) {
|
public function enterNode(Node $node)
|
||||||
|
{
|
||||||
if ($node instanceof Node\Expr\ConstFetch) {
|
if ($node instanceof Node\Expr\ConstFetch) {
|
||||||
if (!empty($node->name) && $node->name instanceof Node\Name) {
|
if (!empty($node->name) && $node->name instanceof Node\Name) {
|
||||||
$this->constants[$node->name->toString()] = true;
|
$this->constants[$node->name->toString()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +1,35 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
namespace Fbrinker\ExtensionCheck\Parser\Visitors;
|
||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\NodeVisitorAbstract;
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
class FunctionCollector extends NodeVisitorAbstract implements CollectorInferface {
|
class FunctionCollector extends NodeVisitorAbstract implements CollectorInferface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<string,bool> $functions
|
||||||
|
*/
|
||||||
private $functions = [];
|
private $functions = [];
|
||||||
|
|
||||||
public function getCollected(): array {
|
public function getCollected(): array
|
||||||
|
{
|
||||||
$list = array_keys($this->functions);
|
$list = array_keys($this->functions);
|
||||||
natcasesort($list);
|
natcasesort($list);
|
||||||
|
|
||||||
return array_values($list);
|
return array_values($list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enterNode(Node $node) {
|
public function enterNode(Node $node)
|
||||||
|
{
|
||||||
if ($node instanceof Node\Expr\FuncCall) {
|
if ($node instanceof Node\Expr\FuncCall) {
|
||||||
if (!empty($node->name) && $node->name instanceof Node\Name) {
|
if (!empty($node->name) && $node->name instanceof Node\Name) {
|
||||||
$this->functions[$node->name->toString()] = true;
|
$this->functions[$node->name->toString()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user