Skip to content

Commit

Permalink
Merge 551d633 into 9e30495
Browse files Browse the repository at this point in the history
  • Loading branch information
craue committed Feb 2, 2015
2 parents 9e30495 + 551d633 commit 3069a2a
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 80 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [#101]: support for concurrent instances of the same flow
- [#104]: removed options from method `createForm`
- [#145]: bumped Symfony dependency to 2.3
- [#148]: restructured data storage
- removed the step field template
- renamed property `step` to `stepNumber` and method `getStep` to `getStepNumber` within event classes
- [#98]+[#143]: add a validation error to the current form if a form of a previous step became invalid
Expand Down Expand Up @@ -34,6 +35,7 @@
[#143]: https://github.com/craue/CraueFormFlowBundle/issues/143
[#145]: https://github.com/craue/CraueFormFlowBundle/issues/145
[#146]: https://github.com/craue/CraueFormFlowBundle/issues/146
[#148]: https://github.com/craue/CraueFormFlowBundle/issues/148

## 2.1.6 (2015-02-02)

Expand Down
61 changes: 13 additions & 48 deletions Form/FormFlow.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
use Craue\FormFlowBundle\Event\PreBindEvent;
use Craue\FormFlowBundle\Event\PreviousStepInvalidEvent;
use Craue\FormFlowBundle\Exception\InvalidTypeException;
use Craue\FormFlowBundle\Storage\SerializableFile;
use Craue\FormFlowBundle\Storage\StorageInterface;
use Craue\FormFlowBundle\Storage\DataManagerInterface;
use Craue\FormFlowBundle\Util\StringUtil;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormFactoryInterface;
Expand All @@ -36,9 +35,9 @@ abstract class FormFlow implements FormFlowInterface {
protected $formFactory;

/**
* @var StorageInterface
* @var DataManagerInterface
*/
protected $storage;
protected $dataManager;

/**
* @var EventDispatcherInterface|null
Expand Down Expand Up @@ -115,11 +114,6 @@ abstract class FormFlow implements FormFlowInterface {
*/
private $formTransitionKey = null;

/**
* @var string|null Is only null if not yet initialized.
*/
private $stepDataKey = null;

/**
* @var string|null Is only null if not yet initialized.
*/
Expand Down Expand Up @@ -190,15 +184,15 @@ public function getRequest() {
/**
* {@inheritDoc}
*/
public function setStorage(StorageInterface $storage) {
$this->storage = $storage;
public function setDataManager(DataManagerInterface $dataManager) {
$this->dataManager = $dataManager;
}

/**
* {@inheritDoc}
*/
public function getStorage() {
return $this->storage;
public function getDataManager() {
return $this->dataManager;
}

/**
Expand Down Expand Up @@ -239,6 +233,9 @@ public function setInstanceId($instanceId) {
$this->instanceId = $instanceId;
}

/**
* {@inheritDoc}
*/
public function getInstanceId() {
if ($this->instanceId === null) {
$this->instanceId = $this->getId();
Expand Down Expand Up @@ -271,18 +268,6 @@ public function getFormTransitionKey() {
return $this->formTransitionKey;
}

public function setStepDataKey($stepDataKey) {
$this->stepDataKey = $stepDataKey;
}

public function getStepDataKey() {
if ($this->stepDataKey === null) {
$this->stepDataKey = $this->getId() . '_data';
}

return $this->stepDataKey;
}

public function setValidationGroupPrefix($validationGroupPrefix) {
$this->validationGroupPrefix = $validationGroupPrefix;
}
Expand Down Expand Up @@ -437,7 +422,7 @@ protected function applySkipping($stepNumber, $direction = 1) {
* {@inheritDoc}
*/
public function reset() {
$this->storage->remove($this->getStepDataKey());
$this->dataManager->drop($this);
$this->currentStepNumber = $this->getFirstStepNumber();

// re-evaluate to not keep steps marked as skipped when resetting
Expand Down Expand Up @@ -574,7 +559,6 @@ protected function refineCurrentStepNumber($refinedStepNumber) {
*/
public function bind($formData) {
$this->setInstanceId($this->determineInstanceId());
$this->setStepDataKey($this->getId() . '_data_' . $this->getInstanceId());

if ($this->hasListeners(FormFlowEvents::PRE_BIND)) {
$event = new PreBindEvent($this);
Expand Down Expand Up @@ -924,30 +908,11 @@ protected function loadStepsConfig() {
}

protected function retrieveStepData() {
$data = $this->storage->get($this->getStepDataKey(), array());

if ($this->handleFileUploads) {
$tempDir = $this->handleFileUploadsTempDir;
array_walk_recursive($data, function(&$value, $key) use ($tempDir) {
if ($value instanceof SerializableFile) {
$value = $value->getAsFile($tempDir);
}
});
}

return $data;
return $this->dataManager->load($this);
}

protected function saveStepData(array $data) {
if ($this->handleFileUploads) {
array_walk_recursive($data, function(&$value, $key) {
if (SerializableFile::isSupported($value)) {
$value = new SerializableFile($value);
}
});
}

$this->storage->set($this->getStepDataKey(), $data);
$this->dataManager->save($this, $data);
}

/**
Expand Down
15 changes: 10 additions & 5 deletions Form/FormFlowInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Craue\FormFlowBundle\Form;

use Craue\FormFlowBundle\Exception\InvalidTypeException;
use Craue\FormFlowBundle\Storage\StorageInterface;
use Craue\FormFlowBundle\Storage\DataManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
Expand Down Expand Up @@ -32,14 +32,14 @@ function setFormFactory(FormFactoryInterface $formFactory);
function setRequest(Request $request = null);

/**
* @param StorageInterface $storage
* @param DataManagerInterface $dataManager
*/
function setStorage(StorageInterface $storage);
function setDataManager(DataManagerInterface $dataManager);

/**
* @return StorageInterface
* @return DataManagerInterface
*/
function getStorage();
function getDataManager();

/**
* @param EventDispatcherInterface $eventDispatcher
Expand Down Expand Up @@ -76,6 +76,11 @@ function isAllowRedirectAfterSubmit();
*/
function getId();

/**
* @return string
*/
function getInstanceId();

/**
* Restores previously saved form data of all steps and determines the current step.
* @param mixed $formData
Expand Down
12 changes: 9 additions & 3 deletions Resources/config/form_flow.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,22 @@

<service id="craue.form.flow.storage" alias="craue.form.flow.storage_default" scope="request" />

<service id="craue.form.flow.data_manager_default" class="Craue\FormFlowBundle\Storage\DataManager" scope="request" public="false">
<argument type="service" id="craue.form.flow.storage" />
</service>

<service id="craue.form.flow.data_manager" alias="craue.form.flow.data_manager_default" scope="request" />

<service id="craue.form.flow" class="%craue.form.flow.class%" scope="request">
<call method="setDataManager">
<argument type="service" id="craue.form.flow.data_manager" />
</call>
<call method="setFormFactory">
<argument type="service" id="form.factory" />
</call>
<call method="setRequest">
<argument type="service" id="request" />
</call>
<call method="setStorage">
<argument type="service" id="craue.form.flow.storage" />
</call>
<call method="setEventDispatcher">
<argument type="service" id="event_dispatcher" on-invalid="ignore" />
</call>
Expand Down
147 changes: 147 additions & 0 deletions Storage/DataManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php

namespace Craue\FormFlowBundle\Storage;

use Craue\FormFlowBundle\Form\FormFlowInterface;

/**
* Manages data of flows and their steps.
*
* It uses the following data structure with {@link DataManagerInterface::STORAGE_ROOT} as name of the root element within the storage:
* <code>
* DataManagerInterface::STORAGE_ROOT => array(
* name of the flow => array(
* instance id of the flow => array(
* 'data' => array() // the actual step data
* )
* )
* )
* </code>
*
* @author Christian Raue <christian.raue@gmail.com>
* @copyright 2011-2015 Christian Raue
* @license http://opensource.org/licenses/mit-license.php MIT License
*/
class DataManager implements ExtendedDataManagerInterface {

/**
* @var string Key for the actual step data.
*/
const DATA_KEY = 'data';

/**
* @var StorageInterface
*/
private $storage;

/**
* @param StorageInterface $storage
*/
public function __construct(StorageInterface $storage) {
$this->storage = $storage;
}

/**
* {@inheritDoc}
*/
public function getStorage() {
return $this->storage;
}

/**
* {@inheritDoc}
*/
public function save(FormFlowInterface $flow, array $data) {
// handle file uploads
if ($flow->isHandleFileUploads()) {
array_walk_recursive($data, function(&$value, $key) {
if (SerializableFile::isSupported($value)) {
$value = new SerializableFile($value);
}
});
}

// drop old data
$this->drop($flow);

// save new data
$savedFlows = $this->storage->get(DataManagerInterface::STORAGE_ROOT, array());

$savedFlows = array_merge_recursive($savedFlows, array(
$flow->getName() => array(
$flow->getInstanceId() => array(
self::DATA_KEY => $data,
),
),
));

$this->storage->set(DataManagerInterface::STORAGE_ROOT, $savedFlows);
}

/**
* {@inheritDoc}
*/
public function load(FormFlowInterface $flow) {
$data = array();

// try to find data for the given flow
$savedFlows = $this->storage->get(DataManagerInterface::STORAGE_ROOT, array());
if (isset($savedFlows[$flow->getName()][$flow->getInstanceId()][self::DATA_KEY])) {
$data = $savedFlows[$flow->getName()][$flow->getInstanceId()][self::DATA_KEY];
}

// handle file uploads
if ($flow->isHandleFileUploads()) {
$tempDir = $flow->getHandleFileUploadsTempDir();
array_walk_recursive($data, function(&$value, $key) use ($tempDir) {
if ($value instanceof SerializableFile) {
$value = $value->getAsFile($tempDir);
}
});
}

return $data;
}

/**
* {@inheritDoc}
*/
public function drop(FormFlowInterface $flow) {
$savedFlows = $this->storage->get(DataManagerInterface::STORAGE_ROOT, array());

// remove data for only this flow instance
if (isset($savedFlows[$flow->getName()][$flow->getInstanceId()])) {
unset($savedFlows[$flow->getName()][$flow->getInstanceId()]);
}

$this->storage->set(DataManagerInterface::STORAGE_ROOT, $savedFlows);
}

/**
* {@inheritDoc}
*/
public function listFlows() {
return array_keys($this->storage->get(DataManagerInterface::STORAGE_ROOT, array()));
}

/**
* {@inheritDoc}
*/
public function listInstances($name) {
$savedFlows = $this->storage->get(DataManagerInterface::STORAGE_ROOT, array());

if (array_key_exists($name, $savedFlows)) {
return array_keys($savedFlows[$name]);
}

return array();
}

/**
* {@inheritDoc}
*/
public function dropAll() {
$this->storage->remove(DataManagerInterface::STORAGE_ROOT);
}

}

0 comments on commit 3069a2a

Please sign in to comment.