1

I'm currently trying to make a webpage look a bit more modern, but I'm having a bit of trouble adding some relatively simple functionality to a modal window.

On my webpage, a user first uploads a file, then on hitting submit the file gets processed by a shell script (which can take from seconds to minutes depending on the file size).

What I had been doing to show the process status was execute the following bit of code using php:

$cmd = "script.bash -i $input_file";

$PID = shell_exec($cmd . " >> $log 2>&1  & echo $!");

while(is_process_running($PID)){
   echo(" . ");
   ob_flush(); flush();
   sleep(3);
}

In addition to some other information that gets displayed (not shown), this would simply print out a "." every few seconds to give the user an indication that the process was running. On completion, a download link would appear so that the processed data could be retrieved.

What I would like to do now is load this information in a modal window. I have no trouble creating the modal window (using boostrap and javascript) and adding download functionality to it, but I can only do this once the $cmd executed via php is complete. What I would like to do is execute the $cmd, load the modal window, then query the process status and display some sort of indicator in the modal window, and finally create the download link when the process is complete. I believe this needs to be done via AJAX, but I'm a bit confused on how to do this. Here is my code in a bit more detail:

<?
    if($theaction == "run_script" and !$error_msg){
        $cmd = "script.bash -i $input_file";

        $PID = shell_exec($cmd . " >> $log 2>&1  & echo $!");

        while(is_process_running($PID)){ #ensure the process is compete before loading the html
            echo("");
            ob_flush(); flush();
            sleep(3);
        }

        echo "
            <script type=\"text/javascript\">
                $(function() { $(\"#myModalProcess\").modal('show') })
            </script>


            <div class=\"modal fade\" id=\"myModalProcess\" tabinex=\"-1\" role=\"dialog\" aria-hidden=\"true\">
                <div class=\"modal-dialog\">
                    <div class=\"modal-content\">
                        <div class=\"modal-header\">
                            <h4><b>Process ID: $PID</b></h4>
                            <hr>
                            <p>Other stuff here</p>
                            <a type=\"button\" class=\"btn btn-primary\" href='".$_SERVER['PHP_SELF']."?theaction=download&workDir=$workDir&out_folder=$out_folder'>Download Results</a>
                        </div>
                    </div>
                </div>
            </div>
        ";
    }
?>
James
  • 1,100
  • 1
  • 13
  • 29

1 Answers1

1

I will clarify the flow for you, but I wont give you the code, because it's so long to write and I think you better need the theory first to understand what you need to develop.

So, the first mistake is trying to execute the javascript and html (modal) code after you ran your php script.

What you should do is use ajax, so you can run your php script (with your shell script inside) via "ajax", and, using ajax again you can ask for the progress while the php script is running.

All of this should be a little bit simple, I know, but the problem is that you have a mix of complicated things here:

  1. You can't leave the page. If you submit a form using multipart-form/data to upload the file, the browser starts the upload, makes the request and when the php script finish, the entire page is reloaded. There you lost control of the page, you just pass the control to the browser.
  2. You have 2 processes that take time and need the progress status: the file upload and the script process. But let's skip the first one.
  3. To avoid leaving the page when submitting a form, you need to submit it via ajax. Here is a link to understand how to do it.
  4. To get the progress you have two ways: The first is using the jQuery ajax progress via xhr and the second is "setting a an interval" in javscript to check every {x time} (i.e.: every 3 seconds) the progress via ajax and when the process finished, clear that interval to stop checking. You can check by executing an ajax request to a path where you have an script that returns you the progress (it can be a php file -> i.e.: www.yourhost.com/your_action/progress.php).
  5. When the script is running, you need to save the progress on a "user global context" (i.e.: cookies, file with user id, some cache, etc), so when you "check the progress" (step 4), you will be making a request and asking for a value that any request can access with the data for the user. Or just work with the "jQuery ajax progress via xhr", read the documentation and make it work that way :)
  6. After your process finished, just stop showing or asking for the progress, show the link or the result and you don't need to reload your page!

Hope this help, and if you have any other specific question, just ask :)

Community
  • 1
  • 1
Yam Frich
  • 77
  • 3
  • Thanks Yam. I am weak on the theory side so thank you very much for clarifying what it is that's going on and what it is I need to do. I'll see what I can do and get back to you if I'm struggling with anything. – James Sep 09 '15 at 14:11
  • Sure, I think you need to separate your code between view (html + js) logic and backend (php) logic and try to have both functions -> 1. run the script 2. get the progress status. Then you can, from your view logic, submit the file and run 1. and check 2. while 1. is running. Try to write your code and I'll help you if you have any specific issue :) – Yam Frich Sep 09 '15 at 14:16