Bladeren bron

Merge branch 'develop' of https://forge.laclic.fr/Laclic/SovBundle into develop

develop
Charly 2 jaren geleden
bovenliggende
commit
230c24b41d
16 gewijzigde bestanden met toevoegingen van 364 en 14 verwijderingen
  1. +5
    -1
      Authenticator/LoginFormAuthenticator.php
  2. +3
    -0
      Component/FileComponent.php
  3. +1
    -0
      Container/ComponentContainer.php
  4. +7
    -0
      Controller/ControllerTrait.php
  5. +2
    -2
      Definition/Field/Site/PageFieldDefinition.php
  6. +0
    -1
      Form/Common/FileManagerType.php
  7. +258
    -0
      Form/Common/FileUploadType.php
  8. +14
    -0
      Repository/AbstractRepositoryQuery.php
  9. +1
    -2
      Repository/User/GroupUserRepositoryQuery.php
  10. +45
    -1
      Resolver/UrlResolver.php
  11. +3
    -2
      Resources/assets/app/adminlte/main/init.js
  12. +7
    -3
      Resources/assets/functions/widgets.js
  13. +1
    -0
      Resources/config/services.yaml
  14. +1
    -0
      Resources/translations/admin.fr.yaml
  15. +0
    -1
      Resources/views/adminlte/crud/form_theme.html.twig
  16. +16
    -1
      Twig/TwigExtension.php

+ 5
- 1
Authenticator/LoginFormAuthenticator.php Bestand weergeven

@@ -13,6 +13,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
@@ -58,7 +59,10 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
return $this->userStore->getOneByEmail($userIdentifier);
}),
new PasswordCredentials($password),
[new CsrfTokenBadge('authenticate', $csrfToken)]
[
new CsrfTokenBadge('authenticate', $csrfToken),
new RememberMeBadge()
]
);
}


+ 3
- 0
Component/FileComponent.php Bestand weergeven

@@ -34,6 +34,9 @@ class FileComponent
$path = substr($path, 1);
}

// gestion des accents et des espaces
$path = urldecode($path);

if ($path) {

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

+ 1
- 0
Container/ComponentContainer.php Bestand weergeven

@@ -2,6 +2,7 @@

namespace Lc\SovBundle\Container;

use Lc\SovBundle\Component\ArrayComponent;
use Lc\SovBundle\Component\CitiesComponent;
use Lc\SovBundle\Component\CookieComponent;
use Lc\SovBundle\Component\DateComponent;

+ 7
- 0
Controller/ControllerTrait.php Bestand weergeven

@@ -33,6 +33,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;

@@ -274,4 +275,10 @@ trait ControllerTrait
return $this->get(SiteSettingContainer::class);
}

public function setNoMemoryAndTimeLimit(): void
{
ini_set('memory_limit', '-1');
set_time_limit(0);
}

}

+ 2
- 2
Definition/Field/Site/PageFieldDefinition.php Bestand weergeven

@@ -18,7 +18,7 @@ class PageFieldDefinition extends AbstractFieldDefinition
];
}

public function configurePanelMain(): array
public function configurePanelGeneral(): array
{
return [
'title',
@@ -29,7 +29,7 @@ class PageFieldDefinition extends AbstractFieldDefinition

public function configurePanels(): array
{
return ['main', 'seo', 'conf'];
return ['general', 'seo', 'conf'];
}

public function configureFields(): array

+ 0
- 1
Form/Common/FileManagerType.php Bestand weergeven

@@ -22,7 +22,6 @@ class FileManagerType extends AbstractType implements DataTransformerInterface
$this->em = $entityManager;
}


public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('path', HiddenType::class, array(

+ 258
- 0
Form/Common/FileUploadType.php Bestand weergeven

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

namespace Lc\SovBundle\Form\Common;

use EasyCorp\Bundle\EasyAdminBundle\Form\DataTransformer\StringToFileTransformer;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\Model\FileUploadState;
use Lc\SovBundle\Model\File\FileInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\File\File;
use Lc\SovBundle\Doctrine\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\String\Slugger\AsciiSlugger;
use Symfony\Component\Uid\Ulid;
use Symfony\Component\Uid\Uuid;

class FileUploadType extends AbstractType implements DataMapperInterface, DataTransformerInterface
{
protected string $projectDir;
protected EntityManager $entityManager;

public function __construct(EntityManager $entityManager, ParameterBagInterface $parameterBag)
{
$this->projectDir = $parameterBag->get('kernel.project_dir');
$this->entityManager = $entityManager;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
$uploadDir = $options['upload_dir'];
$uploadFilename = $options['upload_filename'];
$uploadValidate = $options['upload_validate'];
$allowAdd = $options['allow_add'];
unset($options['upload_dir'], $options['upload_new'], $options['upload_delete'], $options['upload_filename'], $options['upload_validate'], $options['download_path'], $options['allow_add'], $options['allow_delete'], $options['compound']);

$builder->add('path', FileType::class, $options);
$builder->add('legend', TextType::class, array(
'attr' => [
"placeholder" => 'Légende'
],
'label' => false
));
$builder->add('delete', CheckboxType::class, ['required' => false, 'mapped' => false]);

$builder->setDataMapper($this);
$builder->setAttribute('state', new FileUploadState($allowAdd));
$builder->addModelTransformer(new StringToFileTransformer($uploadDir, $uploadFilename, $uploadValidate, $options['multiple']));

/*
$builder->add('path', FileType::class, array(
'block_prefix' => 'file_manager_image',
'label' => false
));

$builder->add('legend', TextType::class, array(
'block_prefix' => 'file_upload_legend',
'attr' => array(
"placeholder" => 'Légende'
),
'label' => false
));

$builder->add('position', HiddenType::class, array(
'block_prefix' => 'file_upload_position',
'empty_data' => 0,
'required' => true,
'attr' => array(
'class' => 'field-position'
),
'label' => false
));
*/
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$uploadNew = static function (UploadedFile $file, string $uploadDir, string $fileName) {
$file->move($uploadDir, $fileName);
};

$uploadDelete = static function (File $file) {
unlink($file->getPathname());
};

$uploadFilename = static function (UploadedFile $file): string {
return $file->getClientOriginalName();
};

$uploadValidate = static function (string $filename): string {
if (!file_exists($filename)) {
return $filename;
}

$index = 1;
$pathInfo = pathinfo($filename);
while (file_exists($filename = sprintf('%s/%s_%d.%s', $pathInfo['dirname'], $pathInfo['filename'], $index, $pathInfo['extension']))) {
++$index;
}

return $filename;
};

$downloadPath = function (Options $options) {
return mb_substr($options['upload_dir'], mb_strlen($this->projectDir.'/public/'));
};

$allowAdd = static function (Options $options) {
return $options['multiple'];
};

$dataClass = static function (Options $options) {
return $options['multiple'] ? null : File::class;
};

$emptyData = static function (Options $options) {
return $options['multiple'] ? [] : null;
};

$resolver->setDefaults([
'upload_dir' => $this->projectDir.'/public/uploads/files/',
'upload_new' => $uploadNew,
'upload_delete' => $uploadDelete,
'upload_filename' => $uploadFilename,
'upload_validate' => $uploadValidate,
'download_path' => $downloadPath,
'allow_add' => $allowAdd,
'allow_delete' => true,
//'data_class' => $dataClass,
'data_class' => $this->entityManager->getEntityName(FileInterface::class),
'empty_data' => $emptyData,
'multiple' => false,
'required' => false,
'error_bubbling' => false,
'allow_file_upload' => true,
]);

$resolver->setAllowedTypes('upload_dir', 'string');
$resolver->setAllowedTypes('upload_new', 'callable');
$resolver->setAllowedTypes('upload_delete', 'callable');
$resolver->setAllowedTypes('upload_filename', ['string', 'callable']);
$resolver->setAllowedTypes('upload_validate', 'callable');
$resolver->setAllowedTypes('download_path', ['null', 'string']);
$resolver->setAllowedTypes('allow_add', 'bool');
$resolver->setAllowedTypes('allow_delete', 'bool');

$resolver->setNormalizer('upload_dir', function (Options $options, string $value): string {
if (\DIRECTORY_SEPARATOR !== mb_substr($value, -1)) {
$value .= \DIRECTORY_SEPARATOR;
}

if (0 !== mb_strpos($value, $this->projectDir)) {
$value = $this->projectDir.'/'.$value;
}

if ('' !== $value && (!is_dir($value) || !is_writable($value))) {
throw new InvalidArgumentException(sprintf('Invalid upload directory "%s" it does not exist or is not writable.', $value));
}

return $value;
});
$resolver->setNormalizer('upload_filename', static function (Options $options, $fileNamePatternOrCallable) {
if (\is_callable($fileNamePatternOrCallable)) {
return $fileNamePatternOrCallable;
}

return static function (UploadedFile $file) use ($fileNamePatternOrCallable) {
return strtr($fileNamePatternOrCallable, [
'[contenthash]' => sha1_file($file->getRealPath()),
'[day]' => date('d'),
'[extension]' => $file->guessClientExtension(),
'[month]' => date('m'),
'[name]' => pathinfo($file->getClientOriginalName(), \PATHINFO_FILENAME),
'[randomhash]' => bin2hex(random_bytes(20)),
'[slug]' => (new AsciiSlugger())
->slug(pathinfo($file->getClientOriginalName(), \PATHINFO_FILENAME))
->lower()
->toString(),
'[timestamp]' => time(),
'[uuid]' => Uuid::v4()->toRfc4122(),
'[ulid]' => new Ulid(),
'[year]' => date('Y'),
]);
};
});
$resolver->setNormalizer('allow_add', static function (Options $options, string $value): bool {
if ($value && !$options['multiple']) {
throw new InvalidArgumentException('Setting "allow_add" option to "true" when "multiple" option is "false" is not supported.');
}

return $value;
});
}

/**
* {@inheritdoc}
*/
public function mapDataToForms($currentFiles, $forms): void
{
/** @var FormInterface $fileForm */
$fileForm = current(iterator_to_array($forms));
$fileForm->setData($currentFiles);
}

/**
* {@inheritdoc}
*/
public function mapFormsToData($forms, &$currentFiles): void
{
/** @var FormInterface[] $children */
$children = iterator_to_array($forms);
$uploadedFiles = $children['path']->getData();

/** @var FileUploadState $state */
$state = $children['path']->getParent()->getConfig()->getAttribute('state');
$state->setCurrentFiles($currentFiles);
$state->setUploadedFiles($uploadedFiles);
$state->setDelete($children['delete']->getData());

if (!$state->isModified()) {
return;
}

if ($state->isAddAllowed() && !$state->isDelete()) {
$currentFiles = array_merge($currentFiles, $uploadedFiles);
} else {
$currentFiles = $uploadedFiles;
}
}

/**
* {@inheritdoc}
*/
public function transform($data)
{
return $data;
}

/**
* {@inheritdoc}
*/
public function reverseTransform($data)
{
return null === $data ? '' : $data;
}
}

+ 14
- 0
Repository/AbstractRepositoryQuery.php Bestand weergeven

@@ -222,5 +222,19 @@ abstract class AbstractRepositoryQuery implements RepositoryQueryInterface
{
return $this->andWhere('.status >= 0');
}

/*
* POSITION
*/

public function filterByPositionBiggerThan(int $position)
{
return $this->andWhere('.position > :position')->setParameter('position', $position);
}

public function filterByPositionSmallerThan(int $position)
{
return $this->andWhere('.position < :position')->setParameter('position', $position);
}
}


+ 1
- 2
Repository/User/GroupUserRepositoryQuery.php Bestand weergeven

@@ -16,11 +16,10 @@ class GroupUserRepositoryQuery extends AbstractRepositoryQuery implements GroupU

public function joinUsers(): self
{

if (!$this->isJoinUsers) {
$this->isJoinUsers = true;
return $this
->innerJoin('.users', 'users');
->leftJoin('.users', 'users');
}
return $this;
}

+ 45
- 1
Resolver/UrlResolver.php Bestand weergeven

@@ -8,14 +8,17 @@ namespace Lc\SovBundle\Resolver;


use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\RequestStack;

class UrlResolver
{
protected ParameterBagInterface $parameterBag;
protected RequestStack $requestStack;

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

public function isServerLocalhost(): bool
@@ -35,4 +38,45 @@ class UrlResolver
}
}

public function isRouteAdmin(): bool
{
return $this->testRoute(['admin_', 'file_manager']);
}

public function isRouteLogin(): bool
{
return $this->testRoute(['sov_login', 'sov_logout', 'frontend_security_login']) ;
}

public function testRoute($mixed, $route = null): bool
{
if(is_null($route)) {
$route = $this->getRouteCurrentRequest();
}

if(!$route) {
return false;
}

if(is_array($mixed)) {
foreach($mixed as $testRoute) {
if($this->testRoute($testRoute, $route)) {
return true;
}
}

return false;
}

return strpos($route, $mixed) !== false;
}

public function getRouteCurrentRequest(): ?string
{
$requestAttributes = $this->requestStack->getCurrentRequest()->attributes->all();
$route = isset($requestAttributes['_route']) ? $requestAttributes['_route'] : null;

return $route;
}

}

+ 3
- 2
Resources/assets/app/adminlte/main/init.js Bestand weergeven

@@ -1,8 +1,9 @@
window.addEventListener('load', (event) => {

$(document).on('select2:open', () => {
// @TODO : cela met le focus sur le premier select2 du document
/*$(document).on('select2:open', () => {
document.querySelector('.select2-search__field').focus();
});
});*/

SovNotification.init();


+ 7
- 3
Resources/assets/functions/widgets.js Bestand weergeven

@@ -18,9 +18,13 @@ export class SovWidgets {
if ($select.data('width')) {
options.width = 'auto'
}
if ($select.find('option[value=""]')) {

// @TODO : génère une erreur
/*if ($select.find('option[value=""]')) {
options.placeholder = $select.find('option[value=""]').html()
}
}*/

options.placeholder = "";

var myselect = $select.select2(options);

@@ -28,11 +32,11 @@ export class SovWidgets {
var event = new Event('change');
e.target.dispatchEvent(event);
});

myselect.on('select2:unselect', function (e) {
var event = new Event('change');
e.target.dispatchEvent(event);
});
SovTools.log(myselect);

myselect.off('select2:open')


+ 1
- 0
Resources/config/services.yaml Bestand weergeven

@@ -1,5 +1,6 @@
parameters:
app.admin.logo: 'laclic.png'
app.admin.logo_sidebar: 'laclic.png'
app.site_name: 'laclic-sov'
app.mail_debug: ''


+ 1
- 0
Resources/translations/admin.fr.yaml Bestand weergeven

@@ -155,6 +155,7 @@ entity:
panels:
general: Général
configuration: Configuration
conf: Configuration
gallery: Galerie
seo: Référencement
opengraph: Opengraph

+ 0
- 1
Resources/views/adminlte/crud/form_theme.html.twig Bestand weergeven

@@ -195,7 +195,6 @@
{{ form_widget(form) }}
{% endblock file_manager_position_row %}


{% block file_manager_widget %}
{% if form.vars.ea_crud_form.ea_field is not null %}
{% set managerDir = form.vars.ea_crud_form.ea_field.customOptions.get('managerDir') %}

+ 16
- 1
Twig/TwigExtension.php Bestand weergeven

@@ -99,6 +99,7 @@ class TwigExtension extends AbstractExtension
new TwigFunction('ea_url_short', [$this, 'generateEaUrl']),
new TwigFunction('is_instance_of', [$this, 'isInstanceOf']),
new TwigFunction('logo_admin', [$this, 'getLogoAdmin']),
new TwigFunction('asset_url', [$this, 'getAssetUrl']),
];
}

@@ -119,6 +120,15 @@ class TwigExtension extends AbstractExtension
];
}

public function getAssetUrl($path)
{
$context = $this->router->getContext();
$host = $context->getScheme().'://'.$context->getHost().'/';

return $host.$path;
}


public function rot13(string $string): string
{
return str_rot13($string);
@@ -240,6 +250,11 @@ class TwigExtension extends AbstractExtension

public function getLogoAdmin(): string
{
return '<img class="logo-admin" src="assets/img/' . $this->getParameter('app.admin.logo') . '" >';
$image = $this->getParameter('app.admin.logo_sidebar');
if(!$image) {
$image = $this->getParameter('app.admin.logo');
}

return '<img class="logo-admin" src="assets/img/' . $image . '" >';
}
}

Laden…
Annuleren
Opslaan