Skip to content

Commit

Permalink
Move creating new submissions to onAfterInit
Browse files Browse the repository at this point in the history
  • Loading branch information
lhalaa committed Sep 3, 2019
1 parent 3a3c432 commit 1993f80
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 48 deletions.
14 changes: 8 additions & 6 deletions src/controllers/PartialSubmissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ public function savePartialSubmission(HTTPRequest $request)
$partialSubmission = PartialFormSubmission::get()->byID($submissionID);

if (!$submissionID || !$partialSubmission) {
$partialSubmission = PartialFormSubmission::create();
// TODO: Set the Parent ID and Parent Class before write, this issue will create new submissions
// every time the session expires when the user proceeds to the next step.
// Also, saving a new submission without a parent creates an
// "AccordionItems" as parent class (first DataObject found)
$submissionID = $partialSubmission->write();
// A new session has already been created in {@link UserDefinedFormControllerExtension::onAfterInit()}
// so this shouldn't happen. Although, when there's a pending ajax save (e.g. user clicks next/prev too fast
// then hit submit), after submission, the submissionID has already been deleted while save is still in
// progress, thus resulting to 404
// TODO: Find a solution dealing with race condition between ajax save and form submit
$this->httpError(404);
}

// Refresh session ID
$request->getSession()->set(self::SESSION_KEY, $submissionID);
foreach ($postVars as $field => $value) {
/** @var EditableFormField $editableField */
Expand Down
36 changes: 7 additions & 29 deletions src/controllers/PartialUserFormController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\UserDefinedForm;

/**
* Class PartialUserFormController
Expand All @@ -39,11 +38,6 @@ class PartialUserFormController extends UserDefinedFormController
'partial',
];

/**
* @var PartialFormSubmission
*/
protected $partialFormSubmission;

/**
* Partial form
*
Expand All @@ -62,20 +56,20 @@ public function partial(HTTPRequest $request)
$controller = parent::create($record);
$controller->doInit();

if (
$controller->data()->PasswordProtected &&
$request->getSession()->get(PasswordForm::PASSWORD_SESSION_KEY) !== $partial->ID
) {
return $this->redirect('verify');
}

// Set the session after init and check if the last session has expired
// or another submission has started
$sessionID = $request->getSession()->get(PartialSubmissionController::SESSION_KEY);
if (!$sessionID || $sessionID !== $partial->ID) {
$request->getSession()->set(PartialSubmissionController::SESSION_KEY, $partial->ID);
}

if (
$controller->PasswordProtected &&
$request->getSession()->get(PasswordForm::PASSWORD_SESSION_KEY) !== $partial->ID
) {
return $this->redirect('verify');
}

$form = $controller->Form();
$form->loadDataFrom($partial->getFields());
$this->populateData($form, $partial);
Expand Down Expand Up @@ -171,20 +165,4 @@ public function validateToken($request)

return $partial;
}

/**
* @return PartialFormSubmission
*/
public function getPartialFormSubmission(): PartialFormSubmission
{
return $this->partialFormSubmission;
}

/**
* @param PartialFormSubmission $partialFormSubmission
*/
public function setPartialFormSubmission(PartialFormSubmission $partialFormSubmission): void
{
$this->partialFormSubmission = $partialFormSubmission;
}
}
4 changes: 3 additions & 1 deletion src/controllers/PartialUserFormVerifyController.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public function doValidate($data, $form)
{
/** @var PartialFormSubmission $partial */
$partial = $this->getPartialFormSubmission();
$request = $this->getRequest();

$password = hash_pbkdf2('SHA256', $data['Password'], $partial->TokenSalt, 1000);
if (!hash_equals($password, $partial->Password)) {
Expand All @@ -87,11 +88,12 @@ public function doValidate($data, $form)
'Password incorrect, please check your password and try again'
)
);
$request->getSession()->clear(PasswordForm::PASSWORD_SESSION_KEY);
$request->getSession()->clear(self::PASSWORD_KEY);

return $this->redirectBack();
}

$request = $this->getRequest();
$request->getSession()->set(PasswordForm::PASSWORD_SESSION_KEY, $partial->ID);
$request->getSession()->set(self::PASSWORD_KEY, $data['Password']);

Expand Down
4 changes: 4 additions & 0 deletions src/extensions/SubmittedFormExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Firesphere\PartialUserforms\Extensions;

use Firesphere\PartialUserforms\Controllers\PartialSubmissionController;
use Firesphere\PartialUserforms\Controllers\PartialUserFormVerifyController;
use Firesphere\PartialUserforms\Forms\PasswordForm;
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
use SilverStripe\Control\Controller;
use SilverStripe\ORM\DataExtension;
Expand Down Expand Up @@ -50,5 +52,7 @@ public function updateAfterProcess()
$partialForm->delete();
$partialForm->destroy();
$request->getSession()->clear(PartialSubmissionController::SESSION_KEY);
$request->getSession()->clear(PasswordForm::PASSWORD_SESSION_KEY);
$request->getSession()->clear(PartialUserFormVerifyController::PASSWORD_KEY);
}
}
67 changes: 61 additions & 6 deletions src/extensions/UserDefinedFormControllerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
namespace Firesphere\PartialUserforms\Extensions;

use Firesphere\PartialUserforms\Controllers\PartialSubmissionController;
use Firesphere\PartialUserforms\Models\PartialFieldSubmission;
use Firesphere\PartialUserforms\Models\PartialFileFieldSubmission;
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
use SilverStripe\Control\NullHTTPRequest;
use SilverStripe\Core\Extension;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
use SilverStripe\UserForms\Model\EditableFormField\EditableFormStep;
use SilverStripe\View\Requirements;

/**
Expand Down Expand Up @@ -34,14 +39,64 @@ public function onAfterInit()
return;
}

$url = $this->owner->getRequest()->getURL();
// This should never run on the 'partial' or 'ping' URL
if (strpos($url, 'partial') === false && strpos($url, 'ping') === false) {
// Clear session on start
$params = $this->owner->getRequest()->params();
// Pages without action e.g. /partial
if (!array_key_exists('Action', $params)) {
return;
}

// This should only run on index
if ($params['Action'] === null || $params['Action'] === 'index') {
$session = $this->owner->getRequest()->getSession();
if ($session && $session->get(PartialSubmissionController::SESSION_KEY)) {
$session->clear(PartialSubmissionController::SESSION_KEY);
if (!$session) {
return;
}

$this->createPartialSubmission();
}
}

/**
* Creates a new partial submission and partial fields.
*
* @throws \SilverStripe\ORM\ValidationException
*/
protected function createPartialSubmission()
{
$page = $this->owner;
// Create partial form
$partialSubmission = PartialFormSubmission::create([
'ParentID' => $page->ID,
'ParentClass' => $page->ClassName,
'UserDefinedFormID' => $page->ID,
'UserDefinedFormClass' => $page->ClassName,
]);
$submissionID = $partialSubmission->write();

// Create partial fields
foreach ($page->data()->Fields() as $field) {

// We don't need literal fields, headers, html, etc
if ($field::config()->literal === true || $field->ClassName == EditableFormStep::class) {
continue;
}

$newData = [
'SubmittedFormID' => $submissionID,
'Name' => $field->Name,
'Title' => $field->getField('Title'),
];

if (in_array(EditableFileField::class, $field->getClassAncestry())) {
$partialFile = PartialFileFieldSubmission::create($newData);
$partialSubmission->PartialUploads()->add($partialFile);
} else {
$partialField = PartialFieldSubmission::create($newData);
$partialSubmission->PartialFields()->add($partialField);
}
}

// Refresh session on start
$page->getRequest()->getSession()->set(PartialSubmissionController::SESSION_KEY, $submissionID);
}
}
13 changes: 7 additions & 6 deletions src/models/PartialFormSubmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ class PartialFormSubmission extends SubmittedForm
];

/**
* Don't add PartialUploads to cascade delete, the parent is changed to SubmittedForm on submission
* @var array
*/
private static $cascade_deletes = [
'PartialFields'
'PartialFields',
'PartialUploads',
];

/**
Expand Down Expand Up @@ -123,7 +123,8 @@ public function getCMSFields()
'Token',
'UserDefinedFormID',
'Submitter',
'PartialUploads'
'PartialUploads',
'Password'
]);

$partialFields = $this->PartialFields();
Expand Down Expand Up @@ -267,7 +268,7 @@ public function canCreate($member = null, $context = [])
*/
public function canView($member = null)
{
if ($this->UserDefinedForm()) {
if ($this->UserDefinedFormID) {
return $this->UserDefinedForm()->canView($member);
}

Expand All @@ -282,7 +283,7 @@ public function canView($member = null)
*/
public function canEdit($member = null)
{
if ($this->UserDefinedForm()) {
if ($this->UserDefinedFormID) {
return $this->UserDefinedForm()->canEdit($member);
}

Expand All @@ -296,7 +297,7 @@ public function canEdit($member = null)
*/
public function canDelete($member = null)
{
if ($this->UserDefinedForm()) {
if ($this->UserDefinedFormID) {
return $this->UserDefinedForm()->canDelete($member);
}

Expand Down

0 comments on commit 1993f80

Please sign in to comment.