V 3.5 RC 1

This commit is contained in:
Romain Neutron
2011-12-05 00:23:28 +01:00
parent 6f1ee368aa
commit 4c5b7eb658
5563 changed files with 466984 additions and 985416 deletions

View File

@@ -1,41 +1,39 @@
<?php
/**
* Class Minify_Controller_Base
* Class Minify_Controller_Base
* @package Minify
*/
/**
* Base class for Minify controller
*
*
* The controller class validates a request and uses it to create sources
* for minification and set options like contentType. It's also responsible
* for loading minifier code upon request.
*
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*
* @todo add static function to ease setting currentPath for CSS files
* (see line 83 of Version1.php)
*/
abstract class Minify_Controller_Base {
/**
* Setup controller sources
*
* You must override this method in your subclass controller to set
* $this->sources. If the request is NOT valid, make sure $this->sources
* is left an empty array. Then strip any controller-specific options from
* $options and return it.
*
* Setup controller sources and set an needed options for Minify::source
*
* You must override this method in your subclass controller to set
* $this->sources. If the request is NOT valid, make sure $this->sources
* is left an empty array. Then strip any controller-specific options from
* $options and return it. To serve files, $this->sources must be an array of
* Minify_Source objects.
*
* @param array $options controller and Minify options
*
* @param array $options Minify options
*
* return array $options Minify::serve options
*/
abstract public function setupSources($options);
/**
* Get default Minify options for this controller.
*
*
* Override in subclass to change defaults
*
* @return array options for Minify
@@ -47,52 +45,54 @@ abstract class Minify_Controller_Base {
,'encodeMethod' => null // determine later
,'encodeLevel' => 9
,'minifierOptions' => array() // no minifier options
,'contentTypeCharset' => 'UTF-8'
,'contentTypeCharset' => 'utf-8'
,'maxAge' => 1800 // 30 minutes
,'rewriteCssUris' => true
,'bubbleCssImports' => false
,'quiet' => false // serve() will send headers and output
,'debug' => false
// 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.
,'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
);
}
}
/**
* Get default minifiers for this controller.
*
*
* Override in subclass to change defaults
*
* @return array minifier callbacks for common types
*/
public function getDefaultMinifers() {
$ret[Minify::TYPE_JS] = array('Minify_Javascript', 'minify');
$ret[Minify::TYPE_JS] = array('JSMin', 'minify');
$ret[Minify::TYPE_CSS] = array('Minify_CSS', 'minify');
$ret[Minify::TYPE_HTML] = array('Minify_HTML', 'minify');
return $ret;
}
/**
* Load any code necessary to execute the given minifier callback.
*
*
* The controller is responsible for loading minification code on demand
* via this method. This built-in function will only load classes for
* static method callbacks where the class isn't already defined. It uses
* the PEAR convention, so, given array('Jimmy_Minifier', 'minCss'), this
* function will include 'Jimmy/Minifier.php'
*
* the PEAR convention, so, given array('Jimmy_Minifier', 'minCss'), this
* function will include 'Jimmy/Minifier.php'.
*
* If you need code loaded on demand and this doesn't suit you, you'll need
* to override this function in your subclass.
* to override this function in your subclass.
* @see Minify_Controller_Page::loadMinifier()
*
*
* @param callback $minifierCallback callback of minifier function
*
*
* @return null
*/
public function loadMinifier($minifierCallback)
@@ -100,20 +100,23 @@ abstract class Minify_Controller_Base {
if (is_array($minifierCallback)
&& is_string($minifierCallback[0])
&& !class_exists($minifierCallback[0], false)) {
require str_replace('_', '/', $minifierCallback[0]) . '.php';
}
}
/**
* Is a user-given file within an allowable directory, existing,
* and having an extension js/css/html/txt
*
* and having an extension js/css/html/txt ?
*
* This is a convenience function for controllers that have to accept
* user-given paths
*
* @param string $file full file path (already processed by realpath())
* @param array $safeDirs directories where files are safe to serve
*
* @param array $safeDirs directories where files are safe to serve. Files can also
* be in subdirectories of these directories.
*
* @return bool file is safe
*/
public static function _fileIsSafe($file, $safeDirs)
@@ -130,22 +133,23 @@ abstract class Minify_Controller_Base {
return false;
}
list($revExt) = explode('.', strrev($base));
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt'));
}
/**
* @var array instances of Minify_Source, which provide content and
* any individual minification needs.
*
*
* @see Minify_Source
*/
public $sources = array();
/**
* Mix in default controller options with user-given options
*
*
* @param array $options user options
*
*
* @return array mixed options
*/
public final function mixInDefaultOptions($options)
@@ -159,18 +163,19 @@ abstract class Minify_Controller_Base {
$ret['minifiers'] = array_merge(
$this->getDefaultMinifers(), $options['minifiers']
);
return $ret;
}
/**
* Analyze sources (if there are any) and set $options 'contentType'
* Analyze sources (if there are any) and set $options 'contentType'
* and 'lastModifiedTime' if they already aren't.
*
*
* @param array $options options for Minify
*
*
* @return array options for Minify
*/
public final function analyzeSources($options = array())
public final function analyzeSources($options = array())
{
if ($this->sources) {
if (! isset($options['contentType'])) {
@@ -183,8 +188,19 @@ abstract class Minify_Controller_Base {
$max = max($source->lastModified, $max);
}
$options['lastModifiedTime'] = $max;
}
}
}
return $options;
}
/**
* Send message to the Minify logger
* @param string $msg
* @return null
*/
protected function log($msg) {
require_once 'Minify/Logger.php';
Minify_Logger::log($msg);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/**
* Class Minify_Controller_Files
* Class Minify_Controller_Files
* @package Minify
*/
@@ -8,7 +8,7 @@ require_once 'Minify/Controller/Base.php';
/**
* Controller class for minifying a set of files
*
*
* E.g. the following would serve the minified Javascript for a site
* <code>
* Minify::serve('Files', array(
@@ -19,7 +19,7 @@ require_once 'Minify/Controller/Base.php';
* )
* ));
* </code>
*
*
* As a shortcut, the controller will replace "//" at the beginning
* of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'.
*
@@ -27,22 +27,29 @@ require_once 'Minify/Controller/Base.php';
* @author Stephen Clay <steve@mrclay.org>
*/
class Minify_Controller_Files extends Minify_Controller_Base {
/**
* Set up file sources
*
*
* @param array $options controller and Minify options
* @return array Minify options
*
*
* Controller options:
*
*
* 'files': (required) array of complete file paths, or a single path
*/
public function setupSources($options) {
// strip controller options
$files = (array)$options['files'];
$files = $options['files'];
// if $files is a single object, casting will break it
if (is_object($files)) {
$files = array($files);
} elseif (! is_array($files)) {
$files = (array)$files;
}
unset($options['files']);
$sources = array();
foreach ($files as $file) {
if ($file instanceof Minify_Source) {
@@ -52,19 +59,21 @@ class Minify_Controller_Files extends Minify_Controller_Base {
if (0 === strpos($file, '//')) {
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
}
$file = realpath($file);
if (file_exists($file)) {
$realPath = realpath($file);
if (is_file($realPath)) {
$sources[] = new Minify_Source(array(
'filepath' => $file
));
'filepath' => $realPath
));
} else {
// file not found
$this->log("The path \"{$file}\" could not be found (or was not a file)");
return $options;
}
}
if ($sources) {
$this->sources = $sources;
}
return $options;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/**
* Class Minify_Controller_Groups
* Class Minify_Controller_Groups
* @package Minify
*/
@@ -9,56 +9,66 @@ require_once 'Minify/Controller/Base.php';
/**
* Controller class for serving predetermined groups of minimized sets, selected
* by PATH_INFO
*
*
* <code>
* Minify::serve('Groups', array(
* Minify::serve('Groups', array(
* 'groups' => array(
* 'css' => array('//css/type.css', '//css/layout.css')
* ,'js' => array('//js/jquery.js', '//js/site.js')
* )
* ));
* </code>
*
*
* If the above code were placed in /serve.php, it would enable the URLs
* /serve.php/js and /serve.php/css
*
*
* As a shortcut, the controller will replace "//" at the beginning
* of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'.
*
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*/
class Minify_Controller_Groups extends Minify_Controller_Base {
/**
* Set up groups of files as sources
*
*
* @param array $options controller and Minify options
* @return array Minify options
*
*
* Controller options:
*
*
* 'groups': (required) array mapping PATH_INFO strings to arrays
* of complete file paths. @see Minify_Controller_Groups
* of complete file paths. @see Minify_Controller_Groups
*/
public function setupSources($options) {
// strip controller options
$groups = $options['groups'];
unset($options['groups']);
// mod_fcgid places PATH_INFO in ORIG_PATH_INFO
$pi = isset($_SERVER['ORIG_PATH_INFO'])
? substr($_SERVER['ORIG_PATH_INFO'], 1)
? substr($_SERVER['ORIG_PATH_INFO'], 1)
: (isset($_SERVER['PATH_INFO'])
? substr($_SERVER['PATH_INFO'], 1)
? substr($_SERVER['PATH_INFO'], 1)
: false
);
if (false === $pi || ! isset($groups[$pi])) {
// no PATH_INFO or not a valid group
$this->log("Missing PATH_INFO or no group set for \"$pi\"");
return $options;
}
$sources = array();
foreach ((array)$groups[$pi] as $file) {
$files = $groups[$pi];
// if $files is a single object, casting will break it
if (is_object($files)) {
$files = array($files);
} elseif (! is_array($files)) {
$files = (array)$files;
}
foreach ($files as $file) {
if ($file instanceof Minify_Source) {
$sources[] = $file;
continue;
@@ -66,19 +76,21 @@ class Minify_Controller_Groups extends Minify_Controller_Base {
if (0 === strpos($file, '//')) {
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
}
$file = realpath($file);
if (file_exists($file)) {
$realPath = realpath($file);
if (is_file($realPath)) {
$sources[] = new Minify_Source(array(
'filepath' => $file
));
'filepath' => $realPath
));
} else {
// file doesn't exist
$this->log("The path \"{$file}\" could not be found (or was not a file)");
return $options;
}
}
if ($sources) {
$this->sources = $sources;
}
return $options;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/**
* Class Minify_Controller_MinApp
* Class Minify_Controller_MinApp
* @package Minify
*/
@@ -8,18 +8,18 @@ require_once 'Minify/Controller/Base.php';
/**
* Controller class for requests to /min/index.php
*
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*/
class Minify_Controller_MinApp extends Minify_Controller_Base {
/**
* Set up groups of files as sources
*
*
* @param array $options controller and Minify options
* @return array Minify options
*
*
*/
public function setupSources($options) {
// filter controller options
@@ -28,7 +28,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
'allowDirs' => '//'
,'groupsOnly' => false
,'groups' => array()
,'maxFiles' => 10
,'maxFiles' => 10
)
,(isset($options['minApp']) ? $options['minApp'] : array())
);
@@ -37,9 +37,19 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
if (isset($_GET['g'])) {
// try groups
if (! isset($cOptions['groups'][$_GET['g']])) {
$this->log("A group configuration for \"{$_GET['g']}\" was not set");
return $options;
}
foreach ((array)$cOptions['groups'][$_GET['g']] as $file) {
$files = $cOptions['groups'][$_GET['g']];
// if $files is a single object, casting will break it
if (is_object($files)) {
$files = array($files);
} elseif (! is_array($files)) {
$files = (array)$files;
}
foreach ($files as $file) {
if ($file instanceof Minify_Source) {
$sources[] = $file;
continue;
@@ -51,9 +61,10 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
if (is_file($file)) {
$sources[] = new Minify_Source(array(
'filepath' => $file
));
));
} else {
// file doesn't exist
$this->log("The path \"{$file}\" could not be found (or was not a file)");
return $options;
}
}
@@ -61,7 +72,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
// try user files
// The following restrictions are to limit the URLs that minify will
// respond to. Ideally there should be only one way to reference a file.
if (// verify at least one file, files are single comma separated,
if (// verify at least one file, files are single comma separated,
// and are all same extension
! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'])
// no "//"
@@ -71,11 +82,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
// no "./"
|| preg_match('/(?:^|[^\\.])\\.\\//', $_GET['f'])
) {
$this->log("GET param 'f' invalid (see MinApp.php line 63)");
return $options;
}
$files = explode(',', $_GET['f']);
if (count($files) > $cOptions['maxFiles'] || $files != array_unique($files)) {
// too many or duplicate files
$this->log("Too many or duplicate files specified");
return $options;
}
if (isset($_GET['b'])) {
@@ -84,8 +98,10 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
&& false === strpos($_GET['b'], '..')
&& $_GET['b'] !== '.') {
// valid base
$base = "/{$_GET['b']}/";
$base = "/{$_GET['b']}/";
} else {
$this->log("GET param 'b' invalid (see MinApp.php line 84)");
return $options;
}
} else {
@@ -96,21 +112,29 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir));
}
foreach ($files as $file) {
$file = realpath($_SERVER['DOCUMENT_ROOT'] . $base . $file);
// don't allow unsafe or duplicate files
if (parent::_fileIsSafe($file, $allowDirs)) {
$path = $_SERVER['DOCUMENT_ROOT'] . $base . $file;
$file = realpath($path);
if (false === $file) {
$this->log("Path \"{$path}\" failed realpath()");
return $options;
} elseif (! parent::_fileIsSafe($file, $allowDirs)) {
$this->log("Path \"{$path}\" failed Minify_Controller_Base::_fileIsSafe()");
return $options;
} else {
$sources[] = new Minify_Source(array(
'filepath' => $file
));
} else {
// unsafe file
return $options;
}
}
}
if ($sources) {
$this->sources = $sources;
} else {
$this->log("No sources to serve");
}
return $options;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/**
* Class Minify_Controller_Page
* Class Minify_Controller_Page
* @package Minify
*/
@@ -8,30 +8,30 @@ require_once 'Minify/Controller/Base.php';
/**
* Controller class for serving a single HTML page
*
*
* @link http://code.google.com/p/minify/source/browse/trunk/web/examples/1/index.php#59
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*/
class Minify_Controller_Page extends Minify_Controller_Base {
/**
* Set up source of HTML content
*
*
* @param array $options controller and Minify options
* @return array Minify options
*
*
* Controller options:
*
*
* 'content': (required) HTML markup
*
*
* 'id': (required) id of page (string for use in server-side caching)
*
*
* 'lastModifiedTime': timestamp of when this content changed. This
* is recommended to allow both server and client-side caching.
*
* 'minifyAll': should all CSS and Javascript blocks be individually
* minified? (default false)
*
* 'minifyAll': should all CSS and Javascript blocks be individually
* minified? (default false)
*
* @todo Add 'file' option to read HTML file.
*/
@@ -52,22 +52,20 @@ class Minify_Controller_Page extends Minify_Controller_Base {
// this will be the 2nd argument passed to Minify_HTML::minify()
$sourceSpec['minifyOptions'] = array(
'cssMinifier' => array('Minify_CSS', 'minify')
,'jsMinifier' => array('Minify_Javascript', 'minify')
,'jsMinifier' => array('JSMin', 'minify')
);
$this->_loadCssJsMinifiers = true;
unset($options['minifyAll']);
}
$this->sources[] = new Minify_Source($sourceSpec);
// may not be needed
//$options['minifier'] = array('Minify_HTML', 'minify');
$options['contentType'] = Minify::TYPE_HTML;
return $options;
}
protected $_loadCssJsMinifiers = false;
/**
* @see Minify_Controller_Base::loadMinifier()
*/
@@ -76,8 +74,8 @@ class Minify_Controller_Page extends Minify_Controller_Base {
if ($this->_loadCssJsMinifiers) {
// Minify will not call for these so we must manually load
// them when Minify/HTML.php is called for.
require 'Minify/CSS.php';
require 'Minify/Javascript.php';
require_once 'Minify/CSS.php';
require_once 'JSMin.php';
}
parent::loadMinifier($minifierCallback); // load Minify/HTML.php
}

View File

@@ -1,6 +1,6 @@
<?php
/**
* Class Minify_Controller_Version1
* Class Minify_Controller_Version1
* @package Minify
*/
@@ -8,22 +8,22 @@ require_once 'Minify/Controller/Base.php';
/**
* Controller class for emulating version 1 of minify.php
*
*
* <code>
* Minify::serve('Version1');
* </code>
*
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*/
class Minify_Controller_Version1 extends Minify_Controller_Base {
/**
* Set up groups of files as sources
*
*
* @param array $options controller and Minify options
* @return array Minify options
*
*
*/
public function setupSources($options) {
self::_setupDefines();
@@ -39,7 +39,7 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
// The following restrictions are to limit the URLs that minify will
// respond to. Ideally there should be only one way to reference a file.
if (! isset($_GET['files'])
// verify at least one file, files are single comma separated,
// verify at least one file, files are single comma separated,
// and are all same extension
|| ! preg_match('/^[^,]+\\.(css|js)(,[^,]+\\.\\1)*$/', $_GET['files'], $m)
// no "//" (makes URL rewriting easier)
@@ -52,33 +52,33 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
return $options;
}
$extension = $m[1];
$files = explode(',', $_GET['files']);
if (count($files) > MINIFY_MAX_FILES) {
return $options;
}
// strings for prepending to relative/absolute paths
$prependRelPaths = dirname($_SERVER['SCRIPT_FILENAME'])
. DIRECTORY_SEPARATOR;
$prependAbsPaths = $_SERVER['DOCUMENT_ROOT'];
$sources = array();
$goodFiles = array();
$hasBadSource = false;
$allowDirs = isset($options['allowDirs'])
? $options['allowDirs']
: MINIFY_BASE_DIR;
foreach ($files as $file) {
// prepend appropriate string for abs/rel paths
$file = ($file[0] === '/' ? $prependAbsPaths : $prependRelPaths) . $file;
// make sure a real file!
$file = realpath($file);
// don't allow unsafe or duplicate files
if (parent::_fileIsSafe($file, $allowDirs)
&& !in_array($file, $goodFiles))
if (parent::_fileIsSafe($file, $allowDirs)
&& !in_array($file, $goodFiles))
{
$goodFiles[] = $file;
$srcOptions = array(
@@ -96,9 +96,10 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
if (! MINIFY_REWRITE_CSS_URLS) {
$options['rewriteCssUris'] = false;
}
return $options;
}
private static function _setupDefines()
{
$defaults = array(