-
-
Notifications
You must be signed in to change notification settings - Fork 398
[LiveComponent] Adds MultiStep Form Feature #2433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
0d280f9
20ef568
6fb25c2
59f13dc
c886e65
06df934
3c43ca5
a3a3514
d2e0660
b2ea6ed
a67443f
4c6a065
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,283 @@ | ||||||||||||||
| <?php | ||||||||||||||
|
|
||||||||||||||
| declare(strict_types=1); | ||||||||||||||
|
|
||||||||||||||
| /* | ||||||||||||||
| * This file is part of the Symfony package. | ||||||||||||||
| * | ||||||||||||||
| * (c) Fabien Potencier <[email protected]> | ||||||||||||||
| * | ||||||||||||||
| * For the full copyright and license information, please view the LICENSE | ||||||||||||||
| * file that was distributed with this source code. | ||||||||||||||
| */ | ||||||||||||||
|
|
||||||||||||||
| namespace Symfony\UX\LiveComponent; | ||||||||||||||
|
|
||||||||||||||
| use Symfony\Component\Form\FormFactoryInterface; | ||||||||||||||
| use Symfony\Component\Form\FormInterface; | ||||||||||||||
| use Symfony\UX\LiveComponent\Attribute\LiveAction; | ||||||||||||||
| use Symfony\UX\LiveComponent\Attribute\LiveProp; | ||||||||||||||
| use Symfony\UX\LiveComponent\Storage\StorageInterface; | ||||||||||||||
| use Symfony\UX\TwigComponent\Attribute\ExposeInTemplate; | ||||||||||||||
| use Symfony\UX\TwigComponent\Attribute\PostMount; | ||||||||||||||
|
|
||||||||||||||
| use function Symfony\Component\String\u; | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @author Silas Joisten <[email protected]> | ||||||||||||||
| * @author Patrick Reimers <[email protected]> | ||||||||||||||
| * @author Jules Pietri <[email protected]> | ||||||||||||||
| */ | ||||||||||||||
| trait ComponentWithMultiStepFormTrait | ||||||||||||||
silasjoisten marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
| { | ||||||||||||||
| use ComponentWithFormTrait; | ||||||||||||||
| use DefaultActionTrait; | ||||||||||||||
|
|
||||||||||||||
| #[LiveProp] | ||||||||||||||
| public ?string $currentStepName = null; | ||||||||||||||
|
Comment on lines
+40
to
+41
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we make this non nullable? I don't see when a multi-step could have "no current step"
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are in a trait and we dont have a constructor or something here. which means it depends on the #[PostMount] hook. if thats not executed it is null by default. i think thats something by design we should not change. |
||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @var string[] | ||||||||||||||
| */ | ||||||||||||||
| #[LiveProp] | ||||||||||||||
| public array $stepNames = []; | ||||||||||||||
|
|
||||||||||||||
| public function hasValidationErrors(): bool | ||||||||||||||
| { | ||||||||||||||
| return $this->form->isSubmitted() && !$this->form->isValid(); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @internal | ||||||||||||||
| * | ||||||||||||||
| * Must be executed after ComponentWithFormTrait::initializeForm() | ||||||||||||||
| */ | ||||||||||||||
| #[PostMount(priority: -250)] | ||||||||||||||
| public function initialize(): void | ||||||||||||||
| { | ||||||||||||||
| $this->currentStepName = $this->getStorage()->get( | ||||||||||||||
| \sprintf('%s_current_step_name', self::prefix()), | ||||||||||||||
| $this->formView->vars['current_step_name'], | ||||||||||||||
| ); | ||||||||||||||
|
|
||||||||||||||
| $this->form = $this->instantiateForm(); | ||||||||||||||
|
|
||||||||||||||
| $formData = $this->getStorage()->get(\sprintf( | ||||||||||||||
| '%s_form_values_%s', | ||||||||||||||
| self::prefix(), | ||||||||||||||
| $this->currentStepName, | ||||||||||||||
| )); | ||||||||||||||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
|
|
||||||||||||||
| $this->form->setData($formData); | ||||||||||||||
|
|
||||||||||||||
| if ([] === $formData) { | ||||||||||||||
| $this->formValues = $this->extractFormValues($this->getFormView()); | ||||||||||||||
| } else { | ||||||||||||||
| $this->formValues = $formData; | ||||||||||||||
| } | ||||||||||||||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
|
|
||||||||||||||
| $this->stepNames = $this->formView->vars['steps_names']; | ||||||||||||||
|
|
||||||||||||||
| // Do not move this. The order is important. | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? 😅
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good question :D i cann add a better comment |
||||||||||||||
| $this->formView = null; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #[LiveAction] | ||||||||||||||
| public function next(): void | ||||||||||||||
| { | ||||||||||||||
| $this->submitForm(); | ||||||||||||||
|
|
||||||||||||||
| if ($this->hasValidationErrors()) { | ||||||||||||||
| return; | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+94
to
+98
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure to be honest. i can test it. |
||||||||||||||
|
|
||||||||||||||
| $this->getStorage()->persist( | ||||||||||||||
| \sprintf('%s_form_values_%s', self::prefix(), $this->currentStepName), | ||||||||||||||
| $this->form->getData(), | ||||||||||||||
| ); | ||||||||||||||
|
|
||||||||||||||
| $found = false; | ||||||||||||||
| $next = null; | ||||||||||||||
|
|
||||||||||||||
| foreach ($this->stepNames as $stepName) { | ||||||||||||||
| if ($this->currentStepName === $stepName) { | ||||||||||||||
| $found = true; | ||||||||||||||
|
|
||||||||||||||
| continue; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if ($found) { | ||||||||||||||
| $next = $stepName; | ||||||||||||||
|
|
||||||||||||||
| break; | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if (null === $next) { | ||||||||||||||
| throw new \RuntimeException('No next forms available.'); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| $this->currentStepName = $next; | ||||||||||||||
| $this->getStorage()->persist(\sprintf('%s_current_step_name', self::prefix()), $this->currentStepName); | ||||||||||||||
|
|
||||||||||||||
| // If we have a next step, we need to resinstantiate the form and reset the form view and values. | ||||||||||||||
| $this->form = $this->instantiateForm(); | ||||||||||||||
| $this->formView = null; | ||||||||||||||
|
|
||||||||||||||
| $formData = $this->getStorage()->get(\sprintf( | ||||||||||||||
| '%s_form_values_%s', | ||||||||||||||
| self::prefix(), | ||||||||||||||
| $this->currentStepName, | ||||||||||||||
| )); | ||||||||||||||
|
|
||||||||||||||
| // I really don't understand why we need to do that. But what I understood is extractFormValues creates | ||||||||||||||
| // an array of initial values. | ||||||||||||||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
| if ([] === $formData) { | ||||||||||||||
| $this->formValues = $this->extractFormValues($this->getFormView()); | ||||||||||||||
| } else { | ||||||||||||||
| $this->formValues = $formData; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| $this->form->setData($formData); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #[LiveAction] | ||||||||||||||
| public function previous(): void | ||||||||||||||
| { | ||||||||||||||
| $found = false; | ||||||||||||||
| $previous = null; | ||||||||||||||
|
|
||||||||||||||
| foreach (array_reverse($this->stepNames) as $stepName) { | ||||||||||||||
| if ($this->currentStepName === $stepName) { | ||||||||||||||
| $found = true; | ||||||||||||||
|
|
||||||||||||||
| continue; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if ($found) { | ||||||||||||||
| $previous = $stepName; | ||||||||||||||
|
|
||||||||||||||
| break; | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if (null === $previous) { | ||||||||||||||
| throw new \RuntimeException('No previous forms available.'); | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+148
to
+167
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. $current = array_search($currentStep, $steps, true);
if (!$current) {
throw new \RuntimeException('No previous steps available.');
}
$previous = $steps[$current - 1];(or similar)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with you example the exception is thrown if no current step is available. |
||||||||||||||
|
|
||||||||||||||
| $this->currentStepName = $previous; | ||||||||||||||
| $this->getStorage()->persist(\sprintf('%s_current_step_name', self::prefix()), $this->currentStepName); | ||||||||||||||
|
|
||||||||||||||
| $this->form = $this->instantiateForm(); | ||||||||||||||
| $this->formView = null; | ||||||||||||||
|
|
||||||||||||||
| $formData = $this->getStorage()->get(\sprintf( | ||||||||||||||
| '%s_form_values_%s', | ||||||||||||||
| self::prefix(), | ||||||||||||||
| $this->currentStepName, | ||||||||||||||
| )); | ||||||||||||||
|
|
||||||||||||||
| $this->formValues = $formData; | ||||||||||||||
| $this->form->setData($formData); | ||||||||||||||
|
Comment on lines
+170
to
+182
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate with "next" method... should this be the main "getCurrentForm" or "getStepForm" method or something like that ? |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #[ExposeInTemplate] | ||||||||||||||
| public function isFirst(): bool | ||||||||||||||
| { | ||||||||||||||
| return $this->currentStepName === $this->stepNames[array_key_first($this->stepNames)]; | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
wdyt ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reset can return false which makes it not typesafe enough for me.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then currentStep === .. would return false no ? |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #[ExposeInTemplate] | ||||||||||||||
| public function isLast(): bool | ||||||||||||||
| { | ||||||||||||||
| return $this->currentStepName === $this->stepNames[array_key_last($this->stepNames)]; | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would like to use the new php functions array_key_first and array_key_last.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. haha the "new" :) The "problem" (a detail, to be honest) here is that you first look for a key, then get the value indexed by that key, then compare currentStepName is identical. But we can update this in time if necessary :) |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #[LiveAction] | ||||||||||||||
| public function submit(): void | ||||||||||||||
| { | ||||||||||||||
| $this->submitForm(); | ||||||||||||||
|
|
||||||||||||||
| if ($this->hasValidationErrors()) { | ||||||||||||||
| return; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| $this->getStorage()->persist( | ||||||||||||||
| \sprintf('%s_form_values_%s', self::prefix(), $this->currentStepName), | ||||||||||||||
| $this->form->getData(), | ||||||||||||||
| ); | ||||||||||||||
|
|
||||||||||||||
| $this->onSubmit(); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| abstract public function onSubmit(); | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @return array<string, mixed> | ||||||||||||||
| */ | ||||||||||||||
| public function getAllData(): array | ||||||||||||||
| { | ||||||||||||||
| $data = []; | ||||||||||||||
|
|
||||||||||||||
| foreach ($this->stepNames as $stepName) { | ||||||||||||||
| $data[$stepName] = $this->getStorage()->get(\sprintf( | ||||||||||||||
| '%s_form_values_%s', | ||||||||||||||
| self::prefix(), | ||||||||||||||
| $stepName, | ||||||||||||||
| )); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| return $data; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public function resetForm(): void | ||||||||||||||
| { | ||||||||||||||
| foreach ($this->stepNames as $stepName) { | ||||||||||||||
| $this->getStorage()->remove(\sprintf('%s_form_values_%s', self::prefix(), $stepName)); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| $this->getStorage()->remove(\sprintf('%s_current_step_name', self::prefix())); | ||||||||||||||
|
|
||||||||||||||
| $this->currentStepName = $this->stepNames[array_key_first($this->stepNames)]; | ||||||||||||||
| $this->form = $this->instantiateForm(); | ||||||||||||||
| $this->formView = null; | ||||||||||||||
| $this->formValues = $this->extractFormValues($this->getFormView()); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| abstract protected function getStorage(): StorageInterface; | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @return class-string<FormInterface> | ||||||||||||||
| */ | ||||||||||||||
| abstract protected static function formClass(): string; | ||||||||||||||
|
|
||||||||||||||
| abstract protected function getFormFactory(): FormFactoryInterface; | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @internal | ||||||||||||||
| */ | ||||||||||||||
| protected function instantiateForm(): FormInterface | ||||||||||||||
| { | ||||||||||||||
| $options = []; | ||||||||||||||
|
|
||||||||||||||
| if (null !== $this->currentStepName) { | ||||||||||||||
| $options['current_step_name'] = $this->currentStepName; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| return $this->getFormFactory()->create( | ||||||||||||||
| type: static::formClass(), | ||||||||||||||
| options: $options, | ||||||||||||||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
| ); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * @internal | ||||||||||||||
| */ | ||||||||||||||
| private static function prefix(): string | ||||||||||||||
| { | ||||||||||||||
| return u(static::class) | ||||||||||||||
| ->afterLast('\\') | ||||||||||||||
| ->snake() | ||||||||||||||
| ->toString(); | ||||||||||||||
|
||||||||||||||
| return u(static::class) | |
| ->afterLast('\\') | |
| ->snake() | |
| ->toString(); | |
| return u(static::class)->afterLast('\\')->snake()->toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And is symfony/string still a requirement ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes i required it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the only place where it is needed? In this case it is preferred to not use a dep but use plain vanilla PHP for it
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,49 @@ | ||||||||||||||||||||||||
| <?php | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| declare(strict_types=1); | ||||||||||||||||||||||||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||
| * This file is part of the Symfony package. | ||||||||||||||||||||||||
| * | ||||||||||||||||||||||||
| * (c) Fabien Potencier <[email protected]> | ||||||||||||||||||||||||
| * | ||||||||||||||||||||||||
| * For the full copyright and license information, please view the LICENSE | ||||||||||||||||||||||||
| * file that was distributed with this source code. | ||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| namespace Symfony\UX\LiveComponent\Form\Type; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| use Symfony\Component\Form\AbstractType; | ||||||||||||||||||||||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||||||||||||||||||||||
| use Symfony\Component\Form\FormInterface; | ||||||||||||||||||||||||
| use Symfony\Component\Form\FormView; | ||||||||||||||||||||||||
| use Symfony\Component\OptionsResolver\Options; | ||||||||||||||||||||||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * @author Silas Joisten <[email protected]> | ||||||||||||||||||||||||
| * @author Patrick Reimers <[email protected]> | ||||||||||||||||||||||||
| * @author Jules Pietri <[email protected]> | ||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||
| final class MultiStepType extends AbstractType | ||||||||||||||||||||||||
silasjoisten marked this conversation as resolved.
Show resolved
Hide resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is where we should describe/document what is a "step". |
||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| public function configureOptions(OptionsResolver $resolver): void | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| $resolver | ||||||||||||||||||||||||
| ->setDefault('current_step_name', static function (Options $options): string { | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's discuss this more globally, but i think "current_step" or even "step" could be enough, and improve readability. Maybe just me, but i feel the implementation choice (e.g., passing the steps as a map) should not impose constraints on the overall naming convention. wdyt ? |
||||||||||||||||||||||||
| return array_key_first($options['steps']); | ||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||
| ->setRequired('steps'); | ||||||||||||||||||||||||
silasjoisten marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public function buildForm(FormBuilderInterface $builder, array $options): void | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| $options['steps'][$options['current_step_name']]($builder); | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be checked first i guess ? 😅
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont think so, because configure options is already ensuring that. (see the test)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may miss-read this, but to me at this point there is no certitude that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allowing to use Maybe with something like that (haven't tested it):
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes i was thinking about the same. so callback or class string of FormTypeInterface. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
IMO, passing
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure we can do that but my question is. Why would it make sense to pass the options of the "parent" form StepType to the children? you got an example or use case where it might be useful? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is more to be consistent with how work the In your PR, you cannot set your form options yet, so there is no direct example. You may want to create step form that is configurable, either from:
Is it clearer that way? |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public function buildView(FormView $view, FormInterface $form, array $options): void | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| $view->vars['current_step_name'] = $options['current_step_name']; | ||||||||||||||||||||||||
| $view->vars['steps_names'] = array_keys($options['steps']); | ||||||||||||||||||||||||
|
Comment on lines
+45
to
+46
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about "step" and "steps" (or "current_step" and "steps" ? To illustrate my point here: if you look at ChoiceType, it does not use "prefered_choices**_values**" or "prefered_choices**_names**"
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure we can rename this. |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
silasjoisten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /* | ||
| * This file is part of the Symfony package. | ||
| * | ||
| * (c) Fabien Potencier <[email protected]> | ||
| * | ||
| * For the full copyright and license information, please view the LICENSE | ||
| * file that was distributed with this source code. | ||
| */ | ||
|
|
||
| namespace Symfony\UX\LiveComponent\Storage; | ||
|
|
||
| use Symfony\Component\HttpFoundation\RequestStack; | ||
|
|
||
| /** | ||
| * @author Silas Joisten <[email protected]> | ||
| * @author Patrick Reimers <[email protected]> | ||
| * @author Jules Pietri <[email protected]> | ||
| */ | ||
| final class SessionStorage implements StorageInterface | ||
| { | ||
| public function __construct( | ||
| private readonly RequestStack $requestStack, | ||
| ) { | ||
| } | ||
|
|
||
| public function persist(string $key, mixed $values): void | ||
| { | ||
| $this->requestStack->getSession()->set($key, $values); | ||
| } | ||
|
|
||
| public function remove(string $key): void | ||
| { | ||
| $this->requestStack->getSession()->remove($key); | ||
| } | ||
|
|
||
| public function get(string $key, mixed $default = []): mixed | ||
| { | ||
| return $this->requestStack->getSession()->get($key, $default); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.