<?php
// class deferer
//
// This class can be used to defer action until after the user connection is closed
// Initiallize the script with deferer::initialize() prior to any outpub
// register actions to be done by using registerAction.
//
// Example: deferer::initialize(); registerAction(function() use($userid, $useremail) {sendUserEmail($userid, $useremail);});
//
// The above example will result in the user's browser closing the connection
// before the sendUserEmail is run which will cause faster client page loading
//
// If you have trouble with database connections closing try initializing
// with registerShutdown = false and manually calling processActions at the end of your script.
//
// Hint: If something needs to be registered toward the end (like closing connections) but
// you want to queue it in your main application script try it like this
// deferer::registerAction(function() { deferer::registerAction(function() {closeSqlConnections();}); });
//
// License MIT
class deferer
{
protected static $actions = array();
protected static $initialized = false;
/**
* Initialize the deferer (must be called before content is outputed)
*
* @param bool $registerShutdown
*/
public static function initialize($registerShutdown=true)
{
if (static::$initialized)
{
return;
}
static::$initialized = true;
ob_start();
if ($registerShutdown)
{
register_shutdown_function("deferer::processActions");
}
}
/**
* Register an action to be done after client connection is closed.
*
* @param closure $action
*/
public static function registerAction(closure $action)
{
static::$actions[] = $action;
}
/**
* Attempt to close the user client agent.
*/
protected static function connectionCloser()
{
while (ob_get_level() > 2) ob_end_flush(); // flush all output buffers into the default level
$length = ob_get_length();
$html = ob_get_clean();
header("Content-Length: ".$length);
header("Connection: Close");
ob_flush(); // headers
echo $html;
flush();
}
/**
* Process all the queued actions.
*/
public static function processActions()
{
if (static::$initialized)
{
static::connectionCloser();
}
foreach (static::$actions as $closure)
{
call_user_func($closure);
}
}
}
|