Web components
File detail
Source code
<?php
/**
* @file ScriptServer.class.php
* Definition of ScriptServer class.
* @author Kamil Dudka <xdudka00@gmail.com>
*/
/**
* ScriptServer sends JavaScript files to client.
* Files are packed at server's side. This can take some time,
* so packed script files are cached at server's side.
* This class is not instantiable for now.
*/
class ScriptServer {
/**
* Send script to client. Script can be red from script cache
* if cache is actual. If not, script will be generated autamatically.
* @param scriptName Name of script to send. Script has to be placed in scriptDir directory.
* @return Return true on success, false if script does not exist.
* @note This method will crash if cacheDir directory is not writeable.
*/
public static function sendScript($scriptName) {
if (false === ereg('^[A-Za-z_][A-Za-z0-9_\.]*.js$', $scriptName))
return false;
// Read paths from Config singleton
$config = Config::instance();
$docRoot = $config->documentRoot();
$scriptDir = $docRoot.$config->scriptDir();
$cacheDir = $docRoot.$config->cacheDir();
// Build file names
$sourceScript = $scriptDir.'/'.$scriptName;
$cachedScript = $cacheDir.'/'.$scriptName;
// Check if script (re)generation is needed
if (!file_exists($sourceScript))
return false;
if (!file_exists($cachedScript) ||
filemtime($sourceScript) > filemtime($cachedScript))
self::generate($sourceScript, $cachedScript);
// Send script
Header('Content-type: text/javascript; charset=utf-8');
readfile($cachedScript);
return true;
}
private static function generate($src, $dest) {
$fSrc = fopen ($src, 'r');
$fDest = fopen ($dest, 'w');
// Record timestamp
$startTS = microtime(true);
fwrite($fDest, '// This file was generated by ScriptServer.class.php at '.date("Y-m-d H:i:s", time())."\n");
fwrite($fDest, '// Source file\'s mtime was '.date("Y-m-d H:i:s", filemtime($src))."\n");
// State set of FA
define('ST_INIT', 0);
define('ST_LONG_COMMENT', 1);
define('ST_INLINE_COMMENT', 2);
define('ST_SLASH_READED', 3);
define('ST_ASTERIX_READED', 4);
define('ST_LINE_BEGIN', 5);
$state = ST_INIT; // FA's initial state
$last = ''; // Last char writen
$ignoreInlineComment = false; // Patch for \// sequence
while (false !== ($c = fgetc($fSrc))) {
switch ($state) {
case ST_INIT:
if ($c == '/') {
$state = ST_SLASH_READED;
$ignoreInlineComment = false;
} else {
if ($c == "\n")
$state = ST_LINE_BEGIN;
if ($c != "\n" || $last != "\n")
fwrite($fDest, $last = $c);
}
break;
case ST_LINE_BEGIN:
if ($c == '/') {
$state = ST_SLASH_READED;
$ignoreInlineComment = true;
}
else if (trim($c)==$c) {
$state = ST_INIT;
if ($c != "\n" || $last != "\n")
fwrite($fDest, $last = $c);
}
break;
case ST_SLASH_READED:
if ($ignoreInlineComment && $c == '/')
$state = ST_INLINE_COMMENT;
else if ($c == '*')
$state = ST_LONG_COMMENT;
else {
if ($c == "\n")
$state = ST_LINE_BEGIN;
else
$state = ST_INIT;
fwrite($fDest, '/'.($last=$c));
}
break;
case ST_INLINE_COMMENT:
if ($c == "\n") {
$state = ST_LINE_BEGIN;
if ($last != "\n")
fwrite($fDest, $last = "\n");
}
break;
case ST_LONG_COMMENT:
if ($c == '*')
$state = ST_ASTERIX_READED;
break;
case ST_ASTERIX_READED:
if ($c == '/')
$state = ST_INIT;
else if ($c != '*')
$state = ST_LONG_COMMENT;
break;
}
}
// Compute time elapsed
$timeElapsed = microtime(true)-$startTS;
fprintf($fDest, "\n// File generated in %.3f s\n", $timeElapsed);
fclose($fSrc);
fclose($fDest);
}
// Avoid class instantiation
private function __construct() { }
}