mirror of
https://github.com/mrclay/minify.git
synced 2025-01-17 21:28:14 +01:00
More work on HTML helpers
This commit is contained in:
parent
b41a908dbf
commit
f2ebbeb526
@ -13,25 +13,46 @@
|
||||
class Minify_HTML_Helper {
|
||||
public $rewriteWorks = true;
|
||||
public $minAppUri = '/min';
|
||||
public $groupsConfigFile = '';
|
||||
|
||||
public static function groupUri($key, $farExpires = true, $debug = false, $charset = 'UTF-8')
|
||||
/*
|
||||
* Get an HTML-escaped Minify URI for a group or set of files
|
||||
*
|
||||
* @param mixed $keyOrFiles a group key or array of filepaths/URIs
|
||||
* @param array $opts options:
|
||||
* 'farExpires' : (default true) append a modified timestamp for cache revving
|
||||
* 'debug' : (default false) append debug flag
|
||||
* 'charset' : (default 'UTF-8') for htmlspecialchars
|
||||
* 'minAppUri' : (default '/min') URI of min directory
|
||||
* 'rewriteWorks' : (default true) does mod_rewrite work in min app?
|
||||
* 'groupsConfigFile' : specify if different
|
||||
* @return string
|
||||
*/
|
||||
public static function getUri($keyOrFiles, $opts = array())
|
||||
{
|
||||
$opts = array_merge(array( // default options
|
||||
'farExpires' => true
|
||||
,'debug' => false
|
||||
,'charset' => 'UTF-8'
|
||||
,'minAppUri' => '/min'
|
||||
,'rewriteWorks' => true
|
||||
,'groupsConfigFile' => ''
|
||||
), $opts);
|
||||
$h = new self;
|
||||
$h->setGroup($key, $farExpires);
|
||||
$uri = $h->getRawUri($farExpires, $debug);
|
||||
return htmlspecialchars($uri, ENT_QUOTES, $charset);
|
||||
}
|
||||
|
||||
public static function filesUri($files, $farExpires = true, $debug = false, $charset = 'UTF-8')
|
||||
{
|
||||
$h = new self;
|
||||
$h->setFiles($files, $farExpires);
|
||||
$uri = $h->getRawUri($farExpires, $debug);
|
||||
return htmlspecialchars($uri, ENT_QUOTES, $charset);
|
||||
$h->minAppUri = $opts['minAppUri'];
|
||||
$h->rewriteWorks = $opts['rewriteWorks'];
|
||||
$h->groupsConfigFile = $opts['groupsConfigFile'];
|
||||
if (is_array($keyOrFiles)) {
|
||||
$h->setFiles($keyOrFiles, $opts['farExpires']);
|
||||
} else {
|
||||
$h->setGroup($keyOrFiles, $opts['farExpires']);
|
||||
}
|
||||
$uri = $h->getRawUri($opts['farExpires'], $opts['debug']);
|
||||
return htmlspecialchars($uri, ENT_QUOTES, $opts['charset']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get URI (not html-escaped) to minify a group/set of files
|
||||
* Get non-HTML-escaped URI to minify the specified files
|
||||
*/
|
||||
public function getRawUri($farExpires = true, $debug = false)
|
||||
{
|
||||
@ -41,7 +62,7 @@ class Minify_HTML_Helper {
|
||||
}
|
||||
if (null === $this->_groupKey) {
|
||||
// @todo: implement shortest uri
|
||||
$path .= "f=" . $this->_fileList;
|
||||
$path = self::_getShortestUri($this->_filePaths, $path);
|
||||
} else {
|
||||
$path .= "g=" . $this->_groupKey;
|
||||
}
|
||||
@ -57,7 +78,7 @@ class Minify_HTML_Helper {
|
||||
{
|
||||
$this->_groupKey = null;
|
||||
if ($checkLastModified) {
|
||||
$this->_sniffLastModified($files);
|
||||
$this->_lastModified = self::getLastModified($files);
|
||||
}
|
||||
// normalize paths like in /min/f=<paths>
|
||||
foreach ($files as $k => $file) {
|
||||
@ -70,51 +91,30 @@ class Minify_HTML_Helper {
|
||||
$file = strtr($file, '\\', '/');
|
||||
$files[$k] = $file;
|
||||
}
|
||||
$this->_fileList = implode(',', $files);
|
||||
$this->_filePaths = $files;
|
||||
}
|
||||
|
||||
public function setGroup($key, $checkLastModified = true)
|
||||
{
|
||||
$this->_groupKey = $key;
|
||||
if ($checkLastModified) {
|
||||
$gcFile = (null === $this->_groupsConfigFile)
|
||||
? dirname(dirname(dirname(dirname(__FILE__)))) . '/groupsConfig.php'
|
||||
: $this->_groupsConfigFile;
|
||||
if (is_file($gcFile)) {
|
||||
$gc = (require $gcFile);
|
||||
if (! $this->groupsConfigFile) {
|
||||
$this->groupsConfigFile = dirname(dirname(dirname(dirname(__FILE__)))) . '/groupsConfig.php';
|
||||
}
|
||||
if (is_file($this->groupsConfigFile)) {
|
||||
$gc = (require $this->groupsConfigFile);
|
||||
if (isset($gc[$key])) {
|
||||
$this->_sniffLastModified($gc[$key]);
|
||||
$this->_lastModified = self::getLastModified($gc[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setPathToMin($path)
|
||||
|
||||
public static function getLastModified($sources, $lastModified = 0)
|
||||
{
|
||||
if (0 === strpos($path, '.')) {
|
||||
// relative path
|
||||
$path = dirname(__FILE__) . "/" . $path;
|
||||
}
|
||||
$file = realpath(rtrim($path, '/\\') . '/groupsConfig.php');
|
||||
if (! $file) {
|
||||
return false;
|
||||
}
|
||||
$this->_groupsConfigFile = $file;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected $_groupKey = null; // if present, URI will be like g=...
|
||||
protected $_fileList = '';
|
||||
protected $_groupsConfigArray = array();
|
||||
protected $_groupsConfigFile = null;
|
||||
protected $_lastModified = null;
|
||||
|
||||
protected function _sniffLastModified($sources)
|
||||
{
|
||||
$max = 0;
|
||||
$max = $lastModified;
|
||||
foreach ((array)$sources as $source) {
|
||||
if ($source instanceof Minify_Source) {
|
||||
if (is_object($source) && isset($source->lastModified)) {
|
||||
$max = max($max, $source->lastModified);
|
||||
} elseif (is_string($source)) {
|
||||
if (0 === strpos($source, '//')) {
|
||||
@ -125,14 +125,20 @@ class Minify_HTML_Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_lastModified = $max;
|
||||
return $max;
|
||||
}
|
||||
|
||||
protected $_groupKey = null; // if present, URI will be like g=...
|
||||
protected $_filePaths = array();
|
||||
protected $_lastModified = null;
|
||||
|
||||
|
||||
/**
|
||||
* In a given array of strings, find the character they all have at
|
||||
* a particular index
|
||||
* @param Array arr array of strings
|
||||
* @param Number pos index to check
|
||||
*
|
||||
* @param array $arr array of strings
|
||||
* @param int $pos index to check
|
||||
* @return mixed a common char or '' if any do not match
|
||||
*/
|
||||
protected static function _getCommonCharAtPos($arr, $pos) {
|
||||
@ -140,7 +146,7 @@ class Minify_HTML_Helper {
|
||||
$c = $arr[0][$pos];
|
||||
if ($c === '' || $l === 1)
|
||||
return $c;
|
||||
for ($i = 1; $i < l; ++$i)
|
||||
for ($i = 1; $i < $l; ++$i)
|
||||
if ($arr[$i][$pos] !== $c)
|
||||
return '';
|
||||
return $c;
|
||||
@ -148,37 +154,40 @@ class Minify_HTML_Helper {
|
||||
|
||||
/**
|
||||
* Get the shortest URI to minify the set of source files
|
||||
* @param Array sources URIs
|
||||
*//*
|
||||
,getBestUri : function (sources) {
|
||||
var pos = 0
|
||||
,base = ''
|
||||
,c;
|
||||
*
|
||||
* @param array $paths root-relative URIs of files
|
||||
* @param string $minRoot root-relative URI of the "min" application
|
||||
*/
|
||||
protected static function _getShortestUri($paths, $minRoot = '/min/') {
|
||||
$pos = 0;
|
||||
$base = '';
|
||||
$c;
|
||||
while (true) {
|
||||
c = MUB.getCommonCharAtPos(sources, pos);
|
||||
if (c === '')
|
||||
$c = self::_getCommonCharAtPos($paths, $pos);
|
||||
if ($c === '') {
|
||||
break;
|
||||
else
|
||||
base += c;
|
||||
++pos;
|
||||
}
|
||||
base = base.replace(/[^\/]+$/, '');
|
||||
var uri = MUB._minRoot + 'f=' + sources.join(',');
|
||||
if (base.charAt(base.length - 1) === '/') {
|
||||
// we have a base dir!
|
||||
var basedSources = sources
|
||||
,i
|
||||
,l = sources.length;
|
||||
for (i = 0; i < l; ++i) {
|
||||
basedSources[i] = sources[i].substr(base.length);
|
||||
} else {
|
||||
$base .= $c;
|
||||
}
|
||||
base = base.substr(0, base.length - 1);
|
||||
var bUri = MUB._minRoot + 'b=' + base + '&f=' + basedSources.join(',');
|
||||
//window.console && console.log([uri, bUri]);
|
||||
uri = uri.length < bUri.length
|
||||
? uri
|
||||
: bUri;
|
||||
++$pos;
|
||||
}
|
||||
return uri;
|
||||
}//*/
|
||||
$base = preg_replace('@[^/]+$@', '', $base);
|
||||
$uri = $minRoot . 'f=' . implode(',', $paths);
|
||||
|
||||
if (substr($base, -1) === '/') {
|
||||
// we have a base dir!
|
||||
$basedPaths = $paths;
|
||||
$l = count($paths);
|
||||
for ($i = 0; $i < $l; ++$i) {
|
||||
$basedPaths[$i] = substr($paths[$i], strlen($base));
|
||||
}
|
||||
$base = substr($base, 0, strlen($base) - 1);
|
||||
$bUri = $minRoot . 'b=' . $base . '&f=' . implode(',', $basedPaths);
|
||||
|
||||
$uri = strlen($uri) < strlen($bUri)
|
||||
? $uri
|
||||
: $bUri;
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
}
|
||||
|
130
min/utils.php
130
min/utils.php
@ -2,89 +2,73 @@
|
||||
/**
|
||||
* Utility functions for generating URIs in HTML files
|
||||
*
|
||||
* Before including this file, /min/lib must be in your include_path.
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
require_once 'Minify/Build.php';
|
||||
require_once dirname(__FILE__) . '/lib/Minify/HTML/Helper.php';
|
||||
|
||||
|
||||
/**
|
||||
* Get a timestamped URI to a minified resource using the default Minify install
|
||||
/*
|
||||
* Get an HTML-escaped Minify URI for a group or set of files. By default, URIs
|
||||
* will contain timestamps to allow far-future Expires headers.
|
||||
*
|
||||
* <code>
|
||||
* <link rel="stylesheet" type="text/css" href="<?php echo Minify_groupUri('css'); ?>" />
|
||||
* <script type="text/javascript" src="<?php echo Minify_groupUri('js'); ?>"></script>
|
||||
* <link rel="stylesheet" type="text/css" href="<?= Minify_getUri('css'); ?>" />
|
||||
* <script src="<?= Minify_getUri('js'); ?>"></script>
|
||||
* <script src="<?= Minify_getUri(array(
|
||||
* '//scripts/file1.js'
|
||||
* ,'//scripts/file2.js'
|
||||
* )); ?>"></script>
|
||||
* </code>
|
||||
*
|
||||
* If you do not want ampersands as HTML entities, set Minify_Build::$ampersand = "&"
|
||||
* before using this function.
|
||||
*
|
||||
* @param string $group a key from groupsConfig.php
|
||||
* @param boolean $modRewriteWorking (default false) Set to true if the RewriteRule
|
||||
* directives in .htaccess are functional. This will remove the "?" from URIs, making them
|
||||
* more cacheable by proxies.
|
||||
* @param mixed $keyOrFiles a group key or array of file paths/URIs
|
||||
* @param array $opts options:
|
||||
* 'farExpires' : (default true) append a modified timestamp for cache revving
|
||||
* 'debug' : (default false) append debug flag
|
||||
* 'charset' : (default 'UTF-8') for htmlspecialchars
|
||||
* 'minAppUri' : (default '/min') URI of min directory
|
||||
* 'rewriteWorks' : (default true) does mod_rewrite work in min app?
|
||||
* 'groupsConfigFile' : specify if different
|
||||
* @return string
|
||||
*/
|
||||
function Minify_groupUri($group, $modRewriteWorking = false)
|
||||
{
|
||||
$path = $modRewriteWorking
|
||||
? "/g={$group}"
|
||||
: "/?g={$group}";
|
||||
return _Minify_getBuild($group)->uri(
|
||||
'/' . basename(dirname(__FILE__)) . $path
|
||||
,$modRewriteWorking
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the last modification time of the source js/css files used by Minify to
|
||||
* build the page.
|
||||
*
|
||||
* If you're caching the output of Minify_groupUri(), you'll want to rebuild
|
||||
* the cache if it's older than this timestamp.
|
||||
*
|
||||
* <code>
|
||||
* // simplistic HTML cache system
|
||||
* $file = '/path/to/cache/file';
|
||||
* if (! file_exists($file) || filemtime($file) < Minify_groupsMtime(array('js', 'css'))) {
|
||||
* // (re)build cache
|
||||
* $page = buildPage(); // this calls Minify_groupUri() for js and css
|
||||
* file_put_contents($file, $page);
|
||||
* echo $page;
|
||||
* exit();
|
||||
* }
|
||||
* readfile($file);
|
||||
* </code>
|
||||
*
|
||||
* @param array $groups an array of keys from groupsConfig.php
|
||||
* @return int Unix timestamp of the latest modification
|
||||
*/
|
||||
function Minify_groupsMtime($groups)
|
||||
{
|
||||
$max = 0;
|
||||
foreach ((array)$groups as $group) {
|
||||
$max = max($max, _Minify_getBuild($group)->lastModified);
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group a key from groupsConfig.php
|
||||
* @return Minify_Build
|
||||
* @private
|
||||
*/
|
||||
function _Minify_getBuild($group)
|
||||
function Minify_getUri($keyOrFiles, $opts = array())
|
||||
{
|
||||
static $builds = array();
|
||||
static $gc = false;
|
||||
if (false === $gc) {
|
||||
$gc = (require dirname(__FILE__) . '/groupsConfig.php');
|
||||
}
|
||||
if (! isset($builds[$group])) {
|
||||
$builds[$group] = new Minify_Build($gc[$group]);
|
||||
}
|
||||
return $builds[$group];
|
||||
return Minify_HTML_Helper::getUri($keyOrFiles, $opts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the last modification time of several source js/css files. If you're
|
||||
* caching the output of Minify_getUri(), you might want to know if one of the
|
||||
* dependent source files has changed so you can update the HTML.
|
||||
*
|
||||
* Since this makes a bunch of stat() calls, you might not want to check this
|
||||
* on every request.
|
||||
*
|
||||
* @param array $keysAndFiles group keys and/or file paths/URIs.
|
||||
* @return int latest modification time of all given keys/files
|
||||
*/
|
||||
function Minify_mtime($keysAndFiles, $groupsConfigFile = null)
|
||||
{
|
||||
$gc = null;
|
||||
if (! $groupsConfigFile) {
|
||||
$groupsConfigFile = dirname(__FILE__) . '/groupsConfig.php';
|
||||
}
|
||||
$sources = array();
|
||||
foreach ($keysAndFiles as $keyOrFile) {
|
||||
if (is_object($keyOrFile)
|
||||
|| 0 === strpos($keyOrFile, '/')
|
||||
|| 1 === strpos($keyOrFile, ':\\')) {
|
||||
// a file/source obj
|
||||
$sources[] = $keyOrFile;
|
||||
} else {
|
||||
if (! $gc) {
|
||||
$gc = (require $groupsConfigFile);
|
||||
}
|
||||
foreach ($gc[$keyOrFile] as $source) {
|
||||
$sources[] = $source;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Minify_HTML_Helper::getLastModified($sources);
|
||||
}
|
||||
|
8
min_unit_tests/_test_files/htmlHelper_groupsConfig.php
Normal file
8
min_unit_tests/_test_files/htmlHelper_groupsConfig.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'css' => array(
|
||||
'//_test_files/css/paths_prepend.css'
|
||||
,'//_test_files/css/styles.css'
|
||||
)
|
||||
);
|
@ -7,42 +7,62 @@ function test_Minify_HTML_Helper()
|
||||
{
|
||||
global $thisDir;
|
||||
|
||||
$realDocRoot = $_SERVER['DOCUMENT_ROOT'];
|
||||
$_SERVER['DOCUMENT_ROOT'] = $thisDir;
|
||||
|
||||
$file1 = $thisDir . '/_test_files/css/paths_prepend.css';
|
||||
$file2 = $thisDir . '/_test_files/css/styles.css';
|
||||
$maxTime = max(filemtime($file1), filemtime($file2));
|
||||
|
||||
$path1 = '/' . dirname($_SERVER['SCRIPT_NAME']) . '/_test_files/css/paths_prepend.css';
|
||||
$path2 = '/' . dirname($_SERVER['SCRIPT_NAME']) . '/_test_files/css/styles.css';
|
||||
$uri1 = '//_test_files/css/paths_prepend.css';
|
||||
$uri2 = '//_test_files/css/styles.css';
|
||||
|
||||
echo Minify_HTML_Helper::filesUri(array($path1, $path2)) . "\n";
|
||||
echo Minify_HTML_Helper::filesUri(array($file1, $file2)) . "\n";
|
||||
echo Minify_HTML_Helper::groupUri('notRealGroup') . "\n";
|
||||
$expected = "/min/b=_test_files/css&f=paths_prepend.css,styles.css&{$maxTime}";
|
||||
$actual = Minify_HTML_Helper::getUri(array($uri1, $uri2));
|
||||
$passed = assertTrue($actual === $expected, 'Minify_HTML_Helper : given URIs');
|
||||
|
||||
$expected = "/min/b=_test_files/css&f=paths_prepend.css,styles.css&{$maxTime}";
|
||||
$actual = Minify_HTML_Helper::getUri(array($file1, $file2));
|
||||
$passed = assertTrue($actual === $expected, 'Minify_HTML_Helper : given filepaths');
|
||||
|
||||
//echo Minify_HTML_Helper::filesUri(array($file1, $file2));
|
||||
$expected = "/min/g=notRealGroup&debug";
|
||||
$actual = Minify_HTML_Helper::getUri('notRealGroup', array('debug' => true));
|
||||
$passed = assertTrue($actual === $expected, 'Minify_HTML_Helper : non-existent group & debug');
|
||||
|
||||
/*
|
||||
$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');
|
||||
|
||||
require_once 'Minify.php';
|
||||
$b = new Minify_Build(array(
|
||||
$file1
|
||||
,new Minify_Source(array('filepath' => $file2))
|
||||
$expected = "/myApp/min/?g=css&{$maxTime}";
|
||||
$actual = Minify_HTML_Helper::getUri('css', array(
|
||||
'rewriteWorks' => false
|
||||
,'minAppUri' => '/myApp/min/'
|
||||
,'groupsConfigFile' => $thisDir . '/_test_files/htmlHelper_groupsConfig.php'
|
||||
));
|
||||
|
||||
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');
|
||||
//*/
|
||||
$passed = assertTrue($actual === $expected, 'Minify_HTML_Helper : existing group');
|
||||
|
||||
$utilsFile = dirname(dirname(__FILE__)) . '/min/utils.php';
|
||||
if (is_file($utilsFile)) {
|
||||
require_once $utilsFile;
|
||||
|
||||
$fiveSecondsAgo = $_SERVER['REQUEST_TIME'] - 5;
|
||||
$obj = new stdClass();
|
||||
$obj->lastModified = $fiveSecondsAgo;
|
||||
|
||||
$output = Minify_mtime(array(
|
||||
$uri1
|
||||
,$uri2
|
||||
,$obj
|
||||
));
|
||||
$passed = assertTrue($output === $fiveSecondsAgo, 'utils.php : Minify_mtime w/ files & obj');
|
||||
|
||||
$obj = new stdClass();
|
||||
$obj->lastModified = strtotime('2000-01-01');
|
||||
$output = Minify_mtime(array(
|
||||
$obj
|
||||
,'css'
|
||||
), $thisDir . '/_test_files/htmlHelper_groupsConfig.php');
|
||||
$passed = assertTrue($output === $maxTime, 'utils.php : Minify_mtime w/ obj & group');
|
||||
|
||||
}
|
||||
|
||||
$_SERVER['DOCUMENT_ROOT'] = $realDocRoot;
|
||||
}
|
||||
|
||||
test_Minify_HTML_Helper();
|
@ -2,6 +2,7 @@
|
||||
|
||||
require 'test_Minify.php';
|
||||
require 'test_Minify_Build.php';
|
||||
require 'test_Minify_HTML_Helper.php';
|
||||
require 'test_Minify_Cache_APC.php';
|
||||
require 'test_Minify_Cache_File.php';
|
||||
require 'test_Minify_Cache_Memcache.php';
|
||||
|
Loading…
x
Reference in New Issue
Block a user