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' );
};
Related
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'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
On my WordPress website, I have an archive page e.g.: http://www.example.com/2017. My archive.php file has a query to show posts as well as two custom post types: case-studies and media:
global $wp_query;
$args = array_merge( $wp_query->query, array( 'post_type' => array('post','case-studies','media'), 'posts_per_page' => 3 ) );
query_posts( $args );
while ( have_posts() ) : the_post();
The archive page will only show provided there are posts under post (the standard post type that is included within WordPress) otherwise it will 404, even though there are posts under case-studies and media.
Is there a workaround this?
Here is a link to my archive.php for those who are interested: archive.php
I've had this problem before. You can include a function in your functions.php file which can redirect the page to archive.php instead of the usual 404. See if this works:
function wpd_date_404_template( $template = '' ){
global $wp_query;
if( isset($wp_query->query['year'])
|| isset($wp_query->query['monthnum'])
|| isset($wp_query->query['day']) ){
$template = locate_template( 'archive.php', false );
}
return $template;
}
add_filter( '404_template', 'wpd_date_404_template' );
Credit to Milo at the WordPress StackExchange. See his answer here: Preventing 404 error on empty date archive
function wpd_date_404_template( $template = '' ){
global $wp_query;
if(
isset($wp_query->query['year']) ||
isset($wp_query->query['monthnum']) ||
isset($wp_query->query['day'])
) {
$template = locate_template( 'archive.php', false );
if ( isset( $wp_query->query['post_type'] ) ) {
$located = locate_template( 'archive-' . $wp_query->query['post_type'] . '.php', false );
$template = $located !== '' ? $located : locate_template( 'archive.php', false );
}
}
return $template;
}
add_filter( '404_template', 'wpd_date_404_template' );
Just used #Dev1997 his answer to solve the issue. With a small improvement to use the specific template for the current (custom) post_type. Maybe it will help someone who is using custom post types.
I've added multiple featured images to my wordpress site using the multiple post thumbnail plugin. I'm trying to display them all underneath the content with their descriptions. I can do it for the main featured image no problem. I can display the rest of the featured images no problem, but whenever I try to add description by it's the page description not the image description.
This is how I added the main image and description.
<?php the_post_thumbnail( 'product-thumbnail' );
echo get_post(get_post_thumbnail_id())->post_content; ?>
The remaining images are added as such:
<?php MultiPostThumbnails::the_post_thumbnail(get_post_type(), 'secondary-
image', NULL, 'product-thumbnail');
?>
And so forth (third, fourth)..
Can somebody help with how to add the descriptions for the rest?
To display your post thumbnail with its caption, simply paste the following code inside the loop:
<?php the_post_thumbnail();
echo get_post(get_post_thumbnail_id())->post_excerpt; ?>
You can also display entire image description by adding this code inside the post loop:
<?php the_post_thumbnail();
echo get_post(get_post_thumbnail_id())->post_content; ?>
the above codes for single images if you use multiple images use this code below
<?php
$the_post_images = get_children( array(
'post_parent' => $post->ID,
'post_type' => 'attachment',
'post_mime_type'=> 'image'
) );
foreach ($the_post_images as $the_post_image) {
// SHOW FEATURED IMAGE TITLES
echo get_the_title( $the_post_image->ID );
//SHOW IMAGE DESCRIPTION OR CAPTIONS
echo apply_filters( 'get_the_excerpt', $the_post_image->post_excerpt );
}
?>
To get image, its caption in multiple post thumbnails,
`
echo $secondimgPath = MultiPostThumbnails::get_post_thumbnail_url( get_post_type(), 'second-featured-image', NULL);
echo $secondimgIdAttachment = abcd_get_attachment_id_by_url($secondimgPath);
$size = array( 854,395, 'bfi_thumb' => true, 'quality' => 100);
echo $secondLargeImage[0] = wp_get_attachment_image( $secondimgIdAttachment,$size );
echo get_post( $secondimgIdAttachment )->post_excerpt;
endif; ?>`
In functions.php, use the following -
function abcd_get_attachment_id_by_url( $url ) {
// Split the $url into two parts with the wp-content directory as the separator
$parsed_url = explode( parse_url( WP_CONTENT_URL, PHP_URL_PATH ), $url );
// Get the host of the current site and the host of the $url, ignoring www
$this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
$file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
// Return nothing if there aren't any $url parts or if the current host and $url host do not match
if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
return;
}
// Now we're going to quickly search the DB for any attachment GUID with a partial path match
// Example: /uploads/2013/05/test-image.jpg
global $wpdb;
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parsed_url[1] ) );
// Returns null if no attachment is found
return $attachment[0];
}
In magento customization tool, you can put file upload option
but I would like that When you upload an image preview in the screen at least when you click on edit the product
which is the variable of the loaded image?
With The URL of the cart image link:
htt....MY-WEB.com/sales/download/downloadCustomOption/id/107/key/a5cae363d3d6cde2e9c6/
I test with:
img src=..
this URL and display ok, but which is the variable that takes this to interfere with an echo
Here they do with flash but if you do not have flash detected with ajax
http://demo.micosolutions.com/afup/ajax-flash-upload-pro-demo/ajax-flash-uploader-demo.html
I think these are the files that can talk about this:
app/design/frontend/base/default/template/catalog/product/view/options/type/file.phtml
app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Options/Type/file.php
Edit Deleted old answer because I misunderstood the question.
Ok this time I hope I understood correctly what you want. To get the URL of an custom option image from a product that was added to the cart you can get it from quote item:
$item = $this->getItem();
$optionIds = $item->getOptionByCode('option_ids');
if( $optionIds ) {
$options = array();
foreach( explode( ',', $optionIds->getValue() ) as $optionId ) {
$option = $this->getProduct()->getOptionById( $optionId );
if( $option->getData( 'type' ) == 'file' ) {
$option = $item->getOptionByCode( 'option_' . $optionId );
$value = unserialize( $option->getData( 'value' ) );
var_dump( $value );
var_dump( Mage::getUrl( 'sales/download/downloadCustomOption', array( 'id' => $option->getId(), 'key' => $value[ 'secret_key' ] ) ) );
echo '<img src="' . Mage::getUrl( 'sales/download/downloadCustomOption', array( 'id' => $option->getId(), 'key' => $value[ 'secret_key' ] ) ) . '"/>';
}
}
}
Output: It var dumps download url and $value content ($value[ 'fullpath' ] is the location of the image file but it is forbiddon to access it from a browser - you will have to move the file to a different location in media folder where it will be accessable from the web).
echo will show the image.
$item is of type Mage_Sales_Model_Quote_Item (this code was tested in checkout/cart/index controller - your_page_url/index.php/checkout/cart -> code can be added at the top of template/checkout/cart/item/default.phtml file to see how it works).