Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[FEATURE] Support for sf_event_mgt #73

Merged
merged 5 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Blueways\BwCaptcha\EventListener;

use Blueways\BwCaptcha\Validation\Validator\CaptchaValidator;
use DERHANSEN\SfEventMgt\Event\ModifyRegistrationValidatorResultEvent;
use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator;
use TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator;

class ModifyRegistrationValidatorResultEventListener
{
public function __invoke(ModifyRegistrationValidatorResultEvent $event): void
{
$captchaSettings = $event->getSettings()['registration']['captcha'] ?? [];
$isCaptchaEnabled = isset($captchaSettings['enabled']) && $captchaSettings['enabled'];
$isBwCaptchaEnabled = isset($captchaSettings['type']) && $captchaSettings['type'] === 'bwCaptcha';

if (!$isCaptchaEnabled || !$isBwCaptchaEnabled) {
return;
}

$validator = new ConjunctionValidator();
$validator->addValidator(new NotEmptyValidator());
$validator->addValidator(new CaptchaValidator());

$result = $validator->validate($event->getRegistration()->getCaptcha());

$event->getResult()->forProperty('captcha')->merge($result);
}
}
5 changes: 5 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ services:

Blueways\BwCaptcha\Middleware\Captcha:
public: true

Blueways\BwCaptcha\EventListener\ModifyRegistrationValidatorResultEventListener:
tags:
- name: event.listener
identifier: 'bw-captcha/sf-event-mgt-registration'
9 changes: 9 additions & 0 deletions Configuration/TypoScript/setup.typoscript
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ plugin.tx_bwcaptcha {
}
}

plugin.tx_sfeventmgt {
view {
partialRootPaths.999999 = EXT:bw_captcha/Resources/Private/SfEventMgt/
}
settings.registration.captcha {
bwCaptcha < plugin.tx_bwcaptcha.settings
}
}

captcha = PAGE
captcha {
typeNum = 3413
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ plugin.tx_bwcaptcha {
}
```

### Usage in other Extensions

#### sf_event_mgt

To use the captcha element in the [sf_event_mgt](https://github.com/derhansen/sf_event_mgt/) extension, add the following TypoScript:

```
plugin.tx_sfeventmgt {
settings {
registration {
requiredFields = captcha
captcha {
enabled = 1
type = bwCaptcha
}
}
}
}
```

If you want to override the shipped [BwCaptcha.html](https://github.com/maikschneider/bw_captcha/blob/main/Resources/Private/SfEventMgt/Registration/Captcha/BwCaptcha.html) partial, you need to configure the partialRootPaths with a higher index:

```
plugin.tx_sfeventmgt.view.partialRootPaths.9999999 = EXT:your_ext/Resources/Private/Partials/
```

```yaml

### Overriding the captcha element

To override the captcha partial, copy it to your extension and add the partial path to
Expand Down
61 changes: 61 additions & 0 deletions Resources/Private/SfEventMgt/Registration/Captcha/BwCaptcha.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:e="http://typo3.org/ns/DERHANSEN/SfEventMgt/ViewHelpers"
data-namespace-typo3-fluid="true">

<f:if condition="{settings.registration.captcha.enabled} && {settings.registration.captcha.type} == 'bwCaptcha'">
<div class="event-registration-row captcha {e:validation.errorClass(fieldname: 'captcha')}">
<label for="captcha">
<f:translate key="formEditor.elements.Captcha" extensionName="bw_captcha" />
<span class="event-required">*</span>
</label>
<div class="captcha">
<img src="{f:uri.page(pageType:3413)}"
alt="{f:translate(extensionName:'bw_captcha',key:'partial.image.alt')}"
aria-live="polite"
loading="lazy"
onload="this.parentElement.classList.remove('captcha--reloading'); return false;"/>
<f:if condition="{settings.registration.captcha.bwCaptcha.refreshButton}">
<a class="captcha__reload"
href="#"
title="{f:translate(extensionName:'bw_captcha',key:'partial.refresh.title')}"
aria-label="{f:translate(extensionName:'bw_captcha',key:'partial.refresh.label')}"
role="button"
data-url="{f:uri.page(pageType:3413)}"
onclick="const div = this.parentElement; div.classList.add('captcha--reloading', 'captcha--spin'); let captchaUrl = this.dataset.url; this.previousElementSibling.setAttribute('src', captchaUrl + (/\?/.test(captchaUrl) ? '&' : '?') + 'now=' + Date.now()); setTimeout(function(){div.classList.remove('captcha--spin')},400); return false;">
<svg width="31" height="28" xmlns="http://www.w3.org/2000/svg">
<g fill="#000" fill-rule="evenodd">
<path d="M10 10.7 6.3 8.5a11 11 0 0 1 20 3l2.5-.8h.4v-.3A14 14 0 0 0 3.6 7L.3 5l1.8 8.3 8-2.6ZM31 23l-1.7-8-8 2.5 3.7 2.1a10.9 10.9 0 0 1-19.8-2.3l-2 .6-1 .3a13.9 13.9 0 0 0 17 9.3 14 14 0 0 0 8.4-6.4l3.4 2Z"/>
</g>
</svg>
</a>
</f:if>
<f:if condition="{settings.registration.captcha.bwCaptcha.audioButton}">
<a class="captcha__audio"
href="#"
data-url="{f:uri.page(pageType:3414)}"
title="{f:translate(extensionName:'bw_captcha',key:'partial.audio.title')}"
aria-label="{f:translate(extensionName:'bw_captcha',key:'partial.audio.label')}"
role="button"
onclick="const div = this.parentElement;window.captchaAudio = window.captchaAudio ? window.captchaAudio : new Audio();window.captchaAudio.addEventListener('ended', () => div.classList.remove('captcha--playing'));if (window.captchaAudio.paused) { div.classList.add('captcha--playing'); const img = div.querySelector('img'); const c = document.createElement('canvas'); const ctx = c.getContext('2d'); const data = new FormData(); c.width = img.naturalWidth; c.height = img.naturalHeight; ctx.drawImage(img, 0, 0); data.append('captchaDataUrl', c.toDataURL());fetch('{f:uri.page(pageType:3414)}', {method: 'POST',body: data}).then(response => response.blob()).then(blob => { window.captchaAudio.src = window.URL.createObjectURL(blob); window.captchaAudio.play(); });} else { window.captchaAudio.pause();div.classList.remove('captcha--playing')} return false;">
<svg xmlns="http://www.w3.org/2000/svg" height="35" fill="none" viewBox="0 0 115 100">
<path fill="#000"
d="M59.145 50.136v39.223c0 1.334-.135 2.667-1.65 3.256-1.521.588-2.308-.386-3.173-1.256C48.197 85.255 42.025 79.188 36 73a7.603 7.603 0 0 0-6.162-2.666c-5.734.187-11.479.078-17.23 0-3 0-3.494-.495-3.494-3.438v-33.88c0-2.666.589-3.317 3.318-3.333H30.786a5.705 5.705 0 0 0 4.48-1.87c6.067-6.078 12.203-12.146 18.322-18.307a14.896 14.896 0 0 1 1.64-1.546 2.285 2.285 0 0 1 2.392-.428 2.296 2.296 0 0 1 1.432 1.964c.114.833.146 1.677.094 2.52.02 12.71.02 25.417 0 38.121Z"/>
<path fill="#000"
class="captcha__audio__mute"
d="M67.935 29.935a3.192 3.192 0 0 1 4.515 0l15.05 15.05 15.05-15.05a3.192 3.192 0 1 1 4.515 4.515L92.015 49.5l15.05 15.05a3.192 3.192 0 1 1-4.515 4.515L87.5 54.015l-15.05 15.05a3.192 3.192 0 1 1-4.515-4.515l15.05-15.05-15.05-15.05a3.192 3.192 0 0 1 0-4.515Z"/>
<path fill="#000"
class="captcha__audio__sound"
d="M97.839 49.896a42.769 42.769 0 0 1-11.584 29.625c-.432.485-.906.927-1.416 1.334A3.642 3.642 0 0 1 80 80.563a3.737 3.737 0 0 1-.307-4.667c.463-.593.963-1.156 1.495-1.682a35.772 35.772 0 0 0 9.349-23.964 35.784 35.784 0 0 0-9.162-24.036 18.253 18.253 0 0 1-1.693-1.896 3.74 3.74 0 0 1 .532-4.864 3.57 3.57 0 0 1 4.65-.105c.59.47 1.131.995 1.615 1.573a42.513 42.513 0 0 1 11.36 28.974Z"/>
<path fill="#000"
class="captcha__audio__sound"
d="M81.333 51.667a25.566 25.566 0 0 1-6.562 16 10.73 10.73 0 0 1-1.6 1.588 3.71 3.71 0 0 1-4.88-.323A3.603 3.603 0 0 1 68 64.24c.375-.547.865-1 1.333-1.506a19.157 19.157 0 0 0-.172-25.495c-.307-.359-.65-.682-.932-1.051a3.695 3.695 0 0 1 .318-5.084 3.749 3.749 0 0 1 5.104.203c.86.85 1.646 1.766 2.349 2.745 3.495 4.64 5.333 10.177 5.333 17.615Z"/>
</svg>
</a>
</f:if>
</div>
<f:form.textfield id="captcha" property="captcha" /><br>
<f:render partial="FormErrors" arguments="{field: 'registration.captcha'}"/>
</div>
</f:if>

</html>
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
"roave/security-advisories": "dev-latest",
"typo3/cms-base-distribution": "^12.0",
"typo3/cms-lowlevel": "^12.0",
"bk2k/bootstrap-package": "dev-master",
"bk2k/bootstrap-package": "^15.0",
"friendsofphp/php-cs-fixer": "^3.12",
"saschaegerer/phpstan-typo3": "^1.9",
"helhum/typo3-console": "^8.0"
"helhum/typo3-console": "^8.0",
"derhansen/sf_event_mgt": "^7.6"
},
"extra": {
"typo3/cms": {
Expand Down
Loading