Files
michaelschiemer/src/Framework/View/Processors/HoneypotProcessor.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);
}
}