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
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?
As mentioned in the title. I try to change the image source to a default image, if an image's expiration date is expired.
I used ACF and added a new date field to all media files.
I then created the following function:
function check_expiration_date($post) {
$url = get_the_post_thumbnail_url($post->ID);
$thumbnail_id = get_post_thumbnail_id( $post->ID );
$today = date('d/m/Y');
$expire = get_field('expiration_date', $thumbnail_id);
if( $expire < $today && $expire!="" )
{
$url = "default.jpg";
}
return $url;
}
Now this function works for images that I add sepcifically in template files
but this will not work for images that have been added via the editor on post pages.
I tried to to use various hooks to change the html markup first before attempting to get the meta information but none of those had any effect on the outcome. Here an example:
function change_image_markup($html, $id, $caption, $title, $align, $url) {
$html5 = "<section>";
$html5 .= "<figure id='post-$id media-$id' class='align-$align'>";
$html5 .= "<img src='$url' alt='$title' />";
if ($caption) {
$html5 .= "<figcaption>$caption</figcaption>";
}
$html5 .= "</figure>";
$html5 .= "<section>";
return $html5;
}
add_filter( 'image_send_to_editor', 'change_image_markup', 10, 9 );
Is there a specific hook that can alter the html markup of images?
I am using Wordpress 5.5.1
any hint or tip is appreciated.
As the question is a month old and I did not receive any answers, I figured I would answer my own question. There is a difference in the requirements though. Instead of changing the image to a default one, I removed the image completely. Both can be achieved though.
So there was no real hook that could me out, as those hooks only call the action when actually inserting the image.
In my case everytime the post is being loaded the images had to be checked if they are expired or not.
Instead of working with hooks I created my own function and call that function inside single.php
In the single.php usually there is something like echo post->post_content;
Instead I call my function and give the post content as a value.
add_post_based_on_expiration_date($post->post_content);
And my function looks something like this:
function add_post_based_on_expiration_date($post_content){
$search_pattern = '/<figure(.*)\/figure>/'; //<figure(.*)/figure> /wp-image-(\d+)/
preg_match_all( $search_pattern, $post_content, $embedded_images );
$embedded_images_count = count( $embedded_images[0] );
$new_content = $post_content;
if ( $embedded_images_count > 0 ) {
for ( $i=0; $i < $embedded_images_count ; $i++ ) {
$dom = new DOMDocument;
#$dom->loadHTML($embedded_images[0][$i]);
$image = $dom->getElementsByTagName('img');
$imageId = str_replace("wp-image-" , "" , $image[0]->getAttribute('class'));
if(check_expiration_date_get_by_id($imageId)){
$new_content = str_replace($embedded_images[0][$i],"",$new_content);
}
};
};
echo $new_content;
}
It looks a bit messy but it does it's job. What I do is using regex to look for the image mark up <figure..... and save it in an array. Afterwards by using the DOM class I get the class, which contains the media ID. Then I call my function which is an alteration of the one above in the question. The function just returns true or false depeding on the expiration date. If it is true I remove it from the content and at the end I return it.
Therefore if an image is expired the image markup gets completely removed.
The downside of this aside from the messy code is the processing time. Since it it always called when opening a post site.
I'm trying to create a custom field that when the editor loads, the pages/posts featured image url would be populated in the post if it exists. The ACF Docs for the load_field function all revolve around using selects and not a normal text field.
I have tried to do something similar like so:
function my_acf_load_field( $field ) {
$file = get_post_meta( $attachment_id, '_wp_attached_file', true );
$field['feat_image_file_name'] = $file;
return $field;
}
// name
add_filter('acf/load_field/name=feat_image_file_name', 'my_acf_load_field');
The page doesn't populate with the value (even though the post does have a feat image assigned). Any help to point me in the right direction would be great. Thank you.
Found the solution thanks to another developer helping me. Solution below:
/* ---------------------------------------------------------------------------
* AUTO-POPULATE ACF Field with FEATURED IMAGE URL PATH
* --------------------------------------------------------------------------- */
function getThumbURL()
{
$myfile = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ));
$finalresult = "";
if(count($myfile) > 0 && is_string($myfile[0]))
{
// get the domain site url and strip it out of the result for relative path only
$domain = get_site_url();
$finalresult = str_replace($domain, '', $myfile[0]);
}
else
{
// Placeholder image if no feat image assigned
$finalresult = '/dir/to/placeholder/img.jpg';
}
return $finalresult;
}
function my_acf_update_value( $value, $post_id, $field ) {
$value = getThumbURL();
return $value;
}
add_filter('acf/update_value/name=feat_image_file_name', 'my_acf_update_value', 10, 3);
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!
I have a WordPress Admin page where you can add a "listing" within this Admin Page I have added many fields which transfer variables over to the listing page which is created/updated. Within this admin page I am trying to take the string after the last "&" in the url which is manually enter in the url before loading the page
see code below:
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$id = substr( $url, strrpos( $url, '&' )+1 );
NOW the code below here is called when the ABOVE admin page is submitted to update the "listing" what I need to do is somehow get the variable $id to pass through to this function and be used again within the submit code. Both of these functions are within functions.php so somehow it should be easy to do this!
This may not be "Wordpress Specific" but is a Wordpress Specific situation where I had this code working on a non-wordpress site. Please help!
$dirname = "../wp-content/themes/Explorable/".$id."/";
$images = glob($dirname."*.jpg");
// Open a known directory, and proceed to read its contents
foreach($images as $image) {
$imageNameLong = substr($image, -14);
$imageName = substr($imageNameLong,0 , -4);
if ( isset( $_POST[$imageName.'links'] ) )
update_post_meta( $post_id, '_'.$imageName.'links', sanitize_text_field( $_POST[$imageName.'links'] ) );
else
delete_post_meta( $post_id, '_'.$imageName.'links' );
if ( isset( $_POST[$imageName.'heading'] ) )
update_post_meta( $post_id, '_'.$imageName.'heading', sanitize_text_field( $_POST[$imageName.'heading'] ) );
else
delete_post_meta( $post_id, '_'.$imageName.'heading' );
};