Skip to content

Instantly share code, notes, and snippets.

@Jibbarth
Created February 12, 2023 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jibbarth/03e4f36ccd296dcb90d83af5707532ac to your computer and use it in GitHub Desktop.
Save Jibbarth/03e4f36ccd296dcb90d83af5707532ac to your computer and use it in GitHub Desktop.
[PHP-CS-Fixer] Configure any rule with except paths
<?php
declare(strict_types=1);
namespace App\Fixer;
use PhpCsFixer\AbstractProxyFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\FixerFactory;
use PhpCsFixer\RuleSet\RuleSet;
use PhpCsFixer\Tokenizer\Tokens;
final class NotInProxyFixer extends AbstractProxyFixer implements ConfigurableFixerInterface
{
private array $localConfig = [];
public function getName(): string
{
return 'Barth/not_in';
}
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Allow to configure any fixer but with except paths',
[
new CodeSample(
"'Barth/not_in' => ['final_class' => ['except' => 'src/Entity']],"
),
],
);
}
public function getPriority(): int
{
return 0;
}
public function configure(array $configuration): void
{
$this->localConfig = $configuration;
// bypass call in construct
if ([] !== $configuration) {
parent::configure($configuration);
}
}
public function getConfigurationDefinition(): FixerConfigurationResolverInterface
{
$fixerFactory = new FixerFactory();
$fixerFactory->registerBuiltInFixers();
if ([] !== $this->localConfig) {
foreach ($this->localConfig as $rule => $config) {
$currentFactory = clone $fixerFactory;
unset($config['except']);
if (0 === count($config)) { // No configurable fixer
$config = true;
}
$ruleset = new RuleSet([$rule => $config]);
$currentFactory->useRuleSet($ruleset);
foreach ($currentFactory->getFixers() as $fixer) {
$this->proxyFixers[$fixer->getName()] = $fixer;
}
}
}
return new NoValidateFixerConfigurationResolver();
}
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
foreach ($this->proxyFixers as $rule => $fixer) {
foreach ($this->localConfig[$rule]['except'] ?? [] as $excludePath) {
if (str_contains($file->getRealPath(), $excludePath)) {
continue 2;
}
}
$fixer->fix($file, $tokens);
}
}
protected function createProxyFixers(): array
{
return [];
}
}
<?php
declare(strict_types=1);
namespace App\Fixer;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
final class NoValidateFixerConfigurationResolver implements FixerConfigurationResolverInterface
{
public function getOptions(): array
{
return [];
}
public function resolve(array $configuration): array
{
return [];
}
}

In your .php-cs-fixer.php, register the rule and configure those you want to have exclude paths:

<?php

$finder = (new PhpCsFixer\Finder())
    ->in(__DIR__)
    ->exclude('var')
;

return (new PhpCsFixer\Config())
    ->registerCustomFixers([
        new \App\Fixer\NotInProxyFixer()
    ])
    ->setRules([
        '@Symfony' => true,
        '@PSR12' => true,
        'Barth/not_in' => [
            'final_class' => ['except' => [
                'src/Entity',
            ]],
            'method_chaining_indentation' => ['except' => [
                'src/DependencyInjection',
            ]],
        ],
    ])
    ->setRiskyAllowed(true)
    ->setFinder($finder)
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment