소스 검색

Merge branch 'develop'

v1
Guillaume 2 년 전
부모
커밋
b22e1ad412
100개의 변경된 파일4816개의 추가작업 그리고 766개의 파일을 삭제
  1. +40
    -17
      Authenticator/LoginFormAuthenticator.php
  2. +29
    -0
      Builder/Ticket/TicketBuilder.php
  3. +29
    -0
      Builder/User/UserBuilder.php
  4. +134
    -0
      Component/CitiesComponent.php
  5. +33
    -0
      Component/CookieComponent.php
  6. +68
    -0
      Component/DateComponent.php
  7. +94
    -0
      Component/EntityComponent.php
  8. +88
    -0
      Component/FileComponent.php
  9. +58
    -0
      Component/FormComponent.php
  10. +78
    -0
      Component/MetaComponent.php
  11. +14
    -0
      Component/NumberComponent.php
  12. +77
    -0
      Component/PointLocationComponent.php
  13. +198
    -0
      Component/StringComponent.php
  14. +39
    -0
      Container/File/FileContainer.php
  15. +39
    -0
      Container/Newsletter/NewsletterContainer.php
  16. +39
    -0
      Container/Reminder/ReminderContainer.php
  17. +57
    -0
      Container/Setting/SiteSettingContainer.php
  18. +39
    -0
      Container/Site/NewsContainer.php
  19. +39
    -0
      Container/Site/PageContainer.php
  20. +39
    -0
      Container/Site/SiteContainer.php
  21. +57
    -0
      Container/Ticket/TicketContainer.php
  22. +39
    -0
      Container/Ticket/TicketMessageContainer.php
  23. +39
    -0
      Container/User/GroupUserContainer.php
  24. +48
    -0
      Container/User/UserContainer.php
  25. +773
    -0
      Controller/AbstractAdminController.php
  26. +0
    -481
      Controller/Admin/AbstractCrudController.php
  27. +0
    -20
      Controller/Admin/UserCrudController.php
  28. +11
    -9
      Controller/Dashboard/DashboardAdminController.php
  29. +38
    -0
      Controller/Newsletter/NewsletterAdminController.php
  30. +154
    -0
      Controller/Reminder/ReminderAdminController.php
  31. +11
    -7
      Controller/Security/SecurityAdminController.php
  32. +54
    -0
      Controller/Setting/SettingAdminController.php
  33. +42
    -0
      Controller/Site/NewsAdminController.php
  34. +40
    -0
      Controller/Site/PageAdminController.php
  35. +188
    -0
      Controller/Ticket/TicketAdminController.php
  36. +23
    -18
      Controller/User/AccountAdminController.php
  37. +25
    -0
      Controller/User/GroupUserAdminController.php
  38. +50
    -0
      Controller/User/UserAdminController.php
  39. +127
    -0
      Definition/AbstractSettingDefinition.php
  40. +51
    -0
      Definition/RolesDefinition.php
  41. +16
    -0
      Definition/RolesDefinitionInterface.php
  42. +41
    -0
      Definition/SiteSettingDefinition.php
  43. +8
    -0
      Definition/SiteSettingDefinitionInterface.php
  44. +28
    -14
      DependencyInjection/Configuration.php
  45. +27
    -11
      Doctrine/EntityManager.php
  46. +27
    -0
      Doctrine/Extension/BlameableNullableTrait.php
  47. +15
    -0
      Doctrine/Extension/ClearIdTrait.php
  48. +1
    -1
      Doctrine/Extension/SluggableTrait.php
  49. +34
    -0
      Doctrine/QueryBuilder.php
  50. +28
    -0
      Event/EntityComponentEvent.php
  51. +6
    -3
      Event/EntityManager/EntityManagerEvent.php
  52. +0
    -73
      EventSubscriber/Action/ActionEasyAdminSubscriber.php
  53. +1
    -1
      EventSubscriber/FlashMessageAdminEventSubscriber.php
  54. +109
    -0
      EventSubscriber/SiteSettingEventSubscriber.php
  55. +52
    -0
      EventSubscriber/SluggablePropertyEventSubscriber.php
  56. +3
    -3
      EventSubscriber/SortablePropertyEventSubscriber.php
  57. +47
    -0
      EventSubscriber/User/UserPasswordEventSubscriber.php
  58. +8
    -0
      Factory/AbstractFactory.php
  59. +8
    -0
      Factory/FactoryInterface.php
  60. +18
    -0
      Factory/File/FileFactory.php
  61. +18
    -0
      Factory/Newsletter/NewsletterFactory.php
  62. +25
    -0
      Factory/Reminder/ReminderFactory.php
  63. +8
    -0
      Factory/Reminder/ReminderFactoryInterface.php
  64. +25
    -0
      Factory/Setting/SiteSettingFactory.php
  65. +8
    -0
      Factory/Setting/SiteSettingFactoryInterface.php
  66. +18
    -0
      Factory/Site/NewsFactory.php
  67. +8
    -0
      Factory/Site/NewsFactoryInterface.php
  68. +17
    -0
      Factory/Site/PageFactory.php
  69. +8
    -0
      Factory/Site/PageFactoryInterface.php
  70. +19
    -0
      Factory/Site/SiteFactory.php
  71. +8
    -0
      Factory/Site/SiteFactoryInterface.php
  72. +24
    -0
      Factory/Ticket/TicketFactory.php
  73. +8
    -0
      Factory/Ticket/TicketFactoryInterface.php
  74. +21
    -0
      Factory/Ticket/TicketMessageFactory.php
  75. +8
    -0
      Factory/Ticket/TicketMessageFactoryInterface.php
  76. +17
    -0
      Factory/User/GroupUserFactory.php
  77. +8
    -0
      Factory/User/GroupUserFactoryInterface.php
  78. +17
    -0
      Factory/User/UserFactory.php
  79. +8
    -0
      Factory/User/UserFactoryInterface.php
  80. +1
    -3
      Field/BooleanField.php
  81. +64
    -65
      Field/CollectionField.php
  82. +1
    -1
      Field/FileManagerField.php
  83. +67
    -0
      Field/Filter/AssociationFilter.php
  84. +62
    -0
      Field/Filter/CheckboxFilter.php
  85. +77
    -0
      Field/Filter/ChoiceFilter.php
  86. +64
    -0
      Field/Filter/DateFilter.php
  87. +175
    -0
      Field/Filter/FilterManager.php
  88. +37
    -0
      Field/Filter/FilterTrait.php
  89. +43
    -0
      Field/Filter/IntegerFilter.php
  90. +59
    -0
      Field/Filter/TextFilter.php
  91. +1
    -1
      Field/GalleryManagerField.php
  92. +1
    -2
      Field/ImageManagerField.php
  93. +21
    -23
      Field/StatusField.php
  94. +25
    -0
      Field/ToggleField.php
  95. +19
    -11
      Form/Common/CrudFormType.php
  96. +1
    -1
      Form/Common/FileManagerType.php
  97. +140
    -0
      Form/Common/FiltersFormType.php
  98. +1
    -1
      Form/Common/PositionType.php
  99. +89
    -0
      Form/Reminder/ReminderAdminFormType.php
  100. +117
    -0
      Form/Setting/BaseSettingType.php

+ 40
- 17
Authenticator/LoginFormAuthenticator.php 파일 보기

@@ -4,6 +4,7 @@ namespace Lc\SovBundle\Authenticator;

use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Doctrine\EntityManager;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface as SfUserInterface;
@@ -30,35 +31,39 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
protected $parameterBag;

public function __construct(
EntityManager $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
UserPasswordEncoderInterface $passwordEncoder
) {
EntityManager $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
UserPasswordEncoderInterface $passwordEncoder,
ParameterBagInterface $parameterBag
)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
$this->parameterBag = $parameterBag;
}

public function supports(Request $request)
{
return self::LOGIN_ROUTE === $request->attributes->get('_route')
&& $request->isMethod('POST');
&& $request->isMethod('POST');
}

public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
'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']
Security::LAST_USERNAME,
$credentials['email']
);

return $credentials;
@@ -72,7 +77,7 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P
}

$user = $this->entityManager->getRepository(UserInterface::class)->findOneBy(
['email' => $credentials['email']]
['email' => $credentials['email']]
);

if (!$user) {
@@ -100,13 +105,31 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P
{
$routeName = 'home';
$email = $request->request->get('email');
$user = $this->entityManager->getRepository(UserInterface::class)->findOneBy(['email' => $email]);

if ($user && ($user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_SUPER_ADMIN'))) {
$routeName = 'admin_dashboard';
$loginRedirection = $this->parameterBag->get('lc_sov.login_redirection');
$useReferer = $loginRedirection['redirect_referer'];
$rolesRedirection = $loginRedirection['roles_redirection'];

if (isset($useReferer) && $useReferer == true) {
$url = $request->request->get('_target_path');
} else {
$user = $this->entityManager->getRepository(UserInterface::class)->findOneBy(['email' => $email]);

if (!empty($user)) {
$roles = $user->getRoles();

foreach ($rolesRedirection as $roleRedirect) {
if (in_array($roleRedirect['role'], $roles)) {
$routeName = $roleRedirect['redirect'];
}
}
}
}

return new RedirectResponse($this->urlGenerator->generate($routeName));
if (isset($url) && !empty($url)) {
return new RedirectResponse($url);
} else {
return new RedirectResponse($this->urlGenerator->generate($routeName));
}
}

protected function getLoginUrl()

+ 29
- 0
Builder/Ticket/TicketBuilder.php 파일 보기

@@ -0,0 +1,29 @@
<?php

namespace Lc\SovBundle\Builder\Ticket;

use Lc\SovBundle\Component\FormComponent;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class TicketBuilder
{
protected FormComponent $formComponent;
protected ParameterBagInterface $parameterBag;

public function __construct(FormComponent $formComponent, ParameterBagInterface $parameterBag)
{
$this->formComponent = $formComponent;
$this->parameterBag = $parameterBag;
}

// uploadImageTicketMessage
public function uploadImageTicketMessage($formTicket): ?string
{
return $this->formComponent->uploadFile(
$formTicket,
'image',
$this->parameterBag->get('app.ticket_images_directory'),
$this->parameterBag->get('app.ticket_images_subdirectory')
);
}
}

+ 29
- 0
Builder/User/UserBuilder.php 파일 보기

@@ -0,0 +1,29 @@
<?php

namespace Lc\SovBundle\Builder\User;

use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Model\Newsletter\NewsletterInterface;
use Lc\SovBundle\Model\User\UserInterface;

class UserBuilder
{
protected EntityManagerInterface $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

public function setNewsletter(UserInterface $user, NewsletterInterface $newsletter, bool $subscribeNewsletter): void
{
if ($subscribeNewsletter) {
$user->addNewsletter($newsletter);
} else {
$user->removeNewsletter($newsletter);
}
$this->entityManager->persist($user);
$this->entityManager->flush();
}
}

+ 134
- 0
Component/CitiesComponent.php 파일 보기

@@ -0,0 +1,134 @@
<?php

namespace Lc\SovBundle\Component;

use Geocoder\Model\Coordinates;
use Geocoder\Provider\Addok\Addok;
use Geocoder\Provider\GoogleMaps\GoogleMaps;
use Geocoder\Provider\Nominatim\Nominatim;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpClient\HttplugClient;

class CitiesComponent
{
protected ParameterBagInterface $parameterBag;

public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}

public function callCitiesApi($method, $url, $data = false)
{
$url = 'https://geo.api.gouv.fr/' . $url;
$curl = curl_init();

switch ($method) {
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);

if ($data) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "PUT":
curl_setopt($curl, CURLOPT_PUT, 1);
break;
default:
if ($data) {
$url = sprintf("%s?%s", $url, http_build_query($data));
}
}

// Optional Authentication:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, "username:password");

curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

$result = curl_exec($curl);

curl_close($curl);

return $result;
}

public function getGeocoderProvider()
{
$provider = false;
$symfonyClient = new HttplugClient();
$configGeocoderProvider = $this->parameterBag->get('geocoder.provider');

/* API du gouvernement */
if ($configGeocoderProvider == 'addok') {
$provider = new Addok($symfonyClient, 'https://api-adresse.data.gouv.fr');
} /* Google Maps */
elseif ($configGeocoderProvider == 'googlemaps') {
$provider = new GoogleMaps($symfonyClient, null, $this->parameterBag->get('geocoder.api_key'));
} /* Nominatim : OpenStreetMap */
elseif ($configGeocoderProvider == 'nominatim') {
$provider = Nominatim::withOpenStreetMapServer(
$symfonyClient,
'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion'
);
}

if (!$provider) {
throw new \ErrorException('Aucun provider (geocoding) défini');
}

return $provider;
}

public function callAddressApi($query)
{
$provider = $this->getGeocoderProvider() ;;
$query = GeocodeQuery::create($query)->withData('type', 'housenumber');
$results = $provider->geocodeQuery($query);
$resultsToReturn = array();
foreach($results as $result) {
if ($result->getStreetNumber() && strlen($result->getStreetNumber()) > 0) {
$resultsToReturn[] = $result;
}
}
return $resultsToReturn;
}

public function callReverseAddressApi($latitude, $longitude)
{
$provider = $this->getGeocoderProvider() ;;
$query = ReverseQuery::create(new Coordinates($latitude, $longitude));
$results = $provider->reverseQuery($query);
return $results->all() ;
}

public function getZipByCity($city, $code = null)
{
$zip = null;

$paramsSearch = [
'nom' => $city,
'fields' => 'nom,codesPostaux'
];

if ($code != null && $code != 0) {
$paramsSearch['code'] = $code;
}

$returnCitiesSearchZip = json_decode($this->callCitiesApi('get', 'communes', $paramsSearch));

if ($returnCitiesSearchZip) {
foreach ($returnCitiesSearchZip as $citySearchZip) {
if (strtolower(trim($city)) == strtolower(trim($citySearchZip->nom))) {
$zip = $citySearchZip->codesPostaux[0];
}
}
}

return $zip;
}

}

+ 33
- 0
Component/CookieComponent.php 파일 보기

@@ -0,0 +1,33 @@
<?php

namespace Lc\SovBundle\Component;

use Lc\SovBundle\Resolver\UrlResolver;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class CookieComponent
{
protected UrlResolver $urlResolver;
protected ParameterBagInterface $parameterBag;

public function __construct(UrlResolver $urlResolver, ParameterBagInterface $parameterBag)
{
$this->urlResolver = $urlResolver;
$this->parameterBag = $parameterBag;
}

public function getCookieDomain()
{
return ($this->urlResolver->isServerLocalhost()) ? null : $this->parameterBag->get('app.cookie_domain_distant');
}

public function cryptCookie($data)
{
return base64_encode($data);
}

public function decryptCookie($data)
{
return base64_decode($data);
}
}

+ 68
- 0
Component/DateComponent.php 파일 보기

@@ -0,0 +1,68 @@
<?php

namespace Lc\SovBundle\Component;

class DateComponent
{
public function date($format, $timestamp)
{
setlocale(LC_TIME, 'fr_FR.UTF8', 'fr.UTF8', 'fr_FR.UTF-8', 'fr.UTF-8');
return strftime($format, $timestamp);
}

public function getNextDay($day)
{
return new \DateTime('next ' . $day);
}

public function getNextDayByNumber($number)
{
return $this->getNextDay($this->getDayByNumber($number, 'en'));
}

public function getDayByNumber($number, $lang = 'fr')
{
if ($lang == 'fr') {
$daysArray = [
1 => 'Lundi',
2 => 'Mardi',
3 => 'Mercredi',
4 => 'Jeudi',
5 => 'Vendredi',
6 => 'Samedi',
7 => 'Dimanche'
];
} else {
$daysArray = [
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
7 => 'Sunday',
];
}

if (isset($daysArray[$number])) {
return $daysArray[$number];
}

return '';
}

// getDeliverySlotHour
public function getHour(\DateTime $date)
{
$timestamp = $date->getTimestamp() ;
$hour = $this->date('%kh', $timestamp) ;
$minutes = $this->date('%M', $timestamp) ;

if($minutes != '00') {
$hour .= $minutes ;
}

return $hour ;
}

}

+ 94
- 0
Component/EntityComponent.php 파일 보기

@@ -0,0 +1,94 @@
<?php

namespace Lc\SovBundle\Component;

use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Event\EntityComponentEvent;
use Lc\SovBundle\Model\File\FileInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class EntityComponent
{
protected EntityManagerInterface $entityManager;
protected ParameterBagInterface $parameterBag;
protected EventDispatcherInterface $eventDispatcher;

public function __construct(
EntityManagerInterface $entityManager,
ParameterBagInterface $parameterBag,
EventDispatcherInterface $eventDispatcher
) {
$this->entityManager = $entityManager;
$this->parameterBag = $parameterBag;
$this->eventDispatcher = $eventDispatcher;
}

public function duplicateEntity($entity)
{
$newEntity = clone $entity;
$classMetadata = $this->entityManager->getClassMetadata(get_class($newEntity));

foreach ($classMetadata->getAssociationMappings() as $associationMapping){
if(in_array(FileInterface::class, class_implements($associationMapping['targetEntity']))){
$methodGet = 'get'.ucfirst($associationMapping['fieldName']);
$methodSet = 'set'.ucfirst($associationMapping['fieldName']);
if(method_exists($newEntity, $methodGet) && method_exists($newEntity, $methodSet)){
if(!is_null($newEntity->$methodGet())){
$newFile = clone $newEntity->$methodGet();
$newEntity->$methodSet($newFile);
}
}
}

}

//TODO dispatch event duplicate
/* if ($newEntity instanceof ProductFamilyInterface) {
// @TODO : à adapter
//$newEntity = $this->productFamilyUtils->processBeforePersistProductFamily($newEntity, false, true);
}
*/
$this->entityManager->create($newEntity);

$this->eventDispatcher->dispatch(new EntityComponentEvent($newEntity), EntityComponentEvent::DUPLICATE_EVENT);

return $newEntity;
}

public function duplicateEntityToOtherHub($entity, $hub)
{
$newEntity = $this->duplicateEntity($entity);

if ($hub) {
$newEntity->setMerchant($hub);
}
$this->entityManager->persist($newEntity);
$this->entityManager->flush();

return $newEntity;
}

public function duplicateImage($entity, $folder = false)
{
$basePath = $this->parameterBag->get('kernel.project_dir') . '/public/uploads/images/';

if ($entity->getImage() && file_exists($basePath . $entity->getImage())) {
$extension = strtolower(pathinfo($basePath . $entity->getImage(), PATHINFO_EXTENSION));

if ($extension == "jpg" || $extension == "png" || $extension == "gif") {
$newImage = md5(uniqid()) . '.' . $extension;
if ($folder) {
$newImage = $folder . '/' . $newImage;
}
copy($basePath . $entity->getImage(), $basePath . $newImage);
$entity->setImage($newImage);
} else {
$entity->setImage(null);
}
} else {
$entity->setImage(null);
}
return $entity;
}
}

+ 88
- 0
Component/FileComponent.php 파일 보기

@@ -0,0 +1,88 @@
<?php

namespace Lc\SovBundle\Component;


use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class FileComponent
{
protected ParameterBagInterface $parameterBag;

public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}

/**
* Retourne le chemin vers le dossier d'uploads de responsiveFilemanager
*
* @return string
*/
public function getFileManagerFolder()
{
return $this->parameterBag->get('app.path.images');
}

// lcLiip
public function liip($path, $thumb = 'tile', $default = 'default.jpg')
{
if (substr($path, 0, 1) === '/') $path = substr($path, 1);

if ($path) {
$fileManagerFolder = substr($this->getFileManagerFolder(), 1) ;

if (strpos($path, $fileManagerFolder) === false) {
$path = $fileManagerFolder . '/' . $path;
}

if (file_exists($path)) {
return $this->liipCacheHelper->getBrowserPath($path, $thumb);
}
}

return $this->liipCacheHelper->getBrowserPath($this->getFileManagerFolder() . '/' . $default, $thumb);
}

public function removeDir($dir)
{
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? $this->removeDir("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}

function folderToZip($folder, &$zipFile, $subfolder = null)
{
if ($zipFile == null) {
// no resource given, exit
return false;
}
// we check if $folder has a slash at its end, if not, we append one
$tabFolder = str_split($folder);
$tabSubFolder = str_split($subfolder);
$folder .= end($tabFolder) == "/" ? "" : "/";
$subfolder .= end($tabSubFolder) == "/" ? "" : "/";
// we start by going through all files in $folder
$handle = opendir($folder);
while ($f = readdir($handle)) {
if ($f != "." && $f != "..") {
if (is_file($folder . $f)) {
// if we find a file, store it
// if we have a subfolder, store it there
if ($subfolder != null)
$zipFile->addFile($folder . $f, $subfolder . $f);
else
$zipFile->addFile($folder . $f);
} elseif (is_dir($folder . $f)) {
// if we find a folder, create a folder in the zip
$zipFile->addEmptyDir($f);
// and call the function again
folderToZip($folder . $f, $zipFile, $f);
}
}
}
}

}

+ 58
- 0
Component/FormComponent.php 파일 보기

@@ -0,0 +1,58 @@
<?php

namespace Lc\SovBundle\Component;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\File\Exception\FileException;

class FormComponent
{
protected ParameterBagInterface $parameterBag;

public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}

public function addCaptchaType(FormBuilderInterface $builder)
{
$builder->add('specialField', HiddenType::class, [
'data' => 0,
'mapped' => false,
'attr' => [
'class' => 'special-field'
],
'constraints' => [
new NotNull(),
new EqualTo(['value' => $this->parameterBag->get('app.captcha_value'), 'message' => 'Valeur incorrecte'])
],
]);
}

// uploadImageTicketMessage
public function uploadFile($form, $child, $directory, $subdirectory): ?string
{
$file = $form->get($child)->getData();

if ($file) {
$originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$newFilename = uniqid().'.'.$file->guessExtension();

try {
$file->move(
$directory,
$newFilename
);
} catch (FileException $e) {
throw new \ErrorException("Une erreur est survenue lors de l'upload du fichier.");
}

return $subdirectory.$newFilename;
}

return false;
}

}

+ 78
- 0
Component/MetaComponent.php 파일 보기

@@ -0,0 +1,78 @@
<?php

namespace Lc\SovBundle\Component;

class MetaComponent
{

public function getMetaTitle($entity)
{
if($entity) {
if(method_exists($entity, 'getMetaTitle')) {
return $entity->getMetaTitle() ;
}
elseif(method_exists($entity, 'getTitle')) {
return $entity->getTitle() ;
}
}

return '' ;
}

public function getMetaDescription($entity)
{
if($entity) {
if(method_exists($entity, 'getMetaDescription')) {
return $entity->getMetaDescription() ;
}
elseif(method_exists($entity, 'getDescription')) {
return $entity->getDescription() ;
}
}

return '' ;
}

public function getOpenGraphTitle($entity)
{
if($entity) {
if(method_exists($entity, 'getOpenGraphTitle')) {
return $entity->getOpenGraphTitle() ;
}
elseif(method_exists($entity, 'getTitle')) {
return $entity->getTitle() ;
}
}

return '' ;
}

public function getOpenGraphDescription($entity)
{
if($entity) {
if(method_exists($entity, 'getOpenGraphDescription')) {
return $entity->getOpenGraphDescription() ;
}
elseif(method_exists($entity, 'getDescription')) {
return $entity->getDescription() ;
}
}

return '' ;
}

public function getOpenGraphImage($entity)
{
if($entity) {
if(method_exists($entity, 'getOpenGraphImage')) {
return $entity->getOpenGraphImage() ;
}
elseif(method_exists($entity, 'getImage')) {
return $entity->getImage() ;
}
}

return '' ;
}

}

+ 14
- 0
Component/NumberComponent.php 파일 보기

@@ -0,0 +1,14 @@
<?php

namespace Lc\SovBundle\Component;


class NumberComponent
{
public function round($price, $precision = 2)
{
return round((($price * 100)) / 100, $precision);
}


}

+ 77
- 0
Component/PointLocationComponent.php 파일 보기

@@ -0,0 +1,77 @@
<?php

namespace Lc\SovBundle\Component;

class PointLocationComponent
{
var $pointOnVertex = true; // Check if the point sits exactly on one of the vertices?

function pointInPolygon($point, $polygon, $pointOnVertex = true)
{
$this->pointOnVertex = $pointOnVertex;

// Transform string coordinates into arrays with x and y values
$point = $this->pointStringToCoordinates($point);
$vertices = array();
foreach ($polygon as $vertex) {
$vertices[] = $this->pointStringToCoordinates($vertex);
}

// Check if the point sits exactly on a vertex
if ($this->pointOnVertex == true and $this->pointOnVertex($point, $vertices) == true) {
return "vertex";
}

// Check if the point is inside the polygon or on the boundary
$intersections = 0;
$vertices_count = count($vertices);

for ($i = 1; $i < $vertices_count; $i++) {
$vertex1 = $vertices[$i - 1];
$vertex2 = $vertices[$i];
if ($vertex1['y'] == $vertex2['y'] and $vertex1['y'] == $point['y'] and $point['x'] > min(
$vertex1['x'],
$vertex2['x']
) and $point['x'] < max(
$vertex1['x'],
$vertex2['x']
)) { // Check if point is on an horizontal polygon boundary
return "boundary";
}
if ($point['y'] > min($vertex1['y'], $vertex2['y']) and $point['y'] <= max(
$vertex1['y'],
$vertex2['y']
) and $point['x'] <= max($vertex1['x'], $vertex2['x']) and $vertex1['y'] != $vertex2['y']) {
$xinters = ($point['y'] - $vertex1['y']) * ($vertex2['x'] - $vertex1['x']) / ($vertex2['y'] - $vertex1['y']) + $vertex1['x'];
if ($xinters == $point['x']) { // Check if point is on the polygon boundary (other than horizontal)
return "boundary";
}
if ($vertex1['x'] == $vertex2['x'] || $point['x'] <= $xinters) {
$intersections++;
}
}
}
// If the number of edges we passed through is odd, then it's in the polygon.
if ($intersections % 2 != 0) {
return "inside";
} else {
return "outside";
}
}

function pointOnVertex($point, $vertices)
{
foreach ($vertices as $vertex) {
if ($point == $vertex) {
return true;
}
}
}

function pointStringToCoordinates($pointString)
{
$coordinates = explode(" ", $pointString);
return array("x" => $coordinates[0], "y" => $coordinates[1]);
}

}

+ 198
- 0
Component/StringComponent.php 파일 보기

@@ -0,0 +1,198 @@
<?php

namespace Lc\SovBundle\Component;

use Cocur\Slugify\Slugify;

class StringComponent
{
public function limitText($text, $limit)
{
$text = strip_tags($text);
if (str_word_count($text, 0) > $limit) {
$words = str_word_count($text, 2);
$pos = array_keys($words);
$text = substr($text, 0, $pos[$limit]) . '...';
}
return $text;
}

public function limitTextByLength($text, $length, $append = '...')
{
if (strlen($text) > $length) {
$text = substr($text, 0, $length) . $append;
}

return $text;
}

function truncateHtml($text, $length = 100, $ending = '...', $exact = false, $considerHtml = true)
{
if ($considerHtml) {
// if the plain text is shorter than the maximum length, return the whole text
if (strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
// splits all html-tags to scanable lines
preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
$total_length = strlen($ending);
$open_tags = array();
$truncate = '';
foreach ($lines as $line_matchings) {
// if there is any html-tag in this line, handle it and add it (uncounted) to the output
if (!empty($line_matchings[1])) {
// if it's an "empty element" with or without xhtml-conform closing slash
if (preg_match(
'/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is',
$line_matchings[1]
)) {
// do nothing
// if tag is a closing tag
} else {
if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
// delete tag from $open_tags list
$pos = array_search($tag_matchings[1], $open_tags);
if ($pos !== false) {
unset($open_tags[$pos]);
}
// if tag is an opening tag
} else {
if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
// add tag to the beginning of $open_tags list
array_unshift($open_tags, strtolower($tag_matchings[1]));
}
}
}
// add html-tag to $truncate'd text
$truncate .= $line_matchings[1];
}
// calculate the length of the plain text part of the line; handle entities as one character
$content_length = strlen(
preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2])
);
if ($total_length + $content_length > $length) {
// the number of characters which are left
$left = $length - $total_length;
$entities_length = 0;
// search for html entities
if (preg_match_all(
'/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
$line_matchings[2],
$entities,
PREG_OFFSET_CAPTURE
)) {
// calculate the real length of all entities in the legal range
foreach ($entities[0] as $entity) {
if ($entity[1] + 1 - $entities_length <= $left) {
$left--;
$entities_length += strlen($entity[0]);
} else {
// no more characters left
break;
}
}
}
$truncate .= substr($line_matchings[2], 0, $left + $entities_length);
// maximum lenght is reached, so get off the loop
break;
} else {
$truncate .= $line_matchings[2];
$total_length += $content_length;
}
// if the maximum length is reached, get off the loop
if ($total_length >= $length) {
break;
}
}
} else {
if (strlen($text) <= $length) {
return $text;
} else {
$truncate = substr($text, 0, $length - strlen($ending));
}
}
// if the words shouldn't be cut in the middle...
if (!$exact) {
// ...search the last occurance of a space...
$spacepos = strrpos($truncate, ' ');
if (isset($spacepos)) {
// ...and cut the text in this position
$truncate = substr($truncate, 0, $spacepos);
}
}
// add the defined ending to the text
$truncate .= $ending;
if ($considerHtml) {
// close all unclosed html-tags
foreach ($open_tags as $tag) {
$truncate .= '</' . $tag . '>';
}
}
return $truncate;
}

function stripAccents($stripAccents)
{
return strtr(
$stripAccents,
'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ',
'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY'
);
}

function cleanStringToCompare($string)
{
return $this->stripAccents(trim(strtolower($string)));
}

public function slugify($string)
{
$slugify = new Slugify();
return $slugify->slugify($string);
}

function camelCase($str)
{
$i = array("-", "_");
$str = preg_replace('/([a-z])([A-Z])/', "\\1 \\2", $str);
$str = preg_replace('@[^a-zA-Z0-9\-_ ]+@', '', $str);
$str = str_replace($i, ' ', $str);
$str = str_replace(' ', '', ucwords(strtolower($str)));
$str = strtolower(substr($str, 0, 1)) . substr($str, 1);
return $str;
}

function snakeCase($str)
{
$str = preg_replace('/([a-z])([A-Z])/', "\\1_\\2", $str);
$str = strtolower($str);
return $str;
}

public function csvEscape($str)
{
return str_replace(array("\r", "\n"), ' ', $str);
}

public function urlEncryptData($datas){
$key = 'secretToken';
foreach ($datas as $data) {
$key .= $data;
}
return md5($key);
}

public function formatPhoneNumber($phone)
{
$phone = preg_replace('`[^0-9]`', '', $phone);
if(strlen($phone) == 10) {
$phone = '+33'.substr($phone, 1, 9) ;
}
elseif(strlen($phone) == 11 && substr($phone, 0, 2) == '33') {
$phone = '+'.$phone ;
}

return $phone ;
}

}

+ 39
- 0
Container/File/FileContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\File;

use Lc\SovBundle\Factory\File\FileFactory;
use Lc\SovBundle\Repository\File\FileRepositoryQuery;
use Lc\SovBundle\Repository\File\FileStore;

class FileContainer
{
protected FileFactory $factory;
protected FileRepositoryQuery $repositoryQuery;
protected FileStore $store;

public function __construct(
FileFactory $factory,
FileRepositoryQuery $repositoryQuery,
FileStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): FileFactory
{
return $this->factory;
}

public function getRepositoryQuery(): FileRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): FileStore
{
return $this->store;
}
}

+ 39
- 0
Container/Newsletter/NewsletterContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Newsletter;

use Lc\SovBundle\Factory\Newsletter\NewsletterFactory;
use Lc\SovBundle\Repository\Newsletter\NewsletterRepositoryQuery;
use Lc\SovBundle\Repository\Newsletter\NewsletterStore;

class NewsletterContainer
{
protected NewsletterFactory $factory;
protected NewsletterRepositoryQuery $repositoryQuery;
protected NewsletterStore $store;

public function __construct(
NewsletterFactory $factory,
NewsletterRepositoryQuery $repositoryQuery,
NewsletterStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): NewsletterFactory
{
return $this->factory;
}

public function getRepositoryQuery(): NewsletterRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): NewsletterStore
{
return $this->store;
}
}

+ 39
- 0
Container/Reminder/ReminderContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Reminder;

use Lc\SovBundle\Factory\Reminder\ReminderFactory;
use Lc\SovBundle\Repository\Reminder\ReminderRepositoryQuery;
use Lc\SovBundle\Repository\Reminder\ReminderStore;

class ReminderContainer
{
protected ReminderFactory $factory;
protected ReminderRepositoryQuery $repositoryQuery;
protected ReminderStore $store;

public function __construct(
ReminderFactory $factory,
ReminderRepositoryQuery $repositoryQuery,
ReminderStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): ReminderFactory
{
return $this->factory;
}

public function getRepositoryQuery(): ReminderRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): ReminderStore
{
return $this->store;
}
}

+ 57
- 0
Container/Setting/SiteSettingContainer.php 파일 보기

@@ -0,0 +1,57 @@
<?php

namespace Lc\SovBundle\Container\Setting;

use Lc\SovBundle\Definition\SiteSettingDefinition;
use Lc\SovBundle\Factory\Setting\SiteSettingFactory;
use Lc\SovBundle\Repository\Setting\SiteSettingRepositoryQuery;
use Lc\SovBundle\Repository\Setting\SiteSettingStore;
use Lc\SovBundle\Solver\Setting\SettingSolver;

class SiteSettingContainer
{
protected SiteSettingFactory $factory;
protected SiteSettingDefinition $definition;
protected SiteSettingRepositoryQuery $repositoryQuery;
protected SiteSettingStore $store;
protected SettingSolver $settingSolver;

public function __construct(
SiteSettingFactory $factory,
SiteSettingDefinition $definition,
SiteSettingRepositoryQuery $repositoryQuery,
SiteSettingStore $store,
SettingSolver $settingSolver
) {
$this->factory = $factory;
$this->definition = $definition;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
$this->settingSolver = $settingSolver;
}

public function getFactory(): SiteSettingFactory
{
return $this->factory;
}

public function getDefinition(): SiteSettingDefinition
{
return $this->definition;
}

public function getRepositoryQuery(): SiteSettingRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): SiteSettingStore
{
return $this->store;
}

public function getSettingSolver(): SettingSolver
{
return $this->settingSolver;
}
}

+ 39
- 0
Container/Site/NewsContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Site;

use Lc\SovBundle\Factory\Site\NewsFactory;
use Lc\SovBundle\Repository\Site\NewsRepositoryQuery;
use Lc\SovBundle\Repository\Site\NewsStore;

class NewsContainer
{
protected NewsFactory $factory;
protected NewsRepositoryQuery $repositoryQuery;
protected NewsStore $store;

public function __construct(
NewsFactory $factory,
NewsRepositoryQuery $repositoryQuery,
NewsStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): NewsFactory
{
return $this->factory;
}

public function getRepositoryQuery(): NewsRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): NewsStore
{
return $this->store;
}
}

+ 39
- 0
Container/Site/PageContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Site;

use Lc\SovBundle\Factory\Site\PageFactory;
use Lc\SovBundle\Repository\Site\PageRepositoryQuery;
use Lc\SovBundle\Repository\Site\PageStore;

class PageContainer
{
protected PageFactory $factory;
protected PageRepositoryQuery $repositoryQuery;
protected PageStore $store;

public function __construct(
PageFactory $factory,
PageRepositoryQuery $repositoryQuery,
PageStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): PageFactory
{
return $this->factory;
}

public function getRepositoryQuery(): PageRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): PageStore
{
return $this->store;
}
}

+ 39
- 0
Container/Site/SiteContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Site;

use Lc\SovBundle\Factory\Site\SiteFactory;
use Lc\SovBundle\Repository\Site\SiteRepositoryQuery;
use Lc\SovBundle\Repository\Site\SiteStore;

class SiteContainer
{
protected SiteFactory $factory;
protected SiteRepositoryQuery $repositoryQuery;
protected SiteStore $store;

public function __construct(
SiteFactory $factory,
SiteRepositoryQuery $repositoryQuery,
SiteStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): SiteFactory
{
return $this->factory;
}

public function getRepositoryQuery(): SiteRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): SiteStore
{
return $this->store;
}
}

+ 57
- 0
Container/Ticket/TicketContainer.php 파일 보기

@@ -0,0 +1,57 @@
<?php

namespace Lc\SovBundle\Container\Ticket;

use Lc\SovBundle\Builder\Ticket\TicketBuilder;
use Lc\SovBundle\Factory\Ticket\TicketFactory;
use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery;
use Lc\SovBundle\Repository\Ticket\TicketStore;
use Lc\SovBundle\Solver\Ticket\TicketSolver;

class TicketContainer
{
protected TicketFactory $factory;
protected TicketBuilder $builder;
protected TicketRepositoryQuery $repositoryQuery;
protected TicketStore $store;
protected TicketSolver $solver;

public function __construct(
TicketFactory $factory,
TicketBuilder $builder,
TicketRepositoryQuery $repositoryQuery,
TicketStore $store,
TicketSolver $solver
) {
$this->factory = $factory;
$this->builder = $builder;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
$this->solver = $solver;
}

public function getFactory(): TicketFactory
{
return $this->factory;
}

public function getBuilder(): TicketBuilder
{
return $this->builder;
}

public function getRepositoryQuery(): TicketRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): TicketStore
{
return $this->store;
}

public function getSolver(): TicketSolver
{
return $this->solver;
}
}

+ 39
- 0
Container/Ticket/TicketMessageContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\Ticket;

use Lc\SovBundle\Factory\Ticket\TicketMessageFactory;
use Lc\SovBundle\Repository\Ticket\TicketMessageRepositoryQuery;
use Lc\SovBundle\Repository\Ticket\TicketMessageStore;

class TicketMessageContainer
{
protected TicketMessageFactory $factory;
protected TicketMessageRepositoryQuery $repositoryQuery;
protected TicketMessageStore $store;

public function __construct(
TicketMessageFactory $factory,
TicketMessageRepositoryQuery $repositoryQuery,
TicketMessageStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): TicketMessageFactory
{
return $this->factory;
}

public function getRepositoryQuery(): TicketMessageRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): TicketMessageStore
{
return $this->store;
}
}

+ 39
- 0
Container/User/GroupUserContainer.php 파일 보기

@@ -0,0 +1,39 @@
<?php

namespace Lc\SovBundle\Container\User;

use Lc\SovBundle\Factory\User\GroupUserFactory;
use Lc\SovBundle\Repository\User\GroupUserRepositoryQuery;
use Lc\SovBundle\Repository\User\GroupUserStore;

class GroupUserContainer
{
protected GroupUserFactory $factory;
protected GroupUserRepositoryQuery $repositoryQuery;
protected GroupUserStore $store;

public function __construct(
GroupUserFactory $factory,
GroupUserRepositoryQuery $repositoryQuery,
GroupUserStore $store
) {
$this->factory = $factory;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): GroupUserFactory
{
return $this->factory;
}

public function getRepositoryQuery(): GroupUserRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): GroupUserStore
{
return $this->store;
}
}

+ 48
- 0
Container/User/UserContainer.php 파일 보기

@@ -0,0 +1,48 @@
<?php

namespace Lc\SovBundle\Container\User;

use Lc\SovBundle\Builder\User\UserBuilder;
use Lc\SovBundle\Factory\User\UserFactory;
use Lc\SovBundle\Repository\User\UserRepositoryQuery;
use Lc\SovBundle\Repository\User\UserStore;

class UserContainer
{
protected UserFactory $factory;
protected UserBuilder $builder;
protected UserRepositoryQuery $repositoryQuery;
protected UserStore $store;

public function __construct(
UserFactory $factory,
UserBuilder $builder,
UserRepositoryQuery $repositoryQuery,
UserStore $store
) {
$this->factory = $factory;
$this->builder = $builder;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
}

public function getFactory(): UserFactory
{
return $this->factory;
}

public function getBuilder(): UserBuilder
{
return $this->builder;
}

public function getRepositoryQuery(): UserRepositoryQuery
{
return $this->repositoryQuery;
}

public function getStore(): UserStore
{
return $this->store;
}
}

+ 773
- 0
Controller/AbstractAdminController.php 파일 보기

@@ -0,0 +1,773 @@
<?php

namespace Lc\SovBundle\Controller;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
use EasyCorp\Bundle\EasyAdminBundle\Factory\ControllerFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
use Lc\SovBundle\Component\EntityComponent;
use Lc\SovBundle\Container\File\FileContainer;
use Lc\SovBundle\Container\Newsletter\NewsletterContainer;
use Lc\SovBundle\Container\Reminder\ReminderContainer;
use Lc\SovBundle\Container\Setting\SiteSettingContainer;
use Lc\SovBundle\Container\Site\NewsContainer;
use Lc\SovBundle\Container\Site\PageContainer;
use Lc\SovBundle\Container\Site\SiteContainer;
use Lc\SovBundle\Container\Ticket\TicketContainer;
use Lc\SovBundle\Container\Ticket\TicketMessageContainer;
use Lc\SovBundle\Container\User\GroupUserContainer;
use Lc\SovBundle\Container\User\UserContainer;
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
use Lc\SovBundle\Doctrine\Extension\SeoInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Field\CollectionField;
use Lc\SovBundle\Field\Filter\FilterManager;
use Lc\SovBundle\Form\Common\FiltersFormType;
use Lc\SovBundle\Form\Common\PositionType;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;


abstract class AbstractAdminController extends EaAbstractCrudController
{
protected FormInterface $filtersForm;

public static function getSubscribedServices()
{
return array_merge(
parent::getSubscribedServices(),
[
TranslatorAdmin::class => TranslatorAdmin::class,
SessionInterface::class => SessionInterface::class,
RequestStack::class => RequestStack::class,
EntityManagerInterface::class => EntityManagerInterface::class,
FilterManager::class => FilterManager::class,
FileContainer::class => FileContainer::class,
NewsletterContainer::class => NewsletterContainer::class,
ReminderContainer::class => ReminderContainer::class,
NewsContainer::class => NewsContainer::class,
PageContainer::class => PageContainer::class,
SiteContainer::class => SiteContainer::class,
TicketContainer::class => TicketContainer::class,
TicketMessageContainer::class => TicketMessageContainer::class,
GroupUserContainer::class => GroupUserContainer::class,
UserContainer::class => UserContainer::class,
SiteSettingContainer::class => SiteSettingContainer::class,

]
);
}


public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
{
$this->overrideGlobalActions($responseParameters->get('global_actions'));
$this->overrideEntitiesActions($responseParameters->get('entities'));
if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
$responseParameters->set('fields', $this->configureFields('index'));

if ($this->filtersForm === null) {
die('nncncd');
//TODO delete under code
$options['fields'] = $responseParameters->get('fields');
$options['entity_class'] = $this->getEntityFqcn();
$options['entity_name'] = $responseParameters->get('entity')->getName();
$this->filtersForm = $this->createForm(FiltersFormType::class, null, $options);
}
$responseParameters->set('filters_form', $this->filtersForm);
}

return $responseParameters;
}

public function overrideEntitiesActions(?EntityCollection $entities): void
{
}

public function overrideGlobalActions(?ActionCollection $actions): void
{
if ($actions) {
$context = $this->get(AdminContextProvider::class)->getContext();
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);

foreach ($actions as $i => $action) {
//récriture du bouton 'retour au parent'
if ($action->getName() == 'index_parent') {
$entity = $context->getEntity()->getInstance();
if ($entity !== null) {
if ($entity->getParent() !== null) {
$url = $adminUrlGenerator
->setController($context->getCrud()->getControllerFqcn())
->set('entityId', $entity->getParent()->getId())
->generateUrl();
$action->setLinkUrl($url);
}
} else {
unset($actions[$i]);
}
}

if ($action->getName() == 'sort') {
$entityId = $context->getRequest()->get('entityId');
if ($entityId != null) {
$url = $adminUrlGenerator
->setController($context->getCrud()->getControllerFqcn())
->setAction($action->getName())
->set('entityId', $entityId)
->generateUrl();
$action->setLinkUrl($url);
}
}
}
}
}

public function configureCrud(Crud $crud): Crud
{
$crud = parent::configureCrud($crud);

$this->setMaxResults($crud);

if ($this->isInstanceOf(SortableInterface::class)) {
$crud->setDefaultSort(['position' => 'ASC']);
}

return $crud;
}

public function setMaxResults(Crud $crud): void
{
$entityClass = $this->getEntityFqcn();
$paramListMaxResults = 'listMaxResults';
$paramSessionListMaxResults = $entityClass.'-'.$paramListMaxResults;
$requestListMaxResults = $this->get(RequestStack::class)->getCurrentRequest()->get($paramListMaxResults);

if ($requestListMaxResults) {
$this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults);
}
$maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get(
$paramSessionListMaxResults
) : 30;

$crud->setPaginatorPageSize($maxResults);
}

public function getSeoPanel(): ?array
{
if ($this->isInstanceOf(SeoInterface::class)) {
return [
FormField::addPanel('seo')->setTemplateName('crud/field/generic'),
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
'Affiché dans les résultats de recherche Google'
)->hideOnIndex(),
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp(
'Affiché dans les résultats de recherche Google'
)->hideOnIndex(),
CollectionField::new('oldUrls')
->setFormTypeOption('entry_type', TextType::class)->setLabel(
'Anciennes urls du document'
)->hideOnIndex(),
];
} else {
return null;
}
}

public function getConfPanel(): ?array
{
if ($this->isInstanceOf(DevAliasInterface::class)) {
return [
FormField::addPanel('configuration')->setTemplateName('crud/field/generic'),
TextField::new('devAlias')->hideOnIndex(),
];
} else {
return null;
}
}

public function sort(AdminContext $context)
{
$event = new BeforeCrudActionEvent($context);
$this->get('event_dispatcher')->dispatch($event);
if ($event->isPropagationStopped()) {
return $event->getResponse();
}

//if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
if (!$this->isInstanceOf(SortableInterface::class)) {
throw new ForbiddenActionException($context);
}

$fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
$filters = $this->get(FilterFactory::class)->create(
$context->getCrud()->getFiltersConfig(),
$fields,
$context->getEntity()
);
$queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters);
$paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);

$entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults());
$this->get(EntityFactory::class)->processFieldsForAll($entities, $fields);

$sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults()))
->add(
'entities',
CollectionType::class,
array(
'required' => true,
'allow_add' => true,
'entry_type' => PositionType::class,
)
)
->getForm();

$entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
$repository = $entityManager->getRepository($this->getEntityFqcn());

$sortableForm->handleRequest($context->getRequest());

if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
foreach ($sortableForm->get('entities')->getData() as $elm) {
$entityInstance = $repository->find($elm['id']);
$entityDto = $context->getEntity()->newWithInstance($entityInstance);

if (!$entityDto->isAccessible()) {
throw new InsufficientEntityPermissionException($context);
}

$event = new BeforeEntityDeletedEvent($entityInstance);
$this->get('event_dispatcher')->dispatch($event);
$entityInstance = $event->getEntityInstance();

$entityInstance->setPosition($elm['position']);
$this->updateEntity($entityManager, $entityInstance);

$this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance));
}

$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('success', $this->translatorAdmin->transFlashMessage('sort'), array());

return $this->redirect($url);
}

$responseParameters = $this->configureResponseParameters(
KeyValueStore::new(
[
'pageName' => Crud::PAGE_INDEX,
'templatePath' => '@LcSov/adminlte/crud/sort.html.twig',
'entities' => $entities,
'paginator' => $paginator,
'global_actions' => array(),
'batch_actions' => array(),
'filters' => $filters,
'sortable_form' => $sortableForm,
]
)
);
$responseParameters->set('fields', $this->configureFields('index'));
$event = new AfterCrudActionEvent($context, $responseParameters);
$this->get('event_dispatcher')->dispatch($event);
if ($event->isPropagationStopped()) {
return $event->getResponse();
}

return $responseParameters;
}

public function duplicate(AdminContext $context, EntityComponent $entityComponent, TranslatorAdmin $translatorAdmin, EntityManagerInterface $em)
{

if (!$this->isGranted(
Permission::EA_EXECUTE_ACTION,
['action' => "duplicate", 'entity' => $context->getEntity()]
)) {
throw new ForbiddenActionException($context);
}

if (!$context->getEntity()->isAccessible()) {
throw new InsufficientEntityPermissionException($context);
}

$newEntity = $entityComponent->duplicateEntity($context->getEntity()->getInstance());
$em->create($newEntity);
$em->flush();

$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::EDIT)
->setEntityId($newEntity->getId())
->generateUrl();

$this->addFlash('success', $translatorAdmin->transFlashMessage('duplicate'), array());

return $this->redirect($url);
}


public function createIndexQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder {
$queryBuilder = parent::createIndexQueryBuilder(
$searchDto,
$entityDto,
$fields,
$filters
);

//TOdo utiliser les repositoryQuery ?
if ($this->isInstanceOf(TreeInterface::class)) {
$entityId = $searchDto->getRequest()->get('entityId');
if ($entityId !== null) {
$queryBuilder->andWhereParent('entity', $entityId);
} else {
$queryBuilder->andWhereParentIsNull('entity');
}
}

$this->filtersForm = $this->createForm(
FiltersFormType::class,
null,
array(
'fields' => $fields,
'entity_dto' => $entityDto,
'entity_class' => $this->getEntityFqcn(),
'entity_name' => $entityDto->getName(),
)
);

$filterManager = $this->get(FilterManager::class);

$this->filtersForm->handleRequest($searchDto->getRequest());
/*if (($this->filtersForm->isSubmitted() && $this->filtersForm->isValid())) {

}*/
$filterManager->handleFiltersForm($queryBuilder, $this->filtersForm, $fields, $entityDto);


return $queryBuilder;
}

public function createSortQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder {
$queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);

return $queryBuilder;
}

public function edit(AdminContext $context)
{
$response = parent::edit($context);;

// on vide le flash bag si édition en ajax (notification déjà affichée en Javascript)
if ($context->getRequest()->isXmlHttpRequest()) {
$this->get('session')->getFlashBag()->clear();
}

return $response;
}

public function isInstanceOf(string $interfaceName): bool
{
return in_array($interfaceName, class_implements($this->getEntityFqcn()));
}

public function getControllerFqcnByInterface(string $interface): string
{
$context = $this->get(AdminContextProvider::class)->getContext();

return $context->getCrudControllers()->findCrudFqcnByEntityFqcn(
$this->get(EntityManagerInterface::class)->getEntityName($interface)
);
}

public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->update($entityInstance);
$entityManager->flush();
}

public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->create($entityInstance);
$entityManager->flush();
}


public function configureActions(Actions $actions): Actions
{
$this->buildIndexActions($actions);
$this->buildEditActions($actions);
$this->buildDetailActions($actions);
$this->buildNewActions($actions);
$this->handleTranslatableEntityActions($actions);
$this->handleSortableEntityActions($actions);
$this->handleTreeEntityActions($actions);

/*$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE, Action::DELETE]);
$actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);*/

return $actions;
}

public function getDuplicateAction(): Action
{
$duplicateAction = Action::new(
'duplicate',
$this->get(TranslatorAdmin::class)->transAction('duplicate'),
'fa fa-fw fa-copy'
)
->linkToCrudAction('duplicate')
->setLabel($this->get(TranslatorAdmin::class)->transAction('duplicate'))
->setCssClass('in-dropdown text-info action-confirm');

return $duplicateAction;
}

public function buildIndexActions(Actions $actions): void
{
$actions->add(Crud::PAGE_INDEX, $this->getDuplicateAction());

$this->actionUpdate(
$actions,
Crud::PAGE_INDEX,
Action::NEW,
[
'icon' => 'plus',
'label' => $this->get(TranslatorAdmin::class)->transAction('create'),
'add_class' => 'btn-sm',
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_INDEX,
Action::EDIT,
[
'class' => 'btn btn-sm btn-primary',
'icon' => 'edit',
'label' => false,
'html_attributes' => array(
'data-toggle' => 'tooltip',
'title' => $this->get(TranslatorAdmin::class)->transAction('edit'),
),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_INDEX,
Action::DETAIL,
[
'icon' => 'eye',
'add_class' => 'btn btn-sm btn-success',
'label' => false,
'html_attributes' => array(
'data-toggle' => 'tooltip',
'title' => $this->get(TranslatorAdmin::class)->transAction('detail'),
),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_INDEX,
Action::DELETE,
[
'icon' => 'trash',
'dropdown' => true,
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_INDEX,
Action::BATCH_DELETE,
[
'class' => 'btn btn-sm btn-danger',
'icon' => 'trash',
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
]
);
}


public function buildEditActions(Actions $actions): void
{
$actions->add(Crud::PAGE_EDIT, Action::INDEX);
$actions->add(Crud::PAGE_EDIT, Action::DELETE);


$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::SAVE_AND_RETURN,
[
'add_class' => 'float-right',
'icon' => 'check',
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::INDEX,
[
'icon' => 'chevron-left',
'class' => 'btn btn-link',
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
]
);


$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::SAVE_AND_CONTINUE,
[
'class' => 'btn btn-info float-right',
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_continue'),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::DELETE,
[
'icon' => 'trash',
'class' => 'btn btn-outline-danger action-delete',
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
]
);
}

public function buildDetailActions(Actions $actions): void
{
}

public function buildNewActions(Actions $actions): void
{
$actions->add(Crud::PAGE_NEW, Action::INDEX);

$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::SAVE_AND_RETURN,
[
'add_class' => 'float-right',
'icon' => 'check',
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::INDEX,
[
'icon' => 'chevron-left',
'class' => 'btn btn-link',
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
]
);

$this->actionUpdate(
$actions,
Crud::PAGE_EDIT,
Action::SAVE_AND_ADD_ANOTHER,
[
'class' => 'btn btn-info float-right',
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_add_another'),
]
);
}

public function handleTranslatableEntityActions(Actions $actions): void
{
if ($this->isInstanceOf(TranslatableInterface::class)) {
$actions->update(
Crud::PAGE_INDEX,
Action::EDIT,
function (Action $action) {
$action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig');

return $action;
}
);
}
}

public function handleSortableEntityActions(Actions $actions): void
{
if ($this->isInstanceOf(SortableInterface::class)) {
$sortAction = Action::new('sort', $this->get(TranslatorAdmin::class)->transAction('sort'), 'fa fa-sort')
->linkToCrudAction('sort')
->setCssClass('btn btn-sm btn-success')
->createAsGlobalAction();

$actions->add(Crud::PAGE_INDEX, $sortAction);
}
}


public function handleTreeEntityActions(Actions $actions): void
{
if ($this->isInstanceOf(TreeInterface::class)) {
$indexChildAction = Action::new(
'index_children',
$this->get(TranslatorAdmin::class)->transAction('index_children'),
'fa fa-list'
)
->linkToCrudAction(Action::INDEX)
->setLabel('')
->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants'))
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
->setCssClass('btn btn-sm btn-success');

$backParentAction = Action::new(
'index_parent',
$this->get(TranslatorAdmin::class)->transAction('index_parent'),
'fa fa-chevron-left'
)
->linkToCrudAction(Action::INDEX)
->setCssClass('btn btn-sm btn-info')
->createAsGlobalAction();

$actions->add(Crud::PAGE_INDEX, $backParentAction);
$actions->add(Crud::PAGE_INDEX, $indexChildAction);
}
}

public function actionUpdate($actions, $crudActionName, $actionName, array $button): void
{
if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) {
$actions->update(
$crudActionName,
$actionName,
function (Action $action) use ($button) {
if (isset($button['add_class'])) {
$action->addCssClass($button['add_class']);
}

if (isset($button['class'])) {
$action->setCssClass($button['class']);
}

if (isset($button['icon'])) {
$action->setIcon('fa fa-'.$button['icon']);
}

if (isset($button['label'])) {
$action->setLabel($button['label']);
}

if (isset($button['dropdown']) && $button['dropdown']) {
$action->addCssClass('in-dropdown');
}

if (isset($button['html_attributes']) && $button['html_attributes']) {
$action->setHtmlAttributes($button['html_attributes']);
}

return $action;
}
);
}
}

public function autocompleteFilter(AdminContext $context): JsonResponse
{
$queryBuilder = $this->createIndexQueryBuilder(
$context->getSearch(),
$context->getEntity(),
FieldCollection::new([]),
FilterCollection::new()
);
$autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT);

/** @var CrudControllerInterface $controller */
$controller = $this->get(ControllerFactory::class)->getCrudControllerInstance(
$autocompleteContext[EA::CRUD_CONTROLLER_FQCN],
Action::INDEX,
$context->getRequest()
);
/** @var FieldDto $field */
$field = FieldCollection::new(
$controller->configureFields($autocompleteContext['originatingPage'])
)->getByProperty($autocompleteContext['propertyName']);

$filterManager = $this->get(FilterManager::class);

$filterManager->applyFilter($queryBuilder, $field, $context->getRequest()->query->get('q'));
if ($filterManager->isRelationField($field->getProperty())) {
$queryBuilder->select($autocompleteContext['propertyName']);
} else {
$queryBuilder->select('entity.'.$autocompleteContext['propertyName']);
}

$responses = array();
foreach ($queryBuilder->getQuery()->getArrayResult() as $result) {
$responses[] = array_values($result)[0];
}


return JsonResponse::fromJsonString(json_encode($responses));
}


}


+ 0
- 481
Controller/Admin/AbstractCrudController.php 파일 보기

@@ -1,481 +0,0 @@
<?php

namespace Lc\SovBundle\Controller\Admin;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
use Lc\SovBundle\Doctrine\Extension\SeoInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Field\CollectionField;
use Lc\SovBundle\Field\GalleryManagerField;
use Lc\SovBundle\Form\Type\Crud\PositionType;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Twig\Environment;

abstract class AbstractCrudController extends EaAbstractCrudController
{
protected $session;
protected $request;
protected $translatorAdmin;

public function __construct(
SessionInterface $session,
RequestStack $request,
EntityManager $em,
Environment $twig,
TranslatorAdmin $translatorAdmin
)
{
$this->session = $session;
$this->request = $request;
$this->em = $em;
$this->twig = $twig;
$this->translatorAdmin = $translatorAdmin;
}

public function configureActions(Actions $actions): Actions
{
/* Translatable */
if ($this->isInstanceOf(TranslatableInterface::class)) {
$actions->update(
Crud::PAGE_INDEX,
Action::EDIT,
function (Action $action) {
$action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig');

return $action;
}
);
}

/* Boutons des actions dans les listes */
$actionsArray[Crud::PAGE_INDEX] = [
Action::NEW => [
'icon' => 'plus',
'label' => $this->translatorAdmin->transAction('create'),
'add_class' => 'btn-sm'
],
Action::EDIT => [
'class' => 'btn btn-sm btn-primary',
'icon' => 'edit',
'label' => false,
'html_attributes' => array(
'data-toggle' => 'tooltip',
'title' => $this->translatorAdmin->transAction('edit')
)
],
Action::DELETE => [
'icon' => 'trash',
'dropdown' => true,
'label' => $this->translatorAdmin->transAction('delete')
],
Action::BATCH_DELETE => [
'class' => 'btn btn-sm btn-danger',
'icon' => 'trash',
'label' => $this->translatorAdmin->transAction('delete')
],
];

/* Boutons des actions dans l'édition */

$actionSaveAndReturn = [
'add_class' => 'float-right',
'icon' => 'check',
'label' => $this->translatorAdmin->transAction('save_and_return')
];
$actionIndex = [
'icon' => 'chevron-left',
'class' => 'btn btn-link',
'label' => $this->translatorAdmin->transAction('back_index')
];

$actionsArray[Crud::PAGE_EDIT] = [
Action::SAVE_AND_CONTINUE => [
'class' => 'btn btn-info float-right',
'label' => $this->translatorAdmin->transAction('save_and_continue')
],
Action::DELETE => [
'icon' => 'trash',
'class' => 'btn btn-outline-danger action-delete',
'label' => $this->translatorAdmin->transAction('delete')
],
Action::SAVE_AND_RETURN => $actionSaveAndReturn,
Action::INDEX => $actionIndex,
];

$actionsArray[Crud::PAGE_NEW] = [
Action::SAVE_AND_ADD_ANOTHER => [
'class' => 'btn btn-info float-right',
'label' => $this->translatorAdmin->transAction('save_and_add_another')
],
Action::SAVE_AND_RETURN => $actionSaveAndReturn,
Action::INDEX => $actionIndex,
];

$actions->add(Crud::PAGE_EDIT, Action::INDEX);
$actions->add(Crud::PAGE_EDIT, Action::DELETE);
$actions->add(Crud::PAGE_NEW, Action::INDEX);

if ($this->isInstanceOf(SortableInterface::class)) {
$sortAction = Action::new('sort', $this->translatorAdmin->transAction('sort'), 'fa fa-sort')
->linkToCrudAction('sort')
->setCssClass('btn btn-sm btn-success')
->createAsGlobalAction();

$actions->add(Crud::PAGE_INDEX, $sortAction);
}


if ($this->isInstanceOf(TreeInterface::class)) {
$indexChildAction = Action::new(
'index_children',
$this->translatorAdmin->transAction('index_children'),
'fa fa-list'
)
->linkToCrudAction(Action::INDEX)
->setLabel('')
->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants'))
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
->setCssClass('btn btn-sm btn-success');

$backParentAction = Action::new(
'index_parent',
$this->translatorAdmin->transAction('index_parent'),
'fa fa-chevron-left'
)
->linkToCrudAction(Action::INDEX)
->setCssClass('btn btn-sm btn-info')
->createAsGlobalAction();

$actions->add(Crud::PAGE_INDEX, $backParentAction);
$actions->add(Crud::PAGE_INDEX, $indexChildAction);
}

$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE]);
$actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);


foreach ($actionsArray as $crudActionName => $actionsStyle) {
foreach ($actionsStyle as $actionName => $button) {
$actions->update(
$crudActionName,
$actionName,
function (Action $action) use ($button) {
if (isset($button['add_class'])) {
$action->addCssClass($button['add_class']);
}

if (isset($button['class'])) {
$action->setCssClass($button['class']);
}

if (isset($button['icon'])) {
$action->setIcon('fa fa-' . $button['icon']);
}

if (isset($button['label'])) {
$action->setLabel($button['label']);
}

if (isset($button['dropdown']) && $button['dropdown']) {
$action->addCssClass('in-dropdown');
}

if (isset($button['html_attributes']) && $button['html_attributes']) {
$action->setHtmlAttributes($button['html_attributes']);
}

return $action;
}
);
}
}

return $actions;
}

public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
{
// fields sur la page index
if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
$responseParameters->set('fields', $this->configureFields('index'));
}

return $responseParameters;
}

public function configureCrud(Crud $crud): Crud
{
$crud = parent::configureCrud($crud);

$this->setMaxResults($crud);
if ($this->isInstanceOf(SortableInterface::class)) {
$crud->setDefaultSort(['position' => 'ASC']);
}
return $crud;
}

public function setMaxResults(Crud $crud)
{
$entityClass = $this->getEntityFqcn();
$paramListMaxResults = 'listMaxResults';
$paramSessionListMaxResults = $entityClass . '-' . $paramListMaxResults;
$requestListMaxResults = $this->request->getCurrentRequest()->get($paramListMaxResults);

if ($requestListMaxResults) {
$this->session->set($paramSessionListMaxResults, $requestListMaxResults);
}
$maxResults = $this->session->get($paramSessionListMaxResults) ? $this->session->get(
$paramSessionListMaxResults
) : 30;

$crud->setPaginatorPageSize($maxResults);
}

public function configureFields(string $pageName): iterable
{
$seoPanel = $confPanel = array();

if ($this->isInstanceOf(SortableInterface::class)) {
$seoPanel = [
FormField::addPanel('seo')->setTemplateName('crud/field/generic'),
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
'Affiché dans les résultats de recherche Google'
)->hideOnIndex(),
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp(
'Affiché dans les résultats de recherche Google'
)->hideOnIndex(),
CollectionField::new('oldUrls')
->setFormTypeOption('entry_type', TextType::class)->setLabel(
'Anciennes urls du document'
)->hideOnIndex(),
];
}

if ($this->isInstanceOf(DevAliasInterface::class)) {
$confPanel = [
FormField::addPanel('configuration')->setTemplateName('crud/field/generic'),
TextField::new('devAlias')->hideOnIndex(),
];
}

return array_merge($seoPanel, $confPanel);
}


public function sort(AdminContext $context)
{
$event = new BeforeCrudActionEvent($context);
$this->get('event_dispatcher')->dispatch($event);
if ($event->isPropagationStopped()) {
return $event->getResponse();
}

if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
throw new ForbiddenActionException($context);
}

$fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
$filters = $this->get(FilterFactory::class)->create(
$context->getCrud()->getFiltersConfig(),
$fields,
$context->getEntity()
);
$queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters);
$paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);

$entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults());
$this->get(EntityFactory::class)->processFieldsForAll($entities, $fields);

$sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults()))
->add(
'entities',
CollectionType::class,
array(
'required' => true,
'allow_add' => true,
'entry_type' => PositionType::class,
)
)
->getForm();

$entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
$repository = $entityManager->getRepository($this->getEntityFqcn());

$sortableForm->handleRequest($context->getRequest());

if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
foreach ($sortableForm->get('entities')->getData() as $elm) {
$entityInstance = $repository->find($elm['id']);
$entityDto = $context->getEntity()->newWithInstance($entityInstance);

if (!$entityDto->isAccessible()) {
throw new InsufficientEntityPermissionException($context);
}

$event = new BeforeEntityDeletedEvent($entityInstance);
$this->get('event_dispatcher')->dispatch($event);
$entityInstance = $event->getEntityInstance();

$entityInstance->setPosition($elm['position']);
$this->updateEntity($entityManager, $entityInstance);

$this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance));
}

$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('success', $this->translatorAdmin->transFlashMessage('sort'), array());

return $this->redirect($url);
}

$responseParameters = $this->configureResponseParameters(
KeyValueStore::new(
[
'pageName' => Crud::PAGE_INDEX,
'templatePath' => '@LcSov/adminlte/crud/sort.html.twig',
'entities' => $entities,
'paginator' => $paginator,
'global_actions' => array(),
'batch_actions' => array(),
'filters' => $filters,
'sortable_form' => $sortableForm,
]
)
);
$responseParameters->set('fields', $this->configureFields('index'));
$event = new AfterCrudActionEvent($context, $responseParameters);
$this->get('event_dispatcher')->dispatch($event);
if ($event->isPropagationStopped()) {
return $event->getResponse();
}

return $responseParameters;
}

public function createIndexQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder
{
$queryBuilder = parent::createIndexQueryBuilder(
$searchDto,
$entityDto,
$fields,
$filters
);

if ($this->isInstanceOf(TreeInterface::class)) {
$entityId = $searchDto->getRequest()->get('entityId');
if ($entityId !== null) {
$queryBuilder->andWhere('entity.parent = :entityId');
$queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId'));
} else {
$queryBuilder->andWhere('entity.parent IS NULL');
}
}


return $queryBuilder;
}

public function createSortQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder
{
$queryBuilder = parent::createIndexQueryBuilder(
$searchDto,
$entityDto,
$fields,
$filters
);

if ($this->isInstanceOf(TreeInterface::class)) {
$entityId = $searchDto->getRequest()->get('entityId');
if ($entityId !== null) {
$queryBuilder->andWhere('entity.parent = :entityId');
$queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId'));
} else {
$queryBuilder->andWhere('entity.parent IS NULL');
}
}


return $queryBuilder;
}

public function edit(AdminContext $context)
{
$response = parent::edit($context);;

// on vide le flash bag si édition en ajax (notification déjà affichée en Javascript)
if ($context->getRequest()->isXmlHttpRequest()) {
$this->session->getFlashBag()->clear();
}

return $response;
}

public function isInstanceOf(string $interfaceName): bool
{
return in_array($interfaceName, class_implements($this->getEntityFqcn()));
}


public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->update($entityInstance);
$entityManager->flush();
}

public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->create($entityInstance);
$entityManager->flush();
}

}


+ 0
- 20
Controller/Admin/UserCrudController.php 파일 보기

@@ -1,20 +0,0 @@
<?php

namespace Lc\SovBundle\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;

abstract class UserCrudController extends AbstractCrudController
{

public function configureFields(string $pageName): iterable
{
return [
TextField::new('email')
];
}

}

Controller/Admin/DashboardController.php → Controller/Dashboard/DashboardAdminController.php 파일 보기

@@ -1,6 +1,6 @@
<?php

namespace Lc\SovBundle\Controller\Admin;
namespace Lc\SovBundle\Controller\Dashboard;

use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
@@ -13,8 +13,9 @@ use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class DashboardController extends AbstractDashboardController
class DashboardAdminController extends AbstractDashboardController
{

public function index(): Response
{
return $this->render('@LcSov/adminlte/dashboard.html.twig');
@@ -26,7 +27,7 @@ class DashboardController extends AbstractDashboardController
// the name visible to end users
->setTitle('LA CLIC !')
// you can include HTML contents too (e.g. to link to an image)
->setTitle('<img src="assets/img/laclic.png" width="100px">')
->setTitle('<img src="assets/img/'.$this->get('parameter_bag')->get('app.admin.logo').'" width="100px">')
// the path defined in this method is passed to the Twig asset() function
->setFaviconPath('favicon.svg')
// the domain used by default is 'messages'
@@ -37,12 +38,14 @@ class DashboardController extends AbstractDashboardController
{
$assets = parent::configureAssets();

$assets->addWebpackEncoreEntry('adminlte-common');
$assets->addWebpackEncoreEntry('adminlte-plugins');
$assets->addWebpackEncoreEntry('adminlte-index');
$assets->addWebpackEncoreEntry('adminlte-form');
$assets->addWebpackEncoreEntry('adminlte-sort');
$assets->addWebpackEncoreEntry('adminlte-field-collection');
$assets->addWebpackEncoreEntry('adminlte-field-filemanager');
$assets->addWebpackEncoreEntry('adminlte-main');
$assets->addWebpackEncoreEntry('sov-reminder');

return $assets;
}
@@ -54,7 +57,7 @@ class DashboardController extends AbstractDashboardController
// if you prefer to create the user menu from scratch, use: return UserMenu::new()->...
return parent::configureUserMenu($user)
// use the given $user object to get the user name
->setName($user->getName())
->setName($user->getFirstName())
// use this method if you don't want to display the name of the user
//->displayUserName(false)
->displayUserAvatar(false)
@@ -82,17 +85,16 @@ class DashboardController extends AbstractDashboardController
'main_menu' => '@LcSov/adminlte/block/menu.html.twig',
'crud/index' => '@LcSov/adminlte/crud/index.html.twig',
'crud/paginator' => '@LcSov/adminlte/crud/paginator.html.twig',
'crud/edit' => '@LcSov/adminlte/crud/edit.html.twig',
'crud/new' => '@LcSov/adminlte/crud/new.html.twig',
'crud/edit' => '@LcSov/adminlte/crud/form.html.twig',
'crud/new' => '@LcSov/adminlte/crud/form.html.twig',
'flash_messages' => '@LcSov/adminlte/block/flash_messages.html.twig',
]
)
->setFormThemes(
[
'@LcSov/adminlte/crud/form_theme.html.twig',
'@FOSCKEditor/Form/ckeditor_widget.html.twig'
//'@FOSCKEditor/Form/ckeditor_widget.html.twig'
]
);
}

}

+ 38
- 0
Controller/Newsletter/NewsletterAdminController.php 파일 보기

@@ -0,0 +1,38 @@
<?php

namespace Lc\SovBundle\Controller\Newsletter;

use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\Newsletter\NewsletterContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Factory\Newsletter\NewsletterFactory;
use Lc\SovBundle\Field\BooleanField;
use Lc\SovBundle\Field\CKEditorField;
use Lc\SovBundle\Field\StatusField;

abstract class NewsletterAdminController extends AbstractAdminController
{
public function configureFields(string $pageName): iterable
{
return array_merge(
[
FormField::addPanel('general'),
TextField::new('title'),
BooleanField::new('isMain')
->setCustomOption('toggle_label', 'Principale'),
CKEditorField::new('description')
->hideOnIndex(),
StatusField::new('status'),
],
$this->getSeoPanel(),
$this->getConfPanel()
);
}

public function createEntity(string $entityFqcn)
{
return $this->get(NewsletterContainer::class)->getFactory()->create();
}

}

+ 154
- 0
Controller/Reminder/ReminderAdminController.php 파일 보기

@@ -0,0 +1,154 @@
<?php

namespace Lc\SovBundle\Controller\Reminder;

use Doctrine\ORM\EntityManagerInterface;
use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\CaracoleBundle\Resolver\SectionResolver;
use Lc\SovBundle\Container\Reminder\ReminderContainer;
use Lc\SovBundle\Factory\Reminder\ReminderFactory;
use Lc\SovBundle\Form\Reminder\ReminderAdminFormType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Annotation\Route;

class ReminderAdminController extends AbstractController
{

protected EntityManagerInterface $entityManager;
protected ReminderContainer $reminderContainer;
protected FormFactoryInterface $formFactory;
protected UrlGeneratorInterface $urlGenerator;
protected MerchantResolver $merchantResolver;
protected SectionResolver $sectionResolver;
protected ParameterBagInterface $parameterBag;

public function __construct(
EntityManagerInterface $entityManager,
ReminderContainer $reminderContainer,
FormFactoryInterface $formFactory,
UrlGeneratorInterface $urlGenerator,
ParameterBagInterface $parameterBag
) {
$this->entityManager = $entityManager;
$this->reminderContainer = $reminderContainer;
$this->formFactory = $formFactory;
$this->urlGenerator = $urlGenerator;
$this->parameterBag = $parameterBag;
}

/**
* @Route("/admin/reminder/modal", name="sov_admin_reminder_render_modal")
*/
public function renderModal(Request $request): Response
{
$id = $request->get('id');

if($id) {
$reminder = $this->reminderContainer->getRepositoryQuery()->getRepository()->find($id);
$action = $this->urlGenerator->generate(
$this->parameterBag->get('app.reminder.route_edit'),
['id' => $id]
);
}
else {
$crudAction = $request->get('crudAction');
$crudControllerFqcn = $request->get('crudControllerFqcn');
$entityId = $request->get('entityId') ? $request->get('entityId') : null ;
$reminder = $this->createEntity($crudAction, $crudControllerFqcn, $entityId);
$action = $this->urlGenerator->generate(
$this->parameterBag->get('app.reminder.route_new')
);
}

$form = $this->formFactory->create(
ReminderAdminFormType::class,
$reminder,
[
'action' => $action
]
);

return $this->render(
'@LcSov/admin/reminder/form_modal.html.twig',
[
'form_reminder' => $form->createView()
]
);
}

/**
* @Route("/admin/reminder/new", name="sov_admin_reminder_new")
*/
public function new(Request $request)
{
$reminder = $this->createEntity();

$form = $this->formFactory->create(ReminderAdminFormType::class, $reminder);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$reminder = $form->getData();
$this->entityManager->persist($reminder);
$this->entityManager->flush();

$this->addFlash('success', 'Le pense-bête a bien été ajouté');
}

return $this->redirect($request->headers->get('referer'));
}

/**
* @Route("/admin/reminder/edit/{id}", name="sov_admin_reminder_edit")
*/
public function edit(Request $request)
{
$id = $request->get('id');
$reminder = $this->reminderContainer->getRepositoryQuery()->getRepository()->find($id);

$form = $this->formFactory->create(ReminderAdminFormType::class, $reminder);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$reminder = $form->getData();
$this->entityManager->update($reminder);
$this->entityManager->flush();

$this->addFlash('success', 'Le pense-bête a bien été mis à jour');
}

return $this->redirect($request->headers->get('referer'));
}

/**
* @Route("/admin/reminder/done", name="sov_admin_reminder_done")
*/
public function done(Request $request): JsonResponse
{
$id = $request->get('id');
$reminder = $this->reminderContainer->getRepositoryQuery()->getRepository()->find($id);
$done = $request->get('done');

if($done == 'true') {
$reminder->setDone(true);
}
else {
$reminder->setDone(false);
}

$this->entityManager->update($reminder);
$this->entityManager->flush();
return new JsonResponse(['success' => true]);
}

public function createEntity(string $crudAction = null, string $crudControllerFqcn = null, int $entityId = null)
{
$factory = new ReminderFactory();
return $factory->create($crudAction, $crudControllerFqcn, $entityId);
}
}

Controller/Admin/SecurityController.php → Controller/Security/SecurityAdminController.php 파일 보기

@@ -1,19 +1,21 @@
<?php

namespace Lc\SovBundle\Controller\Admin;
namespace Lc\SovBundle\Controller\Security;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class SecurityController extends AbstractController
class SecurityAdminController extends AbstractController
{

/**
* @Route("/login", name="sov_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('admin_dashboard');
return $this->redirectToRoute('app_admin_dashboard');
}

// get the login error if there is one
@@ -37,14 +39,14 @@ class SecurityController extends AbstractController
// 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/laclic.png" >',
'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 URL users are redirected to after the login (default: '/admin')
'target_path' => $this->generateUrl('admin_dashboard'),
'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',
@@ -63,7 +65,9 @@ class SecurityController extends AbstractController
]);
}


/**
* @Route("/logout", name="sov_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');

+ 54
- 0
Controller/Setting/SettingAdminController.php 파일 보기

@@ -0,0 +1,54 @@
<?php

namespace Lc\SovBundle\Controller\Setting;

use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Container\Setting\SiteSettingContainer;
use Lc\SovBundle\Container\Site\SiteContainer;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Form\Setting\SiteSettingsFormType;
use Lc\SovBundle\Repository\Setting\SiteSettingRepository;
use Lc\SovBundle\Repository\Site\SiteRepository;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class SettingAdminController extends AbstractController
{
protected EntityManagerInterface $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

/**
* @Route("/admin/setting/site", name="sov_admin_setting_site")
*/
public function manageGlobal(Request $request, EntityManagerInterface $entityManager)
{

$site = $this->get(SiteContainer::class)->getStore()->getOneByDevAlias('default') ;
$form = $this->createForm(SiteSettingsFormType::class, $site);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {

$entityManager->update($site);
$entityManager->flush();

$this->addFlash('success', $this->get(TranslatorAdmin::class)->transFlashMessage('settings_saved'));
}

return $this->render(
'@LcSov/admin/setting/edit_site.html.twig' ,
[
'setting_definition' => $this->get(SiteSettingContainer::class)->getDefinition(),
'form' => $form->createView()
]
);
}

}

+ 42
- 0
Controller/Site/NewsAdminController.php 파일 보기

@@ -0,0 +1,42 @@
<?php

namespace Lc\SovBundle\Controller\Site;

use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\Site\NewsContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Factory\Site\NewsFactory;
use Lc\SovBundle\Field\CKEditorField;
use Lc\SovBundle\Field\StatusField;

abstract class NewsAdminController extends AbstractAdminController
{

public function configureFields(string $pageName): iterable
{
$panel = parent::configureFields($pageName);

return array_merge(
[
FormField::addPanel('general'),
TextField::new('title'),
DateField::new('date')
->setFormat('d/MM/y'),
NumberField::new('position')
->hideOnIndex()
->hideOnForm(),
CKEditorField::new('description'),
StatusField::new('status'),
],
$panel
);
}

public function createEntity(string $entityFqcn)
{
return $this->get(NewsContainer::class)->getFactory()->create();
}
}

+ 40
- 0
Controller/Site/PageAdminController.php 파일 보기

@@ -0,0 +1,40 @@
<?php

namespace Lc\SovBundle\Controller\Site;

use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\Site\PageContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Factory\Site\PageFactory;
use Lc\SovBundle\Field\CKEditorField;
use Lc\SovBundle\Field\StatusField;

abstract class PageAdminController extends AbstractAdminController
{

public function configureFields(string $pageName): iterable
{
$panel = parent::configureFields($pageName);

return array_merge(
[
FormField::addPanel('general'),
TextField::new('title'),
NumberField::new('position')
->hideOnIndex()
->hideOnForm(),
CKEditorField::new('description'),
StatusField::new('status'),
],
$panel
);
}

public function createEntity(string $entityFqcn)
{
return $this->get(PageContainer::class)->getFactory()->create();
}

}

+ 188
- 0
Controller/Ticket/TicketAdminController.php 파일 보기

@@ -0,0 +1,188 @@
<?php

namespace Lc\SovBundle\Controller\Ticket;

use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Lc\SovBundle\Container\Ticket\TicketContainer;
use Lc\SovBundle\Factory\Ticket\TicketFactory;
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface;
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory;
use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface;
use Lc\SovBundle\Form\Ticket\TicketFormType;
use Lc\SovBundle\Form\Ticket\TicketMessageFormType;
use Lc\SovBundle\Form\Ticket\TicketStatusType;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Model\Ticket\TicketModel;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;

class TicketAdminController extends AbstractAdminController
{

public static function getEntityFqcn(): string
{
return TicketInterface::class;
}

public function createEntity(string $entityFqcn)
{
return $this->get(TicketContainer::class)->getFactory()->create();
}

public function configureAssets(Assets $assets): Assets
{
$assets = parent::configureAssets($assets);

$assets->addWebpackEncoreEntry('sov-ticket');

return $assets;
}

public function configureFields(string $pageName): iterable
{
$translatorAdmin = $this->get(TranslatorAdmin::class);
return [
IntegerField::new('id')
->hideOnForm(),
DateField::new('createdAt')->setFormat('short')
->hideOnForm(),
TextField::new('visitorFirstName')
->setTemplatePath('@LcSov/admin/ticket/field/username.html.twig')
->hideOnForm(),
TextField::new('visitorEmail')
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig')
->hideOnForm(),
AssociationField::new('user')
->hideOnIndex(),
TextField::new('subject'),
TextField::new('lastMessage')
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig')
->hideOnForm(),
ChoiceField::new('type')
->autocomplete()
->setChoices(
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getTypeChoices(), 'Ticket', 'type')
),
ChoiceField::new('status')
->autocomplete()
->setChoices(
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getStatusChoices(), 'Ticket', 'status')

)
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig')
->hideOnForm(),
];
}

public function configureActions(Actions $actions): Actions
{
$actions
->add(Crud::PAGE_INDEX, Action::DETAIL)
->remove(Crud::PAGE_INDEX, Action::EDIT);

return parent::configureActions($actions);
}

public function new(AdminContext $context)
{
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);

$ticket = $this->createEntity($context->getEntity()->getFqcn());

$form = $this->createForm(TicketFormType::class, $ticket);

$form->handleRequest($context->getRequest());
if ($form->isSubmitted() && $form->isValid()) {
$ticket = $form->getData();

$this->get(EntityManagerInterface::class)->create($ticket);
$this->get(EntityManagerInterface::class)->flush();

$url = $adminUrlGenerator
->setAction('index')
->generateUrl();

return $this->redirect($url);
}

return $this->render(
'@LcSov/admin/ticket/new.html.twig',
[
'form' => $form->createView(),
]
);
}

public function detail(AdminContext $context)
{
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);
$ticket = $context->getEntity()->getInstance();

$url = $adminUrlGenerator
->setAction('ticketStatusAction')
->generateUrl();

$formTicketStatus = $this->createForm(
TicketStatusType::class,
$ticket,
[
'action' => $url,
'method' => 'POST',
]
);

$ticketMessage = $this->get(TicketContainer::class)->getFactory()->create();
$formAddTicketMessage = $this->createForm(TicketMessageFormType::class, $ticketMessage);
$formAddTicketMessage->handleRequest($this->get(RequestStack::class)->getMainRequest());

if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) {
$ticketMessage = $formAddTicketMessage->getData();
$ticketMessage->setTicket($ticket);
$ticketMessage->setAnswerByAdmin(true);
$this->get(EntityManagerInterface::class)->create($ticketMessage);
$this->get(EntityManagerInterface::class)->flush();
}

return $this->render(
'@LcSov/admin/ticket/detail.html.twig',
[
'form_ticket_status' => $formTicketStatus->createView(),
'form_add_ticket_message' => $formAddTicketMessage->createView(),
'ticket' => $ticket,
]
);
}


public function ticketStatusAction()
{
$request = $this->get('request')->getMasterRequest();
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance();

$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket);
$formTicketStatusForm->handleRequest($request);

$success = false;
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) {
$this->get('em')->persist($ticket);
$this->get('em')->flush();
$success = true;
}

return new JsonResponse(['success' => $success]);
}

}

Controller/Admin/UserController.php → Controller/User/AccountAdminController.php 파일 보기

@@ -1,28 +1,31 @@
<?php

namespace Lc\SovBundle\Controller\Admin;
namespace Lc\SovBundle\Controller\User;

use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Form\Type\User\ChangePasswordFormType;
use Lc\SovBundle\Form\Type\User\ProfileFormType;
use Lc\SovBundle\Form\User\ChangePasswordFormType;
use Lc\SovBundle\Form\User\ProfileFormType;
use Lc\SovBundle\Model\User\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Component\Routing\Annotation\Route;

class UserController extends AbstractController
class AccountAdminController extends AbstractController
{
protected $em;
protected EntityManagerInterface $entityManager;

public function __construct(EntityManager $em)
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $em;
$this->entityManager = $entityManager;
}

/**
* @Route("/admin/account/profile", name="sov_admin_account_profile")
*/
public function profile(Request $request): Response
{
$user = $this->getUser();
@@ -30,23 +33,27 @@ class UserController extends AbstractController

$form->handleRequest($request);


if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();

$this->em->update($user);
$this->em->flush();
$this->entityManager->update($user);
$this->entityManager->flush();

$this->addFlash('success', new TranslatableMessage('form.account_profile.message.success', [], 'admin'));
}

return $this->render(
'@LcSov/user/profile.html.twig',
'@LcSov/admin/user/edit_profile.html.twig',
[
'form' => $form->createView(),
]
);
}

/**
* @Route("/admin/account/password", name="sov_admin_account_password")
*/
public function changePassword(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response
{
$user = $this->getUser();
@@ -59,18 +66,16 @@ class UserController extends AbstractController

$plainPassword = $form->get('plain_password')->getData();

// @TODO : créer UserManager
$newPasswordEncoded = $passwordEncoder->encodePassword($user, $plainPassword);
$user->setPassword($newPasswordEncoded);
$user->setPassword($passwordEncoder->encodePassword($user, $plainPassword));

$this->em->update($user);
$this->em->flush();
$this->entityManager->update($user);
$this->entityManager->flush();

$this->addFlash('success', new TranslatableMessage('form.account_password.message.success', [], 'admin'));
}

return $this->render(
'@LcSov/user/change_password.html.twig',
'@LcSov/admin/user/edit_password.html.twig',
[
'entity_class' => User::class,
'form' => $form->createView()

+ 25
- 0
Controller/User/GroupUserAdminController.php 파일 보기

@@ -0,0 +1,25 @@
<?php

namespace Lc\SovBundle\Controller\User;

use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\User\GroupUserContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Factory\User\GroupUserFactory;

abstract class GroupUserAdminController extends AbstractAdminController
{

public function configureFields(string $pageName): iterable
{
return [
TextField::new('title'),
TextField::new('devAlias'),
];
}

public function createEntity(string $entityFqcn)
{
return $this->get(GroupUserContainer::class)->getFactory()->create();
}
}

+ 50
- 0
Controller/User/UserAdminController.php 파일 보기

@@ -0,0 +1,50 @@
<?php

namespace Lc\SovBundle\Controller\User;

use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\User\UserContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Definition\RolesDefinition;
use Lc\SovBundle\Definition\RolesDefinitionInterface;
use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Factory\User\UserFactory;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

abstract class UserAdminController extends AbstractAdminController
{
protected RolesDefinitionInterface $rolesDefinition;

public function __construct(
SessionInterface $session,
RequestStack $request,
EntityManager $em,
TranslatorAdmin $translatorAdmin,
RolesDefinitionInterface $rolesDefinition
) {
$this->rolesDefinition = $rolesDefinition;
}

public function configureFields(string $pageName): iterable
{

return [
EmailField::new('email'),
TextField::new('lastname'),
TextField::new('firstname'),
ChoiceField::new('roles')
->allowMultipleChoices()
->autocomplete()
->setChoices($this->rolesDefinition->getRolesList())
];
}

public function createEntity(string $entityFqcn)
{
return $this->get(UserContainer::class)->getFactory()->create();
}
}

+ 127
- 0
Definition/AbstractSettingDefinition.php 파일 보기

@@ -0,0 +1,127 @@
<?php

namespace Lc\SovBundle\Definition;

abstract class AbstractSettingDefinition
{
protected $settings = [];

public function addSettingText(array $params): self
{
$params['type'] = 'text';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingTextarea(array $params): self
{
$params['type'] = 'textarea';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingTextareaAdvanced(array $params): self
{
$params['type'] = 'textarea_advanced';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingDate(array $params): self
{
$params['type'] = 'date';
$params['field'] = 'date';
return $this->addSetting($params);
}

public function addSettingTime(array $params): self
{
$params['type'] = 'time';
$params['field'] = 'date';
return $this->addSetting($params);
}

public function addSettingFile(array $params): self
{
$params['type'] = 'file';
$params['field'] = 'file';
return $this->addSetting($params);
}

public function addSettingImage(array $params): self
{
$params['type'] = 'image';
$params['field'] = 'file';
return $this->addSetting($params);
}

public function addSettingSelect(array $params): self
{
$params['type'] = 'select';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingRadio(array $params): self
{
$params['type'] = 'radio';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSetting($params)
{
$name = $params['name'];
$category = $params['category'];

if (!isset($this->settings[$category])) {
$this->settings[$category] = [];
}

$this->settings[$category][$name] = $params;

return $this;
}

public function getSettings(): array
{
return $this->settings;
}

public function getSettingsByCategory($category)
{
$settings = $this->getSettings();

if (isset($settings[$category])) {
return $settings[$category];
}

return [];
}

public function getSettingByName($name): ?array
{
$settings = $this->getSettings();

foreach ($settings as $category => $settingsCategory) {
foreach ($settingsCategory as $nameSetting => $setting) {
if ($nameSetting == $name) {
return $setting;
}
}
}

return null;
}

public function getSettingType($name): ?string
{
$setting = $this->getSettingByName($name);

if ($setting) {
return $setting['type'];
}

return null;
}
}

+ 51
- 0
Definition/RolesDefinition.php 파일 보기

@@ -0,0 +1,51 @@
<?php


namespace Lc\SovBundle\Definition;


class RolesDefinition implements RolesDefinitionInterface
{
const ROLE_USER = 'ROLE_USER' ;
const ROLE_ADMIN = 'ROLE_ADMIN' ;
const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN' ;

protected $roles = array(
self::ROLE_USER => [
'label' => 'Utilisateurs',
'role' => self::ROLE_USER,
],
self::ROLE_ADMIN => [
'label' => 'Administrateurs',
'role' => self::ROLE_ADMIN,
],
self::ROLE_SUPER_ADMIN => [
'label' => 'SuperAdmin',
'role' => self::ROLE_SUPER_ADMIN,
],
);

public function getRoles(): array
{
return $this->roles;
}

public function getRole($role): ?array
{
if (isset($this->roles[$role])) {
return $this->roles[$role];
} else {
return null;
}
}

public function getRolesList(): array
{
$rolesList = array();
foreach ($this->roles as $role) {
$rolesList[$role['label']] = $role['role'];
}

return $rolesList;
}
}

+ 16
- 0
Definition/RolesDefinitionInterface.php 파일 보기

@@ -0,0 +1,16 @@
<?php


namespace Lc\SovBundle\Definition;


interface RolesDefinitionInterface
{

public function getRoles(): array;

public function getRole($role): ?array;

public function getRolesList(): array;

}

+ 41
- 0
Definition/SiteSettingDefinition.php 파일 보기

@@ -0,0 +1,41 @@
<?php

namespace Lc\SovBundle\Definition;


class SiteSettingDefinition extends AbstractSettingDefinition implements SiteSettingDefinitionInterface
{
const CATEGORY_GENERAL = 'general';

const SETTING_MAINTENANCE = 'maintenance';
const SETTING_MAINTENANCE_IP_AUTHORIZED = 'maintenanceIpAuthorized';

public function __construct()
{
$this->addSettingSelect(
[
'category' => self::CATEGORY_GENERAL,
'name' => self::SETTING_MAINTENANCE,
'choices' => [
'Non' => 0,
'Oui' => 1,
]
]
);

$this->addSettingText(
[
'category' => self::CATEGORY_GENERAL,
'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED,
]
);
}

public function getCategories()
{
return [
self::CATEGORY_GENERAL
];
}

}

+ 8
- 0
Definition/SiteSettingDefinitionInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Definition;

interface SiteSettingDefinitionInterface
{

}

+ 28
- 14
DependencyInjection/Configuration.php 파일 보기

@@ -12,21 +12,35 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('lc_sov');
$rootNode = $treeBuilder->getRootNode();
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('lc_sov');
$rootNode = $treeBuilder->getRootNode();

$rootNode
->children()
//->scalarNode('dashboard_default')->defaultValue('App\Controller\Admin\DashboardController')->end()
->scalarNode('homepage_route')->end()
->end();
$rootNode
->children()
//->scalarNode('dashboard_default')->defaultValue('App\Controller\Admin\DashboardController')->end()
->scalarNode('homepage_route')->end()
->arrayNode('login_redirection')
->children()
->scalarNode('redirect_referer')
->defaultValue(true)
->end()
->arrayNode('roles_redirection')
->arrayPrototype()
->children()
->scalarNode('role')->end()
->scalarNode('redirect')->end()
->end()
->end()
->end()
->end()
->end();


return $treeBuilder;
}
return $treeBuilder;
}
}

+ 27
- 11
Doctrine/EntityManager.php 파일 보기

@@ -6,7 +6,6 @@ use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\EntityManager as DoctrineEntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Doctrine\EntityInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
@@ -27,6 +26,11 @@ class EntityManager extends EntityManagerDecorator
parent::__construct($wrapped);
}

public function createQueryBuilder()
{
return new QueryBuilder($this);
}

public function getRepository($className)
{
return $this->wrapped->getRepository($this->getEntityName($className));
@@ -39,31 +43,43 @@ class EntityManager extends EntityManagerDecorator
return new $entityName;
}

public function create(EntityInterface $entity): self
public function create(EntityInterface $entity, bool $dispatchEvent = true): self
{
if($dispatchEvent) {
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_CREATE_EVENT);
}
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::CREATE_EVENT);

if($dispatchEvent) {
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_CREATE_EVENT);
}
return $this;
}

public function update(EntityInterface $entity): self
public function update(EntityInterface $entity, bool $dispatchEvent = true): self
{
if($dispatchEvent){
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_UPDATE_EVENT);
}
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::UPDATE_EVENT);

if($dispatchEvent) {
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_UPDATE_EVENT);
}
return $this;
}

public function delete(EntityInterface $entity): self
public function delete(EntityInterface $entity, bool $dispatchEvent = true): self
{
if($dispatchEvent) {
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_DELETE_EVENT);
}
$this->remove($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::DELETE_EVENT);

if($dispatchEvent) {
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_DELETE_EVENT);
}
return $this;
}

public function flush($entity=null): self
public function flush($entity = null): self
{
$this->wrapped->flush($entity);


+ 27
- 0
Doctrine/Extension/BlameableNullableTrait.php 파일 보기

@@ -0,0 +1,27 @@
<?php

namespace Lc\SovBundle\Doctrine\Extension;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Lc\SovBundle\Model\User\UserInterface;

trait BlameableNullableTrait
{

/**
* @Gedmo\Blameable(on="create")
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\User\UserInterface")
* @ORM\JoinColumn(nullable=true)
*/
protected $createdBy;

/**
* @Gedmo\Blameable(on="update")
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\User\UserInterface")
* @ORM\JoinColumn(nullable=true)
*/
protected $updatedBy;


}

+ 15
- 0
Doctrine/Extension/ClearIdTrait.php 파일 보기

@@ -0,0 +1,15 @@
<?php

namespace Lc\SovBundle\Doctrine\Extension;

trait ClearIdTrait
{

public function clearId($id): self
{
$this->id = $id;

return $this;
}

}

+ 1
- 1
Doctrine/Extension/SluggableTrait.php 파일 보기

@@ -9,7 +9,7 @@ trait SluggableTrait
{
/**
* @ORM\Column(type="string", length=255)
* @Gedmo\Slug(fields={"title"})
* @Gedmo\Slug(fields={"title"}, unique=true)
*/
protected $slug;


+ 34
- 0
Doctrine/QueryBuilder.php 파일 보기

@@ -0,0 +1,34 @@
<?php

namespace Lc\SovBundle\Doctrine;

use Doctrine\ORM\QueryBuilder as DoctrineQueryBuilder;

/**
* class QueryBuilder.
*
* @author La clic !!!!
*/
class QueryBuilder extends DoctrineQueryBuilder
{

public function andWhereParent($dqlId, $entityId):self
{
$this->andWhere($dqlId.'.parent = :entityId');
$this->setParameter('entityId', $entityId);
return $this;
}

public function andWhereParentIsNull($dqlId):self
{
$this->andWhere($dqlId.'.parent IS NULL');
return $this;
}

public function andWhereStatus($dqlId, $status){
$this->andWhere($dqlId.'.status = :status');
$this->setParameter('status', $status);
return $this;
}

}

+ 28
- 0
Event/EntityComponentEvent.php 파일 보기

@@ -0,0 +1,28 @@
<?php

namespace Lc\SovBundle\Event;

use Lc\SovBundle\Doctrine\EntityInterface;
use Symfony\Contracts\EventDispatcher\Event;

/**
* class EntityEvent.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class EntityComponentEvent extends Event
{
const DUPLICATE_EVENT = 'entity_component_event.duplicate';

protected EntityInterface $entity;

public function __construct(EntityInterface $entity)
{
$this->entity = $entity;
}

public function getEntity(): EntityInterface
{
return $this->entity;
}
}

+ 6
- 3
Event/EntityManager/EntityManagerEvent.php 파일 보기

@@ -12,9 +12,12 @@ use Symfony\Contracts\EventDispatcher\Event;
*/
class EntityManagerEvent extends Event
{
const CREATE_EVENT = 'entity_manager_event.create';
const UPDATE_EVENT = 'entity_manager_event.update';
const DELETE_EVENT = 'entity_manager_event.delete';
const PRE_CREATE_EVENT = 'entity_manager_event.pre_create';
const POST_CREATE_EVENT = 'entity_manager_event.post_create';
const PRE_UPDATE_EVENT = 'entity_manager_event.pre_update';
const POST_UPDATE_EVENT = 'entity_manager_event.post_update';
const PRE_DELETE_EVENT = 'entity_manager_event.pre_delete';
const POST_DELETE_EVENT = 'entity_manager_event.post_delete';

protected EntityInterface $entity;


+ 0
- 73
EventSubscriber/Action/ActionEasyAdminSubscriber.php 파일 보기

@@ -1,73 +0,0 @@
<?php

namespace Lc\SovBundle\EventSubscriber\Action;

use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Query;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Gedmo\Translatable\TranslatableListener;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use function Symfony\Component\Translation\t;

class ActionEasyAdminSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;

public function __construct(EntityManager $entityManager, AdminUrlGenerator $adminUrlGenerator)
{
$this->em = $entityManager;
$this->adminUrlGenerator = $adminUrlGenerator;
}

public static function getSubscribedEvents()
{
return [
AfterCrudActionEvent::class => ['overrideSortAction'],
];
}

public function overrideSortAction(AfterCrudActionEvent $event)
{
$actions = $event->getResponseParameters()->get('global_actions');
if ($actions) {
foreach ($actions as $i=>$action) {
//récriture du bouton 'retour au parent'
if ($action->getName() == 'index_parent') {
$entity = $event->getAdminContext()->getEntity()->getInstance();
if ($entity !== null) {
if($entity->getParent() !==null){
$url = $this->adminUrlGenerator
->setController($event->getAdminContext()->getCrud()->getControllerFqcn())
->set('entityId', $entity->getParent()->getId())
->generateUrl();
$action->setLinkUrl($url);
}
}else{
unset($actions[$i]);
}
}

if ($action->getName() == 'sort') {
$entityId = $event->getAdminContext()->getRequest()->get('entityId');
if ($entityId != null) {
$url = $this->adminUrlGenerator
->setController($event->getAdminContext()->getCrud()->getControllerFqcn())
->setAction($action->getName())
->set('entityId', $entityId)
->generateUrl();
$action->setLinkUrl($url);
}
}
}
}
}


}

EventSubscriber/EasyAdminEventSubscriber.php → EventSubscriber/FlashMessageAdminEventSubscriber.php 파일 보기

@@ -9,7 +9,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Translation\TranslatableMessage;

class EasyAdminEventSubscriber implements EventSubscriberInterface
class FlashMessageAdminEventSubscriber implements EventSubscriberInterface
{
protected $session ;


+ 109
- 0
EventSubscriber/SiteSettingEventSubscriber.php 파일 보기

@@ -0,0 +1,109 @@
<?php

namespace Lc\SovBundle\EventSubscriber;

use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Factory\Setting\SiteSettingFactory;
use Lc\SovBundle\Factory\Site\SiteFactory;
use Lc\SovBundle\Repository\Setting\SiteSettingRepository;
use Lc\SovBundle\Repository\Site\SiteRepository;
use Lc\SovBundle\Repository\Site\SiteStore;
use Lc\SovBundle\Solver\Setting\SettingSolver;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class SiteSettingEventSubscriber implements EventSubscriberInterface
{
protected EntityManagerInterface $entityManager;
protected SiteSettingDefinitionInterface $siteSettingDefinition;
protected SiteSettingFactory $siteSettingFactory;
protected SiteSettingRepository $siteSettingRepository;
protected SiteStore $siteStore;
protected SiteFactory $siteFactory;
protected SettingSolver $settingSolver;

public function __construct(
EntityManagerInterface $entityManager,
SiteSettingRepository $siteSettingRepository,
SiteStore $siteStore,
SiteSettingDefinitionInterface $siteSettingDefinition,
SiteSettingFactory $siteSettingFactory,
SiteFactory $siteFactory,
SettingSolver $settingSolver
) {
$this->entityManager = $entityManager;
$this->siteSettingDefinition = $siteSettingDefinition;
$this->siteSettingFactory = $siteSettingFactory;
$this->siteSettingRepository = $siteSettingRepository;
$this->siteStore = $siteStore;
$this->siteFactory = $siteFactory;
$this->settingSolver = $settingSolver;
}

public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => ['initSettings']
];
}

public function initSettings()
{
$site = $this->getSiteDefault();
if (!$site) {
$site = $this->siteFactory->create('default');
$this->entityManager->persist($site);
$this->entityManager->flush($site);
}

$settings = $this->siteSettingDefinition->getSettings();
$factory = $this->siteSettingFactory;

foreach ($settings as $category => $settingList) {
foreach ($settingList as $settingName => $setting) {
$entitySetting = $this->settingSolver->getSetting($site, $settingName);

if (!$entitySetting) {

$text = null;
$date = null;
$file = null;

$fieldValue = isset($setting['default']) ? $setting['default'] : null;

if($setting['field'] == 'text') {
$text = $fieldValue;
}
if($setting['field'] == 'date') {
$date = $fieldValue;
}
if($setting['field'] == 'file') {
$file = $fieldValue;
}

$entitySetting = $factory->create($site, $setting['name'], $text, $date, $file);

$this->entityManager->persist($entitySetting);
} else {
$methodGetValue = 'get' . ucfirst($setting['field']);
if ($entitySetting->$methodGetValue() === null
&& isset($setting['default'])
&& $setting['default'] !== null) {
$methodSetValue = 'set' . ucfirst($setting['field']);
$entitySetting->$methodSetValue($setting['default']);
$this->entityManager->update($entitySetting);
}
}
}
}

$this->entityManager->flush();
}

public function getSiteDefault()
{
return $this->siteStore->getOneByDevAlias('default');
}

}

+ 52
- 0
EventSubscriber/SluggablePropertyEventSubscriber.php 파일 보기

@@ -0,0 +1,52 @@
<?php

namespace Lc\SovBundle\EventSubscriber;

use Doctrine\ORM\EntityManagerInterface;

use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Doctrine\Extension\SluggableInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\StatusInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Event\EntityComponentEvent;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Repository\AbstractRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class SluggablePropertyEventSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;

public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}

public static function getSubscribedEvents()
{
return [
EntityComponentEvent::DUPLICATE_EVENT => ['setSluggablePropertyDuplicateEvent'],
EntityManagerEvent::POST_UPDATE_EVENT => ['setSluggablePropertyUpdateEvent'],
];
}

public function setSluggablePropertyDuplicateEvent(EntityComponentEvent $event)
{
$entity = $event->getEntity();
if ($entity instanceof SluggableInterface) {
$entity->clearId(null);
$entity->setSlug(null);
}
}

public function setSluggablePropertyUpdateEvent(EntityManagerEvent $event)
{
$entity = $event->getEntity();
if ($entity instanceof SluggableInterface) {
$entity->setSlug(null);
}
}

}

EventSubscriber/CreateEntityEventSubscriber.php → EventSubscriber/SortablePropertyEventSubscriber.php 파일 보기

@@ -12,7 +12,7 @@ use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Repository\AbstractRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CreateEntityEventSubscriber implements EventSubscriberInterface
class SortablePropertyEventSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;
@@ -25,11 +25,11 @@ class CreateEntityEventSubscriber implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return [
EntityManagerEvent::CREATE_EVENT => ['createEntity'],
EntityManagerEvent::PRE_CREATE_EVENT => ['setCommonProperty'],
];
}

public function createEntity(EntityManagerEvent $event)
public function setCommonProperty(EntityManagerEvent $event)
{
$entity = $event->getEntity();
$entityRepository = $this->em->getRepository(get_class($entity));

+ 47
- 0
EventSubscriber/User/UserPasswordEventSubscriber.php 파일 보기

@@ -0,0 +1,47 @@
<?php

namespace Lc\SovBundle\EventSubscriber\User;

use Doctrine\ORM\EntityManagerInterface;

use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\StatusInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Repository\AbstractRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserPasswordEventSubscriber implements EventSubscriberInterface
{
protected $passwordEncoder;

public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}

public static function getSubscribedEvents()
{
return [
EntityManagerEvent::PRE_CREATE_EVENT => ['setUserPasswordIfNull'],
];
}

public function setUserPasswordIfNull(EntityManagerEvent $event)
{
$entity = $event->getEntity();

if ($entity instanceof UserInterface) {
if ($entity->getPassword() == null) {
$password = $this->passwordEncoder->encodePassword($entity, $entity->generatePassword());
$entity->setPassword($password);
}
}
}


}

+ 8
- 0
Factory/AbstractFactory.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory;

abstract class AbstractFactory implements FactoryInterface
{

}

+ 8
- 0
Factory/FactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory;

interface FactoryInterface
{

}

+ 18
- 0
Factory/File/FileFactory.php 파일 보기

@@ -0,0 +1,18 @@
<?php

namespace Lc\SovBundle\Factory\File;

use App\Entity\File\File;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\File\FileInterface;

class FileFactory extends AbstractFactory
{
public function create(): FileInterface
{
$file = new File();

return $file;
}

}

+ 18
- 0
Factory/Newsletter/NewsletterFactory.php 파일 보기

@@ -0,0 +1,18 @@
<?php

namespace Lc\SovBundle\Factory\Newsletter;

use App\Entity\Newsletter\Newsletter;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Newsletter\NewsletterInterface;

class NewsletterFactory extends AbstractFactory
{
public function create(): NewsletterInterface
{
$newsletter = new Newsletter();

return $newsletter;
}

}

+ 25
- 0
Factory/Reminder/ReminderFactory.php 파일 보기

@@ -0,0 +1,25 @@
<?php

namespace Lc\SovBundle\Factory\Reminder;

use App\Entity\Reminder\Reminder;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Reminder\ReminderInterface;

class ReminderFactory extends AbstractFactory implements ReminderFactoryInterface
{
public function create(
string $crudAction = null,
string $crudControllerFqcn = null,
int $entityId = null
): ReminderInterface {
$reminder = new Reminder();

$reminder->setCrudAction($crudAction);
$reminder->setCrudControllerFqcn($crudControllerFqcn);
$reminder->setEntityId($entityId);

return $reminder;
}

}

+ 8
- 0
Factory/Reminder/ReminderFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Reminder;

interface ReminderFactoryInterface
{

}

+ 25
- 0
Factory/Setting/SiteSettingFactory.php 파일 보기

@@ -0,0 +1,25 @@
<?php

namespace Lc\SovBundle\Factory\Setting;

use App\Entity\Setting\SiteSetting;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\File\FileInterface;
use Lc\SovBundle\Model\Setting\SiteSettingInterface;
use Lc\SovBundle\Model\Site\SiteInterface;

class SiteSettingFactory extends AbstractFactory implements SiteSettingFactoryInterface
{
public function create(SiteInterface $site, string $name, string $text = null, \DateTime $date = null, FileInterface $file = null): SiteSettingInterface
{
$siteSetting = new SiteSetting();

$siteSetting->setSite($site);
$siteSetting->setName($name);
$siteSetting->setText($text);
$siteSetting->setDate($date);
$siteSetting->setFile($file);

return $siteSetting;
}
}

+ 8
- 0
Factory/Setting/SiteSettingFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Setting;

interface SiteSettingFactoryInterface
{

}

+ 18
- 0
Factory/Site/NewsFactory.php 파일 보기

@@ -0,0 +1,18 @@
<?php

namespace Lc\SovBundle\Factory\Site;

use App\Entity\Site\News;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Site\NewsInterface;

class NewsFactory extends AbstractFactory implements NewsFactoryInterface
{
public function create(): NewsInterface
{
$news = new News();

return $news;
}

}

+ 8
- 0
Factory/Site/NewsFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Site;

interface NewsFactoryInterface
{

}

+ 17
- 0
Factory/Site/PageFactory.php 파일 보기

@@ -0,0 +1,17 @@
<?php

namespace Lc\SovBundle\Factory\Site;

use App\Entity\Site\Page;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Site\PageInterface;

class PageFactory extends AbstractFactory implements PageFactoryInterface
{
public function create(): PageInterface
{
$page = new Page();

return $page;
}
}

+ 8
- 0
Factory/Site/PageFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Site;

interface PageFactoryInterface
{

}

+ 19
- 0
Factory/Site/SiteFactory.php 파일 보기

@@ -0,0 +1,19 @@
<?php

namespace Lc\SovBundle\Factory\Site;

use App\Entity\Site\Site;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Site\SiteInterface;

class SiteFactory extends AbstractFactory implements SiteFactoryInterface
{
public function create(string $devAlias = null): SiteInterface
{
$site = new Site();

$site->setDevAlias($devAlias);

return $site;
}
}

+ 8
- 0
Factory/Site/SiteFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Site;

interface SiteFactoryInterface
{

}

+ 24
- 0
Factory/Ticket/TicketFactory.php 파일 보기

@@ -0,0 +1,24 @@
<?php

namespace Lc\SovBundle\Factory\Ticket;

use App\Entity\Ticket\Ticket;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Model\Ticket\TicketModel;

class TicketFactory extends AbstractFactory implements TicketFactoryInterface
{
public function create(): TicketInterface
{
$ticket = new Ticket();

$ticketMessageFactory = new TicketMessageFactory();
$ticketMessage = $ticketMessageFactory->create($ticket) ;

$ticket->setStatus(TicketModel::TICKET_STATUS_OPEN);
$ticket->addTicketMessage($ticketMessage) ;

return $ticket;
}
}

+ 8
- 0
Factory/Ticket/TicketFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Ticket;

interface TicketFactoryInterface
{

}

+ 21
- 0
Factory/Ticket/TicketMessageFactory.php 파일 보기

@@ -0,0 +1,21 @@
<?php

namespace Lc\SovBundle\Factory\Ticket;

use App\Entity\Ticket\TicketMessage;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Model\Ticket\TicketMessageInterface;

class TicketMessageFactory extends AbstractFactory implements TicketMessageFactoryInterface
{
public function create(TicketInterface $ticket): TicketMessageInterface
{
$ticketMessage = new TicketMessage();

$ticketMessage->setTicket($ticket);
$ticketMessage->setStatus(1);

return $ticketMessage;
}
}

+ 8
- 0
Factory/Ticket/TicketMessageFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Ticket;

interface TicketMessageFactoryInterface
{

}

+ 17
- 0
Factory/User/GroupUserFactory.php 파일 보기

@@ -0,0 +1,17 @@
<?php

namespace Lc\SovBundle\Factory\User;

use App\Entity\User\GroupUser;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\User\GroupUserInterface;

class GroupUserFactory extends AbstractFactory implements GroupUserFactoryInterface
{
public function create(): GroupUserInterface
{
$groupUser = new GroupUser();

return $groupUser;
}
}

+ 8
- 0
Factory/User/GroupUserFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\User;

interface GroupUserFactoryInterface
{

}

+ 17
- 0
Factory/User/UserFactory.php 파일 보기

@@ -0,0 +1,17 @@
<?php

namespace Lc\SovBundle\Factory\User;

use App\Entity\User\User;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\User\UserInterface;

class UserFactory extends AbstractFactory
{
public function create(): UserInterface
{
$user = new User();

return $user;
}
}

+ 8
- 0
Factory/User/UserFactoryInterface.php 파일 보기

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\User;

interface UserFactoryInterface
{

}

+ 1
- 3
Field/BooleanField.php 파일 보기

@@ -4,9 +4,7 @@ namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Lc\SovBundle\Form\Type\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

/**
@@ -21,7 +19,7 @@ final class BooleanField implements FieldInterface
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setTemplatePath('@LcSov/adminlte/crud/field/toggle.html.twig')
->setTemplatePath('@LcSov/adminlte/crud/field/boolean.html.twig')
->setFormType(CheckboxType::class);
}


+ 64
- 65
Field/CollectionField.php 파일 보기

@@ -11,69 +11,68 @@ use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class CollectionField implements FieldInterface
{
use FieldTrait;

public const OPTION_ALLOW_ADD = 'allowAdd';
public const OPTION_ALLOW_DELETE = 'allowDelete';
public const OPTION_ENTRY_IS_COMPLEX = 'entryIsComplex';
public const OPTION_ENTRY_TYPE = 'entryType';
public const OPTION_SHOW_ENTRY_LABEL = 'showEntryLabel';

public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setTemplatePath('@LcSov/adminlte/crud/field/collection.html.twig')
->setFormType(CollectionType::class)
/*->addWebpackEncoreEntries('adminlte-field-collection')*/
->setFormTypeOption('allow_add', true)
->setFormTypeOption('allow_delete', true)
->setFormTypeOption('entry_options', array('label' => false))
->addCssClass('field-collection')
->setFormTypeOption('attr', array('class' => 'field-collection-group'))

//Fixe le bug easyadmin lors de la gestion d'un champ de type array, laisser a false pour une entité
->setFormTypeOption('row_attr', array('data-reindex-key' => true));

}

public function allowAdd(bool $allow = true): self
{
$this->setCustomOption(self::OPTION_ALLOW_ADD, $allow);

return $this;
}

public function allowDelete(bool $allow = true): self
{
$this->setCustomOption(self::OPTION_ALLOW_DELETE, $allow);

return $this;
}

/**
* Set this option to TRUE if the collection items are complex form types
* composed of several form fields (EasyAdmin applies a special rendering to make them look better).
*/
public function setEntryIsComplex(bool $isComplex): self
{
$this->setCustomOption(self::OPTION_ENTRY_IS_COMPLEX, $isComplex);

return $this;
}

public function setEntryType(string $formTypeFqcn): self
{
$this->setCustomOption(self::OPTION_ENTRY_TYPE, $formTypeFqcn);

return $this;
}

public function showEntryLabel(bool $showLabel = true): self
{
$this->setCustomOption(self::OPTION_SHOW_ENTRY_LABEL, $showLabel);

return $this;
}
use FieldTrait;

public const OPTION_ALLOW_ADD = 'allowAdd';
public const OPTION_ALLOW_DELETE = 'allowDelete';
public const OPTION_ENTRY_IS_COMPLEX = 'entryIsComplex';
public const OPTION_ENTRY_TYPE = 'entryType';
public const OPTION_SHOW_ENTRY_LABEL = 'showEntryLabel';

public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setTemplatePath('@LcSov/adminlte/crud/field/collection.html.twig')
->setFormType(CollectionType::class)
/*->addWebpackEncoreEntries('adminlte-field-collection')*/
->setFormTypeOption('allow_add', true)
->setFormTypeOption('allow_delete', true)
->setFormTypeOption('entry_options', array('label' => false))
->addCssClass('field-collection')
->setFormTypeOption('attr', array('class' => 'field-collection-group'))

//Fixe le bug easyadmin lors de la gestion d'un champ de type array, laisser a false pour une entité
->setFormTypeOption('row_attr', array('data-reindex-key' => true));
}

public function allowAdd(bool $allow = true): self
{
$this->setCustomOption(self::OPTION_ALLOW_ADD, $allow);

return $this;
}

public function allowDelete(bool $allow = true): self
{
$this->setCustomOption(self::OPTION_ALLOW_DELETE, $allow);

return $this;
}

/**
* Set this option to TRUE if the collection items are complex form types
* composed of several form fields (EasyAdmin applies a special rendering to make them look better).
*/
public function setEntryIsComplex(bool $isComplex): self
{
$this->setCustomOption(self::OPTION_ENTRY_IS_COMPLEX, $isComplex);

return $this;
}

public function setEntryType(string $formTypeFqcn): self
{
$this->setCustomOption(self::OPTION_ENTRY_TYPE, $formTypeFqcn);

return $this;
}

public function showEntryLabel(bool $showLabel = true): self
{
$this->setCustomOption(self::OPTION_SHOW_ENTRY_LABEL, $showLabel);

return $this;
}
}

+ 1
- 1
Field/FileManagerField.php 파일 보기

@@ -4,7 +4,7 @@ namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Lc\SovBundle\Form\Type\Crud\FileManagerType;
use Lc\SovBundle\Form\Common\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

/**

+ 67
- 0
Field/Filter/AssociationFilter.php 파일 보기

@@ -0,0 +1,67 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class AssociationFilter
{
use FilterTrait;


public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$targetEntity = $options['entity_dto']->getPropertyMetadata($fieldDto->getProperty())->get('targetEntity');

$classImplements = class_implements($targetEntity);
$builder->add(
$fieldDto->getProperty(),
EntityType::class,
array(
'class' => $targetEntity,
'placeholder' => '--',
'query_builder' => function (EntityRepository $repo) use ($classImplements) {
return $repo->createQueryBuilder('entity');
},
'required' => false,
'attr' => array(
'class' => 'select2 input-sm',
'form' => 'filters-form',
),


)
);
}

public function applyFilter(QueryBuilder $queryBuilder, string $fieldProperty, string $filteredValue = null)
{
if ($filteredValue !== null) {
$queryBuilder->andWhere('entity.'.$fieldProperty.' = :'.$fieldProperty.'');
$queryBuilder->setParameter($fieldProperty, $filteredValue);
/* //TODO Faut généraliser avec TreeInterface, ça ne doit pas être ici
if ($field['property'] == 'productCategories') {

$queryBuilder->andWhere(':' . $field['property'] . ' MEMBER OF entity.' . $field['property'] . ' OR product_categories.parent = :' . $field['property']);
$queryBuilder->setParameter($field['property'], $filter);

if ($field['type_options']['multiple']) {
$queryBuilder->andWhere(':' . $field['property'] . ' MEMBER OF entity.' . $field['property'] . '');
} else {
}

if ($filter instanceof TreeInterface && $filter->getParent() == null) {
$queryBuilder->setParameter($field['property'], array_merge(array($filter), $filter->getChildrens()->toArray()));
} else {
}*/
}
}

}

+ 62
- 0
Field/Filter/CheckboxFilter.php 파일 보기

@@ -0,0 +1,62 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;

use function Symfony\Component\String\u;


/**
* @author La clic ! <contact@laclic.fr>
*/
class CheckboxFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add($fieldDto->getProperty(), ChoiceType::class, array(
'choices'=> array(
'Oui' => 1,
'Non' => 0,
),
'placeholder'=> '--',
'required'=>false,
'attr'=>array(
'class'=> 'select2 input-sm',
'form'=> 'filters-form'
)
));
}

public function applyFilter(QueryBuilder $queryBuilder, string $fieldProperty, string $filteredValue= null)
{
if ($filteredValue !== null) {
if ($this->isRelationField($fieldProperty)) {
$aliasRelation = $this->getFieldPropertyRelationAlias($fieldProperty);
if (array_search($aliasRelation, $queryBuilder->getAllAliases()) === false) {
$queryBuilder->innerJoin('entity.'.$aliasRelation, $aliasRelation);
}
$queryBuilder->andWhere(
$fieldProperty.' = :'.$this->getFieldPropertySnake($fieldProperty).''
);
$queryBuilder->setParameter(
$this->getFieldPropertySnake($fieldProperty),
'%'.$filteredValue.'%'
);
} else {
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' = :'.$fieldProperty.''
);
$queryBuilder->setParameter($fieldProperty, '%'.$filteredValue.'%');
}
dump($queryBuilder);
}
}

}

+ 77
- 0
Field/Filter/ChoiceFilter.php 파일 보기

@@ -0,0 +1,77 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;

use function Symfony\Component\String\u;


/**
* @author La clic ! <contact@laclic.fr>
*/
class ChoiceFilter
{
use FilterTrait;

protected $translatorAdmin;

public function __construct(?TranslatorAdmin $translatorAdmin = null)
{
$this->translatorAdmin = $translatorAdmin;
}

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$entity = new $options['entity_class'];
$choicesFct = 'get'.u($fieldDto->getProperty())->title()->toString().'Choices';

if (method_exists($entity, $choicesFct)) {
$builder->add(
$fieldDto->getProperty(),
ChoiceType::class,
array(
'required' => false,
'choices' => $this->translatorAdmin->transChoices(
$entity->$choicesFct(),
$options['entity_name'],
$fieldDto->getProperty()
),
'attr' => array(
'class' => 'select2 input-sm',
'form' => 'filters-form',
),
)
);
}
}

public function applyFilter(QueryBuilder $queryBuilder, string $fieldProperty, string $filteredValue = null)
{
if ($filteredValue !== null) {
if ($this->isRelationField($fieldProperty)) {
$aliasRelation = $this->getFieldPropertyRelationAlias($fieldProperty);
if (array_search($aliasRelation, $queryBuilder->getAllAliases()) === false) {
$queryBuilder->innerJoin('entity.'.$aliasRelation, $aliasRelation);
}
$queryBuilder->andWhere(
$fieldProperty.' LIKE :'.$this->getFieldPropertySnake($fieldProperty).''
);
$queryBuilder->setParameter(
$this->getFieldPropertySnake($fieldProperty),
'%'.$filteredValue.'%'
);
} else {
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' LIKE :'.$fieldProperty.''
);
$queryBuilder->setParameter($fieldProperty, '%'.$filteredValue.'%');
}
}
}

}

+ 64
- 0
Field/Filter/DateFilter.php 파일 보기

@@ -0,0 +1,64 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class DateFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
$builder->create(
str_replace('.', '_', $fieldDto->getProperty()),
FormType::class,
array('inherit_data' => true)
)
->add(
'dateStart',
DateType::class,
array(
'widget' => 'single_text',
'required' => false,
)
)
->add(
'dateEnd',
DateType::class,
array(
'widget' => 'single_text',
'required' => false,

)
)
);
}

public function applyFilter(
QueryBuilder $queryBuilder,
string $fieldProperty,
\DateTime $dateStart = null,
\DateTime $dateEnd = null
) {
if ($dateStart) {
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' >= :dateStart'
)->setParameter('dateStart', $dateStart);
}
if ($dateEnd) {
$dateEnd->setTime(23, 59, 59);
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' <= :dateEnd'
)->setParameter('dateEnd', $dateEnd);
}
}
}

+ 175
- 0
Field/Filter/FilterManager.php 파일 보기

@@ -0,0 +1,175 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;


/**
* @author La clic ! <contact@laclic.fr>
*/
class FilterManager
{
protected $em;

use FilterTrait;

public function __construct(SessionInterface $session, EntityManagerInterface $entityManager)
{
$this->session = $session;
$this->em = $entityManager;
}


public function handleFiltersForm(QueryBuilder $queryBuilder, Form $filtersForm, $fields, EntityDto $entityDto)
{
foreach ($fields as $field) {
if ($field instanceof FieldInterface) {
$fieldDto = $field->getAsDto();
} else {
$fieldDto = $field;
}
if ($fieldDto->isDisplayedOn(Crud::PAGE_INDEX)) {
if ($filtersForm->has($this->getFieldPropertySnake($fieldDto->getProperty()))) {



if ($fieldDto->getFormType() === DateTimeType::class || $fieldDto->getFormType(
) === DateType::class) {
$filteredValue['dateStart'] = $this->getFilteredValue(
$filtersForm,
$entityDto->getFqcn(),
$fieldDto->getProperty(),
'dateStart'
);
$filteredValue['dateEnd'] = $this->getFilteredValue(
$filtersForm,
$entityDto->getFqcn(),
$fieldDto->getProperty(),
'dateEnd'
);
}else{
$filteredValue = $this->getFilteredValue(
$filtersForm,
$entityDto->getFqcn(),
$fieldDto->getProperty()
);
}
$this->applyFilter($queryBuilder, $fieldDto, $filteredValue);
}
}
}
}

public function applyFilter(QueryBuilder $queryBuilder, FieldDto $fieldDto, $filteredValue)
{
switch ($fieldDto->getFormType()) {
case CheckboxType::class:
$checkboxFilter = new CheckboxFilter();
$checkboxFilter->applyFilter($queryBuilder, $fieldDto->getProperty(), $filteredValue);
break;
case ChoiceType::class:
$choiceFilter = new ChoiceFilter();
$choiceFilter->applyFilter($queryBuilder, $fieldDto->getProperty(), $filteredValue);
break;
case IntegerType::class:
$integerFilter = new IntegerFilter();
$integerFilter->applyFilter($queryBuilder, $fieldDto->getProperty(), $filteredValue);
break;
case TextType::class:
$textFilter = new TextFilter();
$textFilter->applyFilter($queryBuilder, $fieldDto->getProperty(), $filteredValue);
break;
case EntityType::class:
$textFilter = new AssociationFilter();
$textFilter->applyFilter($queryBuilder, $fieldDto->getProperty(), $filteredValue);
break;
case DateTimeType::class:
case DateType::class:
$textFilter = new DateFilter();
$textFilter->applyFilter(
$queryBuilder,
$fieldDto->getProperty(),
$filteredValue['dateStart'],
$filteredValue['dateEnd']
);
break;
}
}

public function getFilteredValue(
Form $filtersForm,
string $entityFqcn,
string $field,
string $dateExtraField = null
) {
$field = $this->getFieldPropertySnake($field);
$sessionParam = $entityFqcn.$field.$dateExtraField;

$formField = $this->getFormField($filtersForm, $field, $dateExtraField);

$value = $formField->getData();

//Il existe une valeur posté dans le formulaire
if ($value !== null) {
$this->session->set($sessionParam, $value);
return $value;
}

//action reset
if ($filtersForm->get('reset')->getData() == 'clearAll') {
$this->session->remove($sessionParam);
return null;
}

//Récupération des valeurs stocké en sessions si le forrmFilters n'a pas été posté
if ($this->session->get($sessionParam) && !$filtersForm->isSubmitted() && $formField) {
$value = $this->session->get($sessionParam);

//Champ date
if ($formField->getConfig()->getOption('input') == 'datetime') {
$filtersForm->get($field)->get($dateExtraField)->setData($value);
//Champ association
} elseif ($formField->getConfig()->getOption('class')) {
$valFormated = $this->em->getRepository(
$formField->getConfig()->getOption('class')
)->find($value);
$filtersForm->get($field)->setData($valFormated);
} else {
//Champ noramux
$filtersForm->get($field)->setData($value);
}

return $value;
}

}

public
function getFormField(
Form $filtersForm,
string $field,
string $extraField = null
): Form {
if ($extraField) {
return $filtersForm->get($field)->get($extraField);
} else {
return $filtersForm->get($field);
}
}
}

+ 37
- 0
Field/Filter/FilterTrait.php 파일 보기

@@ -0,0 +1,37 @@
<?php

namespace Lc\SovBundle\Field\Filter;


/**
* @author La clic ! <contact@laclic.fr>
*/
trait FilterTrait
{

public function getFieldPropertySnake(string $fieldName): string
{
return str_replace('.', '_', $fieldName);
}

public function getFieldPropertyBase(string $fieldName): string
{
return str_replace('_', '.', $fieldName);
}

public function isRelationField(string $fieldName, string $needle = "."): bool
{
return strpos($fieldName, $needle) !== false;
}

public function getFieldPropertyWithoutRelation(string $fieldName, string $needle = '.'): string
{
return substr($fieldName, strpos($fieldName, $needle) + 1);
}

public function getFieldPropertyRelationAlias(string $fieldName, string $needle = '.'): string
{
return substr($fieldName, 0, strpos($fieldName, $needle));
}

}

+ 43
- 0
Field/Filter/IntegerFilter.php 파일 보기

@@ -0,0 +1,43 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class IntegerFilter
{
use FilterTrait;


public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
IntegerType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(QueryBuilder $queryBuilder, string $fieldProperty, string $filteredValue= null)
{
if ($filteredValue !== null) {
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' = :'.$fieldProperty.''
);
$queryBuilder->setParameter($fieldProperty, $filteredValue);
}
}

}

+ 59
- 0
Field/Filter/TextFilter.php 파일 보기

@@ -0,0 +1,59 @@
<?php

namespace Lc\SovBundle\Field\Filter;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class TextFilter
{
use FilterTrait;


public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(QueryBuilder $queryBuilder, string $fieldProperty, string $filteredValue= null)
{

if ($filteredValue !== null) {
if ($this->isRelationField($fieldProperty)) {

$aliasRelation = $this->getFieldPropertyRelationAlias($fieldProperty);
if (array_search($aliasRelation, $queryBuilder->getAllAliases()) === false) {
$queryBuilder->innerJoin('entity.'.$aliasRelation, $aliasRelation);
}
$queryBuilder->andWhere(
$fieldProperty.' LIKE :'.$this->getFieldPropertySnake($fieldProperty).''
);
$queryBuilder->setParameter(
$this->getFieldPropertySnake($fieldProperty),
'%'.$filteredValue.'%'
);
} else {
$queryBuilder->andWhere(
'entity.'.$fieldProperty.' LIKE :'.$fieldProperty.''
);
$queryBuilder->setParameter($fieldProperty, '%'.$filteredValue.'%');
}
}
}

}

+ 1
- 1
Field/GalleryManagerField.php 파일 보기

@@ -4,7 +4,7 @@ namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Lc\SovBundle\Form\Type\Crud\FileManagerType;
use Lc\SovBundle\Form\Common\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;



+ 1
- 2
Field/ImageManagerField.php 파일 보기

@@ -4,8 +4,7 @@ namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Lc\SovBundle\Form\Type\Crud\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Lc\SovBundle\Form\Common\FileManagerType;

/**
* @author La clic ! <contact@laclic.fr>

+ 21
- 23
Field/StatusField.php 파일 보기

@@ -4,36 +4,34 @@ namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Lc\SovBundle\Form\Type\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

/**
* @author La clic ! <contact@laclic.fr>
*/
final class StatusField implements FieldInterface
{
use FieldTrait;

public static function new(string $propertyName, ?string $label = null, bool $templateToggle = true): self
{
$field = (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(ChoiceType::class)
->setFormTypeOption('expanded', true)
->setFormTypeOption('multiple', false)
->setFormTypeOption('choices', ['En ligne' => 1, 'Hors ligne' => 0])
->setCustomOption('toggle_label', 'En ligne');

$template = 'toggle.html.twig' ;
if(!$templateToggle) {
$template = 'status.html.twig' ;
}

$field->setTemplatePath('@LcSov/adminlte/crud/field/'.$template) ;

return $field ;
use FieldTrait;

public static function new(string $propertyName, ?string $label = null, bool $templateToggle = true): self
{
$field = (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(ChoiceType::class)
->setFormTypeOption('expanded', true)
->setFormTypeOption('multiple', false)
->setFormTypeOption('choices', ['En ligne' => 1, 'Hors ligne' => 0])
->setFormTypeOption('placeholder', false)
->setCustomOption('toggle_label', 'En ligne');

$template = 'toggle.html.twig';
if (!$templateToggle) {
$template = 'status.html.twig';
}
$field->setTemplatePath('@LcSov/adminlte/crud/field/' . $template);

return $field;
}

}

+ 25
- 0
Field/ToggleField.php 파일 보기

@@ -0,0 +1,25 @@
<?php

namespace Lc\SovBundle\Field;

use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;

/**
* @author La clic ! <contact@laclic.fr>
*/
final class ToggleField implements FieldInterface
{
use FieldTrait;

public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setTemplatePath('@LcSov/adminlte/crud/field/toggle.html.twig')
->setFormType(CheckboxType::class);
}

}

Form/Type/Crud/CrudFormType.php → Form/Common/CrudFormType.php 파일 보기

@@ -1,6 +1,6 @@
<?php

namespace Lc\SovBundle\Form\Type\Crud;
namespace Lc\SovBundle\Form\Common;


use EasyCorp\Bundle\EasyAdminBundle\Form\Type\EaFormPanelType;
@@ -22,20 +22,25 @@ class CrudFormType extends AbstractType

protected $parent;
protected $doctrineOrmTypeGuesser;
public function __construct(DoctrineOrmTypeGuesser $doctrineOrmTypeGuesser, \EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType $crudFormType)
{

public function __construct(
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=[];
$formPanels = [];
$currentFormPanel = 0;
foreach ($entityDto->getFields() as $fieldDto) {

if (null === $formFieldType = $fieldDto->getFormType()) {
$guessType = $this->doctrineOrmTypeGuesser->guessType($entityDto->getFqcn(), $fieldDto->getProperty());
$formFieldType = $guessType->getType();
@@ -50,7 +55,7 @@ class CrudFormType extends AbstractType
'help' => $fieldDto->getHelp(),
'css_class' => $fieldDto->getCssClass(),
];
foreach($fieldDto->getCustomOptions()->all() as $customOptionKey=> $customOption){
foreach ($fieldDto->getCustomOptions()->all() as $customOptionKey => $customOption) {
$formPanels[$currentFormPanel][$customOptionKey] = $customOption;
}
continue;
@@ -60,17 +65,20 @@ class CrudFormType extends AbstractType
//$this->niche->buildForm($builder, $options);
}

public function finishView(FormView $view, FormInterface $form, array $options){
public function finishView(FormView $view, FormInterface $form, array $options)
{
$this->parent->finishView($view, $form, $options);
}
public function configureOptions(OptionsResolver $resolver){
$this->parent->configureOptions($resolver);

public function configureOptions(OptionsResolver $resolver)
{
$this->parent->configureOptions($resolver);
}
public function getBlockPrefix(){

public function getBlockPrefix()
{
return $this->parent->getBlockPrefix();
}



}

Form/Type/Crud/FileManagerType.php → Form/Common/FileManagerType.php 파일 보기

@@ -1,6 +1,6 @@
<?php

namespace Lc\SovBundle\Form\Type\Crud;
namespace Lc\SovBundle\Form\Common;

use Lc\SovBundle\DataTransformer\FileManagerTypeToDataTransformer;
use Lc\SovBundle\Entity\File\File;

+ 140
- 0
Form/Common/FiltersFormType.php 파일 보기

@@ -0,0 +1,140 @@
<?php

namespace Lc\SovBundle\Form\Common;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use Lc\SovBundle\Field\Filter\AssociationFilter;
use Lc\SovBundle\Field\Filter\CheckboxFilter;
use Lc\SovBundle\Field\Filter\ChoiceFilter;
use Lc\SovBundle\Field\Filter\DateFilter;
use Lc\SovBundle\Field\Filter\FilterManager;
use Lc\SovBundle\Field\Filter\IntegerFilter;
use Lc\SovBundle\Field\Filter\TextFilter;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;

use function Symfony\Component\String\u;


class FiltersFormType extends AbstractType
{
protected $translatorAdmin;

public function __construct(TranslatorAdmin $translatorAdmin)
{
$this->translatorAdmin = $translatorAdmin;
}


public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($options['fields'] as $field) {
if ($field instanceof FieldInterface) {
$fieldDto = $field->getAsDto();
} else {
$fieldDto = $field;
}
if ($fieldDto->isDisplayedOn(Crud::PAGE_INDEX)) {
switch ($fieldDto->getFormType()) {
case CheckboxType::class:
$checkboxFilter = new CheckboxFilter();
$checkboxFilter->buildProperty($builder, $fieldDto);

break;
case ChoiceType::class:
$choiceFilter = new ChoiceFilter($this->translatorAdmin);
$choiceFilter->buildProperty($builder, $fieldDto, $options);
break;
case IntegerType::class:
$integerFilter = new IntegerFilter();
$integerFilter->buildProperty($builder, $fieldDto);

break;
case TextType::class:
$textFilter = new TextFilter();
$textFilter->buildProperty($builder, $fieldDto);
break;
case DateTimeType::class:
case DateType::class:
$textFilter = new DateFilter();
$textFilter->buildProperty($builder, $fieldDto);
break;
case EntityType::class:
$associationFilter = new AssociationFilter();
$associationFilter->buildProperty($builder, $fieldDto, $options);
break;
case 'dateinterval':

break;
case 'float':

break;
}
}
}
$builder->add(
'action_apply',
SubmitType::class,
array(
'label_html'=> true,
'label'=> '<i class="fa fa-search"></i>',
'attr' => array(
'class' => 'btn btn-sm btn-info',
'form' => 'filters-form',
'data-toggle'=>"tooltip",
'title'=> $this->translatorAdmin->transAction("apply"),
'aria-label'=> $this->translatorAdmin->transAction("apply")
),
)
);
$builder->add(
'action_reset',
ButtonType::class,
array(
'label_html'=> true,
'label'=> '<i class="fa fa-eraser"></i>',
'attr' => array(
'class' => 'btn btn-sm btn-warning lc-reset-filters',
'form' => 'filters-form',
'data-toggle'=>"tooltip",
'title'=> $this->translatorAdmin->transAction("reset"),
'aria-label'=> $this->translatorAdmin->transAction("reset")
),
)
);
$builder->add('reset', HiddenType::class);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'label' => false,
'csrf_protection' => false,
'entity_dto' => null,
//'translation_domain' => 'lcshop',
'fields' => false,
'entity_name' => false,
'entity_class' => false,
//'entityClass' => false
]
);
}
}

Form/Type/Crud/PositionType.php → Form/Common/PositionType.php 파일 보기

@@ -1,6 +1,6 @@
<?php

namespace Lc\SovBundle\Form\Type\Crud;
namespace Lc\SovBundle\Form\Common;


use Symfony\Component\Form\AbstractType;

+ 89
- 0
Form/Reminder/ReminderAdminFormType.php 파일 보기

@@ -0,0 +1,89 @@
<?php

namespace Lc\SovBundle\Form\Reminder;

use Lc\SovBundle\Model\Reminder\ReminderInterface;
use Lc\SovBundle\Model\User\UserInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ReminderAdminFormType extends AbstractType
{
protected $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
$userClass = $this->entityManager->getEntityName(UserInterface::class);
$userRepo = $this->entityManager->getRepository(UserInterface::class);
$builder
->add('title', TextType::class, ['label' => 'Titre'])
->add(
'description',
TextareaType::class,
array(
'required' => false
)
)
->add(
'crudAction',
HiddenType::class,
array(
'required' => false
)
)
->add(
'crudControllerFqcn',
HiddenType::class,
array(
'required' => false
)
)
->add(
'entityId',
HiddenType::class,
array(
'required' => false
)
)
->add(
'users',
EntityType::class,
array(
'class' => $userClass,
'choices' => $userRepo->findByRole('ROLE_ADMIN'),
'required' => false,
'multiple' => true,
'expanded' => false
)
)
->add(
'dateReminder',
DateType::class,
array(
'required' => false,
'widget' => 'single_text',
)
);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => $this->entityManager->getEntityName(ReminderInterface::class)
]
);
}
}

+ 117
- 0
Form/Setting/BaseSettingType.php 파일 보기

@@ -0,0 +1,117 @@
<?php

namespace Lc\SovBundle\Form\Setting;

use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Form\Common\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;

abstract class BaseSettingType extends AbstractType
{
protected $em;
protected $settingDefinition;

public function __construct(
EntityManagerInterface $entityManager,
SiteSettingDefinitionInterface $settingDefinition
) {
$this->em = $entityManager;
$this->settingDefinition = $settingDefinition;
}

public function buildFormSetting($label, $form, $settingDefinition, $settingEntity)
{
$settingName = $settingEntity->getName();
$setting = $settingDefinition->getSettingByName($settingName);
$settingType = $settingDefinition->getSettingType($settingName);

if ($settingType == 'text') {
$form->add(
'text',
TextType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'textarea') {
$form->add(
'text',
TextareaType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'textarea_advanced') {
$form->add(
'text',
CKEditorType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'select') {
$form->add(
'text',
ChoiceType::class,
[
'label' => $label,
'expanded' => false,
'multiple' => false,
'placeholder' => false,
'choices' => $setting['choices']
]
);
} elseif ($settingType == 'radio') {
$form->add(
'text',
ChoiceType::class,
[
'label' => $label,
'expanded' => true,
'multiple' => false,
'placeholder' => false,
'choices' => $setting['choices']
]
);
} elseif ($settingType == 'date') {
$form->add(
'date',
DateType::class,
[
'label' => $label,
'widget' => 'single_text',
]
);
} elseif ($settingType == 'time') {
$form->add(
'date',
TimeType::class,
[
'label' => $label,
'input' => 'datetime',
'widget' => 'single_text',
]
);
} elseif ($settingType == 'file' || $settingType == 'image') {
$form->add(
'file',
FileManagerType::class,
[
'label' => $label,
'attr' => [
'type' => $settingType
]
]
);
}
}

}


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.

Loading…
취소
저장