mirror of
https://github.com/mrclay/minify.git
synced 2025-08-08 15:16:56 +02:00
+ Minify/Build.php and example 2 showing use
This commit is contained in:
@@ -1,143 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Class HTTP_ConditionalGet_Build
|
|
||||||
* @package Minify
|
|
||||||
* @subpackage HTTP
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maintain a single last modification time for 1 or more directories of files
|
|
||||||
*
|
|
||||||
* Since scanning many files may be slower, the value is cached for a given
|
|
||||||
* number of seconds.
|
|
||||||
*
|
|
||||||
* @package Minify
|
|
||||||
* @subpackage HTTP
|
|
||||||
* @author Stephen Clay <steve@mrclay.org>
|
|
||||||
*/
|
|
||||||
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}");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected 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;
|
|
||||||
}
|
|
||||||
}
|
|
95
lib/Minify/Build.php
Normal file
95
lib/Minify/Build.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Class Minify_Build
|
||||||
|
* @package Minify
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'Minify/Source.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maintain a single last modification time for a group of Minify sources to
|
||||||
|
* allow use of far off Expires headers in Minify.
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* // in config file
|
||||||
|
* $groupSources = array(
|
||||||
|
* 'js' => array('file1.js', 'file2.js')
|
||||||
|
* ,'css' => array('file1.css', 'file2.css', 'file3.css')
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* // during HTML generation
|
||||||
|
* $jsBuild = new Minify_Build($groupSources['js']);
|
||||||
|
* $cssBuild = new Minify_Build($groupSources['css']);
|
||||||
|
*
|
||||||
|
* $script = "<script type='text/javascript' src='"
|
||||||
|
* . $jsBuild->uri('/min.php/js') . "'></script>";
|
||||||
|
* $link = "<link rel='stylesheet' type='text/css' href='"
|
||||||
|
* . $cssBuild->uri('/min.php/css') . "'>";
|
||||||
|
*
|
||||||
|
* // in min.php
|
||||||
|
* Minify::serve('Groups', array(
|
||||||
|
* 'groups' => $groupSources
|
||||||
|
* ));
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @package Minify
|
||||||
|
* @author Stephen Clay <steve@mrclay.org>
|
||||||
|
*/
|
||||||
|
class Minify_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 $b->uri('/site.js');
|
||||||
|
* // outputs "/site.js?1678242"
|
||||||
|
*
|
||||||
|
* echo $b->uri('/scriptaculous.js?load=effects');
|
||||||
|
* // outputs "/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 $sources array of Minify_Source objects and/or file paths
|
||||||
|
*
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function __construct($sources)
|
||||||
|
{
|
||||||
|
$max = 0;
|
||||||
|
foreach ((array)$sources as $source) {
|
||||||
|
if ($source instanceof Minify_Source) {
|
||||||
|
$max = max($max, $source->lastModified);
|
||||||
|
} elseif (is_string($source) && is_file($source)) {
|
||||||
|
$max = max($max, filemtime($source));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->lastModified = $max;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,7 @@ ob_start();
|
|||||||
<?php if (! $minifyCachePath): ?>
|
<?php if (! $minifyCachePath): ?>
|
||||||
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
||||||
<code>Minify::useServerCache()</code>. For the examples this can be set in
|
<code>Minify::useServerCache()</code>. For the examples this can be set in
|
||||||
<code>config.php</code>. Notice that minifying jquery.js takes several seconds!.</p>
|
<code>config.php</code>. Notice that minifying jQuery takes several seconds!.</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<h1>Minify Example 1</h1>
|
<h1>Minify Example 1</h1>
|
||||||
@@ -28,6 +28,9 @@ ob_start();
|
|||||||
<p>This is an example of Minify serving a directory of single css/js files.
|
<p>This is an example of Minify serving a directory of single css/js files.
|
||||||
Each file is minified and sent with HTTP encoding (browser-permitting).</p>
|
Each file is minified and sent with HTTP encoding (browser-permitting).</p>
|
||||||
|
|
||||||
|
<p>In this example, if m.php detects $_GET['v'], a 30-day Expires header is
|
||||||
|
sent rather than the conditional GET.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li id="cssFail"><span>FAIL</span>PASS</li>
|
<li id="cssFail"><span>FAIL</span>PASS</li>
|
||||||
<li id="jsFail1">FAIL</li>
|
<li id="jsFail1">FAIL</li>
|
||||||
|
11
web/examples/2/_groupsSources.php
Normal file
11
web/examples/2/_groupsSources.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$base = realpath(dirname(__FILE__) . '/../1');
|
||||||
|
$groupsSources = array(
|
||||||
|
'js' => array(
|
||||||
|
"{$base}/jquery-1.2.3.js"
|
||||||
|
,"{$base}/test space.js"
|
||||||
|
)
|
||||||
|
,'css' => array("{$base}/test.css")
|
||||||
|
);
|
||||||
|
unset($base);
|
76
web/examples/2/index.php
Normal file
76
web/examples/2/index.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
require '../../config.php';
|
||||||
|
require '_groupsSources.php';
|
||||||
|
|
||||||
|
require 'Minify/Build.php';
|
||||||
|
$jsBuild = new Minify_Build($groupsSources['js']);
|
||||||
|
$cssBuild = new Minify_Build($groupsSources['css']);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Minify Example 2</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="<?php echo $cssBuild->uri('m.php/css'); ?>" />
|
||||||
|
<style type="text/css">
|
||||||
|
#cssFail {
|
||||||
|
width:2.8em;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php if (! $minifyCachePath): ?>
|
||||||
|
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
||||||
|
<code>Minify::useServerCache()</code>. For the examples this can be set in
|
||||||
|
<code>config.php</code>. Notice that minifying jQuery takes several seconds!.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h1>Minify Example 2</h1>
|
||||||
|
|
||||||
|
<p>This is an example using Minify_Build and the Groups controller to
|
||||||
|
automatically create versioned minify URLs</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li id="cssFail"><span>FAIL</span>PASS</li>
|
||||||
|
<li id="jsFail1">FAIL</li>
|
||||||
|
<li id="jsFail2">FAIL</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><a href="">Link to this page (F5 can trigger no-cache headers)</a></p>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="<?php echo $jsBuild->uri('m.php/js'); ?>"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
if ( 1 < 2 ) {
|
||||||
|
$('#jsFail2').html('PASS');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<?php
|
||||||
|
$content = ob_get_clean();
|
||||||
|
|
||||||
|
require 'Minify.php';
|
||||||
|
|
||||||
|
if ($minifyCachePath) {
|
||||||
|
Minify::useServerCache($minifyCachePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pageLastUpdate = max(
|
||||||
|
filemtime(__FILE__)
|
||||||
|
,$jsBuild->lastModified
|
||||||
|
,$cssBuild->lastModified
|
||||||
|
);
|
||||||
|
|
||||||
|
Minify::serve('Page', array(
|
||||||
|
'content' => $content
|
||||||
|
,'id' => __FILE__
|
||||||
|
,'lastModifiedTime' => $pageLastUpdate
|
||||||
|
// also minify the CSS/JS inside the HTML
|
||||||
|
,'minifyAll' => true
|
||||||
|
));
|
14
web/examples/2/m.php
Normal file
14
web/examples/2/m.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require '../../config.php';
|
||||||
|
require '_groupsSources.php';
|
||||||
|
require 'Minify.php';
|
||||||
|
|
||||||
|
if ($minifyCachePath) {
|
||||||
|
Minify::useServerCache($minifyCachePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Minify::serve('Groups', array(
|
||||||
|
'groups' => $groupsSources
|
||||||
|
,'setExpires' => time() + 86400 * 365
|
||||||
|
));
|
35
web/test/test_Minify_Build.php
Normal file
35
web/test/test_Minify_Build.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
require_once '_inc.php';
|
||||||
|
|
||||||
|
require_once 'Minify/Build.php';
|
||||||
|
|
||||||
|
function test_Minify_Build()
|
||||||
|
{
|
||||||
|
global $thisDir;
|
||||||
|
|
||||||
|
$file1 = $thisDir . '/_test_files/css/paths.css';
|
||||||
|
$file2 = $thisDir . '/_test_files/css/styles.css';
|
||||||
|
$maxTime = max(filemtime($file1), filemtime($file2));
|
||||||
|
|
||||||
|
$b = new Minify_Build($file1);
|
||||||
|
assertTrue($b->lastModified == filemtime($file1)
|
||||||
|
,'Minify_Build : single file path');
|
||||||
|
|
||||||
|
$b = new Minify_Build(array($file1, $file2));
|
||||||
|
assertTrue($maxTime == $b->lastModified
|
||||||
|
,'Minify_Build : multiple file paths');
|
||||||
|
|
||||||
|
$b = new Minify_Build(array(
|
||||||
|
$file1
|
||||||
|
,new Minify_Source(array('filepath' => $file2))
|
||||||
|
));
|
||||||
|
|
||||||
|
assertTrue($maxTime == $b->lastModified
|
||||||
|
,'Minify_Build : file path and a Minify_Source');
|
||||||
|
assertTrue($b->uri('/path') == "/path?{$maxTime}"
|
||||||
|
,'Minify_Build : uri() with no querystring');
|
||||||
|
assertTrue($b->uri('/path?hello') == "/path?hello&{$maxTime}"
|
||||||
|
,'Minify_Build : uri() with existing querystring');
|
||||||
|
}
|
||||||
|
|
||||||
|
test_Minify_Build();
|
@@ -5,6 +5,6 @@ require 'test_Javascript.php';
|
|||||||
require 'test_CSS.php';
|
require 'test_CSS.php';
|
||||||
require 'test_HTML.php';
|
require 'test_HTML.php';
|
||||||
require 'test_Packer.php';
|
require 'test_Packer.php';
|
||||||
|
require 'test_Minify_Build.php';
|
||||||
require 'test_HTTP_Encoder.php';
|
require 'test_HTTP_Encoder.php';
|
||||||
require 'test_HTTP_ConditionalGet.php';
|
require 'test_HTTP_ConditionalGet.php';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user