require_once('class.longops.php'); session_start(); $params = array_merge($_GET,$_POST); if(isset($params['longops_action'])) { # 'maxtime': we give 2 seconds for one working session $longop = new LongOps('myLongOperation', array('processid'=>'LONGOPT_DEMO', 'maxtime'=>2)); $longop->dispatch($params); } else die('Empty backend call (no longops_action passed) !'); function myLongOperation($longoptObj, $opt=array()) { if($longoptObj->isAborted()) { # Here make your "Before Abort" cleanup (close/delete unfinished files, drop temp tables in DB etc.) # After that you can call abortProcess(); $opt['message'] = 'Stopped by user !'; $longoptObj->abortProcess($opt); } if(empty($opt['lastItem'])) { # We're on the beginning: Peform initial tasks (create output file, calculate items count to work with etc.) $opt['lastItem'] = 0; $opt['itemCount'] = 50; } else { # We're going to resume from paused job: # Re-open output file(s) and fseek to the saved position, restore other working parameters. } # Main working loop while($opt['lastItem'] < $opt['itemCount']) { # our long action works here: $opt['lastItem'] += 1; usleep(500000); # 0.5 sec delay simulates loong job... if($longoptObj->isTimedOut($opt)) { # here You have to close output file, to reopen it in next work-session for appending - fopen(fname,'a') $opt['message'] = 'Processed:'.$opt['lastItem'].' of '.$opt['itemCount'] . ' items'; $longoptObj->pauseProcess($opt); # will exit($response); } } # Here is the place for "final" cleanups, when the "long job" successfully finished. $opt['message'] = 'Success, handled items: '.$opt['lastItem']; return $opt; }Depending on passed parameters, your function will start long process, resume it after last break, and inside a main working loop , periodically check if "one session" time limit reached.
if($longoptObj->isAborted()) { # Here make your "Before Abort" cleanup (close/delete unfinished files, drop temp tables in DB etc.) # After that you can call abortProcess(); $opt['message'] = 'Stopped by user !'; // Place your "farewell" message to show in the client browser $longoptObj->abortProcess($opt); }
if(empty($opt['lastItem'])) { # We're on the beginning: Peform initial tasks (create output file, calculate items count to work with etc.) $opt['lastItem'] = 0; $opt['itemCount'] = 50; } else { # We're going to resume from paused job: # Re-open output file(s) and fseek to the saved position, restore other working parameters. }Remember: in "start new job" case you have to calculate the whole items count and set it to $opts['itemCount'] element, so LongOps will be able to compute percentage for progress bar. For instance, if your job will handle all records from some SQL query, run "SELECT COUNT(1) FROM ... WHERE ..." with the same WHERE conditions as in the real job and store the result into $opt['itemCount'].
To do this, you write a class that extends abstract LongProcess defined in class.longops.php. That means you have to implement following functions in your class:
start($params) : LongOps call this method from your class to make "initial" procedures:
for example, you're going to export some data to the text file. So you create this file in "start()" function, by calling fopen(fname, 'w').
It's your responsibility to create output file handler(s) and other "state data" - use the $_SESSION global var for that.
Function start() must return associative array with "itemCount" value, that will be used to calculate progress bar "done percentage".
If you forgive to return 'itemCount', LongOps will set value 100.
As an input parameters ($params) you receive all parameters that have come in GET/POST vars from the client.
And remember: YOU DON'S PERFORM ANY MAIN ACTIONS inside start() function. It's called only for "initialization" tasks!
saveState(): inside working loop, when LongOps reaches 'maxtime' seconds elapsed, it calls your function saveState from your class to save all needed data that describes current state, and right after that it sends to the clinet "checkpoint" message, containing percentage data for refreshing porgress bar, and optional message (where you can say user any info about progress, for example, amount of KB already saved to the file)
resume($params): when client receives "checkpoint" rersponse from server, it redraws progress bar (or does somethin else...) and sends request "please continue" back to the server. When server (backend) receives it, it calls function resume() from the your class. Again, this function is not to perform real job, it's here only to restore last saved "checkpoint" (read output file handler from $_SESSION etc.)
action() - here you place your functionality (writing export data to the output fiule...). If you successfully restored state from last checkpoint,
at resume() call, so you can continue from the point where you've stopped.
Here you have a chance to stop the process earlier:
By default LongOps increments "lastItem" value each time it calls action(), and when it reaches "itemCount", LongOps finishes process.
start() should return any non-empty non-string value, if you want to continue process.
But if for some reason you want "early finish", you can just return string value from the start() function.
This string will be sent to the client as "farewell" message. If you don't want to send any text, just return boolean FALSE.
All these values (string or boolean FALSE value) will be treated by LongOps as "stop" command.
Another way to finalize execution - returning associative array with at least one element - 'itemCount', that is equal or less than current
'lastItem' value.
cancel() - LongOps call this function when it receives 'abort' request from client. Inside this function you should close all resources, files, clean temporary tables if any, delete unfinished outpout files if you want. If you return an array with 'message' element, text value from it will be passed to the client, so it can print "stopped farewell" text.
finish() - LongOps call it when 'lastItem' reaches or exceeds value of 'itemCount'. Here you shoul perform any "finalization" tasks, like freeing resources, cleaning $_SESSION from your long-process vars etc. If your function returns array with 'message' item, LognOps will send to the clint it the 'finished' response.
... <link rel="stylesheet" href="jquery-ui-custom.css" type="text/css" /> <script src="jquery.min.js"></script> <script src="jquery-ui-custom.min.js"></script> <script src="../src/longops.jQuery.js"></script> <script type="text/javascript"> function startLongop() { var options = { backend: 'demo-backend.php' ,title : 'Very long operation' ,comment: 'Relax and enjoy the progress.' // ,autoClose: 2 // when process finished, modal dialog will close in 2 seconds ,dialogClass:'div_shade' ,width:400 ,onSuccess: function() { $('.result').append('Your long operation successfully finished<br>'); } }, params = { useroperation:'backupme', userdate:'2013-09-16'}; longOps.start(params, options); } </script> </head> <h2>PHP LongOps (Long Operations) demonstration</h2> <br><br><br> To start "long operation" emulation, Click the button below: <br><br> <input type="button" class="button" onclick="startLongop()" value="Start the demo" /> <br><br> <div class="result" style="height:80px"></div> ...
options = { backend: 'mybackend_url.php' ,title : 'Dialog title' ,comment: 'some comment' ,autoClose: 0 ,width: 300 ,btnStop: 'Cancel' ,btnClose: 'Close' ,btnStopping: 'Stopping...' ,onSuccess: function() { ...} ,onError: function() { ...} ,onCancel: function() { ...} };Any element here is optional.
option | description | default value |
---|---|---|
backend | your backend URL | "./" (that will call default start page in the "current" folder |
title | Title text for dialog window | "Long operation" |
autoClose | if not zero, sets window auto-closing time (in seconds) after process successfully finishes | 0 (dialog window remains on the screen, user has to click "Close" button to remove it |
width | Dialog window width. See jQuery UI dialog() documentation for the same option | 300 |
dialogClass | Aditional css class that will be added to the modal window (see jQuery UI dialog() documentation for the same option) | none |
comment | Any text that will be printed over progress bar | none |
btnStop | caption text for "stop/cancel" button | 'Cancel' |
btnClose | caption text for "CLose" button | 'Close' |
btnStopping | caption text, that comes to "stop" button right after user press it. Button becomes disabled | 'Stopping...' |
onSuccess | event function (or function name) that will fire when long process successfully finished. | null |
onCancel | event function (or function name) that will fire when long process stopped by user, (and server really stopped it and sent 'aborted' response ) | null |
onError | event function (or function name) that will fire when long process was stopped with any error
Any server response that is not 'working', 'finished' or 'aborted' treated as error. In that case modal dialog window will be closed, and response message is alerted. (This is an additional help for debugging backend script) |
null |