@@ -2,107 +2,71 @@ | |||
namespace Lc\SovBundle\Authenticator; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Repository\User\UserStore; | |||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | |||
use Symfony\Component\Form\FormFactoryInterface; | |||
use Symfony\Component\HttpFoundation\RedirectResponse; | |||
use Symfony\Component\HttpFoundation\Request; | |||
use Symfony\Component\Security\Core\User\UserInterface as SfUserInterface; | |||
use Symfony\Component\HttpFoundation\Response; | |||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | |||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; | |||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException; | |||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; | |||
use Symfony\Component\Security\Core\Security; | |||
use Symfony\Component\Security\Core\User\UserProviderInterface; | |||
use Symfony\Component\Security\Csrf\CsrfToken; | |||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; | |||
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator; | |||
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface; | |||
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator; | |||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge; | |||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; | |||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials; | |||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport; | |||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; | |||
use Symfony\Component\Security\Http\Util\TargetPathTrait; | |||
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface | |||
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator | |||
{ | |||
use TargetPathTrait; | |||
public const LOGIN_ROUTE = 'sov_login'; | |||
private $entityManager; | |||
private $urlGenerator; | |||
private $csrfTokenManager; | |||
private $passwordEncoder; | |||
protected $parameterBag; | |||
protected UrlGeneratorInterface $urlGenerator; | |||
protected UserStore $userStore; | |||
protected FormFactoryInterface $formFactory; | |||
protected ParameterBagInterface $parameterBag; | |||
public function __construct( | |||
EntityManager $entityManager, | |||
UrlGeneratorInterface $urlGenerator, | |||
CsrfTokenManagerInterface $csrfTokenManager, | |||
UserPasswordEncoderInterface $passwordEncoder, | |||
ParameterBagInterface $parameterBag | |||
) | |||
{ | |||
$this->entityManager = $entityManager; | |||
UrlGeneratorInterface $urlGenerator, | |||
UserStore $userStore, | |||
FormFactoryInterface $formFactory, | |||
ParameterBagInterface $parameterBag | |||
) { | |||
$this->urlGenerator = $urlGenerator; | |||
$this->csrfTokenManager = $csrfTokenManager; | |||
$this->passwordEncoder = $passwordEncoder; | |||
$this->userStore = $userStore; | |||
$this->formFactory = $formFactory; | |||
$this->parameterBag = $parameterBag; | |||
} | |||
public function supports(Request $request) | |||
public function supports(Request $request): bool | |||
{ | |||
return self::LOGIN_ROUTE === $request->attributes->get('_route') | |||
&& $request->isMethod('POST'); | |||
return $request->isMethod('POST') && $this->getLoginUrl($request) === $request->getPathInfo(); | |||
} | |||
public function getCredentials(Request $request) | |||
public function authenticate(Request $request): PassportInterface | |||
{ | |||
$credentials = [ | |||
'email' => $request->request->get('email'), | |||
'password' => $request->request->get('password'), | |||
'csrf_token' => $request->request->get('_csrf_token'), | |||
]; | |||
$request->getSession()->set( | |||
Security::LAST_USERNAME, | |||
$credentials['email'] | |||
$email = $request->request->get('email'); | |||
$password = $request->request->get('password'); | |||
$csrfToken = $request->request->get('_csrf_token'); | |||
return new Passport( | |||
new UserBadge($email, function ($userIdentifier) { | |||
return $this->userStore->getOneByEmail($userIdentifier); | |||
}), | |||
new PasswordCredentials($password), | |||
[new CsrfTokenBadge('authenticate', $csrfToken)] | |||
); | |||
return $credentials; | |||
} | |||
public function getUser($credentials, UserProviderInterface $userProvider) | |||
{ | |||
$token = new CsrfToken('authenticate', $credentials['csrf_token']); | |||
if (!$this->csrfTokenManager->isTokenValid($token)) { | |||
throw new InvalidCsrfTokenException(); | |||
} | |||
$user = $this->entityManager->getRepository(UserInterface::class)->findOneBy( | |||
['email' => $credentials['email']] | |||
); | |||
if (!$user) { | |||
// fail authentication with a custom error | |||
throw new CustomUserMessageAuthenticationException('Email could not be found.'); | |||
} | |||
return $user; | |||
} | |||
public function checkCredentials($credentials, SfUserInterface $user) | |||
{ | |||
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']); | |||
} | |||
/** | |||
* Used to upgrade (rehash) the user's password automatically over time. | |||
*/ | |||
public function getPassword($credentials): ?string | |||
{ | |||
return $credentials['password']; | |||
} | |||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey) | |||
{ | |||
public function onAuthenticationSuccess( | |||
Request $request, | |||
TokenInterface $token, | |||
string $providerKey | |||
): RedirectResponse { | |||
$routeName = 'home'; | |||
$email = $request->request->get('email'); | |||
$loginRedirection = $this->parameterBag->get('lc_sov.login_redirection'); | |||
@@ -112,7 +76,7 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P | |||
if (isset($useReferer) && $useReferer == true) { | |||
$url = $request->request->get('_target_path'); | |||
} else { | |||
$user = $this->entityManager->getRepository(UserInterface::class)->findOneBy(['email' => $email]); | |||
$user = $this->userStore->getOneByEmail($email); | |||
if (!empty($user)) { | |||
$roles = $user->getRoles(); | |||
@@ -132,8 +96,8 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P | |||
} | |||
} | |||
protected function getLoginUrl() | |||
protected function getLoginUrl(Request $request): string | |||
{ | |||
return $this->urlGenerator->generate(self::LOGIN_ROUTE); | |||
} | |||
} | |||
} |
@@ -60,6 +60,7 @@ use Lc\SovBundle\Field\Filter\FilterManager; | |||
use Lc\SovBundle\Form\Common\FiltersFormType; | |||
use Lc\SovBundle\Form\Common\PositionType; | |||
use Lc\SovBundle\Notification\MailMailjetNotification; | |||
use Lc\SovBundle\Translation\FlashBagTranslator; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | |||
@@ -84,6 +85,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
parent::getSubscribedServices(), | |||
[ | |||
TranslatorAdmin::class => TranslatorAdmin::class, | |||
FlashBagTranslator::class => FlashBagTranslator::class, | |||
SessionInterface::class => SessionInterface::class, | |||
RequestStack::class => RequestStack::class, | |||
EntityManagerInterface::class => EntityManagerInterface::class, | |||
@@ -128,9 +130,16 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$responseParameters->set('filters_form', $this->filtersForm); | |||
} | |||
$responseParameters->set('translation_entity_name', $this->getTranslationEntityName()); | |||
return $responseParameters; | |||
} | |||
public function getTranslationEntityName() | |||
{ | |||
return $this->getEntityFqcn(); | |||
} | |||
public function overrideEntitiesActions(?EntityCollection $entities): void | |||
{ | |||
} | |||
@@ -179,6 +188,8 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$this->setMaxResults($crud); | |||
$crud->setFormOptions(['translation_entity_name' => $this->getTranslationEntityName()]); | |||
if ($this->isInstanceOf(SortableInterface::class)) { | |||
$crud->setDefaultSort(['position' => 'ASC']); | |||
} | |||
@@ -186,6 +197,14 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
return $crud; | |||
} | |||
public function addFlashTranslator(string $type, $translationKeyName, $translationEntityName = null, $translationParam = array()):void | |||
{ | |||
if ($translationEntityName === null && method_exists($this, 'getTranslationEntityName')) { | |||
$translationEntityName = $this->getTranslationEntityName(); | |||
} | |||
$this->get(FlashBagTranslator::class)->add($type, $translationKeyName, $translationEntityName, $translationParam); | |||
} | |||
public function setMaxResults(Crud $crud): void | |||
{ | |||
$entityClass = $this->getEntityFqcn(); | |||
@@ -300,7 +319,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$url = $this->get(AdminUrlGenerator::class) | |||
->setAction(Action::INDEX) | |||
->generateUrl(); | |||
$this->addFlash('success', $this->get(TranslatorAdmin::class)->transFlashMessage('sort'), array()); | |||
$this->addFlashTranslator('success', 'sorted'); | |||
return $this->redirect($url); | |||
} | |||
@@ -355,7 +374,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
->setEntityId($newEntity->getId()) | |||
->generateUrl(); | |||
$this->addFlash('success', $translatorAdmin->transFlashMessage('duplicate'), array()); | |||
$this->addFlashTranslator('success', 'duplicated'); | |||
return $this->redirect($url); | |||
} | |||
@@ -448,14 +467,25 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
{ | |||
$entityManager->update($entityInstance); | |||
$entityManager->flush(); | |||
$this->get(FlashBagTranslator::class)->add('success', 'updated', $this->getTranslationEntityName()); | |||
} | |||
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void | |||
{ | |||
$entityManager->create($entityInstance); | |||
$entityManager->flush(); | |||
$this->get(FlashBagTranslator::class)->add('success', 'created', $this->getTranslationEntityName()); | |||
} | |||
public function deleteEntity(EntityManagerInterface $entityManager, $entityInstance): void | |||
{ | |||
$entityManager->delete($entityInstance); | |||
$entityManager->flush(); | |||
$this->get(FlashBagTranslator::class)->add('success', 'deleted', $this->getTranslationEntityName()); | |||
} | |||
public function configureActions(Actions $actions): Actions | |||
{ |
@@ -17,6 +17,7 @@ use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | |||
use Lc\SovBundle\Container\User\GroupUserContainer; | |||
use Lc\SovBundle\Container\User\UserContainer; | |||
use Lc\SovBundle\Solver\Setting\SettingSolver; | |||
use Lc\SovBundle\Translation\FlashBagTranslator; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Psr\Log\LoggerInterface; | |||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SfAbstractController; | |||
@@ -48,6 +49,7 @@ class AbstractController extends SfAbstractController | |||
LoggerInterface::class => LoggerInterface::class, | |||
TranslatorInterface::class => TranslatorInterface::class, | |||
TranslatorAdmin::class => TranslatorAdmin::class, | |||
FlashBagTranslator::class => FlashBagTranslator::class, | |||
SettingSolver::class => SettingSolver::class, | |||
ComponentContainer::class => ComponentContainer::class, | |||
FileContainer::class => FileContainer::class, | |||
@@ -65,6 +67,16 @@ class AbstractController extends SfAbstractController | |||
); | |||
} | |||
public function addFlashTranslator(string $type, $translationKeyName, $translationEntityName = null, $translationParam = array()):void | |||
{ | |||
if ($translationEntityName === null && method_exists($this, 'getTranslationEntityName')) { | |||
$translationEntityName = $this->getTranslationEntityName(); | |||
} | |||
$this->get(FlashBagTranslator::class)->add($type, $translationKeyName, $translationEntityName, $translationParam); | |||
} | |||
public function getReferer(Request $request): ?string | |||
{ | |||
return $request->headers->get('referer'); | |||
@@ -194,4 +206,4 @@ class AbstractController extends SfAbstractController | |||
{ | |||
return $this->get(SiteSettingContainer::class); | |||
} | |||
} | |||
} |
@@ -97,7 +97,7 @@ class ReminderAdminController extends AbstractController | |||
$this->entityManager->persist($reminder); | |||
$this->entityManager->flush(); | |||
$this->addFlash('success', 'Le pense-bête a bien été ajouté'); | |||
$this->addFlashTranslator('success', 'added'); | |||
} | |||
return $this->redirect($request->headers->get('referer')); | |||
@@ -119,7 +119,7 @@ class ReminderAdminController extends AbstractController | |||
$this->entityManager->update($reminder); | |||
$this->entityManager->flush(); | |||
$this->addFlash('success', 'Le pense-bête a bien été mis à jour'); | |||
$this->addFlashTranslator('success', 'updated'); | |||
} | |||
return $this->redirect($request->headers->get('referer')); |
@@ -3,6 +3,7 @@ | |||
namespace Lc\SovBundle\Controller\Security; | |||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||
use Symfony\Component\HttpFoundation\Request; | |||
use Symfony\Component\HttpFoundation\Response; | |||
use Symfony\Component\Routing\Annotation\Route; | |||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; | |||
@@ -10,59 +11,61 @@ use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; | |||
class SecurityAdminController extends AbstractController | |||
{ | |||
/** | |||
* @Route("/user/login", name="sov_login") | |||
* @Route("/login", name="sov_login") | |||
*/ | |||
public function login(AuthenticationUtils $authenticationUtils): Response | |||
public function login(AuthenticationUtils $authenticationUtils, Request $request): Response | |||
{ | |||
if ($this->getUser()) { | |||
return $this->redirectToRoute('app_admin_dashboard'); | |||
} | |||
dump($request); | |||
if ($this->getUser()) { | |||
return $this->redirectToRoute('app_admin_dashboard'); | |||
} | |||
// get the login error if there is one | |||
$error = $authenticationUtils->getLastAuthenticationError(); | |||
// last username entered by the user | |||
$lastUsername = $authenticationUtils->getLastUsername(); | |||
return $this->render('@EasyAdmin/page/login.html.twig', [ | |||
// parameters usually defined in Symfony login forms | |||
'error' => $error, | |||
'last_username' => $lastUsername, | |||
return $this->render('@EasyAdmin/page/login.html.twig', [ | |||
// parameters usually defined in Symfony login forms | |||
'error' => $error, | |||
'last_username' => $lastUsername, | |||
// OPTIONAL parameters to customize the login form: | |||
// OPTIONAL parameters to customize the login form: | |||
// the translation_domain to use (define this option only if you are | |||
// rendering the login template in a regular Symfony controller; when | |||
// rendering it from an EasyAdmin Dashboard this is automatically set to | |||
// the same domain as the rest of the Dashboard) | |||
'translation_domain' => 'admin', | |||
// the translation_domain to use (define this option only if you are | |||
// rendering the login template in a regular Symfony controller; when | |||
// rendering it from an EasyAdmin Dashboard this is automatically set to | |||
// the same domain as the rest of the Dashboard) | |||
'translation_domain' => 'admin', | |||
// the title visible above the login form (define this option only if you are | |||
// rendering the login template in a regular Symfony controller; when rendering | |||
// it from an EasyAdmin Dashboard this is automatically set as the Dashboard title) | |||
'page_title' => '<img src="assets/img/'.$this->get('parameter_bag')->get('app.admin.logo').'" >', | |||
// the title visible above the login form (define this option only if you are | |||
// rendering the login template in a regular Symfony controller; when rendering | |||
// it from an EasyAdmin Dashboard this is automatically set as the Dashboard title) | |||
'page_title' => '<img src="assets/img/' . $this->get('parameter_bag')->get('app.admin.logo') . '" >', | |||
// the string used to generate the CSRF token. If you don't define | |||
// this parameter, the login form won't include a CSRF token | |||
'csrf_token_intention' => 'authenticate', | |||
// the string used to generate the CSRF token. If you don't define | |||
// this parameter, the login form won't include a CSRF token | |||
'csrf_token_intention' => 'authenticate', | |||
// the URL users are redirected to after the login (default: '/admin') | |||
'target_path' => $this->generateUrl('app_admin_dashboard'), | |||
// the URL users are redirected to after the login (default: '/admin') | |||
'target_path' => $this->generateUrl('app_admin_dashboard'), | |||
// the label displayed for the username form field (the |trans filter is applied to it) | |||
'username_label' => 'Your username', | |||
// the label displayed for the username form field (the |trans filter is applied to it) | |||
'username_label' => 'Your username', | |||
// the label displayed for the password form field (the |trans filter is applied to it) | |||
'password_label' => 'Your password', | |||
// the label displayed for the password form field (the |trans filter is applied to it) | |||
'password_label' => 'Your password', | |||
// the label displayed for the Sign In form button (the |trans filter is applied to it) | |||
'sign_in_label' => 'Log in', | |||
// the label displayed for the Sign In form button (the |trans filter is applied to it) | |||
'sign_in_label' => 'Log in', | |||
// the 'name' HTML attribute of the <input> used for the username field (default: '_username') | |||
'username_parameter' => 'email', | |||
// the 'name' HTML attribute of the <input> used for the username field (default: '_username') | |||
'username_parameter' => 'email', | |||
// the 'name' HTML attribute of the <input> used for the password field (default: '_password') | |||
'password_parameter' => 'password', | |||
]); | |||
// the 'name' HTML attribute of the <input> used for the password field (default: '_password') | |||
'password_parameter' => 'password', | |||
]); | |||
} | |||
/** | |||
@@ -70,6 +73,8 @@ class SecurityAdminController extends AbstractController | |||
*/ | |||
public function logout() | |||
{ | |||
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); | |||
throw new \LogicException( | |||
'This method can be blank - it will be intercepted by the logout key on your firewall.' | |||
); | |||
} | |||
} |
@@ -26,7 +26,7 @@ class SettingAdminController extends AbstractController | |||
$entityManager->update($site); | |||
$entityManager->flush(); | |||
$this->addFlash('success', $this->getTranslatorAdmin()->transFlashMessage('settings_saved')); | |||
$this->addFlashTranslator('success', 'updated'); | |||
} | |||
return $this->render( | |||
@@ -38,4 +38,4 @@ class SettingAdminController extends AbstractController | |||
); | |||
} | |||
} | |||
} |
@@ -40,7 +40,7 @@ class AccountAdminController extends AbstractController | |||
$this->entityManager->update($user); | |||
$this->entityManager->flush(); | |||
$this->addFlash('success', new TranslatableMessage('form.account_profile.message.success', [], 'admin')); | |||
$this->addFlashTranslator('success', 'updated'); | |||
} | |||
return $this->render( | |||
@@ -71,7 +71,7 @@ class AccountAdminController extends AbstractController | |||
$this->entityManager->update($user); | |||
$this->entityManager->flush(); | |||
$this->addFlash('success', new TranslatableMessage('form.account_password.message.success', [], 'admin')); | |||
$this->addFlashTranslator('success', 'passwordUpdated'); | |||
} | |||
return $this->render( |
@@ -1,50 +0,0 @@ | |||
<?php | |||
namespace Lc\SovBundle\EventSubscriber; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityDeletedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent; | |||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | |||
use Symfony\Component\Translation\TranslatableMessage; | |||
class FlashMessageAdminEventSubscriber implements EventSubscriberInterface | |||
{ | |||
protected $session ; | |||
public function __construct(SessionInterface $session) | |||
{ | |||
$this->session = $session ; | |||
} | |||
public static function getSubscribedEvents(): array | |||
{ | |||
return [ | |||
AfterEntityPersistedEvent::class => ['flashMessageAfterPersist'], | |||
AfterEntityUpdatedEvent::class => ['flashMessageAfterUpdate'], | |||
AfterEntityDeletedEvent::class => ['flashMessageAfterDelete'], | |||
]; | |||
} | |||
public function flashMessageAfterPersist(AfterEntityPersistedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.create', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
public function flashMessageAfterUpdate(AfterEntityUpdatedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.update', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
public function flashMessageAfterDelete(AfterEntityDeletedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.delete', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
} |
@@ -55,7 +55,7 @@ class CheckboxFilter | |||
); | |||
$queryBuilder->setParameter($fieldProperty, '%'.$filteredValue.'%'); | |||
} | |||
dump($queryBuilder); | |||
} | |||
} | |||
@@ -9,6 +9,7 @@ use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
use Symfony\Component\Form\FormInterface; | |||
use Symfony\Component\Form\FormView; | |||
use Symfony\Component\OptionsResolver\Options; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
/** | |||
@@ -27,20 +28,17 @@ class CrudFormType extends AbstractType | |||
DoctrineOrmTypeGuesser $doctrineOrmTypeGuesser, | |||
\EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType $crudFormType | |||
) { | |||
$this->parent = $crudFormType; | |||
$this->doctrineOrmTypeGuesser = $doctrineOrmTypeGuesser; | |||
} | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
$this->parent->buildForm($builder, $options); | |||
$entityDto = $options['entityDto']; | |||
$formPanels = []; | |||
$currentFormPanel = 0; | |||
foreach ($entityDto->getFields() as $fieldDto) { | |||
if (null === $formFieldType = $fieldDto->getFormType()) { | |||
$guessType = $this->doctrineOrmTypeGuesser->guessType($entityDto->getFqcn(), $fieldDto->getProperty()); | |||
$formFieldType = $guessType->getType(); | |||
@@ -67,12 +65,22 @@ class CrudFormType extends AbstractType | |||
public function finishView(FormView $view, FormInterface $form, array $options) | |||
{ | |||
$view->vars['translation_entity_name'] = $options['translation_entity_name']; | |||
$this->parent->finishView($view, $form, $options); | |||
} | |||
public function configureOptions(OptionsResolver $resolver) | |||
{ | |||
$this->parent->configureOptions($resolver); | |||
$resolver->setDefaults( | |||
[ | |||
'translation_entity_name' => static function (Options $options, $dataClass) { | |||
return $dataClass ?? $options['entityDto']->getFqcn(); | |||
} | |||
] | |||
); | |||
} | |||
public function getBlockPrefix() |
@@ -80,7 +80,7 @@ class MailMailjetNotification | |||
if (isset($params[self::CONTENT_DATA])) { | |||
$contentData = $params[self::CONTENT_DATA]; | |||
} | |||
dump($emailFrom); | |||
$message->addFrom($emailFrom, $emailFromName) | |||
->setBody($this->templating->render($params[self::CONTENT_TEMPLATE] . '-html.html.twig', $contentData), 'text/html') | |||
->addPart($this->templating->render($params[self::CONTENT_TEMPLATE] . '-text.html.twig', $contentData)); |
@@ -24,9 +24,7 @@ services: | |||
public: false | |||
decorates: doctrine.orm.default_entity_manager | |||
arguments: ["@.inner"] | |||
# EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType: | |||
# class: Lc\SovBundle\Form\Type\CrudFormType | |||
Lc\SovBundle\Maker\: | |||
resource: '../../Maker/' | |||
tags: [ 'maker.command' ] | |||
tags: [ 'maker.command' ] |
@@ -6,7 +6,7 @@ | |||
{% trans_default_domain ea.i18n.translationDomain %} | |||
{% block content_title %} | |||
{{ 'detail'|sov_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) }} | |||
{{ 'detail'|sov_trans_admin_title(translation_entity_name, {id: ea.getEntity().getInstance().getId()}) }} | |||
{% endblock %} | |||
{% block content_breadcrumb %} |
@@ -7,16 +7,16 @@ | |||
{% set form = new_form %} | |||
{% set body_id = 'ea-new-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-new ea-new-' ~ entity.name %} | |||
{% set content_title = 'new'|sov_trans_admin_title(ea.getEntity().getFqcn()) %} | |||
{% set body_id = 'ea-new-' ~translation_entity_name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-new ea-new-' ~ translation_entity_name %} | |||
{% set content_title = 'new'|sov_trans_admin_title(translation_entity_name) %} | |||
{% elseif ea.crud.currentAction == 'edit' %} | |||
{% set form = edit_form %} | |||
{% set body_id = 'ea-edit-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-edit ea-edit-' ~ entity.name %} | |||
{% set content_title = 'edit'|sov_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) %} | |||
{% set body_id = 'ea-edit-' ~ translation_entity_name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-edit ea-edit-' ~ translation_entity_name %} | |||
{% set content_title = 'edit'|sov_trans_admin_title(translation_entity_name, {id: ea.getEntity().getInstance().getId()}) %} | |||
{% endif %} | |||
@@ -2,6 +2,7 @@ | |||
{% use '@EasyAdmin/crud/form_theme.html.twig' %} | |||
{% block form_start %} | |||
{% if form.vars.errors|length > 0 and 'ea_crud' in form.vars.block_prefixes|default([]) %} | |||
{{ form_errors(form) }} | |||
{% endif %} | |||
@@ -92,6 +93,7 @@ | |||
{% endblock form_row %} | |||
{% block form_label -%} | |||
{% if label is same as(false) -%} | |||
<label>{# the empty <label> is needed to not break the form design #}</label> | |||
{%- else -%} | |||
@@ -115,10 +117,18 @@ | |||
{%- endif -%} | |||
{%- endif -%} | |||
{% set entityNameOrObject = form.parent.vars.data %} | |||
{% if form.parent.vars.translation_entity_name is defined %} | |||
{% set entityNameOrObject = form.parent.vars.translation_entity_name %} | |||
{% endif %} | |||
{# | |||
{% if not entityNameOrObject and form.parent.vars.errors.form.config.dataClass is defined %} | |||
{% set entityNameOrObject = form.parent.vars.errors.form.config.dataClass %} | |||
{% endif %} | |||
#} | |||
{% if translation_domain == null %} | |||
{% set translation_domain = 'admin' %} | |||
@@ -257,7 +267,7 @@ | |||
{% endblock file_manager_widget %} | |||
{% block checkbox_radio_label -%} | |||
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#} | |||
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#} | |||
{%- if widget is defined -%} | |||
{% set is_parent_custom = parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class or 'switch-custom' in parent_label_class) %} | |||
{% set is_custom = label_attr.class is defined and ('checkbox-custom' in label_attr.class or 'radio-custom' in label_attr.class or 'switch-custom' in label_attr.class) %} | |||
@@ -298,8 +308,9 @@ | |||
{# {{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain))|raw -}} #} | |||
{% set entityNameOrObject = form.parent.vars.data %} | |||
{% if not entityNameOrObject and form.parent.vars.errors.form.config.dataClass is defined %} | |||
{% set entityNameOrObject = form.parent.vars.errors.form.config.dataClass %} | |||
{% if form.parent.vars.translation_entity_name is defined %} | |||
{% set entityNameOrObject = form.parent.vars.translation_entity_name %} | |||
{% endif %} | |||
<!-- lorsque que le name est un entier "case radio"--> | |||
@@ -351,4 +362,4 @@ | |||
<textarea class="lc-ckeditor" {{ block('widget_attributes') }}>{{ value }}</textarea> | |||
{% endblock %} | |||
{% endblock %} |
@@ -9,7 +9,7 @@ | |||
{% block body_class 'index' ~ (entities|length > 0 ? ' index-' ~ entities|first.name : '') %} | |||
{% block content_title %} | |||
{{ 'index'|sov_trans_admin_title(ea.getEntity().getFqcn()) }} | |||
{{ 'index'|sov_trans_admin_title(translation_entity_name) }} | |||
{% endblock %} | |||
{% block content_breadcrumb %} | |||
@@ -90,11 +90,20 @@ | |||
dir="{{ ea.i18n.textDirection }}"> | |||
{% if field.isSortable %} | |||
<a href="{{ ea_url({ page: 1, sort: { (field.property): next_sort_direction } }).includeReferrer() }}"> | |||
{{ field.getProperty|sov_trans_admin_field(ea.getEntity().getFqcn()) }} | |||
{% if field.label is not null %} | |||
{{ field.label|raw }} | |||
{% else %} | |||
{{ field.getProperty|sov_trans_admin_field_index(translation_entity_name) }} | |||
{% endif %} | |||
<i class="fa fa-fw {{ column_icon }}"></i> | |||
</a> | |||
{% else %} | |||
<span>{{ field.getProperty|sov_trans_admin_field(ea.getEntity().getFqcn()) }}</span> | |||
{% if field.label is not null %} | |||
<span>{{ field.label|raw }}</span> | |||
{% else %} | |||
<span>{{ field.getProperty|sov_trans_admin_field_index(translation_entity_name) }}</span> | |||
{% endif %} | |||
{% endif %} | |||
</th> | |||
{% endif %} |
@@ -0,0 +1,22 @@ | |||
<?php | |||
namespace Lc\SovBundle\Session\Flash; | |||
use \Symfony\Component\HttpFoundation\Session\Flash\FlashBag as SfFlashBag; | |||
/** | |||
* class FlashBag. | |||
* | |||
* @author La clic !!!! | |||
*/ | |||
class FlashBag extends SfFlashBag | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function addTranslatable(string $type, $message, $eedf, $effe) | |||
{ | |||
$this->add($type,$message); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
<?php | |||
namespace Lc\SovBundle\Translation; | |||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | |||
/** | |||
* class FlashBag. | |||
* | |||
* @author La clic !!!! | |||
*/ | |||
class FlashBagTranslator | |||
{ | |||
protected SessionInterface $session; | |||
protected TranslatorAdmin $translatorAdmin; | |||
public function __construct(SessionInterface $session, TranslatorAdmin $translatorAdmin) | |||
{ | |||
$this->session = $session; | |||
$this->translatorAdmin = $translatorAdmin; | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function add( | |||
string $type, | |||
$translationKeyName, | |||
$translationEntityName = null, | |||
$translationParam = array() | |||
): void { | |||
$this->session->getFlashBag()->add( | |||
$type, | |||
$this->translatorAdmin->transFlashMessage( | |||
$type, | |||
$translationKeyName, | |||
$translationEntityName, | |||
$translationParam | |||
) | |||
); | |||
} | |||
} |
@@ -26,32 +26,52 @@ class TranslatorAdmin | |||
return $this->trans('menu.' . $menu); | |||
} | |||
public function transFlashMessage($name, $params = []): string | |||
public function transFlashMessage($type, $name, $entityClass = false, $params = []): string | |||
{ | |||
return $this->trans('flash_message.' . $name, $params); | |||
if ($entityClass) { | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdFlash($type . '.' . $name, $entityClass), | |||
$this->buildTransIdFlash($type . '.' . $name, $entityClass, true) | |||
); | |||
} else { | |||
return $this->trans('flash_message.' . $name, $params); | |||
} | |||
} | |||
public function transField($fieldName, $entityClass): string | |||
{ | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true) | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true) | |||
); | |||
} | |||
public function transChoices(array $choices, string $entityName,string $field): array | |||
public function transFieldIndex($fieldName, $entityClass): string | |||
{ | |||
$idTranslationFieldIndex = $this->buildTransIdField($fieldName.'Index', $entityClass); | |||
$translation = $this->trans($idTranslationFieldIndex); | |||
if ($translation == $idTranslationFieldIndex) { | |||
return $this->transField($fieldName, $entityClass); | |||
}else{ | |||
return $translation; | |||
} | |||
} | |||
public function transChoices(array $choices, string $entityName, string $field): array | |||
{ | |||
$newChoices = []; | |||
foreach ($choices as $key => $choice) { | |||
$newChoices[$this->transField($field.'Choices.'.$choice, $entityName)] = $choice; | |||
$newChoices[$this->transField($field . 'Choices.' . $choice, $entityName)] = $choice; | |||
} | |||
return $newChoices; | |||
} | |||
public function transChoice(string $entityName,string $field, string $choice): string | |||
public function transChoice(string $entityName, string $field, string $choice): string | |||
{ | |||
return $this->transField($field.'Choices.'.$choice, $entityName); | |||
return $this->transField($field . 'Choices.' . $choice, $entityName); | |||
} | |||
public function transHelp($fieldName, $entityClass): string | |||
@@ -59,25 +79,25 @@ class TranslatorAdmin | |||
$fieldName = $fieldName . '_help'; | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true), | |||
true | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true), | |||
true | |||
); | |||
} | |||
public function transPanel($panelName, $entityClass): string | |||
{ | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdPanel($panelName, $entityClass), | |||
$this->buildTransIdPanel($panelName, $entityClass, true) | |||
$this->buildTransIdPanel($panelName, $entityClass), | |||
$this->buildTransIdPanel($panelName, $entityClass, true) | |||
); | |||
} | |||
public function transModal($modalName, $entityClass): string | |||
{ | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdModal($modalName, $entityClass), | |||
$this->buildTransIdModal($modalName, $entityClass, true) | |||
$this->buildTransIdModal($modalName, $entityClass), | |||
$this->buildTransIdModal($modalName, $entityClass, true) | |||
); | |||
} | |||
@@ -96,6 +116,7 @@ class TranslatorAdmin | |||
$this->buildTransIdBox($cardName, $entityClass, true) | |||
); | |||
} | |||
public function transTitle($pageName, $entityClass = null, $params = []): string | |||
{ | |||
$entityName = $this->getEntityName($entityClass); | |||
@@ -105,8 +126,8 @@ class TranslatorAdmin | |||
if ($entityName) { | |||
$baseIdEntityLabel = 'entity.' . $entityName; | |||
$paramsTranslation = [ | |||
'%label%' => $this->trans($baseIdEntityLabel . '.label'), | |||
'%label_plurial%' => $this->trans($baseIdEntityLabel . '.label_plurial'), | |||
'%label%' => $this->trans($baseIdEntityLabel . '.label'), | |||
'%label_plurial%' => $this->trans($baseIdEntityLabel . '.label_plurial'), | |||
]; | |||
} | |||
@@ -115,8 +136,8 @@ class TranslatorAdmin | |||
} | |||
return $this->trans( | |||
'title.' . $pageName, | |||
$paramsTranslation | |||
'title.' . $pageName, | |||
$paramsTranslation | |||
); | |||
} | |||
@@ -164,6 +185,11 @@ class TranslatorAdmin | |||
return $this->buildTransIdEntitySection($boxName, $entityClass, 'boxes', $default); | |||
} | |||
private function buildTransIdFlash($flashName, $entityClass, $default = false): string | |||
{ | |||
return $this->buildTransIdEntitySection($flashName, $entityClass, 'flashes', $default); | |||
} | |||
private function buildTransIdEntitySection($name, $entityClass, $entitySection, $default): string | |||
{ | |||
if ($default) { |
@@ -42,6 +42,7 @@ class TranslatorTwigExtension extends AbstractExtension | |||
{ | |||
return [ | |||
new TwigFilter('sov_trans_admin_field', [$this, 'transAdminField']), | |||
new TwigFilter('sov_trans_admin_field_index', [$this, 'transAdminFieldIndex']), | |||
new TwigFilter('sov_trans_admin_help', [$this, 'transAdminHelp']), | |||
new TwigFilter('sov_trans_admin_panel', [$this, 'transAdminPanel']), | |||
new TwigFilter('sov_trans_admin_modal', [$this, 'transAdminModal']), | |||
@@ -76,6 +77,11 @@ class TranslatorTwigExtension extends AbstractExtension | |||
return $this->translatorAdmin->transField($fieldName, $entityClass); | |||
} | |||
public function transAdminFieldIndex($fieldName, $entityClass) | |||
{ | |||
return $this->translatorAdmin->transFieldIndex($fieldName, $entityClass); | |||
} | |||
public function transAdminChoice($choice, $fieldName, $entityClass) | |||
{ | |||
return $this->translatorAdmin->transChoice($entityClass, $fieldName, $choice); |
@@ -134,7 +134,7 @@ class TwigExtension extends AbstractExtension | |||
public function liip($path, $thumb = 'tile', $default = 'default.jpg') | |||
{ | |||
$this->fileComponent->liip($path, $thumb, $default); | |||
return $this->fileComponent->liip($path, $thumb, $default); | |||
} | |||
public function getFileManagerFolder() |