Skip to content

Commit

Permalink
v2.1.0
Browse files Browse the repository at this point in the history
Add ability to split different user sessions for one stepped form depending on initial data
  • Loading branch information
lexalium authored Dec 30, 2023
1 parent 6e0eb6c commit efdafee
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 20 deletions.
37 changes: 32 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,30 @@ composer require lexal/stepped-form
$dataControl = new DataControl(new DataStorage($storage));
```

4. Create an Event Dispatcher.
4. Create a Session storage to save current form session key and have ability to start one form with different user
initial entity. Use `NullSessionStorage` when there is no need to split form sessions or there is no dependency
on initial user input.
```php
use Lexal\SteppedForm\Form\Storage\SessionStorageInterface;

final class SessionStorage implements SessionStorageInterface
{
public function getCurrent(): ?string
{
// return current active session key (from redis, database, session or any other storage)
return 'main';
}

public function setCurrent(string $namespace): void
{
// set current form session key
}
}

$sessionStorage = new SessionStorage();
```

5. Create an Event Dispatcher.
```php
use Lexal\SteppedForm\EventDispatcher\EventDispatcherInterface;

Expand All @@ -103,7 +126,7 @@ composer require lexal/stepped-form
$dispatcher = new EventDispatcher();
```

5. Create a Stepped Form.
6. Create a Stepped Form.
```php
use Lexal\SteppedForm\EntityCopy\SimpleEntityCopy;
use Lexal\SteppedForm\SteppedForm;
Expand All @@ -115,13 +138,17 @@ composer require lexal/stepped-form
$builder,
$dispatcher,
new SimpleEntityCopy(),
$sessionStorage, // default value is `NullSessionStorage
);
```

6. Use Stepped Form in the application.
7. Use Stepped Form in the application.
```php
/* Starts a new form session */
$form->start(/* entity for initialize a form state */);
$form->start(
/* entity for initialize a form state */,
/* unique session key is you need to split different sessions of one form */,
);

/* Returns a TemplateDefinition of rendered step */
$form->render('key');
Expand Down Expand Up @@ -300,4 +327,4 @@ The form can dispatch the following exceptions:

## License

Stepped Form is licensed under the MIT License. See [LICENSE](LICENSE) for the full license text.
Stepped Form is licensed under the MIT License. See [LICENSE](LICENSE) for the full license text.
13 changes: 13 additions & 0 deletions src/Exception/ReadSessionKeyException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Lexal\SteppedForm\Exception;

final class ReadSessionKeyException extends SteppedFormException
{
public function __construct()
{
parent::__construct('Unable to get current form session key.');
}
}
34 changes: 30 additions & 4 deletions src/Form/Storage/ArrayStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,56 @@

namespace Lexal\SteppedForm\Form\Storage;

use Lexal\SteppedForm\Exception\ReadSessionKeyException;

final class ArrayStorage implements StorageInterface
{
/**
* @var array<string, mixed>
*/
private array $data = [];

public function __construct(private readonly SessionStorageInterface $sessionStorage)
{
}

/**
* @inheritDoc
*
* @throws ReadSessionKeyException
*/
public function has(string $key): bool
{
return isset($this->data[$key]);
return isset($this->data[$this->sessionStorage->getCurrent()][$key]);
}

/**
* @inheritDoc
*
* @throws ReadSessionKeyException
*/
public function get(string $key, mixed $default = null): mixed
{
return $this->data[$key] ?? $default;
return $this->data[$this->sessionStorage->getCurrent()][$key] ?? $default;
}

/**
* @inheritDoc
*
* @throws ReadSessionKeyException
*/
public function put(string $key, mixed $data): void
{
$this->data[$key] = $data;
$this->data[$this->sessionStorage->getCurrent()][$key] = $data;
}

/**
* @inheritDoc
*
* @throws ReadSessionKeyException
*/
public function clear(): void
{
$this->data = [];
unset($this->data[$this->sessionStorage->getCurrent()]);
}
}
20 changes: 20 additions & 0 deletions src/Form/Storage/NullSessionStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Lexal\SteppedForm\Form\Storage;

use Lexal\SteppedForm\SteppedFormInterface;

final class NullSessionStorage implements SessionStorageInterface
{
public function getCurrent(): ?string
{
return SteppedFormInterface::DEFAULT_SESSION_KEY;
}

public function setCurrent(string $sessionKey): void
{
// nothing to save
}
}
23 changes: 23 additions & 0 deletions src/Form/Storage/SessionStorageInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Lexal\SteppedForm\Form\Storage;

use Lexal\SteppedForm\Exception\ReadSessionKeyException;

interface SessionStorageInterface
{
/**
* Returns current session key. Throws an exception when cannot read session key from the storage.
* Returns null if there is no started form.
*
* @throws ReadSessionKeyException
*/
public function getCurrent(): ?string;

/**
* Save current session key to the storage.
*/
public function setCurrent(string $sessionKey): void;
}
7 changes: 6 additions & 1 deletion src/SteppedForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Lexal\SteppedForm\Form\Builder\FormBuilderInterface;
use Lexal\SteppedForm\Form\DataControlInterface;
use Lexal\SteppedForm\Form\StepControlInterface;
use Lexal\SteppedForm\Form\Storage\NullSessionStorage;
use Lexal\SteppedForm\Form\Storage\SessionStorageInterface;
use Lexal\SteppedForm\Form\Storage\StorageInterface;
use Lexal\SteppedForm\Step\RenderStepInterface;
use Lexal\SteppedForm\Step\Step;
Expand All @@ -36,6 +38,7 @@ public function __construct(
private readonly FormBuilderInterface $builder,
private readonly EventDispatcherInterface $dispatcher,
private readonly EntityCopyInterface $entityCopy,
private readonly SessionStorageInterface $sessionStorage = new NullSessionStorage(),
) {
$this->steps = new Steps();
}
Expand All @@ -54,8 +57,10 @@ public function getEntity(): mixed
* @throws EntityNotFoundException
* @throws StepNotFoundException
*/
public function start(mixed $entity): ?StepKey
public function start(mixed $entity, string $sessionKey = self::DEFAULT_SESSION_KEY): ?StepKey
{
$this->sessionStorage->setCurrent($sessionKey);

$this->stepControl->throwIfAlreadyStarted();

$this->build($entity);
Expand Down
4 changes: 3 additions & 1 deletion src/SteppedFormInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

interface SteppedFormInterface
{
public const DEFAULT_SESSION_KEY = '__MAIN__';

/**
* Returns a form data.
*
Expand All @@ -32,7 +34,7 @@ public function getEntity(): mixed;
* @throws AlreadyStartedException
* @throws SteppedFormErrorsException
*/
public function start(mixed $entity): ?StepKey;
public function start(mixed $entity, string $sessionKey = self::DEFAULT_SESSION_KEY): ?StepKey;

/**
* Returns a Template Definition for given step.
Expand Down
3 changes: 2 additions & 1 deletion tests/Form/DataControlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Lexal\SteppedForm\Step\StepBehaviourInterface;
use Lexal\SteppedForm\Step\StepInterface;
use Lexal\SteppedForm\Step\StepKey;
use Lexal\SteppedForm\Tests\InMemorySessionStorage;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

Expand All @@ -22,7 +23,7 @@ final class DataControlTest extends TestCase

protected function setUp(): void
{
$this->dataStorage = new DataStorage(new ArrayStorage());
$this->dataStorage = new DataStorage(new ArrayStorage(new InMemorySessionStorage()));
$this->dataControl = new DataControl($this->dataStorage);
}

Expand Down
3 changes: 2 additions & 1 deletion tests/Form/StepControlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Lexal\SteppedForm\Form\StepControl;
use Lexal\SteppedForm\Form\Storage\ArrayStorage;
use Lexal\SteppedForm\Step\StepKey;
use Lexal\SteppedForm\Tests\InMemorySessionStorage;
use PHPUnit\Framework\TestCase;

final class StepControlTest extends TestCase
Expand All @@ -17,7 +18,7 @@ final class StepControlTest extends TestCase

protected function setUp(): void
{
$this->stepControl = new StepControl(new ArrayStorage());
$this->stepControl = new StepControl(new ArrayStorage(new InMemorySessionStorage()));
}

public function testSetAndGetCurrent(): void
Expand Down
9 changes: 5 additions & 4 deletions tests/Form/Storage/ArrayStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
namespace Lexal\SteppedForm\Tests\Form\Storage;

use Lexal\SteppedForm\Form\Storage\ArrayStorage;
use Lexal\SteppedForm\Tests\InMemorySessionStorage;
use PHPUnit\Framework\TestCase;

final class ArrayStorageTest extends TestCase
{
public function testPut(): void
{
$storage = new ArrayStorage();
$storage = new ArrayStorage(new InMemorySessionStorage());

$storage->put('key', 'value');

Expand All @@ -25,7 +26,7 @@ public function testPut(): void

public function testGet(): void
{
$storage = new ArrayStorage();
$storage = new ArrayStorage(new InMemorySessionStorage());

$storage->put('key', 'value');

Expand All @@ -36,7 +37,7 @@ public function testGet(): void

public function testHas(): void
{
$storage = new ArrayStorage();
$storage = new ArrayStorage(new InMemorySessionStorage());

$storage->put('key', 'value');

Expand All @@ -46,7 +47,7 @@ public function testHas(): void

public function testClear(): void
{
$storage = new ArrayStorage();
$storage = new ArrayStorage(new InMemorySessionStorage());

$storage->put('key', 'value');
$storage->put('key2', 'value2');
Expand Down
3 changes: 2 additions & 1 deletion tests/Form/Storage/DataStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Lexal\SteppedForm\Form\Storage\ArrayStorage;
use Lexal\SteppedForm\Form\Storage\DataStorage;
use Lexal\SteppedForm\Step\StepKey;
use Lexal\SteppedForm\Tests\InMemorySessionStorage;
use PHPUnit\Framework\TestCase;

final class DataStorageTest extends TestCase
Expand All @@ -16,7 +17,7 @@ final class DataStorageTest extends TestCase

protected function setUp(): void
{
$this->dataStorage = new DataStorage(new ArrayStorage());
$this->dataStorage = new DataStorage(new ArrayStorage(new InMemorySessionStorage()));
}

/**
Expand Down
22 changes: 22 additions & 0 deletions tests/InMemorySessionStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Lexal\SteppedForm\Tests;

use Lexal\SteppedForm\Form\Storage\SessionStorageInterface;

final class InMemorySessionStorage implements SessionStorageInterface
{
private ?string $sessionKey = null;

public function getCurrent(): ?string
{
return $this->sessionKey;
}

public function setCurrent(string $sessionKey): void
{
$this->sessionKey = $sessionKey;
}
}
Loading

0 comments on commit efdafee

Please sign in to comment.