I have a small problem. On my wordpress based website I want to create an Order-Status form where people can use a code and check their order's progress. It's not an online store so I don't use woocommerce. The file containing the order's progress is a CSV file.
I tried to use that through a function but didn't work. I even tried Javascript but my code can't find the file on server :(
My question is: What language and what technique should I use for my need.
Thank a lot guyz.
I think this is what you are looking for without the need of any libraries:
First You create a form (the form action can be your homepage since we will be listening for the $_GET parameters on init, which is run on every page load):
<form action="<?php echo site_url() ?>">
<input type="hidden" name="csv_export" value="order_status" />
<input type="text" name="code" />
<input type="submit" value="Download Report" name="download_report" />
</form>
Than you need to add an action on init in functions.php to listen for the get parameter csv_export in order to start your functionality to prepare the csv file and output it for download: (we are using the exit(); function after we create csv to make sure that nothing else runs after this process.)
function check_for_export() {
if ( isset( $_GET['csv_export'], $_GET['code'] ) && $_GET['csv_export'] == 'order_status' ) {
ob_end_clean();
export_order_status_csv( $_GET['code'] );
exit();
}
}
}
add_action('init', 'check_for_export');
Now you can start the functionality to generate the csv report. This function depends on how you are fetching the data but you can follow this example to set the headers and output the report:
function export_order_status_csv( $code ) {
// Make a DateTime object and get a time stamp for the filename
$date = new DateTime();
$ts = $date->format( "Y-m-d-G-i-s" );
// A name with a time stamp, to avoid duplicate filenames
$filename = "order-statuses-export-$ts.csv";
// Tells the browser to expect a CSV file and bring up the
// save dialog in the browser
header( 'Pragma: public' );
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
header( 'Content-Description: File Transfer' );
header( 'Content-Type: text/csv' );
header( 'Content-Disposition: attachment;filename=' . $filename );
header( 'Content-Transfer-Encoding: binary' );
// This opens up the output buffer as a "file"
$fp = fopen( 'php://output', 'w' );
//This needs to be customised from your end, I am doing a WP_Query for this example
$results = new WP_Query();
if ( $results->have_posts() ) {
//This is set to avoid issues with special characters
$bom = ( chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );
//add BOM to fix UTF-8 in Excel
fputs( $fp, $bom );
// Set the headers of the csv
fputcsv( $fp, [
'orderID',
'orderDate',
'orderTotal'
] );
while ( $results->have_posts() ) {
$results->the_post();
//Here we are inserting the row data per result fetched
fputcsv(
$fp,
[
get_the_ID(),
get_the_date(),
'your_custom_data'
]
);
}
wp_reset_query();
// Close the output buffer (Like you would a file)
fclose( $fp );
} else {
fputcsv( $fp, [ 'No Results' ] );
fclose( $fp );
}
}
When exporting a csv you have to hook to an action which is processed before anything has been outputted. There cannot be any output before creating the csv file since we are updating the headers.
If you want to read the data from a csv file and manipulate it to customise your csv export you can use this function instead of the WP_Query in example above: http://php.net/manual/en/function.fgetcsv.php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
I actually used PHPExcel in a previous project that achieved what you're after, though I see it's been deprecated in favour of PhpSpreadsheet library. So I would use that one!
What both libraries can essentially do (amongst many other things) is parse the spreadsheet and return the relevant information based on what you request.
So you could put your spreadsheet in a separate directory which you then use the PhpSpreadsheet library to extract information from - and present to the customer in whatever way you see fit.
Related
How can I achieve server sent events in WordPress. I have searched a lot about it but not able to figure out how can I implement it. The problem I am facing is SSE only takes header as 'Content-Type:text/plain'. How can I sent some event to js script only when some changes occur in my database through WordPress function?
If I use 'Content-Type:text/plain' in WordPress function whole website will turn into text output.
I am aware that Wordpress has heartbeat API but I don't want that. Currently, I am using ajax pooling to achieve the same task but it is taking a lot of resources.
you can make a custom REST API end point and make something like that:
public function prepare_rest_api_demo_response( $request ){
$args = array(
'numberposts' => 1
);
$last_id = '';
$serverTime = time();
$latest_posts = get_posts( $args );
$last_id = $latest_posts['0']->ID;
do {
$latest_posts = get_posts( $args );
if( $latest_posts['0']->ID > $last_id ){
$response = new WP_REST_Response($this->compile_sendMsg_in_apiendpoint_for_SSE($serverTime,$latest_posts,$last_id), 200);
break;
}
// break the loop if the client aborted the connection (closed the page)
if ( connection_aborted() ) {
$response = new WP_REST_Response('data: {connection: "closed"}'."\n\n", 503);
break;
}
sleep(2);
// If we didn't use a while loop, the browser would essentially do polling
// every ~3seconds. Using the while, we keep the connection open and only make
// one request.
} while(true);
$response->header( 'Content-Type', 'text/event-stream' );
$response->header( 'Cache-Control', 'no-cache' );
//$response->header( 'Access-Control-Allow-Origin', '*' );
$response->header( 'Accept', 'application/json' );
return $response;
}
and this function for compile the response in the correct way
private function compile_sendMsg_in_apiendpoint_for_SSE($id, $msg, $lastitemid) {
$msg = json_encode($msg);
echo "id: $id" . "\n";
echo "retry: 1500" . "\n";
//echo "event: nameofevent" . "\n"; // if you need some name for event uncomment that line
echo "data: $msg". PHP_EOL;//use \n instead of PHP_EOL for add another line data: if is the same data object https://www.html5rocks.com/en/tutorials/eventsource/basics/#toc-js-api
echo PHP_EOL;
ob_flush();
flush();
}
How can I protect against injection when updating the post_meta using ajax and update_post_meta() in WordPress? I am worried the user input on my site makes it vulnerable to injection and other nasty stuff i can't think of.
I am new to WordPress development and web development.
I am building a system where the user can log in and update various information about their business which then gets saved to the MySQL database(in the future I will get this data using the WordPress REST API from a client app). So I build the profile page and made a form for the user input and then send the data using ajax and WordPress' update_post_meta() function. This is my ajax callback:
/**
* AJAX Callback
* Always Echos and Exits
*/
function lla_update_profil_meta_callback() {
// Ensure we have the data we need to continue
if( ! isset( $_POST ) || empty( $_POST ) || ! is_user_logged_in() ) {
// If we don't - return custom error message and exit
header( 'HTTP/1.1 400 Empty POST Values' );
echo 'Could Not Verify POST Values.';
exit;
}
// Get our current post ID
$post_id = lla_get_post_id();
if($post_id != null){
//get all the values from $_POST
$um_val = sanitize_text_field($_POST['kategori_id'] ) ;
$selected_term_data = get_term((int)$um_val);
$new_post_title = sanitize_text_field($_POST['post_title']);
//these are the values and im guessing it should be here i protect against injection?
$new_beskrivelse = $_POST['beskrivelse'];
$new_telefon = $_POST['telefon'];
$new_email = $_POST['email'];
$new_website = $_POST['website'];
$new_vejnavn = $_POST['vejnavn'];
$new_husnummer = $_POST['husnummer'];
$new_salside = $_POST['salside'];
$new_postnummer = $_POST['postnummer'];
$new_by = $_POST['by'];
update_post_meta( $post_id, 'kategori_id', $um_val);
update_post_meta($post_id, 'beskrivelse', $new_beskrivelse);
update_post_meta($post_id, 'telefon', $new_telefon);
update_post_meta($post_id, 'email', $new_email);
update_post_meta($post_id, 'website', $new_website);
update_post_meta($post_id, 'vejnavn', $new_vejnavn);
update_post_meta($post_id, 'husnummer', $new_husnummer);
update_post_meta($post_id, 'salside', $new_salside);
update_post_meta($post_id, 'postnummer', $new_postnummer);
update_post_meta($post_id, 'by', $new_by);
//make sure the category chosen is updated in the backend aswell
wp_set_object_terms($post_id, (int)$um_val, $selected_term_data->taxonomy, false);
//updating post-title
$my_post = array(
'ID' => $post_id,
'post_title' => $new_post_title,
'post_name' => $new_post_title,
);
wp_update_post($my_post);
}else{
echo "no post";
}
exit;
}
add_action( 'wp_ajax_nopriv_um_cb', 'lla_update_profil_meta_callback' );
add_action( 'wp_ajax_um_cb', 'lla_update_profil_meta_callback' );
How can I make this more secure?
use functions like:
esc_sql();
esc_attr();
esc_html();
Also see Validating Sanitizing and Escaping User Data
Example:
$new_beskrivelse = esc_sql($_POST['beskrivelse']);
$new_telefon = esc_sql($_POST['telefon']);
$new_email = esc_sql($_POST['email']);
$new_website = esc_sql($_POST['website']);
In Php, I encoded a JSON array from MySQL table . i want to decode it in different Php file . and i want to access the data through JavaScript from different file. anyone please help me.
MY code is:
$serverName = "(local)";
$connectionInfo = array( "Database"=>"sample");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn )
{
echo "Connection established.<br/>";
}
else
{
echo "Connection could not be established.<br/>";
die( print_r( sqlsrv_errors(), true));
}
$str="Select * from sam1";
$res=sqlsrv_query($conn,$str) or die("Error !");
$response=array();
while( $row = sqlsrv_fetch_array( $res, SQLSRV_FETCH_ASSOC) )
{
$response['tdata'][]=$row;
}
print(json_encode($response));
Output is :
{"tdata":[{"id":"1","name":"aaa"},{"id":"2","name":"bbb"},{"id":"3","name":"ccc"}]}
My decode Function is:
$data = file_get_contents('db2.php');
$data1 = json_decode($data, true);
print($data1);
but its not working..
When you return JSON encoded string it is best if you send a proper headers. You should return JSON like that (you can still use print function):
<?php
header('Content-Type: application/json');
echo json_encode($data);
Now, when you retrieve this output, send it to json_decode function that will return an object.
json_decode.
file_get_contents function retrieves content of the file, it does not parse it. To retrieve the content of the file:
by calling it with an URL (DO NOT USE THIS ONE I am showing this method for the purpose of learning only, this function wont load URL if allow_url_fopen directive is off, instead you can use curl library (here))
$json = file_get_contents('www.example.com/db2.php');
echo json_decode($json, true);
by including it with a relative path
$json = (include "db2.php");
echo json_decode($json, true);
in this particular scenario, db2.php has to use return statement like so
return json_encode($response);
by using ob_* with include, this time you do not need to return in db2.php file
ob_start();
include "db2.php";
$json = ob_get_contents();
ob_end_clean();
echo json_decode($json, true);
It looks like you're populating $data with the text of db2.php instead of the output from running the file in php. Try this:
$data = `php db2.php`
I'm working on a wordpress page here http://beta.fray.it/invite and on clicking the Twitter icon I have this onclick attribute set on a list element
onclick="window.location.href = '<?php echo get_template_directory_uri(); ?>/components/invite/twitter/redirect.php';">
this takes me to the php file which should redirect users to Twitter for authentication. I got this working on another server I use for testing, but not here. What happens is that I see content from the main page http://beta.fray.it but no redirection. What is the reason for this?
After you enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php (WP_DEBUG is disabled by default since WP_DEBUG is set to false).
debug.log is generated in your /wp-content/ directory upon an error, warning, a notice or a log call.
You can also utilize a wrapper function to centralize your log calls
if(!function_exists('_log')){
function _log( $message ) {
if( WP_DEBUG === true ){
if( is_array( $message ) || is_object( $message ) ){
error_log( print_r( $message, true ) );
} else {
error_log( $message );
}
}
}
}
you can read more about that here
Check out the codex as well:
http://codex.wordpress.org/Debugging_in_WordPress
try changing your link href
onclick='window.location.href =' + "<?php echo get_template_directory_uri(); ?>" + '/components/invite/twitter/redirect.php';
So, I'm working on a plugin that leverages jquery and mysql to dynamically update dropdown boxes.
When the page first loads, the dropdown box should be populated with data selected from mysql. But nothing, apart from the empty dropdown box rendering to the page, works. And no error messages are issued.
What am I overlooking here?
plugins/myplugin/myplugin.php
<?php
/**
* Plugin Name: Test
* Plugin URI:
* Description: This plugin performs dynamic region updates into select boxes in WordPress
* Version: 1.0.0
* Author: Me
* Author Email:
* License: GPL2
*/
function getregions_scripts() {
wp_enqueue_script(
'getregions-script',
plugin_dir_url(__FILE__) . "assets/getregions.js",
array('jquery'),
'1.0',
true
);
wp_localize_script(
'getregions-script', // this needs to match the name of our enqueued script
'gymRegions', // the name of the object
array('ajaxurl' => admin_url('admin-ajax.php')) // the property/value
);
}
add_action( 'wp_enqueue_scripts', 'getregions_scripts' );
add_action( 'wp_ajax_showcountries', 'showcountries_callback' );
add_action( 'wp_ajax_no_priv_showcountries', 'showcountries_callback' );
function showcountries_callback() {
include_once("pdo_mysql.php");
pdo_connect("localhost","user","password");
pdo_select_db("wpdb");
$action=$_POST["action"];
if($action=="showcountries"){
$showcountry = pdo_query("Select country_data from wp_usertable");
if (!$showcountry) {
$message = 'Invalid query: ' . pdo_error() . "\n";
$message .= 'Whole query: ' . $showcountry;
die($message);
}else{
foreach($showcountry as $row){
echo '<option value=".$row[country_code].">.$row[country_name].</option>';
}
}
}
else if($action=="showregions"){
$country_id= $_POST["country_id"];
$showregion = pdo_query("Select region_code, region_name from regiontbl
WHERE country_id=?", pdo_real_escape_string($country_id));
if (!$showregion) {
$message = 'Invalid query: ' . pdo_error() . "\n";
$message .= 'Whole query: ' . $regionquery;
die($message);
}else{
foreach($showregion as $row){
echo '<option value=".$row[region_code].">.$row[region_name].</option>';
}
}
}
}
function showcountries_frontend() {
$the_html = '
<form id="MyForm">
<div style="float: left">
<select id="CountryList" onchange="getRegion()" size="20"></select>
<select id="RegionList" size="20" onchange="getMap()"></select>
</div>
<div id="cityList" style="float: right"></div>
</form>';
return $the_html;
}
add_shortcode("sc_frontend", "showcountries_frontend");
?>
plugins/myplugin/assets/getregions.js
function initialize($) {
.......
feedData($);
}
jQuery(document).ready(function ($) { initialize($); });
function feedData($) {
jQuery(document).ready(function ($) {
var serialized = $('#MyForm').serialize();
$.ajax({
cache: false,
type: "POST",
async: false,
url: "gymRegions.ajaxurl",
data:{action=showcountries, serialized},
success: function (data) {
$('#CountryList').append(data);
},
error: function (data, status, error) {
console.log(data);
console.log(status);
console.log(error);
}
});
});
}
There's a lot going on here that needs to be addressed.
Your ajax call is looking for a location to make the call to; however, you are passing this value:
url: "gymRegions.ajaxurl",
So, the resulting 404 is based on that string: 192.168.0.50/index.php/testing-2/gymRegions.ajaxurl
Localizing a script
In order to pass the location of your plugin directory to your javascript file, you will need to localize the scrip. This can be done in wordpress using the following:
wp_enqueue_( 'getregions-script', plugin_dir_url(__FILE__) . "assets/getregions.js", array('jquery'), '1.0', true);
wp_localize_script( 'getregions-script', 'gymRegions', array('ajaxurl' => plugin_dir_url(__FILE__) . 'assets/getregions-ajax.php'));
This will allow you to call gymRegions.ajaxurl without quotes in your ajax call.
Make your ajax file
Now that this has been completed, you can create a new php file in your plugin: assets/getregions-ajax.php. This file will house your current showcountries_callback function content (does not need to be a function). Whatever is on this page will be executed.
To include wp, I usually use something like this:
header('Content-Type:application/json');
header("X-Robots-Tag: noindex, nofollow", true);
/* find and load wp to avoid duplicating class */
if (file_exists('../../../../wp-load.php')) :
require_once('../../../../wp-load.php');
else:
require_once('../../../../../wp-load.php');
endif;
After this, I will require my class or execute any code.
JSON encode output
Finally, consider JSON encoding your output. Instead of echo-ing everything instantly create an $html variable and at the end of your file:
echo json_encode($html, JSON_PRETTY_PRINT);
Go one step at a time
This may be a little confusing at first but taking it one step at a time will help. Don't try to eat it all in one bite, just focus on getting 'hello world' to return from your ajax call and then build from there.
There may be other issues but this should at least get you started down the right path.
Remove console.log
Then the data will not be get