Skip to content

Instantly share code, notes, and snippets.

@florentdestremau
Last active December 13, 2019 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save florentdestremau/710d8640187f6ad0c4a15d5a7b9ceb43 to your computer and use it in GitHub Desktop.
Save florentdestremau/710d8640187f6ad0c4a15d5a7b9ceb43 to your computer and use it in GitHub Desktop.
<?php
namespace App\Form;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class NinsuoCollectionType extends CollectionType
{
public function buildView(FormView $view, FormInterface $form, array $options)
{
parent::buildView($view, $form, $options);
if ($form->getConfig()->hasAttribute('prototype')) {
$view->vars['prototype']->vars['block_prefixes'][] = 'ninsuo_collection_entry';
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(
[
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false,
'attr' => ['class' => 'collection_holder'],
]
);
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
parent::finishView($view, $form, $options);
/** @var FormView $children */
$children = $view->children;
foreach ($children as $c) {
$c->vars['block_prefixes'][] = 'ninsuo_collection_entry';
}
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return CollectionType::class;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'ninsuo_collection';
}
}
<?php
class ProductController extends AbstractController
{
/**
* @Route("/create", methods={"POST"})
*/
public function create(
Request $request,
EntityManagerInterface $em,
EventDispatcherInterface $dispatcher,
TranslatorInterface $translator
) {
$product = new Product();
// hack pour initialiser les ProductFormula sans quoi ça plante dans TranslatableType
if ($data = $request->request->all()) {
foreach ($data['formulas'] as $formula) {
$product->addFormula(new ProductFormula());
}
}
$form = $this->createForm(ProductType::class, $product);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($product);
$em->flush();
$dispatcher->dispatch(AppEvents::PRODUCT_CREATED, new ProductEvent($product));
return new JsonResponse(
[
'message' => $translator->trans('product.create_success', ['%productName%' => $product->getName()]),
'id' => $product->getId(),
]
);
}
return new JsonResponse(
['message' => $translator->trans('common.error_message')],
JsonResponse::HTTP_BAD_REQUEST
);
}
}
<?php
namespace App\Form;
use App\Entity\ProductFormula;
use App\Form\Type\TranslatableType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProductFormulaType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'nameTranslatable',
TranslatableType::class,
[
'mapped' => false,
'field' => 'name',
]
);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => ProductFormula::class,
'label_format' => 'productFormula.%name%',
]
);
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return null;
}
}
<?php
namespace App\Form;
use App\Entity\Product;
use App\Entity\ProductSection;
use App\Entity\ProductSelection;
use App\Entity\ProductTag;
use App\Entity\Provider;
use App\Entity\SurveyTemplate;
use App\Form\Type\TranslatableType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProductType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('onlineOrderAvailable')
->add(
'nameTranslatable',
TranslatableType::class,
[
'mapped' => false,
'field' => 'name',
'required' => false,
]
)
->add(
'descriptionTranslatable',
TranslatableType::class,
[
'mapped' => false,
'field' => 'description',
'required' => false,
]
)
->add(
'formulas',
NinsuoCollectionType::class,
[
'label' => 'Formules pour le produit',
'entry_type' => ProductFormulaType::class,
'entry_options' => ['label' => false],
'prototype_name' => 'product_formula',
'attr' => ['class' => 'product-formula-collection'],
]
)
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => Product::class,
'csrf_protection' => false,
'label_format' => 'product.%name%',
]
);
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return null;
}
}
<?php
namespace App\Form\Type;
use App\Model\Translatable;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;
class TranslatableType extends AbstractType
{
const ROOT_LOCALE = 'fr';
private $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($options['locales'] as $locale) {
$builder->add($locale, $options['widget'], ['required' => false]);
}
if (!isset($options['required']) || $options['required'] === true) {
// check if at least one of the fields is not empty
$builder->addEventListener(
FormEvents::SUBMIT,
function (FormEvent $formEvent) use ($options) {
if ($options['required']) {
$form = $formEvent->getForm();
$data = $formEvent->getData();
if (count(array_filter($data)) === 0) {
$form->addError(
new FormError($this->translator->trans('common.at_least_one_field_should_be_filled'))
);
}
}
}
);
}
$builder->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $formEvent) use ($options) {
$form = $formEvent->getForm();
$data = $formEvent->getData();
/** @var Translatable $entity */
$entity = $form->getParent()->getData();
if (!$entity instanceof Translatable) {
return;
}
// other translations
$isRootLocaleStored = false;
$method = "set" . ucfirst($options['field']);
$rootContent = $data[self::ROOT_LOCALE];
if ($rootContent) {
$entity->$method($rootContent);
$isRootLocaleStored = true;
}
foreach ($data as $locale => $content) {
$translation = $entity->findTranslationByLocaleAndField($locale, $options['field']);
if ($content) {
if ($translation) {
$translation->setContent($content);
} else {
$entity->addTranslation($entity->createTranslation($locale, $options['field'], $content));
}
if (!$isRootLocaleStored) {
$entity->$method($data[$locale]);
}
} else {
if ($translation) {
$entity->removeTranslation($translation);
}
}
}
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['field']);
$resolver->setDefaults(
[
'widget' => TextType::class,
'locales' => ['fr', 'en'],
'field' => false,
'required' => true,
]
);
}
public function getBlockPrefix()
{
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment