diff --git a/code/submissions/SubmittedForm.php b/code/submissions/SubmittedForm.php index 9454192..36effde 100755 --- a/code/submissions/SubmittedForm.php +++ b/code/submissions/SubmittedForm.php @@ -13,7 +13,7 @@ class SubmittedForm extends DataObject { ); static $has_many = array( - "FieldValues" => "SubmittedFormField" + "Values" => "SubmittedFormField" ); /** @@ -22,11 +22,13 @@ class SubmittedForm extends DataObject { * */ protected function onBeforeDelete() { - if($this->FieldValues()) { - foreach($this->FieldValues() as $value) { + + if($this->Values()) { + foreach($this->Values() as $value) { $value->delete(); } } + parent::onBeforeDelete(); } } \ No newline at end of file diff --git a/code/submissions/SubmittedFormReportField.php b/code/submissions/SubmittedFormReportField.php index 730f66d..50a2326 100755 --- a/code/submissions/SubmittedFormReportField.php +++ b/code/submissions/SubmittedFormReportField.php @@ -21,12 +21,12 @@ class SubmittedFormReportField extends FormField { function Submissions() { $pageStart = isset($_REQUEST['start']) && is_numeric($_REQUEST['start']) ? $_REQUEST['start'] : 0; $pageLength = 10; - + $items = $this->form->getRecord()->getComponents('Submissions', null, "\"Created\" DESC", null, "$pageStart,$pageLength"); $formId = $this->form->getRecord()->ID; foreach(DB::query("SELECT COUNT(*) AS \"CountRows\" FROM \"SubmittedForm\" WHERE \"ParentID\" = $formId") as $r) $totalCount = $r['CountRows']; - + $items->setPageLimits($pageStart, $pageLength, $totalCount); $items->NextStart = $pageStart + $pageLength; $items->PrevStart = $pageStart - $pageLength; @@ -61,100 +61,116 @@ class SubmittedFormReportField extends FormField { * * @return HTTPResponse / bool */ - public function export() { + public function export($id = false) { + if($id && is_int($id)) { + $SQL_ID = $id; + } + else { + if(isset($_REQUEST['id'])) { + $SQL_ID = Convert::raw2sql($_REQUEST['id']); + } + else { + user_error("No UserDefinedForm Defined.", E_USER_ERROR); + + return false; + } + } + $now = Date("Y-m-d_h.i.s"); $fileName = "export-$now.csv"; $separator = ","; + + $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); - // Get the UserDefinedForm to export data from the URL - $SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false; + if($udf) { + $csvHeaderNames = array(); + $csvHeaderTitle = array(); + + $submissions = $udf->Submissions(); + + if($submissions && $submissions->exists()) { + + // Get all the submission IDs (so we know what names/titles to get - helps for sites with many UDF's) + $inClause = array(); + foreach($submissions as $submission) { + $inClause[] = $submission->ID; + } - if($SQL_ID) { - $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); - if($udf) { - $submissions = $udf->Submissions(); - if($submissions && $submissions->Count() > 0) { - - // Get all the submission IDs (so we know what names/titles to get - helps for sites with many UDF's) - $inClause = array(); - foreach($submissions as $submission) { - $inClause[] = $submission->ID; - } + // Get the CSV header rows from the database + + $tmp = DB::query(" + SELECT DISTINCT \"SubmittedFormField\".\"ID\", \"Name\", \"Title\" + FROM \"SubmittedFormField\" + LEFT JOIN \"SubmittedForm\" ON \"SubmittedForm\".\"ID\" = \"SubmittedFormField\".\"ParentID\" + WHERE \"SubmittedFormField\".\"ParentID\" IN (" . implode(',', $inClause) . ") + GROUP BY \"Name\" + ORDER BY \"SubmittedFormField\".\"ID\" + "); - // Get the CSV header rows from the database - - $tmp = DB::query("SELECT DISTINCT \"SubmittedFormField\".\"ID\", \"Name\", \"Title\" - FROM \"SubmittedFormField\" - LEFT JOIN \"SubmittedForm\" ON \"SubmittedForm\".\"ID\" = \"SubmittedFormField\".\"ParentID\" - WHERE \"SubmittedFormField\".\"ParentID\" IN (" . implode(',', $inClause) . ") - GROUP BY \"Name\" - ORDER BY \"SubmittedFormField\".\"ID\""); - - // Sort the Names and Titles from the database query into separate keyed arrays - foreach($tmp as $array) { - $csvHeaderNames[] = $array['Name']; - $csvHeaderTitle[] = $array['Title']; - - } - - // For every submission... - $i = 0; - foreach($submissions as $submission) { - - // Get the rows for this submission (One row = one form field) - $dataRow = $submission->FieldValues(); - $rows[$i] = array(); - - // For every row/field, get all the columns - foreach($dataRow as $column) { - - // If the Name of this field is in the $csvHeaderNames array, get an array of all the places it exists - if($index = array_keys($csvHeaderNames, $column->Name)) { - if(is_array($index)) { - - // Set the final output array for each index that we want to insert this value into - foreach($index as $idx) { - $rows[$i][$idx] = $column->Value; - } - $rows[$i]['Submitted'] = $submission->Created; - } - } - } - - $i++; - } - // CSV header row - $csvData = '"' . implode('","', $csvHeaderTitle) . '"' . ',"Submitted"'."\n"; - - // For every row of data (one form submission = one row) - foreach($rows as $row) { - // Loop over all the names we can use - for($i=0;$ioutput(); - } else { - HTTPRequest::send_file($csvData, $fileName)->output(); + // For every submission... + $i = 0; + foreach($submissions as $submission) { + + // Get the rows for this submission (One row = one form field) + $dataRow = $submission->Values(); + + $rows[$i] = array(); + + // For every row/field, get all the columns + foreach($dataRow as $column) { + // If the Name of this field is in the $csvHeaderNames array, get an array of all the places it exists + if($index = array_keys($csvHeaderNames, $column->Name)) { + if(is_array($index)) { + // Set the final output array for each index that we want to insert this value into + foreach($index as $idx) { + $rows[$i][$idx] = $column->Value; + } + } + } + } + + $rows[$i]['Submitted'] = $submission->Created; + + $i++; } + // CSV header row + $csvData = '"' . implode('","', $csvHeaderTitle) . '"' . ',"Submitted"'."\n"; + + // For every row of data (one form submission = one row) + foreach($rows as $row) { + + for($i=0;$ioutput(); } } else { - user_error("'$SQL_ID' is not a valid UserDefinedForm ID.", E_USER_ERROR); + user_error("'$SQL_ID' is a valid type, but we can't find a UserDefinedForm in the database that matches the ID.", E_USER_ERROR); } } @@ -163,20 +179,28 @@ class SubmittedFormReportField extends FormField { * * @return Redirect|Boolean */ - public function deletesubmissions() { - $SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false; - if($SQL_ID) { - $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); - $submissions = $udf->Submissions(); - if($submissions) { - foreach($submissions as $submission) { - // delete the submission @see $submission->onBeforeDelete() for more info - $submission->delete(); - } - return (Director::is_ajax()) ? true : Director::redirectBack(); + public function deletesubmissions($id = false) { + if($id && is_int($id)) { + $SQL_ID = $id; + } + else { + if(isset($_REQUEST['id'])) { + $SQL_ID = Convert::raw2sql($_REQUEST['id']); } } - return (Director::is_ajax()) ? false : Director::redirectBack(); + + if(isset($SQL_ID)) { + $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); + $submissions = $udf->Submissions(); + + if($submissions) { + foreach($submissions as $submission) { + $submission->delete(); + } + return (Director::is_ajax() || SapphireTest::is_running_test()) ? true : Director::redirectBack(); + } + } + return (Director::is_ajax() || SapphireTest::is_running_test()) ? false : Director::redirectBack(); } /** @@ -184,16 +208,24 @@ class SubmittedFormReportField extends FormField { * * @return Redirect|Boolean */ - public function deletesubmission() { - $SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false; - if($SQL_ID) { + public function deletesubmission($id = false) { + if($id && is_int($id)) { + $SQL_ID = $id; + } + else { + if(isset($_REQUEST['id'])) { + $SQL_ID = Convert::raw2sql($_REQUEST['id']); + } + } + + if(isset($SQL_ID)) { $submission = DataObject::get_by_id("SubmittedForm", $SQL_ID); if($submission) { $submission->delete(); - return (Director::is_ajax()) ? true : Director::redirectBack(); + return (Director::is_ajax() || SapphireTest::is_running_test()) ? true : Director::redirectBack(); } } - return (Director::is_ajax()) ? false : Director::redirectBack(); + return (Director::is_ajax() || SapphireTest::is_running_test()) ? false : Director::redirectBack(); } } \ No newline at end of file diff --git a/javascript/UserForm.js b/javascript/UserForm.js index 24734d5..62de04f 100644 --- a/javascript/UserForm.js +++ b/javascript/UserForm.js @@ -69,10 +69,11 @@ * we let the href of the delete link to do all the work for us */ - $("#FormSubmissions .deleteSubmission").click(function() { + $("#userforms-submissions .deleteSubmission").click(function() { var deletedSubmission = $(this); + $.post($(this).attr('href'), function(data) { - deletedSubmission.parents('div.report').fadeOut(); + deletedSubmission.parents('div.userform-submission').fadeOut(); }); return false; }); diff --git a/templates/SubmittedFormReportField.ss b/templates/SubmittedFormReportField.ss index 20a1dc1..63d9d5f 100644 --- a/templates/SubmittedFormReportField.ss +++ b/templates/SubmittedFormReportField.ss @@ -1,18 +1,17 @@ -
+
<% if Submissions %> - -
    - + <% control Submissions %> -
    - +
    +

    <% _t('SUBMITTED', 'Submitted at') %> $Created.Nice. <% _t('DELETESUBMISSION', 'Delete Submission') %>

    + - <% control FieldValues %> + <% control Values %> @@ -21,8 +20,10 @@
    $Title $FormattedValue
    <% end_control %> + <% if Submissions.MoreThanOnePage %> - \ No newline at end of file diff --git a/tests/EditableFormFieldTest.php b/tests/EditableFormFieldTest.php index d9010cf..037f848 100644 --- a/tests/EditableFormFieldTest.php +++ b/tests/EditableFormFieldTest.php @@ -193,12 +193,6 @@ class EditableFormFieldTest extends FunctionalTest { function testEditableDropdownField() { $dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown'); - - $option1 = $this->objFromFixture('EditableOption', 'option-1'); - $option2 = $this->objFromFixture('EditableOption', 'option-2'); - - $dropdown->Options()->add($option1); - $dropdown->Options()->add($option2); $field = $dropdown->getFormField(); @@ -211,19 +205,13 @@ class EditableFormFieldTest extends FunctionalTest { function testEditableRadioField() { $radio = $this->objFromFixture('EditableRadioField', 'radio-field'); - - $option1 = $this->objFromFixture('EditableOption', 'option-1'); - $option2 = $this->objFromFixture('EditableOption', 'option-2'); - - $radio->Options()->add($option1); - $radio->Options()->add($option2); - + $field = $radio->getFormField(); $this->assertThat($field, $this->isInstanceOf('OptionsetField')); $values = $field->getSource(); - $this->assertEquals(array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'), $values); + $this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values); } function testTitleField() { @@ -255,4 +243,59 @@ class EditableFormFieldTest extends FunctionalTest { $this->assertEquals($text->getSettingFieldName('Foo'), "Fields[". $text->ID ."][CustomSettings][Foo]"); } + + function testMultipleOptionDuplication() { + $dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown'); + + $clone = $dropdown->duplicate(); + + $this->assertEquals($clone->Options()->Count(), $dropdown->Options()->Count()); + + foreach($clone->Options() as $option) { + $orginal = $dropdown->Options()->find('Title', $option->Title); + + $this->assertEquals($orginal->Sort, $option->Sort); + } + } + + function testMultipleOptionPopulateFromPostData() { + $dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown'); + + $data = array(); + + foreach($dropdown->Options() as $option) { + $orginal[$option->ID] = array( + 'Title' => $option->Title, + 'Sort' => $option->Sort + ); + + $data[$option->ID] = array( + 'Title' => 'New - '. $option->Title, + 'Sort' => $option->Sort + 1 + ); + } + + $dropdown->populateFromPostData($data); + + $count = $dropdown->Options()->Count(); + + foreach($dropdown->Options() as $option) { + $this->assertEquals($option->Title, 'New - '. $orginal[$option->ID]['Title']); + $this->assertEquals($option->Sort, $orginal[$option->ID]['Sort'] + 1); + } + + unset($data[1]); + + $dropdown->populateFromPostData($data); + + $this->assertEquals($dropdown->Options()->Count(), $count-1); + } + + function testEditableTextFieldConfiguration() { + $text = $this->objFromFixture('EditableTextField', 'basic-text'); + + $configuration = $text->getFieldConfiguration(); + + Debug::show($configuration); + } } \ No newline at end of file diff --git a/tests/FieldEditorTest.php b/tests/FieldEditorTest.php index d3090cd..97ca44d 100644 --- a/tests/FieldEditorTest.php +++ b/tests/FieldEditorTest.php @@ -28,7 +28,7 @@ class FieldEditorTest extends FunctionalTest { function testSaveInto() { $this->logInWithPermission('ADMIN'); - + // @todo } function testAddField() { diff --git a/tests/SubmittedFormTest.php b/tests/SubmittedFormTest.php index bbc40b0..637e0e7 100644 --- a/tests/SubmittedFormTest.php +++ b/tests/SubmittedFormTest.php @@ -4,27 +4,105 @@ class SubmittedFormTest extends FunctionalTest { static $fixture_file = 'userforms/tests/SubmittedFormTest.yml'; - function testReportSubmissions() { + protected $controller, $form, $page, $field; + + function setUp() { + parent::setUp(); + $this->page = $this->objFromFixture('UserDefinedForm', 'popular-form'); + $this->controller = new SubmittedFormTest_Controller($this->page); + $this->form = $this->controller->Form(); + $this->field = $this->form->dataFieldByName('Report'); } - function testCSVExport() { + function testSubmissions() { + $submissions = $this->field->Submissions(); + // test with 11 submissions. Should be over 2 pages. 10 per page. + // @todo add tests to ensure the order + $this->assertEquals($submissions->Count(), 10); + $this->assertEquals($submissions->TotalPages(), 2); + $this->assertEquals($submissions->TotalItems(), 11); + } + + function testGetSubmissionns() { + $template = $this->field->getSubmissions(); + + $parser = new CSSContentParser($template); + + // check to ensure that the pagination exists + $pagination = $parser->getBySelector('.userforms-submissions-pagination'); + + $this->assertEquals(str_replace("\n", ' ',(string) $pagination[0]->span), "Viewing rows 0 - 10 of 11 rows"); + $this->assertEquals(str_replace("\n", ' ',(string) $pagination[0]->a), "Next page"); + + // ensure the actions exist + $actions = $parser->getBySelector('.userforms-submission-actions'); + $this->assertEquals(count($actions[0]->li), 2); + + // submissions + $submissions = $parser->getBySelector('.userform-submission'); + $this->assertEquals(count($submissions), 10); + } + + function testCSVExport() { + $export = $this->field->export($this->page->ID); + + // export it back to an array (rather than string) + $exportLines = explode("\n", $export); + $data = array(); + + array_pop($exportLines); + + foreach($exportLines as $line) { + $line = explode("\",\"", $line); + + $clean = array(); + foreach($line as $part) { + $clean[] = trim($part, "\""); + } + + $data[] = $clean; + } + + // check the headers are fine + $this->assertEquals($data[0], array( + 'Submitted Title','Submitted Title 2','Submitted' + )); + + // check the number of records in the export + + $this->assertEquals(count($data), 12); + + $this->assertEquals($data[1][0], 'Value 1'); + $this->assertEquals($data[1][1], ""); + + $this->assertEquals($data[2][0], ""); + $this->assertEquals($data[2][1], 'Value 2'); } function testdeletesubmission() { + $submission = $this->objFromFixture('SubmittedForm', 'long-1'); + $count = $this->page->Submissions()->Count(); + $this->assertTrue($this->field->deletesubmission($submission->ID)); + + $this->assertEquals($count - 1, $this->page->Submissions()->Count()); + + $this->assertFalse($this->field->deletesubmission(-1)); } function testdeletesubmissions() { + $this->assertTrue($this->field->deletesubmissions($this->page->ID)); + $this->assertEquals($this->page->Submissions()->Count(), 0); } function testOnBeforeDeleteOfForm() { $field = $this->objFromFixture('SubmittedFormField', 'submitted-form-field-1'); $form = $field->Parent(); - $this->assertEquals($form->FieldValues()->Count(), 2); + $this->assertEquals($form->Values()->Count(), 2); $form->delete(); $fields = DataObject::get('SubmittedFormField', "ParentID = '$form->ID'"); @@ -60,9 +138,17 @@ class SubmittedFormTest extends FunctionalTest { } -class SubmittedFormTest_Controller extends Controller { +class SubmittedFormTest_Controller extends ContentController { - function ReportField() { - return new Form($this, 'ReportField', new FieldSet(new SubmittedFormReportField('Report'), new FieldSet())); + function Form() { + $form = new Form($this, 'Form', new FieldSet(new SubmittedFormReportField('Report')), new FieldSet(new FormAction('Submit'))); + + $form->loadDataFrom($this->data()); + + return $form; + } + + function forTemplate() { + return $this->renderWith(array('ContentController')); } } diff --git a/tests/SubmittedFormTest.yml b/tests/SubmittedFormTest.yml index 8bcd3df..7aefb01 100644 --- a/tests/SubmittedFormTest.yml +++ b/tests/SubmittedFormTest.yml @@ -1,22 +1,49 @@ +SubmittedForm: + submitted-form-1: + + submitted-form-2: + + long-1: + + long-2: + + long-3: + + long-4: + + long-5: + + long-6: + + long-7: + + long-8: + + long-9: + + long-10: + + long-11: + + UserDefinedForm: form-page: Title: Form + Submissions: =>SubmittedForm.submitted-form-1 form-page-2: Title: Second Form + Submissions: =>SubmittedForm.submitted-form-2 + + popular-form: + Title: Popular Form + Submissions: =>SubmittedForm.long-1, =>SubmittedForm.long-2, =>SubmittedForm.long-3, =>SubmittedForm.long-4, =>SubmittedForm.long-5, =>SubmittedForm.long-6, =>SubmittedForm.long-7, =>SubmittedForm.long-8, =>SubmittedForm.long-9, =>SubmittedForm.long-10, =>SubmittedForm.long-11 File: uploaded-file: Name: My File Filename: my-file.jpg - -SubmittedForm: - submitted-form-1: - Parent: =>UserDefinedForm.form-page - - submitted-form-2: - Parent: =>UserDefinedForm.form-page-2 - + SubmittedFormField: submitted-form-field-1: Parent: =>SubmittedForm.submitted-form-1 @@ -32,6 +59,18 @@ SubmittedFormField: I am here testing Testing until I cannot I love my testing + + long-submitted-1: + Name: Submitted Name + Title: Submitted Title + Parent: =>SubmittedForm.long-1 + Value: Value 1 + + long-submitted-2: + Parent: =>SubmittedForm.long-2 + Name: Submitted Name 2 + Title: Submitted Title 2 + Value: Value 2 SubmittedFileField: submitted-file-1: diff --git a/tests/UserDefinedFormTest.yml b/tests/UserDefinedFormTest.yml index 85df8ac..77acadc 100644 --- a/tests/UserDefinedFormTest.yml +++ b/tests/UserDefinedFormTest.yml @@ -2,19 +2,34 @@ EditableOption: option-1: Name: Option1 Title: Option 1 - Sort: 1 option-2: Name: Option2 Title: Option 2 - Sort: 2 + department-1: Name: dept1 Title: sales@example.com - + department-2: Name: dept2 Title: accounts@example.com + + option-3: + Name: Option3 + Title: Option 3 + + option-4: + Name: Option4 + Title: Option 4 + + option-5: + Name: Option5 + Title: Option 5 + + option-6: + Name: Option6 + Title: Option 6 UserDefinedForm_EmailRecipient: recipient-1: @@ -73,7 +88,7 @@ EditableCheckboxGroupField: checkbox-group: Name: check-box-group Title: Check box group - Options: =>EditableOption.option-1, =>EditableOption.option-2 + Options: =>EditableOption.option-3, =>EditableOption.option-4 EditableEmailField: email-field: @@ -85,7 +100,7 @@ EditableRadioField: radio-field: Name: radio-option Title: Radio Option - Options: =>EditableOption.option-1, =>EditableOption.option-2 + Options: =>EditableOption.option-5, =>EditableOption.option-6 UserDefinedForm: