1
0
mirror of https://github.com/mrclay/minify.git synced 2025-08-13 17:44:00 +02:00

Merge pull request #512 from mrclay/deps

Large restructuring
This commit is contained in:
Steve Clay
2016-03-10 18:48:49 -05:00
30 changed files with 629 additions and 637 deletions

View File

@@ -1,12 +1,15 @@
## 3.0 progress
* Better CSS minification via Túbal Martín's CSSMin
* Docs overhaul
* New API incompatible with the 2.x versions
## Version 3.0.0 (unreleased)
* The project root is now what is deployed as `min`
* Installation requires use of Composer to install dependencies
* Removes JSMin+ (unmaintained, high memory usage)
* Removes DooDigestAuth
* Removes Minify_Loader (uses Composer)
* Removes Minify_Logger (uses Monolog)
* The Minify, source, and controller components have changed APIs
* Better CSS minification via Túbal Martín's CSSMin
* Add config option for simply concatenating files
* Add config option for altering creation of Minify/MinApp objects
* Missing spec no longer redirects, instead links to docs
* Removed JSMin+ (unmaintained, high memory usage)
## Version 2.2.1 (2014-10-30)
* Builder styled with Bootstrap (thanks to help from acidvertigo)

View File

@@ -1,8 +1,6 @@
<?php
/**
* Sets up autoloader for Minify
*
* @package Minify
* Sets up autoloading and returns the Minify\App
*/
call_user_func(function () {
@@ -15,3 +13,5 @@ call_user_func(function () {
}
require $file;
});
return new \Minify\App(__DIR__);

View File

@@ -1,13 +1,14 @@
<?php
// check for auto-encoding
$encodeOutput = (function_exists('gzdeflate')
&& !ini_get('zlib.output_compression'));
$app = (require __DIR__ . '/../bootstrap.php');
/* @var \Minify\App $app */
$config = $app->config;
// recommend $min_symlinks setting for Apache UserDir
$symlinkOption = '';
if (0 === strpos($_SERVER["SERVER_SOFTWARE"], 'Apache/')
&& preg_match('@^/\\~(\\w+)/@', $_SERVER['REQUEST_URI'], $m)
if (0 === strpos($app->env->server("SERVER_SOFTWARE"), 'Apache/')
&& preg_match('@^/\\~(\\w+)/@', $app->env->server('REQUEST_URI'), $m)
) {
$userDir = DIRECTORY_SEPARATOR . $m[1] . DIRECTORY_SEPARATOR;
if (false !== strpos(__FILE__, $userDir)) {
@@ -18,24 +19,19 @@ if (0 === strpos($_SERVER["SERVER_SOFTWARE"], 'Apache/')
}
}
require __DIR__ . '/../bootstrap.php';
require __DIR__ . '/../config.php';
if (! $min_enableBuilder) {
if (!$config->enableBuilder) {
header('Content-Type: text/plain');
die('This application is not enabled. See https://github.com/mrclay/minify/blob/master/docs/BuilderApp.wiki.md');
}
if (isset($min_builderPassword)
&& is_string($min_builderPassword)
&& $min_builderPassword !== '') {
DooDigestAuth::http_auth('Minify Builder', array('admin' => $min_builderPassword));
}
$cachePathCode = '';
if (! isset($min_cachePath) && ! function_exists('sys_get_temp_dir')) {
$detectedTmp = Minify_Cache_File::tmp();
$cachePathCode = "\$min_cachePath = " . var_export($detectedTmp, 1) . ';';
if ($config->builderPassword && $config->builderPassword !== '') {
$auth = new Intervention\Httpauth\Httpauth(array(
'username' => 'admin',
'password' => $config->builderPassword,
'type' => 'digest',
'realm' => 'Minify Builder',
));
$auth->secure();
}
ob_start();
@@ -79,13 +75,6 @@ b {color:#c00}
FirePHP console will report the cause of the error.
</p>
<?php if ($cachePathCode): ?>
<p class=topNote><strong>Note:</strong> <code><?php echo
htmlspecialchars($detectedTmp); ?></code> was discovered as a usable temp directory.<br>To
slightly improve performance you can hardcode this in /min/config.php:
<code><?php echo htmlspecialchars($cachePathCode); ?></code></p>
<?php endIf; ?>
<p id=minRewriteFailed class="hide"><strong>Note:</strong> Your webserver does not seem to
support mod_rewrite (used in /min/.htaccess). Your Minify URIs will contain "?", which
<a href="http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/"
@@ -106,7 +95,7 @@ and click [Update].</p>
<div id=bmUris></div>
<p><button class="btn btn-primary" id=update class=hide>Update</button></p>
<p><button class="btn btn-primary hide" id=update>Update</button></p>
<div id=results class=hide>
@@ -218,26 +207,8 @@ by Minify. E.g. <code>@import "<span class=minRoot>/min/?</span>g=css2";</code><
<?php
$content = ob_get_clean();
if (!isset($min_cachePath)) {
$min_cachePath = '';
}
if (is_string($min_cachePath)) {
$cache = new Minify_Cache_File($min_cachePath, $min_cacheFileLocking);
} else {
$cache = $min_cachePath;
}
$env = new Minify_Env();
$sourceFactory = new Minify_Source_Factory($env, array(
'uploaderHoursBehind' => $min_uploaderHoursBehind,
));
$controller = new Minify_Controller_Page($env, $sourceFactory);
$server = new Minify($cache);
$server->serve($controller, array(
$controller = new Minify_Controller_Page($app->env, $app->sourceFactory);
$minify = $app->minify->serve($controller, array(
'content' => $content,
'id' => __FILE__,
'lastModifiedTime' => max(
@@ -247,5 +218,4 @@ $server->serve($controller, array(
filemtime(__DIR__ . '/../lib/Minify.php')
),
'minifyAll' => true,
'encodeOutput' => $encodeOutput,
));

View File

@@ -5,18 +5,18 @@
* @package Minify
*/
require __DIR__ . '/../bootstrap.php';
$app = (require __DIR__ . '/../bootstrap.php');
/* @var \Minify\App $app */
$_oc = ini_get('zlib.output_compression');
// allow access only if builder is enabled
require __DIR__ . '/../config.php';
if (! $min_enableBuilder) {
if (!$app->config->enableBuilder) {
header('Location: /');
exit;
}
if (isset($_GET['hello'])) {
if ($app->env->get('hello')) {
// echo 'World!'
// try to prevent double encoding (may not have an effect)

View File

@@ -23,10 +23,13 @@
"classmap": ["tests/TestCase.php"]
},
"require": {
"php": ">=5.3.0",
"ext-pcre": "*",
"firephp/firephp-core": "~0.4.0",
"intervention/httpauth": "~2.0",
"monolog/monolog": "~1.1",
"mrclay/jsmin-php": "~2",
"php": ">=5.3.0",
"mrclay/props-dic": "^2.2",
"tubalmartin/cssmin": "~2.4.8"
},
"require-dev": {

View File

@@ -27,12 +27,8 @@ $min_builderPassword = 'admin';
/**
* Set to true to log messages to FirePHP (Firefox Firebug addon).
* Set to true to log messages to FirePHP (Firefox Firebug addon) and PHP's error_log
* Set to false for no error logging (Minify may be slightly faster).
* @link http://www.firephp.org/
*
* If you want to use a custom error logger, set this to your logger
* instance. Your object should have a method log(string $message).
*/
$min_errorLogger = false;
@@ -193,9 +189,6 @@ $min_uploaderHoursBehind = 0;
*
* You can see the default implementations (and what gets passed in) in index.php.
*/
//$min_factories['minify'] = ... a callable
//$min_factories['controller'] = ... a callable
//$min_factories['minify'] = ... a callable accepting a Minify\App object
//$min_factories['controller'] = ... a callable accepting a Minify\App object
// try to disable output_compression (may not have an effect)
ini_set('zlib.output_compression', '0');

View File

@@ -12,8 +12,8 @@
**/
return array(
// 'testJs' => array('//minify/min/quick-test.js'),
// 'testCss' => array('//minify/min/quick-test.css'),
// 'testJs' => array('//minify/quick-test.js'),
// 'testCss' => array('//minify/quick-test.css'),
// 'js' => array('//js/file1.js', '//js/file2.js'),
// 'css' => array('//css/file1.css', '//css/file2.css'),
);
);

126
index.php
View File

@@ -7,127 +7,7 @@
* @package Minify
*/
require __DIR__ . '/bootstrap.php';
$app = (require __DIR__ . '/bootstrap.php');
/* @var \Minify\App $app */
// set config path defaults
$min_configPaths = array(
'base' => __DIR__ . '/config.php',
'test' => __DIR__ . '/config-test.php',
'groups' => __DIR__ . '/groupsConfig.php',
);
// check for custom config paths
if (!empty($min_customConfigPaths) && is_array($min_customConfigPaths)) {
$min_configPaths = array_merge($min_configPaths, $min_customConfigPaths);
}
// load config
require $min_configPaths['base'];
if (isset($_GET['test'])) {
include $min_configPaths['test'];
}
// setup factories
$defaultFactories = array(
'minify' => function (Minify_CacheInterface $cache) {
return new Minify($cache);
},
'controller' => function (Minify_Env $env, Minify_Source_Factory $sourceFactory) {
return new Minify_Controller_MinApp($env, $sourceFactory);
},
);
if (!isset($min_factories)) {
$min_factories = array();
}
$min_factories = array_merge($defaultFactories, $min_factories);
// use an environment object to encapsulate all input
$server = $_SERVER;
if ($min_documentRoot) {
$server['DOCUMENT_ROOT'] = $min_documentRoot;
}
$env = new Minify_Env(array(
'server' => $server,
));
// TODO probably should do this elsewhere...
$min_serveOptions['minifierOptions']['text/css']['docRoot'] = $env->getDocRoot();
$min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
$min_serveOptions['minApp']['symlinks'] = $min_symlinks;
// auto-add targets to allowDirs
foreach ($min_symlinks as $uri => $target) {
$min_serveOptions['minApp']['allowDirs'][] = $target;
}
if ($min_allowDebugFlag) {
// TODO get rid of static stuff
$min_serveOptions['debug'] = Minify_DebugDetector::shouldDebugRequest($env);
}
if (!empty($min_concatOnly)) {
$min_serveOptions['concatOnly'] = true;
}
if ($min_errorLogger) {
if (true === $min_errorLogger) {
$min_errorLogger = FirePHP::getInstance(true);
}
// TODO get rid of global state
Minify_Logger::setLogger($min_errorLogger);
}
// check for URI versioning
if (null !== $env->get('v') || preg_match('/&\\d/', $env->server('QUERY_STRING'))) {
$min_serveOptions['maxAge'] = 31536000;
}
// need groups config?
if (null !== $env->get('g')) {
// we need groups config
$min_serveOptions['minApp']['groups'] = (require $min_configPaths['groups']);
}
// cache defaults
if (!isset($min_cachePath)) {
$min_cachePath = '';
}
if (!isset($min_cacheFileLocking)) {
$min_cacheFileLocking = true;
}
if (is_string($min_cachePath)) {
$cache = new Minify_Cache_File($min_cachePath, $min_cacheFileLocking);
} else {
// assume it meets interface.
$cache = $min_cachePath;
}
/* @var Minify_CacheInterface $cache */
$minify = call_user_func($min_factories['minify'], $cache);
/* @var Minify $minify */
if (!$env->get('f') && $env->get('g') === null) {
// no spec given
$msg = '<p>No "f" or "g" parameters were detected.</p>';
$url = 'https://github.com/mrclay/minify/blob/master/docs/CommonProblems.wiki.md#long-url-parameters-are-ignored';
$defaults = $minify->getDefaultOptions();
$minify->errorExit($defaults['badRequestHeader'], $url, $msg);
}
$sourceFactoryOptions = array();
// translate legacy setting to option for source factory
if (isset($min_serveOptions['minApp']['noMinPattern'])) {
$sourceFactoryOptions['noMinPattern'] = $min_serveOptions['minApp']['noMinPattern'];
}
if (isset($min_serveOptions['minApp']['allowDirs'])) {
$sourceFactoryOptions['allowDirs'] = $min_serveOptions['minApp']['allowDirs'];
}
$sourceFactory = new Minify_Source_Factory($env, $sourceFactoryOptions, $cache);
$controller = call_user_func($min_factories['controller'], $env, $sourceFactory);
/* @var Minify_ControllerInterface $controller */
$minify->serve($controller, $min_serveOptions);
$app->runServer();

View File

@@ -1,121 +0,0 @@
<?php
/**
* DooDigestAuth class file.
*
* @author Leng Sheng Hong <darkredz@gmail.com>
* @link http://www.doophp.com/
* @copyright Copyright &copy; 2009 Leng Sheng Hong
* @license http://www.doophp.com/license
*/
/**
* Handles HTTP digest authentication
*
* <p>HTTP digest authentication can be used with the URI router.
* HTTP digest is much more recommended over the use of HTTP Basic auth which doesn't provide any encryption.
* If you are running PHP on Apache in CGI/FastCGI mode, you would need to
* add the following line to your .htaccess for digest auth to work correctly.</p>
* <code>RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]</code>
*
* <p>This class is tested under Apache 2.2 and Cherokee web server. It should work in both mod_php and cgi mode.</p>
*
* @author Leng Sheng Hong <darkredz@gmail.com>
* @version $Id: DooDigestAuth.php 1000 2009-07-7 18:27:22
* @package doo.auth
* @since 1.0
*/
class DooDigestAuth{
/**
* Authenticate against a list of username and passwords.
*
* <p>HTTP Digest Authentication doesn't work with PHP in CGI mode,
* you have to add this into your .htaccess <code>RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]</code></p>
*
* @param string $realm Name of the authentication session
* @param array $users An assoc array of username and password: array('uname1'=>'pwd1', 'uname2'=>'pwd2')
* @param string $fail_msg Message to be displayed if the User cancel the login
* @param string $fail_url URL to be redirect if the User cancel the login
* @return string The username if login success.
*/
public static function http_auth($realm, $users, $fail_msg=NULL, $fail_url=NULL) {
$realm = "Restricted area - $realm";
//user => password
//$users = array('admin' => '1234', 'guest' => 'guest');
if(!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && strpos($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 'Digest')===0){
$_SERVER['PHP_AUTH_DIGEST'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
}
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
header('HTTP/1.1 401 Unauthorized');
if($fail_msg!=NULL)
die($fail_msg);
if($fail_url!=NULL)
die("<script>window.location.href = '$fail_url'</script>");
exit;
}
// analyze the PHP_AUTH_DIGEST variable
if (!($data = self::http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || !isset($users[$data['username']])){
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
header('HTTP/1.1 401 Unauthorized');
if($fail_msg!=NULL)
die($fail_msg);
if($fail_url!=NULL)
die("<script>window.location.href = '$fail_url'</script>");
exit;
}
// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response){
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
if($fail_msg!=NULL)
die($fail_msg);
if($fail_url!=NULL)
die("<script>window.location.href = '$fail_url'</script>");
exit;
}
// ok, valid username & password
return $data['username'];
}
/**
* Method to parse the http auth header, works with IE.
*
* Internet Explorer returns a qop="xxxxxxxxxxx" in the header instead of qop=xxxxxxxxxxx as most browsers do.
*
* @param string $txt header string to parse
* @return array An assoc array of the digest auth session
*/
private static function http_digest_parse($txt)
{
$res = preg_match("/username=\"([^\"]+)\"/i", $txt, $match);
$data['username'] = (isset($match[1]))?$match[1]:null;
$res = preg_match('/nonce=\"([^\"]+)\"/i', $txt, $match);
$data['nonce'] = $match[1];
$res = preg_match('/nc=([0-9]+)/i', $txt, $match);
$data['nc'] = $match[1];
$res = preg_match('/cnonce=\"([^\"]+)\"/i', $txt, $match);
$data['cnonce'] = $match[1];
$res = preg_match('/qop=([^,]+)/i', $txt, $match);
$data['qop'] = str_replace('"','',$match[1]);
$res = preg_match('/uri=\"([^\"]+)\"/i', $txt, $match);
$data['uri'] = $match[1];
$res = preg_match('/response=\"([^\"]+)\"/i', $txt, $match);
$data['response'] = $match[1];
return $data;
}
}

View File

@@ -4,6 +4,8 @@
* @package Minify
*/
use Psr\Log\LoggerInterface;
/**
* Minify - Combines, minifies, and caches JavaScript and CSS files on demand.
*
@@ -64,10 +66,17 @@ class Minify {
protected $options = null;
/**
* @param Minify_CacheInterface $cache
* @var LoggerInterface|null
*/
public function __construct(Minify_CacheInterface $cache) {
protected $logger = null;
/**
* @param Minify_CacheInterface $cache
* @param LoggerInterface $logger
*/
public function __construct(Minify_CacheInterface $cache, LoggerInterface $logger = null) {
$this->cache = $cache;
$this->logger = $logger;
}
/**
@@ -209,6 +218,10 @@ class Minify {
$this->selectionId = $config->getSelectionId();
$this->options = $this->analyzeSources($config->getOptions());
if (!$this->options['quiet'] && !headers_sent()) {
ini_set('zlib.output_compression', '0');
}
// check request validity
if (!$this->sources) {
// invalid request!
@@ -321,7 +334,7 @@ class Minify {
try {
$content = $this->combineMinify();
} catch (Exception $e) {
$this->controller->log($e->getMessage());
$this->logger && $this->logger->critical($e->getMessage());
if (! $this->options['quiet']) {
$this->errorExit($this->options['errorHeader'], self::URL_DEBUG);
}
@@ -338,7 +351,7 @@ class Minify {
try {
$content = $this->combineMinify();
} catch (Exception $e) {
$this->controller->log($e->getMessage());
$this->logger && $this->logger->critical($e->getMessage());
if (! $this->options['quiet']) {
$this->errorExit($this->options['errorHeader'], self::URL_DEBUG);
}
@@ -413,7 +426,7 @@ class Minify {
$sourceFactory = new Minify_Source_Factory($env, array(
'checkAllowDirs' => false,
), $this->cache);
$controller = new Minify_Controller_Files($env, $sourceFactory);
$controller = new Minify_Controller_Files($env, $sourceFactory, $this->logger);
$options = array_merge($options, array(
'files' => (array)$sources,
@@ -689,11 +702,10 @@ class Minify {
if (!empty($options['contentType'])) {
// just verify sources have null content type or match the options
if ($sourceType !== null && $sourceType !== $options['contentType']) {
// TODO better logging
Minify_Logger::log('ContentType mismatch');
$this->logger && $this->logger->warning('ContentType mismatch');
$this->sources = array();
return $options;
}
@@ -704,11 +716,9 @@ class Minify {
$type = $sourceType;
} elseif ($sourceType !== $type) {
// TODO better logging
Minify_Logger::log('ContentType mismatch');
$this->logger && $this->logger->warning('ContentType mismatch');
$this->sources = array();
return $options;
}
}

258
lib/Minify/App.php Normal file
View File

@@ -0,0 +1,258 @@
<?php
namespace Minify;
use Props\Container;
use Psr\Log\LoggerInterface;
/**
* @property \Minify_CacheInterface $cache
* @property \Minify\Config $config
* @property string $configPath
* @property \Minify_ControllerInterface $controller
* @property string $dir
* @property string $docRoot
* @property \Minify_Env $env
* @property \Monolog\Handler\ErrorLogHandler $errorLogHandler
* @property array $groupsConfig
* @property string $groupsConfigPath
* @property \Psr\Log\LoggerInterface $logger
* @property \Minify $minify
* @property array $serveOptions
* @property \Minify_Source_Factory $sourceFactory
* @property array $sourceFactoryOptions
*/
class App extends Container {
public function __construct($dir)
{
$that = $this;
$this->dir = rtrim($dir, '/\\');
$this->cache = function (App $app) use ($that) {
$config = $app->config;
if ($config->cachePath instanceof \Minify_CacheInterface) {
return $config->cachePath;
}
if (!$config->cachePath || is_string($config->cachePath)) {
return new \Minify_Cache_File($config->cachePath, $config->cacheFileLocking, $app->logger);
}
$type = $that->typeOf($config->cachePath);
throw new \RuntimeException('$min_cachePath must be a path or implement Minify_CacheInterface.'
. " Given $type");
};
$this->config = function (App $app) {
$config = (require $app->configPath);
if ($config instanceof \Minify\Config) {
return $config;
}
// copy from vars into properties
$config = new \Minify\Config();
$propNames = array_keys(get_object_vars($config));
$varNames = array_map(function ($name) {
return "min_$name";
}, $propNames);
$vars = compact($varNames);
foreach ($varNames as $varName) {
if (isset($vars[$varName])) {
$config->{substr($varName, 4)} = $vars[$varName];
}
}
return $config;
};
$this->configPath = "{$this->dir}/config.php";
$this->controller = function (App $app) use ($that) {
$config = $app->config;
if (empty($config->factories['controller'])) {
$ctrl = new \Minify_Controller_MinApp($app->env, $app->sourceFactory, $app->logger);
} else {
$ctrl = call_user_func($config->factories['controller'], $app);
}
if ($ctrl instanceof \Minify_ControllerInterface) {
return $ctrl;
}
$type = $that->typeOf($ctrl);
throw new \RuntimeException('$min_factories["controller"] callable must return an implementation'
." of Minify_CacheInterface. Returned $type");
};
$this->docRoot = function (App $app) {
$config = $app->config;
if (empty($config->documentRoot)) {
return $app->env->getDocRoot();
}
return rtrim($config->documentRoot, '/\\');
};
$this->env = function (App $app) {
$config = $app->config;
$envArgs = empty($config->envArgs) ? array() : $config->envArgs;
return new \Minify_Env($envArgs);
};
$this->errorLogHandler = function (App $app) {
$format = "%channel%.%level_name%: %message% %context% %extra%";
$handler = new \Monolog\Handler\ErrorLogHandler();
$handler->setFormatter(new \Monolog\Formatter\LineFormatter($format));
return $handler;
};
$this->groupsConfig = function (App $app) {
return (require $app->groupsConfigPath);
};
$this->groupsConfigPath = "{$this->dir}/groupsConfig.php";
$this->logger = function (App $app) use ($that) {
$value = $app->config->errorLogger;
if ($value instanceof \Psr\Log\LoggerInterface) {
return $value;
}
$logger = new \Monolog\Logger('minify');
if (!$value) {
return $logger;
}
if ($value === true || $value instanceof \FirePHP) {
$logger->pushHandler($app->errorLogHandler);
$logger->pushHandler(new \Monolog\Handler\FirePHPHandler());
return $logger;
}
if ($value instanceof \Monolog\Handler\HandlerInterface) {
$logger->pushHandler($value);
return $logger;
}
// BC
if (is_object($value) && is_callable(array($value, 'log'))) {
$handler = new \Minify\Logger\LegacyHandler($value);
$logger->pushHandler($handler);
return $logger;
}
$type = $that->typeOf($value);
throw new \RuntimeException('If set, $min_errorLogger must be a PSR-3 logger or a Monolog handler.'
." Given $type");
};
$this->minify = function (App $app) use ($that) {
$config = $app->config;
if (empty($config->factories['minify'])) {
return new \Minify($app->cache, $app->logger);
}
$minify = call_user_func($config->factories['minify'], $app);
if ($minify instanceof \Minify) {
return $minify;
}
$type = $that->typeOf($minify);
throw new \RuntimeException('$min_factories["minify"] callable must return a Minify object.'
." Returned $type");
};
$this->serveOptions = function (App $app) {
$config = $app->config;
$env = $app->env;
$ret = $config->serveOptions;
$ret['minifierOptions']['text/css']['docRoot'] = $app->docRoot;
$ret['minifierOptions']['text/css']['symlinks'] = $config->symlinks;
$ret['minApp']['symlinks'] = $config->symlinks;
// auto-add targets to allowDirs
foreach ($config->symlinks as $uri => $target) {
$ret['minApp']['allowDirs'][] = $target;
}
if ($config->allowDebugFlag) {
$ret['debug'] = \Minify_DebugDetector::shouldDebugRequest($env);
}
if ($config->concatOnly) {
$ret['concatOnly'] = true;
}
// check for URI versioning
if ($env->get('v') !== null || preg_match('/&\\d/', $app->env->server('QUERY_STRING'))) {
$ret['maxAge'] = 31536000;
}
// need groups config?
if ($env->get('g') !== null) {
$ret['minApp']['groups'] = $app->groupsConfig;
}
return $ret;
};
$this->sourceFactory = function (App $app) {
return new \Minify_Source_Factory($app->env, $app->sourceFactoryOptions, $app->cache);
};
$this->sourceFactoryOptions = function (App $app) {
$serveOptions = $app->serveOptions;
$ret = array();
// translate legacy setting to option for source factory
if (isset($serveOptions['minApp']['noMinPattern'])) {
$ret['noMinPattern'] = $serveOptions['minApp']['noMinPattern'];
}
if (isset($serveOptions['minApp']['allowDirs'])) {
$ret['allowDirs'] = $serveOptions['minApp']['allowDirs'];
}
if (is_numeric($app->config->uploaderHoursBehind)) {
$ret['uploaderHoursBehind'] = $app->config->uploaderHoursBehind;
}
return $ret;
};
}
public function runServer() {
if (!$this->env->get('f') && $this->env->get('g') === null) {
// no spec given
$msg = '<p>No "f" or "g" parameters were detected.</p>';
$url = 'https://github.com/mrclay/minify/blob/master/docs/CommonProblems.wiki.md#long-url-parameters-are-ignored';
$defaults = $this->minify->getDefaultOptions();
$this->minify->errorExit($defaults['badRequestHeader'], $url, $msg);
}
$this->minify->serve($this->controller, $this->serveOptions);
}
/**
* @param mixed $var
* @return string
*/
private function typeOf($var) {
$type = gettype($var);
return $type === 'object' ? get_class($var) : $type;
}
}

View File

@@ -4,15 +4,42 @@
* @package Minify
*/
use Psr\Log\LoggerInterface;
class Minify_Cache_File implements Minify_CacheInterface {
public function __construct($path = '', $fileLocking = false)
/**
* @var string
*/
private $path;
/**
* @var bool
*/
private $locking;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @param string $path
* @param bool $fileLocking
* @param LoggerInterface $logger
*/
public function __construct($path = '', $fileLocking = false, LoggerInterface $logger = null)
{
if (! $path) {
$path = self::tmp();
$path = sys_get_temp_dir();
}
$this->_locking = $fileLocking;
$this->_path = $path;
$this->locking = $fileLocking;
$this->path = $path;
if (!$logger) {
$logger = new \Monolog\Logger('minify');
}
$this->logger = $logger;
}
/**
@@ -26,18 +53,17 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function store($id, $data)
{
$flag = $this->_locking
$flag = $this->locking
? LOCK_EX
: null;
$file = $this->_path . '/' . $id;
$file = $this->path . '/' . $id;
if (! @file_put_contents($file, $data, $flag)) {
$this->_log("Minify_Cache_File: Write failed to '$file'");
$this->logger->warning("Minify_Cache_File: Write failed to '$file'");
}
// write control
if ($data !== $this->fetch($id)) {
@unlink($file);
$this->_log("Minify_Cache_File: Post-write read failed for '$file'");
$this->logger->warning("Minify_Cache_File: Post-write read failed for '$file'");
return false;
}
@@ -53,7 +79,7 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function getSize($id)
{
return filesize($this->_path . '/' . $id);
return filesize($this->path . '/' . $id);
}
/**
@@ -67,7 +93,7 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function isValid($id, $srcMtime)
{
$file = $this->_path . '/' . $id;
$file = $this->path . '/' . $id;
return (is_file($file) && (filemtime($file) >= $srcMtime));
}
@@ -79,14 +105,14 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function display($id)
{
if ($this->_locking) {
$fp = fopen($this->_path . '/' . $id, 'rb');
if ($this->locking) {
$fp = fopen($this->path . '/' . $id, 'rb');
flock($fp, LOCK_SH);
fpassthru($fp);
flock($fp, LOCK_UN);
fclose($fp);
} else {
readfile($this->_path . '/' . $id);
readfile($this->path . '/' . $id);
}
}
@@ -99,8 +125,8 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function fetch($id)
{
if ($this->_locking) {
$fp = fopen($this->_path . '/' . $id, 'rb');
if ($this->locking) {
$fp = fopen($this->path . '/' . $id, 'rb');
if (!$fp) {
return false;
}
@@ -111,7 +137,7 @@ class Minify_Cache_File implements Minify_CacheInterface {
return $ret;
} else {
return file_get_contents($this->_path . '/' . $id);
return file_get_contents($this->path . '/' . $id);
}
}
@@ -122,81 +148,30 @@ class Minify_Cache_File implements Minify_CacheInterface {
*/
public function getPath()
{
return $this->_path;
return $this->path;
}
/**
* Get a usable temp directory
*
* Adapted from Solar/Dir.php
* @author Paul M. Jones <pmjones@solarphp.com>
* @license http://opensource.org/licenses/bsd-license.php BSD
* @link http://solarphp.com/trac/core/browser/trunk/Solar/Dir.php
*
* @return string
* @deprecated
*/
public static function tmp()
{
static $tmp = null;
if (! $tmp) {
$tmp = function_exists('sys_get_temp_dir')
? sys_get_temp_dir()
: self::_tmp();
$tmp = rtrim($tmp, DIRECTORY_SEPARATOR);
}
return $tmp;
}
/**
* Returns the OS-specific directory for temporary files
*
* @author Paul M. Jones <pmjones@solarphp.com>
* @license http://opensource.org/licenses/bsd-license.php BSD
* @link http://solarphp.com/trac/core/browser/trunk/Solar/Dir.php
*
* @return string
*/
protected static function _tmp()
{
// non-Windows system?
if (strtolower(substr(PHP_OS, 0, 3)) != 'win') {
$tmp = empty($_ENV['TMPDIR']) ? getenv('TMPDIR') : $_ENV['TMPDIR'];
if ($tmp) {
return $tmp;
} else {
return '/tmp';
}
}
// Windows 'TEMP'
$tmp = empty($_ENV['TEMP']) ? getenv('TEMP') : $_ENV['TEMP'];
if ($tmp) {
return $tmp;
}
// Windows 'TMP'
$tmp = empty($_ENV['TMP']) ? getenv('TMP') : $_ENV['TMP'];
if ($tmp) {
return $tmp;
}
// Windows 'windir'
$tmp = empty($_ENV['windir']) ? getenv('windir') : $_ENV['windir'];
if ($tmp) {
return $tmp;
}
// final fallback for Windows
return getenv('SystemRoot') . '\\temp';
trigger_error(__METHOD__ . ' is deprecated in Minfy 3.0', E_USER_DEPRECATED);
return sys_get_temp_dir();
}
/**
* Send message to the Minify logger
* @param string $msg
* @return null
* @deprecated Use $this->logger
*/
protected function _log($msg)
{
Minify_Logger::log($msg);
trigger_error(__METHOD__ . ' is deprecated in Minify 3.0.', E_USER_DEPRECATED);
$this->logger->warning($msg);
}
private $_path = null;
private $_locking = null;
}

73
lib/Minify/Config.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
namespace Minify;
use Minify_CacheInterface;
class Config
{
/**
* @var bool
*/
public $enableBuilder = false;
/**
* @var bool
*/
public $concatOnly = false;
/**
* @var string
*/
public $builderPassword = 'admin';
/**
* @var bool|object
*/
public $errorLogger = false;
/**
* @var bool
*/
public $allowDebugFlag = false;
/**
* @var string|Minify_CacheInterface
*/
public $cachePath = '';
/**
* @var string
*/
public $documentRoot = '';
/**
* @var bool
*/
public $cacheFileLocking = true;
/**
* @var array
*/
public $serveOptions = array();
/**
* @var array
*/
public $symlinks = array();
/**
* @var int
*/
public $uploaderHoursBehind = 0;
/**
* @var array
*/
public $envArgs = array();
/**
* @var callable[]
*/
public $factories = array();
}

View File

@@ -4,6 +4,9 @@
* @package Minify
*/
use Psr\Log\LoggerInterface;
use Monolog\Logger;
/**
* Base class for Minify controller
*
@@ -24,14 +27,24 @@ abstract class Minify_Controller_Base implements Minify_ControllerInterface {
*/
protected $sourceFactory;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @param Minify_Env $env
* @param Minify_Source_Factory $sourceFactory
* @param LoggerInterface $logger
*/
public function __construct(Minify_Env $env, Minify_Source_Factory $sourceFactory)
public function __construct(Minify_Env $env, Minify_Source_Factory $sourceFactory, LoggerInterface $logger = null)
{
$this->env = $env;
$this->sourceFactory = $sourceFactory;
if (!$logger) {
$logger = new Logger('minify');
}
$this->logger = $logger;
}
/**
@@ -49,9 +62,11 @@ abstract class Minify_Controller_Base implements Minify_ControllerInterface {
* @param string $msg
*
* @return null
* @deprecated use $this->logger
*/
public function log($msg)
{
Minify_Logger::log($msg);
trigger_error(__METHOD__ . ' is deprecated in Minify 3.0.', E_USER_DEPRECATED);
$this->logger->info($msg);
}
}

View File

@@ -4,6 +4,9 @@
* @package Minify
*/
use Psr\Log\LoggerInterface;
use Monolog\Logger;
/**
* Controller class for minifying a set of files
*
@@ -28,16 +31,6 @@
*/
class Minify_Controller_Files extends Minify_Controller_Base {
/**
* @param Minify_Env $env Environment
* @param Minify_Source_Factory $sourceFactory Source factory. If you need to serve files from any path, this
* component must have its "checkAllowDirs" option set to false.
*/
public function __construct(Minify_Env $env, Minify_Source_Factory $sourceFactory)
{
parent::__construct($env, $sourceFactory);
}
/**
* Set up file sources
*
@@ -62,16 +55,10 @@ class Minify_Controller_Files extends Minify_Controller_Base {
$sources = array();
foreach ($files as $file) {
if ($file instanceof Minify_SourceInterface) {
$sources[] = $file;
continue;
}
try {
$sources[] = $this->sourceFactory->makeSource(array(
'filepath' => $file,
));
$sources[] = $this->sourceFactory->makeSource($file);
} catch (Minify_Source_FactoryException $e) {
$this->log($e->getMessage());
$this->logger->error($e->getMessage());
return new Minify_ServeConfiguration($options);
}

View File

@@ -51,7 +51,7 @@ class Minify_Controller_Groups extends Minify_Controller_Files {
);
if (false === $pathInfo || ! isset($groups[$pathInfo])) {
// no PATH_INFO or not a valid group
$this->log("Missing PATH_INFO or no group set for \"$pathInfo\"");
$this->logger->info("Missing PATH_INFO or no group set for \"$pathInfo\"");
return new Minify_ServeConfiguration($options);
}

View File

@@ -58,13 +58,13 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$selectionId .= 'g=' . $get['g'];
$keys = explode(',', $get['g']);
if ($keys != array_unique($keys)) {
$this->log("Duplicate group key found.");
$this->logger->info("Duplicate group key found.");
return new Minify_ServeConfiguration($options);
}
foreach ($keys as $key) {
if (! isset($localOptions['groups'][$key])) {
$this->log("A group configuration for \"{$key}\" was not found");
$this->logger->info("A group configuration for \"{$key}\" was not found");
return new Minify_ServeConfiguration($options);
}
@@ -76,23 +76,17 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$files = (array)$files;
}
foreach ($files as $file) {
if ($file instanceof Minify_SourceInterface) {
$sources[] = $file;
continue;
}
try {
$source = $this->sourceFactory->makeSource(array(
'filepath' => $file,
));
$source = $this->sourceFactory->makeSource($file);
$sources[] = $source;
} catch (Minify_Source_FactoryException $e) {
$this->log($e->getMessage());
$this->logger->error($e->getMessage());
if (null === $firstMissingResource) {
$firstMissingResource = basename($file);
continue;
} else {
$secondMissingResource = basename($file);
$this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'");
$this->logger->info("More than one file was missing: '$firstMissingResource', '$secondMissingResource'");
return new Minify_ServeConfiguration($options);
}
@@ -112,14 +106,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
// no "\"
|| strpos($get['f'], '\\') !== false
) {
$this->log("GET param 'f' was invalid");
$this->logger->info("GET param 'f' was invalid");
return new Minify_ServeConfiguration($options);
}
$ext = ".{$m[1]}";
$files = explode(',', $get['f']);
if ($files != array_unique($files)) {
$this->log("Duplicate files were specified");
$this->logger->info("Duplicate files were specified");
return new Minify_ServeConfiguration($options);
}
@@ -131,7 +125,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
// valid base
$base = "/{$get['b']}/";
} else {
$this->log("GET param 'b' was invalid");
$this->logger->info("GET param 'b' was invalid");
return new Minify_ServeConfiguration($options);
}
@@ -153,19 +147,17 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
}
try {
$source = $this->sourceFactory->makeSource(array(
'filepath' => $path,
));
$source = $this->sourceFactory->makeSource($path);
$sources[] = $source;
$basenames[] = basename($path, $ext);
} catch (Minify_Source_FactoryException $e) {
$this->log($e->getMessage());
$this->logger->error($e->getMessage());
if (null === $firstMissingResource) {
$firstMissingResource = $uri;
continue;
} else {
$secondMissingResource = $uri;
$this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'");
$this->logger->info("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'");
return new Minify_ServeConfiguration($options);
}
@@ -178,7 +170,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
}
if (!$sources) {
$this->log("No sources to serve");
$this->logger->info("No sources to serve");
return new Minify_ServeConfiguration($options);
}

View File

@@ -1,5 +1,7 @@
<?php
use Psr\Log\LoggerInterface;
interface Minify_ControllerInterface {
/**

View File

@@ -23,6 +23,7 @@ class Minify_Env {
$options = array_merge(array(
'server' => $_SERVER,
'get' => $_GET,
'post' => $_POST,
'cookie' => $_COOKIE,
), $options);
@@ -33,6 +34,7 @@ class Minify_Env {
$this->server['DOCUMENT_ROOT'] = rtrim($this->server['DOCUMENT_ROOT'], '/\\');
}
$this->get = $options['get'];
$this->post = $options['post'];
$this->cookie = $options['cookie'];
}
@@ -47,30 +49,36 @@ class Minify_Env {
: null;
}
public function cookie($key = null)
public function cookie($key = null, $default = null)
{
if (null === $key) {
return $this->cookie;
}
return isset($this->cookie[$key])
? $this->cookie[$key]
: null;
return isset($this->cookie[$key]) ? $this->cookie[$key] : $default;
}
public function get($key = null)
public function get($key = null, $default = null)
{
if (null === $key) {
return $this->get;
}
return isset($this->get[$key])
? $this->get[$key]
: null;
return isset($this->get[$key]) ? $this->get[$key] : $default;
}
public function post($key = null, $default = null)
{
if (null === $key) {
return $this->post;
}
return isset($this->post[$key]) ? $this->post[$key] : $default;
}
protected $server = null;
protected $get = null;
protected $post = null;
protected $cookie = null;
/**

View File

@@ -31,17 +31,19 @@ class Minify_HTML_Helper {
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' => ''
'farExpires' => true,
'debug' => false,
'charset' => 'UTF-8',
'minAppUri' => '/min',
'rewriteWorks' => true,
'groupsConfigFile' => self::app()->groupsConfigPath,
), $opts);
$h = new self;
$h->minAppUri = $opts['minAppUri'];
$h->rewriteWorks = $opts['rewriteWorks'];
$h->groupsConfigFile = $opts['groupsConfigFile'];
if (is_array($keyOrFiles)) {
$h->setFiles($keyOrFiles, $opts['farExpires']);
} else {
@@ -98,7 +100,7 @@ class Minify_HTML_Helper {
$file = substr($file, 2);
} elseif (0 === strpos($file, '/')
|| 1 === strpos($file, ':\\')) {
$file = substr($file, strlen($_SERVER['DOCUMENT_ROOT']) + 1);
$file = substr($file, strlen(self::app()->env->getDocRoot()) + 1);
}
$file = strtr($file, '\\', '/');
$files[$k] = $file;
@@ -117,7 +119,7 @@ class Minify_HTML_Helper {
$this->_groupKey = $key;
if ($checkLastModified) {
if (! $this->groupsConfigFile) {
$this->groupsConfigFile = dirname(dirname(dirname(__DIR__))) . '/groupsConfig.php';
$this->groupsConfigFile = self::app()->groupsConfigPath;
}
if (is_file($this->groupsConfigFile)) {
$gc = (require $this->groupsConfigFile);
@@ -145,23 +147,35 @@ class Minify_HTML_Helper {
public static function getLastModified($sources, $lastModified = 0)
{
$max = $lastModified;
$factory = self::app()->sourceFactory;
/** @var Minify_Source $source */
foreach ((array)$sources as $source) {
if ($source instanceof Minify_Source) {
$max = max($max, $source->getLastModified());
} elseif (is_string($source)) {
if (0 === strpos($source, '//')) {
$source = $_SERVER['DOCUMENT_ROOT'] . substr($source, 1);
}
if (is_file($source)) {
$max = max($max, filemtime($source));
}
}
$source = $factory->makeSource($source);
$max = max($max, $source->getLastModified());
}
return $max;
}
/**
* @param \Minify\App $app
* @return \Minify\App
* @internal
*/
public static function app(\Minify\App $app = null)
{
static $cached;
if ($app) {
$cached = $app;
return $app;
}
if ($cached === null) {
$cached = (require __DIR__ . '/../../../bootstrap.php');
}
return $cached;
}
protected $_groupKey = null; // if present, URI will be like g=...
protected $_filePaths = array();
protected $_lastModified = null;

View File

@@ -1,45 +0,0 @@
<?php
/**
* Class Minify_Loader
* @package Minify
*/
/**
* Class autoloader
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
* @deprecated Use Composer (/vendor/autoload.php)
*/
class Minify_Loader {
public function loadClass($class)
{
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR;
$file .= strtr($class, "\\_", DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) . '.php';
if (is_readable($file)) {
require $file;
return;
}
$map = array(
'JavascriptPacker' => 'class.JavaScriptPacker.php',
);
if (!isset($map[$class])) {
return;
}
@include $map[$class];
}
public static function register()
{
$inst = new self();
spl_autoload_register(array($inst, 'loadClass'));
return $inst;
}
}
return Minify_Loader::register();

View File

@@ -1,47 +0,0 @@
<?php
/**
* Class Minify_Logger
* @package Minify
*/
/**
* Message logging class
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*
* @todo lose this singleton! pass log object in Minify::serve and distribute to others
*/
class Minify_Logger {
/**
* Set logger object.
*
* The object should have a method "log" that accepts a value as 1st argument and
* an optional string label as the 2nd.
*
* @param mixed $obj or a "falsey" value to disable
* @return null
*/
public static function setLogger($obj = null) {
self::$_logger = $obj
? $obj
: null;
}
/**
* Pass a message to the logger (if set)
*
* @param string $msg message to log
* @return null
*/
public static function log($msg, $label = 'Minify') {
if (! self::$_logger) return;
self::$_logger->log($msg, $label);
}
/**
* @var mixed logger object (like FirePHP) or null (i.e. no logger available)
*/
private static $_logger = null;
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Minify\Logger;
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
class LegacyHandler extends AbstractProcessingHandler
{
private $obj;
public function __construct($obj)
{
if (!is_callable(array($obj, 'log'))) {
throw new \InvalidArgumentException('$obj must have a public log() method');
}
$this->obj = $obj;
parent::__construct();
}
protected function write(array $record)
{
$this->obj->log((string)$record['formatted']);
}
}

View File

@@ -133,12 +133,16 @@ class Minify_Source_Factory {
*/
public function makeSource($spec)
{
$source = null;
if ($spec instanceof Minify_SourceInterface) {
$source = $spec;
if (is_string($spec)) {
$spec = array(
'filepath' => $spec,
);
} elseif ($spec instanceof Minify_SourceInterface) {
return $spec;
}
$source = null;
if (empty($spec['filepath'])) {
// not much we can check
return new Minify_Source($spec);

View File

@@ -1,26 +1,29 @@
<?php
die('Disabled: use this only for testing');
require __DIR__ . '/../../bootstrap.php';
$app = (require __DIR__ . '/../../bootstrap.php');
/* @var \Minify\App $app */
function getPost($key) {
return get_magic_quotes_gpc()
? stripslashes($_POST[$key])
: $_POST[$key];
// use FirePHP if not already setup
if (!$app->config->errorLogger) {
$app->config->errorLogger = true;
}
$app->cache = new Minify_Cache_Null();
$env = $app->env;
function h($txt) {
return htmlspecialchars($txt, ENT_QUOTES, 'UTF-8');
}
if (isset($_POST['textIn'])) {
require '../config.php';
$textIn = str_replace("\r\n", "\n", getPost('textIn'));
if ($env->post('textIn')) {
$textIn = str_replace("\r\n", "\n", $env->post('textIn'));
}
if (isset($_POST['method']) && $_POST['method'] === 'Minify and serve') {
if ($env->post('method') === 'Minify and serve') {
$base = trim(getPost('base'));
$base = trim($env->post('base'));
if ($base) {
$textIn = preg_replace(
'@(<head\\b[^>]*>)@i'
@@ -38,16 +41,12 @@ if (isset($_POST['method']) && $_POST['method'] === 'Minify and serve') {
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSSmin', 'minify');
}
$source = new Minify_Source($sourceSpec);
Minify_Logger::setLogger(FirePHP::getInstance(true));
$env = new Minify_Env();
$controller = new Minify_Controller_Files($env, new Minify_Source_Factory($env));
$minify = new Minify(new Minify_Cache_Null());
$controller = new Minify_Controller_Files($env, $app->sourceFactory, $app->logger);
try {
$minify->serve($controller, array(
'files' => $source
,'contentType' => Minify::TYPE_HTML
$app->minify->serve($controller, array(
'files' => $source,
'contentType' => Minify::TYPE_HTML,
));
} catch (Exception $e) {
echo h($e->getMessage());
@@ -58,16 +57,16 @@ if (isset($_POST['method']) && $_POST['method'] === 'Minify and serve') {
$tpl = array();
$tpl['classes'] = array('Minify_HTML', 'JSMin\\JSMin', 'Minify_CSS');
if (isset($_POST['method']) && in_array($_POST['method'], $tpl['classes'])) {
if (in_array($env->post('method'), $tpl['classes'])) {
$args = array($textIn);
if ($_POST['method'] === 'Minify_HTML') {
if ($env->post('method') === 'Minify_HTML') {
$args[] = array(
'cssMinifier' => array('Minify_CSSmin', 'minify')
,'jsMinifier' => array('JSMin\\JSMin', 'minify')
);
}
$func = array($_POST['method'], 'minify');
$func = array($env->post('method'), 'minify');
$tpl['inBytes'] = strlen($textIn);
$startTime = microtime(true);
try {

View File

@@ -5,7 +5,12 @@ die('Disabled: use this only for testing');
* Fetch and minify a URL (auto-detect HTML/JS/CSS)
*/
require __DIR__ . '/../../bootstrap.php';
$app = (require __DIR__ . '/../../bootstrap.php');
/* @var \Minify\App $app */
$app->cache = new Minify_Cache_Null();
$env = $app->env;
function getPost($key) {
if (! isset($_POST[$key])) {
@@ -47,9 +52,9 @@ if (isset($_POST['url'])) {
require '../config.php';
$url = trim(getPost('url'));
$ua = trim(getPost('ua'));
$cook = trim(getPost('cook'));
$url = trim($env->post('url'));
$ua = trim($env->post('ua'));
$cook = trim($env->post('cook'));
if (! preg_match('@^https?://@', $url)) {
die('HTTP(s) only.');
@@ -98,10 +103,10 @@ if (isset($_POST['url'])) {
$sourceSpec['contentType'] = $type['minify'];
if ($type['minify'] === 'text/html') {
if (isset($_POST['minJs'])) {
if ($env->post('minJs')) {
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin\\JSMin', 'minify');
}
if (isset($_POST['minCss'])) {
if ($env->post('minCss')) {
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSSmin', 'minify');
}
}
@@ -109,7 +114,7 @@ if (isset($_POST['url'])) {
$source = new Minify_Source($sourceSpec);
$sendType = 'text/plain';
if ($type['minify'] === 'text/html' && ! isset($_POST['asText'])) {
if ($type['minify'] === 'text/html' && $env->post('asText') === null) {
$sendType = $type['sent'];
}
if ($type['charset']) {
@@ -119,10 +124,8 @@ if (isset($_POST['url'])) {
// using combine instead of serve because it allows us to specify a
// Content-Type like application/xhtml+xml IF we need to
$minify = new Minify(new Minify_Cache_Null());
try {
echo $minify->combine(array($source));
echo $app->minify->combine(array($source));
} catch (Exception $e) {
header('Content-Type: text/html;charset=utf-8');
echo htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
@@ -132,9 +135,7 @@ if (isset($_POST['url'])) {
header('Content-Type: text/html; charset=utf-8');
$ua = get_magic_quotes_gpc()
? stripslashes($_SERVER['HTTP_USER_AGENT'])
: $_SERVER['HTTP_USER_AGENT'];
$ua = $env->server('HTTP_USER_AGENT');
?>
<!DOCTYPE html><head><title>Minify URL</title></head>
@@ -146,7 +147,7 @@ $ua = get_magic_quotes_gpc()
The fetched resource Content-Type will determine the minifier used.</p>
<form action="?2" method="post">
<p><label>URL: <input type="text" name="url" size="60"></label></p>
<p><label>URL: <input type="text" name="url" value="https://code.jquery.com/jquery-2.2.1.js" size="60"></label></p>
<p><input type="submit" value="Fetch and minify"></p>
<fieldset><legend>HTML options</legend>

View File

@@ -1,51 +1,39 @@
<?php
die('Disabled: use this only for testing');
require __DIR__ . '/../../bootstrap.php';
$app = (require __DIR__ . '/../../bootstrap.php');
/* @var \Minify\App $app */
$env = $app->env;
header('Content-Type: text/html;charset=utf-8');
function h($str) { return htmlspecialchars($str, ENT_QUOTES); }
function getPost($name, $default = '') { return isset($_POST[$name]) ? $_POST[$name] : $default; }
function getInput($name, $default = '', $size = 50) {
$val = h(isset($_POST[$name]) ? $_POST[$name] : $default);
return "<input type='text' name='{$name}' value='{$val}' size='{$size}' />";
}
// validate user POST (no arrays and fix slashes)
if (! empty($_POST)) {
foreach ($_POST as $name => $val) {
if (! is_string($val)) {
unset($_POST[$name]);
continue;
}
if (get_magic_quotes_gpc()) {
$_POST[$name] = stripslashes($val);
}
}
global $env;
$val = $env->post($name, $default);
return "<input type='text' name='{$name}' value='" . h($val) . "' size='{$size}' />";
}
$defaultCurrentDir = __DIR__;
$defaultDocRoot = realpath($_SERVER['DOCUMENT_ROOT']);
$defaultDocRoot = realpath($env->getDocRoot());
$defaultSymLink = '//symlinkPath';
$defaultSymTarget = ($defaultCurrentDir[0] === '/') ? '/tmp' : 'C:\\WINDOWS\\Temp';
$defaultCss = "url(hello.gif)\nurl(../hello.gif)\nurl(../../hello.gif)\nurl(up/hello.gif)";
$out = '';
if (isset($_POST['css'])) {
require '../config.php';
if ($env->post('css')) {
$symlinks = array();
if ('' !== ($target = getPost('symTarget'))) {
$symlinks[getPost('symLink')] = $target;
if ('' !== ($target = $env->post('symTarget'))) {
$symlinks[$env->post('symLink')] = $target;
}
$css = Minify_CSS_UriRewriter::rewrite(
getPost('css')
, getPost('currentDir')
, getPost('docRoot')
, $symlinks
$env->post('css'),
$env->post('currentDir'),
$env->post('docRoot'),
$symlinks
);
$out = "<hr /><pre><code>" . h($css) . '</code></pre>';
}
@@ -57,7 +45,7 @@ if (isset($_POST['css'])) {
<div><label>document root: <?php echo getInput('docRoot', $defaultDocRoot); ?></label></div>
<div><label>symlink: <?php echo getInput('symLink', $defaultSymLink); ?> => <?php echo getInput('symTarget', $defaultSymTarget); ?></label></div>
<div><label>current directory: <?php echo getInput('currentDir', $defaultCurrentDir); ?></label></div>
<p><label>input CSS: <textarea name="css" cols="80" rows="5"><?php echo h(getPost('css', $defaultCss)); ?></textarea></label></p>
<p><label>input CSS: <textarea name="css" cols="80" rows="5"><?php echo h($env->post('css', $defaultCss)); ?></textarea></label></p>
<p><input type="submit" value="rewrite()" /></p>
</form>
<?php echo $out; ?>

View File

@@ -16,6 +16,7 @@
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
<exclude>tests/JsClosureCompilerTest.php</exclude>
</testsuite>
</testsuites>

View File

@@ -51,7 +51,7 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
{
$src = "(function(){})();";
$minOutput = $this->compile($src, array(
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => 0
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => 0,
));
$this->assertSame($src, $minOutput, 'With no limit set, it should compile properly');
@@ -65,7 +65,7 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
$e = null;
try {
$this->compile($src, array(
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => $allowedBytes
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => $allowedBytes,
));
} catch (Minify_JS_ClosureCompiler_Exception $e) {
}
@@ -78,10 +78,14 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
// Test additional options passed to HTTP request
public function test6()
{
$ecmascript5 = "[1,].length;";
$ecmascript3 = "[1,].length;";
$e = null;
try {
$this->compile($ecmascript5);
$this->compile($ecmascript3, array(
Minify_JS_ClosureCompiler::OPTION_ADDITIONAL_OPTIONS => array(
'language' => 'ECMASCRIPT3',
),
));
} catch (Minify_JS_ClosureCompiler_Exception $e) {
}
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e, 'Throws Minify_JS_ClosureCompiler_Exception');
@@ -94,8 +98,8 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
$minExpected = '1;';
$minOutput = $this->compile($ecmascript5, array(
Minify_JS_ClosureCompiler::OPTION_ADDITIONAL_OPTIONS => array(
'language' => 'ECMASCRIPT5'
)
'language' => 'ECMASCRIPT5',
),
));
$this->assertSame($minExpected, $minOutput, 'Language option should make it compile');
}

View File

@@ -56,7 +56,7 @@ function Minify_mtime($keysAndFiles, $groupsConfigFile = null)
{
$gc = null;
if (! $groupsConfigFile) {
$groupsConfigFile = __DIR__ . '/groupsConfig.php';
$groupsConfigFile = Minify_HTML_Helper::app()->groupsConfigPath;
}
$sources = array();
foreach ($keysAndFiles as $keyOrFile) {