Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Codebase to use modern PHP features using Rector #225

Merged
merged 10 commits into from
Feb 20, 2024
Merged
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
3 changes: 2 additions & 1 deletion rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
// ->withPhpSets(php80: true)
->withPhpSets(php80: true)
->withPreparedSets(deadCode: true, codingStyle: true)
->withRules([
AddVoidReturnTypeWhereNoReturnRector::class,
]);
17 changes: 6 additions & 11 deletions src/ClassesFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,17 @@ public function findAndLoadClasses(): Collection
if ($this->isMostLikelyPestTest($file)) {
return true;
}

require_once $file->getRealPath();
} catch (Exception $e) {
} catch (Exception) {
//
}
});

ob_end_clean();

return collect(get_declared_classes())
->reject(function (string $className) {
return Str::startsWith($className, ['SwooleLibrary']);
});
->reject(static fn (string $className) => Str::startsWith($className, ['SwooleLibrary']));
}

/**
Expand All @@ -52,19 +51,15 @@ protected function findFilesInProjectPath(): Collection
->name('*.php');

return collect($files)
->reject(function ($file) use ($excludes) {
return $this->isExcluded($file, $excludes);
});
->reject(fn ($file) => $this->isExcluded($file, $excludes));
}

/**
* Determine if a file has been defined in the exclude configuration.
*/
protected function isExcluded(SplFileInfo $file, Collection $excludes): bool
{
return $excludes->contains(function ($exclude) use ($file) {
return Str::startsWith($file->getPathname(), $exclude);
});
return $excludes->contains(static fn ($exclude) => Str::startsWith($file->getPathname(), $exclude));
}

/**
Expand Down Expand Up @@ -102,7 +97,7 @@ protected function isMostLikelyPestTest(SplFileInfo $file): bool
'afterAll',
]);

if (preg_match("/$methodNames\s*\(/", $fileContent)) {
if (preg_match(sprintf('/%s\s*\(/', $methodNames), $fileContent)) {
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Classifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ public function getClassifierForClassInstance(ReflectionClass $class): Classifie
$classifierInstance = new $classifier();

if (! $this->implementsContract($classifier)) {
throw new Exception("Classifier {$classifier} does not implement ".ClassifierContract::class.'.');
throw new Exception(sprintf('Classifier %s does not implement ', $classifier).ClassifierContract::class.'.');
}

try {
$satisfied = $classifierInstance->satisfies($class);
} catch (Exception $e) {
} catch (Exception) {
$satisfied = false;
}

Expand Down
10 changes: 4 additions & 6 deletions src/Classifiers/ControllerClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,23 @@ public function name(): string
public function satisfies(ReflectionClass $class): bool
{
return collect(app(Router::class)->getRoutes())
->reject(function ($route) {
->reject(static function ($route) {
if (method_exists($route, 'getActionName')) {
// Laravel
return $route->getActionName() === 'Closure';
}

// Lumen
return data_get($route, 'action.uses') === null;
})
->map(function ($route) {
->map(static function ($route) {
if (method_exists($route, 'getController')) {
// Laravel
try {
return get_class($route->getController());
} catch (Throwable $e) {
return $route->getController()::class;
} catch (Throwable) {
return;
}
}

// Lumen
return Str::before(data_get($route, 'action.uses'), '@');
})
Expand Down
6 changes: 1 addition & 5 deletions src/Classifiers/EventListenerClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ public function name(): string
public function satisfies(ReflectionClass $class): bool
{
return collect($this->getEvents())
->map(function (array $listeners) {
return collect($listeners)->map(function ($closure) {
return $this->getEventListener($closure);
})->toArray();
})
->map(fn (array $listeners) => collect($listeners)->map(fn ($closure) => $this->getEventListener($closure))->toArray())
->collapse()
->flatten()
->unique()
Expand Down
6 changes: 4 additions & 2 deletions src/Classifiers/MiddlewareClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ protected function getMiddlewares(): array
{
$reflection = new ReflectionProperty($this->httpKernel, 'middleware');
$reflection->setAccessible(true);

$middleware = $reflection->getValue($this->httpKernel);

$reflection = new ReflectionProperty($this->httpKernel, 'routeMiddleware');
$reflection->setAccessible(true);

$routeMiddlwares = $reflection->getValue($this->httpKernel);

return array_values(array_unique(array_merge($middleware, $routeMiddlwares)));
Expand All @@ -65,7 +67,7 @@ protected function getHttpKernelInstance()
{
try {
return app(Kernel::class);
} catch (BindingResolutionException $e) {
} catch (BindingResolutionException) {
// Lumen
return app();
}
Expand All @@ -89,7 +91,7 @@ private function getRouteMiddlewares(): array
$router = $reflection->getValue($this->httpKernel);

return collect($router->getRoutes()->getRoutes())
->map(fn (Route $route) => $route->middleware())
->map(static fn (Route $route) => $route->middleware())
->flatten()
->unique()
->toArray();
Expand Down
18 changes: 4 additions & 14 deletions src/Classifiers/ObserverClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,12 @@ public function name(): string
public function satisfies(ReflectionClass $class): bool
{
return collect($this->getEvents())
->filter(function ($_listeners, $event) {
return Str::startsWith($event, 'eloquent.');
})
->map(function ($listeners) {
return collect($listeners)->map(function ($closure) {
return $this->getEventListener($closure);
})->toArray();
})
->filter(static fn ($_listeners, $event) => Str::startsWith($event, 'eloquent.'))
->map(fn ($listeners) => collect($listeners)->map(fn ($closure) => $this->getEventListener($closure))->toArray())
->collapse()
->unique()
->filter(function ($eventListener) {
return is_string($eventListener);
})
->filter(function (string $eventListenerSignature) use ($class) {
return Str::contains($eventListenerSignature, $class->getName());
})
->filter(static fn ($eventListener) => is_string($eventListener))
->filter(static fn (string $eventListenerSignature) => Str::contains($eventListenerSignature, $class->getName()))
->count() > 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/Classifiers/ResourceClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function satisfies(ReflectionClass $class): bool
if ($class->isSubclassOf(JsonResource::class)) {
return true;
}

return $class->isSubclassOf(ResourceCollection::class);
}

Expand Down
42 changes: 18 additions & 24 deletions src/Console/StatsListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,31 @@ class StatsListCommand extends Command

/**
* Execute the console command.
*
* @return void
*/
public function handle()
public function handle(): void
{
$classes = app(ClassesFinder::class)->findAndLoadClasses();

// Transform Classes into ReflectionClass instances
// Remove Classes based on the RejectionStrategy
// Remove Classes based on the namespace
$reflectionClasses = $classes->map(function ($class) {
return new ReflectionClass($class);
})->reject(function (ReflectionClass $class) {
return app(config('stats.rejection_strategy', RejectVendorClasses::class))
->shouldClassBeRejected($class);
})->unique(function (ReflectionClass $class) {
return $class->getFileName();
})->reject(function (ReflectionClass $class) {
// Never discard anonymous database migrations
if (Str::contains($class->getName(), 'Migration@anonymous')) {
return false;
}

foreach (config('stats.ignored_namespaces', []) as $namespace) {
if (Str::startsWith($class->getNamespaceName(), $namespace)) {
return true;
$reflectionClasses = $classes
->map(static fn ($class) => new ReflectionClass($class))
->reject(static fn (ReflectionClass $class) => app(config('stats.rejection_strategy', RejectVendorClasses::class))
->shouldClassBeRejected($class))
->unique(static fn (ReflectionClass $class) => $class->getFileName())
->reject(static function (ReflectionClass $class) {
// Never discard anonymous database migrations
if (Str::contains($class->getName(), 'Migration@anonymous')) {
return false;
}
}

return false;
});
foreach (config('stats.ignored_namespaces', []) as $namespace) {
if (Str::startsWith($class->getNamespaceName(), $namespace)) {
return true;
}
}
return false;
});

$project = new Project($reflectionClasses);

Expand All @@ -84,7 +78,7 @@ private function getArrayOfComponentsToDisplay(): array
return explode(',', $this->option('components'));
}

private function renderOutput(Project $project)
private function renderOutput(Project $project): void
{
if ($this->option('json') === true) {
$json = (new JsonOutput())->render(
Expand Down
31 changes: 13 additions & 18 deletions src/Outputs/AsciiTableOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function __construct(OutputStyle $output)
$this->output = $output;
}

public function render(Project $project, bool $isVerbose = false, array $filterByComponentName = [])
public function render(Project $project, bool $isVerbose = false, array $filterByComponentName = []): void
{
$this->isVerbose = $isVerbose;
$this->project = $project;
Expand All @@ -52,19 +52,13 @@ public function render(Project $project, bool $isVerbose = false, array $filterB
->setHeaders(['Name', 'Classes', 'Methods', 'Methods/Class', 'LoC', 'LLoC', 'LLoC/Method']);

// Render "Core" components
$this->renderComponents($table, $groupedByComponent->filter(function ($_, $key) {
return $key !== 'Other' && ! Str::contains($key, 'Test');
}));
$this->renderComponents($table, $groupedByComponent->filter(static fn ($_, $key) => $key !== 'Other' && ! Str::contains($key, 'Test')));

// Render Test components
$this->renderComponents($table, $groupedByComponent->filter(function ($_, $key) {
return Str::contains($key, 'Test');
}));
$this->renderComponents($table, $groupedByComponent->filter(static fn ($_, $key) => Str::contains($key, 'Test')));

// Render "Other" component
$this->renderComponents($table, $groupedByComponent->filter(function ($_, $key) {
return $key == 'Other';
}));
$this->renderComponents($table, $groupedByComponent->filter(static fn ($_, $key) => $key === 'Other'));

$table->addRow(new TableSeparator);
$this->addTotalRow($table);
Expand All @@ -73,7 +67,7 @@ public function render(Project $project, bool $isVerbose = false, array $filterB
$table->render();
}

private function renderComponents(Table $table, Collection $groupedByComponent)
private function renderComponents(Table $table, Collection $groupedByComponent): void
{
foreach ($groupedByComponent as $componentName => $classifiedClasses) {
$component = new Component($componentName, $classifiedClasses);
Expand All @@ -86,6 +80,7 @@ private function renderComponents(Table $table, Collection $groupedByComponent)
foreach ($classifiedClasses as $classifiedClass) {
$this->addClassifiedClassTableRow($table, $classifiedClass);
}

$table->addRow(new TableSeparator);
}
}
Expand All @@ -104,7 +99,7 @@ private function addComponentTableRow(Table $table, Component $component): void
]);
}

private function addClassifiedClassTableRow(Table $table, ClassifiedClass $classifiedClass)
private function addClassifiedClassTableRow(Table $table, ClassifiedClass $classifiedClass): void
{
$table->addRow([
new TableCell(
Expand All @@ -119,7 +114,7 @@ private function addClassifiedClassTableRow(Table $table, ClassifiedClass $class
]);
}

private function addTotalRow(Table $table)
private function addTotalRow(Table $table): void
{
$table->addRow([
'name' => 'Total',
Expand All @@ -132,19 +127,19 @@ private function addTotalRow(Table $table)
]);
}

private function addMetaRow(Table $table)
private function addMetaRow(Table $table): void
{
$table->setFooterTitle(implode(' • ', [
"Code LLoC: {$this->project->statistic()->getLogicalLinesOfCodeForApplicationCode()}",
"Test LLoC: {$this->project->statistic()->getLogicalLinesOfCodeForTestCode()}",
'Code LLoC: ' . $this->project->statistic()->getLogicalLinesOfCodeForApplicationCode(),
'Test LLoC: ' . $this->project->statistic()->getLogicalLinesOfCodeForTestCode(),
'Code/Test Ratio: 1:'.$this->project->statistic()->getApplicationCodeToTestCodeRatio(),
'Routes: '.app(NumberOfRoutes::class)->get(),
]));
}

private function rightAlignNumbers(Table $table)
private function rightAlignNumbers(Table $table): void
{
for ($i = 1; $i <= 6; $i++) {
for ($i = 1; $i <= 6; ++$i) {
$table->setColumnStyle($i, (new TableStyle)->setPadType(STR_PAD_LEFT));
}
}
Expand Down
Loading