fix order and update of user settings form

This commit is contained in:
Kevin Papst
2020-08-18 23:22:16 +02:00
parent fbb3dd89cf
commit d8ae7635d1
7 changed files with 74 additions and 89 deletions

View File

@@ -21,7 +21,6 @@ use App\Form\UserTeamsType;
use App\Repository\TeamRepository; use App\Repository\TeamRepository;
use App\Repository\TimesheetRepository; use App\Repository\TimesheetRepository;
use App\Utils\LocaleSettings; use App\Utils\LocaleSettings;
use Doctrine\Common\Collections\ArrayCollection;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
@@ -212,13 +211,6 @@ class ProfileController extends AbstractController
$event = new PrepareUserEvent($profile); $event = new PrepareUserEvent($profile);
$this->dispatcher->dispatch($event); $this->dispatcher->dispatch($event);
/** @var \ArrayIterator $iterator */
$iterator = $profile->getPreferences()->getIterator();
$iterator->uasort(function (UserPreference $a, UserPreference $b) {
return ($a->getOrder() < $b->getOrder()) ? -1 : 1;
});
$profile->setPreferences(new ArrayCollection(iterator_to_array($iterator)));
$original = []; $original = [];
foreach ($profile->getPreferences() as $preference) { foreach ($profile->getPreferences() as $preference) {
$original[$preference->getName()] = $preference; $original[$preference->getName()] = $preference;
@@ -227,7 +219,8 @@ class ProfileController extends AbstractController
$form = $this->createPreferencesForm($profile); $form = $this->createPreferencesForm($profile);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted()) {
if ($form->isValid()) {
$entityManager = $this->getDoctrine()->getManager(); $entityManager = $this->getDoctrine()->getManager();
$preferences = $profile->getPreferences(); $preferences = $profile->getPreferences();
@@ -261,14 +254,24 @@ class ProfileController extends AbstractController
'_locale' => $locale, '_locale' => $locale,
'username' => $profile->getUsername() 'username' => $profile->getUsername()
]); ]);
} else {
$this->flashError('action.update.error', ['%reason%' => 'Validation failed']);
}
} }
// prepare ordered preferences
$sections = []; $sections = [];
/** @var \ArrayIterator $iterator */
$iterator = $profile->getPreferences()->getIterator();
$iterator->uasort(function (UserPreference $a, UserPreference $b) {
return ($a->getOrder() < $b->getOrder()) ? -1 : 1;
});
/** @var UserPreference $pref */ /** @var UserPreference $pref */
foreach ($profile->getPreferences() as $pref) { foreach ($iterator as $pref) {
if ($pref->isEnabled()) { if ($pref->isEnabled()) {
$sections[$pref->getSection()] = $pref->getSection(); $sections[$pref->getSection()][] = $pref->getName();
} }
} }

View File

@@ -336,7 +336,7 @@ class User extends BaseUser implements UserInterface
} }
foreach ($this->preferences as $preference) { foreach ($this->preferences as $preference) {
if ($preference->getName() == $name) { if ($preference->getName() === $name) {
return $preference; return $preference;
} }
} }

View File

@@ -14,7 +14,7 @@ use App\Entity\UserPreference;
use Symfony\Contracts\EventDispatcher\Event; use Symfony\Contracts\EventDispatcher\Event;
/** /**
* This event should be used, if further user preferences should added dynamically * This event should be used, if further user preferences should be added dynamically.
*/ */
final class UserPreferenceEvent extends Event final class UserPreferenceEvent extends Event
{ {
@@ -26,11 +26,11 @@ final class UserPreferenceEvent extends Event
/** /**
* @var User * @var User
*/ */
protected $user; private $user;
/** /**
* @var UserPreference[] * @var UserPreference[]
*/ */
protected $preferences; private $preferences = [];
/** /**
* @param User $user * @param User $user
@@ -44,9 +44,10 @@ final class UserPreferenceEvent extends Event
/** /**
* Do not set the preferences directly to the user object, but ONLY via addPreference() * Do not set the preferences directly to the user object, but ONLY via addPreference()
*
* @return User * @return User
*/ */
public function getUser() public function getUser(): User
{ {
return $this->user; return $this->user;
} }
@@ -54,7 +55,7 @@ final class UserPreferenceEvent extends Event
/** /**
* @return UserPreference[] * @return UserPreference[]
*/ */
public function getPreferences() public function getPreferences(): array
{ {
return $this->preferences; return $this->preferences;
} }

View File

@@ -17,31 +17,23 @@ use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserProfileSubscriber implements EventSubscriberInterface final class UserProfileSubscriber implements EventSubscriberInterface
{ {
/** /**
* @var EventDispatcherInterface * @var EventDispatcherInterface
*/ */
protected $eventDispatcher; private $eventDispatcher;
/** /**
* @var TokenStorageInterface * @var TokenStorageInterface
*/ */
protected $storage; private $storage;
/**
* @param EventDispatcherInterface $dispatcher
* @param TokenStorageInterface $storage
*/
public function __construct(EventDispatcherInterface $dispatcher, TokenStorageInterface $storage) public function __construct(EventDispatcherInterface $dispatcher, TokenStorageInterface $storage)
{ {
$this->eventDispatcher = $dispatcher; $this->eventDispatcher = $dispatcher;
$this->storage = $storage; $this->storage = $storage;
} }
/**
* @return array
*/
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array
{ {
return [ return [
@@ -49,10 +41,7 @@ class UserProfileSubscriber implements EventSubscriberInterface
]; ];
} }
/** public function prepareUserProfile(KernelEvent $event): void
* @param KernelEvent $event
*/
public function prepareUserProfile(KernelEvent $event)
{ {
if (!$this->canHandleEvent($event)) { if (!$this->canHandleEvent($event)) {
return; return;
@@ -65,11 +54,7 @@ class UserProfileSubscriber implements EventSubscriberInterface
$this->eventDispatcher->dispatch($event); $this->eventDispatcher->dispatch($event);
} }
/** private function canHandleEvent(KernelEvent $event): bool
* @param KernelEvent $event
* @return bool
*/
protected function canHandleEvent(KernelEvent $event): bool
{ {
// Ignore sub-requests // Ignore sub-requests
if (!$event->isMasterRequest()) { if (!$event->isMasterRequest()) {

View File

@@ -34,10 +34,6 @@ class UserPreferenceType extends AbstractType
$this->translate = $translator; $this->translate = $translator;
} }
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder->addEventListener( $builder->addEventListener(
@@ -56,7 +52,7 @@ class UserPreferenceType extends AbstractType
} }
$required = true; $required = true;
if (CheckboxType::class == $preference->getType()) { if (CheckboxType::class === $preference->getType()) {
$required = false; $required = false;
} }

View File

@@ -2,11 +2,11 @@
{% block main %} {% block main %}
{{ form_start(form) }} {{ form_start(form) }}
{% for section, counter in sections %} {% for section, entries in sections %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %} {% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% block box_body %} {% block box_body %}
{% for pref in form.children.preferences %} {% for pref in form.children.preferences %}
{% if pref.vars.data.section == section %} {% if pref.vars.data.name in entries %}
{{ form_row(pref) }} {{ form_row(pref) }}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View File

@@ -410,10 +410,14 @@ class ProfileControllerTest extends ControllerBaseTest
return [ return [
// assert that the user doesn't have the "hourly-rate_own_profile" permission // assert that the user doesn't have the "hourly-rate_own_profile" permission
[User::ROLE_USER, UserFixtures::USERNAME_USER, 82, 82, 'ar', null], [User::ROLE_USER, UserFixtures::USERNAME_USER, 82, 82, 'ar', null],
// admins are allowed to update their own hourly rate // teamleads are allowed to update their own hourly rate, but not other peoples hourly rate
[User::ROLE_TEAMLEAD, UserFixtures::USERNAME_TEAMLEAD, 35, 37.5, 'ar', 19.54],
// admins are allowed to update their own hourly rate, but not other peoples hourly rate
[User::ROLE_ADMIN, UserFixtures::USERNAME_ADMIN, 81, 37.5, 'ar', 19.54], [User::ROLE_ADMIN, UserFixtures::USERNAME_ADMIN, 81, 37.5, 'ar', 19.54],
// admins are allowed to update other peoples hourly rate // super-admins are allowed to update other peoples hourly rate
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_USER, 82, 37.5, 'en', 19.54], [User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_ADMIN, 81, 37.5, 'en', 19.54],
// super-admins are allowed to update their own hourly rate
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_SUPER_ADMIN, 46, 37.5, 'ar', 19.54],
]; ];
} }
@@ -431,21 +435,16 @@ class ProfileControllerTest extends ControllerBaseTest
$this->assertEquals($hourlyRateOriginal, $user->getPreferenceValue(UserPreference::HOURLY_RATE)); $this->assertEquals($hourlyRateOriginal, $user->getPreferenceValue(UserPreference::HOURLY_RATE));
$this->assertNull($user->getPreferenceValue(UserPreference::INTERNAL_RATE)); $this->assertNull($user->getPreferenceValue(UserPreference::INTERNAL_RATE));
$this->assertNull($user->getPreferenceValue(UserPreference::SKIN)); $this->assertNull($user->getPreferenceValue(UserPreference::SKIN));
$this->assertEquals(false, $user->getPreferenceValue('theme.collapsed_sidebar'));
$this->assertEquals('month', $user->getPreferenceValue('calendar.initial_view'));
$form = $client->getCrawler()->filter('form[name=user_preferences_form]')->form(); $form = $client->getCrawler()->filter('form[name=user_preferences_form]')->form();
$client->submit($form, [ $client->submit($form, [
'user_preferences_form' => [ 'user_preferences_form' => [
'preferences' => [ 'preferences' => [
['name' => UserPreference::HOURLY_RATE, 'value' => 37.5], 0 => ['name' => UserPreference::HOURLY_RATE, 'value' => 37.5],
['name' => UserPreference::INTERNAL_RATE, 'value' => 19.54], 1 => ['name' => UserPreference::INTERNAL_RATE, 'value' => 19.54],
['name' => 'timezone', 'value' => 'America/Creston'], 2 => ['name' => UserPreference::TIMEZONE, 'value' => 'America/Creston'],
['name' => 'language', 'value' => 'ar'], 3 => ['name' => UserPreference::LOCALE, 'value' => 'ar'],
['name' => UserPreference::SKIN, 'value' => 'blue'], 4 => ['name' => UserPreference::SKIN, 'value' => 'blue'],
['name' => 'theme.layout', 'value' => 'fixed'],
['name' => 'theme.collapsed_sidebar', 'value' => true],
['name' => 'calendar.initial_view', 'value' => 'agendaDay'],
] ]
] ]
]); ]);
@@ -462,10 +461,11 @@ class ProfileControllerTest extends ControllerBaseTest
$this->assertEquals($hourlyRate, $user->getPreferenceValue(UserPreference::HOURLY_RATE)); $this->assertEquals($hourlyRate, $user->getPreferenceValue(UserPreference::HOURLY_RATE));
$this->assertEquals($expectedInternalRate, $user->getPreferenceValue(UserPreference::INTERNAL_RATE)); $this->assertEquals($expectedInternalRate, $user->getPreferenceValue(UserPreference::INTERNAL_RATE));
$this->assertEquals('', $user->getPreferenceValue('America/Creston')); $this->assertEquals('America/Creston', $user->getPreferenceValue(UserPreference::TIMEZONE));
$this->assertEquals('ar', $user->getPreferenceValue('language')); $this->assertEquals('America/Creston', $user->getTimezone());
$this->assertEquals('ar', $user->getPreferenceValue(UserPreference::LOCALE));
$this->assertEquals('ar', $user->getLanguage());
$this->assertEquals('ar', $user->getLocale());
$this->assertEquals('blue', $user->getPreferenceValue(UserPreference::SKIN)); $this->assertEquals('blue', $user->getPreferenceValue(UserPreference::SKIN));
$this->assertEquals(true, $user->getPreferenceValue('theme.collapsed_sidebar'));
$this->assertEquals('agendaDay', $user->getPreferenceValue('calendar.initial_view'));
} }
} }