Skip to content
This repository was archived by the owner on Nov 24, 2022. It is now read-only.

Commit b79622f

Browse files
authored
Merge pull request #72 from ckingbailey/feat/clean-csv
decode html entities and use new Export module for defs download
2 parents 2cc388f + 16bb894 commit b79622f

File tree

4 files changed

+91
-4
lines changed

4 files changed

+91
-4
lines changed

api/def.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
use SVBX\Export;
3+
4+
require 'vendor/autoload.php';
5+
require 'session.php';
6+
7+
if (strcasecmp($_SERVER['REQUEST_METHOD'], 'POST')) {
8+
header('Access-Control-Allow-Methods: POST', true, 405);
9+
exit;
10+
}
11+
12+
try {
13+
// check Session vars against DB
14+
$link = new MySqliDB(DB_CREDENTIALS);
15+
$fields = [ 'username', 'userID', 'firstname', 'lastname', 'role' ];
16+
17+
$link->where('userID', $_SESSION['userID']);
18+
$result = $link->getOne('users_enc', $fields);
19+
20+
if ($result['username'] !== $_SESSION['username']
21+
|| $result['role'] !== $_SESSION['role']
22+
|| $result['firstname'] !== $_SESSION['firstname']
23+
|| $result['lastname'] !== $_SESSION['lastname'])
24+
{
25+
header('Status: 403 Forbidden', true, 403);
26+
exit;
27+
}
28+
29+
// if Auth ok, validate fields on first data element of POST against fields in DB
30+
// note: element at index 0 is heading names, not table data
31+
$post = trim(file_get_contents('php://input'));
32+
$post = json_decode($post, true);
33+
$post = filter_var_array($post, FILTER_SANITIZE_SPECIAL_CHARS);
34+
35+
$link->where('table_name', 'CDL');
36+
$link->orWhere('table_name', 'BARTDL');
37+
$cols = $link->getValue('information_schema.columns', 'column_name', null); // returns 50+ columns
38+
$cols = array_map('strtolower', $cols);
39+
40+
$postKeys = array_keys($post[1] + $post[count($post) - 1] + $post[floor((count($post) / 2))]); // grab keys from first, middle, and last element of post data
41+
42+
if (($idIndex = array_search('ID', $postKeys)) !== false) unset($postKeys[$idIndex]); // don't try to match ID col name
43+
44+
foreach ($postKeys as $key) {
45+
if (array_search(strtolower($key), $cols) === false) {
46+
header('Status: 400 Bad Request', true, 400);
47+
exit;
48+
}
49+
}
50+
51+
header('Content-Type: text/csv', true);
52+
53+
echo Export::csv($post);
54+
} catch (\Exception $e) {
55+
error_log($e);
56+
header('500 Internal server error', true, 500);
57+
} catch (\Error $e) {
58+
error_log($e);
59+
header('500 Internal server error', true, 500);
60+
} finally {
61+
if (is_a($link, 'MySqliDB')) $link->disconnect();
62+
exit;
63+
}

src/Export.php

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ public static function csv($data) {
1111
private static function str_putcsv(array $input, $delimiter = ',', $enclosure = '"') {
1212
$pointer = fopen('php://temp', 'r+b'); // open memory stream with read/write permission and binary mode on
1313
foreach ($input as $line) {
14+
$line = array_map(function($el) {
15+
return html_entity_decode($el, ENT_QUOTES, 'utf-8');
16+
}, $line);
1417
fputcsv($pointer, $line, $delimiter, $enclosure); // puts a single line
1518
}
1619
rewind($pointer);

templates/dashboard.html.twig

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
}).then(text => {
132132
const date = new Date()
133133
const timestamp = date.getFullYear()
134-
+ '' + date.getMonth()
134+
+ '' + (date.getMonth() + 1)
135135
+ '' + date.getDate()
136136
+ '' + date.getHours()
137137
+ '' + date.getMinutes()

templates/defs.html.twig

+24-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,30 @@
2727
<script src='js/pie_chart.js'></script>
2828
<script>
2929
document.getElementById('getCsvBtn').addEventListener('click', event => {
30-
const jsonData = {{ dataWithHeadings | json_encode | raw }}
31-
getCsv(event, jsonData, res => {
32-
download(res, `def_dump_${Date.now()}.csv`, 'text/csv')
30+
const json = JSON.stringify({{ dataWithHeadings | json_encode | raw }})
31+
fetch('/api/def.php', {
32+
method: 'POST',
33+
body: json,
34+
credentials: 'same-origin',
35+
headers: {
36+
'Content-type': 'application/json',
37+
'Accept': 'text/csv'
38+
}
39+
}).then(res => {
40+
if (!res.ok) throw res
41+
return res.text()
42+
}).then(text => {
43+
const d = new Date()
44+
const timestamp = d.getFullYear()
45+
+ '' + (d.getMonth() + 1)
46+
+ '' + d.getDate()
47+
+ '' + d.getHours()
48+
+ '' + d.getMinutes()
49+
+ '' + d.getSeconds()
50+
download(text, `defs_summary_${timestamp}.csv`, 'text/csv')
51+
}).catch(err => {
52+
if (err.status) console.err(`${err.status} ${res.statusText} ${res.url}`)
53+
else console.err(err)
3354
})
3455
})
3556
{% if view is same as('BART') %}

0 commit comments

Comments
 (0)