Compare commits

...

217 Commits
0.2.1 ... 3

Author SHA1 Message Date
github-actions
26936f33e4 Merge branch '3.4' into 3 2024-02-07 11:15:05 +00:00
Guy Sartorelli
5badc345de
TLN Update translations (#111) 2024-02-07 16:12:33 +13:00
github-actions
eb858ca76e Merge branch '3.4' into 3 2023-08-23 11:14:45 +00:00
Guy Sartorelli
19603c31bc
ENH Update translations (#101) 2023-08-21 13:16:40 +12:00
Steve Boyd
17411fbb95 Merge branch '3.4' into 3 2023-06-16 12:09:40 +12:00
Guy Sartorelli
404ae173d0
Merge pull request #98 from creative-commoners/pulls/3.4/tx-1686724855
ENH Update translations
2023-06-15 10:06:13 +12:00
Steve Boyd
afbcf59ec4 ENH Update translations 2023-06-14 18:40:55 +12:00
Guy Sartorelli
5742971245
Merge branch '3.4' into 3 2023-04-26 12:46:05 +12:00
Guy Sartorelli
23843cd97f
MNT Revert erroneous dependency changes (#95) 2023-03-28 17:02:59 +13:00
Maxime Rainville
6ef3acd518
Merge pull request #94 from creative-commoners/pulls/3.4/no-deprecations
FIX Don't use deprecated API
2023-03-28 11:18:04 +13:00
Guy Sartorelli
3f62dfd4a4
FIX Don't use deprecated API 2023-03-28 10:23:53 +13:00
Maxime Rainville
7c81d075d6
Merge pull request #93 from creative-commoners/pulls/3/dispatch-ci
MNT Use gha-dispatch-ci
2023-03-23 14:19:24 +13:00
Steve Boyd
04aefedeef MNT Use gha-dispatch-ci 2023-03-21 13:41:47 +13:00
Guy Sartorelli
754bcee5da
MNT Update development dependencies 2023-03-10 16:32:56 +13:00
Guy Sartorelli
4971ddf3cb
MNT Update release dependencies 2023-03-10 16:32:52 +13:00
Guy Sartorelli
9fd768d5ad
MNT Update development dependencies 2023-03-10 12:21:29 +13:00
Guy Sartorelli
4e3f68cdb1
Merge pull request #92 from creative-commoners/pulls/3/tx-1678080129
ENH Update translations
2023-03-08 10:32:21 +13:00
Steve Boyd
c5d644eb71 ENH Update translations 2023-03-06 18:22:09 +13:00
Maxime Rainville
9a7ed5f091
Merge pull request #91 from creative-commoners/pulls/3/broken-build-cms4
MNT Explicitly test with default_spam_protector set to null
2023-01-26 17:01:35 +13:00
Steve Boyd
ed1d210f0d MNT Explicitly test with default_spam_protector set to null 2023-01-24 10:34:16 +13:00
Maxime Rainville
1c99bc8b92
Merge pull request #88 from creative-commoners/pulls/3/fix-invoke-method-on-null
FIX Check  value is not NULL
2023-01-17 10:25:18 +13:00
Sabina Talipova
2a55708ae8 FIX Check value is not NULL 2023-01-17 08:30:17 +13:00
Sabina Talipova
2c8fc03f2f
Merge pull request #85 from creative-commoners/pulls/3/stop-using-depr
API Stop using deprecated API
2022-12-05 16:40:37 +13:00
Steve Boyd
688b438e88 API Stop using deprecated API 2022-11-24 17:36:45 +13:00
Steve Boyd
fc36247598 Merge branch '3.3' into 3 2022-08-02 18:58:04 +12:00
Steve Boyd
0d7a57cedf Merge branch '3.2' into 3.3 2022-08-02 18:58:00 +12:00
Guy Sartorelli
0e5a2dc66d
Merge pull request #84 from creative-commoners/pulls/3.2/standardise-modules
MNT Standardise modules
2022-08-02 15:41:11 +12:00
Steve Boyd
3b0d8d08ed MNT Standardise modules 2022-08-01 16:23:11 +12:00
Steve Boyd
e028d76a34 Merge branch '3.3' into 3 2022-07-25 11:38:54 +12:00
Steve Boyd
4b7d18fe0e Merge branch '3.2' into 3.3 2022-07-25 11:38:51 +12:00
Guy Sartorelli
8eb3e05f76
Merge pull request #83 from creative-commoners/pulls/3.2/module-standards
MNT Use GitHub Actions CI
2022-07-15 17:20:32 +12:00
Steve Boyd
63fbae7413 MNT Use GitHub Actions CI 2022-07-05 19:07:16 +12:00
Steve Boyd
3e9f292082 Merge branch '3.3' into 3 2022-05-10 22:10:54 +12:00
Steve Boyd
af01b0ad01 Update translations 2022-05-04 13:29:41 +12:00
Guy Sartorelli
ed7dc6e38e
Merge pull request #82 from creative-commoners/pulls/3/php81
ENH PHP 8.1 compatibility
2022-04-26 17:57:43 +12:00
Steve Boyd
d452367262 ENH PHP 8.1 compatibility 2022-04-13 13:47:43 +12:00
Maxime Rainville
a2a21988ed Merge branch '3.2' into 3 2022-03-19 22:58:09 +13:00
Maxime Rainville
228f2a3058 Merge branch '3.1' into 3.2 2022-03-17 15:20:37 +13:00
Maxime Rainville
68d550b817
Merge pull request #79 from creative-commoners/pulls/3.1/write-without-parent
FIX Allow fields without parents to be programatically created
2022-03-17 15:18:02 +13:00
Maxime Rainville
514b6d7a17
Merge pull request #81 from creative-commoners/pulls/3/php74
DEP Set PHP 7.4 as the minimum version
2022-02-18 22:08:44 +13:00
Steve Boyd
f7febc1e98 DEP Set PHP 7.4 as the minimum version 2022-02-10 17:37:49 +13:00
Maxime Rainville
04eb8df284
Merge pull request #80 from creative-commoners/pulls/3/sapphire-test-nine
API phpunit 9 support
2021-11-01 22:24:02 +13:00
Steve Boyd
46169f71a0 API phpunit 9 support 2021-10-27 18:14:42 +13:00
Steve Boyd
643fedaf21 FIX Allow fields without parents to be programatically created 2021-08-12 13:35:02 +12:00
Steve Boyd
9c9900f75a Merge branch '3.1' into 3 2021-05-21 14:03:17 +12:00
Maxime Rainville
ca6f507af8 Update translations 2021-05-17 15:09:54 +12:00
Maxime Rainville
c2c4342c01 MNT Remove obsolete branch-alias 2021-05-05 11:17:33 +12:00
Steve Boyd
050ef82451 Merge branch '3.0' into 3 2021-02-02 14:11:10 +13:00
Steve Boyd
3a8702b1fa
Merge pull request #76 from creative-commoners/pulls/3.0/update-form-field
[Backport] Makes use of EditableFormField updateFormField
2021-02-02 14:09:40 +13:00
3Dgoo
857389c7ff Makes use of EditableFormField updateFormField
This fixes issue #61
2021-02-02 13:55:21 +13:00
Steve Boyd
1459ed89ff
Update build status badge 2021-01-21 16:41:59 +13:00
Steve Boyd
e717411a9d
Merge pull request #75 from 3Dgoo/patch-1
ENH Make use of EditableFormField updateFormField
2021-01-14 16:16:06 +13:00
3Dgoo
d5ae93c88e
Makes use of EditableFormField updateFormField
This fixes issue #61
2020-11-25 15:52:44 +10:30
Steve Boyd
0db3e7aee0 Merge branch '3.0' into 3 2020-11-11 17:45:16 +13:00
Serge Latyntsev
856cc80ffa
Merge pull request #74 from creative-commoners/pulls/3.0/shared-config
MNT Use shared travis config, use sminnee/phpunit
2020-11-10 16:46:52 +13:00
Steve Boyd
a20b215e5c MNT Use shared travis config, use sminnee/phpunit 2020-11-10 14:03:59 +13:00
Steve Boyd
a36bb28b0c
Merge pull request #73 from creative-commoners/pulls/3.0/travis
Update travis 3.0
2020-07-06 09:04:06 +12:00
Steve Boyd
6ecccd2625 Update travis 2020-06-23 16:11:03 +12:00
Garion Herman
669b189ba7 Merge branch '3.0' into 3 2019-11-20 22:15:43 +13:00
Robbie Averill
dce36b8fe7
Merge pull request #71 from creative-commoners/pulls/3.0/xenial
Update to Xenial, expand build matrix
2019-11-20 00:18:27 -08:00
Garion Herman
5978c62022 Update to Xenial, expand build matrix 2019-11-20 18:35:30 +13:00
Robbie Averill
f3fa9fe9fc Merge branch '3.0' 2019-05-10 10:14:27 +12:00
Robbie Averill
e024613ede Update translations 2019-05-10 10:13:46 +12:00
Robbie Averill
b88a706ae7 Merge branch '3.0' 2018-11-07 16:35:56 +02:00
Will Rossiter
0c445a1dbf Add legacy mapping 2018-11-07 16:35:45 +02:00
Guy Marriott
6d39bc23ec
Merge pull request #68 from creative-commoners/pulls/3.0/remove-json-methods
FIX Replace Convert JSON methods with json_* methods, deprecated from SilverStripe 4.4
2018-10-29 11:28:25 +13:00
Robbie Averill
fc934d93fd FIX Replace Convert JSON methods with json_* methods, deprecated from SilverStripe 4.4 2018-10-28 21:40:35 +00:00
Will Rossiter
506d82fc9d Add legacy mapping 2018-09-19 21:01:36 +12:00
Robbie Averill
27a40c6210
Merge pull request #67 from creative-commoners/pulls/master/add-supported-module-badge
Add supported module badge to readme
2018-06-18 10:15:13 +12:00
Dylan Wagstaff
fe2aed7e58 Add supported module badge to readme 2018-06-15 17:48:43 +12:00
Robbie Averill
4c65d66931 Update branch alias for 3.x-dev 2018-06-11 12:12:27 +12:00
Robbie Averill
b826f232c4 Merge branch '3.0' 2018-06-11 12:12:07 +12:00
Robbie Averill
21d8212807 Remove obsolete branch alias 2018-06-11 12:11:43 +12:00
Dylan Wagstaff
192a1c4c2b
Merge pull request #66 from JorisDebonnet/patch-1
Removed still unsupported Invisible reCaptcha from README
2018-04-06 12:17:35 +12:00
JorisDebonnet
0fd7971cd9
Removed still unsupported Invisible reCaptcha from README
UndefinedOffset's plugin actually supports reCAPTCHA v2 (a.k.a. NoCaptcha), same as chillu's, so I merged them into one line.
2018-04-05 08:09:30 +02:00
Ingo Schommer
f69ee07ec0
Mentioned new invisible Recaptcha option 2018-01-12 15:31:22 +13:00
Robbie Averill
059191d91e
Merge pull request #63 from creative-commoners/pulls/3.0/upgrade-upgrade-upgrade
FIX Check and make updates for SS4 compatibility
2017-12-20 15:22:53 +13:00
Raissa North
38ee7a76da ENHANCEMENT Check and make updates for SS4 compatability 2017-12-20 10:07:31 +13:00
Raissa North
46fde9a573 Merge branch '2' 2017-12-19 15:43:25 +13:00
Raissa North
79e2958fad Merge branch '2.0' into 2 2017-12-19 15:41:03 +13:00
Raissa North
68ba83dd6d Remove Transifex configuration. Please commit directly to lang files. 2017-12-19 15:39:26 +13:00
Raissa North
4513998f1e Remove PHP 5.3 from Travis builds 2017-12-19 15:38:57 +13:00
Dylan Wagstaff
1dda806f39
Merge pull request #60 from creative-commoners/pulls/3.0/ican
FIX Ensure getIcon returns exposed resource URL for icon
2017-11-03 14:38:09 +13:00
Robbie Averill
47eef922c7 FIX Ensure getIcon returns exposed resource URL for icon 2017-11-03 11:12:20 +13:00
Daniel Hensby
654f45292c
Merge pull request #59 from creative-commoners/pulls/3.0/update-ci-and-vendorise
Vendorise, update Travis config, fix polymorphic relationship
2017-11-02 11:04:14 +00:00
Robbie Averill
e38c6c3a87 FIX Update for polymorphic relationship for UserDefinedForm and child Fields 2017-11-02 14:53:20 +13:00
Robbie Averill
88b1b10f61 FIX Vendorise module, update CI to include userforms 2017-11-02 14:42:30 +13:00
Damian Mooyman
0a7b3f768d Merge pull request #58 from creative-commoners/pulls/vendorise-ci
FIX convert CI bootstrap references to new their new locations in vendor
2017-10-05 13:25:46 +13:00
Dylan Wagstaff
d09dbdd9f1 FIX convert CI bootstrap references to new their new locations in vendor 2017-10-05 10:07:59 +13:00
Franco Springveldt
b4e9b6e5cb Merge pull request #57 from creative-commoners/pulls/3.0/update-docs
DOCS Add namespaces to class references in readme, fix typos
2017-09-05 09:46:30 +12:00
Robbie Averill
779b155ee0 DOCS Add namespaces to class references in readme, fix typos 2017-09-05 09:40:17 +12:00
Franco Springveldt
42c733061d Merge pull request #51 from Firesphere/master
SilverStripe 4 and Namespacing
2017-09-05 09:29:33 +12:00
Robbie Averill
05fcdb6f41 FIX Typo in userforms form field class name 2017-08-28 17:41:04 +12:00
Robbie Averill
680411e2ac FIX Missing syntax opening in readme, and tweaks for pre-emptive userforms compatibility 2017-08-28 13:44:53 +12:00
Robbie Averill
a1ea0df540 Add upgrader mapping file 2017-08-28 13:20:19 +12:00
Robbie Averill
cef1e24f86 FIX Add versioned to dev requirements 2017-08-28 13:19:39 +12:00
Robbie Averill
37dde110c9 Update usage examples in readme, minor fixes in travis configuration and gitattributes 2017-08-28 13:19:05 +12:00
Robbie Averill
c5f0827c2e Add namespaces, separate test classes, add PSR-4 autoloader, update PSR-2 compliance 2017-08-28 13:19:03 +12:00
Robbie Averill
a60f592598 Update Travis configuration to be standalone, add codecov.io, update license year 2017-08-28 13:11:49 +12:00
Simon Erkelens
b757c3dc6d SilverStripe 4 and Namespacing 2017-08-28 13:11:48 +12:00
Robbie Averill
5f8d2af0d1 Merge branch '2' 2017-08-28 11:20:58 +12:00
Robbie Averill
27da2d6ab4 Add composer alias for 2.1.x-dev 2017-08-28 11:18:51 +12:00
James Ellis
ef3e6d45b6 Configurable fieldname (#56)
* Allow for a configurable field name

* Add a test for configurable field name

* Remove extra conditional by storing the field name in a private static

* No need for field_name config removal as it's now specified as a class property
2017-08-24 11:16:19 +01:00
Daniel Hensby
d2467ac73a Merge pull request #55 from creative-commoners/pulls/2.0/userforms-compat
FIX Compatibility with userforms 3/4 getCMSFields, remove deprecated getSettings etc use
2017-07-19 15:39:55 +01:00
Robbie Averill
3e7f021de7 FIX Compatibility with userforms 3/4 getCMSFields, remove deprecated getSettings use etc 2017-07-07 16:13:10 +12:00
Robbie Averill
5cc9312a8d Move stub classes to their own files, run PSR-2 linter 2017-07-07 14:23:01 +12:00
Robbie Averill
3d771d8179 Move userforms requirement to travis setup call 2017-07-07 14:08:25 +12:00
Robbie Averill
4cd01b2c82 Add PHP7 + SS3.6 build to Travis configuration 2017-07-07 14:08:12 +12:00
Daniel Hensby
a25b052510 Merge pull request #53 from creative-commoners/pulls/travis-php7
Add PHP7 + SS3.6 build to Travis configuration
2017-06-15 16:49:46 +01:00
Robbie Averill
2af878f6fa Move userforms requirement to travis setup call 2017-06-15 13:24:36 +12:00
Robbie Averill
5aa1ca9afb Add PHP7 + SS3.6 build to Travis configuration 2017-06-15 11:36:19 +12:00
Brett Tasker
56ec1f42c6 Update translations 2017-02-09 11:28:52 +13:00
Daniel Hensby
e9880ca3e5
Fixing travis setup 2017-01-31 17:45:39 +00:00
Daniel Hensby
3b4f757d6e
Merge branch '1.1' into 2.0 2017-01-31 12:11:24 +00:00
Daniel Hensby
b1a8445a75
Merge branch '1.1' into 2.0 2017-01-31 12:09:41 +00:00
Daniel Hensby
cc58c0b741
Merge branch '1.0' into 1.1 2017-01-31 12:08:34 +00:00
Daniel Hensby
1b3f3b9c62
Merge branch '0.4' into 1.0 2017-01-31 12:06:32 +00:00
Daniel Hensby
8e61aeb62b
Merge remote-tracking branch 'origin/0.3' into 0.4 2017-01-31 12:04:05 +00:00
Damian Mooyman
df6e182dd2 Update translations 2016-11-17 12:39:49 +13:00
Damian Mooyman
344cf73ccf Remove obsolete branch-alias 2016-11-17 10:17:57 +13:00
Damian Mooyman
38d168bd01 Update translations 2016-08-17 11:08:00 +12:00
Will Rossiter
9db26d69f0 Merge pull request #48 from silverstripe/add-helpful-robot-badge
Added Helpful Robot badge
2016-05-22 08:44:21 +12:00
Christopher Pitt
3ca9a32bb2 Added Helpful Robot badge 2016-05-21 17:16:50 +12:00
Damian Mooyman
b4b4ca14e8 Update changelog for 2.0.4 release 2016-05-19 11:56:38 +12:00
Damian Mooyman
858baaf526 Update translations 2016-05-18 16:58:44 +12:00
Damian Mooyman
73bdcd9f7f Merge pull request #46 from sekjal/setForm
Set Form for formField when validating
2016-03-07 14:01:50 +13:00
Ian Walls
14e768ca32 Set Form for formField when validating
When using EditableSpamProtectionField with UserForms 3.0, forms
with a spam protector field (defined from FormSpamProtectorExtension),
form submissions return an error:

PHP Fatal error:  Call to a member function FormName() on a non-object

This because the exemplar formField generated by getFormField() does
not have any connection to the particular form being submitted.  This
is fixed with a simple setForm() call in the validateField() function
2016-03-02 11:55:53 -05:00
Damian Mooyman
ad6e97dacb Add changelog for 2.0.3 release 2016-02-04 16:51:53 +13:00
Damian Mooyman
078b0f51f9 Merge pull request #44 from chillu/pulls/validate-field-fix
Validate field fix
2016-01-22 12:53:30 +13:00
Ingo Schommer
84bbe9d153 Tests for EditableSpamProtectionField validation
Requires setFormField() method to avoid excessive mocking
2016-01-08 16:35:46 +13:00
Tim Kung
529960d485 updating validateField method on EditableSpamProtectionField to use correct error message 2016-01-08 16:35:14 +13:00
Damian Mooyman
8d1cc403b9 Merge pull request #43 from helpfulrobot/update-license-year
Updated license year
2016-01-05 09:50:09 +13:00
helpfulrobot
405023a5fa Updated license year 2016-01-01 06:38:59 +13:00
Daniel Hensby
947d0f09e0 Merge pull request #30 from helpfulrobot/add-standard-scrutinizer-config
Added standard Scrutinizer config
2015-11-25 15:35:23 +00:00
Daniel Hensby
965389ded9 Merge pull request #31 from helpfulrobot/convert-to-psr-2
Converted to PSR-2
2015-11-25 15:31:30 +00:00
Daniel Hensby
3495ecf726 Merge pull request #38 from helpfulrobot/add-standard-code-of-conduct
Added standard code of conduct
2015-11-23 17:49:10 +00:00
helpfulrobot
cfb204d152 Added standard code of conduct 2015-11-21 20:11:25 +13:00
helpfulrobot
4a606eee82 Added standard Scrutinizer config 2015-11-21 19:27:50 +13:00
helpfulrobot
7ee2dcea0f Converted to PSR-2 2015-11-21 19:15:15 +13:00
Daniel Hensby
8e4f03a409 Merge pull request #33 from helpfulrobot/add-standard-travis-config
Added standard Travis config
2015-11-20 16:05:05 +00:00
Daniel Hensby
220a1e7bf6 Merge pull request #34 from helpfulrobot/add-standard-editor-config
Added standard editor config
2015-11-20 15:12:25 +00:00
Daniel Hensby
9054db2d5b Merge pull request #35 from helpfulrobot/add-standard-license
Added standard license
2015-11-19 12:03:41 +00:00
Daniel Hensby
b13161e1cd Merge pull request #36 from helpfulrobot/add-license-to-composer
Added license to composer.json
2015-11-19 12:00:18 +00:00
Daniel Hensby
2b1d357b6e Merge pull request #37 from helpfulrobot/add-standard-git-attributes
Added standard git attributes
2015-11-19 10:43:30 +00:00
helpfulrobot
df60023e1f Added standard git attributes 2015-11-19 19:09:37 +13:00
helpfulrobot
2f002bcfb8 Added license to composer.json 2015-11-19 18:54:40 +13:00
helpfulrobot
ec51614ade Added standard license 2015-11-19 18:29:00 +13:00
Damian Mooyman
ddef979901 Merge pull request #32 from scott1702/master
Add changelog for release
2015-11-19 14:55:47 +13:00
helpfulrobot
10730a4c64 Added standard Travis config 2015-11-19 14:18:04 +13:00
helpfulrobot
bc7d2c55e9 Added standard editor config 2015-11-19 13:23:15 +13:00
scott1702
c1643a85fb Add changelog for release 2015-11-18 16:50:28 +13:00
Daniel Hensby
2ee8123494 Merge pull request #29 from rasstislav/patch-1
Create sk.yml
2015-11-17 18:23:12 +00:00
rasstislav
46b0990bff Create sk.yml 2015-11-17 13:19:17 +01:00
Damian Mooyman
e7fd668474 Update translations 2015-11-17 16:07:38 +13:00
Scott Hutchinson
1f00c8df41 Merge pull request #28 from silverstripe/pulls/tests
Add tests for php 5.6 and framework 3.2
2015-10-30 18:41:31 +13:00
Damian Mooyman
961aa1832e Add tests for php 5.6 and framework 3.2 2015-10-30 17:34:50 +13:00
Damian Mooyman
09ec50bf2d Merge pull request #25 from silverstripe-rebelalliance/westpac
Fix for compatibility with userforms 3.0
2015-09-21 17:39:30 +12:00
Christopher Joe
da87f71a15 Fix for compatibility with userforms 3.0 2015-09-21 14:14:49 +12:00
Damian Mooyman
9cbb11a884 Update translations 2015-08-20 12:47:37 +12:00
Daniel Hensby
c48a4cf582 Move to new travis containerised infrastructure 2015-07-20 16:03:39 +01:00
Damian Mooyman
12947ae886 Add transifex config 2015-05-26 17:14:40 +12:00
Will Rossiter
9c649f0b6c Merge pull request #20 from Cheddam/master
FIX: Stop attempting to filter an UnsavedRelationList
2015-05-05 17:19:21 +12:00
Garion Herman
9e62b91217 BUGFIX: Stop attempting to filter an UnsavedRelationList 2015-04-30 12:25:54 +12:00
Damian Mooyman
747a801ba5 Merge pull request #19 from tractorcow/pulls/fix-tests
BUG Fix travis / unit tests
2015-03-25 12:59:49 +13:00
Damian Mooyman
c7b211e585 BUG Fix travis / unit tests 2015-03-25 08:53:17 +13:00
Sean Harvey
4478e61390 Merge pull request #18 from tractorcow/pulls/api-save-comment-spam
API Enable comments to save spam status
2015-03-24 12:26:52 +13:00
Damian Mooyman
c40d120b0d API Enable comments to save spam status 2015-03-23 17:22:13 +13:00
Damian Mooyman
ae391bcfb2 Alias master as 2.0 2015-03-23 11:35:25 +13:00
Will Rossiter
adbb4be14d BUG notice level error with statics 2015-01-31 15:34:54 +13:00
Will Rossiter
c1a8a83011 Merge pull request #17 from dhensby/master
Adding .editorconfig
2014-12-05 15:18:33 +13:00
Daniel Hensby
0a219493b4 Adding .editorconfig 2014-12-04 15:54:09 +00:00
Will Rossiter
949ec2b359 If no protector is set then skip the form field 2014-11-12 11:24:21 +13:00
Will Rossiter
05650e912d FIX: typo in field name 2014-09-26 08:53:55 +12:00
Will Rossiter
420a51bbb5 FIX: Ensure protector is a valid class to create 2014-09-26 08:21:06 +12:00
Damian Mooyman
9abe13fcb6 API Refactor field mapping from FormSpamProtectionExtension into SpamProtector API EditableSpamProtectionField may now be configured for spam on an individual field basis Translations added 2014-09-26 08:20:40 +12:00
Will Rossiter
39f7f0be45 Merge pull request #13 from tractorcow/pulls/insertbefore
API Re-introduced ability to insert spam field before another existing field
2014-03-07 20:38:25 +13:00
Damian Mooyman
007a52eb0c API Re-introduced ability to insert spam field before another existing field 2014-03-07 17:03:08 +13:00
Will Rossiter
35a6ad160c Added @tractorcow's akismet module link 2014-02-19 22:11:39 +13:00
Will Rossiter
186c6aba47 Merge pull request #11 from tractorcow/pulls/refactor-mapping
API Refactor field mapping into SpamProtector / UserForms extension
2014-02-19 22:09:55 +13:00
Damian Mooyman
c050dcc05a API Refactor field mapping from FormSpamProtectionExtension into SpamProtector
API EditableSpamProtectionField may now be configured for spam on an individual field basis
Translations added
2014-02-19 08:40:07 +13:00
Will Rossiter
b3af63e387 ID can be used to validate object 2014-02-15 23:00:42 +13:00
Will Rossiter
124d3761ee Add travis 2014-02-10 20:55:38 +13:00
Will Rossiter
03ebf8e19a Add basic tests 2014-02-10 20:54:13 +13:00
Will Rossiter
440e30b611 API: Use config / extension APIs
Overhaul of spam protection to use an extension on Form rather than the SpamProtectorManager. More fluent interface and easier to replace the built in spam protection api with an alternative.
2014-02-10 20:53:59 +13:00
Will Rossiter
28b57beb37 Ignore .DS_Store 2014-02-10 20:48:53 +13:00
Ingo Schommer
a9545bc842 More accurate class_exists() check
The class "Comment" was actually defined by
phing/filters/StripLineComments.php. Since I have installed
phing globally through composer, its automatically in the include_path.
That's a separate problem, but this is a viable workaround.
2013-12-29 12:01:53 +01:00
Ingo Schommer
645b435cea Create LICENSE 2013-09-02 11:44:06 +02:00
Ingo Schommer
b6dc56793d Fixed composer constraint to allow for RC releases 2013-08-14 11:54:04 +02:00
Will Rossiter
b4500aec4e Merge pull request #8 from catcherdev/master
Compatibility w/ comment module
2013-06-10 22:39:49 -07:00
catcher
839b9e0fc9 Update 'CommenterURL' field reference to 'URL' 2013-06-10 16:46:30 -06:00
Ingo Schommer
0acf116c52 Fixed composer constraints 2013-05-07 15:18:54 +03:00
Will Rossiter
7a7344d04c Merge pull request #6 from tractorcow/patch-1
BUG Fixed incorrect field specification
2013-04-09 20:23:03 -07:00
Damian Mooyman
77871a54b7 BUG Fixed incorrect field specification
Email spam field (for Mollom, which I presume this extension is targetting) should be author_mail not author_email

https://github.com/silverstripe/silverstripe-mollom/blob/master/code/MollomField.php#L28
2013-04-10 14:52:08 +12:00
Will Rossiter
74b7990058 Branch 1.0 for 3.0.* compatibility 2013-04-05 21:19:05 +13:00
Will Rossiter
c75d20b2ef Merge 2013-04-05 21:15:43 +13:00
Will Rossiter
bd5e778d4f Merged 2013-04-05 21:13:26 +13:00
Will Rossiter
4ad952fe99 Merged 2013-04-05 21:13:05 +13:00
Will Rossiter
a97e278fd0 FIX: 3.1 extension API updates 2013-04-05 21:11:43 +13:00
Ingo Schommer
1c841b25e1 Create composer.json 2013-04-04 15:31:00 +03:00
Will Rossiter
f4917921ec Make spamprotection for comments opt in by default 2012-12-16 11:23:40 +13:00
vikas srivastava
823efc3483 NEW Added composer.json Added composer.json file which will help this module for submission on proposed extension.silverstripe.org website. Please add more fields according to requirement.
For more information please visit at http://extension.openbees.org/instructions/
2012-09-23 09:14:52 +12:00
Will Rossiter
03377fba84 Update Readme.md 2012-09-07 21:25:15 +12:00
Will Rossiter
c4d2cd0b7a Merge pull request #4 from UndefinedOffset/master
Fix creation of deprecated FieldSet in EditableSpamProtectionField
2012-07-06 16:37:15 -07:00
Ed
704e8555cc BUGFIX: Fixed replaced deprecated FieldSet() with FieldList()
Updated graphic to look better in 3.0
2012-07-06 19:59:57 -03:00
Ingo Schommer
fcfc80c63a Merge pull request #3 from robert-h-curry/master
Upgrade to module to make it 3.0 compatible.
2012-07-06 05:08:55 -07:00
Robert Curry
76051243e3 Upgrade to be 3.0 compatible. 2012-07-06 14:43:38 +12:00
Will Rossiter
c70f270d86 MINOR: hide required configuration, field validation is handled by the form field directly, not the form as things like widgets will always fail the built in validation. Fixes #6752 2012-04-14 23:23:38 +12:00
Will Rossiter
237d08d5dd FEATURE: added extension for new comments module 2010-12-13 00:50:08 +00:00
Carlos Barberis
feddb2cc49 BUGFIX: Added condition to verify userforms module class exists 2010-07-21 01:56:12 +00:00
Saophalkun Ponlu
5598dd3517 MINOR: merge changes from trunk at 107280 2010-06-30 19:07:48 +00:00
Saophalkun Ponlu
aa8ef8aca9 MINOR: update documentation 2010-06-29 05:49:00 +00:00
Will Rossiter
35beeaf4a5 MINOR: Updated documentation and converted readme to markdown 2010-06-10 02:31:06 +00:00
Will Rossiter
59c70f297c created branch for new version 2010-05-06 03:12:55 +00:00
Saophalkun Ponlu
261a155b97 MINOR: documentation 2010-04-12 02:32:44 +00:00
Saophalkun Ponlu
1c902a19e7 BUGFIX: return false when there's no spam protector class has been specified 2010-02-02 03:04:52 +00:00
Ingo Schommer
5ac128830b BUGFIX Don't try to instanciate new SpamProtector instances if none is set in SpamProtectorManager::update_form() 2009-11-26 20:16:37 +00:00
Will Rossiter
78038e14ca APICHANGE: Removed getFieldName() and replaced it with getFormField(). APICHANGE: removed individual calls to update_form() on Spam Protectors to make the code simplier. APICHANGE: removed callback objects on the SpamProtectorFields as they were no longer used. APICHANGE: removed fieldMapping from individual formfields to the abstract class. MINOR: fixed misc documentation with package names 2009-09-17 04:06:53 +00:00
53 changed files with 1443 additions and 288 deletions

17
.editorconfig Normal file
View File

@ -0,0 +1,17 @@
# For more information about the properties used in this file,
# please see the EditorConfig documentation:
# http://editorconfig.org
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[{*.yml,package.json}]
indent_size = 2
# The indent size used in the package.json file cannot be changed:
# https://github.com/npm/npm/pull/3180#issuecomment-16336516

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
/tests export-ignore
/docs export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/.scrutinizer.yml export-ignore
/codecov.yml export-ignore

11
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,11 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
jobs:
ci:
name: CI
uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1

16
.github/workflows/dispatch-ci.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Dispatch CI
on:
# At 11:10 AM UTC, only on Saturday and Sunday
schedule:
- cron: '10 11 * * 6,0'
jobs:
dispatch-ci:
name: Dispatch CI
# Only run cron on the silverstripe account
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
runs-on: ubuntu-latest
steps:
- name: Dispatch CI
uses: silverstripe/gha-dispatch-ci@v1

17
.github/workflows/keepalive.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: Keepalive
on:
workflow_dispatch:
# The 4th of every month at 10:50am UTC
schedule:
- cron: '50 10 4 * *'
jobs:
keepalive:
name: Keepalive
# Only run cron on the silverstripe account
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
runs-on: ubuntu-latest
steps:
- name: Keepalive
uses: silverstripe/gha-keepalive@v1

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

9
.tx/config Normal file
View File

@ -0,0 +1,9 @@
[main]
host = https://www.transifex.com
[o:silverstripe:p:silverstripe-spamprotection:r:master]
file_filter = lang/<lang>.yml
source_file = lang/en.yml
source_lang = en
type = YML

11
.upgrade.yml Normal file
View File

@ -0,0 +1,11 @@
mappings:
SpamProtector: SilverStripe\SpamProtection\SpamProtector
CommentSpamProtection: SilverStripe\SpamProtection\Extension\CommentSpamProtection
EditableSpamProtectionField: SilverStripe\SpamProtection\EditableSpamProtectionField
FormSpamProtectionExtension: SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension
EditableSpamProtectionFieldTest: SilverStripe\SpamProtection\Tests\EditableSpamProtectionFieldTest
EditableSpamProtectionFieldTest_Protector: SilverStripe\SpamProtection\Tests\Stub\Protector
FormSpamProtectionExtensionTest: SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest
FormSpamProtectionExtensionTest_BarProtector: SilverStripe\SpamProtection\Tests\Stub\BarProtector
FormSpamProtectionExtensionTest_BazProtector: SilverStripe\SpamProtection\Tests\Stub\BazProtector
FormSpamProtectionExtensionTest_FooProtector: SilverStripe\SpamProtection\Tests\Stub\FooProtector

View File

@ -1,8 +0,0 @@
0.1:
- initial release
0.2
- Renamed 'SpamProtecterManager' to 'SpamProtectorManager'. Note the typo with the 'er'
0.3 (trunk)
- Updated Error Reporting to be a bit more verbose

38
INSTALL
View File

@ -1,38 +0,0 @@
SilverStripe SpamProtection Module 0.1 beta
=======================================
INSTALLATION
------------
1. Unzip this file (spamprotection-0.1.tar.gz) inside your SilverStripe installation directory.
It should be at the same level as 'jsparty', 'cms' and 'sapphire' modules.
2. Ensure the directory name for the module is 'spamprotection'.
3. Visit your SilverStripe site in a webbrowser and run www.yoursite.com/dev/build
5. We now need to setup some basic features to get the module up and running. Open up _config.php
inside project directory (typically 'mysite/_config.php') with your favourite text editor.
Read the instructions below to setup the initial configuration of the module.
SETTING UP THE MODULE (in 'mysite/_config.php')
------------------------------------------------------
Before putting the following code in '_config.php', make sure you have a subclass of 'SpamProtectorField' installed or written. One
example of 'SpamProtector' subclass is 'MollomField'.
SpamProtectorManager::set_spam_protector('MollomSpamProtector');
UPDATING A FORM TO INCLUDE THE SPAM PROTECTOR FIELD
---------------------------------------------------
This following code should appear after the form creation.
$protector = SpamProtectorManager::update_form($form, 'Message');
This code add an instance of a 'SpamProtectorField' class specified in SETTING UP THE MODULE section. The newly created field will have
MollomField field. The first parameter is a Form object in which the field will be added into and the second parameter tells
SpamProtectorManagor to place the new field before a field named 'Message'.

30
README
View File

@ -1,30 +0,0 @@
###############################################
SpamProtection Module
###############################################
Maintainer Contact
-----------------------------------------------
Saophalkun Ponlu
<phalkunz (at) silverstripe (dot) com>
Will Rossiter
<will (at) silverstripe (dot) com>
Requirements
-----------------------------------------------
SilverStripe 2.3
Documentation
-----------------------------------------------
http://doc.silverstripe.com/doku.php?id=modules:spamprotection
Installation Instructions
-----------------------------------------------
See INSTALL
Usage Overview
-----------------------------------------------
See INSTALL
Known issues
-----------------------------------------------

150
README.md Normal file
View File

@ -0,0 +1,150 @@
# SpamProtection Module
[![CI](https://github.com/silverstripe/silverstripe-spamprotection/actions/workflows/ci.yml/badge.svg)](https://github.com/silverstripe/silverstripe-spamprotection/actions/workflows/ci.yml)
[![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
## Maintainer Contact
* Saophalkun Ponlu
<phalkunz (at) silverstripe (dot) com>
* Will Rossiter
<will (at) fullscreen (dot) io>
## Requirements
Silverstripe 4.0+
**Note:** For Silverstripe 3.x, please use the [2.x release line](https://github.com/silverstripe/silverstripe-spamprotection/tree/2.0).
## Install
To install run `composer require silverstripe/spamprotection`.
## Documentation
This module provides a generic, consistent API for adding spam protection to
your Silverstripe Forms. This does not provide any spam protection out of the
box. For that, you must also download one of the spam protection
implementations. Currently available options are:
* reCAPTCHA v2 (two implementations: [one](https://github.com/chillu/silverstripe-recaptcha), [two](https://github.com/UndefinedOffset/silverstripe-nocaptcha))
* [MathSpamProtection](https://github.com/silverstripe/silverstripe-mathspamprotection)
* [Akismet](https://github.com/silverstripe/silverstripe-akismet)
* [Mollom](https://github.com/silverstripe-archive/silverstripe-mollom)
As a developer you can also provide your own protector by creating a class which
implements the `\SilverStripe\SpamProtection\SpamProtector` interface. More on that below.
## Configuring
After installing this module and a protector of your choice (i.e mollom) you'll
need to rebuild your database through `dev/build` and set the default protector
via SilverStripe's config system. This will update any Form instances that have
spam protection hooks with that protector.
*mysite/_config/spamprotection.yml*
```yaml
---
name: mycustomspamprotection
---
SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension:
default_spam_protector: MollomSpamProtector
```
To add spam protection to your form instance call `enableSpamProtection`.
```php
// your existing form code
$form = new Form(/* .. */);
$form->enableSpamProtection();
```
The logic to perform the actual spam validation is controlled by each of the
individual `SpamProtector` implementations since they each require a different
implementation client side or server side.
### Options
`enableSpamProtection` takes a hash of optional configuration values.
```php
$form->enableSpamProtection(array(
'protector' => MathSpamProtector::class,
'name' => 'Captcha'
));
```
Options to configure are:
* `protector`: a class name string or class instance which implements
`\SilverStripe\SpamProtection\SpamProtector`. Defaults to your
`SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension.default_spam_protector` value.
* `name`: the form field name argument for the Captcha. Defaults to `Captcha`.
* `title`: title of the Captcha form field. Defaults to `''`
* `insertBefore`: name of existing field to insert the spam protection field prior to
* `mapping`: an array mapping of the Form fields to the standardised list of
field names. The list of standardised fields to pass to the spam protector are:
```
title
body
contextUrl
contextTitle
authorName
authorMail
authorUrl
authorIp
authorId
```
## Defining your own `SpamProtector`
Any class that implements `\SilverStripe\SpamProtection\SpamProtector` and the `getFormField()` method can
be set as the spam protector. The `getFormField()` method returns the
`FormField` to be inserted into the `Form`. The `FormField` returned should be
in charge of the validation process.
```php
<?php
use CaptchaField;
use SilverStripe\SpamProtection\SpamProtector;
class CustomSpamProtector implements SpamProtector
{
public function getFormField($name = null, $title = null, $value = null)
{
// CaptchaField is an imagined class which has some functionality.
// See silverstripe-mollom module for an example.
return new CaptchaField($name, $title, $value);
}
}
```
## Using Spam Protection with User Forms
This module provides an `EditableSpamProtectionField` wrapper which you can add
to your UserForm instances. After installing this module and running `/dev/build`
to rebuild the database, your Form Builder interface will have an option for
`Spam Protection Field`. The type of spam protection used will be based on your
currently selected SpamProtector instance.
## Releasing code with Spam Protection support
Spam protection is useful to provide but in some cases we do not want to require
the developer to use spam protection. In that case, modules can provide the
following pattern:
```php
use SilverStripe\Forms\Form;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
$form = new Form(/* .. */);
if ($form->hasExtension(FormSpamProtectionExtension::class)) {
$form->enableSpamProtection();
}
```

View File

@ -1,3 +0,0 @@
<?php
?>

View File

@ -0,0 +1,6 @@
---
Name: spamprotection
---
SilverStripe\Forms\Form:
extensions:
- SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension

30
changelog.md Normal file
View File

@ -0,0 +1,30 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [2.0.4]
* Set Form for formField when validating
* Update translations.
## [2.0.3]
* Fix validateField method on EditableSpamProtectionField to use correct error message
* Converted to PSR-2
* Added standard Scrutinizer config
* Added standard code of conduct
* Added standard editor config
* Added standard Travis config
* Added standard license
* Added license to composer.json
* Added standard git attributes
## [2.0.2]
* Changelog added.
* Create sk.yml
* Update translations
* Add tests for php 5.6 and framework 3.2
* Fix for compatibility with userforms 3.0

1
code-of-conduct.md Normal file
View File

@ -0,0 +1 @@
When having discussions about this module in issues or pull request please adhere to the [SilverStripe Community Code of Conduct](https://docs.silverstripe.org/en/contributing/code_of_conduct).

View File

@ -1,50 +1,284 @@
<?php
/**
* Editable Spam Protecter Field. Used with the User Defined Forms module (if
* installed) to allow the user to have captcha fields with their custom forms
*
* @package SpamProtection
*/
namespace SilverStripe\SpamProtection;
class EditableSpamProtectionField extends EditableFormField {
static $singular_name = 'Spam Protection Field';
static $plural_name = 'Spam Protection Fields';
function __construct( $record = null, $isSingleton = false ) {
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormField;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField;
use SilverStripe\UserForms\Model\EditableFormField\EditableNumericField;
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
parent::__construct( $record, $isSingleton );
}
function getFormField() {
return $this->createField();
}
function getFilterField() {
return $this->createField(true);
}
function createField() {
if($protector = SpamProtectorManager::get_spam_protector()) {
if($protector) {
$protector = new $protector();
if($class = $protector->getFieldName()) {
return new $class($class, $this->Title);
}
}
}
return false;
}
/**
* @return string
*/
public function Icon() {
return 'spamprotection/images/' . strtolower($this->class) . '.png';
}
function showInReports() {
return false;
}
if (!class_exists(EditableFormField::class)) {
return;
}
/**
* Editable Spam Protecter Field. Used with the User Defined Forms module (if
* installed) to allow the user to have captcha fields with their custom forms
*
* @package spamprotection
*/
class EditableSpamProtectionField extends EditableFormField
{
private static $singular_name = 'Spam Protection Field';
private static $plural_name = 'Spam Protection Fields';
private static $table_name = 'EditableSpamProtectionField';
/**
* Fields to include spam detection for
*
* @var array
* @config
*/
private static $check_fields = array(
EditableEmailField::class,
EditableTextField::class,
EditableNumericField::class
);
private static $db = array(
'SpamFieldSettings' => 'Text'
);
/**
* @var FormField
*/
protected $formField = null;
public function getFormField()
{
if ($this->formField) {
return $this->formField;
}
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
return false;
}
// Extract saved field mappings and update this field.
$fieldMapping = array();
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$spamField = $this->spamMapValue($mapSetting);
$fieldMapping[$otherField->Name] = $spamField;
}
$protector->setFieldMapping($fieldMapping);
// Generate field
$field = $protector->getFormField($this->Name, $this->Title, null);
$this->doUpdateFormField($field);
return $field;
}
/**
* @param FormField $field
* @return self
*/
public function setFormField(FormField $field)
{
$this->formField = $field;
return $this;
}
/**
* Gets the list of all candidate spam detectable fields on this field's form
*
* @return DataList
*/
protected function getCandidateFields()
{
// Get list of all configured classes available for spam detection
$types = $this->config()->get('check_fields');
$typesInherit = array();
foreach ($types as $type) {
$subTypes = ClassInfo::subclassesFor($type);
$typesInherit = array_merge($typesInherit, $subTypes);
}
// Get all candidates of the above types
$parent = $this->Parent();
if (!$parent) {
return DataList::create(EditableFormField::class);
}
return $parent
->Fields()
->filter('ClassName', $typesInherit)
->exclude('Title', ''); // Ignore this field and those without titles
}
/**
* Write the spam field mapping values to a serialised DB field
*
* {@inheritDoc}
*/
public function onBeforeWrite()
{
$fieldMap = json_decode($this->SpamFieldSettings ?? '', true);
if (empty($fieldMap)) {
$fieldMap = array();
}
foreach ($this->record as $key => $value) {
if (substr($key ?? '', 0, 8) === 'spammap-') {
$fieldMap[substr($key, 8)] = $value;
}
}
$this->setField('SpamFieldSettings', json_encode($fieldMap));
return parent::onBeforeWrite();
}
/**
* Used in userforms 3.x and above
*
* {@inheritDoc}
*/
public function getCMSFields()
{
/** @var FieldList $fields */
$fields = parent::getCMSFields();
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
return $fields;
}
if ($this->Parent()->Fields() instanceof UnsavedRelationList) {
return $fields;
}
// Each other text field in this group can be assigned a field mapping
$mapGroup = FieldGroup::create()
->setTitle(_t(__CLASS__.'.SPAMFIELDMAPPING', 'Spam Field Mapping'))
->setName('SpamFieldMapping')
->setDescription(_t(
__CLASS__.'.SPAMFIELDMAPPINGDESCRIPTION',
'Select the form fields that correspond to any relevant spam protection identifiers'
));
// Generate field specific settings
$mappableFields = FormSpamProtectionExtension::config()->get('mappable_fields');
$mappableFieldsMerged = array_combine($mappableFields ?? [], $mappableFields ?? []);
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$fieldOption = DropdownField::create(
'spammap-' . $mapSetting,
$otherField->Title,
$mappableFieldsMerged,
$this->spamMapValue($mapSetting)
)->setEmptyString('');
$mapGroup->push($fieldOption);
}
$fields->addFieldToTab('Root.Main', $mapGroup);
return $fields;
}
/**
* Try to retrieve a value for the given spam field map name from the serialised data
*
* @param string $mapSetting
* @return string
*/
public function spamMapValue($mapSetting)
{
$map = json_decode($this->SpamFieldSettings ?? '', true);
if (empty($map)) {
$map = array();
}
if (array_key_exists($mapSetting, $map ?? [])) {
return $map[$mapSetting];
}
return '';
}
/**
* Using custom validateField method
* as Spam Protection Field implementations may have their own error messages
* and may not be based on the field being required, e.g. Honeypot Field
*
* @param array $data
* @param Form $form
* @return void
*/
public function validateField($data, $form)
{
$formField = $this->getFormField();
$formField->setForm($form);
if (isset($data[$this->Name])) {
$formField->setValue($data[$this->Name]);
}
$validator = $form->getValidator();
if (!$formField->validate($validator)) {
$errors = $validator->getErrors();
$foundError = false;
// field validate implementation may not add error to validator
if (count($errors ?? []) > 0) {
// check if error already added from fields' validate method
foreach ($errors as $error) {
if ($error['fieldName'] == $this->Name) {
$foundError = $error;
break;
}
}
}
if ($foundError !== false) {
// use error messaging already set from validate method
$form->sessionMessage($foundError['message'], $foundError['messageType']);
} else {
// fallback to custom message set in CMS or default message if none set
$form->sessionError($this->getErrorMessage()->HTML());
}
}
}
public function getFieldValidationOptions()
{
return FieldList::create();
}
public function getRequired()
{
return false;
}
public function getIcon()
{
$resource = ModuleLoader::getModule('silverstripe/spamprotection')
->getResource('images/editablespamprotectionfield.png');
if (!$resource->exists()) {
return '';
}
return $resource->getURL();
}
public function showInReports()
{
return false;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace SilverStripe\SpamProtection\Extension;
use SilverStripe\Core\Extension;
/**
* Apply the spam protection to the comments module if it is installed.
*
* @package spamprotection
*/
class CommentSpamProtection extends Extension
{
public function alterCommentForm(&$form)
{
$form->enableSpamProtection(array(
'name' => 'IsSpam',
'mapping' => array(
'Name' => 'authorName',
'Email' => 'authorEmail',
'URL' => 'authorUrl',
'Comment' => 'body',
'ReturnURL' => 'contextUrl'
),
'checks' => array(
'spam',
'profanity'
)
));
}
}

View File

@ -0,0 +1,138 @@
<?php
namespace SilverStripe\SpamProtection\Extension;
use LogicException;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
/**
* An extension to the {@link Form} class which provides the method
* {@link enableSpamProtection()} helper.
*
* @package spamprotection
*/
class FormSpamProtectionExtension extends Extension
{
use Configurable;
/**
* @config
*
* The default spam protector class name to use. Class should implement the
* {@link SpamProtector} interface.
*
* @var string $spam_protector
*/
private static $default_spam_protector;
/**
* @config
*
* The {@link enableSpamProtection} method will define which of the form
* values correlates to this form mapped fields list. Totally custom forms
* and subclassed SpamProtector instances are define their own mapping
*
* @var array $mappable_fields
*/
private static $mappable_fields = array(
'id',
'title',
'body',
'contextUrl',
'contextTitle',
'authorName',
'authorMail',
'authorUrl',
'authorIp',
'authorId'
);
/**
* @config
*
* The field name to use for the {@link SpamProtector} {@link FormField}
*
* @var string $spam_protector
*/
private static $field_name = "Captcha";
/**
* Instantiate a SpamProtector instance
*
* @param array $options Configuration options
* @return SpamProtector|null
*/
public static function get_protector($options = null)
{
// generate the spam protector
if (isset($options['protector'])) {
$protector = $options['protector'];
} else {
$protector = self::config()->get('default_spam_protector');
}
if ($protector && class_exists($protector ?? '')) {
return Injector::inst()->create($protector);
} else {
return null;
}
}
/**
* Activates the spam protection module.
*
* @param array $options
* @throws LogicException when get_protector method returns NULL.
* @return Object
*/
public function enableSpamProtection($options = array())
{
// captcha form field name (must be unique)
if (isset($options['name'])) {
$name = $options['name'];
} else {
$name = $this->config()->get('field_name');
}
// captcha field title
if (isset($options['title'])) {
$title = $options['title'];
} else {
$title = '';
}
// set custom mapping on this form
$protector = self::get_protector($options);
if ($protector === null) {
throw new LogicException('No spam protector has been set. Null is not valid value.');
}
if ($protector && isset($options['mapping'])) {
$protector->setFieldMapping($options['mapping']);
}
if ($protector) {
// add the form field
if ($field = $protector->getFormField($name, $title)) {
$field->setForm($this->owner);
// Add before field specified by insertBefore
$inserted = false;
if (!empty($options['insertBefore'])) {
$inserted = $this->owner->Fields()->insertBefore($options['insertBefore'], $field);
}
if (!$inserted) {
// Add field to end if not added already
$this->owner->Fields()->push($field);
}
}
}
return $this->owner;
}
}

View File

@ -1,34 +1,44 @@
<?php
namespace SilverStripe\SpamProtection;
use SilverStripe\Forms\FormField;
/**
* Spam Protector base interface. All Protectors should implement this interface
* to ensure that they contain all the correct methods and we do not get too many
* odd missing function errors
*
* @package SpamProtection
* SpamProtector base interface.
*
* All Protectors are required implement this interface if they want to appear
* on the form.
*
* Classes with this interface are used to generate helper lists to allow the
* user to select the protector.
*
* @package spamprotection
*/
interface SpamProtector {
/**
* Return the name of the Field Associated with this protector
*/
public function getFieldName();
/**
* Function required to handle dynamic feedback of the system.
* if unneeded just return true
*/
public function sendFeedback($object = null, $feedback = "");
/**
* Updates the form with the given protection
*/
public function updateForm($form, $before = null, $fieldsToSpamServiceMapping = null);
/**
* Set which fields need to be mapped for protection
*/
public function setFieldMapping($fieldToPostTitle, $fieldsToPostBody = null, $fieldToAuthorName = null, $fieldToAuthorUrl = null, $fieldToAuthorEmail = null, $fieldToAuthorOpenId = null);
interface SpamProtector
{
/**
* Return the {@link FormField} associated with this protector.
*
* Most spam methods will simply return a piece of HTML to be injected at
* the end of the form. If a spam method needs to inject more than one
* form field (i.e a hidden field and a text field) then return a
* {@link FieldGroup} from this method to include both.
*
* @param string $name
* @param string $title
* @param mixed $value
* @return FormField The resulting field
*/
public function getFormField($name = null, $title = null, $value = null);
/**
* Set the fields to map spam protection too
*
* @param array $fieldMapping array of Field Names, where the indexes of the array are
* the field names of the form and the values are the standard spamprotection
* fields used by the protector
*/
public function setFieldMapping($fieldMapping);
}
?>

View File

@ -1,44 +0,0 @@
<?php
/**
* This class acts as a template for spam protecting form field, for instance MollomField.
* It provides a number of properties for mapping fields of the form which this object belongs to
* to spam checking service fields.
*
* In order to further process the form values or take any action according the status of spam checking,
* markAsSpam() and markAsHam should be called in validate() after the status of the spam checking has
* been obtained.
*
* @package spamprotection
*/
class SpamProtectorField extends FormField {
protected $spanControlCallbackObj = null;
/**
* Set the Callback Object
*/
function setCallbackObject($callbackObject) {
$this->spanControlCallbackObj = $callbackObject;
}
/**
* Tell the callback object the submission is spam
*/
protected function markAsSpam() {
if ($this->spanControlCallbackObj && $this->spanControlCallbackObj instanceof Spamable) {
$this->spanControlCallbackObj->markAsSpam($this->getForm());
}
}
/**
* Tell the callback object the submission is ham
*/
protected function markAsHam() {
if ($this->spanControlCallbackObj && $this->spanControlCallbackObj instanceof Spamable) {
$this->spanControlCallbackObj->markAsHam($this->getForm());
}
}
}
?>

View File

@ -1,76 +0,0 @@
<?php
/**
* This class is responsible for setting an system-wide spam protecter field
* and add the protecter field to a form.
*
* @package spamprotection
*/
class SpamProtectorManager {
static $spam_protector = null;
/**
* Set the name of the spam protecter class
*
* @param String the name of protecter field class
*/
static function set_spam_protector($protector) {
self::$spam_protector = $protector;
}
/**
* Get the name of the spam protector class
*/
static function get_spam_protector() {
return self::$spam_protector;
}
/**
* Add the spam protector field to a form
* @param Form the form that the protecter field added into
* @param string the name of the field that the protecter field will be added in front of
* @param array an associative array
* with the name of the spam web service's field, for example post_title, post_body, author_name
* and a string of field names (seperated by comma) as a value.
* The naming of the fields is based on the implementation of the subclass of SpamProtectorField.
* *** Most of the web service doesn't require this.
* @return SpamProtector object on success or null if the spamprotector class is not found
* also null if spamprotectorfield creation fails.
*/
static function update_form($form, $before=null, $fieldsToSpamServiceMapping=null) {
$check = null;
$protectorClass = self::$spam_protector;
if(!class_exists($protectorClass)) {
user_error("Spam Protector class '$protectorClass' does not exist. Please define a valid Spam Protector", E_USER_WARNING);
}
if(!$protectorClass) return null;
$protector = new $protectorClass();
try {
$check = $protector->updateForm($form, $before, $fieldsToSpamServiceMapping);
} catch (Exception $e) {
user_error("SpamProtectorManager::update_form(): '$protectorClass' is not correctly set up. " . $e, E_USER_WARNING);
}
if(!$check) return null;
return $protector;
}
/**
* Send Feedback to the Spam Protection. The level of feedback
* will depend on the Protector class.
*
* @param DataObject The Object which you want to send feedback about. Must have a
* SessionID field.
* @param String Feedback on the $object usually 'spam' or 'ham' for non spam entries
*/
static function send_feedback($object, $feedback) {
$protector = new self::$spam_protector();
return $protector->sendFeedback($object, $feedback);
}
}
?>

1
codecov.yml Normal file
View File

@ -0,0 +1 @@
comment: false

43
composer.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "silverstripe/spamprotection",
"description": "Spam protection module for SilverStripe.",
"type": "silverstripe-vendormodule",
"keywords": [
"silverstripe",
"spamprotection"
],
"authors": [
{
"name": "Saophalkun Ponlu",
"email": "phalkunz@silverstripe.com"
},
{
"name": "Will Rossiter",
"email": "will@fullscreen.io"
}
],
"require": {
"php": "^7.4 || ^8.0",
"silverstripe/framework": "^4.10"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"silverstripe/versioned": "^1.0",
"squizlabs/php_codesniffer": "^3.0",
"silverstripe/userforms": "^5"
},
"extra": {
"expose": [
"images"
]
},
"autoload": {
"psr-4": {
"SilverStripe\\SpamProtection\\": "code/",
"SilverStripe\\SpamProtection\\Tests\\": "tests/"
}
},
"license": "BSD-3-Clause",
"minimum-stability": "dev",
"prefer-stable": true
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

9
lang/da.yml Normal file
View File

@ -0,0 +1,9 @@
da:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Spam beskyttelsefelter'
PLURALS:
one: 'Et spam beskyttelsefelt'
other: '{count} Spambeskyttelsefelter'
SINGULARNAME: 'Spam beskyttelsesfelt'
SPAMFIELDMAPPING: 'Spam felt mapping'
SPAMFIELDMAPPINGDESCRIPTION: 'Vælg de formfelter der matcher relevante spam beskyttelses identifikatorer'

9
lang/de.yml Normal file
View File

@ -0,0 +1,9 @@
de:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: Spamschutzfelder
PLURALS:
one: 'Ein Spamschutzfeld'
other: '{count} Spamschutzfelder'
SINGULARNAME: Spamschutzfeld
SPAMFIELDMAPPING: 'Spamschutzfeld Zuordnung'
SPAMFIELDMAPPINGDESCRIPTION: 'Wähle die Formularfelder, die mit Spamschutz verbunden sind'

10
lang/en.yml Normal file
View File

@ -0,0 +1,10 @@
en:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Spam Protection Fields'
PLURALS:
one: 'A Spam Protection Field'
other: '{count} Spam Protection Fields'
SINGULARNAME: 'Spam Protection Field'
SPAMFIELDMAPPING: 'Spam Field Mapping'
SPAMFIELDMAPPINGDESCRIPTION: 'Select the form fields that correspond to any relevant spam protection identifiers'
db_SpamFieldSettings: 'Spam field settings'

View File

@ -1,16 +0,0 @@
<?php
global $lang;
$lang['en_US']['EditableSpamProtectionField']['PLURALNAME'] = array(
'Spam Protection Fields',
50,
'Pural name of the object, used in dropdowns and to generally identify a collection of this object in the interface'
);
$lang['en_US']['EditableSpamProtectionField']['SINGULARNAME'] = array(
'Spam Protection Field',
50,
'Singular name of the object, used in dropdowns and to generally identify a single object in the interface'
);
?>

10
lang/eo.yml Normal file
View File

@ -0,0 +1,10 @@
eo:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Spamprotektaj kampoj'
PLURALS:
one: 'Unu spamprotekta kampo'
other: '{count} spamprotektaj kampoj'
SINGULARNAME: 'Spamprotekta kampo'
SPAMFIELDMAPPING: 'Spamkampa mapigo'
SPAMFIELDMAPPINGDESCRIPTION: 'Elektu la kampojn kiuj rilatas al eventualaj rilataj spamprotektaj identigiloj'
db_SpamFieldSettings: 'Spamkampaj agordoj'

6
lang/es.yml Normal file
View File

@ -0,0 +1,6 @@
es:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Campos de protección de spam'
SINGULARNAME: 'Campo de protección de spam'
SPAMFIELDMAPPING: 'Mapeo del campo spam'
SPAMFIELDMAPPINGDESCRIPTION: 'Seleccionar los campos del formulario que corresponden a cualquier identificador de protección de spam relevante'

6
lang/fa_IR.yml Normal file
View File

@ -0,0 +1,6 @@
fa_IR:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'فیلدهای محافظت از هرزنوشته'
SINGULARNAME: 'فیلد محافظت از هرزنوشته'
SPAMFIELDMAPPING: 'نقشه‌برداری فیلد هرزنوشته'
SPAMFIELDMAPPINGDESCRIPTION: 'فیلدهای فرم را مطابق با هریک از شناسایی‌کننده‌های محافظت از هرزنوشته انتخاب کنید'

9
lang/fi.yml Normal file
View File

@ -0,0 +1,9 @@
fi:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Roskapostisuojauksen kentät'
PLURALS:
one: 'Roskapostin suodatuskenttä'
other: '{count} Roskapostin suodatuskenttää'
SINGULARNAME: 'Roskapostisuojauksen kenttä'
SPAMFIELDMAPPING: 'Roskapostikentän kuvaus'
SPAMFIELDMAPPINGDESCRIPTION: 'Valitse lomakekenttä, joka vastaa mitä tahansa oleellista roskapostisuodatuksen tunnistetta'

9
lang/fi_FI.yml Normal file
View File

@ -0,0 +1,9 @@
fi_FI:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Roskapostisuojauksen kentät'
PLURALS:
one: 'Roskapostin suodatuskenttä'
other: '{count} Roskapostin suodatuskenttää'
SINGULARNAME: 'Roskapostisuojauksen kenttä'
SPAMFIELDMAPPING: 'Roskapostikentän kuvaus'
SPAMFIELDMAPPINGDESCRIPTION: 'Valitse lomakekenttä, joka vastaa mitä tahansa oleellista roskapostisuodatuksen tunnistetta'

6
lang/hr.yml Normal file
View File

@ -0,0 +1,6 @@
hr:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Polja Spam zaštite'
SINGULARNAME: 'Polje Spam zaštite'
SPAMFIELDMAPPING: 'Mapiranje polja Spama'
SPAMFIELDMAPPINGDESCRIPTION: 'Odaberite polja forme koji odgovaraju relevantnim identifikatorima za zaštitu od spama'

10
lang/it.yml Normal file
View File

@ -0,0 +1,10 @@
it:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Campi di Prevenzione Spam'
PLURALS:
many: '{count} Campi di Prevenzione Spam'
one: 'Un Campo di Prevenzione Spam'
other: '{count} Campi di Prevenzione Spam'
SINGULARNAME: 'Campo di Prevenzione Spam'
SPAMFIELDMAPPING: 'Mappatura Campo Spam'
SPAMFIELDMAPPINGDESCRIPTION: 'Selezionare i campi della form che forniscono una qualche protezione dallo spam'

9
lang/nl.yml Normal file
View File

@ -0,0 +1,9 @@
nl:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Anti-spam velden'
PLURALS:
one: 'Een anti-spam veld'
other: '{count} Anti-spam velden'
SINGULARNAME: 'Anti-spam veld'
SPAMFIELDMAPPING: 'Spam-velden koppelen'
SPAMFIELDMAPPINGDESCRIPTION: 'Kies de velden die overeenkomen met de anti-spam identifiers'

6
lang/ru.yml Normal file
View File

@ -0,0 +1,6 @@
ru:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Поля защиты от спама'
SINGULARNAME: 'Поле защиты от спама'
SPAMFIELDMAPPING: 'Привязка полей для защиты от спама'
SPAMFIELDMAPPINGDESCRIPTION: 'Выберите поля формы, которые соответствуют любому индентификатору защиты от спама'

12
lang/sk.yml Normal file
View File

@ -0,0 +1,12 @@
sk:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Polia ochrany proti spamu'
PLURALS:
few: '{count} polia ochrany proti spamu'
many: '{count} polí ochrany proti spamu'
one: 'Pole ochrany proti spamu'
other: '{count} polí ochrany proti spamu'
SINGULARNAME: 'Pole ochrany proti spamu'
SPAMFIELDMAPPING: 'Mapovanie spamového poľa'
SPAMFIELDMAPPINGDESCRIPTION: 'Vyberte polia formulára, ktoré zodpovedajú všetkým príslušným identifikátorom ochrany proti spamu'
db_SpamFieldSettings: 'Nastavenia poľa spamu'

4
lang/sl.yml Normal file
View File

@ -0,0 +1,4 @@
sl:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Polja za zaščito pred neželeno pošto'
SINGULARNAME: 'Polje za zaščito pred neželeno pošto'

6
legacy.yml Normal file
View File

@ -0,0 +1,6 @@
---
Name: spamprotectionlegacy
---
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
EditableSpamProtectionField: 'SilverStripe\SpamProtection\EditableSpamProtectionField'

12
license.md Normal file
View File

@ -0,0 +1,12 @@
Copyright (c) 2017, SilverStripe Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

13
phpcs.xml.dist Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="SilverStripe">
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
<file>code</file>
<file>tests</file>
<rule ref="PSR2" >
<!-- Current exclusions -->
<exclude name="PSR1.Methods.CamelCapsMethodName" />
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols" />
</rule>
</ruleset>

17
phpunit.xml.dist Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Default">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">code/</directory>
<exclude>
<directory suffix=".php">tests/</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,178 @@
<?php
namespace SilverStripe\SpamProtection\Tests;
use ReflectionClass;
use SilverStripe\ORM\DataList;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\EditableSpamProtectionField;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\SpamProtection\Tests\Stub\Protector;
class EditableSpamProtectionFieldTest extends SapphireTest
{
protected $usesDatabase = true;
protected function setUp(): void
{
parent::setUp();
if (!class_exists(EditableSpamProtectionField::class)) {
$this->markTestSkipped('"userforms" module not installed');
}
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
Protector::class
);
}
public function testValidateFieldDoesntAddErrorOnSuccess()
{
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(true));
$formMock
->expects($this->never())
->method('sessionMessage');
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
public function testValidateFieldAddsErrorFromField()
{
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(false));
$formMock->getValidator()->validationError('MyField', 'some field message', 'required');
$formMock
->expects($this->once())
->method('sessionMessage')
->with($this->stringContains('some field message'), $this->anything());
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
public function testValidateFieldAddsDefaultError()
{
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(false));
// field doesn't set any validation errors here
$formMock
->expects($this->once())
->method('sessionError')
->with($this->stringContains('default error message'));
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
public function testSpamConfigurationShowsInCms()
{
$field = $this->getEditableFormFieldMock();
$fields = $field->getCMSFields();
$this->assertInstanceOf(FieldGroup::class, $fields->fieldByName('Root.Main.SpamFieldMapping'));
}
public function testSpamMapSettingsAreSerialised()
{
$field = $this->getEditableFormFieldMock();
$field->SpamFieldSettings = json_encode(array('foo' => 'bar', 'bar' => 'baz'));
$field->write();
$this->assertJson($field->SpamFieldSettings);
$this->assertSame('bar', $field->spamMapValue('foo'));
$this->assertSame('baz', $field->spamMapValue('bar'));
}
public function testGetIcon()
{
$field = new EditableSpamProtectionField;
$this->assertStringContainsString('/images/editablespamprotectionfield.png', $field->getIcon());
}
protected function getFormMock()
{
$formMock = $this->getMockBuilder(Form::class)
->setMethods(['sessionMessage', 'sessionError', 'getValidator'])
->disableOriginalConstructor()
->getMock();
$formMock
->expects($this->any())
->method('getValidator')
->will($this->returnValue(new RequiredFields()));
return $formMock;
}
protected function getEditableFormFieldMock()
{
$page = new UserDefinedForm();
$page->write();
$formFieldMock = $this->getMockBuilder(TextField::class)
->disableOriginalConstructor()
->getMock();
$editableFormFieldMock = new EditableSpamProtectionField(array(
'ParentID' => $page->ID,
'ParentClass' => get_class($page),
'Name' => 'MyField',
'CustomErrorMessage' => 'default error message'
));
$editableFormFieldMock->write();
$editableFormFieldMock->setFormField($formFieldMock);
return $editableFormFieldMock;
}
public function testGetCandidateFieldsParentStatus()
{
$field = new EditableSpamProtectionField();
$field->Name = 'MyField';
$reflection = new ReflectionClass($field);
$method = $reflection->getMethod('getCandidateFields');
$method->setAccessible(true);
// Assert with no parent
$list = $method->invoke($field);
$this->assertTrue($list instanceof DataList);
// Assert with parent
$page = new UserDefinedForm();
$page->write();
$field->ParentID = $page->ID;
$field->ParentClass = get_class($page);
$field->write();
$list = $method->invoke($field);
$this->assertTrue($list instanceof DataList);
}
}

View File

@ -0,0 +1,142 @@
<?php
namespace SilverStripe\SpamProtection\Tests;
use LogicException;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\SpamProtection\Tests\Stub\FooProtector;
use SilverStripe\SpamProtection\Tests\Stub\BarProtector;
use SilverStripe\SpamProtection\Tests\Stub\BazProtector;
/**
* @package spamprotection
*/
class FormSpamProtectionExtensionTest extends SapphireTest
{
protected $usesDatabase = false;
/**
* @var Form
*/
protected $form = null;
protected function setUp(): void
{
parent::setUp();
$this->form = new Form(new Controller, 'Form', new FieldList(
new TextField('Title'),
new TextField('Comment'),
new TextField('URL')
), new FieldList());
$this->form->disableSecurityToken();
}
public function testEnableSpamProtectionThrowsException()
{
$this->expectException(LogicException::class);
$this->expectExceptionMessage('No spam protector has been set. Null is not valid value.');
Config::modify()->set(FormSpamProtectionExtension::class, 'default_spam_protector', null);
$this->form->enableSpamProtection();
}
public function testEnableSpamProtection()
{
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
FooProtector::class
);
$form = $this->form->enableSpamProtection();
$this->assertEquals('Foo', $form->Fields()->fieldByName('Captcha')->Title());
}
public function testEnableSpamProtectionCustomProtector()
{
$form = $this->form->enableSpamProtection(array(
'protector' => BarProtector::class
));
$this->assertEquals('Bar', $form->Fields()->fieldByName('Captcha')->Title());
}
public function testEnableSpamProtectionCustomTitle()
{
$form = $this->form->enableSpamProtection(array(
'protector' => BarProtector::class,
'title' => 'Baz',
));
$this->assertEquals('Baz', $form->Fields()->fieldByName('Captcha')->Title());
}
public function testCustomOptions()
{
$form = $this->form->enableSpamProtection(array(
'protector' => BazProtector::class,
'title' => 'Qux',
'name' => 'Borris'
));
$this->assertEquals('Qux', $form->Fields()->fieldByName('Borris')->Title());
}
public function testConfigurableName()
{
$field_name = "test_configurable_name";
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
FooProtector::class
);
Config::modify()->set(
FormSpamProtectionExtension::class,
'field_name',
$field_name
);
$form = $this->form->enableSpamProtection();
// remove for subsequent tests
Config::modify()->remove(FormSpamProtectionExtension::class, 'field_name');
// field should take up configured name
$this->assertEquals('Foo', $form->Fields()->fieldByName($field_name)->Title());
}
public function testInsertBefore()
{
$form = $this->form->enableSpamProtection(array(
'protector' => FooProtector::class,
'insertBefore' => 'URL'
));
$fields = $form->Fields();
$this->assertEquals('Title', $fields[0]->Title());
$this->assertEquals('Comment', $fields[1]->Title());
$this->assertEquals('Foo', $fields[2]->Title());
$this->assertEquals('URL', $fields[3]->Title());
}
public function testInsertBeforeMissing()
{
$form = $this->form->enableSpamProtection(array(
'protector' => FooProtector::class,
'insertBefore' => 'NotAField'
));
// field should default to the end instead
$fields = $form->Fields();
$this->assertEquals('Title', $fields[0]->Title());
$this->assertEquals('Comment', $fields[1]->Title());
$this->assertEquals('URL', $fields[2]->Title());
$this->assertEquals('Foo', $fields[3]->Title());
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BarProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
$title = $title ?: 'Bar';
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BazProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FooProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, 'Foo', $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BarProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
$title = $title ?: 'Bar';
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BazProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FooProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, 'Foo', $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

19
tests/Stub/Protector.php Normal file
View File

@ -0,0 +1,19 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
class Protector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, 'Foo', $value);
}
public function setFieldMapping($fieldMapping)
{
}
}