Feedback collate and download - vish93 - 2017-04-04
Bit of background I have a feedback form in my theme, which will via ajax post data to my feedbackapi.php file where the posted feedback is then stored to a csv file.
I have also created a plugin so this csv file can be downloaded in the admin. My code is as follows:
plugin file:
PHP Code: <?php /* Plugin Name: Hello World Description: Gather Feedback Version: 1.0 Author: Vish Patel */ # get correct id for plugin $thisfile=basename(__FILE__, ".php"); $plugin_folder_name = 'hello-world'; $plugin_folder_path = GSPLUGINPATH.$plugin_folder_name.'/'; $rel_plugin_folder_path = substr(GSPLUGINPATH, strlen(GSROOTPATH)).$plugin_folder_name.'/'; # register plugin register_plugin( $thisfile, //Plugin id 'Vish Feedback', //Plugin name '1.0', //Plugin version 'Vish Patel', //Plugin author 'http://www.cagintranet.com/', //author website 'Gather feedback and save to a CSV file', //Plugin description 'plugins', //page type - on which admin tab to display 'Feedback_admin' //main function (administration) ); # activate filter add_action('index-posttemplate','hello_world'); # add a link in the admin tab 'theme' add_action('plugins-sidebar','createSideMenu',array($thisfile,'Vish Feedback')); # functions function hello_world() { // echo("<script>alert('wags');</script>"); } function createPath($path) { if (is_dir($path)) return true; $prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 ); $return = createPath($prev_path); return ($return && is_writable($prev_path)) ? mkdir($path) : false; } function Feedback_admin() { global $plugin_folder_path; global $filename; global $year; global $month; global $path; global $rel_plugin_folder_path; $year = date("Y"); $month = date("m"); $path = $plugin_folder_path.$year.'/'.$month.'/'; createPath($path); $filename = $path."vish.csv"; if (file_exists($filename)) { $row = 0; if (($handle = fopen($filename, "r")) !== FALSE) { while (($data = fgetcsv($handle)) !== FALSE) { $row++; } fclose($handle); } $message = $row > 1 ? "<a href='../{$rel_plugin_folder_path}{$year}/{$month}/vish.csv' download>Download Current months feedback spreadsheet</a>" : "No Feedback available for download!"; echo($message); } else { echo("No Feedback available for download!"); $ourFileHandle = fopen($filename, 'w') or die("can't open file"); $headers = ['Apprenticeship_Programme', 'Rating', 'Programme_Performance', 'Quality_Of_Programme','Programme_Communication_Quality','Assessor_Performance','Assessor_Contact_Frequency','Assessor_Feedback','Trainer_Technical_Competence','Trainer_Management_Ability','Trainer_Help_Ability']; fputcsv($ourFileHandle, $headers); fclose($ourFileHandle); } } ?>
My form:
Code: <form method="post" id="feedbackform" class="form-horizontal">
<p class="prog"></p>
<h2>Feedback</h2>
<div id="inf"></div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<h3>Provide feedback on:</h3>
<select class="form-control" id="RatingFor" name="RatingFor"required="required">
<option name="Programme" value="Programme">My Programme</option>
<option name="Assessor" value="Assessor">My Assessor</option>
<option name="Trainer" value="Trainer">My Trainer</option>
</select>
</div>
</div>
<div class="reqalt">
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="progq1">My programme performance in delivering the skills development I need at work is:</label>
<input class='rangeSlider' id='progq1' name='progq1'type="range" min="0" max="4" value="0" required="required"/><span class="range"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="progq2">The quality of my programme training facility is:</label>
<input class='rangeSlider' id='progq2' name='progq2'type="range" min="0" max="4" value="0" required="required"/><span class="range"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<label for="progq3">The level and quality of communication from my programme is:</label>
<input class='rangeSlider' id='progq3' name='progq3'type="range" min="0" max="4" value="0" required="required"/><span class="range"></span>
</div>
</div>
</div>
<div class="reqalt2">
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="asq1">My assessors performance in helping me through my programme is:</label>
<input class='rangeSlider' id='asq1' name='asq1'type="range" min="0" max="4" value="0" disabled="disabled"/><span class="range"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="asq2">The frequency of my assessors contact with me is:</label>
<input class='rangeSlider' id='asq2' name='asq2'type="range" min="0" max="4" value="0" disabled="disabled"/><span class="range"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="asq3">My assessors feedback at the end of my assessment visit is:</label>
<input class='rangeSlider' id='asq3' name='asq3'type="range" min="0" max="4" value="0" disabled="disabled"/><span class="range"></span>
</div>
</div>
</div>
</div>
<div class="reqalt3">
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<div>
<label for="trai1">My trainers technical competence in delivering my training is:</label>
<input class='rangeSlider' id='trai1' name='trai1'type="range" min="0" max="4" value="0"disabled="disabled"/><span class="range"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<label for="trai2">My trainers ability to manage the group during my block release is:</label>
<input class='rangeSlider' id='trai2' name='trai2'type="range" min="0" max="4" value="0" disabled="disabled"/><span class="range"></span>
</div>
</div>
<div class="form-group row">
<div class="col-sm-8 col-sm-offset-2">
<label for="trai3">My trainers ability to help me update my portfolio at the end of each training session is:</label>
<input class='rangeSlider' id='trai3' name='trai3'type="range" min="0" max="4" value="0" disabled="disabled"/><span class="range"></span>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit!</button>
<button type="button" class="btn btn-primary" data-dismiss="modal"><i class="fa fa-times"></i> Close</button>
</form>
Javascript:
Code: var rangeValues ={
"0":"",
"1": "Poor",
"2": "Satisfactory",
"3": "Good",
"4": "Outstanding"
};
$("#feedback").on("show.bs.modal", function (a) {
var b = $(a.relatedTarget);
var c = b.data('prog');
$(".prog").html("<input type='hidden' id='ProgramTitle' name='programTitle' value=\"" + c + '" readonly>');
}), $('.rangeSlider').on("change", function() {
$(this).next().html(rangeValues[$(this).val()]);
});
$('#RatingFor').change(function(){
$('.reqalt')[ ($("option[value='Programme']").is(":checked"))? "show" : "hide" ]();
$('.reqalt2')[ ($("option[value='Assessor']").is(":checked"))? "show" : "hide" ]();
$('.reqalt3')[ ($("option[value='Trainer']").is(":checked"))? "show" : "hide" ]();
($( ".reqalt" ).is( ":hidden" ))? ($( ".reqalt :input" ).removeAttr('required'), $( ".reqalt :input" ).attr('disabled', true)): ($( ".reqalt :input" ).attr('required', true), $( ".reqalt :input" ).removeAttr('disabled', true));
($( ".reqalt2" ).is( ":hidden" ))? ($( ".reqalt2 :input" ).removeAttr('required'), $( ".reqalt2 :input" ).attr('disabled', true)): ($( ".reqalt2 :input" ).attr('required', true), $( ".reqalt2 :input" ).removeAttr('disabled', true));
($( ".reqalt3" ).is( ":hidden" ))? ($( ".reqalt3 :input" ).removeAttr('required'), $( ".reqalt3 :input" ).attr('disabled', true)): ($( ".reqalt3 :input" ).attr('required', true), $( ".reqalt3 :input" ).removeAttr('disabled', true));
});
$("#feedback").on("hidden.bs.modal", function () {
document.getElementById("feedbackform").reset();
$(".reqalt, .reqalt2, .reqalt3").removeAttr("style");
($( ".reqalt" ).is( ":hidden" ))? ($( ".reqalt :input" ).attr('required', true), $( ".reqalt :input" ).removeAttr('disabled', true)):($( ".reqalt :input" ).removeAttr('required'), $( ".reqalt :input" ).attr('disabled', true));
($( ".reqalt2" ).is( ":hidden" ))? ($( ".reqalt2 :input" ).removeAttr('required'), $( ".reqalt2 :input" ).attr('disabled', true)): ($( ".reqalt2 :input" ).attr('required', true), $( ".reqalt2 :input" ).removeAttr('disabled', true));
($( ".reqalt3" ).is( ":hidden" ))? ($( ".reqalt3 :input" ).removeAttr('required'), $( ".reqalt3 :input" ).attr('disabled', true)): ($( ".reqalt3 :input" ).attr('required', true), $( ".reqalt3 :input" ).removeAttr('disabled', true));
$("#inf").children().length > 0 && $("#inf").empty();
$("body").addClass("modal-open");
$(this).find(".range").html('');
});
$('form input').on('keypress', function(e) {
return e.which !== 13;
});
$("#feedbackform").submit(function (a) {
var values = $(this).serializeArray(),
filled;
for (var i = 2; i < values.length; i++) {
if(values[i].value === '0'){filled = false; break;}
}
if(filled === false){
if(!$("#inf .msg-no").length){
document.getElementById("inf").innerHTML = "<div class=\"msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Please Complete All Required Fields!<a href='#' class='close' data-dismiss='alert' aria-label='close'>×</a></div>";
}
} else{
$.ajax({
url: window.location.href + "theme/mytheme/Scripts/feedbackapi.php",
type: "POST",
data: values,
success: function (a) {
if (document.getElementById("inf").innerHTML = a, $("#inf div").hasClass("msg-yes")) {
document.getElementById("feedbackform").reset();
$(".reqalt, .reqalt2, .reqalt3").removeAttr("style");
($( ".reqalt" ).is( ":hidden" ))? ($( ".reqalt :input" ).removeAttr('required'), $( ".reqalt :input" ).attr('disabled', true)): ($( ".reqalt :input" ).attr('required', true), $( ".reqalt :input" ).removeAttr('disabled', true));
($( ".reqalt2" ).is( ":hidden" ))? ($( ".reqalt2 :input" ).removeAttr('required'), $( ".reqalt2 :input" ).attr('disabled', true)): ($( ".reqalt2 :input" ).attr('required', true), $( ".reqalt2 :input" ).removeAttr('disabled', true));
($( ".reqalt3" ).is( ":hidden" ))? ($( ".reqalt3 :input" ).removeAttr('required'), $( ".reqalt3 :input" ).attr('disabled', true)): ($( ".reqalt3 :input" ).attr('required', true), $( ".reqalt3 :input" ).removeAttr('disabled', true));
$("#feedbackform").find(".range").html('');
}
},
error: function(a){
alert(a);
}
});
}
a.preventDefault();
});
My Feedbackapi.php:
PHP Code: <?php session_start(); if($_SERVER['REQUEST_METHOD'] == 'POST'){ function createPath($path) { if (is_dir($path)) return true; $prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 ); $return = createPath($prev_path); return ($return && is_writable($prev_path)) ? mkdir($path) : false; } function putToFile($dataList){ $year = date("Y"); $month = date("m"); $plugin_folder_name = 'hello-world'; $plugin_folder_path = "../../../plugins/".$plugin_folder_name.'/'; $path = $plugin_folder_path.$year.'/'.$month.'/'; if(createPath($path)){ $filename = $path."vish.csv"; if (file_exists($filename)) { $file = fopen($filename,"a"); foreach ($dataList as $line) { fputcsv($file,explode(',',$line)); } fclose($file); $sucessmsg = "<div class=\"msg-yes alert alert-success alert-dismissable\"><strong>Success!</strong> Thank you for your Feedback. <a href='#' class='close' data-dismiss='alert' aria-label='close'>×</a></div>"; echo($sucessmsg); } else{ $ourFileHandle = fopen($filename, 'w') or exit("can't open file"); $headers = ['Apprenticeship_Programme', 'Rating', 'Programme_Performance', 'Quality_Of_Programme','Programme_Communication_Quality','Assessor_Performance','Assessor_Contact_Frequency','Assessor_Feedback','Trainer_Technical_Competence','Trainer_Management_Ability','Trainer_Help_Ability']; fputcsv($ourFileHandle, $headers); fclose($ourFileHandle); putToFile($dataList); } } else { exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); } } if (isset($_SESSION['last_submit']) && time()-$_SESSION['last_submit'] < 30){exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Please wait at least 30 seconds before another submit<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>');}else{$_SESSION['last_submit'] = time();}
if(empty($_POST['programTitle']) || empty($_POST['RatingFor'])) { exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong>Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); } else{ $progTitle = isset( $_POST['programTitle'] ) ? filter_var($_POST["programTitle"], FILTER_SANITIZE_STRING): ''; if(empty($progTitle)){ exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); } else{ $rating = isset( $_POST['RatingFor'] ) ? filter_var($_POST["RatingFor"], FILTER_SANITIZE_STRING): ''; $whitelist = array('Programme', 'Assessor','Trainer'); if (in_array($rating, $whitelist)) { switch($rating){ case "Programme": $progq1 = isset( $_POST['progq1'] ) && filter_var($_POST['progq1'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["progq1"] : '';
switch($progq1){ case "1": $progq1 = "poor"; break; case "2": $progq1 = "Satisfactory"; break; case "3": $progq1 = "Good"; break; case "4": $progq1 = "Outstanding"; break; default: $progq1 = ''; }
$progq2 = isset( $_POST['progq2'] ) && filter_var($_POST['progq2'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["progq2"] : '';
switch($progq2){ case "1": $progq2 = "poor"; break; case "2": $progq2 = "Satisfactory"; break; case "3": $progq2 = "Good"; break; case "4": $progq2 = "Outstanding"; break; default: $progq2 = ''; }
$progq3 = isset( $_POST['progq3'] ) && filter_var($_POST['progq3'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["progq3"] : '';
switch($progq3){ case "1": $progq3 = "poor"; break; case "2": $progq3 = "Satisfactory"; break; case "3": $progq3 = "Good"; break; case "4": $progq3 = "Outstanding"; break; default: $progq3 = ''; }
if(empty($progq1) || empty($progq3) || empty($progq3)){ exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); }else{ $progData = array("{$progTitle},{$rating},{$progq1},{$progq2},{$progq3},null,null,null,null,null,null"); putToFile($progData); } break; case "Assessor": $asq1 = isset( $_POST['asq1'] ) && filter_var($_POST['asq1'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["asq1"] : '';
switch($asq1){ case "1": $asq1 = "poor"; break; case "2": $asq1 = "Satisfactory"; break; case "3": $asq1 = "Good"; break; case "4": $asq1 = "Outstanding"; break; default: $asq1 = ''; }
$asq2 = isset( $_POST['asq2'] ) && filter_var($_POST['asq2'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["asq2"] : '';
switch($asq2){ case "1": $asq2 = "poor"; break; case "2": $asq2 = "Satisfactory"; break; case "3": $asq2 = "Good"; break; case "4": $asq2 = "Outstanding"; break; default: $asq2 = ''; }
$asq3 = isset( $_POST['asq3'] ) && filter_var($_POST['asq3'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["asq3"] : '';
switch($asq3){ case "1": $asq3 = "poor"; break; case "2": $asq3 = "Satisfactory"; break; case "3": $asq3 = "Good"; break; case "4": $asq3 = "Outstanding"; break; default: $asq3 = ''; }
if(empty($asq1) || empty($asq2) || empty($asq3)){ exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); }else{ $asqData = array("{$progTitle},{$rating},null,null,null,{$asq1},{$asq2},{$asq3},null,null,null"); putToFile($asqData); } break; case "Trainer": $trai1 = isset( $_POST['trai1'] ) && filter_var($_POST['trai1'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["trai1"] : '';
switch($trai1){ case "1": $trai1 = "poor"; break; case "2": $trai1 = "Satisfactory"; break; case "3": $trai1 = "Good"; break; case "4": $trai1 = "Outstanding"; break; default: $trai1 = ''; }
$trai2 = isset( $_POST['trai2'] ) && filter_var($_POST['trai2'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["trai2"] : '';
switch($trai2){ case "1": $trai2 = "poor"; break; case "2": $trai2 = "Satisfactory"; break; case "3": $trai2 = "Good"; break; case "4": $trai2 = "Outstanding"; break; default: $trai2 = ''; }
$trai3 = isset( $_POST['trai3'] ) && filter_var($_POST['trai3'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 4)) ) ? $_POST["trai3"] : '';
switch($trai3){ case "1": $trai3 = "poor"; break; case "2": $trai3 = "Satisfactory"; break; case "3": $trai3 = "Good"; break; case "4": $trai3 = "Outstanding"; break; default: $trai3 = ''; }
if(empty($trai1) || empty($trai2) || empty($trai3)){ exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); }else{ $traiData = array("{$progTitle},{$rating},null,null,null,null,null,null,{$trai1},{$trai2},{$trai3}"); putToFile($traiData); } break; } } else{ exit('<div class="\msg-no alert alert-warning alert-dismissable\"><strong>Warning!</strong> Something went wrong! Please try again.<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a></div>'); } } } }
?>
Now, in the plugin I have the line: $message = $row > 1 ? "<a href='../{$rel_plugin_folder_path}{$year}/{$month}/vish.csv' download>Download Current months feedback spreadsheet</a>" : "No Feedback available for download!"; which if more than one row in csv will echo out a downloadable link. Clicking this link however results in forbidden.
I would like to know if my approach here is correct and in get simple what would be the best way to allow the csv file to be downloaded ?
|