mirror of
https://github.com/mrclay/minify.git
synced 2025-08-06 06:07:24 +02:00
+ HTTP_ConditionalGet_Build directory change monitor, + post-processing hook in Minify (for appending timestamps to URIs, etc.)
This commit is contained in:
128
lib/HTTP/ConditionalGet/Build.php
Normal file
128
lib/HTTP/ConditionalGet/Build.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class HTTP_ConditionalGet_Build {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last modification time of all files in the build
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $lastModified = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to use as ampersand in uri(). Set this to '&' if
|
||||||
|
* you are not HTML-escaping URIs.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $ampersand = '&';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a time-stamped URI
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* echo 'src="' . $b->uri('/site.js') . '"';
|
||||||
|
* // outputs src="/site.js?1678242"
|
||||||
|
*
|
||||||
|
* echo 'src="' . $b->uri('/scriptaculous.js?load=effects') . '"';
|
||||||
|
* // outputs src="/scriptaculous.js?load=effects&1678242"
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function uri($uri) {
|
||||||
|
$sep = strpos($uri, '?') === false
|
||||||
|
? '?'
|
||||||
|
: self::$ampersand;
|
||||||
|
return "{$uri}{$sep}{$this->lastModified}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a build object
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
*
|
||||||
|
* 'id': (required) unique string for this build.
|
||||||
|
*
|
||||||
|
* 'savePath': PHP-writeable directory to store build info. If not
|
||||||
|
* specified, sys_get_temp_dir() will be used.
|
||||||
|
*
|
||||||
|
* 'scanPaths': (required) array of directory paths to scan. A single path
|
||||||
|
* string is also accepted.
|
||||||
|
*
|
||||||
|
* 'scanDeep': should we scan descendant directories? (default true)
|
||||||
|
*
|
||||||
|
* 'scanPattern': filenames must match this (default matches css & js
|
||||||
|
* files not starting with ".")
|
||||||
|
*
|
||||||
|
* 'delay': seconds to wait before scanning again (default 300)
|
||||||
|
*
|
||||||
|
* @return int last modified timestamp
|
||||||
|
*/
|
||||||
|
public function __construct($options)
|
||||||
|
{
|
||||||
|
$savePath = isset($options['savePath'])
|
||||||
|
? $options['savePath']
|
||||||
|
: sys_get_temp_dir();
|
||||||
|
$file = $savePath . DIRECTORY_SEPARATOR
|
||||||
|
. 'HTTP_ConditionalGet_Build_'
|
||||||
|
. md5($options['id'])
|
||||||
|
. '.txt';
|
||||||
|
|
||||||
|
// check build file
|
||||||
|
$loaded = file_get_contents($file);
|
||||||
|
if ($loaded) {
|
||||||
|
list($this->lastModified, $nextCheck) = explode('|', $loaded);
|
||||||
|
} else {
|
||||||
|
$nextCheck = 0;
|
||||||
|
}
|
||||||
|
if ($nextCheck > $_SERVER['REQUEST_TIME']) {
|
||||||
|
// done here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan last modified times
|
||||||
|
$options['scanPattern'] = isset($options['scanPattern'])
|
||||||
|
? $options['scanPattern']
|
||||||
|
: '/^[^\\.].*\\.(?:css|js)$/';
|
||||||
|
$options['scanDeep'] = isset($options['scanDeep'])
|
||||||
|
? $options['scanDeep']
|
||||||
|
: true;
|
||||||
|
$max = 0;
|
||||||
|
foreach ((array)$options['scanPaths'] as $path) {
|
||||||
|
$max = max($max, self::_scan($max, $path, $options));
|
||||||
|
}
|
||||||
|
$this->lastModified = $max;
|
||||||
|
|
||||||
|
$nextCheck = $_SERVER['REQUEST_TIME']
|
||||||
|
+ (isset($options['delay'])
|
||||||
|
? (int)$options['delay']
|
||||||
|
: 300);
|
||||||
|
|
||||||
|
// save build file
|
||||||
|
file_put_contents($file, "{$this->lastModified}|{$nextCheck}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _scan($max, $path, $options)
|
||||||
|
{
|
||||||
|
$d = dir($path);
|
||||||
|
while (false !== ($entry = $d->read())) {
|
||||||
|
if ('.' === $entry[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$fullPath = $path . DIRECTORY_SEPARATOR . $entry;
|
||||||
|
if (is_dir($entry)) {
|
||||||
|
if ($options['scanDeep']) {
|
||||||
|
$max = max($max, self::_scan($max, $fullPath, $options));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (preg_match($options['scanPattern'], $entry)) {
|
||||||
|
$max = max($max, filemtime($fullPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$d->close();
|
||||||
|
return $max;
|
||||||
|
}
|
||||||
|
}
|
@@ -348,6 +348,14 @@ class Minify {
|
|||||||
}
|
}
|
||||||
$content = implode($implodeSeparator, $pieces);
|
$content = implode($implodeSeparator, $pieces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do any post-processing (esp. for editing build URIs)
|
||||||
|
if (self::$_options['postprocessorRequire']) {
|
||||||
|
require_once self::$_options['postprocessorRequire'];
|
||||||
|
}
|
||||||
|
if (self::$_options['postprocessor']) {
|
||||||
|
$content = call_user_func(self::$_options['postprocessor'], $content, $type);
|
||||||
|
}
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,6 +44,11 @@ abstract class Minify_Controller_Base {
|
|||||||
// if you override this, the response code MUST be directly after
|
// if you override this, the response code MUST be directly after
|
||||||
// the first space.
|
// the first space.
|
||||||
,'badRequestHeader' => 'HTTP/1.0 400 Bad Request'
|
,'badRequestHeader' => 'HTTP/1.0 400 Bad Request'
|
||||||
|
|
||||||
|
// callback function to see/modify content of all sources
|
||||||
|
,'postprocessor' => null
|
||||||
|
// file to require to load preprocessor
|
||||||
|
,'postprocessorRequire' => null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ class Minify_HTML {
|
|||||||
|
|
||||||
self::$_isXhtml = (false !== strpos($html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
self::$_isXhtml = (false !== strpos($html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
||||||
|
|
||||||
self::$_replacementHash = 'HTTPMINIFY' . md5(time());
|
self::$_replacementHash = 'MINIFYHTML' . md5(time());
|
||||||
|
|
||||||
// remove SCRIPTs (and minify)
|
// remove SCRIPTs (and minify)
|
||||||
$html = preg_replace_callback('/\\s*(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>\\s*/i',
|
$html = preg_replace_callback('/\\s*(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>\\s*/i',
|
||||||
|
@@ -92,8 +92,7 @@ class V1Controller extends Minify_Controller_Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$v1 = new V1Controller();
|
|
||||||
if (MINIFY_USE_CACHE) {
|
if (MINIFY_USE_CACHE) {
|
||||||
Minify::useServerCache(MINIFY_CACHE_DIR);
|
Minify::useServerCache(MINIFY_CACHE_DIR);
|
||||||
}
|
}
|
||||||
Minify::serve($v1);
|
Minify::serve(new V1Controller());
|
Reference in New Issue
Block a user