Compare commits

...

147 Commits

Author SHA1 Message Date
5778c54ae0 Add missing initialization 2022-02-09 10:19:13 +01:00
9b65966d27 update composer.json 2021-05-28 11:53:54 +02:00
633e30ae47 Add flow registration validation support 2021-05-28 08:08:42 +02:00
Grégoire Passault
2f96c759ab
Merge pull request #223 from Gemorroj/patch-1
php 8 support
2021-04-20 09:20:37 +02:00
Gemorroj
2769e4791a
php 8 support
#222
2021-04-18 12:06:03 +03:00
Gregwar
5e434e1859 gregwar/captcha version bump 2021-01-09 01:01:13 +01:00
Gregwar
df6915eb5e README details 2020-04-28 10:45:36 +02:00
Gregwar
b7685e63a1 README indentation 2020-04-28 10:44:39 +02:00
Gregwar
15bee25e9c Indentation in README 2020-04-28 10:43:03 +02:00
Gregwar
3a4e31473a Adding some note about session_key option for multiple captcha on same
page
2020-04-17 16:13:37 +02:00
Gregwar
fec0ebb2f1 Autowire controller 2020-04-09 10:18:10 +02:00
Grégoire Passault
cdbe566acc
Merge pull request #212 from l-vo/bundle_auto_registration
Fix flex auto-registration
2020-03-02 11:00:37 +01:00
Laurent VOULLEMIER
93f9d3c1a7 Fix flex auto-registration 2020-02-29 20:31:09 +01:00
Gregwar
d4475118d0 Merge branch 'master' of github.com:Gregwar/CaptchaBundle 2020-01-14 11:15:40 +01:00
Gregwar
b8a129fc2a Adding controller class in services.yml 2020-01-14 11:14:42 +01:00
Grégoire Passault
fe4b0dea2b
Merge pull request #210 from alexander-schranz/patch-1
Fix compatibility table
2020-01-14 10:06:23 +01:00
Alexander Schranz
640acadeea
Fix compatibility table 2020-01-13 18:35:47 +01:00
Grégoire Passault
a22ba77f52
Merge pull request #208 from Olaf1989/symfony-5
Fully support Symfony 4 and 5
2020-01-08 16:31:01 +01:00
Olaf
459a108ee6 docs (Readme) update README.md 2020-01-03 01:07:49 +01:00
Olaf
3691a30240 chore (Packages) allow Symfony 4 and PHP 7.1 2020-01-03 01:01:41 +01:00
Olaf
2012808bc6 docs (Readme) update README.md 2020-01-03 00:43:31 +01:00
Olaf
2b62be4af1 fix (Symfony) use Symfony 5 web_path 2020-01-03 00:42:56 +01:00
Olaf
3f25597f94 Merge branch 'symfony-5' of https://github.com/Olaf1989/CaptchaBundle into symfony-5 2020-01-03 00:17:34 +01:00
Olaf
478c64633e fix (ECS) apply coding standard 2020-01-03 00:12:44 +01:00
Olaf
2ed4f74954 chore (ECS) add easy coding standard 2020-01-03 00:09:09 +01:00
Olaf
60c0e04366
Delete composer.lock 2020-01-03 00:05:31 +01:00
Olaf
61a8561dd6 fix (Captcha) allow null value for bypassCode 2020-01-03 00:04:18 +01:00
Olaf
5515c25872 chore (Symfony) use Symfony 5 + strict typing
Update Symfony version to 5
Use strict typing
2019-12-30 00:27:20 +01:00
Gregwar
eeb01bdca5 Typo 2019-12-02 10:24:14 +01:00
Grégoire Passault
678459f58f
Merge pull request #205 from tacman/patch-1
Support Symfony 5, drop support for Symfony 2
2019-12-02 10:23:50 +01:00
tacman
1781a6aa62
Support Symfony 5, drop support for Symfony 2 2019-12-01 08:00:17 -05:00
Grégoire Passault
3ccfdf1c93
Merge pull request #200 from adamwojs/fix_deprecated_tree_builder_root_call
Fixed deprecated TreeBuilder::root method call in SF 4
2019-09-23 15:07:46 +02:00
Grégoire Passault
b703ed1a0c
Merge pull request #201 from adamwojs/fix_deprecated_spacelesss_tag
Removed deprecated spaceless tag
2019-09-23 15:07:20 +02:00
Adam Wójs
25de43ac90 Removed deprecated spaceless tag 2019-09-22 13:59:41 +02:00
Adam Wójs
1b4835eb4d Fixed deprecated TreeBuilder::root method call in SF 4 2019-09-22 13:10:16 +02:00
Grégoire Passault
be1ce45060
Merge pull request #196 from ferdynator/master
Fixes deprecation warnings in Symfony 4.2
2019-08-15 18:04:18 +02:00
Frederik Schubert
0f6cd70920
Fixed deprecation warning 2019-01-23 11:01:56 +01:00
Frederik Schubert
754310f488
Fixed deprecation warning 2019-01-23 11:01:17 +01:00
Grégoire Passault
c2d5468556
Merge pull request #172 from cengizhancaliskan/master
Support of multiple instance
2018-11-20 11:41:34 +01:00
Grégoire Passault
980afdc10a
Merge pull request #187 from mandalor-development/master
Changed template reference
2018-04-24 11:22:05 +02:00
Mandalor-Development
791128c0fd Changed template reference
According to:
https://symfony.com/doc/current/templating.html#referencing-templates-in-a-bundle

Fixed error:
[critical] Uncaught PHP Exception Twig_Error_Loader: "Unable to find template "GregwarCaptchaBundle::captcha.html.twig" (looked into: /[path]/templates, /[path]/templates, /[path]/vendor/symfony/twig-bridge/Resources/views/Form)." at /[path]/templates/form.html.twig line 17
2018-02-28 15:15:55 +01:00
Grégoire Passault
639430383f
Merge pull request #180 from andreybolonin/master
add sf 4.0 support
2017-12-28 12:21:03 +01:00
andreybolonin
8e98c5c0ab add public services 2017-12-28 12:30:19 +02:00
andreybolonin
539884cd5d add sf 4.0 support 2017-11-27 18:08:24 +02:00
Gregwar
8ce4adb1b1 Adding background_images in persisted options (fixes #175) 2017-10-02 11:12:17 +02:00
Gregwar
b787a8002e Rising default quality to 50 2017-09-27 12:01:02 +02:00
Cengizhan Çalışkan
ba9c0e6166 Change session key for as_url option 2017-03-27 22:32:00 +03:00
Cengizhan Çalışkan
25b8840f2a Support of multiple instance 2017-03-19 18:40:34 +03:00
Grégoire Passault
045ba7e67e Merge pull request #150 from dprolife/patch-1
Update composer.json
2017-02-23 10:26:22 +01:00
Gregwar
18c85d3a4f donate 2016-10-24 12:05:50 +02:00
Gregwar
f6c45045f0 Adding class captcha_image on the <img> captcha tag (see #160) 2016-09-21 10:36:55 +02:00
Gregwar
f95a951b26 Detail 2016-08-05 20:07:20 +02:00
Grégoire Passault
e1ed228b8b Merge pull request #168 from linnaea/patch-1
Quote parameter references in services.yml
2016-05-30 12:28:28 +02:00
Linnaea Von Lavia
0b3495a081 Quote parameter references in services.yml
Not quoting a scalar starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.
2016-05-28 22:40:00 +08:00
Grégoire Passault
53c25b2e9a Merge pull request #163 from hackzilla/master
Update CaptchaType.php
2016-02-02 23:40:33 +01:00
Daniel Platt
fcf8c4fd01 Update CaptchaType.php
add getBlockPrefix for Symfony3 compatibility.
2016-02-02 22:15:18 +00:00
Grégoire Passault
e91cb1a3b7 Merge pull request #139 from RicoVZ/patch-1
Replaced usage of "pattern" with "path"
2015-12-30 19:19:50 +01:00
dprolife
1f6c80c326 Update composer.json
Fix symfony requirements
2015-12-17 22:51:31 +01:00
Gregwar
f06ff4d2c2 Clarification 2015-12-13 12:12:45 +01:00
Gregwar
42cb26794d Getting compatible with php>=5.3.9 2015-12-13 12:10:14 +01:00
Gregwar
e10494a767 Using | instead of || 2015-12-13 12:03:17 +01:00
Gregwar
8682eee873 README 2015-12-11 10:02:21 +01:00
Gregwar
c508d510ff README (see #148) 2015-12-11 10:01:40 +01:00
Gregwar
d328f215b2 Merge branch 'master' of github.com:Gregwar/CaptchaBundle 2015-12-07 14:25:30 +01:00
Gregwar
a26f03cc93 Using php 5.5 as a dependency because of ::class (see #148) 2015-12-07 14:25:06 +01:00
Gregwar
1862776c9a Supporting v3 2015-12-06 23:20:09 +01:00
Gregwar
c989422a82 Clarifying readme 2015-12-06 23:10:05 +01:00
Gregwar
52107b0c32 Using ::class instead of type alias (working w/ sf3, see #148) 2015-12-06 23:07:05 +01:00
Grégoire Passault
e335e2a924 Merge pull request #149 from Restless-ET/patch-1
Fix YAML syntax in services.yml file
2015-12-05 14:22:11 +01:00
Restless-ET
0971f224f4 Fix YAML syntax in services.yml file
The '@' character is supposed to be a reserved indicator for YAML. Therefore when using it at the beginning of a string (as in this case) we should enclose it in quotes.
http://yaml.org/spec/1.2/spec.html#id2774228

Also, since Symfony 2.8 this kind of usage is already marked as deprecated: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#yaml
2015-12-05 00:52:50 +00:00
Grégoire Passault
29610bb574 Merge pull request #145 from verschoof/patch-1
Update README.md
2015-10-29 11:14:06 +01:00
Mitchel
018fdd3f35 Update README.md
Added composer require instead of the manual way.
Composer require will search the latest version and install it for you.
2015-10-29 10:15:34 +01:00
Grégoire Passault
476530a212 Merge pull request #141 from max-kovpak/patch-2
POST_BIND deprecated
2015-09-25 09:21:54 +02:00
Max Kovpak
87d38d98a4 Update CaptchaType.php
Checkout version
2015-08-26 11:26:01 +03:00
Max Kovpak
3cc4b072c3 POST_BIND deprecated
POST_BIND deprecated since version 2.3, to be removed in 3.0. Use POST_SUBMIT instead.
2015-08-25 17:15:15 +03:00
Grégoire Passault
0f5e9870f1 Merge pull request #140 from max-kovpak/patch-1
Make it more unique
2015-08-25 16:06:15 +02:00
Max Kovpak
c844cbcdbc Update CaptchaGenerator.php 2015-08-25 17:05:28 +03:00
Max Kovpak
50405a74a1 Make it more unique
If you have 2 forms on one page time will be not unique
2015-08-25 16:57:49 +03:00
Grégoire Passault
84760b0a9f Merge pull request #136 from StudioMaX/patch-1
Add configureOptions method to form types for SF 2.7
2015-08-18 20:19:33 +02:00
RicoVZ
ef281889ab Replaced usage of "pattern" with "path"
As described in issue #135
2015-08-18 09:48:41 +02:00
Grégoire Passault
8468f93194 Merge pull request #81 from ChessCom/master
Add the option of custom background images for the captcha
2015-08-13 12:30:47 +02:00
Grégoire Passault
fe1102f5c6 Merge pull request #138 from Burakhan/master
Adding Turkish language translate
2015-08-10 12:05:33 +02:00
Burakhan
f1fdfc142f Adding Turkish language translate 2015-08-10 11:15:05 +03:00
StudioMaX
2e49f50c1a Add configureOptions method to form types for SF 2.7 2015-07-09 22:19:21 +06:00
Grégoire Passault
8d3ee7334f Merge pull request #130 from amouhzi/patch-1
Arabic translations: gregwar_captcha.ar.yml
2015-05-28 00:16:52 +02:00
Grégoire Passault
805e77f24a Merge pull request #131 from amouhzi/patch-2
Arabic translations: validators.ar.yml
2015-05-28 00:15:59 +02:00
Hassan Amouhzi
adab98ad84 Arabic translations: validators.ar.yml 2015-05-27 22:49:51 +02:00
Hassan Amouhzi
4040d06508 Arabic translations: gregwar_captcha.ar.yml 2015-05-27 22:45:26 +02:00
Gregwar
448b812f65 Fixing captcha url (broken in #128, see also #129) 2015-05-25 11:41:13 +02:00
Grégoire Passault
4aba359e71 Merge pull request #128 from piotrantosik/master
Don't cache captcha image
2015-05-22 18:00:07 +02:00
Piotr Antosik
8c39274fa4 don't cache captcha image 2015-05-22 15:01:00 +02:00
Ivan Lackovic
232168d408 remove comments 2015-05-19 20:20:14 +02:00
Ivan Lackovic
6a147a2ea3 Merge remote-tracking branch 'upstream/master' 2015-05-13 16:24:05 +02:00
Gregwar
c221d9cb42 Merge branch 'master' of github.com:Gregwar/CaptchaBundle 2015-05-13 08:42:05 +02:00
Gregwar
7574ad33f1 Updating to 1.1 2015-05-13 08:41:47 +02:00
Grégoire Passault
d80ff1959b Merge pull request #125 from cordoval/minor-improvement
minor updates
2015-05-13 08:40:54 +02:00
Gregwar
694994c3c2 Fixing composer.json (broken in #126) 2015-05-13 08:39:21 +02:00
Grégoire Passault
01429c4486 Merge pull request #126 from cordoval/move-to-psr4
move to psr4
2015-05-13 08:34:02 +02:00
Luis Cordova
6032e5df52 move to psr4 2015-05-12 20:16:59 -05:00
Luis Cordova
d77e0b1f2a minor updates 2015-05-12 20:12:49 -05:00
Grégoire Passault
a4176fcf74 Merge pull request #116 from kuborgh/patch-404
fixed uncached 404
2015-02-04 16:57:21 +01:00
Ben Zörb
909d1a3773 fixed uncached 404 2015-02-04 09:29:14 +01:00
Gregwar
d6c6de0f83 Merge branch 'master' of github.com:Gregwar/CaptchaBundle
Conflicts:
	composer.json
2015-01-27 17:12:52 +01:00
Gregwar
ac95e1d4b1 v1.0.12 2015-01-27 17:11:57 +01:00
Grégoire Passault
c844d0a440 Merge pull request #113 from waldermort/patch-1
Fix: Bypass code incorrectly compared
2015-01-13 14:43:37 +01:00
Grégoire Passault
f20fc3c3b7 Merge pull request #114 from waldermort/patch-2
Fix: Numeric bypass code defaults to integer type
2015-01-13 14:42:45 +01:00
waldermort
0cb34f33b0 Fix: Numeric bypass code defaults to integer type
When adding a numeric only bypass code into config.yml, it is treated as an integer which causes validation to fail. A workaround is to surround the parameter with double quotes but many users may not be aware of this. This fix will explicitly convert it to a string.
2015-01-13 20:16:15 +08:00
waldermort
843f367540 Fix: Bypass code incorrectly compared
When the bypass code is given the value of '0', PHP equates it to boolean false causing the validation to fail.
2015-01-13 20:10:53 +08:00
Grégoire Passault
94c5f0a03b Merge pull request #107 from Hast/translation/ukrainian
Added ukrainian translation
2014-09-26 21:07:06 +02:00
Alexandr Zagorulya
6a522b7043 Added ukrainian translation 2014-09-26 22:03:38 +03:00
Ivan Lackovic
3d1383e8ae Merge remote-tracking branch 'upstream/master' 2014-09-04 14:04:51 +02:00
Grégoire Passault
62e44cd388 Merge pull request #103 from kuborgh/cache
HTTP 1.1 equivalent to Pragma: no-cache
2014-08-27 16:12:32 +02:00
Hannes Giesenow
459901319c HTTP 1.1 equivalent to Pragma: no-cache
See http://stackoverflow.com/questions/10314174/difference-between-pragma-and-cache-control-headers for detailed explanation
2014-08-27 14:34:57 +02:00
Grégoire Passault
1c542e1164 Merge pull request #102 from kuborgh/cache
Added no-cache header
2014-08-27 13:06:49 +02:00
Hannes Giesenow
dc3e0c6495 Added no-cache header
This prevents Varnish from caching the captcha image
2014-08-27 12:29:12 +02:00
Grégoire Passault
bd208c45a8 Merge pull request #94 from piotrantosik/psr
update docblock, fix typos, improve composer.json
2014-08-19 12:28:19 +02:00
Piotr Antosik
9614209d83 update docblock, fix typos, improve composer.json 2014-08-19 12:19:27 +02:00
Grégoire Passault
90088c80fc Merge pull request #100 from stefan-bofirov-dnh/master
Added bulgarian translation
2014-08-19 10:12:21 +02:00
Stefan Bofirov
06c713fbb4 Added bulgarian translation 2014-08-17 16:17:41 +03:00
Gregwar
162a2a87cd Changing gcp to gcb 2014-07-31 16:41:27 +02:00
Grégoire Passault
fe3df8a640 Merge pull request #98 from Adezandee/master
[BUG] Fix session key variable naming
2014-07-31 11:40:52 -03:00
Arnaud Dezandee
b87b05e29d Fix session key variable naming 2014-07-29 19:03:41 +02:00
Grégoire Passault
cdf64984b7 Merge pull request #95 from piotrantosik/issue
fix multiple captcha on page
2014-07-24 18:07:26 -03:00
Piotr Antosik
458e7cafef fix multiple captcha on page 2014-07-21 14:46:14 +02:00
Grégoire Passault
ce96122ef2 Merge pull request #93 from aitboudad/patch-1
fixed typo.
2014-07-10 11:32:26 +02:00
Abdellatif AitBoudad
c4c69b0a47 fixed typo. 2014-07-10 10:30:57 +01:00
Grégoire Passault
6b573121a5 Merge pull request #92 from dypa/patch-1
Update CaptchaValidator.php
2014-07-03 10:55:24 +02:00
dypa
e34e191d32 Update CaptchaValidator.php
fix typo (lol)
2014-07-03 12:50:49 +04:00
Grégoire Passault
7dd05f5389 Merge pull request #88 from mseshachalam/patch-1
Patch 1
2014-05-14 11:55:23 +02:00
Rajini Kanth
de0d9408d6 corrected typos 2014-05-14 10:35:18 +05:30
Rajini Kanth
cb45fe2847 separated class names to parameters
Easier to override the services of this bundle without compiler pass. (http://symfony.com/doc/current/cookbook/bundles/override.html)
2014-05-14 10:32:02 +05:30
Gregwar
1fec709d05 Merge branch 'master' of github.com:Gregwar/CaptchaBundle 2014-05-07 17:19:30 +02:00
Gregwar
35cbc6226c Adding text & background color to persist options (see #18) 2014-05-07 17:18:57 +02:00
Grégoire Passault
7c38520965 Merge pull request #84 from piotrantosik/master
add polish translation
2014-04-07 10:15:46 +02:00
Piotr Antosik
277e3baff0 add pl translation 2014-04-07 09:41:36 +02:00
Ivan Lackovic
798f29e635 Merge remote-tracking branch 'upstream/master'
Conflicts:
	DependencyInjection/Configuration.php
2014-03-19 16:27:04 +01:00
Gregwar
f2e07fe6f2 Merge branch 'master' of github.com:Gregwar/CaptchaBundle 2014-03-19 16:15:10 +01:00
Gregwar
ab786e3b0e Updating to v1.0.11 2014-03-19 16:14:56 +01:00
Grégoire Passault
f206bb66cc Merge pull request #80 from gondo/master
added Czech translation
2014-03-06 17:23:06 +01:00
gondo
3340af5c43 Create validators.cs.yml 2014-03-06 16:24:41 +01:00
gondo
bc3fdda50b Rename gregwar_captcha.cz.yml to gregwar_captcha.cs.yml 2014-03-06 16:22:57 +01:00
gondo
b2340539d2 Create gregwar_captcha.cz.yml 2014-03-06 16:22:28 +01:00
lackovic10
34a84af209 README.md - updated docs, added background images and ignore all effects descriptions 2013-09-26 21:22:02 +02:00
lackovic10
3ad62e4d0d added ignore_all_effects to configuration 2013-09-26 21:10:02 +02:00
lackovic10
a16743a230 added background_images to configuration 2013-09-26 20:38:39 +02:00
lackovic10
4f46a609ba Revert "composer.json - updated to use a gregwar/captcha fork (chesscom)"
This reverts commit b085af6e0078d216d048422bb5816ce06ae1bd21.
2013-09-26 17:28:48 +02:00
lackovic10
b085af6e00 composer.json - updated to use a gregwar/captcha fork (chesscom) 2013-09-25 20:53:52 +02:00
27 changed files with 531 additions and 395 deletions

View File

@ -1,31 +1,37 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\Controller; namespace Gregwar\CaptchaBundle\Controller;
use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/** /**
* Generates a captcha via a URL * Generates a captcha via a URL.
* *
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com> * @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
*/ */
class CaptchaController extends Controller class CaptchaController extends AbstractController
{ {
/** /** @var CaptchaGenerator */
* Action that is used to generate the captcha, save its code, and stream the image private $captchaGenerator;
*
* @param \Symfony\Component\HttpFoundation\Request $request /** @var array */
* @param string $key private $config;
*
* @return \Symfony\Component\HttpFoundation\Response public function __construct(CaptchaGenerator $captchaGenerator, array $config)
*/
public function generateCaptchaAction(Request $request, $key)
{ {
$options = $this->container->getParameter('gregwar_captcha.config'); $this->captchaGenerator = $captchaGenerator;
$session = $this->get('session'); $this->config = $config;
$whitelistKey = $options['whitelist_key']; }
public function generateCaptchaAction(Request $request, string $key): Response
{
$session = $request->getSession();
$whitelistKey = $this->config['whitelist_key'];
$isOk = false; $isOk = false;
if ($session->has($whitelistKey)) { if ($session->has($whitelistKey)) {
@ -36,24 +42,35 @@ class CaptchaController extends Controller
} }
if (!$isOk) { if (!$isOk) {
throw $this->createNotFoundException('Unable to generate a captcha via an URL with this session key.'); return $this->error($this->config);
} }
/* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */
$generator = $this->container->get('gregwar_captcha.generator');
$persistedOptions = $session->get($key, array()); $persistedOptions = $session->get($key, array());
$options = array_merge($options, $persistedOptions); $options = array_merge($this->config, $persistedOptions);
$phrase = $generator->getPhrase($options); $phrase = $this->captchaGenerator->getPhrase($options);
$generator->setPhrase($phrase); $this->captchaGenerator->setPhrase($phrase);
$persistedOptions['phrase'] = $phrase; $persistedOptions['phrase'] = $phrase;
$session->set($key, $persistedOptions); $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('Content-type', 'image/jpeg');
$response->headers->set('Pragma', 'no-cache');
$response->headers->set('Cache-Control', 'no-cache');
return $response;
}
private function error(array $options): Response
{
$this->captchaGenerator->setPhrase('');
$response = new Response($this->captchaGenerator->generate($options));
$response->setStatusCode(428);
$response->headers->set('Content-type', 'image/jpeg');
$response->headers->set('Pragma', 'no-cache');
$response->headers->set('Cache-Control', 'no-cache');
return $response; return $response;
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\DependencyInjection; namespace Gregwar\CaptchaBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
@ -7,15 +9,10 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface class Configuration implements ConfigurationInterface
{ {
/** public function getConfigTreeBuilder(): TreeBuilder
* Generates the configuration tree.
*
* @return TreeBuilder
*/
public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder('gregwar_captcha');
$rootNode = $treeBuilder->root('gregwar_captcha'); $rootNode = $treeBuilder->getRootNode();
$rootNode $rootNode
->addDefaultsIfNotSet() ->addDefaultsIfNotSet()
@ -30,10 +27,10 @@ class Configuration implements ConfigurationInterface
->scalarNode('as_url')->defaultValue(false)->end() ->scalarNode('as_url')->defaultValue(false)->end()
->scalarNode('reload')->defaultValue(false)->end() ->scalarNode('reload')->defaultValue(false)->end()
->scalarNode('image_folder')->defaultValue('captcha')->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('gc_freq')->defaultValue(100)->end()
->scalarNode('expiration')->defaultValue(60)->end() ->scalarNode('expiration')->defaultValue(60)->end()
->scalarNode('quality')->defaultValue(30)->end() ->scalarNode('quality')->defaultValue(50)->end()
->scalarNode('invalid_message')->defaultValue('Bad code value')->end() ->scalarNode('invalid_message')->defaultValue('Bad code value')->end()
->scalarNode('bypass_code')->defaultValue(null)->end() ->scalarNode('bypass_code')->defaultValue(null)->end()
->scalarNode('whitelist_key')->defaultValue('captcha_whitelist_key')->end() ->scalarNode('whitelist_key')->defaultValue('captcha_whitelist_key')->end()
@ -44,11 +41,13 @@ class Configuration implements ConfigurationInterface
->scalarNode('interpolation')->defaultValue(true)->end() ->scalarNode('interpolation')->defaultValue(true)->end()
->arrayNode('text_color')->prototype('scalar')->end()->end() ->arrayNode('text_color')->prototype('scalar')->end()->end()
->arrayNode('background_color')->prototype('scalar')->end()->end() ->arrayNode('background_color')->prototype('scalar')->end()->end()
->arrayNode('background_images')->prototype('scalar')->end()->end()
->scalarNode('disabled')->defaultValue(false)->end() ->scalarNode('disabled')->defaultValue(false)->end()
->scalarNode('ignore_all_effects')->defaultValue(false)->end()
->scalarNode('session_key')->defaultValue('captcha')->end()
->end() ->end()
; ;
return $treeBuilder; return $treeBuilder;
} }
} }

View File

@ -1,24 +1,29 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\DependencyInjection; namespace Gregwar\CaptchaBundle\DependencyInjection;
use Exception;
use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\FileLocator;
/** /**
* Extension used to load the configuration, set parameters, and initialize the captcha view * Extension used to load the configuration, set parameters, and initialize the captcha view.
* *
* @author Gregwar <g.passault@gmail.com> * @author Gregwar <g.passault@gmail.com>
*/ */
class GregwarCaptchaExtension extends Extension class GregwarCaptchaExtension extends Extension
{ {
/** /**
* @param array $configs * @param array $configs
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container * @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 = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml'); $loader->load('services.yml');
@ -34,6 +39,6 @@ class GregwarCaptchaExtension extends Extension
$container->setParameter('gregwar_captcha.config.whitelist_key', $config['whitelist_key']); $container->setParameter('gregwar_captcha.config.whitelist_key', $config['whitelist_key']);
$resources = $container->getParameter('twig.form.resources'); $resources = $container->getParameter('twig.form.resources');
$container->setParameter('twig.form.resources', array_merge(array('GregwarCaptchaBundle::captcha.html.twig'), $resources)); $container->setParameter('twig.form.resources', array_merge(array('@GregwarCaptcha/captcha.html.twig'), $resources));
} }
} }

View File

@ -1,64 +1,54 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\Generator; namespace Gregwar\CaptchaBundle\Generator;
use Symfony\Component\Finder\Finder; use Gregwar\Captcha\CaptchaBuilder;
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Gregwar\Captcha\PhraseBuilder;
use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Routing\RouterInterface;
use Gregwar\Captcha\CaptchaBuilderInterface; use Gregwar\Captcha\CaptchaBuilderInterface;
use Gregwar\Captcha\PhraseBuilderInterface; use Gregwar\Captcha\PhraseBuilderInterface;
/** /**
* Uses configuration parameters to call the services that generate captcha images * Uses configuration parameters to call the services that generate captcha images.
* *
* @author Gregwar <g.passault@gmail.com> * @author Gregwar <g.passault@gmail.com>
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com> * @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
*/ */
class CaptchaGenerator class CaptchaGenerator
{ {
/** /** @var RouterInterface */
* @var \Symfony\Component\Routing\RouterInterface
*/
protected $router; protected $router;
/** /** @var CaptchaBuilder */
* @var CaptchaBuilder
*/
protected $builder; protected $builder;
/** /** @var PhraseBuilder */
* @var PhraseBuilder
*/
protected $phraseBuilder; protected $phraseBuilder;
/** /** @var ImageFileHandler */
* @var ImageFileHandler
*/
protected $imageFileHandler; protected $imageFileHandler;
/** /**
* @param \Symfony\Component\Routing\RouterInterface $router * @param RouterInterface $router
* @param CaptchaBuilderInterface $builder * @param CaptchaBuilderInterface $builder
* @param ImageFileHandlerInterface $imageFileHandler * @param PhraseBuilderInterface $phraseBuilder
* @param ImageFileHandler $imageFileHandler
*/ */
public function __construct(RouterInterface $router, CaptchaBuilderInterface $builder, PhraseBuilderInterface $phraseBuilder, ImageFileHandler $imageFileHandler) public function __construct(
{ RouterInterface $router,
$this->router = $router; CaptchaBuilderInterface $builder,
$this->builder = $builder; PhraseBuilderInterface $phraseBuilder,
$this->phraseBuilder = $phraseBuilder; ImageFileHandler $imageFileHandler
$this->imageFileHandler = $imageFileHandler; ) {
$this->router = $router;
$this->builder = $builder;
$this->phraseBuilder = $phraseBuilder;
$this->imageFileHandler = $imageFileHandler;
} }
/** public function getCaptchaCode(array &$options): string
* Get the captcha URL, stream, or filename that will go in the image's src attribute
*
* @param $key
* @param array $options
*
* @return array
*/
public function getCaptchaCode(array &$options)
{ {
$this->builder->setPhrase($this->getPhrase($options)); $this->builder->setPhrase($this->getPhrase($options));
@ -71,27 +61,21 @@ class CaptchaGenerator
// Returns the image generation URL // Returns the image generation URL
if ($options['as_url']) { if ($options['as_url']) {
return $this->router->generate('gregwar_captcha.generate_captcha', array('key' => $options['session_key'])); 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));
} }
/** public function setPhrase(string $phrase): void
* Sets the phrase to the builder
*/
public function setPhrase($phrase)
{ {
$this->builder->setPhrase($phrase); $this->builder->setPhrase($phrase);
} }
/** public function generate(array &$options): string
* @param string $key
* @param array $options
*
* @return string
*/
public function generate(array &$options)
{ {
$this->builder->setDistortion($options['distortion']); $this->builder->setDistortion($options['distortion']);
@ -99,7 +83,7 @@ class CaptchaGenerator
$this->builder->setMaxBehindLines($options['max_behind_lines']); $this->builder->setMaxBehindLines($options['max_behind_lines']);
if (isset($options['text_color']) && $options['text_color']) { 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'); throw new \RuntimeException('text_color should be an array of r, g and b');
} }
@ -108,7 +92,7 @@ class CaptchaGenerator
} }
if (isset($options['background_color']) && $options['background_color']) { 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'); throw new \RuntimeException('background_color should be an array of r, g and b');
} }
@ -120,6 +104,9 @@ class CaptchaGenerator
$fingerprint = isset($options['fingerprint']) ? $options['fingerprint'] : null; $fingerprint = isset($options['fingerprint']) ? $options['fingerprint'] : null;
$this->builder->setBackgroundImages($options['background_images']);
$this->builder->setIgnoreAllEffects($options['ignore_all_effects']);
$content = $this->builder->build( $content = $this->builder->build(
$options['width'], $options['width'],
$options['height'], $options['height'],
@ -141,13 +128,7 @@ class CaptchaGenerator
return $this->imageFileHandler->saveAsFile($content); return $this->imageFileHandler->saveAsFile($content);
} }
/** public function getPhrase(array &$options): string
* @param string $key
* @param array $options
*
* @return string
*/
public function getPhrase(array &$options)
{ {
// Get the phrase that we'll use for this image // Get the phrase that we'll use for this image
if ($options['keep_value'] && isset($options['phrase'])) { if ($options['keep_value'] && isset($options['phrase'])) {
@ -156,8 +137,7 @@ class CaptchaGenerator
$phrase = $this->phraseBuilder->build($options['length'], $options['charset']); $phrase = $this->phraseBuilder->build($options['length'], $options['charset']);
$options['phrase'] = $phrase; $options['phrase'] = $phrase;
} }
return $phrase; return $phrase;
} }
} }

View File

@ -1,11 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\Generator; namespace Gregwar\CaptchaBundle\Generator;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
/** /**
* Handles actions related to captcha image files including saving and garbage collection * Handles actions related to captcha image files including saving and garbage collection.
* *
* @author Gregwar <g.passault@gmail.com> * @author Gregwar <g.passault@gmail.com>
* @author Jeremy Livingston <jeremy@quizzle.com> * @author Jeremy Livingston <jeremy@quizzle.com>
@ -13,69 +15,61 @@ use Symfony\Component\Finder\Finder;
class ImageFileHandler class ImageFileHandler
{ {
/** /**
* Name of folder for captcha images * Name of folder for captcha images.
*
* @var string * @var string
*/ */
protected $imageFolder; protected $imageFolder;
/** /**
* Absolute path to public web folder * Absolute path to public web folder.
*
* @var string * @var string
*/ */
protected $webPath; protected $webPath;
/** /**
* Frequency of garbage collection in fractions of 1 * Frequency of garbage collection in fractions of 1.
*
* @var int * @var int
*/ */
protected $gcFreq; protected $gcFreq;
/** /**
* Maximum age of images in minutes * Maximum age of images in minutes.
*
* @var int * @var int
*/ */
protected $expiration; protected $expiration;
/** /**
* @param $imageFolder * @param string $imageFolder
* @param $webPath * @param string $webPath
* @param $gcFreq * @param string $gcFreq
* @param $expiration * @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->imageFolder = $imageFolder;
$this->webPath = $webPath; $this->webPath = $webPath;
$this->gcFreq = $gcFreq; $this->gcFreq = $gcFreq;
$this->expiration = $expiration; $this->expiration = $expiration;
} }
/** public function saveAsFile($contents): string
* Saves the provided image content as a file
*
* @param string $contents
*
* @return string
*/
public function saveAsFile($contents)
{ {
$this->createFolderIfMissing(); $this->createFolderIfMissing();
$filename = md5(uniqid()) . '.jpg'; $filename = md5(uniqid()).'.jpg';
$filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename; $filePath = $this->webPath.'/'.$this->imageFolder.'/'.$filename;
imagejpeg($contents, $filePath, 15); imagejpeg($contents, $filePath, 15);
return '/' . $this->imageFolder . '/' . $filename; return '/'.$this->imageFolder.'/'.$filename;
} }
/** public function collectGarbage(): bool
* Randomly runs garbage collection on the image directory
*
* @return bool
*/
public function collectGarbage()
{ {
if (!mt_rand(1, $this->gcFreq) == 1) { if (1 == !mt_rand(1, $this->gcFreq)) {
return false; return false;
} }
@ -83,24 +77,20 @@ class ImageFileHandler
$finder = new Finder(); $finder = new Finder();
$criteria = sprintf('<= now - %s minutes', $this->expiration); $criteria = sprintf('<= now - %s minutes', $this->expiration);
$finder->in($this->webPath . '/' . $this->imageFolder) $finder->in($this->webPath.'/'.$this->imageFolder)
->date($criteria); ->date($criteria);
foreach($finder->files() as $file) { foreach ($finder->files() as $file) {
unlink($file->getPathname()); unlink($file->getPathname());
} }
return true; return true;
} }
/** protected function createFolderIfMissing(): void
* Creates the folder if it doesn't exist
*/
protected function createFolderIfMissing()
{ {
if (!file_exists($this->webPath . '/' . $this->imageFolder)) { if (!file_exists($this->webPath.'/'.$this->imageFolder)) {
mkdir($this->webPath . '/' . $this->imageFolder, 0755); mkdir($this->webPath.'/'.$this->imageFolder, 0755);
} }
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle; namespace Gregwar\CaptchaBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Bundle\Bundle;

View File

@ -1,4 +1,4 @@
Copyright (c) <2011-2013> Grégoire Passault Copyright (c) <2011-2015> Grégoire Passault
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

166
README.md
View File

@ -1,109 +1,66 @@
Gregwar's CaptchaBundle Gregwar's CaptchaBundle
===================== =====================
The `GregwarCaptchaBundle` adds support for a "captcha" form type for the [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YUXRLWHQSWS6L)
Symfony2 form component.
The `GregwarCaptchaBundle` adds support for a captcha form type for the
Symfony form component.
It uses [gregwar/captcha](https://github.com/Gregwar/Captcha) as captcha generator, which is a separate standalone library that can be used for none-symfony projects.
Compatibility with Symfony
==========================
| CaptchaBundle | Symfony | PHP |
|:---------------:|:---------:|:--------:|
| 2.1.* | 4.* - 5.* | >= 7.1 |
| 2.0.* | 2.8 - 3.* | >= 5.3.9 |
| 1.* | 2.1 - 2.7 | >= 5.3.0 |
Important note: the master of this repository is containing current development
in order to work with Symfony 2.1. If you are using Symfony 2.0 please checkout
the 2.0 branch.
Installation Installation
============ ============
### Step 1: Download the GregwarCaptchaBundle ### Step 1: Download the GregwarCaptchaBundle
Ultimately, the GregwarCaptchaBundle files should be downloaded to the Use composer require to download and install the package.
'vendor/bundles/Gregwar/CaptchaBundle' directory. At the end of the installation, the bundle is automatically registered thanks to the Symfony recipe.
You can accomplish this several ways, depending on your personal preference.
The first method is the standard Symfony2 method.
***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 ``` bash
$ php bin/vendors install composer require gregwar/captcha-bundle
``` ```
***Using submodules*** If you don't use flex, register it manually:
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
```
***Using Composer***
Add the following to the "require" section of your `composer.json` file:
```
"gregwar/captcha-bundle": "dev-master"
```
And update your dependencies
### 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
<?php
// app/autoload.php
$loader->registerNamespaces(array(
// ...
'Gregwar' => __DIR__.'/../vendor/bundles',
));
```
### Step 3: Enable the bundle
Finally, enable the bundle in the kernel:
```php ```php
<?php <?php
// app/appKernel.php // config/bundles.php
return [
public function registerBundles() // ...
{ Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true]
$bundles = array( ];
// ...
new Gregwar\CaptchaBundle\GregwarCaptchaBundle(),
);
}
``` ```
Configuration Configuration
============= =============
Add the following configuration to your `app/config/config.yml`: If you need to customize the global bundle configuration, you can create a `/config/packages/gregwar_captcha.yaml` file with your configuration:
``` yaml
gregwar_captcha: ~ gregwar_captcha:
width: 160
height: 50
```
Usage Usage
===== =====
You can use the "captcha" type in your forms this way: You can use the "captcha" type in your forms this way:
```php ``` php
<?php <?php
// ... use Gregwar\CaptchaBundle\Type\CaptchaType;
$builder->add('captcha', 'captcha'); // That's all ! // ...
// ... $builder->add('captcha', CaptchaType::class); // That's all !
// ...
``` ```
Note that the generated image will, by default, be embedded in the HTML document Note that the generated image will, by default, be embedded in the HTML document
@ -115,7 +72,7 @@ Options
You can define the following configuration options globally: 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") * **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) * **gc_freq**: frequency of garbage collection in fractions of 1 (default=100)
* **expiration**: maximum lifetime of captcha image files in minutes (default=60) * **expiration**: maximum lifetime of captcha image files in minutes (default=60)
@ -126,7 +83,7 @@ You can define the following configuration options globally or on the CaptchaTyp
* **disabled**: disable globally the CAPTCHAs (can be useful in dev environment), it will * **disabled**: disable globally the CAPTCHAs (can be useful in dev environment), it will
still appear but won't be editable and won't be checked still appear but won't be editable and won't be checked
* **length**: the length of the captcha (number of chars, default 5) * **length**: the length of the captcha (number of chars, default 5)
* **quality**: jpeg quality of captchas (default=15) * **quality**: jpeg quality of captchas (default=30)
* **charset**: the charset used for code generation (default=abcdefhjkmnprstuvwxyz23456789) * **charset**: the charset used for code generation (default=abcdefhjkmnprstuvwxyz23456789)
* **font**: the font to use (default is random among some pre-provided fonts), this should be an absolute path * **font**: the font to use (default is random among some pre-provided fonts), this should be an absolute path
* **keep_value**: the value will be the same until the form is posted, even if the page is refreshed (default=true) * **keep_value**: the value will be the same until the form is posted, even if the page is refreshed (default=true)
@ -141,27 +98,32 @@ You can define the following configuration options globally or on the CaptchaTyp
* **max_front_lines**, **max_behind_lines**: the maximum number of lines to draw on top/behind the image. `0` will draw no lines; `null` will use the default algorithm (the * **max_front_lines**, **max_behind_lines**: the maximum number of lines to draw on top/behind the image. `0` will draw no lines; `null` will use the default algorithm (the
number of lines depends on the size of the image). (default=null) number of lines depends on the size of the image). (default=null)
* **background_color**: sets the background color, if you want to force it, this should be an array of r,g &b, for instance [255, 255, 255] will force the background to be white * **background_color**: sets the background color, if you want to force it, this should be an array of r,g &b, for instance [255, 255, 255] will force the background to be white
* **background_images**: Sets custom user defined images as the captcha background (1 image is selected randomly). It is recommended to turn off all the effects on the image (ignore_all_effects). The full paths to the images must be passed.
* **interpolation**: enable or disable the interpolation on the captcha * **interpolation**: enable or disable the interpolation on the captcha
* **ignore_all_effects**: Recommended to use when setting background images, will disable all image effects.
* **session_key**, if you want to host multiple CAPTCHA on the same page, you might have different session keys to ensure proper storage of the clear phrase for those different forms
Example : Example :
```php ``` php
<?php <?php
// ... use Gregwar\CaptchaBundle\Type\CaptchaType;
$builder->add('captcha', 'captcha', array( // ...
'width' => 200, $builder->add('captcha', CaptchaType::class, array(
'height' => 50, 'width' => 200,
'length' => 6, 'height' => 50,
)); 'length' => 6,
));
``` ```
You can also set these options for your whole application using the `gregwar_captcha` You can also set these options for your whole application using the `gregwar_captcha`
configuration entry in your `config.yml` file: configuration entry in your `config.yml` file:
``` yaml
gregwar_captcha: gregwar_captcha:
width: 200 width: 200
height: 50 height: 50
length: 6 length: 6
```
Translation Translation
=========== ===========
@ -170,16 +132,20 @@ The messages are using the translator, you can either change the `invalid_messag
As URL As URL
============ ============
To use a URL to generate a captcha image, you must add the bundle's routing configuration to your app/routing.yml file: To use a URL to generate a captcha image, you must add the bundle's routing configuration to your `config/routes.yaml` file:
gregwar_captcha_routing: ``` yaml
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml" gregwar_captcha_routing:
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
```
This will use the bundle's route of "/generate-captcha/{key}" to handle the generation. If this route conflicts with an application route, you can prefix the bundle's routes when you import: This will use the bundle's route of `/generate-captcha/{key}` to handle the generation. If this route conflicts with an application route, you can prefix the bundle's routes when you import:
gregwar_captcha_routing: ``` yaml
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml" gregwar_captcha_routing:
prefix: /_gcb resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
prefix: /_gcb
```
Since the session key is transported in the URL, it's also added in another session array, under the `whitelist_key` key, for security reasons Since the session key is transported in the URL, it's also added in another session array, under the `whitelist_key` key, for security reasons
@ -190,7 +156,7 @@ The widget support the standard Symfony theming, see the [documentation](http://
The default rendering is: The default rendering is:
```html ``` twig
{% block captcha_widget %} {% block captcha_widget %}
{% spaceless %} {% spaceless %}
<img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" /> <img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />

View File

@ -1,3 +1,3 @@
gregwar_captcha.generate_captcha: gregwar_captcha.generate_captcha:
pattern: /generate-captcha/{key} path: /generate-captcha/{key}
defaults: { _controller: GregwarCaptchaBundle:Captcha:generateCaptcha } defaults: { _controller: Gregwar\CaptchaBundle\Controller\CaptchaController::generateCaptchaAction }

View File

@ -1,32 +1,58 @@
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
gregwar_captcha.captcha_builder.class: Gregwar\Captcha\CaptchaBuilder
gregwar_captcha.phrase_builder.class: Gregwar\Captcha\PhraseBuilder
services: services:
captcha.type: Gregwar\CaptchaBundle\Controller\CaptchaController:
class: Gregwar\CaptchaBundle\Type\CaptchaType public: true
alias: 'gregwar_captcha.controller'
gregwar_captcha.controller:
class: '%gregwar_captcha.controller.class%'
public: true
arguments: arguments:
- @session - '@gregwar_captcha.generator'
- @gregwar_captcha.generator - '%gregwar_captcha.config%'
- @translator autowire: true
- %gregwar_captcha.config%
# captcha.type:
gregwar_captcha.type:
class: '%gregwar_captcha.captcha_type.class%'
public: true
arguments:
- '@session'
- '@gregwar_captcha.generator'
- '@translator'
- '%gregwar_captcha.config%'
tags: tags:
- { name: form.type, alias: captcha } - { name: form.type, alias: captcha }
gregwar_captcha.generator: gregwar_captcha.generator:
class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator class: '%gregwar_captcha.captcha_generator.class%'
public: true
arguments: arguments:
- @router - '@router'
- @gregwar_captcha.captcha_builder - '@gregwar_captcha.captcha_builder'
- @gregwar_captcha.phrase_builder - '@gregwar_captcha.phrase_builder'
- @gregwar_captcha.image_file_handler - '@gregwar_captcha.image_file_handler'
gregwar_captcha.image_file_handler: gregwar_captcha.image_file_handler:
class: Gregwar\CaptchaBundle\Generator\ImageFileHandler class: '%gregwar_captcha.image_file_handler.class%'
public: true
arguments: arguments:
- %gregwar_captcha.config.image_folder% - '%gregwar_captcha.config.image_folder%'
- %gregwar_captcha.config.web_path% - '%gregwar_captcha.config.web_path%'
- %gregwar_captcha.config.gc_freq% - '%gregwar_captcha.config.gc_freq%'
- %gregwar_captcha.config.expiration% - '%gregwar_captcha.config.expiration%'
gregwar_captcha.captcha_builder: gregwar_captcha.captcha_builder:
class: Gregwar\Captcha\CaptchaBuilder class: '%gregwar_captcha.captcha_builder.class%'
public: true
gregwar_captcha.phrase_builder: gregwar_captcha.phrase_builder:
class: Gregwar\Captcha\PhraseBuilder class: '%gregwar_captcha.phrase_builder.class%'
public: true

View File

@ -0,0 +1 @@
Renew: تجديد

View File

@ -0,0 +1 @@
Renew: Обнови

View File

@ -0,0 +1 @@
Renew: Obnovit

View File

@ -0,0 +1 @@
Renew: Przeładuj

View File

@ -0,0 +1 @@
Renew: Yenile

View File

@ -0,0 +1 @@
Renew: Оновити

View File

@ -0,0 +1 @@
Bad code value: الرمز غير متطابق

View File

@ -0,0 +1 @@
Bad code value: Грешен код

View File

@ -0,0 +1 @@
Bad code value: Špatný kontrolní kód

View File

@ -0,0 +1 @@
Bad code value: Kod jest niepoprawny

View File

@ -0,0 +1 @@
Bad code value: Kod eşleşmiyor

View File

@ -0,0 +1 @@
Bad code value: Невірний код

View File

@ -2,8 +2,8 @@
{% if is_human %} {% if is_human %}
- -
{% else %} {% else %}
{% spaceless %} {% apply spaceless %}
<img id="{{ image_id }}" src="{{ captcha_code }}" alt="" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" /> <img class="captcha_image" id="{{ image_id }}" src="{{ captcha_code }}" alt="" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />
{% if reload %} {% if reload %}
<script type="text/javascript"> <script type="text/javascript">
function reload_{{ image_id }}() { function reload_{{ image_id }}() {
@ -14,7 +14,6 @@
<a class="captcha_reload" href="javascript:reload_{{ image_id }}();">{{ 'Renew'|trans({}, 'gregwar_captcha') }}</a> <a class="captcha_reload" href="javascript:reload_{{ image_id }}();">{{ 'Renew'|trans({}, 'gregwar_captcha') }}</a>
{% endif %} {% endif %}
{{ form_widget(form) }} {{ form_widget(form) }}
{% endspaceless %} {% endapply %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -1,155 +1,142 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\Type; namespace Gregwar\CaptchaBundle\Type;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvents;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Gregwar\CaptchaBundle\Validator\CaptchaValidator; use Gregwar\CaptchaBundle\Validator\CaptchaValidator;
use Gregwar\CaptchaBundle\Generator\CaptchaGenerator; use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
/** /**
* Captcha type * Captcha type.
* *
* @author Gregwar <g.passault@gmail.com> * @author Gregwar <g.passault@gmail.com>
*/ */
class CaptchaType extends AbstractType class CaptchaType extends AbstractType
{ {
/** const SESSION_KEY_PREFIX = '_captcha_';
* @var \Symfony\Component\HttpFoundation\Session\SessionInterface
*/ /** @var SessionInterface */
protected $session; protected $session;
/** /** @var CaptchaGenerator */
* The session key
* @var string
*/
protected $key = null;
/**
* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator
*/
protected $generator; protected $generator;
/** /** @var TranslatorInterface */
* @var TranslatorInterface
*/
protected $translator; protected $translator;
/** /** @var array */
* Options
* @var array
*/
private $options = array(); private $options = array();
/** /**
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session * @param SessionInterface $session
* @param \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator * @param CaptchaGenerator $generator
* @param array $options * @param TranslatorInterface $translator
* @param array $options
*/ */
public function __construct(SessionInterface $session, CaptchaGenerator $generator, TranslatorInterface $translator, $options) public function __construct(SessionInterface $session, CaptchaGenerator $generator, TranslatorInterface $translator, $options)
{ {
$this->session = $session; $this->session = $session;
$this->generator = $generator; $this->generator = $generator;
$this->translator = $translator; $this->translator = $translator;
$this->options = $options; $this->options = $options;
} }
/** /**
* @param \Symfony\Component\Form\FormBuilderInterface $builder * {@inheritdoc}
* @param array $options
*/ */
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$this->key = 'gcb_'.$builder->getForm()->getName();
$validator = new CaptchaValidator( $validator = new CaptchaValidator(
$this->translator, $this->translator,
$this->session, $this->session,
$this->key, sprintf('%s%s', self::SESSION_KEY_PREFIX, $options['session_key']),
$options['invalid_message'], $options['invalid_message'],
$options['bypass_code'], $options['bypass_code'],
$options['humanity'] $options['humanity'],
$options['request']
); );
$builder->addEventListener(FormEvents::POST_BIND, array($validator, 'validate')); $builder->addEventListener(FormEvents::POST_SUBMIT, array($validator, 'validate'));
} }
/** /**
* @param \Symfony\Component\Form\FormView $view * {@inheritdoc}
* @param \Symfony\Component\Form\FormInterface $form
* @param array $options
*/ */
public function buildView(FormView $view, FormInterface $form, array $options) public function buildView(FormView $view, FormInterface $form, array $options)
{ {
$isHuman = false;
if ($options['reload'] && !$options['as_url']) { if ($options['reload'] && !$options['as_url']) {
throw new \InvalidArgumentException('GregwarCaptcha: The reload option cannot be set without as_url, see the README for more information'); throw new \InvalidArgumentException('GregwarCaptcha: The reload option cannot be set without as_url, see the README for more information');
} }
$sessionKey = sprintf('%s%s', self::SESSION_KEY_PREFIX, $options['session_key']);
$isHuman = false;
if ($options['humanity'] > 0) { if ($options['humanity'] > 0) {
$humanityKey = $this->key.'_humanity'; $humanityKey = sprintf('%s_humanity', $sessionKey);
if ($this->session->get($humanityKey, 0) > 0) { if ($this->session->get($humanityKey, 0) > 0) {
$isHuman = true; $isHuman = true;
} }
} }
if ($options['as_url']) { if ($options['as_url']) {
$key = $this->key;
$keys = $this->session->get($options['whitelist_key'], array()); $keys = $this->session->get($options['whitelist_key'], array());
if (!in_array($key, $keys)) { if (!in_array($sessionKey, $keys)) {
$keys[] = $key; $keys[] = $sessionKey;
} }
$this->session->set($options['whitelist_key'], $keys); $this->session->set($options['whitelist_key'], $keys);
$options['session_key'] = $this->key; $options['session_key'] = $sessionKey;
} }
$view->vars = array_merge($view->vars, array( $view->vars = array_merge($view->vars, array(
'captcha_width' => $options['width'], 'captcha_width' => $options['width'],
'captcha_height' => $options['height'], 'captcha_height' => $options['height'],
'reload' => $options['reload'], 'reload' => $options['reload'],
'image_id' => uniqid('captcha_'), 'image_id' => uniqid('captcha_'),
'captcha_code' => $this->generator->getCaptchaCode($options), 'captcha_code' => $this->generator->getCaptchaCode($options),
'value' => '', 'value' => '',
'is_human' => $isHuman 'is_human' => $isHuman,
)); ));
$persistOptions = array(); $persistOptions = array();
foreach (array('phrase', 'width', 'height', 'distortion', 'length', 'quality') as $key) { foreach (array('phrase', 'width', 'height', 'distortion', 'length',
'quality', 'background_color', 'background_images', 'text_color', ) as $key) {
$persistOptions[$key] = $options[$key]; $persistOptions[$key] = $options[$key];
} }
$this->session->set($this->key, $persistOptions); $this->session->set($sessionKey, $persistOptions);
} }
/** /**
* @param \Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver * {@inheritdoc}
*/ */
public function setDefaultOptions(OptionsResolverInterface $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$this->options['mapped'] = false; $this->options['mapped'] = false;
$this->options['request'] = null;
$resolver->setDefaults($this->options); $resolver->setDefaults($this->options);
} }
/** public function getParent(): string
* @return string
*/
public function getParent()
{ {
return 'text'; return TextType::class;
} }
/** public function getName(): string
* @return string {
*/ return $this->getBlockPrefix();
public function getName() }
public function getBlockPrefix(): string
{ {
return 'captcha'; return 'captcha';
} }

View File

@ -1,73 +1,88 @@
<?php <?php
declare(strict_types=1);
namespace Gregwar\CaptchaBundle\Validator; namespace Gregwar\CaptchaBundle\Validator;
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvent;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\HttpFoundation\Request;
/** /**
* Captcha validator * Captcha validator.
* *
* @author Gregwar <g.passault@gmail.com> * @author Gregwar <g.passault@gmail.com>
*/ */
class CaptchaValidator class CaptchaValidator
{ {
/** /** @var SessionInterface */
* @var \Symfony\Component\HttpFoundation\Session\SessionInterface
*/
private $session; private $session;
/** /**
* Session key to store the code * Session key to store the code.
*
* @var string
*/ */
private $key; private $key;
/** /**
* Error message text for non-matching submissions * Error message text for non-matching submissions.
*
* @var string
*/ */
private $invalidMessage; private $invalidMessage;
/** /**
* Configuration parameter used to bypass a required code match * Configuration parameter used to bypass a required code match.
*
* @var string
*/ */
private $bypassCode; private $bypassCode;
/** /**
* Number of form that the user can submit without captcha * Number of form that the user can submit without captcha.
*
* @var int * @var int
*/ */
private $humanity; private $humanity;
/** /**
* Translator * Translator.
*
* @var TranslatorInterface * @var TranslatorInterface
*/ */
private $translator; private $translator;
/** /**
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session * Request
* @param string $key *
* @param string $invalidMessage * @var Request
* @param string|null $bypassCode
*/ */
public function __construct(TranslatorInterface $translator, SessionInterface $session, $key, $invalidMessage, $bypassCode, $humanity) private $req;
{
$this->translator = $translator; public function __construct(
$this->session = $session; TranslatorInterface $translator,
$this->key = $key; SessionInterface $session,
$this->invalidMessage = $invalidMessage; string $key,
$this->bypassCode = $bypassCode; string $invalidMessage,
$this->humanity = $humanity; ?string $bypassCode,
int $humanity,
?Request $req
) {
$this->translator = $translator;
$this->session = $session;
$this->key = $key;
$this->invalidMessage = $invalidMessage;
$this->bypassCode = $bypassCode;
$this->humanity = $humanity;
$this->req = $req;
} }
/** public function validate(FormEvent $event): void
* @param FormEvent $event
*/
public function validate(FormEvent $event)
{ {
$form = $form = $event->getForm(); $form = $event->getForm();
$code = $form->getData(); $code = $form->getData();
$expectedCode = $this->getExpectedCode(); $expectedCode = $this->getExpectedCode();
@ -75,12 +90,13 @@ class CaptchaValidator
if ($this->humanity > 0) { if ($this->humanity > 0) {
$humanity = $this->getHumanity(); $humanity = $this->getHumanity();
if ($humanity > 0) { if ($humanity > 0) {
$this->updateHumanity($humanity-1); $this->updateHumanity($humanity - 1);
return; return;
} }
} }
if (!($code && 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'))); $form->addError(new FormError($this->translator->trans($this->invalidMessage, array(), 'validators')));
} else { } else {
if ($this->humanity > 0) { if ($this->humanity > 0) {
@ -88,15 +104,16 @@ class CaptchaValidator
} }
} }
$this->session->remove($this->key); if (null == $this->req || 1 < $this->req->get('flow_registration_step')) {
$this->session->remove($this->key);
if ($this->session->has($this->key . '_fingerprint')) { if ($this->session->has($this->key.'_fingerprint')) {
$this->session->remove($this->key . '_fingerprint'); $this->session->remove($this->key.'_fingerprint');
}
} }
} }
/** /**
* Retrieve the expected CAPTCHA code * Retrieve the expected CAPTCHA code.
* *
* @return mixed|null * @return mixed|null
*/ */
@ -112,51 +129,39 @@ class CaptchaValidator
} }
/** /**
* Retreive the humanity * Retrieve the humanity.
* *
* @return mixed|null * @return mixed|null
*/ */
protected function getHumanity() protected function getHumanity()
{ {
return $this->session->get($this->key . '_humanity', 0); return $this->session->get($this->key.'_humanity', 0);
} }
/** protected function updateHumanity(int $newValue): void
* Updates the humanity
*/
protected function updateHumanity($newValue)
{ {
if ($newValue > 0) { if ($newValue > 0) {
$this->session->set($this->key . '_humanity', $newValue); $this->session->set($this->key.'_humanity', $newValue);
} else { } else {
$this->session->remove($this->key . '_humanity'); $this->session->remove($this->key.'_humanity');
} }
return null;
} }
/** protected function niceize(string $code): string
* Process the codes
*
* @param $code
*
* @return string
*/
protected function niceize($code)
{ {
return strtr(strtolower($code), 'oil', '01l'); 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 string $code
* @param $expectedCode * @param string|null $expectedCode
* *
* @return bool * @return bool
*/ */
protected function compare($code, $expectedCode) protected function compare($code, $expectedCode): bool
{ {
return ($expectedCode && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode)); return null !== $expectedCode && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode);
} }
} }

View File

@ -1,9 +1,9 @@
{ {
"name": "gregwar/captcha-bundle", "name": "cadoles/captcha",
"type": "captcha-bundle", "type": "symfony-bundle",
"description": "Captcha bundle", "description": "Captcha bundle",
"keywords": ["symfony2", "captcha", "bot", "visual", "code", "security", "spam"], "keywords": ["symfony2", "symfony", "captcha", "bot", "visual", "code", "security", "spam"],
"homepage": "https://github.com/Gregwar/CaptchaBundle", "homepage": "https://github.com/Cadoles/CaptchaBundle",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
{ {
@ -17,13 +17,23 @@
} }
], ],
"require": { "require": {
"php": ">=5.3.0", "php": ">=7.1.3",
"gregwar/captcha": "v1.0.10" "ext-gd": "*",
"gregwar/captcha": "^1.1.9",
"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": { "autoload": {
"psr-0": { "psr-4": {
"Gregwar\\CaptchaBundle": "" "Gregwar\\CaptchaBundle\\": "/"
} }
}, },
"target-dir": "Gregwar/CaptchaBundle" "config": {
"sort-packages": true
},
"require-dev": {
"symplify/easy-coding-standard": "^6.1"
}
} }

138
ecs.yaml Normal file
View File

@ -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: ~