I'm using wordpress with woocommerce and I've installed a plugin for file uploads, which put into checkout page, when the order was placed. I need this uploader to change the name of uploaded file to the order number current placed. see the picture...
Order Number as file name by upload
This put in woocommerce order number in the front-end site
<?php echo $order->get_order_number(); ?>
In functions.php I have this code as test to handle with file name by uploading:
add_filter('wfu_before_file_upload', 'wfu_before_file_upload_handler', 10, 2);
function wfu_before_file_upload_handler($file_path, $file_unique_id) {
// separate file name from file path
$only_filename = basename($file_path);
$only_filepath = substr($file_path, 0, - strlen($only_filename));
// separate file extension from file name
$dot_pos = strrpos($only_filename, ".");
if ( $dot_pos ) {
$ext_part = substr($only_filename, $dot_pos);
$name_part = substr($only_filename, 0, $dot_pos);
}
// add timestamp to the end of name_part
$current_datetime = gmdate("U");
$only_filename = $name_part . "-" . gmdate("YmdHis", $current_datetime) . $ext_part;
// return the full file path
$file_path = $only_filepath . $only_filename;
return $file_path;
}
This is actually from the plugin developer as example, how to handle file name of uploaded file with wordpress filter.
I would like to make $current_order_number instead of $current_datetime but how I can then get the current order number from database? I've tried following:
$order = get_order_number();
$current_order_number = $order;
$new_filename = $current_order_number . $ext_part;
// return the full file path
$file_path = $only_filepath . $new_filename;
return $file_path;
But it's not working. I still get error message by uploading the file. Any ideas what I'm doing wrong?
Thank you.
Tomas
Related
I am working with wordpress -> contact form 7 and saving the data with contact form 7 to database extension plugin.
The plugin has filters to modify data before saving into database. ([Like This Page])1
now i wanted to save the file into different folder on the server and output link to that file into the admin panel. i used the filter like this.
function cfdbFilterSaveFile($formData) {
// CHANGE THIS: CF7 form name you want to manipulate
$formName = 'DemoReport';
// CHANGE THIS: upload field name on your form
$fieldName = 'Report';
// CHANGE THIS: directory where the file will be saved permanently
$uploaddir = '/home2/username/public_html/example.com/report/wp-content/uploads/reports/';
$urlDir = 'http://example.com/report/wp-content/uploads/reports/';
if ($formData && $formName == $formData->title && isset($formData->uploaded_files[$fieldName])) {
// make a copy of data from cf7
$formCopy = clone $formData;
// breakdown parts of uploaded file, to get basename
$path = pathinfo($formCopy->uploaded_files[$fieldName]);
// directory of the new file
$newfile = $uploaddir . $path['basename'];
// check if a file with the same name exists in the directory
if (file_exists($newfile)) {
$dupname = true;
$i = 2;
while ($dupname) {
$newpath = pathinfo($newfile);
$newfile = $uploaddir . $newpath['filename'] . '-' . $i . '.' . $newpath['extension'];
if (file_exists($newfile)) {
$i++;
} else {
$dupname = false;
}
}
}
// make a copy of file to new directory
copy($formCopy->uploaded_files[$fieldName], $newfile);
// save the path to the copied file to the cfdb database
$formCopy->posted_data[$fieldName] = $newfile;
$path = pathinfo($newfile);
$filelink = '<a href=' . $urlDir . $path['basename'] . '>' . $path['basename'] . '</a>';
$formCopy->posted_data[$fieldName . '-url'] = $filelink;
// delete the original file from $formCopy
unset($formCopy->uploaded_files[$fieldName]);
return $formCopy;
}
return $formData; }
add_filter('cfdb_form_data', 'cfdbFilterSaveFile');
Now with this code the file is saved into the folder on the server as expected but i am not able to output the clickable link to the saved file in the admin panel tables. In place of clickable links the full url is there. As in the screenshot.
ScreenShot
The output is coming as full URL (as marked 1 in screenshot), while i want the url to output as a link to the file (something like 2 in screenshot). I tried to use echo() and sprintf but got php syntex error.
Thanks for the suggestions. I have found alternate way to output links. What I have to do is output the form submission data on a webpage and convert links clickable by javascript as suggested by #Ovidash ... That is a acceptable workaround for my issue. Thanks for all the suggestions.
I'm using Laravel 5.4.*. I've this simple code in a helper file to upload images/gif in S3 bucket under a folder named say "instant_gifs/". The code is below:
if ( !function_exists('uploadFile') ) {
function uploadFile($fileContent, $fileName, $size='full', $disk='s3')
{
$rv = '';
if( empty($fileContent) ) {
return $rv;
}
if($size == 'full') {
dump($fileName);
$path = Storage::disk($disk)->put(
$fileName,
$fileContent,
'public'
);
}
if ( $path ) {
$rv = $fileName;
}
return $rv;
}
}
From the controller, I'm calling the helper method as below:
$file = $request->gif;
$file_name = 'instant_gifs/' . $user_id . '_' . time() . '_' . $file->getClientOriginalName();
$result = uploadFile($file, $file_name);
In the the $fileName parameter of the helper method, I'm providing the fileName as for example in this format:
"instant_gifs/83_1518596022_giphy.gif"
but after the upload, I see that the file gets stored under this folder
"vvstorage/instant_gifs/83_1518596022_giphy.gif/CRm1o1YEcvX3fAulDeDfwT7DIMCxOKG8WFGcA3lB.gif"
with a random file name
CRm1o1YEcvX3fAulDeDfwT7DIMCxOKG8WFGcA3lB.gif
Whereas, according to the code, it should get stored in this path:
"vvstorage/instant_gifs/83_1518596022_giphy.gif"
Doesn't get any explanation why this is happening. Any clue will be appreciated.
BucketName = vvstorage
Folder I'm mimicking = instant_gifs
After some research & testing, found the issue. put() method expects the 2nd parameter as the file contents or stream not the file object. In my code, I was sending the file as $file = $request->gif; or $file = $request->file('gif'); hoping that Storage class will implicitly get the file contents. But to get the expected result, I needed to call the helper method from the controller as below. Notice the file_get_contents() part.
$file = $request->gif;
$file_name = 'instant_gifs/' . $user_id . '_' . time() . '_' . $file>getClientOriginalName();
$result = uploadFile( file_get_contents($file), $file_name );
Now, I got the image correctly stored under the correct path for example in /instant_gifs/9_1518633281_IMG_7491.jpg.
Now, let me compare/summarize the available methods for achieving the same result:
1) put():
$path = Storage::disk('s3')->put(
'/instant_gifs/9_1518633281_IMG_7491.jpg', #$path
file_get_contents($request->file('gif')), #$fileContent
'public' #$visibility
Got it stored in /vvstorage/instant_gifs/9_1518633281_IMG_7491.jpg
2) putFileAs(): To achieve the same thing withputFileAs(), I needed to write it as below. 1st parameter expects the directory name, I left it blank as I'm mimicking the directory name in s3 through the filename.
$path = Storage::disk('s3')->putFileAs(
'', ## 1st parameter expects directory name, I left it blank as I'm mimicking the directory name through the filename
'/instant_gifs/9_1518633281_IMG_7491.jpg',
$request->file('gif'), ## 3rd parameter file resource
['visibility' => 'public'] #$options
);
Got it stored in /vvstorage/instant_gifs/9_1518633281_IMG_7491.jpg
3) storeAs():
$path = $request->file('gif')->storeAs(
'', #$path
'/instant_gifs/9_1518633281_IMG_7491.jpg', #$fileName
['disk'=>'s3', 'visibility'=>'public'] #$options
);
Got it stored in /vvstorage/instant_gifs/9_1518633281_IMG_7491.jpg
Extras::
4) For storing Thumbnails through put(). Example of stream() ...
$imgThumb = Image::make($request->file('image'))->resize(300, 300)->stream(); ##create thumbnail
$path = Storage::disk('s3')->put(
'profilethumbs/' . $imgName,
$imgThumb->__toString(),
'public'
);
Hope that it helps someone.
1.) Why is there vvstorage in the url?
It is appending that route because your root folder inside of your configuration for S3 is set as vvstorage, so whenever you upload to S3 all files will be prepended with vvstorage.
2.) Why random name even when you passed the name of the file?
Because when using put the file will get a unique ID generated and set as it's file name so no matter what you pass, it won't save the file under the name you wanted. But if you use putFileAs then you can override the default behaviour of put and pass a name of the file.
Hope this clarifies it
:) i found this 1 line of code in another post which successfully compresses the image using pngquant. the thing is, it outputs the optimised image with a different name (obviously to preserve the original).
im trying to find a way to:
a) add a minimum quality parameter of 60
b) use an if/else statement to to allow the user to choose to overwrite the existing file or output a new optimised image (of a user specified name)
thank you! ntlri - not to long read it
<?php system('pngquant --quality=85 image.png'); ?>
so what i have tried is the following.. for some reason the single quotes need to be double quotes to parse the variables correctly..
<?php
$min_quality = 60; $max_quality = 85;
$keep_original = 'dont_keep';
if ($keep_original == 'keep') {
$image_name = 'image.png';
$path_to_image = 'images/' . $image_name;
$new_file = 'image2.png';
$path_to_new_image = 'images/' . $new_file;
// don't know how to output to specified $new_file name
system("pngquant --quality=$min_quality-$max_quality $path_to_image");
} else {
$image_name = 'image.png';
$path_to_image = 'images/' . $image_name;
// don't know if you can overwrite file by same name as additional parameter
system("pngquant --quality=$min_quality-$max_quality $path_to_image");
// dont't know how you get the name of the new optimised image
$optimised_image = 'images/' . $whatever_the_optimised_image_is_called;
rename($optimised_image, $image_name);
unlink($optimised_image);
}
?>
from the docs of this program :
The output filename is the same as the input name except that\n\ it
ends in \"-fs8.png\", \"-or8.png\" or your custom extension
so , for this question:
// don't know how to output to specified $new_file name
system("pngquant --quality=$min_quality-$max_quality $path_to_image");
to choose a new name, assume you are compress image name.png :
--ext=_x.png
this will create new image called name_x.png
so , your $new_file would be just a suffix ,
$new_file = '_x.png'; // to choose new file name name_x.png
// don't know if you can overwrite file by same name as additional
parameter
as mentioned in the program docs , the new file name will be suffixed by either -fs8.png or -or8.png , so you may rename the file which will produced with this suffix , OR simply set the --ext option to : .png and this will append to the original file
--ext=.png
for more details, check the repository
i spoke to pornel whos the chappie that developed pngquant. its actually a lot simpler than all that i wrote that before...
! important - it is very important to use escapeshellarg() else people can take over your server by uploading a file with a special filename apparently.
$image_name = 'image.png';
$target_file = 'images/' . $image_name;
$existing_image = 'image.png'; // image already on server if applicable
$keep = 'keep';
$target_escaped = escapeshellarg($target_file);
if ($keep == 'keep') {
// process/change output file to image_compressed.png keeping both images
system("pngquant --force --quality=70 $target_escaped --ext=_compressed.png");
$remove_ext = substr($newFileName, 0 , (strrpos($newFileName, ".")));
// $new_image is just the name (image_compressed.png) if you need it
$new_image = $remove_ext . '_compressed.png';
// remove old file if different name
if ($existing_image != $newFileName) {
$removeOld = '../images/' . $existing_image;
unlink($removeOld);
} // comment out if you want to keep existing file
} else {
// overwrite if file has the same name
system("pngquant --force --quality=70 $target_escaped --ext=.png");
// remove old file if different name
if ($existing_image != $newFileName) {
$removeOld = '../images/' . $existing_image;
unlink($removeOld);
}
$new_image = $newFileName;
}
to override same name use this command
pngquant.exe --ext=.png --force input.png
so the output name will remain input.png
Suppose I uploaded a media file for eg image, and its name is example_123_56737_303030.png but before upload I want this name of the image to be changed as any thing of my choice (best will be post_id of this attachment) so it looks like 122.png (122 is the post_id of this attachment).
Now the things that needs to be achieved is :
Name should be changed when I upload the file from back-end/front-end/directly in media/In post/In page/Any custom post type (means if media is uploaded from anywhere in the wordpress website).
The serialize data which wordpress saves for every image, that are _wp_attached_file, _wp_attachment_metadata in wp_post_meta table should be as per the new name.
The image should be of the new name in the folder as well (upload
place/directory is fine no changes required in that).
Put below code into your functions.php
function handle_uploadedimage($arr) {
// Get the parent post ID, if there is one
if( isset($_REQUEST['post_id']) ) {
$post_id = $_REQUEST['post_id'];
} else {
$post_id = false;
}
// Only do this if we got the post ID--otherwise they're probably in
// the media section rather than uploading an image from a post.
if($post_id && is_numeric($post_id)) {
// Get the post slug
$post_obj = get_post($post_id);
// If we find post
if(!empty($post_obj->post_name)) {
$post_slug = $post_obj->post_name;
$random_number = rand(10000,99999);
$ext = pathinfo($arr['name'], PATHINFO_EXTENSION);
//Write your logic to remove any special characters from file name
$arr['name'] = $post_slug . '-' . $random_number . '.'.$ext;
}
}
return $arr;
}
add_filter('wp_handle_upload_prefilter', 'handle_uploadedimage', 1, 1);
You can also try below version
function handle_uploadedimage($arr) {
$random_number = md5(rand(10000,99999));
$ext = pathinfo($arr['name'], PATHINFO_EXTENSION);
$arr['name'] = $random_number .'.'.$ext;
return $arr;
}
add_filter('wp_handle_upload_prefilter', 'handle_uploadedimage', 1, 1);
You can also try this plugin wordpress.org/plugins/file-renaming-on-upload/screenshots which will be better I guess
The script below takes a named file that resides in the "myplugin" folder (the folder that the script itself resides in) and runs file_get_contents() on it to load the contents into memory, then does some preprocessing on the contents before finally inserting it as a post into the WordPress database via the wp_insert_post method.
$my_post3 = array();
$my_post3['post_title'] = 'Privacy Policy';
if(file_exists(ABSPATH.'/wp-content/plugins/myplugin/pages/privacy_policy.txt'))
{
$my_privacy_policy = file_get_contents(ABSPATH.'/wp-content/plugins/myplugin/pages/privacy_policy.txt');
}
else
{
$my_privacy_policy = "";
}
$my_post3['post_content'] = addslashes($my_post3_replace);
$my_post3['post_type'] = 'page';
$my_post3['post_status'] = 'publish';
wp_insert_post($my_post3);
This method works pretty good. However, this method forces me to write a different routine for every file I want to use as the basis of a new page.
What I would like to do instead, is create a folder called "pages" and place my .txt files in that, then run a for loop on the contents of the folder, creating a new page for each file in the folder. I'd like to use the file name (minus the .txt extension) as the name of the page.
For example, the pages folder may have these files:
About Us.txt
Contact Us.txt
And the routine would result in the creation of two new pages in WordPress site, one called "About Us" containing the content found in that file. The other page would of course be "Contact Us" with the contents of that file.
In this way, I can just drop an unlimited number of named and prepopulated .txt files into that folder and when I activate my plugin, it creates those pages.
I just need some help with the for loop and how to reference the folder and files.
I will also have a folder called "posts", which will do the same for posts that this routine does for pages.
Thanks in advance for your help and suggestions.
Update based on #clientbucket answer:
DEFINE ('PAGES', './pages/');
$directory_pages = new DirectoryIterator(PAGES);
foreach ($directory_pages as $files) {
if ($files_pages->isFile()) {
$file_name_page = $files_pages->getFilename();
$my_page_content = file_get_contents(PAGES. $file_name_page);
$my_page['post_content'] = addslashes($my_page_content);
$my_page['post_title'] = $file_name_page;
$my_page['post_type'] = 'page';
$my_page['post_status'] = 'publish';
wp_insert_post($my_page);
}
}
DEFINE ('POSTS', './posts/');
$directory_posts = new DirectoryIterator(POSTS);
foreach ($directory_posts as $files_posts) {
if ($files_posts->isFile()) {
$file_name_post = $files_posts->getFilename();
$my_post_content = file_get_contents(POSTS. $file_name_post);
$my_post['post_content'] = addslashes($my_post_content);
$my_post['post_title'] = $file_name_post;
$my_post['post_type'] = 'post';
$my_post['post_status'] = 'publish';
$post_id = wp_insert_post($my_post);
stick_post($post_id);
}
}
Fatal error: Uncaught exception 'UnexpectedValueException' with message 'DirectoryIterator::__construct(./pages/) [directoryiterator.--construct]: failed to open dir: No such file or directory' in C:\xampplite\htdocs\mytestsite\wp-content\plugins\myplugindirectory\myplugin.php:339
Line 339 is here > $directory_pages = new DirectoryIterator(PAGES);
Here is another way you could try.
DEFINE ('PAGES', './pages/'); //Define the directory path
$directory = new DirectoryIterator(PAGES); //Get all the contents in the directory
foreach ($directory as $files) { //Check that the contents of the directory are each files and then do what you want with them after you have the name of the file.
if ($files->isFile()) {
$file_name = $files->getFilename();
$my_page = file_get_contents(PAGES. $file_name); //Collect the content of the file.
} else {
//Insert nothing into the $my_privacy_policy variable.
}
echo $my_page; // Do what you want with the contents of the file.
}
From the PHP manual here:
http://php.net/manual/en/function.glob.php
They provide this solution for finding all text files in a directory:
<?php
foreach (glob("*.txt") as $filename) {
echo $filename . "\n";
}
?>
Given this example, your actual request is to be able to create a file based on the name in another directory. I'll leave the hard work to you - but this is a simple implementation:
<?php
$source_dir = "/your/directory/with/textfiles";
$target_dir = "/directory/to/create/files/in";
foreach (glob($source_dir . DIRECTORY_SEPARATOR . "*.txt") as $filename) {
$filepart = explode('.',$filename);
file_put_contents($target_dir . DIRECTORY_SEPARATOR . $filepart[0] . ".php");
}
?>