qr_generator-1.0.1/src/Form/QRCodeExportForm.php
src/Form/QRCodeExportForm.php
<?php
declare(strict_types=1);
namespace Drupal\qr_generator\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Endroid\QrCode\Builder\Builder;
use Symfony\Component\HttpFoundation\Response;
use Endroid\QrCode\Writer\PngWriter;
use Endroid\QrCode\Writer\SvgWriter;
use Endroid\QrCode\Writer\PdfWriter;
/**
* Form controller for generating and exporting QR codes.
*
* This form allows users to create a QR code for a given entity
* and download it in one of several output formats (PNG, SVG, PDF).
* The QR code content is based on an internal URL generated from
* the UUID of the target `qr_code` entity passed in the route.
*
* Features:
* - Configurable QR code size (in pixels) and margin.
* - Output format selection with built-in validation.
* - Uses the Endroid\QrCode library to generate images.
* - Streams the generated QR code directly to the browser as a file download.
*
* Workflow:
* 1. User enters size, margin, and selects output format.
* 2. On submit, the form constructs an absolute URL for the entity.
* 3. The appropriate writer (PNG, SVG, or PDF) is instantiated.
* 4. The QR code is built with the Endroid\QrCode\Builder API.
* 5. The binary result is returned as an HTTP response with appropriate
* content type and download filename.
*
* @package Drupal\qr_generator\Form
*/
final class QRCodeExportForm extends FormBase
{
/**
* {@inheritdoc}
*/
public function getFormId(): string
{
return 'qr_generator_q_r_code_export';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array
{
$form['size'] = [
'#type' => 'number',
'#title' => $this->t('Size (px)'),
'#default_value' => 300,
'#min' => 100,
'#max' => 1000,
];
$form['margin'] = [
'#type' => 'number',
'#title' => $this->t('Margin'),
'#default_value' => 10,
'#min' => 0,
'#max' => 50,
];
$form['format'] = [
'#type' => 'select',
'#title' => $this->t('Output format'),
'#options' => [
'png' => 'PNG',
'svg' => 'SVG',
'pdf' => 'PDF',
],
'#default_value' => 'png',
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Generate QR Code'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void
{
$size = (int) $form_state->getValue('size');
$margin = (int) $form_state->getValue('margin');
$format = $form_state->getValue('format');
// Validate size
if ($size <= 0) {
$form_state->setErrorByName('size', $this->t('Size must be a positive number.'));
}
// Validate margin
if ($margin < 0) {
$form_state->setErrorByName('margin', $this->t('Margin cannot be negative.'));
}
// Validate format
$allowed_formats = ['png', 'pdf', 'svg']; // Example allowed values
if (!in_array($format, $allowed_formats)) {
$form_state->setErrorByName('format', $this->t('Invalid format selected. Allowed formats: @formats', [
'@formats' => implode(', ', $allowed_formats),
]));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void
{
$size = (int) $form_state->getValue('size');
$margin = (int) $form_state->getValue('margin');
$format = $form_state->getValue('format');
$entity = \Drupal::routeMatch()->getParameter('qr_code');
$url = Url::fromUri('internal:/api/qr-code/' . $entity->uuid())->setAbsolute()->toString();
// Determine writer
$writer = match ($format) {
'svg' => new SvgWriter(),
'pdf' => new PdfWriter(),
default => new PngWriter(),
};
$builder = new Builder();
$result = $builder->build($writer, null, false, $url, null, null, $size, $margin);
$filename = $entity->uuid() . '_' . \Drupal::time()->getCurrentTime() . '.' . $format;
$response = new Response($result->getString());
$response->headers->set('Content-Type', $result->getMimeType());
$response->headers->set('Content-Disposition', 'attachment; filename="'.$filename.'"');
$response->send();
exit;
}
}
