While using woocommerce_process_product_meta hook how to debug? - php

I need to store informations in a custom product type.
I correctly created the form, and I'm using the hook woocommerce_process_product_meta to save the custom informations about this product.
In the same function, I am doing a file upload, like this. The basic informations are saved, but the upload does not work.
add_action( 'woocommerce_process_product_meta', 'save_my_custom_settings' );
function save_my_custom_settings( $post_id ){
echo "test";
//Save options
update_post_meta( $post_id, 'my_custom_option', esc_attr( $_POST[ 'my_custom_option' ] ) );
/*
* Upload the file
*/
if ( $_FILES["my_file"] ) {
$path_parts = pathinfo( $_FILES["my_file"]["name"] );
$extension = $path_parts['extension'];
$stored_file_name = time() . '.' . $extension;
$storage_dir = dirname( __FILE__ ) . '/downloads';
$target_file = $storage_dir . '/' . $stored_file_name;
if ( !move_uploaded_file($_FILES["my_file"]["tmp_name"], $target_file) ) {
echo "Sorry, there was an error uploading your file.";
} else echo "File transfer ok";
/*
* Store information on the file
*/
update_post_meta( $post_id, 'my_file_name', $stored_file_name );
} else echo "File missing!!";
}
I know the directory exists and that the function is called, since the other options are correctly saved. However, the file simply isn't uploaded.
I'm sure I could debug this myself, the problem is that I don't know how to display any notifications, so I don't know what is wrong. As you can see, in the sample above I tried to use an "echo", but I can't see that output.
What can I use to display a notification when the product is saved, so I know what is going on?

To debug in Wordpress you should first read the following: Debugging in Wordpress.
Also read: Debugging WooCommerce PHP with Javascript console.log doesn't work
Now there is multiple tricks/ways to get the data. I use this sometimes like in your case:
For example you can use some temporary meta fields to store any debug data for the current order, with Wordpress function update_post_meta().
Then you will be able to output related data with get_post_meta() or look directly in database in wp_postmeta table for your temporary debug custom fields keys…

Don't know if this is the answer, but your if statement has $_FILES["my__file"] but the other lines have $_FILES["my_file"] so there's a discrepancy in the naming there!

Related

use plugin_dir_path on a secondary php inside plugin folder

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?

Print content if first ACF Repeater field is empty

I’m trying to make a simple document management system with ACF's repeater field. I need to print a button to download a file attached to the the top repeater field (with the size and filetype of the download). But if the top repeater field is empty, it should print “file not available” content.
I’m pretty new to PHP but this mostly works so far:
$repeater = get_field( 'document' )[0];
if( $repeater ) {
$fileurl = $repeater[ 'document' ][ 'url' ];
$filesize = filesize( get_attached_file ($repeater[ 'file' ][ 'id' ]) );
$filesize = size_format($filesize);
$filetype = wp_check_filetype( get_attached_file ($repeater[ 'file' ][ 'id' ]));
$download = '<div>Download<div>' . $filesize . ' <span>' . $filetype[ 'ext' ] .'</span></div></div>' ;
echo $download;
}
This prints a button to the attached file in the top repeater, when there is an attached file in the top repeater. Only it prints out a dead link if there is nothing in the top repeater. This won’t do. I need to add an else condition or something so that it prints "file not available" content if there is nothing in the first repeater.
if(empty( $repeater )) {
$unavailable = '<div>Unavailable<div>This document isn\'t ready yet. Please check back later.</div></div>' ;
echo $unavailable;
}
I've tried a lot of different ways to do this, such as above, and I don't know what I'm doing wrong. Can you help?
You have to check for a value before displaying field like that :
if( get_field('document'){
... // there is an attached file
}
else {
$unavailable = '<div>Unavailable<div>This document isn\'t ready yet. Please check back later.</div></div>' ;
echo $unavailable;
}
I think they had your case at the ACF support forum: https://support.advancedcustomfields.com/forums/topic/if-repeater-field-if-empty-else-doesnt-work/
I finally got it! I think I wasn't declaring my variables clearly enough.
$row = get_field( 'document' );
$first_row = $row[0];
$first_row_file = $first_row[ 'file' ];
if( $first_row_file ) :
$download = '<div>Available!<div>This document is ready for download.</div></div>' ;
echo $download;
else :
$unavailable = '<div>Unavailable!<div>This document isn\'t ready yet. Please check back later.</div></div>' ;
echo $unavailable;
endif;
Now I can add more sophisticated content (like a download button) to display when there is a file to download, and a helpful message when there isn't.

Custom Upload Directory does not change attachment meta

I'm trying to make a download script for a password protected wordpress site. To make use of PHPs readfile() function I need to retrieve the full attachment URL based on it's ID i am passing to the download script.
I made a Custom Post Type named Downloads and also changed it's upload directory to a folder inside wp-content also named downloads.
Here is the code for it:
add_filter( 'upload_dir', 'custom_upload_directory' );
function custom_upload_directory( $args ) {
$id = $_REQUEST['post_id'];
$parent = get_post( $id )->post_parent;
if( "downloads" == get_post_type( $id ) || "downloads" == get_post_type( $parent ) ) {
$args['path'] = WP_CONTENT_DIR . '/downloads';
$args['url'] = WP_CONTENT_URL . '/downloads';
}
return $args;
}
Upload works fine and when I click the link to the desired file, the ID is passed to a script via $_POST, which also works fine. But I just can't figure out a way to get the right file URL. Here's what I tried:
wp_get_attachment_url( $id ); // returns: example.com/wp-content/uploads/html/theme/wp-content/downloads/filename.ext
wp_get_attachment_link( $id ); // returns: slug
get_attachment_link( $id ); // returns: example.com/downloads/file (without .ext)
get_attached_file( $id, true ); // returns: html/theme/wp-content/downloads/filename.ext
get_post_meta( $id, '_wp_attached_file', false ); // returns: html/theme/wp-content/downloads/filename.ext
wp_get_attachment_metadata( $id ); // returns nothing
What I expected any of those functions to return was example.com/wp-content/downloads/filename.ext
But as you can see, some mix up the default upload directory and combine it with the new one while others just return half of the full URL (html/theme/... it's the directory the website sits on the server). So any ideas would be appreciated.
Hours, days and even weeks later I finally found an answer and modified it to fit my needs. I came as far as displaying the right URL (the modified one) inside the file upload lightbox of Wordpress. But after publishing/updating the post it went back to the same old .../wp-content/uploads/file.ext URL.
Someone else, somewhere else got exactly the same problem and fortunately it is said there, that you must not just alter $args['path'] and $args['url'] but you also have to alter basedir, baseurl and subdir.
So, the complete code to change a custom post types upload directory (in this case I chose the directory .../wp-content/downloads) is the following:
add_filter( 'upload_dir', 'change_upload_dir' );
function change_upload_dir( $args ) {
$id = $_REQUEST['post_id'];
if( get_post_type( $id ) == 'downloads' ) {
$args['basedir'] = wp_normalize_path( WP_CONTENT_DIR . 'downloads' );
$args['baseurl'] = content_url() . '/downloads';
$args['path'] = $args['basedir'];
$args['url'] = $args['baseurl'];
$args['subdir'] = '';
return $args;
}
}
So now, calling wp_get_attachment_url() finally results in something like example.com/wp-content/downloads/file.ext

WordPress: Functions inside while loop with variable in the name

I'm trying to create a PHP while loop for WordPress that populates content to some Gravity Forms fields. I'm using Advanced Custom Fields with a repeater field to get the content and then trying to use eval() to create functions inside the while loop, like this:
if( have_rows( 'tickets', 'option' ) ) :
while( have_rows( 'tickets', 'option' ) ) : the_row();
$shortname = get_sub_field('short_name');
$image = get_sub_field('image');
add_filter( 'gform_field_value_' . $shortname . '_img', 'populate_' . $shortname . '_img' );
eval("
function populate_{$shortname}_img( $value ) {
return $image;
}
");
endwhile;
endif;
The problem is that I'm getting this error:
Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'populate_test_img' not found or invalid function name in /srv/www/nordstan/htdocs/wp-includes/plugin.php on line 235
(I'm getting multiples of these, of course, and one of the $shortname variables are "test".)
However, if I'm changing "return $image" to "return 'test'", no error message is printed and the whole thing is executed correctly, so the functions are created.
What am I doing wrong?
Thanks in advance!
Change the order...because your eval doesn't run until after the add_filter, add_filter is failing to find the function (that doesn't exist until run time).
$shortname = get_sub_field('short_name');
$image = get_sub_field('image');
eval("
function populate_{$shortname}_img( $value ) {
return '$image';
}
");
add_filter( 'gform_field_value_' . $shortname . '_img', 'populate_' . $shortname . '_img' );
also note that $image is a string and needs to be treated as such in the context of that eval'd code.

ignore text because of echo´ing image?

I´m drawing an image in PHP from another website, which works. And I´m getting info and from a webpage, which is working. But together it isn´t and only shows the image.
If I cut the picture part and put it at the end it gives an error.
(Use for example nickname Mazey if you need to check out how that JSON page look like)
Has it to do with combining file get contents and my curl function?
<?php
$profPic = json_decode( file_get_contents( 'https://api.kag2d.com/player/'.urlencode( $_GET['nickname'] ).'/avatar/s' ) );
if ( $profPic ) {
if ( isset( $profPic->small ) ) {
$profPic = $profPic->small;
$extension = strtolower( pathinfo( $profPic, PATHINFO_EXTENSION ) );
$content = file_get_contents( $profPic );
if ( $content ) {
header( "Content-type: image/".$extension );
echo $content;
exit();
}
}
} else {
echo "error";
}
$stats = json_decode(file_get_contents('https://api.kag2d.com/player/'.urlencode( $_GET['nickname'] ).'/status' ));
if ( $stats ) {
if ( isset ( $stats->playerInfo ) ) {
echo $stats->playerInfo->username;
} else {
echo 'Error';
}
} else {
echo 'Error';
}
?>
You are attempting to return two different HTTP responses in the same file. If you read the section for images, it does an exit() after printing the image data. This why it stops processing.
When I ran the URLs included in the source, the username returned is the same as the value in the $_GET['nickname']. Do you actually need to look this value up? It would work if you just returned the image.
A solution is to return a JSON document like your third party server is doing, and embed all the information in this. It is legal HTML to have image data as an URL, so the entire thing could be returned as single JSON document. HTML based example from the RFC2397
<IMG SRC="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAA
AMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZt
fzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbt
LiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYG
ejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3i
q9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXy
ym7PHhhx4dbgYKAAA7" ALT="Larry">
Unlike email, noone seems to be developing multi-part mime responses inside HTTP. I did a quick google, but no useful results.

Categories