diff --git a/Controller/CaptchaController.php b/Controller/CaptchaController.php index 8d8d83e..d3c5751 100644 --- a/Controller/CaptchaController.php +++ b/Controller/CaptchaController.php @@ -1,32 +1,37 @@ */ class CaptchaController extends AbstractController { - /** - * Action that is used to generate the captcha, save its code, and stream the image - * - * @param string $key - * - * @return Response - * - * @throws NotFoundHttpException - */ - public function generateCaptchaAction($key) + /** @var CaptchaGenerator */ + private $captchaGenerator; + + /** @var array */ + private $config; + + public function __construct(CaptchaGenerator $captchaGenerator, array $config) { - $options = $this->container->getParameter('gregwar_captcha.config'); - $session = $this->get('session'); - $whitelistKey = $options['whitelist_key']; + $this->captchaGenerator = $captchaGenerator; + $this->config = $config; + } + + public function generateCaptchaAction(Request $request, string $key): Response + { + $session = $request->getSession(); + $whitelistKey = $this->config['whitelist_key']; $isOk = false; if ($session->has($whitelistKey)) { @@ -37,21 +42,18 @@ class CaptchaController extends AbstractController } if (!$isOk) { - return $this->error($options); + return $this->error($this->config); } - /* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */ - $generator = $this->container->get('gregwar_captcha.generator'); - $persistedOptions = $session->get($key, array()); - $options = array_merge($options, $persistedOptions); + $options = array_merge($this->config, $persistedOptions); - $phrase = $generator->getPhrase($options); - $generator->setPhrase($phrase); + $phrase = $this->captchaGenerator->getPhrase($options); + $this->captchaGenerator->setPhrase($phrase); $persistedOptions['phrase'] = $phrase; $session->set($key, $persistedOptions); - $response = new Response($generator->generate($options)); + $response = new Response($this->captchaGenerator->generate($options)); $response->headers->set('Content-type', 'image/jpeg'); $response->headers->set('Pragma', 'no-cache'); $response->headers->set('Cache-Control', 'no-cache'); @@ -59,20 +61,11 @@ class CaptchaController extends AbstractController return $response; } - /** - * Returns an empty image with status code 428 Precondition Required - * - * @param array $options - * - * @return Response - */ - protected function error($options) + private function error(array $options): Response { - /* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */ - $generator = $this->container->get('gregwar_captcha.generator'); - $generator->setPhrase(''); + $this->captchaGenerator->setPhrase(''); - $response = new Response($generator->generate($options)); + $response = new Response($this->captchaGenerator->generate($options)); $response->setStatusCode(428); $response->headers->set('Content-type', 'image/jpeg'); $response->headers->set('Pragma', 'no-cache'); diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 3683c20..ab4b23c 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1,5 +1,7 @@ getRootNode(); - } else { - // BC for symfony/config <= 4.1 - $rootNode = $treeBuilder->root('gregwar_captcha'); - } + $rootNode = $treeBuilder->getRootNode(); $rootNode ->addDefaultsIfNotSet() @@ -36,7 +27,7 @@ class Configuration implements ConfigurationInterface ->scalarNode('as_url')->defaultValue(false)->end() ->scalarNode('reload')->defaultValue(false)->end() ->scalarNode('image_folder')->defaultValue('captcha')->end() - ->scalarNode('web_path')->defaultValue('%kernel.root_dir%/../web')->end() + ->scalarNode('web_path')->defaultValue('%kernel.project_dir%/public')->end() ->scalarNode('gc_freq')->defaultValue(100)->end() ->scalarNode('expiration')->defaultValue(60)->end() ->scalarNode('quality')->defaultValue(50)->end() diff --git a/DependencyInjection/GregwarCaptchaExtension.php b/DependencyInjection/GregwarCaptchaExtension.php index 740b3e6..060fff8 100755 --- a/DependencyInjection/GregwarCaptchaExtension.php +++ b/DependencyInjection/GregwarCaptchaExtension.php @@ -1,24 +1,29 @@ */ class GregwarCaptchaExtension extends Extension { /** - * @param array $configs + * @param array $configs * @param ContainerBuilder $container + * + * @throws Exception */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); diff --git a/Generator/CaptchaGenerator.php b/Generator/CaptchaGenerator.php index 58ff58a..08b33dc 100644 --- a/Generator/CaptchaGenerator.php +++ b/Generator/CaptchaGenerator.php @@ -1,48 +1,40 @@ * @author Jeremy Livingston */ class CaptchaGenerator { - /** - * @var RouterInterface - */ + /** @var RouterInterface */ protected $router; - /** - * @var CaptchaBuilder - */ + /** @var CaptchaBuilder */ protected $builder; - /** - * @var PhraseBuilder - */ + /** @var PhraseBuilder */ protected $phraseBuilder; - /** - * @var ImageFileHandler - */ + /** @var ImageFileHandler */ protected $imageFileHandler; /** - * @param RouterInterface $router + * @param RouterInterface $router * @param CaptchaBuilderInterface $builder - * @param PhraseBuilderInterface $phraseBuilder - * @param ImageFileHandler $imageFileHandler + * @param PhraseBuilderInterface $phraseBuilder + * @param ImageFileHandler $imageFileHandler */ public function __construct( RouterInterface $router, @@ -50,20 +42,13 @@ class CaptchaGenerator PhraseBuilderInterface $phraseBuilder, ImageFileHandler $imageFileHandler ) { - $this->router = $router; - $this->builder = $builder; - $this->phraseBuilder = $phraseBuilder; - $this->imageFileHandler = $imageFileHandler; + $this->router = $router; + $this->builder = $builder; + $this->phraseBuilder = $phraseBuilder; + $this->imageFileHandler = $imageFileHandler; } - /** - * Get the captcha URL, stream, or filename that will go in the image's src attribute - * - * @param array $options - * - * @return array - */ - public function getCaptchaCode(array &$options) + public function getCaptchaCode(array &$options): string { $this->builder->setPhrase($this->getPhrase($options)); @@ -76,27 +61,21 @@ class CaptchaGenerator // Returns the image generation URL if ($options['as_url']) { - return $this->router->generate('gregwar_captcha.generate_captcha', - array('key' => $options['session_key'], 'n' => md5(microtime(true).mt_rand()))); + return $this->router->generate( + 'gregwar_captcha.generate_captcha', + array('key' => $options['session_key'], 'n' => md5(microtime(true).mt_rand())) + ); } - return 'data:image/jpeg;base64,' . base64_encode($this->generate($options)); + return 'data:image/jpeg;base64,'.base64_encode($this->generate($options)); } - /** - * Sets the phrase to the builder - */ - public function setPhrase($phrase) + public function setPhrase(string $phrase): void { $this->builder->setPhrase($phrase); } - /** - * @param array $options - * - * @return string - */ - public function generate(array &$options) + public function generate(array &$options): string { $this->builder->setDistortion($options['distortion']); @@ -104,7 +83,7 @@ class CaptchaGenerator $this->builder->setMaxBehindLines($options['max_behind_lines']); if (isset($options['text_color']) && $options['text_color']) { - if (count($options['text_color']) !== 3) { + if (3 !== count($options['text_color'])) { throw new \RuntimeException('text_color should be an array of r, g and b'); } @@ -113,7 +92,7 @@ class CaptchaGenerator } if (isset($options['background_color']) && $options['background_color']) { - if (count($options['background_color']) !== 3) { + if (3 !== count($options['background_color'])) { throw new \RuntimeException('background_color should be an array of r, g and b'); } @@ -149,12 +128,7 @@ class CaptchaGenerator return $this->imageFileHandler->saveAsFile($content); } - /** - * @param array $options - * - * @return string - */ - public function getPhrase(array &$options) + public function getPhrase(array &$options): string { // Get the phrase that we'll use for this image if ($options['keep_value'] && isset($options['phrase'])) { @@ -163,7 +137,7 @@ class CaptchaGenerator $phrase = $this->phraseBuilder->build($options['length'], $options['charset']); $options['phrase'] = $phrase; } - + return $phrase; } } diff --git a/Generator/ImageFileHandler.php b/Generator/ImageFileHandler.php index 71dda0f..616d6f2 100644 --- a/Generator/ImageFileHandler.php +++ b/Generator/ImageFileHandler.php @@ -1,11 +1,13 @@ * @author Jeremy Livingston @@ -13,69 +15,61 @@ use Symfony\Component\Finder\Finder; class ImageFileHandler { /** - * Name of folder for captcha images + * Name of folder for captcha images. + * * @var string */ protected $imageFolder; /** - * Absolute path to public web folder + * Absolute path to public web folder. + * * @var string */ protected $webPath; /** - * Frequency of garbage collection in fractions of 1 + * Frequency of garbage collection in fractions of 1. + * * @var int */ protected $gcFreq; /** - * Maximum age of images in minutes + * Maximum age of images in minutes. + * * @var int */ protected $expiration; /** - * @param $imageFolder - * @param $webPath - * @param $gcFreq - * @param $expiration + * @param string $imageFolder + * @param string $webPath + * @param string $gcFreq + * @param string $expiration */ - public function __construct($imageFolder, $webPath, $gcFreq, $expiration) + public function __construct(string $imageFolder, string $webPath, string $gcFreq, string $expiration) { - $this->imageFolder = $imageFolder; - $this->webPath = $webPath; - $this->gcFreq = $gcFreq; - $this->expiration = $expiration; + $this->imageFolder = $imageFolder; + $this->webPath = $webPath; + $this->gcFreq = $gcFreq; + $this->expiration = $expiration; } - /** - * Saves the provided image content as a file - * - * @param string $contents - * - * @return string - */ - public function saveAsFile($contents) + public function saveAsFile($contents): string { $this->createFolderIfMissing(); - $filename = md5(uniqid()) . '.jpg'; - $filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename; + $filename = md5(uniqid()).'.jpg'; + $filePath = $this->webPath.'/'.$this->imageFolder.'/'.$filename; imagejpeg($contents, $filePath, 15); - return '/' . $this->imageFolder . '/' . $filename; + return '/'.$this->imageFolder.'/'.$filename; } - /** - * Randomly runs garbage collection on the image directory - * - * @return bool - */ - public function collectGarbage() + public function collectGarbage(): bool { - if (!mt_rand(1, $this->gcFreq) == 1) { + if (1 == !mt_rand(1, $this->gcFreq)) { return false; } @@ -83,23 +77,20 @@ class ImageFileHandler $finder = new Finder(); $criteria = sprintf('<= now - %s minutes', $this->expiration); - $finder->in($this->webPath . '/' . $this->imageFolder) + $finder->in($this->webPath.'/'.$this->imageFolder) ->date($criteria); - foreach($finder->files() as $file) { + foreach ($finder->files() as $file) { unlink($file->getPathname()); } return true; } - /** - * Creates the folder if it doesn't exist - */ - protected function createFolderIfMissing() + protected function createFolderIfMissing(): void { - if (!file_exists($this->webPath . '/' . $this->imageFolder)) { - mkdir($this->webPath . '/' . $this->imageFolder, 0755); + if (!file_exists($this->webPath.'/'.$this->imageFolder)) { + mkdir($this->webPath.'/'.$this->imageFolder, 0755); } } } diff --git a/GregwarCaptchaBundle.php b/GregwarCaptchaBundle.php index 9ad5967..838fc20 100755 --- a/GregwarCaptchaBundle.php +++ b/GregwarCaptchaBundle.php @@ -1,5 +1,7 @@ | +| 2.* | 2.8 - 3.* | 5.3.9 > | +| 1.* | 2.1 - 2.7 | 5.3.0 > | -If you are using Symfony `>= 2.8`, you should use version `2.*` Installation ============ ### Step 1: Download the GregwarCaptchaBundle -Ultimately, the GregwarCaptchaBundle files should be downloaded to the -'vendor/bundles/Gregwar/CaptchaBundle' directory. - -You can accomplish this several ways, depending on your personal preference. -The first method is the standard Symfony method. - -***Using Composer*** - -Use composer require to download and install the package. +Use composer require to download and install the package. +At the end of the installation you can automaticly create the configuration thanks to the Symfony recipe. ``` bash composer require gregwar/captcha-bundle ``` -***Using the vendors script*** - -Add the following lines to your `deps` file: - -``` - [GregwarCaptchaBundle] - git=http://github.com/Gregwar/CaptchaBundle.git - target=/bundles/Gregwar/CaptchaBundle - version=origin/2.0 <- add this if you are using Symfony 2.0 -``` - -Now, run the vendors script to download the bundle: - -``` bash -$ php bin/vendors install -``` - -***Using submodules*** - -If you prefer instead to use git submodules, then run the following: - -``` bash -$ git submodule add git://github.com/Gregwar/CaptchaBundle.git vendor/bundles/Gregwar/CaptchaBundle -$ git submodule update --init -``` - -### Step 2: Configure the Autoloader - -If you use composer, you can skip this step. - -Now you will need to add the `Gregwar` namespace to your autoloader: - -``` php -registerNamespaces(array( - // ... - 'Gregwar' => __DIR__.'/../vendor/bundles', -)); -``` -### Step 3: Enable the bundle - -Finally, enable the bundle in the kernel: - -```php -add('captcha', CaptchaType::class); // That's all ! - // If you're using php<5.5, you can use instead: - $builder->add('captcha', 'Gregwar\CaptchaBundle\Type\CaptchaType'); // ... ``` @@ -123,7 +62,7 @@ Options You can define the following configuration options globally: * **image_folder**: name of folder for captcha images relative to public web folder in case **as_file** is set to true (default="captcha") -* **web_path**: absolute path to public web folder (default="%kernel.root_dir%/../web") +* **web_path**: absolute path to public web folder (default='%kernel.project_dir%/public') * **gc_freq**: frequency of garbage collection in fractions of 1 (default=100) * **expiration**: maximum lifetime of captcha image files in minutes (default=60) @@ -155,7 +94,7 @@ number of lines depends on the size of the image). (default=null) Example : -```php +``` php diff --git a/Resources/config/services.yml b/Resources/config/services.yml index fca2c44..04dff56 100755 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,4 +1,5 @@ parameters: + gregwar_captcha.controller.class: Gregwar\CaptchaBundle\Controller\CaptchaController gregwar_captcha.captcha_type.class: Gregwar\CaptchaBundle\Type\CaptchaType gregwar_captcha.captcha_generator.class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator gregwar_captcha.image_file_handler.class: Gregwar\CaptchaBundle\Generator\ImageFileHandler @@ -6,7 +7,15 @@ parameters: gregwar_captcha.phrase_builder.class: Gregwar\Captcha\PhraseBuilder services: - captcha.type: + gregwar_captcha.controller: + class: '%gregwar_captcha.controller.class%' + public: true + arguments: + - '@gregwar_captcha.generator' + - '%gregwar_captcha.config%' + +# captcha.type: + gregwar_captcha.type: class: '%gregwar_captcha.captcha_type.class%' public: true arguments: diff --git a/Type/CaptchaType.php b/Type/CaptchaType.php index ac9d00a..8e659ea 100644 --- a/Type/CaptchaType.php +++ b/Type/CaptchaType.php @@ -1,22 +1,23 @@ */ @@ -24,25 +25,16 @@ class CaptchaType extends AbstractType { const SESSION_KEY_PREFIX = '_captcha_'; - /** - * @var SessionInterface - */ + /** @var SessionInterface */ protected $session; - /** - * @var CaptchaGenerator - */ + /** @var CaptchaGenerator */ protected $generator; - /** - * @var TranslatorInterface - */ + /** @var TranslatorInterface */ protected $translator; - /** - * Options - * @var array - */ + /** @var array */ private $options = array(); /** @@ -53,10 +45,10 @@ class CaptchaType extends AbstractType */ public function __construct(SessionInterface $session, CaptchaGenerator $generator, TranslatorInterface $translator, $options) { - $this->session = $session; - $this->generator = $generator; - $this->translator = $translator; - $this->options = $options; + $this->session = $session; + $this->generator = $generator; + $this->translator = $translator; + $this->options = $options; } /** @@ -72,8 +64,8 @@ class CaptchaType extends AbstractType $options['bypass_code'], $options['humanity'] ); - $event = \Symfony\Component\HttpKernel\Kernel::VERSION >= 2.3 ? FormEvents::POST_SUBMIT : FormEvents::POST_BIND; - $builder->addEventListener($event, array($validator, 'validate')); + + $builder->addEventListener(FormEvents::POST_SUBMIT, array($validator, 'validate')); } /** @@ -86,7 +78,7 @@ class CaptchaType extends AbstractType } $sessionKey = sprintf('%s%s', self::SESSION_KEY_PREFIX, $options['session_key']); - $isHuman = false; + $isHuman = false; if ($options['humanity'] > 0) { $humanityKey = sprintf('%s_humanity', $sessionKey); @@ -105,18 +97,18 @@ class CaptchaType extends AbstractType } $view->vars = array_merge($view->vars, array( - 'captcha_width' => $options['width'], - 'captcha_height' => $options['height'], - 'reload' => $options['reload'], - 'image_id' => uniqid('captcha_'), - 'captcha_code' => $this->generator->getCaptchaCode($options), - 'value' => '', - 'is_human' => $isHuman + 'captcha_width' => $options['width'], + 'captcha_height' => $options['height'], + 'reload' => $options['reload'], + 'image_id' => uniqid('captcha_'), + 'captcha_code' => $this->generator->getCaptchaCode($options), + 'value' => '', + 'is_human' => $isHuman, )); $persistOptions = array(); foreach (array('phrase', 'width', 'height', 'distortion', 'length', - 'quality', 'background_color', 'background_images', 'text_color') as $key) { + 'quality', 'background_color', 'background_images', 'text_color', ) as $key) { $persistOptions[$key] = $options[$key]; } @@ -132,36 +124,17 @@ class CaptchaType extends AbstractType $resolver->setDefaults($this->options); } - /** - * {@inheritdoc} - * BC for SF < 2.7 - */ - public function setDefaultOptions(OptionsResolverInterface $resolver) + public function getParent(): string { - $this->configureOptions($resolver); + return TextType::class; } - /** - * @return string - */ - public function getParent() - { - // Not using ::class to support Symfony 2.8 w/ php>=5.3.9 - return 'Symfony\Component\Form\Extension\Core\Type\TextType'; - } - - /** - * @return string - */ - public function getName() + public function getName(): string { return $this->getBlockPrefix(); } - /** - * @return string - */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'captcha'; } diff --git a/Validator/CaptchaValidator.php b/Validator/CaptchaValidator.php index 7ee2a51..cdabc8e 100644 --- a/Validator/CaptchaValidator.php +++ b/Validator/CaptchaValidator.php @@ -1,73 +1,76 @@ */ class CaptchaValidator { - /** - * @var SessionInterface - */ + /** @var SessionInterface */ private $session; /** - * Session key to store the code + * Session key to store the code. + * + * @var string */ private $key; /** - * Error message text for non-matching submissions + * Error message text for non-matching submissions. + * + * @var string */ private $invalidMessage; /** - * Configuration parameter used to bypass a required code match + * Configuration parameter used to bypass a required code match. + * + * @var string */ private $bypassCode; /** - * Number of form that the user can submit without captcha + * Number of form that the user can submit without captcha. + * * @var int */ private $humanity; /** - * Translator + * Translator. + * * @var TranslatorInterface */ private $translator; - /** - * @param TranslatorInterface $translator - * @param SessionInterface $session - * @param string $key - * @param string $invalidMessage - * @param string $bypassCode - * @param int $humanity - */ - public function __construct(TranslatorInterface $translator, SessionInterface $session, $key, $invalidMessage, $bypassCode, $humanity) - { - $this->translator = $translator; - $this->session = $session; - $this->key = $key; - $this->invalidMessage = $invalidMessage; - $this->bypassCode = (string)$bypassCode; - $this->humanity = $humanity; + public function __construct( + TranslatorInterface $translator, + SessionInterface $session, + string $key, + string $invalidMessage, + ?string $bypassCode, + int $humanity + ) { + $this->translator = $translator; + $this->session = $session; + $this->key = $key; + $this->invalidMessage = $invalidMessage; + $this->bypassCode = $bypassCode; + $this->humanity = $humanity; } - /** - * @param FormEvent $event - */ - public function validate(FormEvent $event) + public function validate(FormEvent $event): void { $form = $event->getForm(); @@ -77,12 +80,13 @@ class CaptchaValidator if ($this->humanity > 0) { $humanity = $this->getHumanity(); if ($humanity > 0) { - $this->updateHumanity($humanity-1); + $this->updateHumanity($humanity - 1); + return; } } - if (!($code !== null && is_string($code) && ($this->compare($code, $expectedCode) || $this->compare($code, $this->bypassCode)))) { + if (!(null !== $code && is_string($code) && ($this->compare($code, $expectedCode) || $this->compare($code, $this->bypassCode)))) { $form->addError(new FormError($this->translator->trans($this->invalidMessage, array(), 'validators'))); } else { if ($this->humanity > 0) { @@ -92,13 +96,13 @@ class CaptchaValidator $this->session->remove($this->key); - if ($this->session->has($this->key . '_fingerprint')) { - $this->session->remove($this->key . '_fingerprint'); + if ($this->session->has($this->key.'_fingerprint')) { + $this->session->remove($this->key.'_fingerprint'); } } /** - * Retrieve the expected CAPTCHA code + * Retrieve the expected CAPTCHA code. * * @return mixed|null */ @@ -114,51 +118,39 @@ class CaptchaValidator } /** - * Retrieve the humanity + * Retrieve the humanity. * * @return mixed|null */ protected function getHumanity() { - return $this->session->get($this->key . '_humanity', 0); + return $this->session->get($this->key.'_humanity', 0); } - /** - * Updates the humanity - */ - protected function updateHumanity($newValue) + protected function updateHumanity(int $newValue): void { if ($newValue > 0) { - $this->session->set($this->key . '_humanity', $newValue); + $this->session->set($this->key.'_humanity', $newValue); } else { - $this->session->remove($this->key . '_humanity'); + $this->session->remove($this->key.'_humanity'); } - - return null; } - /** - * Process the codes - * - * @param $code - * - * @return string - */ - protected function niceize($code) + protected function niceize(string $code): string { return strtr(strtolower($code), 'oil', '01l'); } /** - * Run a match comparison on the provided code and the expected code + * Run a match comparison on the provided code and the expected code. * - * @param $code - * @param $expectedCode + * @param string $code + * @param string|null $expectedCode * * @return bool */ - protected function compare($code, $expectedCode) + protected function compare($code, $expectedCode): bool { - return ($expectedCode !== null && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode)); + return null !== $expectedCode && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode); } } diff --git a/composer.json b/composer.json index 703267b..d4351e7 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,23 @@ } ], "require": { - "php": ">=5.3.9", + "php": "^7.1.3", + "ext-gd": "*", "gregwar/captcha": "~1.1", - "symfony/framework-bundle": "~3.0|~4.0|~5.0", - "symfony/form": "~3.0|~4.0|~5.0", - "twig/twig": "^1.40|^2.9|^3" + "symfony/form": "~4.0|~5.0", + "symfony/framework-bundle": "~4.0|~5.0", + "symfony/translation": "~4.0|^5.0", + "twig/twig": "^2.10|^3.0" }, "autoload": { "psr-4": { "Gregwar\\CaptchaBundle\\": "/" } + }, + "config": { + "sort-packages": true + }, + "require-dev": { + "symplify/easy-coding-standard": "^6.1" } } diff --git a/ecs.yaml b/ecs.yaml new file mode 100644 index 0000000..3c977fc --- /dev/null +++ b/ecs.yaml @@ -0,0 +1,138 @@ +parameters: + exclude_files: + - 'vendor/*' + - 'LICENSE' + - 'README.md' + +services: + # PSR1 + PhpCsFixer\Fixer\Basic\EncodingFixer: ~ + PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer: ~ + + PhpCsFixer\Fixer\NamespaceNotation\BlankLineAfterNamespaceFixer: ~ + PhpCsFixer\Fixer\ControlStructure\ElseifFixer: ~ + PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer: ~ + PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer: ~ + PhpCsFixer\Fixer\Whitespace\LineEndingFixer: ~ + PhpCsFixer\Fixer\Casing\ConstantCaseFixer: ~ + PhpCsFixer\Fixer\Casing\LowercaseKeywordsFixer: ~ + PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer: + ensure_fully_multiline: true + PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer: ~ + PhpCsFixer\Fixer\PhpTag\NoClosingTagFixer: ~ + PhpCsFixer\Fixer\FunctionNotation\NoSpacesAfterFunctionNameFixer: ~ + PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer: ~ + PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer: ~ + PhpCsFixer\Fixer\Comment\NoTrailingWhitespaceInCommentFixer: ~ + PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer: ~ + PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer: + elements: + - 'property' + PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer: ~ + PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer: ~ + PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer: ~ + PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer: ~ + PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer: ~ + + PhpCsFixer\Fixer\Basic\BracesFixer: + allow_single_line_closure: true + PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer: ~ + PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: + spacing: none + PhpCsFixer\Fixer\Operator\NewWithBracesFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer: + tags: + - method + - param + - property + - return + - throws + - type + - var + PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer: ~ + PhpCsFixer\Fixer\Operator\IncrementStyleFixer: ~ + PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: ~ + PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer: ~ + PhpCsFixer\Fixer\CastNotation\CastSpacesFixer: ~ + PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer: ~ + PhpCsFixer\Fixer\FunctionNotation\FunctionTypehintSpaceFixer: ~ + PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer: + comment_types: + - hash + PhpCsFixer\Fixer\ControlStructure\IncludeFixer: ~ + PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer: ~ + PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer: + elements: + - method + PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer: ~ + PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer: ~ + PhpCsFixer\Fixer\Phpdoc\NoBlankLinesAfterPhpdocFixer: ~ + PhpCsFixer\Fixer\Comment\NoEmptyCommentFixer: ~ + PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocSeparationFixer: ~ + PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer: ~ + PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer: + tokens: + - curly_brace_block + - extra + - parenthesis_brace_block + - square_brace_block + - throw + - use + PhpCsFixer\Fixer\NamespaceNotation\NoLeadingNamespaceWhitespaceFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer: ~ + PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer: ~ + PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer: ~ + PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer: ~ + PhpCsFixer\Fixer\ControlStructure\NoTrailingCommaInListCallFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\NoTrailingCommaInSinglelineArrayFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\TrailingCommaInMultilineArrayFixer: ~ + PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer: ~ + PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\NormalizeIndexBraceFixer: ~ + PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocAnnotationWithoutDotFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocIndentFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocNoAccessFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocNoEmptyReturnFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocNoPackageFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocNoUselessInheritdocFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocReturnSelfReferenceFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocScalarFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocSingleLineVarSpacingFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocSummaryFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocToCommentFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocVarWithoutNameFixer: ~ + PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer: ~ + PhpCsFixer\Fixer\ClassNotation\SelfAccessorFixer: ~ + PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer: ~ + PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer: ~ + PhpCsFixer\Fixer\Semicolon\SpaceAfterSemicolonFixer: ~ + PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer: ~ + PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\TrimArraySpacesFixer: ~ + PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer: ~ + PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer: + singleLine: true + PhpCsFixer\Fixer\Casing\MagicConstantCasingFixer: ~ + PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer: + use: echo + PhpCsFixer\Fixer\Import\NoLeadingImportSlashFixer: ~ + PhpCsFixer\Fixer\Import\NoUnusedImportsFixer: ~ + PhpCsFixer\Fixer\PhpUnit\PhpUnitFqcnAnnotationFixer: ~ + PhpCsFixer\Fixer\Phpdoc\PhpdocNoAliasTagFixer: ~ + PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer: ~ + PhpCsFixer\Fixer\NamespaceNotation\SingleBlankLineBeforeNamespaceFixer: ~ + + # new since PHP-CS-Fixer 2.6 + PhpCsFixer\Fixer\ControlStructure\NoUnneededCurlyBracesFixer: ~ + PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer: ~ + PhpCsFixer\Fixer\Semicolon\SemicolonAfterInstructionFixer: ~ + PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer: ~ + + # new since 2.11 + PhpCsFixer\Fixer\Operator\StandardizeIncrementFixer: ~