I have added a bunch of new fields to my checkout form in woocommerce. it reads in the finished php file as such;
<form name="checkout" method="post" class="checkout woocommerce-checkout processing" action="http://localhost:100/wordpress/checkout/" enctype="multipart/form-data" style="position: relative; zoom: 1;">
<div id="pagePreview">
<input type="file" name="CheckoutImageUpload">
<div class="BBtextInputFrontend">
<input class="BBTextBoxFront" placeholder="placeholder">
<input class="BBInitialValue BBData" type="text" name="BBInitialValue[]">
</div>
<div class="BBtextInputFrontend">
<input class="BBTextBoxFront" placeholder="placeholder">
<input class="BBInitialValue BBData" type="text" name="BBInitialValue[]">
</div>
</div>
<!-- the rest is the default woocommerce billing inputs -->
<div class="col2-set" id="customer_details">
<div class="col-1">
<div class="woocommerce-billing-fields">
<h3>Billing Details</h3>
the problem is that the input
<input type="file" name="CheckoutImageUpload">
never returns a value in the $_FILES array. in fact, the $_FILES array always returns an empty array. I can get the other values through $_POST with no issue. but not files. putting the plugin on a fresh install on another separate computer yields the exact same results.
I'm currently using this code to find the values:
function add_image($order_id) {
//if they DID upload a file...
if ($_FILES['CheckoutImageUpload']['name']) {
?>Y<?php
die();
}
else {
?>N<?php
die();
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'add_image', 100, 1);
can anyone help? I feel like I'm losing my mind
The complete code mentioned I've added below. what you see above is a shortening of it while keeping the important parts.
<?php
/*
#package BBPlugin
#wordpress_plugin
Plugin Name: Brave books book preview plugin
Plugin URI: null
Description: Allows the user to single out words to be replaced for a preview in a book.
Author: Goodship
Version: 0.0.2
Author URI: www.Goodship.co.za
*/
// If this file is called directly, abort execution.
if ( ! defined( 'WPINC' ) ) {
die;
}
ini_set('error_reporting', E_ALL);
// This will attach the file needed for the class which defines
// meta boxes, their tabs, views and partial content.
require_once plugin_dir_path( __FILE__ ) . 'admin/class-BBPlugin.php';
/**
The class that represents the meta box that will display
the navigation tabs and each of the fields for the meta box.
*/
require_once plugin_dir_path( __FILE__ ) . 'admin/class-BBPlugin-meta-box.php';
/*
Execute the plugin.
Everything for this particular plugin will be done so from within
the Author_Commentary/admin subpackage. This means that there is no reason to setup
any hooks until we're in the context of the Author_Commentary_Admin class.
#since 0.0.1
*/
/*
This will create an instance of the BBPlugin_Admin class
from the class file mentioned previously as soon as the plugin is activated,
After accepting the plugin name and version parameters.
*/
add_shortcode("BB", "BraveBooksShortCode");
function BraveBooksShortCode( $atts, $content = null , $checkout) {
$inputDiv = '<div class="BBtextInputFrontend">
<input class="BBTextBoxFront" type="text" placeholder="'.$content.'" />
<input class="BBInitialValue BBData" type="text" name="BBInitialValue[]" />
</div>';
return $inputDiv;
}
function Run_BBPlugin() {
$BBPlugin = new BBPlugin_Admin('BB-Plugin', '0.0.1');
$BBPlugin->initialize_hooks();
}
Run_BBPlugin();
wp_register_style( 'postStyles', '/'.'wp-content/plugins/BBPluginv2/admin/assets/css/BBClasses.css' );
wp_enqueue_style('postStyles');
wp_enqueue_script( 'jquery' );
function load_my_script(){
wp_register_script(
'functions',
'/wp-content/plugins/BBPluginv2/admin/assets/js/functions.js' ,
array( 'jquery' )
);
wp_enqueue_script( 'functions' );
}
add_action('wp_enqueue_scripts', 'load_my_script');
function woo_redirect_to_checkout() {
$checkout_url = WC()->cart->get_checkout_url();
return $checkout_url;
}
add_filter ('woocommerce_add_to_cart_redirect', 'woo_redirect_to_checkout');
function check_if_cart_has_product( $valid, $product_id, $quantity ) {
global $woocommerce;
$woocommerce->cart->empty_cart();
$woocommerce->cart->add_to_cart($product_id,0);
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'check_if_cart_has_product', 10, 3 );
function change_add_to_cart_loop( $product ) {
global $product; // this may not be necessary as it should have pulled the object in already
return 'READ MORE';
}
add_filter( 'woocommerce_loop_add_to_cart_link', 'change_add_to_cart_loop' );
function woo_custom_cart_button_text() {
return __( 'Buy this book', 'woocommerce' );
}
add_filter( 'woocommerce_product_single_add_to_cart_text', 'woo_custom_cart_button_text' ); // 2.1 +
function wc_remove_all_quantity_fields( $return, $product ) {
return true;
}
add_filter( 'woocommerce_is_sold_individually', 'wc_remove_all_quantity_fields', 10, 2 );
function wc_add_to_cart_message_filter($message, $product_id = null) {
$message = sprintf( 'Please remember to enter your details before purchase.');
return $message;
}
add_filter ( 'wc_add_to_cart_message', 'wc_add_to_cart_message_filter', 10, 2 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order , $order_id){
global $woocommerce, $post;?>
<div class="order_data_column">
<h4><?php _e( 'Words used' ); ?></h4>
<?php
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
echo '<p>' .json_encode(get_post_meta($product_id, 'BBPlugin-Pages', true) ). '</p>';
echo '<p>' .json_encode(get_post_meta($post->ID, 'your_key', true) ). '</p>';
}
$pageJSONData = json_encode(get_post_meta($product_id, 'BBPlugin-Pages', true));
$wordsJSONData = json_encode(get_post_meta($post->ID, 'your_key', true));
?>
<script type='text/javascript'>
var pageArray = <?php echo $pageJSONData ?>;
var wordsArray = <?php echo $wordsJSONData ?>;
</script>
Create PDF
</div>
<?php
}
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );
/*
** Getting an image to upload
*/
function add_image($order_id, $posted) {
$sanitized_input_data = array();
$inputsData = $_POST['BBInitialValue'];
$filesData = $_FILES['CheckoutImageUpload'];
$testLog = fopen("testicle.txt","w") or exit ("Unable to open file!");
fwrite ($testLog , "added files: " . $_FILES['CheckoutImageUpload']['name']);
foreach ( $inputsData as $inputsBoxNumber => $inputBoxData ) {
$inputArray = explode( "|", $inputBoxData );
if ( ! empty( $inputBoxData ) ) {
$BBData = array(
'shortcode' => $inputArray[0],
'word_used' => $inputArray[1]
);
fwrite ($testLog , "found files: " . $inputArray[0]);
$sanitized_input_data[ $inputsBoxNumber ] = $BBData;
}
}
fclose ($testLog);
update_post_meta( $order_id, 'your_key', $sanitized_input_data);
//if they DID upload a file...
if ($_FILES['CheckoutImageUpload']['name']) {
//if no errors...
if (!$_FILES['CheckoutImageUpload']['error'] ) {
$valid_file = true;
//now is the time to modify the future file name and validate the file
$new_file_name = strtolower($_FILES['CheckoutImageUpload']['tmp_name'] ); //rename file
if ($_FILES['CheckoutImageUpload']['size'] > ( 1024000 ) ){ //can't be larger than 1 MB
$valid_file = false;
$message = 'Oops! Your file\'s size is to large.';
echo $message;
die();
}
//if the file has passed the test
if ( $valid_file ) {
//move it to where we want it to be
//copy( $_FILES['CheckoutImageUpload']['tmp_name'], plugin_dir_path( __FILE__ ) . 'admin' );
$message = 'Congratulations! Your file was accepted.';
echo $message;
$BBdirectory = wp_upload_dir();
$BBdirectory = $BBdirectory['path'] .'/'. $order_id .'/';
if (!file_exists($BBdirectory)) {
mkdir($BBdirectory, 0777, true);
if (move_uploaded_file($_FILES['CheckoutImageUpload']['tmp_name'], $BBdirectory . $_FILES["CheckoutImageUpload"]['name'])) {
echo "Uploaded";
die();
} else {
echo "File was not uploaded";
die();
}
}
}
} //if there is an error...
else {
//set that to be the returned message
$message = 'Ooops! Your upload triggered the following error: ' . $_FILES['CheckoutImageUpload']['error'];
echo $message;
}
}
else {
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'add_image', 99, 2);
//add_action( 'woocommerce_checkout_update_order_meta', 'add_image');
/*
function platoon_add_order_meta( $order_id, $posted ) {
$sanitized_input_data = array();
$inputsData = $_POST['BBInitialValue'];
foreach ( $inputsData as $inputsBoxNumber => $inputBoxData ) {
$inputArray = explode( "|", $inputBoxData );
if ( ! empty( $inputBoxData ) ) {
$BBData = array(
'shortcode' => $inputArray[0],
'word_used' => $inputArray[1]
);
$sanitized_input_data[ $inputsBoxNumber ] = $BBData;
}
}
update_post_meta( $order_id, 'your_key', $sanitized_input_data);
}
add_action( 'woocommerce_checkout_update_order_meta', 'platoon_add_order_meta', 99, 2 );
*/
function add_checkout_notice() {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$item = end($items)['data']->post->ID;
$pages = get_post_meta( $item, 'BBPlugin-Pages', true );
echo '<div id="pagePreview">';
echo '<input type="file" name="CheckoutImageUpload" />';
foreach ( $pages as $pageNumber=>$pageData ) {
if ($pageData["page_type"] == "text_only"){
$designedData = $pageData["text"];
$designedData = do_shortcode ( $designedData, false );
echo $designedData;
}
else if ($pageData["page_type"] == "2up"){
$designedData = $pageData["text"];
$designedData = do_shortcode ( $designedData, false );
echo $designedData;
}
}
echo '</div>';
?>
<script>
function Test(){
<?php
/*
$testLog = fopen("testicle.txt","w") or exit ("Unable to open file!");
fwrite ($testLog , "added files: " . $_FILES['CheckoutImageUpload'] . $_POST['BBInitialValue']);
fclose ($testLog);
*/
?>
}
</script>
<a onclick="Test()" class="btn">Call PHP Function</a>
<?php
}
add_action( 'woocommerce_checkout_before_customer_details', 'add_checkout_notice');
/*
** end of image upload
*/
?>
I've also included the code below for debugging, and it also returns nothing, so it isn't exclusive to the action.
?>
<script>
function Test(){
<?php
$testLog = fopen("testicle.txt","w") or exit ("Unable to open file!");
fwrite ($testLog , "added files: " . $_FILES);
fclose ($testLog);
?>
}
</script>
<a onclick="Test()" class="btn">Call PHP Function</a>
<?php
"#Fred -ii- I used that link you added to get all the errors and I received this error: [Thu Mar 31 12:23:09.121930 2016] [:error] [pid 11208:tid 1248] [client 127.0.0.1:51335] PHP Notice: Undefined index: CheckoutImageUpload in Z:\Work\J00028 - Brave books plugin\Wordpress stack\apps\wordpress\htdocs\wp-content\plugins\BBPluginv2\BBPlugin.php on line 290, referer: http://localhost:100/wordpress/product/a-book/ Does this help? – Captain Dando"
Your file's name attribute is name="checkoutupload" but you're using $_FILES['CheckoutImageUpload'] throughout your code.
So, to keep you from changing all of the $_FILES['CheckoutImageUpload'] to the named attribute, simply change the file name attribute to name="CheckoutImageUpload".
Also make sure that the folder you are uploading to has the correct path and that it has the proper permissions to write to it.
do check var_dump($_FILES); for debugging
check $_FILES['yourFieldName']['error'] for file upload errors. php stores any errors encountered during upload, allocation, etc in ['errors']
$_FILES is an array so fwrite ($testLog , "added files: " . $_FILES); wont work var_dump should work best most of the time. (for silent debugging use a recursive foreach loop)
should you encounter errors in $_FILES['yourFieldName']['error'], most of the time the filesize is to big (php.ini) or the folder is not writeable
try the following:
function add_image($order_id) {
//var_dump($_FILES);
$errors = array();
if (
!isset($_FILES['CheckoutImageUpload']['error']) ||
is_array($_FILES['CheckoutImageUpload']['error'])
) {
$errors[] = 'Invalid file.';
}
switch ($_FILES['CheckoutImageUpload']['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
$errors[] = 'you sent no file';
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$errors[] = 'file too big'
default:
$errors[] = 'unknown error';
}
// check filesize manually
if ($_FILES['CheckoutImageUpload']['size'] > 50000) { // whatever your php.ini says
$errors[] = 'file too big';
}
return json_encode($errors);
}
Also try small text files for dev purposes. If big files fail increase these php.ini values:
max_input_time
max_execution_time
upload_max_filesize
post_max_size
session.gc_maxlifetime
I'd simplify and just test a simple file upload first
Here is a sample. Save it as test_upload.php and access it directly through your web server to test file uploads.
<?php
// test_upload.php
// Tests php file upload capabilities
if($_SERVER['REQUEST_METHOD'] == 'POST') {
echo "<pre>";
print_r($_FILES);
exit();
}
?>
<form enctype="multipart/form-data" method='post' action=''>
<input type='file' name='file' />
<input type='submit' value='submit form' />
</form>
If this doesn't work, you need to check your php.ini and also make sure that the configured temporary directory is writable by the web server.
You can find your system's temporary directory by running the following:
php -B 'echo sys_get_temp_dir(); echo "\n"; exit();'
As this is a ajax method, you need to add a ajax method to upload the files as the settings are slightly different. I think the performance of this will be poor but see what you think!
You need to check a few things in the script
1. I think i have used the correct identifer for the form (classname="checkout") examine your outputted html to ensure this is correct
2. This will only work with 1 file upload on the page, modify jQuery(document) if you need to narrow this down
3. Ajaxurl -- read the notes in the code, i'd recommend you check this first before trying the script
jQuery(form.checkout).on('submit', function(){
var fd = new FormData();
//searches the whole document, i am assuming you only need 1 file uploaded
var file = jQuery(document).find('input[type="file"]');
var individual_file = file[0].files[0];
fd.append("imagefile", individual_file);
fd.append('action', 'upload_image');
jQuery.ajax({
type: 'POST',
url: ajaxurl, // nb-----------------have you got a variable for ajaxurl? if not insert var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>'; somewhere in your template...or google the wp way!
data: fd,
contentType: false,
processData: false,
success: function(response){
//just spit out the response to the console to catch php errors etc..
console.log(response);
}
});
});
In your functions.php...
function upload_image(){
echo 'action had been called';
var_dump($_FILES);
// work with files!
}
add_action('wp_ajax_upload_image', 'upload_image');
add_action('wp_ajax_nopriv_upload_image', 'upload_image');
Did you dump the $_FILES completly?
Maybe you have an other field with the same form name.
If you would have posted the complet form it would be easier (as already mentioned).
Another reason might be, that your php stack doesn't have write permission to the upload folder and then returns nothing.
Check your server logs.
It might tell you what happened.
Something else I just thought off.
Use Crome and check what requests have been fired.
But make shure that you hightlited the checkbox in the network section to persist the session.
Your Browser might reload the page without you recognizing it.
:)
Related
I'm trying to make a plugin to add a column to print some pdf files using the library fpdf using the code:
function rz_listing_pdf_column($columns) {
$columns['pdf'] = __( 'PDF', 'text_domain' );
return $columns;
}
add_filter( 'manage_rz_listing_posts_columns', 'rz_listing_pdf_column' );
function rz_listing_pdf_column_content($column, $post_id) {
if ( $column == 'pdf' ) {
$pdf_link = plugins_url('pdf.php?id=' . $post_id, __FILE__);
echo 'Download';
}
}
add_action( 'manage_rz_listing_posts_custom_column', 'rz_listing_pdf_column_content', 10, 2 );
this should open "pdf.php?id=" or print a PDF file using the post meta values of the clicked post, my issue it's that if I try to use
require_once plugin_dir_path(__FILE__) . 'fpdf/fpdf.php';
doesn't work, so neither I can't use:
$player1_birthday = get_post_meta($post_id, 'rz_player1_birthday', true);
because it's not reading anything coming from Wordpress, I'm new on this so I know I'm doing something wrong, any help?
I am attempting to upload a PDF from a custom Wordpress plugin. Expected behavior is to create a custom post type manual, and upload a PDF from my computer.
The PDF should save in wp_content/uploads/manuals/
Currently when I save a manual post type, the $_POST data is received by savePost(), however no $_FILES data is sent, so I don't have access to save files.
I have checked php.ini that file upload is allowed, and confirmed that proper permissions are set on the folders for the plugin to upload files. I've also tested locally and on two different shared hosting providers. I have also tested that other plugins are able to upload pdfs to this specific directory successfully. Have also checked that the file size is under the maximum file size allowed.
The only errors I'm receiving are related to $_FILES being null. I can see the file listed in the $_POST data however, as ["file"]=> string(9) "dummy.pdf"
//create the manuals custom post type
function create_custom_post_type() {
register_post_type( 'manuals',
array(
'labels' => array(
'name' => __( 'Manuals' ),
'singular_name' => __( 'Manual' )
),
'public' => true,
'has_archive' => true,
'supports' => array( 'title','custom_fields'),
)
);
}
add_action( 'init', 'create_custom_post_type' );
//add the manuals box to post page
function manuals_meta_box() {
add_meta_box( 'manuals_meta_box',
'Manuals PDF',
'display_manuals_meta_box',
'manuals', 'normal', 'high'
);
}
add_action( 'add_meta_boxes', 'manuals_meta_box' );
//display html on the meta box
function display_manuals_meta_box( $manual ) {
$saveLocation = ABSPATH.'/wp-content/uploads/manuals';
if (!file_exists(ABSPATH.'/wp-content/uploads/manuals')) {
mkdir(ABSPATH.'/wp-content/uploads/manuals', 0777, true);
}
//see if this has been uploaded before
$file = esc_html( get_post_meta( $manual->ID, 'file', true ) );
?>
<p><?php echo $file?$file:'File: Not set';?></p>
<form method="POST" enctype="multipart/form-data">
<?php wp_nonce_field(plugin_basename(__FILE__), 'custom-nonce'); ?>
<input type="file" name="file">
<input id="submit" class="submitBtn mfInput" name="submit" type="submit" placeholder="">
</form>
<?php
}
//on post save, try to save the pdf selected
function savePost( $manual_id, $manual ) {
//security checks
if(!wp_verify_nonce($_POST['custom-nonce'], plugin_basename(__FILE__))) {
return $manual_id;
}
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $manual_id;
}
if ( $manual->post_type == 'manuals' ){
if(!current_user_can('edit_page', $manual_id)) {
return $manual_id;
}
} else {
if(!current_user_can('edit_page', $manual_id)) {
return $manual_id;
}
}
if ( !function_exists('media_handle_upload') ) {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
}
moveTheFile($_FILES['file']);
}
//move from tmp to actual file location
function moveTheFile($file){
$moved = move_uploaded_file($file['tmp_name'], ABSPATH . "/wp-content/uploads/manuals/" . $file['name']);
if( $moved ) {
echo "Successfully uploaded";
} else {
wp_die(var_dump($_FILES).'<br><br>'.var_dump($_POST));
}
}
add_action( 'save_post', 'savePost', 10, 2 );
Errors I receive are:
Trying to access array offset on value of type null
Undefined array key "file"
Trying to access array offset on value of type null
move_uploaded_file(): Passing null to parameter #1 ($from) of type string is deprecated
I was trying to add an image field to the woocommerce account settings section so that users could upload their avatars.
With a bit of research here on stack I came across this question that worked and gave the solution to my problem: Add a profile picture (file upload) on My account > edit account in WooCommerce
However, other questions have arisen and I have thought about extending the question to try to improve the final result as I believe it is a very common situation.
So I hope someone can answer this.
Will the uploaded image not appear for the post comments section or woocommerce product reviews? Do we need to change the meta image for this? It would be very useful to be able to view the uploaded image anywhere on the site, including the comments and reviews section.
If the user wants to remove the image and go back to the default how can he do it? There is no remove image button. Is there a way to insert a button and remove the image uploaded ?
Is there a way to set upload limit? For example, uploaded images must be jpeg or png and must not exceed 1mb in size.
The biggest problem is the directory where the images are saved, can it be different from the default media library? Furthermore, when the user changes multiple images, the previous one is not deleted and will remain forever in the media library taking up space unnecessarily.
I believe the answer to these questions completes something that the woocommerce world lacks by default. This may be a standard solution for most users.
For convenience, I report the code of the previous question:
// Add field
function action_woocommerce_edit_account_form_start() {
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="image"><?php esc_html_e( 'Image', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
</p>
<?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );
// Validate
function action_woocommerce_save_account_details_errors( $args ){
if ( isset($_POST['image']) && empty($_POST['image']) ) {
$args->add( 'image_error', __( 'Please provide a valid image', 'woocommerce' ) );
}
}
add_action( 'woocommerce_save_account_details_errors','action_woocommerce_save_account_details_errors', 10, 1 );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
// Add enctype to form to allow image upload
function action_woocommerce_edit_account_form_tag() {
echo 'enctype="multipart/form-data"';
}
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );
To display the image (can be used anywhere, provided you adjust the desired hook)
// Display
function action_woocommerce_edit_account_form() {
// Get current user id
$user_id = get_current_user_id();
// Get attachment id
$attachment_id = get_user_meta( $user_id, 'image', true );
// True
if ( $attachment_id ) {
$original_image_url = wp_get_attachment_url( $attachment_id );
// Display Image instead of URL
echo wp_get_attachment_image( $attachment_id, 'full');
}
}
add_action( 'woocommerce_edit_account_form', 'action_woocommerce_edit_account_form' );
// Save
function action_woocommerce_save_account_details( $user_id ) {
if ( isset( $_FILES['image'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
function wp_set_custom_upload_folder($uploads) {
$uploads['path'] = $uploads['basedir'] . '/custom-folder';
$uploads['url'] = $uploads['baseurl'] . '/custom-folder';
if (!file_exists($uploads['path'])) {
mkdir($uploads['path'], 0755, true);
}
return $uploads;
}
add_filter('upload_dir', 'wp_set_custom_upload_folder');
$attachment_id = media_handle_upload( 'image', 0 );
if ( is_wp_error( $attachment_id ) ) {
update_user_meta( $user_id, 'image', $_FILES['image'] . ": " . $attachment_id->get_error_message() );
} else {
$old_attachment_id = get_user_meta( $user_id, 'image', true );
wp_delete_attachment($old_attachment_id);
update_user_meta( $user_id, 'image', $attachment_id );
}
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
Set custom upload directory for profile image uploads
// Display function
function action_woocommerce_edit_account_form() {
// Get current user id
$user_id = get_current_user_id();
// Get attachment id
$attachment_id = get_user_meta($user_id, 'image', true);
// True
if ($attachment_id) {
$original_image_url = wp_get_attachment_url($attachment_id);
// Display Image instead of URL
echo wp_get_attachment_image($attachment_id, 'full');
if (isset($_GET['rm_profile_image_id'])) {
if ($attachment_id == $_GET['rm_profile_image_id']) {
wp_delete_attachment($attachment_id);
delete_user_meta($user_id, 'image');
?> <script>
window.location='<?php echo wc_get_account_endpoint_url('edit-account') ?>';
</script>
<?php
exit();
}
} else {
echo '<a href=' . wc_get_account_endpoint_url('edit-account') . '?rm_profile_image_id=' . $attachment_id . '> ' . __('Remove') . ' </a>';
}
}
}
When I have some free time I want to work on these issues. I'm not very good with codes I'm just a fan, but with study, research and practice I hope to make my contribution to this topic.
I publish this answer to update it every time I find a new solution. I'm sure someone can offer more efficient solutions, so corrections and answers that improve the topic are welcome.
Solution to problem n1 - Set the uploaded image anywhere on the site
Set the get_avatar filter (responsible for displaying the avatar in the comments section and other section of website) and assign it the url stored in the image meta_key.
add_filter( 'get_avatar', 'my_custom_avatar', 10, 6 );
function my_custom_avatar( $avatar, $id_or_email, $size, $default, $alt, $args ) {
// What is the custom image field's meta key?
// Set this value to match the meta key of your custom image field.
$meta_key = "image";
// Nothing really to change below here, unless
// you want to change the <img> tag HTML.
$user = false;
if ( is_numeric( $id_or_email ) ) {
$user = get_user_by( 'id' , (int)$id_or_email );
}
elseif ( is_object( $id_or_email ) ) {
if ( ! empty( $id_or_email->user_id ) ) {
$id = (int)$id_or_email->user_id;
$user = get_user_by( 'id' , $id );
}
} else {
$user = get_user_by( 'email', $id_or_email );
}
if ( $user && is_object( $user ) ) {
$post_id = get_user_meta( $user->ID, $meta_key, true );
if ( $post_id ) {
$attachment_url = wp_get_attachment_url( $post_id );
// HTML for the avatar <img> tag. This is WP default.
$avatar = wp_get_attachment_image($post_id, $size = array('50', '50'));
}
}
return $avatar;
}
Solution to problem n3 - Set a size limit for files
Thanks to this question Limit the size of a file upload (html input element) I found the solution to limit the file size in bytes. So here's what I did:
I assigned the input type file the id file
<input id="file" type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg">
I then applied the script below
/* Limit File Size for Avatar Upload (size in bytes) */
var uploadField = document.getElementById("file");
uploadField.onchange = function() {
// Put size in Bytes
if(this.files[0].size > 100000){
alert("File is too big!");
this.value = "";
};
};
The code provided by #mujuonly looks promising, however, please take the following into consideration:
Add a remove_filter after the else block in 1st code. Else all the website uploads will happen in that directory.
To do so, use:
remove_filter('upload_dir', 'wp_set_custom_upload_folder');
after else block.
2nd code should check if the user meta was deleted successfully or not. The line delete_user_meta($user_id, 'image'); should be wrapped in if condition like so:
if (delete_user_meta($user_id, 'image')){
wp_delete_attachment($attachment_id);
}
This way you don't delete the image first and make it unavailable for failed delete_user_meta.
I can't figure out what I'm doing wrong! I want the function to return a freshly-created variable with a true/false value that I can use to see if we've got the file or not.
// Check to make sure external files are available
function checklink ( $link, $checkname ) {
$try_url = #fopen( $link,'r' );
if( $try_url !== false ) { return $$checkname; }
}
var_dump( checklink( 'https://code.jquery.com/jquery-3.3.1.min.js', 'jqueryOK' ) ); // NULL
I've tried setting $checkname to true or false, adding an extra line to give it a value before return ... PHP 'knows' there is a variable $jqueryOK but says it's undefined.
What am I missing?
UPDATE
Decided to share the outcome, as this is often an overlooked thing in Wordpress - and am changing the title to reflect the task.
// Check to make sure external files are available
function checklink ($link) {
return( bool )#fopen( $link, 'r' );
}
function thatwomanuk_external_scripts()
{
if ($GLOBALS['pagenow'] != 'wp-login.php' && !is_admin()) {
// jquery
$link = 'https://code.jquery.com/jquery-3.3.1.min.js';
if( checklink( $link ) ) { // true - otherwise, Wordpress will load its own
wp_deregister_script('jquery'); // remove jQuery v1
wp_register_script('jquery', $link, array(), '3.3.1', true); // add jQuery v3
wp_enqueue_script('jquery');
wp_script_add_data( 'jquery', array( 'integrity', 'crossorigin' ), array( 'sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=', 'anonymous' ) );
}
// google fonts
$link = 'https://fonts.googleapis.com/css?family=Raleway:300,400,400i,500|Ubuntu:300,400,400i,500&subset=latin-ext';
$fallback = get_template_directory_uri() . '/fonts/thatwoman-fonts-min.css';
if( checklink( $link ) ) {
wp_enqueue_style( 'custom-google-fonts', $link, false );
} else {
wp_enqueue_style( 'custom-google-fonts', $fallback, false );
}
// touch events library
$link = 'https://cdnjs.cloudflare.com/ajax/libs/jquery-touch-events/1.0.5/jquery.mobile-events.js';
$fallback = get_template_directory_uri() . '/js/lib/jquery.mobile-events.min.js';
if( checklink( $link ) ) {
wp_register_script('thatwoman-touch-events', $link, array( 'jquery' ), '1.0.5', true);
} else {
wp_register_script('thatwoman-touch-events', $fallback, array( 'jquery' ), '1.0.5', true);
}
wp_enqueue_script('thatwoman-touch-events');
}
}
add_action( 'wp_enqueue_scripts', 'thatwomanuk_external_scripts' );
Thanks to #u_mulder for making me see sense.
You should simplify your function to:
// Check to make sure external files are available
function checklink ($link) {
return (bool)#fopen( $link,'r');
}
After that in your code:
$link1Available = checklink($link1);
$link2Available = checklink($link2);
// etc
Or as an array:
$links = ['link1', 'link2', 'link3'];
$linksAvailable = [];
foreach ($links as $link) {
$linksAvailable[$link] = checklink($link);
}
If you just want to have a local fallback for a CDN loaded js file, you can use wp_scripts()->add_inline_script() which was added in 4.5, to add a js check if the library was loaded, see my detailed answer on wordpress.stackexchange here.
The short version:
You can use wp_scripts()->add_inline_script(), which will append a js script to an enqueued script, no questions asked, no code problems checked (there is a wrapper function wp_add_inline_script that does checks but does not permit </script> tags, even encoded).
This is a working example
function _enqueue_my_scripts() {
// the normal enqueue
wp_enqueue_script( 'jquery-cdn', 'https://code.jquery.com/jquery-3.3.1.min.js' );
// our custom code which will check for the existance of jQuery (in this case)
wp_scripts()->add_inline_script( 'jquery-cdn',
"window.jQuery || document.write('<script src=\"".get_template_directory_uri() ."/js/jQuery.js\">\\x3C/script>')", 'after');
}
add_action('wp_enqueue_scripts', '_enqueue_my_scripts', 100);
which will give you
<script type='text/javascript' src='https://code.jquery.com/jquery-3.3.1.min.js'></script>
<script type='text/javascript'>
window.Swiper || document.write('<script src="http://localhost/wordpress/wp-content/themes/wp-theme/js/jQuery.js">\x3C/script>')
</script>
in your HTML.
Replace 'window.jQuery' and '/js/jQuery.js' according to your needs but don't touch the rest of the line as it is meant to pass through the correct line to the HTML.
You have double $$ sign in return statement:
if( $try_url !== false ) { return $$checkname; }
there is a button on my settings that once clicked it will prompt to download a csv file. Here is the code.
<?php
/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_plugin_menu' );
/** Step 1. */
function my_plugin_menu() {
add_options_page( 'Members Log Data',
'Members Log',
'manage_options',
'sj-member-option',
'members_option' );
}
/** Step 3. */
function members_option() {
if ( !current_user_can( 'manage_options' ) )
{
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
}
$name = "member-log-".date('Y-m-d');
$list[] = array('username','no of favorites');
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=' . $name);
$op = fopen('php://output','w');
foreach($list as $row)
{
fputcsv($op,$row);
}
fclose($op);
/*
echo '<div class="wrap">';
echo '<p>Here is where the form would go if I actually had options.</p>';
echo '</div>';
*/
}
I am getting can not modify session header.
I would like to ask how to do this in WP as I am familiar outside of it.
You're trying to send a header command too late, hence the error. Use the hook load-(your_page) for this kind of output.
function my_plugin_menu() {
$page = add_options_page( 'Members Log Data',
'Members Log',
'manage_options',
'sj-member-option',
'members_option' );
add_action( "load-$page", 'do_export' );
}
In the members_option function callback add a <form> with a submit button and in the new do_export function you'll put the export actions. Something like bellow, note that I'm not checking for the nonce, but for security best practices you should do it instead of checking for $_POST['submit'].
function members_option() {
if ( !current_user_can( 'manage_options' ) )
{
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
}
?>
<form method='post' >
<p class="submit">
<?php wp_nonce_field('my-import'); ?>
<input type='submit' name='submit' value='Restore'/>
</p>
</form>
<?php
}
function do_export() {
if( isset( $_POST['submit'] ) && 'Restore' == $_POST['submit'] )
{
$name = "member-log-".date('Y-m-d');
$list[] = array('username','no of favorites');
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=' . $name);
$op = fopen('php://output','w');
foreach($list as $row)
{
fputcsv($op,$row);
}
fclose($op);
}
}
In my tests, the export result was an HTML file with the full contents of the page plus the 'username','no of favorites' that you defined, but this is a matter for another question/research.