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:
My form:
Javascript:
My Feedbackapi.php:
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 ?
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 ?