79 lines
2.5 KiB
PHP
79 lines
2.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\View\Processors;
|
|
|
|
use App\Framework\View\DomProcessor;
|
|
use App\Framework\View\DomWrapper;
|
|
use App\Framework\View\RenderContext;
|
|
use Dom\HTMLDocument;
|
|
use Dom\HTMLElement;
|
|
|
|
final readonly class HoneypotProcessor implements DomProcessor
|
|
{
|
|
private const array HONEYPOT_NAMES = [
|
|
'email_confirm',
|
|
'website_url',
|
|
'phone_number',
|
|
'user_name',
|
|
'company_name'
|
|
];
|
|
|
|
public function process(DomWrapper $dom, RenderContext $context): DomWrapper
|
|
{
|
|
$forms = $dom->document->querySelectorAll('form');
|
|
|
|
/** @var HTMLElement $form */
|
|
foreach($forms as $form) {
|
|
$this->addHoneypot($dom->document, $form);
|
|
$this->addTimeValidation($dom->document, $form);
|
|
}
|
|
|
|
return $dom;
|
|
}
|
|
|
|
private function addHoneypot(HTMLDocument $dom, HTMLElement $form): void
|
|
{
|
|
$honeypotName = self::HONEYPOT_NAMES[array_rand(self::HONEYPOT_NAMES)];
|
|
|
|
// Versteckter Container
|
|
$container = $dom->createElement('div');
|
|
$container->setAttribute('style', 'position:absolute;left:-9999px;visibility:hidden;');
|
|
$container->setAttribute('aria-hidden', 'true');
|
|
|
|
// Honeypot mit realistischem Label
|
|
$label = $dom->createElement('label');
|
|
$label->textContent = 'Website (optional)';
|
|
$label->setAttribute('for', $honeypotName);
|
|
|
|
$honeypot = $dom->createElement('input');
|
|
$honeypot->setAttribute('type', 'text');
|
|
$honeypot->setAttribute('name', $honeypotName);
|
|
$honeypot->setAttribute('id', $honeypotName);
|
|
$honeypot->setAttribute('autocomplete', 'off');
|
|
$honeypot->setAttribute('tabindex', '-1');
|
|
|
|
$container->appendChild($label);
|
|
$container->appendChild($honeypot);
|
|
|
|
// Honeypot-Name als verstecktes Feld
|
|
$nameField = $dom->createElement('input');
|
|
$nameField->setAttribute('type', 'hidden');
|
|
$nameField->setAttribute('name', '_honeypot_name');
|
|
$nameField->setAttribute('value', $honeypotName);
|
|
|
|
$form->insertBefore($container, $form->firstChild);
|
|
$form->insertBefore($nameField, $form->firstChild);
|
|
}
|
|
|
|
private function addTimeValidation(HTMLDocument $dom, HTMLElement $form): void
|
|
{
|
|
$timeField = $dom->createElement('input');
|
|
$timeField->setAttribute('type', 'hidden');
|
|
$timeField->setAttribute('name', '_form_start_time');
|
|
$timeField->setAttribute('value', (string)time());
|
|
|
|
$form->insertBefore($timeField, $form->firstChild);
|
|
}
|
|
}
|