Add requirements in Symfony 6 localized route - symfony

Symfony supports localized route, like shown here https://symfony.com/doc/current/routing.html#localized-routes-i18n
class CompanyController extends AbstractController
{
#[Route(path: [
'en' => '/about-us',
'nl' => '/over-ons'
], name: 'about_us')]
public function about(): Response
{
// ...
}
}
Is there anyway to add lang specific requirements on the path array? Something that would look like this:
class CompanyController extends AbstractController
{
#[Route(path: [
'en' => [ 'path' => '/{slug}', 'requirement': \w+]
'fr' => ['path' => '/{slug}', 'requirement': \d+]
], name: 'about_us')]
public function about($slug): Response
{
// ...
}
}
Thanks a lot

Related

Add class TextEditorField EasyAdmin 4

is there a way to add a custom class to a specific tag with the TextEditorField - EasyAdmin : https://symfony.com/bundles/EasyAdminBundle/current/fields/TextEditorField.html
This field is using trix editor : https://trix-editor.org
I'd like to do something like this :
public function configureFields(string $pageName): iterable {
return [
TextEditorField::new('description', 'Description')->setNumOfRows(30)->setTrixEditorConfig([
'blockAttributes' => [
'default' => ['tagName' => 'p'],
'heading1' => ['tagName' => 'h2', 'class' => 'myClass'],
]
])
];
}
Actually, I want to add the class 'myClass' to all the h2 tags.

OroPlatform: Override core entity form builder

Context
I'm trying to change the form type of one field on one of the core entity: Business Unit
The default form field is TextField and I want to change it to ChoiceType.
Here is my custom field on Business Unit entity created with migration :
$table->addColumn('periodicite', 'string', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'Périodicité'],
],
]);
Issue
I've seen on the Oro documentation that entity_config.yml could solve my problem. I've tried to put these lines but it doesn't work :
entity_config:
business_unit:
entity:
items:
periodicite:
form:
type: Symfony\Component\Form\Extension\Core\Type\ChoiceType
options:
choices:
Mensuel: Mensuel
Trimestriel: Trimestriel
placeholder: false
required: true
label: "Périodicite"
I have also tried to create a new migration to change the field type on my custom field but it doesn't work
<?php
namespace Baltimore\Bundle\AppBundle\Migrations\Schema\v1_1;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\EntityConfigBundle\Migration\UpdateEntityConfigFieldValueQuery;
use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtension;
use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtensionAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
use Oro\Bundle\OrganizationBundle\Entity\BusinessUnit;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class UpdateBusinessUnitField implements Migration, ExtendExtensionAwareInterface
{
/** #var ExtendExtension */
protected $extendExtension;
/**
* #inheritdoc
*/
public function setExtendExtension(ExtendExtension $extendExtension)
{
$this->extendExtension = $extendExtension;
}
public function up(Schema $schema, QueryBag $queries)
{
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
BusinessUnit::class,
'periodicite',
'form',
'form_type',
ChoiceType::class
)
);
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
BusinessUnit::class,
'periodicite',
'form',
'form_options',
[
'choices' => [
'Mensuel' => 'Mensuel',
'Trimestriel' => 'Trimestriel',
'Annuel' => 'Annuel',
],
]
)
);
}
}
I have found a solution with the changeColumn method in my migration file and it works like a charm.
By the way, these properties works also with the addColumn method.
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->getTable('oro_business_unit');
$table->changeColumn('periodicite', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'Périodicité'],
'form' => [
'form_type' => ChoiceType::class,
'form_options' => [
'choices' => [
'Mensuel' => 'Mensuel',
'Trimestriel' => 'Trimestriel',
'Semestriel' => 'Semestriel',
'Annuel' => 'Annuel'
]
]
],
],
]);
}
I don't know about the possibility to override entity config metadata using the YAML file. If there is - please share the documentation you used to implement it in the comments.
But for sure, you can manage the same using the schema migration, like in this example:
class UpdateOpportunityRelationFormType implements Migration
{
/**
* {#inheritdoc}
*/
public function up(Schema $schema, QueryBag $queries)
{
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
Quote::class,
'opportunity',
'form',
'form_type',
OpportunitySelectType::class
)
);
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
Quote::class,
'opportunity',
'form',
'form_options',
['attr' => ['readonly' => true]]
)
);
}
}

Guess custom form type when embedding custom classes

Two simple classes form my app model: Money and Product.
As Money app form being reusable, I've decided to create MoneyType extending AbstractType.
// App\Entity\Product
/**
* #ORM\Embedded(class="Money\Money")
*/
private $price;
// App\Form\ProductType
$builder->add('price', MoneyType::class)
// App\Form\Type\MoneyType
class MoneyType extends AbstractType
{
private $transformer;
public function __construct(MoneyToArrayTransformer $transformer)
{
$this->transformer = $transformer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('amount', NumberType::class, [
'html5' => true,
'constraints' => [
new NotBlank(),
new PositiveOrZero(),
],
'attr' => [
'min' => '0',
'step' => '0.01',
],
])
->add('currency', ChoiceType::class, [
'choices' => $this->getCurrenciesChoices(),
'constraints' => [
new NotBlank(),
],
]);
$builder->addModelTransformer($this->transformer);
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'data_class' => null
]);
}
...
}
Is it possible to guess the field type without specifying it explicitly for obtaining the following code?
// App\Form\ProductType
$builder->add('price')
Any help is welcome. Thank you in advance.
You can implement a custom TypeGuesser that reads the doctrine metadata and checks if the field is an embeddable of the desired type. This is a basic implementation
namespace App\Form\TypeGuesser;
use App\Form\Type\MoneyType;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Doctrine\ORM\EntityManagerInterface;
class MoneyTypeGuesser implements FormTypeGuesserInterface
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function guessType($class, $property)
{
if (!$metadata = $this->em->getClassMetadata($class)) {
return null;
}
if (
isset($metadata->embeddedClasses[$property]) &&
'Money\Money' == $metadata->embeddedClasses[$property]['class']
) {
return new TypeGuess(MoneyType::class, [], Guess::HIGH_CONFIDENCE);
}
}
// Other interface functions ommited for brevity, you can return null
}
You can see all the interface methods that you need to implement here.
The Form TypeGuesser is mostly based on the annotation #var Money\Money and you should be able to build your down guesser for your own types, see https://symfony.com/doc/current/form/type_guesser.html
Also take a look at https://github.com/symfony/symfony/blob/4.3/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php on how to guess the type by doctrine orm specific types.
You could derive your own app specific guesser with those two examples.

Can't generate new routes in Sonata Admin

I'm struggling to make a custom action in Sonata Admnin, I followed the guide Sonata documentation and tried to copy the code from another of my projects where it worked fine.
My Admin class is:
namespace BlogBundle\Admin;
use AppBundle\Form\Type\FacebookType;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\CoreBundle\Form\Type\BooleanType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Knp\Menu\ItemInterface as MenuItemInterface;
use Sonata\AdminBundle\Admin\AdminInterface;
class PostAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('facebookAction');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id',TextType::class,[
'label' => 'entity.post.id'
])
->add('active',BooleanType::class,[
'label' => 'entity.post.active'
])
->add('_action', null, [
'actions' => [
'show' => [],
'edit' => [],
'delete' => [],
'facebook' => [
'template' => 'BlogBundle:Admin:empty.html.twig'
]
]
]);
;
}
//...
}
Service declaration:
services:
admin.blog.post:
class: BlogBundle\Admin\PostAdmin
arguments: [~, BlogBundle\Entity\Post, BlogBundle:PostAdmin]
tags:
- { name: sonata.admin, manager_type: orm, label: 'admin.name.post', group: 'admin.group.blog'}
And the CRUD Controller:
namespace BlogBundle\Controller;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
class PostAdminController extends Controller
{
public function facebookAction()
{
}
}
Looking at the profiler the route is not being generated and the button for my custom route is not displayed on the list even if it is set on the configureListFields function.
Symfony's version is 3.2.2 and Sonata 3.10.3

Symfony2 FOSUserBundle override profile form : field form empty?

I overrided registration form from FOSUserBundle with additionals fields: it works well.
When I apply the same logic to override Profile Form : the form appears well with my additionals fields but all is empty (the fields do not contain values ​​of the connected user).
Note: when I use the default form from the bundle the profile form contains the values ​​of the connected user.
Is there a specific action compared to override the registration form to retrieve the values ​​of the connected user ?
HERE IS CODE :
src/Vn/UserBundle/Resources/config/services.yml
services:
...
vn_user.profile.form.type:
class: Vn\UserBundle\Form\Type\ProfileFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: vn_user_profile }
vn_user.form.handler.profile:
class: Vn\UserBundle\Form\Handler\ProfileFormHandler
arguments: ["#fos_user.profile.form", "#request", "#fos_user.user_manager"]
scope: request
public: false
symfony/app/config/config.yml
fos_user:
...
profile:
form:
type: vn_user_profile
handler: vn_user.form.handler.profile
src/Vn/UserBundle/Form/Type/ProfileFormType.php
namespace Vn\UserBundle\Form\Type;
use Symfony\Component\Form\FormBuilder;
use FOS\UserBundle\Form\Type\ProfileFormType as BaseType;
class ProfileFormType extends BaseType
{
public function buildUserForm(FormBuilder $builder, array $options)
{
parent::buildUserForm($builder, $options);
// custom field
$builder->add('profile',new MyProfileFormType(),array(
'label' => 'PROFILE'
));
}
public function getName()
{
return 'vn_user_profile';
}
}
src/Vn/UserBundle/Form/Type/MyProfileFormType.php
namespace Vn\UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class MyProfileFormType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('birthday','birthday', array(
'input' => 'array',
'widget' => 'choice',
'label' => 'Birthday',
))
->add('firstname','text', array(
'trim' => true,
'label' => 'Firstname',
))
->add('lastname','text', array(
'trim' => true,
'label' => 'Lastname',
))
->add('gender','choice', array(
'choices' => array('1' => 'Male', '2' => 'Female'),
'expanded' => true,
'required' => true,
'label' => 'Vous êtes',
));
}
public function getName()
{
return 'vn_user_myprofile';
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Vn\UserBundle\Document\Profile',
);
}
}
I found the mistake in my file ProfilFormeHandler.php : in the function process() I called parent::onSucess() instead of parent::process() ...
The result is a "silent" bug (silent because not fatal error appears) due to my fault of course
Thanks for time you spent to try to help me, very sorry !
<?php
// src/Vn/UserBundle/Form/Handler/RegistrationFormHandler.php
namespace Vn\UserBundle\Form\Handler;
use FOS\UserBundle\Form\Handler\ProfileFormHandler as BaseHandler;
use FOS\UserBundle\Model\UserInterface;
class ProfileFormHandler extends BaseHandler
{
public function process(UserInterface $user)
{
//parent::onSuccess($user);
parent::process($user); // sound better of course : )
}
protected function onSuccess(UserInterface $user)
{
$this->userManager->updateUser($user);
}
}

Resources