Is there a way to run a php function after a file is uploaded?
-
I have written a function that records all PDF files from the media folder so that you can just insert them into pages using shortcodes but it wont update the records when I upload a new PDF file, only when I refresh the page. Is there a way to make it record as soon as the file is uploaded?
-
We would probably need to see the function you have written. You may be able to add a function to refresh the page automatically, or to make an Ajax call to refresh the data.
function build_options(){ //Deal with the PDF files $all_pdfs = get_pdf_files(); $options = get_option( 'pdf-display-plugin-options' ); if($options == ''){$options = false; delete_option( 'pdf-display-plugin-options' );} if($options != false){ $data_from_file = 'EMPTY'; $saved_data_array = array(); if(file_exists(plugin_dir_path(__FILE__)."Saved_Data")){ $data_from_file = ''; $data_file = fopen(plugin_dir_path(__FILE__)."Saved_Data", 'r'); $data_from_file = file_get_contents(plugin_dir_path(__FILE__)."Saved_Data"); fclose($data_file); unlink(plugin_dir_path(__FILE__)."Saved_Data"); } if($data_from_file != 'EMPTY'){ $saved_data_array = explode('||', $data_from_file); } $data_array = array(); foreach($saved_data_array as $data){ $parts = explode(':', $data); $data_array[str_replace('display-setting-','',$parts[0])] = $parts[1]; } //var_dump($data_array); //check validity of each entry $real_options = ""; //create an array of pdf entries from the options table $all_pdf_entries = read_pdf_options_table_entry($options); //loop through all entries in the options table foreach($all_pdf_entries as $entry){ if(in_array($entry['path'], $all_pdfs)){ //if the file this entry references exists record it into $real_options $id = $entry['id']; $path = prepare_pdf_path($entry['path']); $display = $entry['display']; //if this entry's display setting was changed if($data_array[$id] != null){ //get the new value $display = $data_array[$id]; } $real_options = $real_options.$id.'|*|'.$path.'|*|'.$display.'#@#'; } } //re-interpret data from this loop $all_pdf_entries = read_pdf_options_table_entry( $real_options ); //gather all recorded paths $paths = gather_all_attr($all_pdf_entries, 'path'); //check to make sure each pdf file has a corresponding entry foreach($all_pdfs as $file){ if(in_array($file, $paths)){ //if this file is already recorded }else{ //If this file is not recorded, create an entry and add it to the master list //first get a valid ID number $id_records = gather_all_attr($all_pdf_entries, 'id'); //count up until you find an ID number that isn't already taken $x = 0; while(in_array($x,$id_records)){ $x++; } $id = $x; $path = prepare_pdf_path($file); $display = 'linked'; $real_options = $real_options.$id.'|*|'.$path.'|*|'.$display.'#@#'; } } update_option('pdf-display-plugin-options', $real_options); }else{ echo $options; $option_value = ''; $id = 0; foreach($all_pdfs as $pdf){ //echo $pdf.'<br>'; $id = $id+1; $display = 'linked'; $path = prepare_pdf_path($pdf); $option_value = $option_value.$id.'|*|'.$path.'|*|'.$display.'#@#'; } add_option( 'pdf-display-plugin-options', $option_value ); } }
Though if there’s just a way to make it refresh after the file uploads that might work fine too. I just need to add new PDF files to the options when they’re uploaded or delete them from the options when the file is deleted.
Right now that function runs on admin_init which kind of works but if I could get it to run that function with the file upload that would be better.
The usual file upload form causes a new page request to occur. If the form action is the same page or non-existent, a reload automatically occurs. Either an alternative upload method is used, or something more subtle is preventing your page from updating, such as some sort of caching scheme or a race condition where the page is served before the file can be saved and recorded. By the time you manually reload, it’s all said and done.
A bit of a cheat would be to blindly add the recently uploaded file to the page data if it is not already in the data, assuming the upload will soon complete. Better would be to use Ajax to monitor the upload status and only update the data upon success. Without knowing what the upload form and handler code looks like, it’s all speculation.
The form and it’s process.php only runs on it’s own screen, it’s not meant to run on upload. I could (and now that you point it out, I probably should) split or copy part of the above function and make it it’s own function to run on upload because all it needs to do is update the “pdf-display-plugin-options” in the options, it doesn’t even need the “Saved_Data” or any other forms. I create (and delete) the Saved_Data file through the form because it was the easiest way I could find to change and update one specific part of the “pdf-display-plugin-options” at a time (making the PDF embed or link when you use the shortcode). The part of the plugin that handles Saved_Data and the form has it’s own page.
All it needs to do when a new PDF is uploaded is check to see if THAT pdf is recorded (which it wouldn’t be) and record it if it isn’t.
So the above function that’s supposed to run when a file is uploaded would look like this instead:
function on_upload(){ //Deal with the PDF files. All get_pdf_files() does is filter the media folder and return any PDF files it finds $all_pdfs = get_pdf_files(); $options = get_option( 'pdf-display-plugin-options' ); //if nothing has been recorded, delte this options entry and start over if($options == ''){$options = false; delete_option( 'pdf-display-plugin-options' );} if($options != false){ //create an array of pdf entries from the options table. read_pdf_options_table_entry() just splits the options entry into chunks I can use $all_pdf_entries = read_pdf_options_table_entry($options); //loop through all entries in the options table foreach($all_pdf_entries as $entry){ if(in_array($entry['path'], $all_pdfs)){ //if the file this entry references exists record it into $real_options $id = $entry['id']; $path = prepare_pdf_path($entry['path']); $display = $entry['display']; } } //re-interpret data from this loop $all_pdf_entries = read_pdf_options_table_entry( $real_options ); //gather all recorded paths $paths = gather_all_attr($all_pdf_entries, 'path'); //check to make sure each pdf file has a corresponding entry foreach($all_pdfs as $file){ if(!in_array($file, $paths)){ //If this file is not recorded, create an entry and add it to the master list //first get a valid ID number $id_records = gather_all_attr($all_pdf_entries, 'id'); //count up until you find an ID number that isn't already taken $x = 0; while(in_array($x,$id_records)){ $x++; } $id = $x; $path = prepare_pdf_path($file); $display = 'linked'; $real_options = $real_options.$id.'|*|'.$path.'|*|'.$display.'#@#'; } } update_option('pdf-display-plugin-options', $real_options); }else{ //echo $options; $option_value = ''; $id = 0; foreach($all_pdfs as $pdf){ //echo $pdf.'<br>'; $id = $id+1; $display = 'linked'; $path = prepare_pdf_path($pdf); $option_value = $option_value.$id.'|*|'.$path.'|*|'.$display.'#@#'; } add_option( 'pdf-display-plugin-options', $option_value ); } }
Oops! There doesn’t seem to be a way to edit this. I accidentally deleted a line that wasn’t supposed to be deleted:
//loop through all entries in the options table foreach($all_pdf_entries as $entry){ if(in_array($entry['path'], $all_pdfs)){ //if the file this entry references exists record it into $real_options $id = $entry['id']; $path = prepare_pdf_path($entry['path']); $display = $entry['display']; $real_options .= $id.'|*|'.$path.'|*|'.$display.'#@#'; } }
When the upload form is submitted to start the upload, it’s in essence a page request where the action destination sends a response, usually the same page with an added message. In other words, a reload. That said, a frequent variant is to manage it all through Ajax requests, which sounds like is happening in your case. In the case of Ajax uploads, you could modify the PHP handler script (process.php apparently) to run your on_upload() function, though it strikes me as overkill since it’ll be called on the next request anyway.
If you added the JS call
location:reload();
to the upload script after the upload completes, that too would cause your on_upload() to run as part of the new request. Better would be to modify the list on the current page directly without going to the server, only relying on the upload completion response as confirmation that the file exists. I don’t think it’s possible for the file status to be wrong on this as long as confirmation is received. Even if it were, the situation would be corrected on the next page request or reload.Ah, ok. I miss understood before. I guess it’s not really necessary anymore to have this run right after the file is uploaded since the function runs on admin_init so whenever you do anything else after uploading it refreshes the options table entry. It creates a weird little bug where if you upload a pdf but don’t do anything else it wont be recorded right away and if for some reason you’ve already added the shortcode to a page (say you deleted the PDF, refreshed, and then re-uploaded it) you’ll get an error message on that page just saying that the file is missing (part of the plugin) but again, as soon as you do anything else the bug is corrected.
Ah! I see what you mean now. I had a more conventional situation in mind. I did not realize you were encountering a shortcode failure due to the server data not yet being synced. That’s beyond a JS patch up I was suggesting.
The way to fix that would be for that on_upload() function to run as part of the upload handler. You know, like actually on upload ?? Instead of on init on the next request. It’ll help site performance some because it’ll only be run after uploads instead of on every request.
But then there is a possibility of the data becoming out of sync because of FTP actions on related files. You could also run on_upload() as a scheduled event, say every hour or so, to keep the data in sync. You could still encounter weird errors like you describe this way, but it would be due to FTP actions, not normal user operations.
You could also place a refresh button somewhere in the backend to manually execute on_upload() after any FTP operations. Or you could still run on_upload() on init if you wanted, but it seems like overkill to me if it’s run on the actual upload.
- The topic ‘Is there a way to run a php function after a file is uploaded?’ is closed to new replies.