FEATURE: added ability to delete 1 submission or all the submissions from the userdefined form

This commit is contained in:
Will Rossiter 2009-04-15 04:23:43 +00:00
parent 6368c972d1
commit 8926ad082b
8 changed files with 227 additions and 192 deletions

View File

@ -256,99 +256,6 @@ class UserDefinedForm_Controller extends Page_Controller {
'Form' => $this->Form
);
}
/**
* Export each of the form submissions for this UserDefinedForm
* instance into a CSV file.
*
* In order to run this export function, the user must be
* able to edit the page, so we check canEdit()
*
* @return HTTPResponse / bool
*/
public function export() {
if(!$this->canEdit()) return false;
$now = Date("Y-m-d_h.i.s");
$fileName = "export-$now.csv";
$separator = ",";
// Get the UserDefinedForm to export data from the URL
$SQL_ID = Convert::raw2sql(Director::urlParam('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 Name, Title FROM SubmittedFormField LEFT JOIN SubmittedForm ON SubmittedForm.ID = SubmittedFormField.ParentID WHERE SubmittedFormField.ParentID IN (" . implode(',', $inClause) . ")");
// 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;
}
}
}
}
$i++;
}
// CSV header row
$csvData = '"' . implode('","', $csvHeaderTitle) . '"' . "\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;$i<count($csvHeaderNames);$i++) {
if(!$row[$i]) $csvData .= '"",'; // If there is no data for this column, output it as blank instead
else $csvData .= '"'.$row[$i].'",'; // Otherwise, output the value for this column
}
// Start a new row for each submission
$csvData .= "\n";
}
} else {
user_error("No submissions to export.", E_USER_ERROR);
}
HTTPRequest::send_file($csvData, $fileName)->output();
} else {
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);
}
} else {
user_error("'$SQL_ID' is not a valid UserDefinedForm ID.", E_USER_ERROR);
}
}
function ReportFilterForm() {
return new SubmittedFormReportField_FilterForm( $this, 'ReportFilterForm' );

View File

@ -1,8 +1,8 @@
<?php
/**
* Allows CMS user to create forms dynamically.
* @package forms
* @subpackage fieldeditor
*
* @package userforms
*/
class FieldEditor extends FormField {
@ -63,8 +63,6 @@ class FieldEditor extends FormField {
foreach($fields as $field => $title) {
// get the nice title and strip out field
$niceTitle = trim(str_ireplace("Field", "", eval("return $title::\$singular_name;")));
// keep old javascript happy
$title = trim(str_ireplace("Editable", "", $title));
$output->push(new ArrayData(array(

View File

@ -14,16 +14,17 @@ class SubmittedForm extends DataObject {
);
/**
* Return the Link to DeleteLink
* Before we delete this form make sure we delete all the
* field values so that we don't leave old data round
*
* @return String
*/
public function DeleteLink() {
return $this->Parent()->Link().'deletesubmission/'.$this->ID;
}
function SubmitTime() {
return $this->Created;
protected function onBeforeDelete() {
if($this->FieldValues()) {
foreach($this->FieldValues() as $value) {
$value->delete();
}
}
parent::onBeforeDelete();
}
}
?>

View File

@ -1,7 +1,8 @@
<?php
/**
* Data received from a UserDefinedForm submission
* @package cms
*
* @package userforms
*/
class SubmittedFormField extends DataObject {

View File

@ -8,7 +8,7 @@ class SubmittedFormReportField extends FormField {
function Field() {
Requirements::css(SAPPHIRE_DIR . "/css/SubmittedFormReportField.css");
Requirements::javascript("userforms/javascript/UserForm.js");
return $this->renderWith("SubmittedFormReportField");
}
@ -22,25 +22,142 @@ class SubmittedFormReportField extends FormField {
}
/**
* Link to the export function of the controller
* ID of this forms record
*
* @return String
* @return int
*/
function ExportLink() {
if($this->Submissions() && $this->Submissions()->Count() > 0) {
return $this->form->getRecord()->Link() . 'export/' . $this->form->getRecord()->ID;
function RecordID() {
return $this->form->getRecord()->ID;
}
/**
* Export each of the form submissions for this UserDefinedForm
* instance into a CSV file.
*
* In order to run this export function, the user must be
* able to edit the page, so we check canEdit()
*
* @return HTTPResponse / bool
*/
public function export() {
$now = Date("Y-m-d_h.i.s");
$fileName = "export-$now.csv";
$separator = ",";
// Get the UserDefinedForm to export data from the URL
$SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false;
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 Name, Title FROM SubmittedFormField LEFT JOIN SubmittedForm ON SubmittedForm.ID = SubmittedFormField.ParentID WHERE SubmittedFormField.ParentID IN (" . implode(',', $inClause) . ")");
// 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;
}
}
}
}
$i++;
}
// CSV header row
$csvData = '"' . implode('","', $csvHeaderTitle) . '"' . "\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;$i<count($csvHeaderNames);$i++) {
if(!$row[$i]) $csvData .= '"",'; // If there is no data for this column, output it as blank instead
else $csvData .= '"'.$row[$i].'",'; // Otherwise, output the value for this column
}
// Start a new row for each submission
$csvData .= "\n";
}
} else {
user_error("No submissions to export.", E_USER_ERROR);
}
HTTPRequest::send_file($csvData, $fileName)->output();
} else {
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);
}
} else {
user_error("'$SQL_ID' is not a valid UserDefinedForm ID.", E_USER_ERROR);
}
}
/**
* Link to the delete the submission
*
* @return String
* Delete all the submissions listed in the user defined form
*
* @return Redirect|Boolean
*/
function DeleteLink() {
if($this->Submissions() && $this->Submissions()->Count() > 0) {
return $this->form->getRecord()->Link() . 'deletesubmissions/' . $this->form->getRecord()->ID;
}
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();
}
}
return (Director::is_ajax()) ? false : Director::redirectBack();
}
/**
* Delete a given submission from a user defined form
*
* @return Redirect|Boolean
*/
public function deletesubmission() {
$SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false;
if($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()) ? false : Director::redirectBack();
}
}
?>

View File

@ -492,64 +492,61 @@ FieldEditorCheckboxGroupField = Class.extend('FieldEditorRadioField');
FieldEditorDropdown = Class.extend('FieldEditorRadioField');
Behaviour.register(
{
'div.FieldEditor ul.Menu li a': {
Behaviour.register({
'div.FieldEditor ul.Menu li a': {
urlForFieldMethod: function(methodName) {
return this.ownerForm().action + '/field/Fields/' + methodName + '?NewID=' + this.numNewFields;
},
ownerForm: function() {
var f = this.parentNode;
while(f && f.tagName.toLowerCase() != 'form') f = f.parentNode;
return f;
},
onclick: function() {
// get the ID of the field editor here
urlForFieldMethod: function(methodName) {
return this.ownerForm().action + '/field/Fields/' + methodName + '?NewID=' + this.numNewFields;
},
ownerForm: function() {
var f = this.parentNode;
while(f && f.tagName.toLowerCase() != 'form') f = f.parentNode;
return f;
},
onclick: function() {
// get the ID of the field editor here
if( Element.hasClassName( $('Fields'), 'readonly' ) )
return false;
action = this.urlForFieldMethod("addfield") + "&Type=" + this.id + ($('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '');;
statusMessage('Adding new field' );
new Ajax.Request(action, {
method: 'get',
onFailure: reportError,
onSuccess: this.appendNewField.bind(this)
});
if( Element.hasClassName( $('Fields'), 'readonly' ) )
return false;
},
appendNewField: function(response) {
this.numNewFields++;
var el = document.createElement('div');
el.innerHTML = response.responseText;
var i=0;
while(!el.childNodes[i].tagName) i++;
var newField = el.childNodes[i];
$('Fields_fields').appendChild(newField);
// Behaviour.debug();
if(newField) {
Behaviour.apply(newField,true);
FieldEditor.applyTo('div.FieldEditor');
}
// do we want to make sorting explicit?
Sortable.create('Fields_fields', {tag: 'div', handle:'handle'});
statusMessage('Added new field','good');
action = this.urlForFieldMethod("addfield") + "&Type=" + this.id + ($('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '');;
statusMessage('Adding new field' );
new Ajax.Request(action, {
method: 'get',
onFailure: reportError,
onSuccess: this.appendNewField.bind(this)
});
return false;
},
appendNewField: function(response) {
this.numNewFields++;
var el = document.createElement('div');
el.innerHTML = response.responseText;
var i=0;
while(!el.childNodes[i].tagName) i++;
var newField = el.childNodes[i];
$('Fields_fields').appendChild(newField);
// Behaviour.debug();
if(newField) {
Behaviour.apply(newField,true);
FieldEditor.applyTo('div.FieldEditor');
}
// do we want to make sorting explicit?
Sortable.create('Fields_fields', {tag: 'div', handle:'handle'});
statusMessage('Added new field','good');
}
}
);
});
function reportError(request){
// More complex error for developers

11
javascript/UserForm.js Normal file
View File

@ -0,0 +1,11 @@
(function($) {
$(document).ready(function() {
$("#FormSubmissions .deleteSubmission").click(function() {
var deletedSubmission = $(this);
$.post($(this).attr('href'), function(data) {
deletedSubmission.parents('div.report').fadeOut();
});
return false;
});
})
})(jQuery);

View File

@ -3,25 +3,28 @@
</div>
<div class="reports" id="FormSubmissions">
<% if ExportLink %>
<a href="$ExportLink" title="<% _t('EXPORTCSVFILE', 'Export CSV file') %>"><strong><% _t('EXPORTSUBMISSIONS', 'Export submissions to CSV') %></strong></a>
<% end_if %>
<!-- <% if DeleteLink %>
<a href="$DeleteLink" title="<% _t('DELETEALLSUBMISSIONS', 'Delete Submissions') %>"><strong><% _t('DELETEALLSUBMISSIONS', 'Delete Submissions') %></strong></a>
<% end_if %>
-->
<% control Submissions %>
<div class="report">
<span class="submitted"><% _t('SUBMITTED', 'Submitted at') %> $Created.Nice. <!--<a href="$DeleteLink"><% _t('DELETESUBMISSION', 'Delete Submission') %></a>--></span>
<table>
<% control FieldValues %>
<tr>
<td class="field">$Title</td>
<td class="value"><% if Link %><a href="$Link"><% end_if %>$Value<% if Link %></a><% end_if %></td>
</tr>
<% end_control %>
</table>
</div>
<% end_control %>
<% if Submissions %>
<ul class="formSubmissionActions">
<!-- @todo work out why url_handlers dont like /export/2 -->
<li><a href="{$Top.Link}/export/?id={$RecordID}"><% _t('EXPORTSUBMISSIONS', 'Export submissions to CSV') %></a></li>
<li><a href="{$Top.Link}/deletesubmissions/?id={$RecordID}" class="deleteSubmission"><% _t('DELETEALLSUBMISSIONS', 'Delete All Submissions') %></a></li>
</ul>
<% control Submissions %>
<div class="report">
<h4 class="submitted"><% _t('SUBMITTED', 'Submitted at') %> $Created.Nice. <a href="{$Top.Link}/deletesubmission/?id={$ID}" class="deleteSubmission"><% _t('DELETESUBMISSION', 'Delete Submission') %></a></h4>
<table>
<% control FieldValues %>
<tr>
<td class="field">$Title</td>
<td class="value"><% if Link %><a href="$Link"><% end_if %>$Value<% if Link %></a><% end_if %></td>
</tr>
<% end_control %>
</table>
</div>
<% end_control %>
<% else %>
<p><% _t('NOSUBMISSIONS', 'No Submissions') %></p>
<% end_if %>
</div>