Initial release

This commit is contained in:
Jürgen Mummert
2026-02-17 18:53:23 +01:00
commit 63b5556b21
45 changed files with 3962 additions and 0 deletions
+206
View File
@@ -0,0 +1,206 @@
<?php
declare(strict_types=1);
namespace MummertMedia\EventManagerBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Url;
class EventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$termsLabel = 'Ich stimme den Nutzungsbedingungen zu.';
if (null !== $options['terms_page_url']) {
$termsLabel = sprintf(
'Ich stimme den <a href="%s" target="_blank" rel="noopener noreferrer">Nutzungsbedingungen</a> zu.',
htmlspecialchars($options['terms_page_url'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'),
);
}
$showOrganizationSelect = true === $options['show_organization'];
$builder
->add('title', TextType::class, [
'label' => 'Titel',
'required' => true,
])
->add('startDate', DateType::class, [
'label' => 'Startdatum',
'required' => false,
'widget' => 'single_text',
'input' => 'string',
'html5' => false,
'format' => 'yyyy-MM-dd',
'attr' => [
'class' => 'js-flatpickr-date',
],
])
->add('endDate', DateType::class, [
'label' => 'Enddatum',
'required' => false,
'widget' => 'single_text',
'input' => 'string',
'html5' => false,
'format' => 'yyyy-MM-dd',
'help' => 'Lassen Sie das Feld leer, um ein eintägiges Event zu erstellen.',
'attr' => [
'class' => 'js-flatpickr-date',
],
])
->add('addTime', CheckboxType::class, [
'label' => 'Dem Event eine Start- und Endzeit hinzufügen.',
'required' => false,
'attr' => [
'class' => 'js-add-time-toggle',
],
])
->add('startTime', TimeType::class, [
'label' => 'Startzeit',
'required' => false,
'input' => 'string',
'widget' => 'single_text',
'html5' => false,
'input_format' => 'H:i',
'attr' => [
'class' => 'js-flatpickr-time',
],
])
->add('endTime', TimeType::class, [
'label' => 'Endzeit',
'required' => false,
'input' => 'string',
'widget' => 'single_text',
'html5' => false,
'input_format' => 'H:i',
'help' => 'Lassen Sie das Feld leer, um ein Event mit offenem Ende zu erstellen.',
'attr' => [
'class' => 'js-flatpickr-time',
],
]);
if ($showOrganizationSelect) {
$builder->add('organization_ids', ChoiceType::class, [
'label' => 'Veranstalter',
'choices' => $options['organization_choices'],
'required' => true,
'mapped' => false,
'multiple' => true,
'data' => $options['selected_organization_ids'],
'attr' => [
'class' => 'js-organization-choice',
'data-placeholder' => 'Veranstalter suchen …',
],
]);
}
$builder
->add('location_id', ChoiceType::class, [
'label' => 'Veranstaltungsort',
'choices' => $options['location_choices'],
'required' => false,
'choice_value' => static fn ($value) => null !== $value ? (string) $value : '',
'placeholder' => 'Bitte auswählen',
'attr' => [
'class' => 'js-location-choice',
'data-placeholder' => 'Veranstaltungsort suchen …',
],
])
->add('type', ChoiceType::class, [
'label' => 'Typ',
'choices' => [
'Unterkunft' => 'accommodation',
'Einkaufen' => 'shopping',
'Kultur' => 'culture',
],
'multiple' => true,
'required' => false,
'attr' => [
'class' => 'js-event-type-choice',
'data-placeholder' => 'Typen suchen …',
],
])
->add('teaser', TextareaType::class, ['label' => 'Teaser', 'required' => false])
->add('description', TextareaType::class, ['label' => 'Beschreibung', 'required' => false])
->add('url', UrlType::class, [
'label' => 'Link (extern)',
'required' => false,
'default_protocol' => 'https',
'invalid_message' => 'Bitte eine gültige URL mit http:// oder https:// eingeben (z. B. https://example.org).',
'constraints' => [
new Url([
'protocols' => ['http', 'https'],
'message' => 'Bitte eine gültige URL mit http:// oder https:// eingeben (z. B. https://example.org).',
]),
],
])
->add('addImage', CheckboxType::class, [
'label' => 'Dem Event ein Bild hinzufügen',
'required' => false,
'attr' => [
'class' => 'js-add-image-toggle',
],
])
->add('eventUpload', FileType::class, [
'label' => 'Bild hochladen',
'required' => false,
'mapped' => false,
'attr' => [
'class' => 'js-event-image-upload',
'accept' => 'image/*',
],
])
->add('photographer', TextType::class, [
'label' => 'Urheber/Fotograf',
'required' => false,
'attr' => [
'class' => 'js-photographer',
'maxlength' => '255',
],
])
->add('termsAccepted', CheckboxType::class, [
'label' => $termsLabel,
'label_html' => true,
'required' => true,
])
->add('isSoldOut', CheckboxType::class, [
'label' => 'Diese Veranstaltung ist ausverkauft.',
'required' => false,
])
->add('isCanceled', CheckboxType::class, [
'label' => 'Diese Veranstaltung wurde abgesagt.',
'required' => false,
])
->add('published', CheckboxType::class, ['label' => 'Veröffentlicht', 'required' => false]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'csrf_protection' => true,
'location_choices' => [],
'organization_choices' => [],
'selected_organization_ids' => [],
'show_organization' => false,
'terms_page_url' => null,
]);
$resolver->setAllowedTypes('location_choices', 'array');
$resolver->setAllowedTypes('organization_choices', 'array');
$resolver->setAllowedTypes('selected_organization_ids', 'array');
$resolver->setAllowedTypes('show_organization', 'bool');
$resolver->setAllowedTypes('terms_page_url', ['null', 'string']);
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace MummertMedia\EventManagerBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class OrganizationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title', TextType::class, ['label' => 'Titel', 'required' => true])
->add('street', TextType::class, ['label' => 'Straße', 'required' => false])
->add('postal', TextType::class, ['label' => 'PLZ', 'required' => false])
->add('city', TextType::class, ['label' => 'Ort', 'required' => false])
->add('state', TextType::class, ['label' => 'Bundesland', 'required' => false])
->add('country', TextType::class, ['label' => 'Land', 'required' => false])
->add('phone', TextType::class, ['label' => 'Telefon', 'required' => false])
->add('email', EmailType::class, ['label' => 'E-Mail', 'required' => false])
->add('website', TextType::class, ['label' => 'Webseite', 'required' => false])
->add('description', TextareaType::class, ['label' => 'Beschreibung', 'required' => false])
->add('type', ChoiceType::class, [
'label' => 'Typ',
'choices' => [
'Unterkunft' => 'accommodation',
'Einkaufen' => 'shopping',
'Kultur' => 'culture',
],
'multiple' => true,
'required' => false,
'attr' => [
'class' => 'js-organization-type-choice',
'data-placeholder' => 'Typ auswählen …',
],
])
->add('logoUpload', FileType::class, [
'label' => 'Logo hochladen',
'required' => false,
'mapped' => false,
'attr' => [
'class' => 'js-logo-upload',
'accept' => 'image/*',
],
]);
}
}