summaryrefslogtreecommitdiffstats
path: root/admin/survey/minify/lib/Minify
diff options
context:
space:
mode:
Diffstat (limited to 'admin/survey/minify/lib/Minify')
-rw-r--r--admin/survey/minify/lib/Minify/App.php293
-rw-r--r--admin/survey/minify/lib/Minify/Build.php101
-rw-r--r--admin/survey/minify/lib/Minify/CSS.php98
-rw-r--r--admin/survey/minify/lib/Minify/CSS/Compressor.php275
-rw-r--r--admin/survey/minify/lib/Minify/CSS/UriRewriter.php358
-rw-r--r--admin/survey/minify/lib/Minify/CSSmin.php88
-rw-r--r--admin/survey/minify/lib/Minify/Cache/APC.php136
-rw-r--r--admin/survey/minify/lib/Minify/Cache/File.php183
-rw-r--r--admin/survey/minify/lib/Minify/Cache/Memcache.php141
-rw-r--r--admin/survey/minify/lib/Minify/Cache/Null.php67
-rw-r--r--admin/survey/minify/lib/Minify/Cache/WinCache.php139
-rw-r--r--admin/survey/minify/lib/Minify/Cache/XCache.php130
-rw-r--r--admin/survey/minify/lib/Minify/Cache/ZendPlatform.php129
-rw-r--r--admin/survey/minify/lib/Minify/CacheInterface.php58
-rw-r--r--admin/survey/minify/lib/Minify/ClosureCompiler.php240
-rw-r--r--admin/survey/minify/lib/Minify/CommentPreserver.php87
-rw-r--r--admin/survey/minify/lib/Minify/Config.php78
-rw-r--r--admin/survey/minify/lib/Minify/Controller/Base.php81
-rw-r--r--admin/survey/minify/lib/Minify/Controller/Files.php71
-rw-r--r--admin/survey/minify/lib/Minify/Controller/Groups.php76
-rw-r--r--admin/survey/minify/lib/Minify/Controller/MinApp.php196
-rw-r--r--admin/survey/minify/lib/Minify/Controller/Page.php69
-rw-r--r--admin/survey/minify/lib/Minify/ControllerInterface.php22
-rw-r--r--admin/survey/minify/lib/Minify/DebugDetector.php30
-rw-r--r--admin/survey/minify/lib/Minify/Env.php127
-rw-r--r--admin/survey/minify/lib/Minify/HTML.php258
-rw-r--r--admin/survey/minify/lib/Minify/HTML/Helper.php250
-rw-r--r--admin/survey/minify/lib/Minify/ImportProcessor.php217
-rw-r--r--admin/survey/minify/lib/Minify/JS/ClosureCompiler.php237
-rw-r--r--admin/survey/minify/lib/Minify/JS/JShrink.php48
-rw-r--r--admin/survey/minify/lib/Minify/LessCssSource.php128
-rw-r--r--admin/survey/minify/lib/Minify/Lines.php209
-rw-r--r--admin/survey/minify/lib/Minify/Logger/LegacyHandler.php24
-rw-r--r--admin/survey/minify/lib/Minify/NailgunClosureCompiler.php113
-rw-r--r--admin/survey/minify/lib/Minify/Packer.php31
-rw-r--r--admin/survey/minify/lib/Minify/ScssCssSource.php176
-rw-r--r--admin/survey/minify/lib/Minify/ServeConfiguration.php71
-rw-r--r--admin/survey/minify/lib/Minify/Source.php219
-rw-r--r--admin/survey/minify/lib/Minify/Source/Factory.php197
-rw-r--r--admin/survey/minify/lib/Minify/Source/FactoryException.php5
-rw-r--r--admin/survey/minify/lib/Minify/SourceInterface.php82
-rw-r--r--admin/survey/minify/lib/Minify/SourceSet.php31
-rw-r--r--admin/survey/minify/lib/Minify/YUICompressor.php157
43 files changed, 5726 insertions, 0 deletions
diff --git a/admin/survey/minify/lib/Minify/App.php b/admin/survey/minify/lib/Minify/App.php
new file mode 100644
index 0000000..5ddb3e9
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/App.php
@@ -0,0 +1,293 @@
+<?php
+
+namespace Minify;
+
+use Minify_Cache_File;
+use Minify_CacheInterface;
+use Minify_Controller_MinApp;
+use Minify_ControllerInterface;
+use Minify_DebugDetector;
+use Minify_Env;
+use Minify_Source_Factory;
+use Props\Container;
+use Psr\Log\LoggerInterface;
+use RuntimeException;
+use Monolog;
+use Minify;
+
+/**
+ * @property Minify_CacheInterface $cache
+ * @property 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 LoggerInterface $logger
+ * @property \Minify $minify
+ * @property array $serveOptions
+ * @property Minify_Source_Factory $sourceFactory
+ * @property array $sourceFactoryOptions
+ */
+class App extends Container
+{
+
+ /**
+ * Constructor
+ *
+ * @param string $dir Directory containing config files
+ */
+ 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));
+
+ $prefixer = function ($name) {
+ return "min_$name";
+ };
+ $varNames = array_map($prefixer, $propNames);
+
+ $vars = compact($varNames);
+
+ foreach ($varNames as $varName) {
+ if (isset($vars[$varName])) {
+ $config->{substr($varName, 4)} = $vars[$varName];
+ }
+ }
+
+ if ($config->documentRoot) {
+ // copy into env
+ if (empty($config->envArgs['server'])) {
+ $config->envArgs['server'] = $_SERVER;
+ }
+ $config->envArgs['server']['DOCUMENT_ROOT'] = $config->documentRoot;
+ }
+
+ 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 $app->env->normalizePath($config->documentRoot);
+ };
+
+ $this->env = function (App $app) {
+ return new Minify_Env($app->config->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 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 (isset($serveOptions['checkAllowDirs'])) {
+ $ret['checkAllowDirs'] = $serveOptions['checkAllowDirs'];
+ }
+
+ 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;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Build.php b/admin/survey/minify/lib/Minify/Build.php
new file mode 100644
index 0000000..177b262
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Build.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Class Minify_Build
+ * @package Minify
+ */
+
+/**
+ * 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
+ * ,'setExpires' => (time() + 86400 * 365)
+ * ));
+ * </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 = '&amp;';
+
+ /**
+ * 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&amp1678242"
+ * </code>
+ *
+ * @param string $uri
+ * @param boolean $forceAmpersand (default = false) Force the use of ampersand to
+ * append the timestamp to the URI.
+ * @return string
+ */
+ public function uri($uri, $forceAmpersand = false)
+ {
+ $sep = ($forceAmpersand || 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
+ *
+ */
+ public function __construct($sources)
+ {
+ $max = 0;
+ 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));
+ }
+ }
+ }
+ $this->lastModified = $max;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/CSS.php b/admin/survey/minify/lib/Minify/CSS.php
new file mode 100644
index 0000000..91b076e
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CSS.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Class Minify_CSS
+ * @package Minify
+ */
+
+/**
+ * Minify CSS
+ *
+ * This class uses Minify_CSS_Compressor and Minify_CSS_UriRewriter to
+ * minify CSS and rewrite relative URIs.
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ * @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
+ *
+ * @deprecated Use Minify_CSSmin
+ */
+class Minify_CSS
+{
+
+ /**
+ * Minify a CSS string
+ *
+ * @param string $css
+ *
+ * @param array $options available options:
+ *
+ * 'preserveComments': (default true) multi-line comments that begin
+ * with "/*!" will be preserved with newlines before and after to
+ * enhance readability.
+ *
+ * 'removeCharsets': (default true) remove all @charset at-rules
+ *
+ * 'prependRelativePath': (default null) if given, this string will be
+ * prepended to all relative URIs in import/url declarations
+ *
+ * 'currentDir': (default null) if given, this is assumed to be the
+ * directory of the current CSS file. Using this, minify will rewrite
+ * all relative URIs in import/url declarations to correctly point to
+ * the desired files. For this to work, the files *must* exist and be
+ * visible by the PHP process.
+ *
+ * 'symlinks': (default = array()) If the CSS file is stored in
+ * a symlink-ed directory, provide an array of link paths to
+ * target paths, where the link paths are within the document root. Because
+ * paths need to be normalized for this to work, use "//" to substitute
+ * the doc root in the link paths (the array keys). E.g.:
+ * <code>
+ * array('//symlink' => '/real/target/path') // unix
+ * array('//static' => 'D:\\staticStorage') // Windows
+ * </code>
+ *
+ * 'docRoot': (default = $_SERVER['DOCUMENT_ROOT'])
+ * see Minify_CSS_UriRewriter::rewrite
+ *
+ * @return string
+ */
+ public static function minify($css, $options = array())
+ {
+ $options = array_merge(array(
+ 'compress' => true,
+ 'removeCharsets' => true,
+ 'preserveComments' => true,
+ 'currentDir' => null,
+ 'docRoot' => $_SERVER['DOCUMENT_ROOT'],
+ 'prependRelativePath' => null,
+ 'symlinks' => array(),
+ ), $options);
+
+ if ($options['removeCharsets']) {
+ $css = preg_replace('/@charset[^;]+;\\s*/', '', $css);
+ }
+
+ if ($options['compress']) {
+ if (! $options['preserveComments']) {
+ $css = Minify_CSS_Compressor::process($css, $options);
+ } else {
+ $processor = array('Minify_CSS_Compressor', 'process');
+ $css = Minify_CommentPreserver::process($css, $processor, array($options));
+ }
+ }
+
+ if (! $options['currentDir'] && ! $options['prependRelativePath']) {
+ return $css;
+ }
+
+ if ($options['currentDir']) {
+ $currentDir = $options['currentDir'];
+ $docRoot = $options['docRoot'];
+ $symlinks = $options['symlinks'];
+
+ return Minify_CSS_UriRewriter::rewrite($css, $currentDir, $docRoot, $symlinks);
+ }
+
+ return Minify_CSS_UriRewriter::prepend($css, $options['prependRelativePath']);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/CSS/Compressor.php b/admin/survey/minify/lib/Minify/CSS/Compressor.php
new file mode 100644
index 0000000..e0ccabb
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CSS/Compressor.php
@@ -0,0 +1,275 @@
+<?php
+/**
+ * Class Minify_CSS_Compressor
+ * @package Minify
+ */
+
+/**
+ * Compress CSS
+ *
+ * This is a heavy regex-based removal of whitespace, unnecessary
+ * comments and tokens, and some CSS value minimization, where practical.
+ * Many steps have been taken to avoid breaking comment-based hacks,
+ * including the ie5/mac filter (and its inversion), but expect tricky
+ * hacks involving comment tokens in 'content' value strings to break
+ * minimization badly. A test suite is available.
+ *
+ * Note: This replaces a lot of spaces with line breaks. It's rumored
+ * (https://github.com/yui/yuicompressor/blob/master/README.md#global-options)
+ * that some source control tools and old browsers don't like very long lines.
+ * Compressed files with shorter lines are also easier to diff. If this is
+ * unacceptable please use CSSmin instead.
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ * @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
+ *
+ * @deprecated Use CSSmin (tubalmartin/cssmin)
+ */
+class Minify_CSS_Compressor
+{
+
+ /**
+ * Minify a CSS string
+ *
+ * @param string $css
+ *
+ * @param array $options (currently ignored)
+ *
+ * @return string
+ */
+ public static function process($css, $options = array())
+ {
+ $obj = new Minify_CSS_Compressor($options);
+
+ return $obj->_process($css);
+ }
+
+ /**
+ * @var array
+ */
+ protected $_options = null;
+
+ /**
+ * Are we "in" a hack? I.e. are some browsers targetted until the next comment?
+ *
+ * @var bool
+ */
+ protected $_inHack = false;
+
+ /**
+ * Constructor
+ *
+ * @param array $options (currently ignored)
+ */
+ private function __construct($options)
+ {
+ $this->_options = $options;
+ }
+
+ /**
+ * Minify a CSS string
+ *
+ * @param string $css
+ *
+ * @return string
+ */
+ protected function _process($css)
+ {
+ $css = str_replace("\r\n", "\n", $css);
+
+ // preserve empty comment after '>'
+ // http://www.webdevout.net/css-hacks#in_css-selectors
+ $css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
+
+ // preserve empty comment between property and value
+ // http://css-discuss.incutio.com/?page=BoxModelHack
+ $css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
+ $css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
+
+ // apply callback to all valid comments (and strip out surrounding ws
+ $pattern = '@\\s*/\\*([\\s\\S]*?)\\*/\\s*@';
+ $css = preg_replace_callback($pattern, array($this, '_commentCB'), $css);
+
+ // remove ws around { } and last semicolon in declaration block
+ $css = preg_replace('/\\s*{\\s*/', '{', $css);
+ $css = preg_replace('/;?\\s*}\\s*/', '}', $css);
+
+ // remove ws surrounding semicolons
+ $css = preg_replace('/\\s*;\\s*/', ';', $css);
+
+ // remove ws around urls
+ $pattern = '/
+ url\\( # url(
+ \\s*
+ ([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
+ \\s*
+ \\) # )
+ /x';
+ $css = preg_replace($pattern, 'url($1)', $css);
+
+ // remove ws between rules and colons
+ $pattern = '/
+ \\s*
+ ([{;]) # 1 = beginning of block or rule separator
+ \\s*
+ ([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
+ \\s*
+ :
+ \\s*
+ (\\b|[#\'"-]) # 3 = first character of a value
+ /x';
+ $css = preg_replace($pattern, '$1$2:$3', $css);
+
+ // remove ws in selectors
+ $pattern = '/
+ (?: # non-capture
+ \\s*
+ [^~>+,\\s]+ # selector part
+ \\s*
+ [,>+~] # combinators
+ )+
+ \\s*
+ [^~>+,\\s]+ # selector part
+ { # open declaration block
+ /x';
+ $css = preg_replace_callback($pattern, array($this, '_selectorsCB'), $css);
+
+ // minimize hex colors
+ $pattern = '/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i';
+ $css = preg_replace($pattern, '$1#$2$3$4$5', $css);
+
+ // remove spaces between font families
+ $pattern = '/font-family:([^;}]+)([;}])/';
+ $css = preg_replace_callback($pattern, array($this, '_fontFamilyCB'), $css);
+
+ $css = preg_replace('/@import\\s+url/', '@import url', $css);
+
+ // replace any ws involving newlines with a single newline
+ $css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
+
+ // separate common descendent selectors w/ newlines (to limit line lengths)
+ $pattern = '/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/';
+ $css = preg_replace($pattern, "$1\n$2{", $css);
+
+ // Use newline after 1st numeric value (to limit line lengths).
+ $pattern = '/
+ ((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
+ \\s+
+ /x';
+ $css = preg_replace($pattern, "$1\n", $css);
+
+ // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
+ $css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
+
+ return trim($css);
+ }
+
+ /**
+ * Replace what looks like a set of selectors
+ *
+ * @param array $m regex matches
+ *
+ * @return string
+ */
+ protected function _selectorsCB($m)
+ {
+ // remove ws around the combinators
+ return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
+ }
+
+ /**
+ * Process a comment and return a replacement
+ *
+ * @param array $m regex matches
+ *
+ * @return string
+ */
+ protected function _commentCB($m)
+ {
+ $hasSurroundingWs = (trim($m[0]) !== $m[1]);
+ $m = $m[1];
+ // $m is the comment content w/o the surrounding tokens,
+ // but the return value will replace the entire comment.
+ if ($m === 'keep') {
+ return '/**/';
+ }
+
+ if ($m === '" "') {
+ // component of http://tantek.com/CSS/Examples/midpass.html
+ return '/*" "*/';
+ }
+
+ if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
+ // component of http://tantek.com/CSS/Examples/midpass.html
+ return '/*";}}/* */';
+ }
+
+ if ($this->_inHack) {
+ // inversion: feeding only to one browser
+ $pattern = '@
+ ^/ # comment started like /*/
+ \\s*
+ (\\S[\\s\\S]+?) # has at least some non-ws content
+ \\s*
+ /\\* # ends like /*/ or /**/
+ @x';
+ if (preg_match($pattern, $m, $n)) {
+ // end hack mode after this comment, but preserve the hack and comment content
+ $this->_inHack = false;
+
+ return "/*/{$n[1]}/**/";
+ }
+ }
+
+ if (substr($m, -1) === '\\') { // comment ends like \*/
+ // begin hack mode and preserve hack
+ $this->_inHack = true;
+
+ return '/*\\*/';
+ }
+
+ if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
+ // begin hack mode and preserve hack
+ $this->_inHack = true;
+
+ return '/*/*/';
+ }
+
+ if ($this->_inHack) {
+ // a regular comment ends hack mode but should be preserved
+ $this->_inHack = false;
+
+ return '/**/';
+ }
+
+ // Issue 107: if there's any surrounding whitespace, it may be important, so
+ // replace the comment with a single space
+ return $hasSurroundingWs ? ' ' : ''; // remove all other comments
+ }
+
+ /**
+ * Process a font-family listing and return a replacement
+ *
+ * @param array $m regex matches
+ *
+ * @return string
+ */
+ protected function _fontFamilyCB($m)
+ {
+ // Issue 210: must not eliminate WS between words in unquoted families
+ $flags = PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY;
+ $pieces = preg_split('/(\'[^\']+\'|"[^"]+")/', $m[1], null, $flags);
+ $out = 'font-family:';
+
+ while (null !== ($piece = array_shift($pieces))) {
+ if ($piece[0] !== '"' && $piece[0] !== "'") {
+ $piece = preg_replace('/\\s+/', ' ', $piece);
+ $piece = preg_replace('/\\s?,\\s?/', ',', $piece);
+ }
+ $out .= $piece;
+ }
+
+ return $out . $m[2];
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/CSS/UriRewriter.php b/admin/survey/minify/lib/Minify/CSS/UriRewriter.php
new file mode 100644
index 0000000..6f69908
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CSS/UriRewriter.php
@@ -0,0 +1,358 @@
+<?php
+/**
+ * Class Minify_CSS_UriRewriter
+ * @package Minify
+ */
+
+/**
+ * Rewrite file-relative URIs as root-relative in CSS files
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_CSS_UriRewriter
+{
+
+ /**
+ * rewrite() and rewriteRelative() append debugging information here
+ *
+ * @var string
+ */
+ public static $debugText = '';
+
+ /**
+ * In CSS content, rewrite file relative URIs as root relative
+ *
+ * @param string $css
+ *
+ * @param string $currentDir The directory of the current CSS file.
+ *
+ * @param string $docRoot The document root of the web site in which
+ * the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']).
+ *
+ * @param array $symlinks (default = array()) If the CSS file is stored in
+ * a symlink-ed directory, provide an array of link paths to
+ * target paths, where the link paths are within the document root. Because
+ * paths need to be normalized for this to work, use "//" to substitute
+ * the doc root in the link paths (the array keys). E.g.:
+ * <code>
+ * array('//symlink' => '/real/target/path') // unix
+ * array('//static' => 'D:\\staticStorage') // Windows
+ * </code>
+ *
+ * @return string
+ */
+ public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
+ {
+ self::$_docRoot = self::_realpath(
+ $docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
+ );
+ self::$_currentDir = self::_realpath($currentDir);
+ self::$_symlinks = array();
+
+ // normalize symlinks in order to map to link
+ foreach ($symlinks as $link => $target) {
+ $link = ($link === '//') ? self::$_docRoot : str_replace('//', self::$_docRoot . '/', $link);
+ $link = strtr($link, '/', DIRECTORY_SEPARATOR);
+
+ self::$_symlinks[$link] = self::_realpath($target);
+ }
+
+ self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
+ . "currentDir : " . self::$_currentDir . "\n";
+ if (self::$_symlinks) {
+ self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
+ }
+ self::$debugText .= "\n";
+
+ $css = self::_trimUrls($css);
+
+ $css = self::_owlifySvgPaths($css);
+
+ // rewrite
+ $pattern = '/@import\\s+([\'"])(.*?)[\'"]/';
+ $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
+
+ $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/';
+ $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
+
+ $css = self::_unOwlify($css);
+
+ return $css;
+ }
+
+ /**
+ * In CSS content, prepend a path to relative URIs
+ *
+ * @param string $css
+ *
+ * @param string $path The path to prepend.
+ *
+ * @return string
+ */
+ public static function prepend($css, $path)
+ {
+ self::$_prependPath = $path;
+
+ $css = self::_trimUrls($css);
+
+ $css = self::_owlifySvgPaths($css);
+
+ // append
+ $pattern = '/@import\\s+([\'"])(.*?)[\'"]/';
+ $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
+
+ $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/';
+ $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
+
+ $css = self::_unOwlify($css);
+
+ self::$_prependPath = null;
+
+ return $css;
+ }
+
+ /**
+ * Get a root relative URI from a file relative URI
+ *
+ * <code>
+ * Minify_CSS_UriRewriter::rewriteRelative(
+ * '../img/hello.gif'
+ * , '/home/user/www/css' // path of CSS file
+ * , '/home/user/www' // doc root
+ * );
+ * // returns '/img/hello.gif'
+ *
+ * // example where static files are stored in a symlinked directory
+ * Minify_CSS_UriRewriter::rewriteRelative(
+ * 'hello.gif'
+ * , '/var/staticFiles/theme'
+ * , '/home/user/www'
+ * , array('/home/user/www/static' => '/var/staticFiles')
+ * );
+ * // returns '/static/theme/hello.gif'
+ * </code>
+ *
+ * @param string $uri file relative URI
+ *
+ * @param string $realCurrentDir realpath of the current file's directory.
+ *
+ * @param string $realDocRoot realpath of the site document root.
+ *
+ * @param array $symlinks (default = array()) If the file is stored in
+ * a symlink-ed directory, provide an array of link paths to
+ * real target paths, where the link paths "appear" to be within the document
+ * root. E.g.:
+ * <code>
+ * array('/home/foo/www/not/real/path' => '/real/target/path') // unix
+ * array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
+ * </code>
+ *
+ * @return string
+ */
+ public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
+ {
+ // prepend path with current dir separator (OS-independent)
+ $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR);
+ $path .= DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
+
+ self::$debugText .= "file-relative URI : {$uri}\n"
+ . "path prepended : {$path}\n";
+
+ // "unresolve" a symlink back to doc root
+ foreach ($symlinks as $link => $target) {
+ if (0 === strpos($path, $target)) {
+ // replace $target with $link
+ $path = $link . substr($path, strlen($target));
+
+ self::$debugText .= "symlink unresolved : {$path}\n";
+
+ break;
+ }
+ }
+ // strip doc root
+ $path = substr($path, strlen($realDocRoot));
+
+ self::$debugText .= "docroot stripped : {$path}\n";
+
+ // fix to root-relative URI
+ $uri = strtr($path, '/\\', '//');
+ $uri = self::removeDots($uri);
+
+ self::$debugText .= "traversals removed : {$uri}\n\n";
+
+ return $uri;
+ }
+
+ /**
+ * Remove instances of "./" and "../" where possible from a root-relative URI
+ *
+ * @param string $uri
+ *
+ * @return string
+ */
+ public static function removeDots($uri)
+ {
+ $uri = str_replace('/./', '/', $uri);
+ // inspired by patch from Oleg Cherniy
+ do {
+ $uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed);
+ } while ($changed);
+
+ return $uri;
+ }
+
+ /**
+ * Defines which class to call as part of callbacks, change this
+ * if you extend Minify_CSS_UriRewriter
+ *
+ * @var string
+ */
+ protected static $className = 'Minify_CSS_UriRewriter';
+
+ /**
+ * Get realpath with any trailing slash removed. If realpath() fails,
+ * just remove the trailing slash.
+ *
+ * @param string $path
+ *
+ * @return mixed path with no trailing slash
+ */
+ protected static function _realpath($path)
+ {
+ $realPath = realpath($path);
+ if ($realPath !== false) {
+ $path = $realPath;
+ }
+
+ return rtrim($path, '/\\');
+ }
+
+ /**
+ * Directory of this stylesheet
+ *
+ * @var string
+ */
+ private static $_currentDir = '';
+
+ /**
+ * DOC_ROOT
+ *
+ * @var string
+ */
+ private static $_docRoot = '';
+
+ /**
+ * directory replacements to map symlink targets back to their
+ * source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
+ *
+ * @var array
+ */
+ private static $_symlinks = array();
+
+ /**
+ * Path to prepend
+ *
+ * @var string
+ */
+ private static $_prependPath = null;
+
+ /**
+ * @param string $css
+ *
+ * @return string
+ */
+ private static function _trimUrls($css)
+ {
+ $pattern = '/
+ url\\( # url(
+ \\s*
+ ([^\\)]+?) # 1 = URI (assuming does not contain ")")
+ \\s*
+ \\) # )
+ /x';
+
+ return preg_replace($pattern, 'url($1)', $css);
+ }
+
+ /**
+ * @param array $m
+ *
+ * @return string
+ */
+ private static function _processUriCB($m)
+ {
+ // $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
+ $isImport = ($m[0][0] === '@');
+ // determine URI and the quote character (if any)
+ if ($isImport) {
+ $quoteChar = $m[1];
+ $uri = $m[2];
+ } else {
+ // $m[1] is either quoted or not
+ $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : '';
+
+ $uri = ($quoteChar === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2);
+ }
+
+ if ($uri === '') {
+ return $m[0];
+ }
+
+ // if not root/scheme relative and not starts with scheme
+ if (!preg_match('~^(/|[a-z]+\:)~', $uri)) {
+ // URI is file-relative: rewrite depending on options
+ if (self::$_prependPath === null) {
+ $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
+ } else {
+ $uri = self::$_prependPath . $uri;
+ if ($uri[0] === '/') {
+ $root = '';
+ $rootRelative = $uri;
+ $uri = $root . self::removeDots($rootRelative);
+ } elseif (preg_match('@^((https?\:)?//([^/]+))/@', $uri, $m) && (false !== strpos($m[3], '.'))) {
+ $root = $m[1];
+ $rootRelative = substr($uri, strlen($root));
+ $uri = $root . self::removeDots($rootRelative);
+ }
+ }
+ }
+
+ if ($isImport) {
+ return "@import {$quoteChar}{$uri}{$quoteChar}";
+ } else {
+ return "url({$quoteChar}{$uri}{$quoteChar})";
+ }
+ }
+
+ /**
+ * Mungs some inline SVG URL declarations so they won't be touched
+ *
+ * @link https://github.com/mrclay/minify/issues/517
+ * @see _unOwlify
+ *
+ * @param string $css
+ * @return string
+ */
+ private static function _owlifySvgPaths($css)
+ {
+ $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~';
+
+ return preg_replace($pattern, '$1owl$2', $css);
+ }
+
+ /**
+ * Undo work of _owlify
+ *
+ * @see _owlifySvgPaths
+ *
+ * @param string $css
+ * @return string
+ */
+ private static function _unOwlify($css)
+ {
+ $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~';
+
+ return preg_replace($pattern, '$1url', $css);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/CSSmin.php b/admin/survey/minify/lib/Minify/CSSmin.php
new file mode 100644
index 0000000..dcde782
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CSSmin.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Class Minify_CSSmin
+ * @package Minify
+ */
+
+use tubalmartin\CssMin\Minifier as CSSmin;
+
+/**
+ * Wrapper for CSSmin
+ *
+ * This class uses CSSmin and Minify_CSS_UriRewriter to minify CSS and rewrite relative URIs.
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_CSSmin
+{
+
+ /**
+ * Minify a CSS string
+ *
+ * @param string $css
+ *
+ * @param array $options available options:
+ *
+ * 'removeCharsets': (default true) remove all @charset at-rules
+ *
+ * 'prependRelativePath': (default null) if given, this string will be
+ * prepended to all relative URIs in import/url declarations
+ *
+ * 'currentDir': (default null) if given, this is assumed to be the
+ * directory of the current CSS file. Using this, minify will rewrite
+ * all relative URIs in import/url declarations to correctly point to
+ * the desired files. For this to work, the files *must* exist and be
+ * visible by the PHP process.
+ *
+ * 'symlinks': (default = array()) If the CSS file is stored in
+ * a symlink-ed directory, provide an array of link paths to
+ * target paths, where the link paths are within the document root. Because
+ * paths need to be normalized for this to work, use "//" to substitute
+ * the doc root in the link paths (the array keys). E.g.:
+ * <code>
+ * array('//symlink' => '/real/target/path') // unix
+ * array('//static' => 'D:\\staticStorage') // Windows
+ * </code>
+ *
+ * 'docRoot': (default = $_SERVER['DOCUMENT_ROOT'])
+ * see Minify_CSS_UriRewriter::rewrite
+ *
+ * @return string
+ */
+ public static function minify($css, $options = array())
+ {
+ $options = array_merge(array(
+ 'compress' => true,
+ 'removeCharsets' => true,
+ 'currentDir' => null,
+ 'docRoot' => $_SERVER['DOCUMENT_ROOT'],
+ 'prependRelativePath' => null,
+ 'symlinks' => array(),
+ ), $options);
+
+ if ($options['removeCharsets']) {
+ $css = preg_replace('/@charset[^;]+;\\s*/', '', $css);
+ }
+ if ($options['compress']) {
+ $obj = new CSSmin();
+ $css = $obj->run($css);
+ }
+ if (! $options['currentDir'] && ! $options['prependRelativePath']) {
+ return $css;
+ }
+ if ($options['currentDir']) {
+ return Minify_CSS_UriRewriter::rewrite(
+ $css
+ ,$options['currentDir']
+ ,$options['docRoot']
+ ,$options['symlinks']
+ );
+ }
+
+ return Minify_CSS_UriRewriter::prepend(
+ $css
+ ,$options['prependRelativePath']
+ );
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Cache/APC.php b/admin/survey/minify/lib/Minify/Cache/APC.php
new file mode 100644
index 0000000..27a57d7
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/APC.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Class Minify_Cache_APC
+ * @package Minify
+ */
+
+/**
+ * APC-based cache class for Minify
+ *
+ * <code>
+ * Minify::setCache(new Minify_Cache_APC());
+ * </code>
+ *
+ * @package Minify
+ * @author Chris Edwards
+ **/
+class Minify_Cache_APC implements Minify_CacheInterface
+{
+
+ /**
+ * Create a Minify_Cache_APC object, to be passed to
+ * Minify::setCache().
+ *
+ *
+ * @param int $expire seconds until expiration (default = 0
+ * meaning the item will not get an expiration date)
+ *
+ * @return null
+ */
+ public function __construct($expire = 0)
+ {
+ $this->_exp = $expire;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id
+ *
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ return apc_store($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp);
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ if (! $this->_fetch($id)) {
+ return false;
+ }
+
+ if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
+ return mb_strlen($this->_data, '8bit');
+ } else {
+ return strlen($this->_data);
+ }
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id
+ *
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id
+ */
+ public function display($id)
+ {
+ echo $this->_fetch($id) ? $this->_data : '';
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ return $this->_fetch($id) ? $this->_data : '';
+ }
+
+ private $_exp = null;
+
+ // cache of most recently fetched id
+ private $_lm = null;
+ private $_data = null;
+ private $_id = null;
+
+ /**
+ * Fetch data and timestamp from apc, store in instance
+ *
+ * @param string $id
+ *
+ * @return bool success
+ */
+ private function _fetch($id)
+ {
+ if ($this->_id === $id) {
+ return true;
+ }
+ $ret = apc_fetch($id);
+ if (false === $ret) {
+ $this->_id = null;
+
+ return false;
+ }
+
+ list($this->_lm, $this->_data) = explode('|', $ret, 2);
+ $this->_id = $id;
+
+ return true;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Cache/File.php b/admin/survey/minify/lib/Minify/Cache/File.php
new file mode 100644
index 0000000..5db1e20
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/File.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Class Minify_Cache_File
+ * @package Minify
+ */
+
+use Psr\Log\LoggerInterface;
+
+class Minify_Cache_File implements Minify_CacheInterface
+{
+
+ /**
+ * @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 = sys_get_temp_dir();
+ }
+ $this->locking = $fileLocking;
+ $this->path = $path;
+
+ if (!$logger) {
+ $logger = new \Monolog\Logger('minify');
+ }
+ $this->logger = $logger;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ $flag = $this->locking ? LOCK_EX : null;
+ $file = $this->path . '/' . $id;
+
+ if (! @file_put_contents($file, $data, $flag)) {
+ $this->logger->warning("Minify_Cache_File: Write failed to '$file'");
+ }
+
+ // write control
+ if ($data !== $this->fetch($id)) {
+ @unlink($file);
+ $this->logger->warning("Minify_Cache_File: Post-write read failed for '$file'");
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ return filesize($this->path . '/' . $id);
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ $file = $this->path . '/' . $id;
+
+ return (is_file($file) && (filemtime($file) >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id (e.g. a filename)
+ */
+ public function display($id)
+ {
+ if (!$this->locking) {
+ readfile($this->path . '/' . $id);
+
+ return;
+ }
+
+ $fp = fopen($this->path . '/' . $id, 'rb');
+ flock($fp, LOCK_SH);
+ fpassthru($fp);
+ flock($fp, LOCK_UN);
+ fclose($fp);
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ if (!$this->locking) {
+ return file_get_contents($this->path . '/' . $id);
+ }
+
+ $fp = fopen($this->path . '/' . $id, 'rb');
+ if (!$fp) {
+ return false;
+ }
+
+ flock($fp, LOCK_SH);
+ $ret = stream_get_contents($fp);
+ flock($fp, LOCK_UN);
+ fclose($fp);
+
+ return $ret;
+ }
+
+ /**
+ * Fetch the cache path used
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->path;
+ }
+
+ /**
+ * Get a usable temp directory
+ *
+ * @return string
+ * @deprecated
+ */
+ public static function tmp()
+ {
+ 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)
+ {
+ trigger_error(__METHOD__ . ' is deprecated in Minify 3.0.', E_USER_DEPRECATED);
+ $this->logger->warning($msg);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Cache/Memcache.php b/admin/survey/minify/lib/Minify/Cache/Memcache.php
new file mode 100644
index 0000000..726785a
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/Memcache.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Class Minify_Cache_Memcache
+ * @package Minify
+ */
+
+/**
+ * Memcache-based cache class for Minify
+ *
+ * <code>
+ * // fall back to disk caching if memcache can't connect
+ * $memcache = new Memcache;
+ * if ($memcache->connect('localhost', 11211)) {
+ * Minify::setCache(new Minify_Cache_Memcache($memcache));
+ * } else {
+ * Minify::setCache();
+ * }
+ * </code>
+ **/
+class Minify_Cache_Memcache implements Minify_CacheInterface
+{
+
+ /**
+ * Create a Minify_Cache_Memcache object, to be passed to
+ * Minify::setCache().
+ *
+ * @param Memcache $memcache already-connected instance
+ *
+ * @param int $expire seconds until expiration (default = 0
+ * meaning the item will not get an expiration date)
+ */
+ public function __construct($memcache, $expire = 0)
+ {
+ $this->_mc = $memcache;
+ $this->_exp = $expire;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id
+ *
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ return $this->_mc->set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", 0, $this->_exp);
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ if (! $this->_fetch($id)) {
+ return false;
+ }
+
+ if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
+ return mb_strlen($this->_data, '8bit');
+ } else {
+ return strlen($this->_data);
+ }
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id
+ *
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id
+ */
+ public function display($id)
+ {
+ echo $this->_fetch($id) ? $this->_data : '';
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ return $this->_fetch($id) ? $this->_data : '';
+ }
+
+ private $_mc = null;
+ private $_exp = null;
+
+ // cache of most recently fetched id
+ private $_lm = null;
+ private $_data = null;
+ private $_id = null;
+
+ /**
+ * Fetch data and timestamp from memcache, store in instance
+ *
+ * @param string $id
+ *
+ * @return bool success
+ */
+ private function _fetch($id)
+ {
+ if ($this->_id === $id) {
+ return true;
+ }
+
+ $ret = $this->_mc->get($id);
+ if (false === $ret) {
+ $this->_id = null;
+
+ return false;
+ }
+
+ list($this->_lm, $this->_data) = explode('|', $ret, 2);
+ $this->_id = $id;
+
+ return true;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Cache/Null.php b/admin/survey/minify/lib/Minify/Cache/Null.php
new file mode 100644
index 0000000..b6f6566
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/Null.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * Class Minify_Cache_Null
+ *
+ * If this is used, Minify will not use a cache and, for each 200 response, will
+ * need to recombine files, minify and encode the output.
+ *
+ * @package Minify
+ */
+class Minify_Cache_Null implements Minify_CacheInterface
+{
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id (e.g. a filename)
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id (e.g. a filename)
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id (e.g. a filename)
+ */
+ public function display($id)
+ {
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ }
+} \ No newline at end of file
diff --git a/admin/survey/minify/lib/Minify/Cache/WinCache.php b/admin/survey/minify/lib/Minify/Cache/WinCache.php
new file mode 100644
index 0000000..089d66d
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/WinCache.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Class Minify_Cache_Wincache
+ * @package Minify
+ */
+
+/**
+ * WinCache-based cache class for Minify
+ *
+ * <code>
+ * Minify::setCache(new Minify_Cache_WinCache());
+ * </code>
+ *
+ * @package Minify
+ * @author Matthias Fax
+ **/
+class Minify_Cache_WinCache implements Minify_CacheInterface
+{
+ /**
+ * Create a Minify_Cache_Wincache object, to be passed to
+ * Minify::setCache().
+ *
+ * @param int $expire seconds until expiration (default = 0
+ * meaning the item will not get an expiration date)
+ *
+ * @throws Exception
+ */
+ public function __construct($expire = 0)
+ {
+ if (!function_exists('wincache_ucache_info')) {
+ throw new Exception("WinCache for PHP is not installed to be able to use Minify_Cache_WinCache!");
+ }
+ $this->_exp = $expire;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id
+ *
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ return wincache_ucache_set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp);
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ if (!$this->_fetch($id)) {
+ return false;
+ }
+
+ if (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload') & 2)) {
+ return mb_strlen($this->_data, '8bit');
+ } else {
+ return strlen($this->_data);
+ }
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id
+ *
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id
+ */
+ public function display($id)
+ {
+ echo $this->_fetch($id) ? $this->_data : '';
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ return $this->_fetch($id) ? $this->_data : '';
+ }
+
+ private $_exp = null;
+
+ // cache of most recently fetched id
+ private $_lm = null;
+ private $_data = null;
+ private $_id = null;
+
+ /**
+ * Fetch data and timestamp from WinCache, store in instance
+ *
+ * @param string $id
+ *
+ * @return bool success
+ */
+ private function _fetch($id)
+ {
+ if ($this->_id === $id) {
+ return true;
+ }
+
+ $suc = false;
+ $ret = wincache_ucache_get($id, $suc);
+ if (!$suc) {
+ $this->_id = null;
+
+ return false;
+ }
+
+ list($this->_lm, $this->_data) = explode('|', $ret, 2);
+ $this->_id = $id;
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/admin/survey/minify/lib/Minify/Cache/XCache.php b/admin/survey/minify/lib/Minify/Cache/XCache.php
new file mode 100644
index 0000000..aa2a8de
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/XCache.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Class Minify_Cache_XCache
+ *
+ * @link http://xcache.lighttpd.net/
+ * @package Minify
+ */
+
+/**
+ * XCache-based cache class for Minify
+ * {@see http://xcache.lighttpd.net/wiki/XcacheApi XCache API}
+ *
+ * <code>
+ * Minify::setCache(new Minify_Cache_XCache());
+ * </code>
+ *
+ * @package Minify
+ * @author Elan Ruusamäe <glen@delfi.ee>
+ **/
+class Minify_Cache_XCache implements Minify_CacheInterface
+{
+
+ /**
+ * Create a Minify_Cache_XCache object, to be passed to
+ * Minify::setCache().
+ *
+ * @param int $expire seconds until expiration (default = 0
+ * meaning the item will not get an expiration date)
+ */
+ public function __construct($expire = 0)
+ {
+ $this->_exp = $expire;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id
+ * @param string $data
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ return xcache_set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp);
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ if (! $this->_fetch($id)) {
+ return false;
+ }
+
+ if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
+ return mb_strlen($this->_data, '8bit');
+ } else {
+ return strlen($this->_data);
+ }
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id
+ * @param int $srcMtime mtime of the original source file(s)
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id
+ */
+ public function display($id)
+ {
+ echo $this->_fetch($id) ? $this->_data : '';
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id
+ * @return string
+ */
+ public function fetch($id)
+ {
+ return $this->_fetch($id) ? $this->_data : '';
+ }
+
+ private $_exp = null;
+
+ // cache of most recently fetched id
+ private $_lm = null;
+ private $_data = null;
+ private $_id = null;
+
+ /**
+ * Fetch data and timestamp from xcache, store in instance
+ *
+ * @param string $id
+ * @return bool success
+ */
+ private function _fetch($id)
+ {
+ if ($this->_id === $id) {
+ return true;
+ }
+
+ $ret = xcache_get($id);
+ if (false === $ret) {
+ $this->_id = null;
+
+ return false;
+ }
+
+ list($this->_lm, $this->_data) = explode('|', $ret, 2);
+ $this->_id = $id;
+
+ return true;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Cache/ZendPlatform.php b/admin/survey/minify/lib/Minify/Cache/ZendPlatform.php
new file mode 100644
index 0000000..90dfabb
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Cache/ZendPlatform.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Class Minify_Cache_ZendPlatform
+ * @package Minify
+ */
+
+/**
+ * ZendPlatform-based cache class for Minify
+ *
+ * Based on Minify_Cache_APC, uses output_cache_get/put (currently deprecated)
+ *
+ * <code>
+ * Minify::setCache(new Minify_Cache_ZendPlatform());
+ * </code>
+ *
+ * @package Minify
+ * @author Patrick van Dissel
+ */
+class Minify_Cache_ZendPlatform implements Minify_CacheInterface
+{
+
+ /**
+ * Create a Minify_Cache_ZendPlatform object, to be passed to
+ * Minify::setCache().
+ *
+ * @param int $expire seconds until expiration (default = 0
+ * meaning the item will not get an expiration date)
+ *
+ */
+ public function __construct($expire = 0)
+ {
+ $this->_exp = $expire;
+ }
+
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id
+ *
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data)
+ {
+ return output_cache_put($id, "{$_SERVER['REQUEST_TIME']}|{$data}");
+ }
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id)
+ {
+ return $this->_fetch($id) ? strlen($this->_data) : false;
+ }
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id
+ *
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime)
+ {
+ return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
+ }
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id
+ */
+ public function display($id)
+ {
+ echo $this->_fetch($id) ? $this->_data : '';
+ }
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id
+ *
+ * @return string
+ */
+ public function fetch($id)
+ {
+ return $this->_fetch($id) ? $this->_data : '';
+ }
+
+ private $_exp = null;
+
+ // cache of most recently fetched id
+ private $_lm = null;
+ private $_data = null;
+ private $_id = null;
+
+ /**
+ * Fetch data and timestamp from ZendPlatform, store in instance
+ *
+ * @param string $id
+ *
+ * @return bool success
+ */
+ private function _fetch($id)
+ {
+ if ($this->_id === $id) {
+ return true;
+ }
+
+ $ret = output_cache_get($id, $this->_exp);
+ if (false === $ret) {
+ $this->_id = null;
+
+ return false;
+ }
+
+ list($this->_lm, $this->_data) = explode('|', $ret, 2);
+ $this->_id = $id;
+
+ return true;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/CacheInterface.php b/admin/survey/minify/lib/Minify/CacheInterface.php
new file mode 100644
index 0000000..4b1c51a
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CacheInterface.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Interface Minify_CacheInterface
+ * @package Minify
+ */
+
+/**
+ * Interface for Minify cache adapters
+ *
+ * @package Minify
+ */
+interface Minify_CacheInterface
+{
+ /**
+ * Write data to cache.
+ *
+ * @param string $id cache id (e.g. a filename)
+ * @param string $data
+ *
+ * @return bool success
+ */
+ public function store($id, $data);
+
+ /**
+ * Get the size of a cache entry
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return int size in bytes
+ */
+ public function getSize($id);
+
+ /**
+ * Does a valid cache entry exist?
+ *
+ * @param string $id cache id (e.g. a filename)
+ * @param int $srcMtime mtime of the original source file(s)
+ *
+ * @return bool exists
+ */
+ public function isValid($id, $srcMtime);
+
+ /**
+ * Send the cached content to output
+ *
+ * @param string $id cache id (e.g. a filename)
+ */
+ public function display($id);
+
+ /**
+ * Fetch the cached content
+ *
+ * @param string $id cache id (e.g. a filename)
+ *
+ * @return string
+ */
+ public function fetch($id);
+}
diff --git a/admin/survey/minify/lib/Minify/ClosureCompiler.php b/admin/survey/minify/lib/Minify/ClosureCompiler.php
new file mode 100644
index 0000000..e95ebc3
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/ClosureCompiler.php
@@ -0,0 +1,240 @@
+<?php
+/**
+ * Class Minify_ClosureCompiler
+ * @package Minify
+ */
+
+/**
+ * Compress Javascript using the Closure Compiler
+ *
+ * You must set $jarFile and $tempDir before calling the minify functions.
+ * Also, depending on your shell's environment, you may need to specify
+ * the full path to java in $javaExecutable or use putenv() to setup the
+ * Java environment.
+ *
+ * <code>
+ * Minify_ClosureCompiler::$jarFile = '/path/to/closure-compiler-20120123.jar';
+ * Minify_ClosureCompiler::$tempDir = '/tmp';
+ * $code = Minify_ClosureCompiler::minify(
+ * $code,
+ * array('compilation_level' => 'SIMPLE_OPTIMIZATIONS')
+ * );
+ *
+ * --compilation_level WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS
+ *
+ * </code>
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ * @author Elan Ruusamäe <glen@delfi.ee>
+ */
+class Minify_ClosureCompiler
+{
+ public static $isDebug = false;
+
+ /**
+ * Filepath of the Closure Compiler jar file. This must be set before
+ * calling minifyJs().
+ *
+ * @var string
+ */
+ public static $jarFile;
+
+ /**
+ * Writable temp directory. This must be set before calling minifyJs().
+ *
+ * @var string
+ */
+ public static $tempDir;
+
+ /**
+ * Filepath of "java" executable (may be needed if not in shell's PATH)
+ *
+ * @var string
+ */
+ public static $javaExecutable = 'java';
+
+ /**
+ * Default command line options passed to closure-compiler
+ *
+ * @var array
+ */
+ public static $defaultOptions = array(
+ 'charset' => 'utf-8',
+ 'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
+ 'warning_level' => 'QUIET',
+ );
+
+ /**
+ * Minify a Javascript string
+ *
+ * @param string $js
+ * @param array $options (verbose is ignored)
+ * @see https://code.google.com/p/closure-compiler/source/browse/trunk/README
+ * @return string
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ public static function minify($js, $options = array())
+ {
+ $min = new static();
+
+ return $min->process($js, $options);
+ }
+
+ /**
+ * Process $js using $options.
+ *
+ * @param string $js
+ * @param array $options
+ * @return string
+ * @throws Exception
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ public function process($js, $options)
+ {
+ $tmpFile = $this->dumpFile(self::$tempDir, $js);
+ try {
+ $result = $this->compile($tmpFile, $options);
+ } catch (Exception $e) {
+ unlink($tmpFile);
+ throw $e;
+ }
+ unlink($tmpFile);
+
+ return $result;
+ }
+
+ /**
+ * @param string $tmpFile
+ * @param array $options
+ * @return string
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function compile($tmpFile, $options)
+ {
+ $command = $this->getCommand($options, $tmpFile);
+
+ return implode("\n", $this->shell($command));
+ }
+
+ /**
+ * @param array $userOptions
+ * @param string $tmpFile
+ * @return string
+ */
+ protected function getCommand($userOptions, $tmpFile)
+ {
+ $args = array_merge(
+ $this->getCompilerCommandLine(),
+ $this->getOptionsCommandLine($userOptions)
+ );
+
+ return implode(' ', $args) . ' ' . escapeshellarg($tmpFile);
+ }
+
+ /**
+ * @return array
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function getCompilerCommandLine()
+ {
+ $this->checkJar(self::$jarFile);
+ $server = array(
+ self::$javaExecutable,
+ '-jar',
+ escapeshellarg(self::$jarFile)
+ );
+
+ return $server;
+ }
+
+ /**
+ * @param array $userOptions
+ * @return array
+ */
+ protected function getOptionsCommandLine($userOptions)
+ {
+ $args = array();
+
+ $options = array_merge(
+ static::$defaultOptions,
+ $userOptions
+ );
+
+ foreach ($options as $key => $value) {
+ $args[] = "--{$key} " . escapeshellarg($value);
+ }
+
+ return $args;
+ }
+
+ /**
+ * @param string $jarFile
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function checkJar($jarFile)
+ {
+ if (!is_file($jarFile)) {
+ throw new Minify_ClosureCompiler_Exception('$jarFile(' . $jarFile . ') is not a valid file.');
+ }
+ if (!is_readable($jarFile)) {
+ throw new Minify_ClosureCompiler_Exception('$jarFile(' . $jarFile . ') is not readable.');
+ }
+ }
+
+ /**
+ * @param string $tempDir
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function checkTempdir($tempDir)
+ {
+ if (!is_dir($tempDir)) {
+ throw new Minify_ClosureCompiler_Exception('$tempDir(' . $tempDir . ') is not a valid direcotry.');
+ }
+ if (!is_writable($tempDir)) {
+ throw new Minify_ClosureCompiler_Exception('$tempDir(' . $tempDir . ') is not writable.');
+ }
+ }
+
+ /**
+ * Write $content to a temporary file residing in $dir.
+ *
+ * @param string $dir
+ * @param string $content
+ * @return string
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function dumpFile($dir, $content)
+ {
+ $this->checkTempdir($dir);
+ $tmpFile = tempnam($dir, 'cc_');
+ if (!$tmpFile) {
+ throw new Minify_ClosureCompiler_Exception('Could not create temp file in "' . $dir . '".');
+ }
+ file_put_contents($tmpFile, $content);
+
+ return $tmpFile;
+ }
+
+ /**
+ * Execute command, throw if exit code is not in $expectedCodes array
+ *
+ * @param string $command
+ * @param array $expectedCodes
+ * @return mixed
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function shell($command, $expectedCodes = array(0))
+ {
+ exec($command, $output, $result_code);
+ if (!in_array($result_code, $expectedCodes)) {
+ throw new Minify_ClosureCompiler_Exception("Unpexpected return code: $result_code");
+ }
+
+ return $output;
+ }
+}
+
+class Minify_ClosureCompiler_Exception extends Exception
+{
+}
diff --git a/admin/survey/minify/lib/Minify/CommentPreserver.php b/admin/survey/minify/lib/Minify/CommentPreserver.php
new file mode 100644
index 0000000..2e6599d
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/CommentPreserver.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Class Minify_CommentPreserver
+ * @package Minify
+ */
+
+/**
+ * Process a string in pieces preserving C-style comments that begin with "/*!"
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_CommentPreserver
+{
+
+ /**
+ * String to be prepended to each preserved comment
+ *
+ * @var string
+ */
+ public static $prepend = "\n";
+
+ /**
+ * String to be appended to each preserved comment
+ *
+ * @var string
+ */
+ public static $append = "\n";
+
+ /**
+ * Process a string outside of C-style comments that begin with "/*!"
+ *
+ * On each non-empty string outside these comments, the given processor
+ * function will be called. The comments will be surrounded by
+ * Minify_CommentPreserver::$preprend and Minify_CommentPreserver::$append.
+ *
+ * @param string $content
+ * @param callback $processor function
+ * @param array $args array of extra arguments to pass to the processor
+ * function (default = array())
+ * @return string
+ */
+ public static function process($content, $processor, $args = array())
+ {
+ $ret = '';
+ while (true) {
+ list($beforeComment, $comment, $afterComment) = self::_nextComment($content);
+ if ('' !== $beforeComment) {
+ $callArgs = $args;
+ array_unshift($callArgs, $beforeComment);
+ $ret .= call_user_func_array($processor, $callArgs);
+ }
+ if (false === $comment) {
+ break;
+ }
+ $ret .= $comment;
+ $content = $afterComment;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Extract comments that YUI Compressor preserves.
+ *
+ * @param string $in input
+ *
+ * @return array 3 elements are returned. If a YUI comment is found, the
+ * 2nd element is the comment and the 1st and 3rd are the surrounding
+ * strings. If no comment is found, the entire string is returned as the
+ * 1st element and the other two are false.
+ */
+ private static function _nextComment($in)
+ {
+ if (false === ($start = strpos($in, '/*!')) || false === ($end = strpos($in, '*/', $start + 3))) {
+ return array($in, false, false);
+ }
+
+ $beforeComment = substr($in, 0, $start);
+ $comment = self::$prepend . '/*!' . substr($in, $start + 3, $end - $start - 1) . self::$append;
+
+ $endChars = (strlen($in) - $end - 2);
+ $afterComment = (0 === $endChars) ? '' : substr($in, -$endChars);
+
+ return array($beforeComment, $comment, $afterComment);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Config.php b/admin/survey/minify/lib/Minify/Config.php
new file mode 100644
index 0000000..a085920
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Config.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Minify;
+
+use Minify_CacheInterface;
+
+class Config
+{
+ /**
+ * @var bool
+ */
+ public $enableBuilder = false;
+
+ /**
+ * @var bool
+ */
+ public $enableStatic = 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();
+}
diff --git a/admin/survey/minify/lib/Minify/Controller/Base.php b/admin/survey/minify/lib/Minify/Controller/Base.php
new file mode 100644
index 0000000..557b514
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Controller/Base.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Class Minify_Controller_Base
+ * @package Minify
+ */
+
+use Psr\Log\LoggerInterface;
+use Monolog\Logger;
+
+/**
+ * Base class for Minify controller
+ *
+ * The controller class validates a request and uses it to create a configuration for Minify::serve().
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+abstract class Minify_Controller_Base implements Minify_ControllerInterface
+{
+
+ /**
+ * @var Minify_Env
+ */
+ protected $env;
+
+ /**
+ * @var Minify_Source_Factory
+ */
+ 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, LoggerInterface $logger = null)
+ {
+ $this->env = $env;
+ $this->sourceFactory = $sourceFactory;
+ if (!$logger) {
+ $logger = new Logger('minify');
+ }
+ $this->logger = $logger;
+ }
+
+ /**
+ * Create controller sources and options for Minify::serve()
+ *
+ * @param array $options controller and Minify options
+ *
+ * @return Minify_ServeConfiguration
+ */
+ abstract public function createConfiguration(array $options);
+
+ /**
+ * Send message to the Minify logger
+ *
+ * @param string $msg
+ *
+ * @return null
+ * @deprecated use $this->logger
+ */
+ public function log($msg)
+ {
+ trigger_error(__METHOD__ . ' is deprecated in Minify 3.0.', E_USER_DEPRECATED);
+ $this->logger->info($msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEnv()
+ {
+ return $this->env;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Controller/Files.php b/admin/survey/minify/lib/Minify/Controller/Files.php
new file mode 100644
index 0000000..a9bb941
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Controller/Files.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Class Minify_Controller_Files
+ * @package Minify
+ */
+
+use Monolog\Logger;
+
+/**
+ * Controller class for minifying a set of files
+ *
+ * E.g. the following would serve the minified Javascript for a site
+ * <code>
+ * $options = [
+ * 'checkAllowDirs' => false, // allow files to be anywhere
+ * ];
+ * $sourceFactory = new Minify_Source_Factory($env, $options, $cache);
+ * $controller = new Minify_Controller_Files($env, $sourceFactory);
+ * $minify->serve($controller, [
+ * 'files' => [
+ * '//js/jquery.js',
+ * '//js/plugins.js',
+ * '/home/username/file.js',
+ * ],
+ * ]);
+ * </code>
+ *
+ * @package Minify
+ * @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 Minify_ServeConfiguration
+ *
+ * Controller options:
+ *
+ * 'files': (required) array of complete file paths, or a single path
+ */
+ public function createConfiguration(array $options)
+ {
+ // strip controller options
+
+ $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) {
+ try {
+ $sources[] = $this->sourceFactory->makeSource($file);
+ } catch (Minify_Source_FactoryException $e) {
+ $this->logger->error($e->getMessage());
+
+ return new Minify_ServeConfiguration($options);
+ }
+ }
+
+ return new Minify_ServeConfiguration($options, $sources);
+ }
+}
+
diff --git a/admin/survey/minify/lib/Minify/Controller/Groups.php b/admin/survey/minify/lib/Minify/Controller/Groups.php
new file mode 100644
index 0000000..6d4e5f4
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Controller/Groups.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Class Minify_Controller_Groups
+ * @package Minify
+ */
+
+/**
+ * Controller class for serving predetermined groups of minimized sets, selected
+ * by PATH_INFO
+ *
+ * <code>
+ * 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
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_Controller_Groups extends Minify_Controller_Files
+{
+
+ /**
+ * Set up groups of files as sources
+ *
+ * @param array $options controller and Minify options
+ *
+ * 'groups': (required) array mapping PATH_INFO strings to arrays
+ * of complete file paths. @see Minify_Controller_Groups
+ *
+ * @return array Minify options
+ */
+ public function createConfiguration(array $options)
+ {
+ // strip controller options
+ $groups = $options['groups'];
+ unset($options['groups']);
+
+ $server = $this->env->server();
+
+ // mod_fcgid places PATH_INFO in ORIG_PATH_INFO
+ if (isset($server['ORIG_PATH_INFO'])) {
+ $pathInfo = substr($server['ORIG_PATH_INFO'], 1);
+ } elseif (isset($server['PATH_INFO'])) {
+ $pathInfo = substr($server['PATH_INFO'], 1);
+ } else {
+ $pathInfo = false;
+ }
+
+ if (false === $pathInfo || ! isset($groups[$pathInfo])) {
+ // no PATH_INFO or not a valid group
+ $this->logger->info("Missing PATH_INFO or no group set for \"$pathInfo\"");
+
+ return new Minify_ServeConfiguration($options);
+ }
+
+ $files = $groups[$pathInfo];
+ // if $files is a single object, casting will break it
+ if (is_object($files)) {
+ $files = array($files);
+ } elseif (! is_array($files)) {
+ $files = (array)$files;
+ }
+
+ $options['files'] = $files;
+
+ return parent::createConfiguration($options);
+ }
+}
+
diff --git a/admin/survey/minify/lib/Minify/Controller/MinApp.php b/admin/survey/minify/lib/Minify/Controller/MinApp.php
new file mode 100644
index 0000000..9a6a098
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Controller/MinApp.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Class Minify_Controller_MinApp
+ * @package Minify
+ */
+
+/**
+ * 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 createConfiguration(array $options)
+ {
+ // PHP insecure by default: realpath() and other FS functions can't handle null bytes.
+ $get = $this->env->get();
+ foreach (array('g', 'b', 'f') as $key) {
+ if (isset($get[$key])) {
+ $get[$key] = str_replace("\x00", '', (string)$get[$key]);
+ }
+ }
+
+ // filter controller options
+ $defaults = array(
+ 'groupsOnly' => false,
+ 'groups' => array(),
+ 'symlinks' => array(),
+ );
+ $minApp = isset($options['minApp']) ? $options['minApp'] : array();
+ $localOptions = array_merge($defaults, $minApp);
+
+ unset($options['minApp']);
+
+ // normalize $symlinks in order to map to target
+ $symlinks = array();
+ foreach ($localOptions['symlinks'] as $link => $target) {
+ if (0 === strpos($link, '//')) {
+ $link = rtrim(substr($link, 1), '/') . '/';
+ $target = rtrim($target, '/\\');
+ $symlinks[$link] = $target;
+ }
+ }
+
+ $sources = array();
+ $selectionId = '';
+ $firstMissing = null;
+
+ if (isset($get['g'])) {
+ // add group(s)
+ $selectionId .= 'g=' . $get['g'];
+ $keys = explode(',', $get['g']);
+ if ($keys != array_unique($keys)) {
+ $this->logger->info("Duplicate group key found.");
+
+ return new Minify_ServeConfiguration($options);
+ }
+ foreach ($keys as $key) {
+ if (! isset($localOptions['groups'][$key])) {
+ $this->logger->info("A group configuration for \"{$key}\" was not found");
+
+ return new Minify_ServeConfiguration($options);
+ }
+ $files = $localOptions['groups'][$key];
+ // 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) {
+ try {
+ $source = $this->sourceFactory->makeSource($file);
+ $sources[] = $source;
+ } catch (Minify_Source_FactoryException $e) {
+ $this->logger->error($e->getMessage());
+ if (null === $firstMissing) {
+ $firstMissing = basename($file);
+ continue;
+ } else {
+ $secondMissing = basename($file);
+ $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing'");
+
+ return new Minify_ServeConfiguration($options);
+ }
+ }
+ }
+ }
+ }
+ if (! $localOptions['groupsOnly'] && isset($get['f'])) {
+ // try user files
+ // The following restrictions are to limit the URLs that minify will
+ // respond to.
+
+ // verify at least one file, files are single comma separated, and are all same extension
+ $validPattern = preg_match('/^[^,]+\\.(css|less|scss|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m);
+ $hasComment = strpos($get['f'], '//') !== false;
+ $hasEscape = strpos($get['f'], '\\') !== false;
+
+ if (!$validPattern || $hasComment || $hasEscape) {
+ $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->logger->info("Duplicate files were specified");
+
+ return new Minify_ServeConfiguration($options);
+ }
+
+ if (isset($get['b'])) {
+ // check for validity
+ $isValidBase = preg_match('@^[^/]+(?:/[^/]+)*$@', $get['b']);
+ $hasDots = false !== strpos($get['b'], '..');
+ $isDot = $get['b'] === '.';
+
+ if ($isValidBase && !$hasDots && !$isDot) {
+ // valid base
+ $base = "/{$get['b']}/";
+ } else {
+ $this->logger->info("GET param 'b' was invalid");
+
+ return new Minify_ServeConfiguration($options);
+ }
+ } else {
+ $base = '/';
+ }
+
+ $basenames = array(); // just for cache id
+ foreach ($files as $file) {
+ $uri = $base . $file;
+ $path = $this->env->getDocRoot() . $uri;
+
+ // try to rewrite path
+ foreach ($symlinks as $link => $target) {
+ if (0 === strpos($uri, $link)) {
+ $path = $target . DIRECTORY_SEPARATOR . substr($uri, strlen($link));
+ break;
+ }
+ }
+
+ try {
+ $source = $this->sourceFactory->makeSource($path);
+ $sources[] = $source;
+ $basenames[] = basename($path, $ext);
+ } catch (Minify_Source_FactoryException $e) {
+ $this->logger->error($e->getMessage());
+ if (null === $firstMissing) {
+ $firstMissing = $uri;
+ continue;
+ } else {
+ $secondMissing = $uri;
+ $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing`'");
+
+ return new Minify_ServeConfiguration($options);
+ }
+ }
+ }
+ if ($selectionId) {
+ $selectionId .= '_f=';
+ }
+ $selectionId .= implode(',', $basenames) . $ext;
+ }
+
+ if (!$sources) {
+ $this->logger->info("No sources to serve");
+
+ return new Minify_ServeConfiguration($options);
+ }
+
+ if (null !== $firstMissing) {
+ array_unshift($sources, new Minify_Source(array(
+ 'id' => 'missingFile',
+ // should not cause cache invalidation
+ 'lastModified' => 0,
+ // due to caching, filename is unreliable.
+ 'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n",
+ 'minifier' => 'Minify::nullMinifier',
+ )));
+ }
+
+ return new Minify_ServeConfiguration($options, $sources, $selectionId);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Controller/Page.php b/admin/survey/minify/lib/Minify/Controller/Page.php
new file mode 100644
index 0000000..8ca00d5
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Controller/Page.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Class Minify_Controller_Page
+ * @package Minify
+ */
+
+/**
+ * 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)
+ */
+ public function createConfiguration(array $options)
+ {
+ if (isset($options['file'])) {
+ $sourceSpec = array(
+ 'filepath' => $options['file']
+ );
+ $f = $options['file'];
+ } else {
+ // strip controller options
+ $sourceSpec = array(
+ 'content' => $options['content'],
+ 'id' => $options['id'],
+ );
+ $f = $options['id'];
+ unset($options['content'], $options['id']);
+ }
+ // something like "builder,index.php" or "directory,file.html"
+ $selectionId = strtr(substr($f, 1 + strlen(dirname(dirname($f)))), '/\\', ',,');
+
+ if (isset($options['minifyAll'])) {
+ // this will be the 2nd argument passed to Minify_HTML::minify()
+ $sourceSpec['minifyOptions'] = array(
+ 'cssMinifier' => array('Minify_CSSmin', 'minify'),
+ 'jsMinifier' => array('JSMin\\JSMin', 'minify'),
+ );
+ unset($options['minifyAll']);
+ }
+
+ $sourceSpec['contentType'] = Minify::TYPE_HTML;
+ $sources[] = new Minify_Source($sourceSpec);
+
+ return new Minify_ServeConfiguration($options, $sources, $selectionId);
+ }
+}
+
diff --git a/admin/survey/minify/lib/Minify/ControllerInterface.php b/admin/survey/minify/lib/Minify/ControllerInterface.php
new file mode 100644
index 0000000..d468635
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/ControllerInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+
+interface Minify_ControllerInterface
+{
+
+ /**
+ * Create controller sources and options for Minify::serve()
+ *
+ * @param array $options controller and Minify options
+ *
+ * @return Minify_ServeConfiguration
+ */
+ public function createConfiguration(array $options);
+
+ /**
+ * Get the Env component
+ *
+ * @return Minify_Env
+ */
+ public function getEnv();
+} \ No newline at end of file
diff --git a/admin/survey/minify/lib/Minify/DebugDetector.php b/admin/survey/minify/lib/Minify/DebugDetector.php
new file mode 100644
index 0000000..2a3c7a7
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/DebugDetector.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Detect whether request should be debugged
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_DebugDetector
+{
+ public static function shouldDebugRequest(Minify_Env $env)
+ {
+ if ($env->get('debug') !== null) {
+ return true;
+ }
+
+ $cookieValue = $env->cookie('minifyDebug');
+ if ($cookieValue) {
+ foreach (preg_split('/\\s+/', $cookieValue) as $debugUri) {
+ $pattern = '@' . preg_quote($debugUri, '@') . '@i';
+ $pattern = str_replace(array('\\*', '\\?'), array('.*', '.'), $pattern);
+ if (preg_match($pattern, $env->getRequestUri())) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Env.php b/admin/survey/minify/lib/Minify/Env.php
new file mode 100644
index 0000000..3bc78f7
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Env.php
@@ -0,0 +1,127 @@
+<?php
+
+class Minify_Env
+{
+
+ /**
+ * @return string
+ */
+ public function getDocRoot()
+ {
+ return $this->server['DOCUMENT_ROOT'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getRequestUri()
+ {
+ return $this->server['REQUEST_URI'];
+ }
+
+ public function __construct($options = array())
+ {
+ $options = array_merge(array(
+ 'server' => $_SERVER,
+ 'get' => $_GET,
+ 'post' => $_POST,
+ 'cookie' => $_COOKIE,
+ ), $options);
+
+ $this->server = $options['server'];
+ if (empty($this->server['DOCUMENT_ROOT'])) {
+ $this->server['DOCUMENT_ROOT'] = $this->computeDocRoot($options['server']);
+ } else {
+ $this->server['DOCUMENT_ROOT'] = rtrim($this->server['DOCUMENT_ROOT'], '/\\');
+ }
+
+ $this->server['DOCUMENT_ROOT'] = $this->normalizePath($this->server['DOCUMENT_ROOT']);
+ $this->get = $options['get'];
+ $this->post = $options['post'];
+ $this->cookie = $options['cookie'];
+ }
+
+ public function server($key = null)
+ {
+ if (null === $key) {
+ return $this->server;
+ }
+
+ return isset($this->server[$key]) ? $this->server[$key] : null;
+ }
+
+ public function cookie($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $this->cookie;
+ }
+
+ return isset($this->cookie[$key]) ? $this->cookie[$key] : $default;
+ }
+
+ public function get($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $this->get;
+ }
+
+ 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;
+ }
+
+ /**
+ * turn windows-style slashes into unix-style,
+ * remove trailing slash
+ * and lowercase drive letter
+ *
+ * @param string $path absolute path
+ *
+ * @return string
+ */
+ public function normalizePath($path)
+ {
+ $realpath = realpath($path);
+ if ($realpath) {
+ $path = $realpath;
+ }
+
+ $path = str_replace('\\', '/', $path);
+ $path = rtrim($path, '/');
+ if (substr($path, 1, 1) === ':') {
+ $path = lcfirst($path);
+ }
+
+ return $path;
+ }
+
+ protected $server;
+ protected $get;
+ protected $post;
+ protected $cookie;
+
+ /**
+ * Compute $_SERVER['DOCUMENT_ROOT'] for IIS using SCRIPT_FILENAME and SCRIPT_NAME.
+ *
+ * @param array $server
+ * @return string
+ */
+ protected function computeDocRoot(array $server)
+ {
+ if (isset($server['SERVER_SOFTWARE']) && 0 !== strpos($server['SERVER_SOFTWARE'], 'Microsoft-IIS/')) {
+ throw new InvalidArgumentException('DOCUMENT_ROOT is not provided and could not be computed');
+ }
+
+ $substrLength = strlen($server['SCRIPT_FILENAME']) - strlen($server['SCRIPT_NAME']);
+ $docRoot = substr($server['SCRIPT_FILENAME'], 0, $substrLength);
+
+ return rtrim($docRoot, '\\');
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/HTML.php b/admin/survey/minify/lib/Minify/HTML.php
new file mode 100644
index 0000000..24b14ac
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/HTML.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * Class Minify_HTML
+ * @package Minify
+ */
+
+/**
+ * Compress HTML
+ *
+ * This is a heavy regex-based removal of whitespace, unnecessary comments and
+ * tokens. IE conditional comments are preserved. There are also options to have
+ * STYLE and SCRIPT blocks compressed by callback functions.
+ *
+ * A test suite is available.
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_HTML
+{
+ /**
+ * @var boolean
+ */
+ protected $_jsCleanComments = true;
+
+ /**
+ * "Minify" an HTML page
+ *
+ * @param string $html
+ *
+ * @param array $options
+ *
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
+ * elements.
+ *
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
+ * elements. Note: the type attribute is ignored.
+ *
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
+ * unset, minify will sniff for an XHTML doctype.
+ *
+ * @return string
+ */
+ public static function minify($html, $options = array())
+ {
+ $min = new self($html, $options);
+
+ return $min->process();
+ }
+
+ /**
+ * Create a minifier object
+ *
+ * @param string $html
+ *
+ * @param array $options
+ *
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
+ * elements.
+ *
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
+ * elements. Note: the type attribute is ignored.
+ *
+ * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block
+ *
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
+ * unset, minify will sniff for an XHTML doctype.
+ */
+ public function __construct($html, $options = array())
+ {
+ $this->_html = str_replace("\r\n", "\n", trim($html));
+ if (isset($options['xhtml'])) {
+ $this->_isXhtml = (bool)$options['xhtml'];
+ }
+ if (isset($options['cssMinifier'])) {
+ $this->_cssMinifier = $options['cssMinifier'];
+ }
+ if (isset($options['jsMinifier'])) {
+ $this->_jsMinifier = $options['jsMinifier'];
+ }
+ if (isset($options['jsCleanComments'])) {
+ $this->_jsCleanComments = (bool)$options['jsCleanComments'];
+ }
+ }
+
+ /**
+ * Minify the markeup given in the constructor
+ *
+ * @return string
+ */
+ public function process()
+ {
+ if ($this->_isXhtml === null) {
+ $this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
+ }
+
+ $this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
+ $this->_placeholders = array();
+
+ // replace SCRIPTs (and minify) with placeholders
+ $this->_html = preg_replace_callback(
+ '/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/iu'
+ ,array($this, '_removeScriptCB')
+ ,$this->_html);
+
+ // replace STYLEs (and minify) with placeholders
+ $this->_html = preg_replace_callback(
+ '/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/iu'
+ ,array($this, '_removeStyleCB')
+ ,$this->_html);
+
+ // remove HTML comments (not containing IE conditional comments).
+ $this->_html = preg_replace_callback(
+ '/<!--([\\s\\S]*?)-->/u'
+ ,array($this, '_commentCB')
+ ,$this->_html);
+
+ // replace PREs with placeholders
+ $this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/iu'
+ ,array($this, '_removePreCB')
+ ,$this->_html);
+
+ // replace TEXTAREAs with placeholders
+ $this->_html = preg_replace_callback(
+ '/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/iu'
+ ,array($this, '_removeTextareaCB')
+ ,$this->_html);
+
+ // trim each line.
+ // @todo take into account attribute values that span multiple lines.
+ $this->_html = preg_replace('/^\\s+|\\s+$/mu', '', $this->_html);
+
+ // remove ws around block/undisplayed elements
+ $this->_html = preg_replace('/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body'
+ .'|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form'
+ .'|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav'
+ .'|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)'
+ .'|ul|video)\\b[^>]*>)/iu', '$1', $this->_html);
+
+ // remove ws outside of all elements
+ $this->_html = preg_replace(
+ '/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?</u'
+ ,'>$1$2$3<'
+ ,$this->_html);
+
+ // use newlines before 1st attribute in open tags (to limit line lengths)
+ $this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/iu', "$1\n$2", $this->_html);
+
+ // fill placeholders
+ $this->_html = str_replace(
+ array_keys($this->_placeholders)
+ ,array_values($this->_placeholders)
+ ,$this->_html
+ );
+ // issue 229: multi-pass to catch scripts that didn't get replaced in textareas
+ $this->_html = str_replace(
+ array_keys($this->_placeholders)
+ ,array_values($this->_placeholders)
+ ,$this->_html
+ );
+
+ return $this->_html;
+ }
+
+ protected function _commentCB($m)
+ {
+ return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
+ ? $m[0]
+ : '';
+ }
+
+ protected function _reservePlace($content)
+ {
+ $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
+ $this->_placeholders[$placeholder] = $content;
+
+ return $placeholder;
+ }
+
+ protected $_isXhtml;
+ protected $_replacementHash;
+ protected $_placeholders = array();
+ protected $_cssMinifier;
+ protected $_jsMinifier;
+
+ protected function _removePreCB($m)
+ {
+ return $this->_reservePlace("<pre{$m[1]}");
+ }
+
+ protected function _removeTextareaCB($m)
+ {
+ return $this->_reservePlace("<textarea{$m[1]}");
+ }
+
+ protected function _removeStyleCB($m)
+ {
+ $openStyle = "<style{$m[1]}";
+ $css = $m[2];
+ // remove HTML comments
+ $css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/u', '', $css);
+
+ // remove CDATA section markers
+ $css = $this->_removeCdata($css);
+
+ // minify
+ $minifier = $this->_cssMinifier
+ ? $this->_cssMinifier
+ : 'trim';
+ $css = call_user_func($minifier, $css);
+
+ return $this->_reservePlace($this->_needsCdata($css)
+ ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
+ : "{$openStyle}{$css}</style>"
+ );
+ }
+
+ protected function _removeScriptCB($m)
+ {
+ $openScript = "<script{$m[2]}";
+ $js = $m[3];
+
+ // whitespace surrounding? preserve at least one space
+ $ws1 = ($m[1] === '') ? '' : ' ';
+ $ws2 = ($m[4] === '') ? '' : ' ';
+
+ // remove HTML comments (and ending "//" if present)
+ if ($this->_jsCleanComments) {
+ $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/u', '', $js);
+ }
+
+ // remove CDATA section markers
+ $js = $this->_removeCdata($js);
+
+ // minify
+ $minifier = $this->_jsMinifier
+ ? $this->_jsMinifier
+ : 'trim';
+ $js = call_user_func($minifier, $js);
+
+ return $this->_reservePlace($this->_needsCdata($js)
+ ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
+ : "{$ws1}{$openScript}{$js}</script>{$ws2}"
+ );
+ }
+
+ protected function _removeCdata($str)
+ {
+ return (false !== strpos($str, '<![CDATA['))
+ ? str_replace(array('<![CDATA[', ']]>'), '', $str)
+ : $str;
+ }
+
+ protected function _needsCdata($str)
+ {
+ return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/u', $str));
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/HTML/Helper.php b/admin/survey/minify/lib/Minify/HTML/Helper.php
new file mode 100644
index 0000000..84ed45e
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/HTML/Helper.php
@@ -0,0 +1,250 @@
+<?php
+/**
+ * Class Minify_HTML_Helper
+ * @package Minify
+ */
+
+/**
+ * Helpers for writing Minify URIs into HTML
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_HTML_Helper
+{
+ public $rewriteWorks = true;
+ public $minAppUri = '/min';
+ public $groupsConfigFile = '';
+
+ /**
+ * Get an HTML-escaped Minify URI for a group or set of files
+ *
+ * @param string|array $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' => 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 {
+ $h->setGroup($keyOrFiles, $opts['farExpires']);
+ }
+ $uri = $h->getRawUri($opts['farExpires'], $opts['debug']);
+
+ return htmlspecialchars($uri, ENT_QUOTES, $opts['charset']);
+ }
+
+ /**
+ * Get non-HTML-escaped URI to minify the specified files
+ *
+ * @param bool $farExpires
+ * @param bool $debug
+ * @return string
+ */
+ public function getRawUri($farExpires = true, $debug = false)
+ {
+ $path = rtrim($this->minAppUri, '/') . '/';
+ if (! $this->rewriteWorks) {
+ $path .= '?';
+ }
+ if (null === $this->_groupKey) {
+ // @todo: implement shortest uri
+ $path = self::_getShortestUri($this->_filePaths, $path);
+ } else {
+ $path .= "g=" . $this->_groupKey;
+ }
+ if ($debug) {
+ $path .= "&debug";
+ } elseif ($farExpires && $this->_lastModified) {
+ $path .= "&" . $this->_lastModified;
+ }
+
+ return $path;
+ }
+
+ /**
+ * Set the files that will comprise the URI we're building
+ *
+ * @param array $files
+ * @param bool $checkLastModified
+ */
+ public function setFiles($files, $checkLastModified = true)
+ {
+ $this->_groupKey = null;
+ if ($checkLastModified) {
+ $this->_lastModified = self::getLastModified($files);
+ }
+ // normalize paths like in /min/f=<paths>
+ foreach ($files as $k => $file) {
+ if (0 === strpos($file, '//')) {
+ $file = substr($file, 2);
+ } elseif (0 === strpos($file, '/') || 1 === strpos($file, ':\\')) {
+ $file = substr($file, strlen(self::app()->env->getDocRoot()) + 1);
+ }
+ $file = strtr($file, '\\', '/');
+ $files[$k] = $file;
+ }
+ $this->_filePaths = $files;
+ }
+
+ /**
+ * Set the group of files that will comprise the URI we're building
+ *
+ * @param string $key
+ * @param bool $checkLastModified
+ */
+ public function setGroup($key, $checkLastModified = true)
+ {
+ $this->_groupKey = $key;
+ if ($checkLastModified) {
+ if (! $this->groupsConfigFile) {
+ $this->groupsConfigFile = self::app()->groupsConfigPath;
+ }
+ if (is_file($this->groupsConfigFile)) {
+ $gc = (require $this->groupsConfigFile);
+ $keys = explode(',', $key);
+ foreach ($keys as $key) {
+ if (!isset($gc[$key])) {
+ // this can happen if value is null
+ // which could be solved with array_filter
+ continue;
+ }
+
+ $this->_lastModified = self::getLastModified($gc[$key], $this->_lastModified);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the max(lastModified) of all files
+ *
+ * @param array|string $sources
+ * @param int $lastModified
+ * @return int
+ */
+ public static function getLastModified($sources, $lastModified = 0)
+ {
+ $max = $lastModified;
+ $factory = self::app()->sourceFactory;
+
+ /** @var Minify_Source $source */
+ foreach ((array)$sources as $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;
+
+ /**
+ * In a given array of strings, find the character they all have at
+ * a particular index
+ *
+ * @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)
+ {
+ if (!isset($arr[0][$pos])) {
+ return '';
+ }
+ $c = $arr[0][$pos];
+ $l = count($arr);
+ if ($l === 1) {
+ return $c;
+ }
+ for ($i = 1; $i < $l; ++$i) {
+ if ($arr[$i][$pos] !== $c) {
+ return '';
+ }
+ }
+
+ return $c;
+ }
+
+ /**
+ * Get the shortest URI to minify the set of source files
+ *
+ * @param array $paths root-relative URIs of files
+ * @param string $minRoot root-relative URI of the "min" application
+ * @return string
+ */
+ protected static function _getShortestUri($paths, $minRoot = '/min/')
+ {
+ $pos = 0;
+ $base = '';
+ while (true) {
+ $c = self::_getCommonCharAtPos($paths, $pos);
+ if ($c === '') {
+ break;
+ } else {
+ $base .= $c;
+ }
+ ++$pos;
+ }
+ $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;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/ImportProcessor.php b/admin/survey/minify/lib/Minify/ImportProcessor.php
new file mode 100644
index 0000000..0f8c981
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/ImportProcessor.php
@@ -0,0 +1,217 @@
+<?php
+/**
+ * Class Minify_ImportProcessor
+ * @package Minify
+ */
+
+/**
+ * Linearize a CSS/JS file by including content specified by CSS import
+ * declarations. In CSS files, relative URIs are fixed.
+ *
+ * @imports will be processed regardless of where they appear in the source
+ * files; i.e. @imports commented out or in string content will still be
+ * processed!
+ *
+ * This has a unit test but should be considered "experimental".
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ * @author Simon Schick <simonsimcity@gmail.com>
+ */
+class Minify_ImportProcessor
+{
+ public static $filesIncluded = array();
+
+ public static function process($file)
+ {
+ self::$filesIncluded = array();
+ self::$_isCss = (strtolower(substr($file, -4)) === '.css');
+ $obj = new Minify_ImportProcessor(dirname($file));
+
+ return $obj->_getContent($file);
+ }
+
+ // allows callback funcs to know the current directory
+ private $_currentDir;
+
+ // allows callback funcs to know the directory of the file that inherits this one
+ private $_previewsDir;
+
+ // allows _importCB to write the fetched content back to the obj
+ private $_importedContent = '';
+
+ private static $_isCss;
+
+ /**
+ * @param String $currentDir
+ * @param String $previewsDir Is only used internally
+ */
+ private function __construct($currentDir, $previewsDir = "")
+ {
+ $this->_currentDir = $currentDir;
+ $this->_previewsDir = $previewsDir;
+ }
+
+ private function _getContent($file, $is_imported = false)
+ {
+ $file = preg_replace('~\\?.*~', '', $file);
+ $file = realpath($file);
+ if (! $file
+ || in_array($file, self::$filesIncluded)
+ || false === ($content = @file_get_contents($file))) {
+ // file missing, already included, or failed read
+ return '';
+ }
+ self::$filesIncluded[] = realpath($file);
+ $this->_currentDir = dirname($file);
+
+ // remove UTF-8 BOM if present
+ if (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) {
+ $content = substr($content, 3);
+ }
+ // ensure uniform EOLs
+ $content = str_replace("\r\n", "\n", $content);
+
+ // process @imports
+ $pattern = '/
+ @import\\s+
+ (?:url\\(\\s*)? # maybe url(
+ [\'"]? # maybe quote
+ (.*?) # 1 = URI
+ [\'"]? # maybe end quote
+ (?:\\s*\\))? # maybe )
+ ([a-zA-Z,\\s]*)? # 2 = media list
+ ; # end token
+ /x';
+ $content = preg_replace_callback($pattern, array($this, '_importCB'), $content);
+
+ // You only need to rework the import-path if the script is imported
+ if (self::$_isCss && $is_imported) {
+ // rewrite remaining relative URIs
+ $pattern = '/url\\(\\s*([^\\)\\s]+)\\s*\\)/';
+ $content = preg_replace_callback($pattern, array($this, '_urlCB'), $content);
+ }
+
+ return $this->_importedContent . $content;
+ }
+
+ private function _importCB($m)
+ {
+ $url = $m[1];
+ $mediaList = preg_replace('/\\s+/', '', $m[2]);
+
+ if (strpos($url, '://') > 0) {
+ // protocol, leave in place for CSS, comment for JS
+ return self::$_isCss
+ ? $m[0]
+ : "/* Minify_ImportProcessor will not include remote content */";
+ }
+ if ('/' === $url[0]) {
+ // protocol-relative or root path
+ $url = ltrim($url, '/');
+ $file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR
+ . strtr($url, '/', DIRECTORY_SEPARATOR);
+ } else {
+ // relative to current path
+ $file = $this->_currentDir . DIRECTORY_SEPARATOR
+ . strtr($url, '/', DIRECTORY_SEPARATOR);
+ }
+ $obj = new Minify_ImportProcessor(dirname($file), $this->_currentDir);
+ $content = $obj->_getContent($file, true);
+ if ('' === $content) {
+ // failed. leave in place for CSS, comment for JS
+ return self::$_isCss
+ ? $m[0]
+ : "/* Minify_ImportProcessor could not fetch '{$file}' */";
+ }
+
+ return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList))
+ ? $content
+ : "@media {$mediaList} {\n{$content}\n}\n";
+ }
+
+ private function _urlCB($m)
+ {
+ // $m[1] is either quoted or not
+ $quote = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : '';
+
+ $url = ($quote === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2);
+
+ if ('/' !== $url[0]) {
+ if (strpos($url, '//') > 0) {
+ // probably starts with protocol, do not alter
+ } else {
+ // prepend path with current dir separator (OS-independent)
+ $path = $this->_currentDir
+ . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
+ // update the relative path by the directory of the file that imported this one
+ $url = self::getPathDiff(realpath($this->_previewsDir), $path);
+ }
+ }
+
+ return "url({$quote}{$url}{$quote})";
+ }
+
+ /**
+ * @param string $from
+ * @param string $to
+ * @param string $ps
+ * @return string
+ */
+ private function getPathDiff($from, $to, $ps = DIRECTORY_SEPARATOR)
+ {
+ $realFrom = $this->truepath($from);
+ $realTo = $this->truepath($to);
+
+ $arFrom = explode($ps, rtrim($realFrom, $ps));
+ $arTo = explode($ps, rtrim($realTo, $ps));
+ while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) {
+ array_shift($arFrom);
+ array_shift($arTo);
+ }
+
+ return str_pad("", count($arFrom) * 3, '..' . $ps) . implode($ps, $arTo);
+ }
+
+ /**
+ * This function is to replace PHP's extremely buggy realpath().
+ * @param string $path The original path, can be relative etc.
+ * @return string The resolved path, it might not exist.
+ * @see http://stackoverflow.com/questions/4049856/replace-phps-realpath
+ */
+ private function truepath($path)
+ {
+ // whether $path is unix or not
+ $unipath = ('' === $path) || ($path{0} !== '/');
+
+ // attempts to detect if path is relative in which case, add cwd
+ if (strpos($path, ':') === false && $unipath) {
+ $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path;
+ }
+
+ // resolve path parts (single dot, double dot and double delimiters)
+ $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
+ $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
+ $absolutes = array();
+ foreach ($parts as $part) {
+ if ('.' === $part) {
+ continue;
+ }
+ if ('..' === $part) {
+ array_pop($absolutes);
+ } else {
+ $absolutes[] = $part;
+ }
+ }
+
+ $path = implode(DIRECTORY_SEPARATOR, $absolutes);
+ // resolve any symlinks
+ if (file_exists($path) && linkinfo($path) > 0) {
+ $path = readlink($path);
+ }
+ // put initial separator that could have been lost
+ $path = !$unipath ? '/' . $path : $path;
+
+ return $path;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/JS/ClosureCompiler.php b/admin/survey/minify/lib/Minify/JS/ClosureCompiler.php
new file mode 100644
index 0000000..05e2e33
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/JS/ClosureCompiler.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * Class Minify_JS_ClosureCompiler
+ * @package Minify
+ */
+
+/**
+ * Minify Javascript using Google's Closure Compiler API
+ *
+ * @link http://code.google.com/closure/compiler/
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ *
+ * @todo can use a stream wrapper to unit test this?
+ */
+class Minify_JS_ClosureCompiler
+{
+
+ /**
+ * @var string The option key for the maximum POST byte size
+ */
+ const OPTION_MAX_BYTES = 'maxBytes';
+
+ /**
+ * @var string The option key for additional params. @see __construct
+ */
+ const OPTION_ADDITIONAL_OPTIONS = 'additionalParams';
+
+ /**
+ * @var string The option key for the fallback Minifier
+ */
+ const OPTION_FALLBACK_FUNCTION = 'fallbackFunc';
+
+ /**
+ * @var string The option key for the service URL
+ */
+ const OPTION_COMPILER_URL = 'compilerUrl';
+
+ /**
+ * @var int The default maximum POST byte size according to https://developers.google.com/closure/compiler/docs/api-ref
+ */
+ const DEFAULT_MAX_BYTES = 200000;
+
+ /**
+ * @var string[] $DEFAULT_OPTIONS The default options to pass to the compiler service
+ *
+ * @note This would be a constant if PHP allowed it
+ */
+ private static $DEFAULT_OPTIONS = array(
+ 'output_format' => 'text',
+ 'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
+ );
+
+ /**
+ * @var string $url URL of compiler server. defaults to Google's
+ */
+ protected $serviceUrl = 'https://closure-compiler.appspot.com/compile';
+
+ /**
+ * @var int $maxBytes The maximum JS size that can be sent to the compiler server in bytes
+ */
+ protected $maxBytes = self::DEFAULT_MAX_BYTES;
+
+ /**
+ * @var string[] $additionalOptions Additional options to pass to the compiler service
+ */
+ protected $additionalOptions = array();
+
+ /**
+ * @var callable Function to minify JS if service fails. Default is JSMin
+ */
+ protected $fallbackMinifier = array('JSMin\\JSMin', 'minify');
+
+ /**
+ * Minify JavaScript code via HTTP request to a Closure Compiler API
+ *
+ * @param string $js input code
+ * @param array $options Options passed to __construct(). @see __construct
+ *
+ * @return string
+ */
+ public static function minify($js, array $options = array())
+ {
+ $obj = new self($options);
+
+ return $obj->min($js);
+ }
+
+ /**
+ * @param array $options Options with keys available below:
+ *
+ * fallbackFunc : (callable) function to minify if service unavailable. Default is JSMin.
+ *
+ * compilerUrl : (string) URL to closure compiler server
+ *
+ * maxBytes : (int) The maximum amount of bytes to be sent as js_code in the POST request.
+ * Defaults to 200000.
+ *
+ * additionalParams : (string[]) Additional parameters to pass to the compiler server. Can be anything named
+ * in https://developers.google.com/closure/compiler/docs/api-ref except for js_code and
+ * output_info
+ */
+ public function __construct(array $options = array())
+ {
+ if (isset($options[self::OPTION_FALLBACK_FUNCTION])) {
+ $this->fallbackMinifier = $options[self::OPTION_FALLBACK_FUNCTION];
+ }
+ if (isset($options[self::OPTION_COMPILER_URL])) {
+ $this->serviceUrl = $options[self::OPTION_COMPILER_URL];
+ }
+ if (isset($options[self::OPTION_ADDITIONAL_OPTIONS]) && is_array($options[self::OPTION_ADDITIONAL_OPTIONS])) {
+ $this->additionalOptions = $options[self::OPTION_ADDITIONAL_OPTIONS];
+ }
+ if (isset($options[self::OPTION_MAX_BYTES])) {
+ $this->maxBytes = (int) $options[self::OPTION_MAX_BYTES];
+ }
+ }
+
+ /**
+ * Call the service to perform the minification
+ *
+ * @param string $js JavaScript code
+ * @return string
+ * @throws Minify_JS_ClosureCompiler_Exception
+ */
+ public function min($js)
+ {
+ $postBody = $this->buildPostBody($js);
+
+ if ($this->maxBytes > 0) {
+ $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
+ ? mb_strlen($postBody, '8bit')
+ : strlen($postBody);
+ if ($bytes > $this->maxBytes) {
+ throw new Minify_JS_ClosureCompiler_Exception(
+ 'POST content larger than ' . $this->maxBytes . ' bytes'
+ );
+ }
+ }
+
+ $response = $this->getResponse($postBody);
+
+ if (preg_match('/^Error\(\d\d?\):/', $response)) {
+ if (is_callable($this->fallbackMinifier)) {
+ // use fallback
+ $response = "/* Received errors from Closure Compiler API:\n$response"
+ . "\n(Using fallback minifier)\n*/\n";
+ $response .= call_user_func($this->fallbackMinifier, $js);
+ } else {
+ throw new Minify_JS_ClosureCompiler_Exception($response);
+ }
+ }
+
+ if ($response === '') {
+ $errors = $this->getResponse($this->buildPostBody($js, true));
+ throw new Minify_JS_ClosureCompiler_Exception($errors);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Get the response for a given POST body
+ *
+ * @param string $postBody
+ * @return string
+ * @throws Minify_JS_ClosureCompiler_Exception
+ */
+ protected function getResponse($postBody)
+ {
+ $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
+
+ if ($allowUrlFopen) {
+ $contents = file_get_contents($this->serviceUrl, false, stream_context_create(array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'compilation_level' => 'SIMPLE',
+ 'output_format' => 'text',
+ 'output_info' => 'compiled_code',
+ 'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n",
+ 'content' => $postBody,
+ 'max_redirects' => 0,
+ 'timeout' => 15,
+ )
+ )));
+ } elseif (defined('CURLOPT_POST')) {
+ $ch = curl_init($this->serviceUrl);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
+ $contents = curl_exec($ch);
+ curl_close($ch);
+ } else {
+ throw new Minify_JS_ClosureCompiler_Exception(
+ "Could not make HTTP request: allow_url_open is false and cURL not available"
+ );
+ }
+
+ if (false === $contents) {
+ throw new Minify_JS_ClosureCompiler_Exception(
+ "No HTTP response from server"
+ );
+ }
+
+ return trim($contents);
+ }
+
+ /**
+ * Build a POST request body
+ *
+ * @param string $js JavaScript code
+ * @param bool $returnErrors
+ * @return string
+ */
+ protected function buildPostBody($js, $returnErrors = false)
+ {
+ return http_build_query(
+ array_merge(
+ self::$DEFAULT_OPTIONS,
+ $this->additionalOptions,
+ array(
+ 'js_code' => $js,
+ 'output_info' => ($returnErrors ? 'errors' : 'compiled_code')
+ )
+ ),
+ null,
+ '&'
+ );
+ }
+}
+
+class Minify_JS_ClosureCompiler_Exception extends Exception
+{
+}
diff --git a/admin/survey/minify/lib/Minify/JS/JShrink.php b/admin/survey/minify/lib/Minify/JS/JShrink.php
new file mode 100644
index 0000000..5eb5042
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/JS/JShrink.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Class Minify\JS\JShrink
+ *
+ * @package Minify
+ */
+
+namespace Minify\JS;
+
+/**
+ * Wrapper to Javascript Minifier built in PHP http://www.tedivm.com
+ *
+ * @package Minify
+ * @author Elan Ruusamäe <glen@pld-linux.org>
+ * @link https://github.com/tedious/JShrink
+ *
+ */
+class JShrink
+{
+ /**
+ * Contains the default options for minification. This array is merged with
+ * the one passed in by the user to create the request specific set of
+ * options (stored in the $options attribute).
+ *
+ * @var string[]
+ */
+ protected static $defaultOptions = array('flaggedComments' => true);
+
+ /**
+ * Takes a string containing javascript and removes unneeded characters in
+ * order to shrink the code without altering it's functionality.
+ *
+ * @param string $js The raw javascript to be minified
+ * @param array $options Various runtime options in an associative array
+ *
+ * @see JShrink\Minifier::minify()
+ * @return string
+ */
+ public static function minify($js, array $options = array())
+ {
+ $options = array_merge(
+ self::$defaultOptions,
+ $options
+ );
+
+ return \JShrink\Minifier::minify($js, $options);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/LessCssSource.php b/admin/survey/minify/lib/Minify/LessCssSource.php
new file mode 100644
index 0000000..389932c
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/LessCssSource.php
@@ -0,0 +1,128 @@
+<?php
+
+class Minify_LessCssSource extends Minify_Source
+{
+ /**
+ * @var Minify_CacheInterface
+ */
+ private $cache;
+
+ /**
+ * Parsed lessphp cache object
+ *
+ * @var array
+ */
+ private $parsed;
+
+ /**
+ * @inheritdoc
+ */
+ public function __construct(array $spec, Minify_CacheInterface $cache)
+ {
+ parent::__construct($spec);
+
+ $this->cache = $cache;
+ }
+
+ /**
+ * Get last modified of all parsed files
+ *
+ * @return int
+ */
+ public function getLastModified()
+ {
+ $cache = $this->getCache();
+
+ return $cache['lastModified'];
+ }
+
+ /**
+ * Get content
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ $cache = $this->getCache();
+
+ return $cache['compiled'];
+ }
+
+ /**
+ * Get lessphp cache object
+ *
+ * @return array
+ */
+ private function getCache()
+ {
+ // cache for single run
+ // so that getLastModified and getContent in single request do not add additional cache roundtrips (i.e memcache)
+ if (isset($this->parsed)) {
+ return $this->parsed;
+ }
+
+ // check from cache first
+ $cache = null;
+ $cacheId = $this->getCacheId();
+ if ($this->cache->isValid($cacheId, 0)) {
+ if ($cache = $this->cache->fetch($cacheId)) {
+ $cache = unserialize($cache);
+ }
+ }
+
+ $less = $this->getCompiler();
+ $input = $cache ? $cache : $this->filepath;
+ $cache = $less->cachedCompile($input);
+
+ if (!is_array($input) || $cache['updated'] > $input['updated']) {
+ $cache['lastModified'] = $this->getMaxLastModified($cache);
+ $this->cache->store($cacheId, serialize($cache));
+ }
+
+ return $this->parsed = $cache;
+ }
+
+ /**
+ * Calculate maximum last modified of all files,
+ * as the 'updated' timestamp in cache is not the same as file last modified timestamp:
+ * @link https://github.com/leafo/lessphp/blob/v0.4.0/lessc.inc.php#L1904
+ * @return int
+ */
+ private function getMaxLastModified($cache)
+ {
+ $lastModified = 0;
+ foreach ($cache['files'] as $mtime) {
+ $lastModified = max($lastModified, $mtime);
+ }
+
+ return $lastModified;
+ }
+
+ /**
+ * Make a unique cache id for for this source.
+ *
+ * @param string $prefix
+ *
+ * @return string
+ */
+ private function getCacheId($prefix = 'minify')
+ {
+ $md5 = md5($this->filepath);
+
+ return "{$prefix}_less2_{$md5}";
+ }
+
+ /**
+ * Get instance of less compiler
+ *
+ * @return lessc
+ */
+ private function getCompiler()
+ {
+ $less = new lessc();
+ // do not spend CPU time letting less doing minify
+ $less->setPreserveComments(true);
+
+ return $less;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Lines.php b/admin/survey/minify/lib/Minify/Lines.php
new file mode 100644
index 0000000..60bf3b4
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Lines.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Class Minify_Lines
+ * @package Minify
+ */
+
+/**
+ * Add line numbers in C-style comments for easier debugging of combined content
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ * @author Adam Pedersen (Issue 55 fix)
+ */
+class Minify_Lines
+{
+
+ /**
+ * Add line numbers in C-style comments
+ *
+ * This uses a very basic parser easily fooled by comment tokens inside
+ * strings or regexes, but, otherwise, generally clean code will not be
+ * mangled. URI rewriting can also be performed.
+ *
+ * @param string $content
+ *
+ * @param array $options available options:
+ *
+ * 'id': (optional) string to identify file. E.g. file name/path
+ *
+ * 'currentDir': (default null) if given, this is assumed to be the
+ * directory of the current CSS file. Using this, minify will rewrite
+ * all relative URIs in import/url declarations to correctly point to
+ * the desired files, and prepend a comment with debugging information about
+ * this process.
+ *
+ * @return string
+ */
+ public static function minify($content, $options = array())
+ {
+ $id = (isset($options['id']) && $options['id']) ? $options['id'] : '';
+ $content = str_replace("\r\n", "\n", $content);
+
+ $lines = explode("\n", $content);
+ $numLines = count($lines);
+ // determine left padding
+ $padTo = strlen((string) $numLines); // e.g. 103 lines = 3 digits
+ $inComment = false;
+ $i = 0;
+ $newLines = array();
+
+ while (null !== ($line = array_shift($lines))) {
+ if (('' !== $id) && (0 === $i % 50)) {
+ if ($inComment) {
+ array_push($newLines, '', "/* {$id} *|", '');
+ } else {
+ array_push($newLines, '', "/* {$id} */", '');
+ }
+ }
+
+ ++$i;
+ $newLines[] = self::_addNote($line, $i, $inComment, $padTo);
+ $inComment = self::_eolInComment($line, $inComment);
+ }
+
+ $content = implode("\n", $newLines) . "\n";
+
+ // check for desired URI rewriting
+ if (isset($options['currentDir'])) {
+ Minify_CSS_UriRewriter::$debugText = '';
+ $docRoot = isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT'];
+ $symlinks = isset($options['symlinks']) ? $options['symlinks'] : array();
+
+ $content = Minify_CSS_UriRewriter::rewrite($content, $options['currentDir'], $docRoot, $symlinks);
+
+ $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
+ . Minify_CSS_UriRewriter::$debugText . "*/\n"
+ . $content;
+ }
+
+ return $content;
+ }
+
+ /**
+ * Is the parser within a C-style comment at the end of this line?
+ *
+ * @param string $line current line of code
+ *
+ * @param bool $inComment was the parser in a C-style comment at the
+ * beginning of the previous line?
+ *
+ * @return bool
+ */
+ private static function _eolInComment($line, $inComment)
+ {
+ while (strlen($line)) {
+ if ($inComment) {
+ // only "*/" can end the comment
+ $index = self::_find($line, '*/');
+ if ($index === false) {
+ return true;
+ }
+
+ // stop comment and keep walking line
+ $inComment = false;
+ @$line = (string)substr($line, $index + 2);
+ continue;
+ }
+
+ // look for "//" and "/*"
+ $single = self::_find($line, '//');
+ $multi = self::_find($line, '/*');
+ if ($multi === false) {
+ return false;
+ }
+
+ if ($single === false || $multi < $single) {
+ // start comment and keep walking line
+ $inComment = true;
+ @$line = (string)substr($line, $multi + 2);
+ continue;
+ }
+
+ // a single-line comment preceeded it
+ return false;
+ }
+
+ return $inComment;
+ }
+
+ /**
+ * Prepend a comment (or note) to the given line
+ *
+ * @param string $line current line of code
+ *
+ * @param string $note content of note/comment
+ *
+ * @param bool $inComment was the parser in a comment at the
+ * beginning of the line?
+ *
+ * @param int $padTo minimum width of comment
+ *
+ * @return string
+ */
+ private static function _addNote($line, $note, $inComment, $padTo)
+ {
+ if ($inComment) {
+ $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line;
+ } else {
+ $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line;
+ }
+
+ return rtrim($line);
+ }
+
+ /**
+ * Find a token trying to avoid false positives
+ *
+ * @param string $str String containing the token
+ * @param string $token Token being checked
+ * @return bool
+ */
+ private static function _find($str, $token)
+ {
+ switch ($token) {
+ case '//':
+ $fakes = array(
+ '://' => 1,
+ '"//' => 1,
+ '\'//' => 1,
+ '".//' => 2,
+ '\'.//' => 2,
+ );
+ break;
+ case '/*':
+ $fakes = array(
+ '"/*' => 1,
+ '\'/*' => 1,
+ '"//*' => 2,
+ '\'//*' => 2,
+ '".//*' => 3,
+ '\'.//*' => 3,
+ '*/*' => 1,
+ '\\/*' => 1,
+ );
+ break;
+ default:
+ $fakes = array();
+ }
+
+ $index = strpos($str, $token);
+ $offset = 0;
+
+ while ($index !== false) {
+ foreach ($fakes as $fake => $skip) {
+ $check = substr($str, $index - $skip, strlen($fake));
+ if ($check === $fake) {
+ // move offset and scan again
+ $offset += $index + strlen($token);
+ $index = strpos($str, $token, $offset);
+ break;
+ }
+ }
+ // legitimate find
+ return $index;
+ }
+
+ return $index;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Logger/LegacyHandler.php b/admin/survey/minify/lib/Minify/Logger/LegacyHandler.php
new file mode 100644
index 0000000..fe4800f
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Logger/LegacyHandler.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Minify\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']);
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/NailgunClosureCompiler.php b/admin/survey/minify/lib/Minify/NailgunClosureCompiler.php
new file mode 100644
index 0000000..683e30f
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/NailgunClosureCompiler.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * Class Minify_ClosureCompiler
+ * @package Minify
+ */
+
+/**
+ * Run Closure Compiler via NailGun
+ *
+ * @package Minify
+ * @author Elan Ruusamäe <glen@delfi.ee>
+ * @link https://github.com/martylamb/nailgun
+ */
+class Minify_NailgunClosureCompiler extends Minify_ClosureCompiler
+{
+ const NG_SERVER = 'com.martiansoftware.nailgun.NGServer';
+ const CC_MAIN = 'com.google.javascript.jscomp.CommandLineRunner';
+
+ /**
+ * For some reasons Nailgun thinks that it's server
+ * broke the connection and returns 227 instead of 0
+ * We'll just handle this here instead of fixing
+ * the nailgun client itself.
+ *
+ * It also sometimes breaks on 229 on the devbox.
+ * To complete this whole madness and made future
+ * 'fixes' easier I added this nice little array...
+ * @var array
+ */
+ private static $NG_EXIT_CODES = array(0, 227, 229);
+
+ /**
+ * Filepath of "ng" executable (from Nailgun package)
+ *
+ * @var string
+ */
+ public static $ngExecutable = 'ng';
+
+ /**
+ * Filepath of the Nailgun jar file.
+ *
+ * @var string
+ */
+ public static $ngJarFile;
+
+ /**
+ * Get command to launch NailGun server.
+ *
+ * @return array
+ */
+ protected function getServerCommandLine()
+ {
+ $this->checkJar(self::$ngJarFile);
+ $this->checkJar(self::$jarFile);
+
+ $classPath = array(
+ self::$ngJarFile,
+ self::$jarFile,
+ );
+
+ // The command for the server that should show up in the process list
+ $server = array(
+ self::$javaExecutable,
+ '-server',
+ '-cp', implode(':', $classPath),
+ self::NG_SERVER,
+ );
+
+ return $server;
+ }
+
+ /**
+ * @return array
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function getCompilerCommandLine()
+ {
+ $server = array(
+ self::$ngExecutable,
+ escapeshellarg(self::CC_MAIN)
+ );
+
+ return $server;
+ }
+
+ /**
+ * @param string $tmpFile
+ * @param array $options
+ * @return string
+ * @throws Minify_ClosureCompiler_Exception
+ */
+ protected function compile($tmpFile, $options)
+ {
+ $this->startServer();
+
+ $command = $this->getCommand($options, $tmpFile);
+
+ return implode("\n", $this->shell($command, self::$NG_EXIT_CODES));
+ }
+
+ private function startServer()
+ {
+ $serverCommand = implode(' ', $this->getServerCommandLine());
+ $psCommand = $this->shell("ps -o cmd= -C " . self::$javaExecutable);
+ if (in_array($serverCommand, $psCommand, true)) {
+ // already started!
+ return;
+ }
+
+ $this->shell("$serverCommand </dev/null >/dev/null 2>/dev/null & sleep 10");
+ }
+} \ No newline at end of file
diff --git a/admin/survey/minify/lib/Minify/Packer.php b/admin/survey/minify/lib/Minify/Packer.php
new file mode 100644
index 0000000..53e9a9b
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Packer.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Class Minify_Packer
+ *
+ * To use this class you must first download the PHP port of Packer
+ * and place the file "class.JavaScriptPacker.php" in /lib (or your
+ * include_path).
+ * @link http://joliclic.free.fr/php/javascript-packer/en/
+ *
+ * Be aware that, as long as HTTP encoding is used, scripts minified with JSMin
+ * will provide better client-side performance, as they need not be unpacked in
+ * client-side code.
+ *
+ * @package Minify
+ */
+
+/**
+ * Minify Javascript using Dean Edward's Packer
+ *
+ * @package Minify
+ */
+class Minify_Packer
+{
+ public static function minify($code, $options = array())
+ {
+ // @todo: set encoding options based on $options :)
+ $packer = new JavascriptPacker($code, 'Normal', true, false);
+
+ return trim($packer->pack());
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/ScssCssSource.php b/admin/survey/minify/lib/Minify/ScssCssSource.php
new file mode 100644
index 0000000..ebccbe8
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/ScssCssSource.php
@@ -0,0 +1,176 @@
+<?php
+use Leafo\ScssPhp\Compiler;
+use Leafo\ScssPhp\Server;
+use Leafo\ScssPhp\Version;
+
+/**
+ * Class for using SCSS files
+ *
+ * @link https://github.com/leafo/scssphp/
+ */
+class Minify_ScssCssSource extends Minify_Source
+{
+ /**
+ * @var Minify_CacheInterface
+ */
+ private $cache;
+
+ /**
+ * Parsed SCSS cache object
+ *
+ * @var array
+ */
+ private $parsed;
+
+ /**
+ * @inheritdoc
+ */
+ public function __construct(array $spec, Minify_CacheInterface $cache)
+ {
+ parent::__construct($spec);
+
+ $this->cache = $cache;
+ }
+
+ /**
+ * Get last modified of all parsed files
+ *
+ * @return int
+ */
+ public function getLastModified()
+ {
+ $cache = $this->getCache();
+
+ return $cache['updated'];
+ }
+
+ /**
+ * Get content
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ $cache = $this->getCache();
+
+ return $cache['content'];
+ }
+
+ /**
+ * Make a unique cache id for for this source.
+ *
+ * @param string $prefix
+ *
+ * @return string
+ */
+ private function getCacheId($prefix = 'minify')
+ {
+ $md5 = md5($this->filepath);
+
+ return "{$prefix}_scss_{$md5}";
+ }
+
+ /**
+ * Get SCSS cache object
+ *
+ * Runs the compilation if needed
+ *
+ * Implements Leafo\ScssPhp\Server logic because we need to get parsed files without parsing actual content
+ *
+ * @return array
+ */
+ private function getCache()
+ {
+ // cache for single run
+ // so that getLastModified and getContent in single request do not add additional cache roundtrips (i.e memcache)
+ if (isset($this->parsed)) {
+ return $this->parsed;
+ }
+
+ // check from cache first
+ $cache = null;
+ $cacheId = $this->getCacheId();
+ if ($this->cache->isValid($cacheId, 0)) {
+ if ($cache = $this->cache->fetch($cacheId)) {
+ $cache = unserialize($cache);
+ }
+ }
+
+ $input = $cache ? $cache : $this->filepath;
+
+ if ($this->cacheIsStale($cache)) {
+ $cache = $this->compile($this->filepath);
+ }
+
+ if (!is_array($input) || $cache['updated'] > $input['updated']) {
+ $this->cache->store($cacheId, serialize($cache));
+ }
+
+ return $this->parsed = $cache;
+ }
+
+ /**
+ * Determine whether .scss file needs to be re-compiled.
+ *
+ * @param array $cache Cache object
+ *
+ * @return boolean True if compile required.
+ */
+ private function cacheIsStale($cache)
+ {
+ if (!$cache) {
+ return true;
+ }
+
+ $updated = $cache['updated'];
+ foreach ($cache['files'] as $import => $mtime) {
+ $filemtime = filemtime($import);
+
+ if ($filemtime !== $mtime || $filemtime > $updated) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Compile .scss file
+ *
+ * @param string $filename Input path (.scss)
+ *
+ * @see Server::compile()
+ * @return array meta data result of the compile
+ */
+ private function compile($filename)
+ {
+ $start = microtime(true);
+ $scss = new Compiler();
+
+ // set import path directory the input filename resides
+ // otherwise @import statements will not find the files
+ // and will treat the @import line as css import
+ $scss->setImportPaths(dirname($filename));
+
+ $css = $scss->compile(file_get_contents($filename), $filename);
+ $elapsed = round((microtime(true) - $start), 4);
+
+ $v = Version::VERSION;
+ $ts = date('r', $start);
+ $css = "/* compiled by scssphp $v on $ts (${elapsed}s) */\n\n" . $css;
+
+ $imports = $scss->getParsedFiles();
+
+ $updated = 0;
+ foreach ($imports as $mtime) {
+ $updated = max($updated, $mtime);
+ }
+
+ return array(
+ 'elapsed' => $elapsed, // statistic, can be dropped
+ 'updated' => $updated,
+ 'content' => $css,
+ 'files' => $imports,
+ );
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/ServeConfiguration.php b/admin/survey/minify/lib/Minify/ServeConfiguration.php
new file mode 100644
index 0000000..1c30708
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/ServeConfiguration.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Class Minify_ServeConfiguration
+ * @package Minify
+ */
+
+/**
+ * A configuration for Minify::serve() determined by a controller
+ *
+ * @package Minify
+ */
+class Minify_ServeConfiguration
+{
+
+ /**
+ * @var Minify_SourceInterface[]
+ */
+ protected $sources;
+
+ /**
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * @var string
+ */
+ protected $selectionId = '';
+
+ /**
+ * @param array $options
+ * @param Minify_SourceInterface[] $sources
+ * @param string $selectionId
+ */
+ public function __construct(array $options, array $sources = array(), $selectionId = '')
+ {
+ $this->options = $options;
+ $this->sources = $sources;
+ $this->selectionId = $selectionId;
+ }
+
+ /**
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * @return Minify_SourceInterface[]
+ */
+ public function getSources()
+ {
+ return $this->sources;
+ }
+
+ /**
+ * Short name to place inside cache id
+ *
+ * The setupSources() method may choose to set this, making it easier to
+ * recognize a particular set of sources/settings in the cache folder. It
+ * will be filtered and truncated to make the final cache id <= 250 bytes.
+ *
+ * @return string
+ */
+ public function getSelectionId()
+ {
+ return $this->selectionId;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Source.php b/admin/survey/minify/lib/Minify/Source.php
new file mode 100644
index 0000000..d94bf58
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Source.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * Class Minify_Source
+ * @package Minify
+ */
+
+/**
+ * A content source to be minified by Minify.
+ *
+ * This allows per-source minification options and the mixing of files with
+ * content from other sources.
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_Source implements Minify_SourceInterface
+{
+
+ /**
+ * @var int time of last modification
+ */
+ protected $lastModified;
+
+ /**
+ * @var callback minifier function specifically for this source.
+ */
+ protected $minifier;
+
+ /**
+ * @var array minification options specific to this source.
+ */
+ protected $minifyOptions = array();
+
+ /**
+ * @var string full path of file
+ */
+ protected $filepath;
+
+ /**
+ * @var string HTTP Content Type (Minify requires one of the constants Minify::TYPE_*)
+ */
+ protected $contentType;
+
+ /**
+ * @var string
+ */
+ protected $content;
+
+ /**
+ * @var callable
+ */
+ protected $getContentFunc;
+
+ /**
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * Create a Minify_Source
+ *
+ * In the $spec array(), you can either provide a 'filepath' to an existing
+ * file (existence will not be checked!) or give 'id' (unique string for
+ * the content), 'content' (the string content) and 'lastModified'
+ * (unixtime of last update).
+ *
+ * @param array $spec options
+ */
+ public function __construct($spec)
+ {
+ if (isset($spec['filepath'])) {
+ $ext = pathinfo($spec['filepath'], PATHINFO_EXTENSION);
+ switch ($ext) {
+ case 'js': $this->contentType = Minify::TYPE_JS;
+ break;
+ case 'less': // fallthrough
+ case 'scss': // fallthrough
+ case 'css': $this->contentType = Minify::TYPE_CSS;
+ break;
+ case 'htm': // fallthrough
+ case 'html': $this->contentType = Minify::TYPE_HTML;
+ break;
+ }
+ $this->filepath = $spec['filepath'];
+ $this->id = $spec['filepath'];
+
+ // TODO ideally not touch disk in constructor
+ $this->lastModified = filemtime($spec['filepath']);
+
+ if (!empty($spec['uploaderHoursBehind'])) {
+ // offset for Windows uploaders with out of sync clocks
+ $this->lastModified += round($spec['uploaderHoursBehind'] * 3600);
+ }
+ } elseif (isset($spec['id'])) {
+ $this->id = 'id::' . $spec['id'];
+ if (isset($spec['content'])) {
+ $this->content = $spec['content'];
+ } else {
+ $this->getContentFunc = $spec['getContentFunc'];
+ }
+ $this->lastModified = isset($spec['lastModified']) ? $spec['lastModified'] : time();
+ }
+ if (isset($spec['contentType'])) {
+ $this->contentType = $spec['contentType'];
+ }
+ if (isset($spec['minifier'])) {
+ $this->setMinifier($spec['minifier']);
+ }
+ if (isset($spec['minifyOptions'])) {
+ $this->minifyOptions = $spec['minifyOptions'];
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLastModified()
+ {
+ return $this->lastModified;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMinifier()
+ {
+ return $this->minifier;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMinifier($minifier = null)
+ {
+ if ($minifier === '') {
+ error_log(__METHOD__ . " cannot accept empty string. Use 'Minify::nullMinifier' or 'trim'.");
+ $minifier = 'Minify::nullMinifier';
+ }
+ if ($minifier !== null && !is_callable($minifier, true)) {
+ throw new InvalidArgumentException('minifier must be null or a valid callable');
+ }
+ $this->minifier = $minifier;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMinifierOptions()
+ {
+ return $this->minifyOptions;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMinifierOptions(array $options)
+ {
+ $this->minifyOptions = $options;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getContentType()
+ {
+ return $this->contentType;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getContent()
+ {
+ if (null === $this->filepath) {
+ if (null === $this->content) {
+ $content = call_user_func($this->getContentFunc, $this->id);
+ } else {
+ $content = $this->content;
+ }
+ } else {
+ $content = file_get_contents($this->filepath);
+ }
+
+ // remove UTF-8 BOM if present
+ if (strpos($content, "\xEF\xBB\xBF") === 0) {
+ return substr($content, 3);
+ }
+
+ return $content;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFilePath()
+ {
+ return $this->filepath;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setupUriRewrites()
+ {
+ if ($this->filepath
+ && !isset($this->minifyOptions['currentDir'])
+ && !isset($this->minifyOptions['prependRelativePath'])) {
+ $this->minifyOptions['currentDir'] = dirname($this->filepath);
+ }
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Source/Factory.php b/admin/survey/minify/lib/Minify/Source/Factory.php
new file mode 100644
index 0000000..4371931
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Source/Factory.php
@@ -0,0 +1,197 @@
+<?php
+
+class Minify_Source_Factory
+{
+
+ /**
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * @var callable[]
+ */
+ protected $handlers = array();
+
+ /**
+ * @var Minify_Env
+ */
+ protected $env;
+
+ /**
+ * @param Minify_Env $env
+ * @param array $options
+ *
+ * noMinPattern : Pattern matched against basename of the filepath (if present). If the pattern
+ * matches, Minify will try to avoid re-compressing the resource.
+ *
+ * fileChecker : Callable responsible for verifying the existence of the file.
+ *
+ * resolveDocRoot : If true, a leading "//" will be replaced with the document root.
+ *
+ * checkAllowDirs : If true, the filepath will be verified to be within one of the directories
+ * specified by allowDirs.
+ *
+ * allowDirs : Directory paths in which sources can be served.
+ *
+ * uploaderHoursBehind : How many hours behind are the file modification times of uploaded files?
+ * If you upload files from Windows to a non-Windows server, Windows may report
+ * incorrect mtimes for the files. Immediately after modifying and uploading a
+ * file, use the touch command to update the mtime on the server. If the mtime
+ * jumps ahead by a number of hours, set this variable to that number. If the mtime
+ * moves back, this should not be needed.
+ *
+ * @param Minify_CacheInterface $cache Optional cache for handling .less files.
+ *
+ */
+ public function __construct(Minify_Env $env, array $options = array(), Minify_CacheInterface $cache = null)
+ {
+ $this->env = $env;
+ $this->options = array_merge(array(
+ 'noMinPattern' => '@[-\\.]min\\.(?:[a-zA-Z]+)$@i', // matched against basename
+ 'fileChecker' => array($this, 'checkIsFile'),
+ 'resolveDocRoot' => true,
+ 'checkAllowDirs' => true,
+ 'allowDirs' => array('//'),
+ 'uploaderHoursBehind' => 0,
+ ), $options);
+
+ // resolve // in allowDirs
+ $docRoot = $env->getDocRoot();
+ foreach ($this->options['allowDirs'] as $i => $dir) {
+ if (0 === strpos($dir, '//')) {
+ $this->options['allowDirs'][$i] = $docRoot . substr($dir, 1);
+ }
+ }
+
+ if ($this->options['fileChecker'] && !is_callable($this->options['fileChecker'])) {
+ throw new InvalidArgumentException("fileChecker option is not callable");
+ }
+
+ $this->setHandler('~\.less$~i', function ($spec) use ($cache) {
+ return new Minify_LessCssSource($spec, $cache);
+ });
+
+ $this->setHandler('~\.scss~i', function ($spec) use ($cache) {
+ return new Minify_ScssCssSource($spec, $cache);
+ });
+
+ $this->setHandler('~\.(js|css)$~i', function ($spec) {
+ return new Minify_Source($spec);
+ });
+ }
+
+ /**
+ * @param string $basenamePattern A pattern tested against basename. E.g. "~\.css$~"
+ * @param callable $handler Function that recieves a $spec array and returns a Minify_SourceInterface
+ */
+ public function setHandler($basenamePattern, $handler)
+ {
+ $this->handlers[$basenamePattern] = $handler;
+ }
+
+ /**
+ * @param string $file
+ * @return string
+ *
+ * @throws Minify_Source_FactoryException
+ */
+ public function checkIsFile($file)
+ {
+ $realpath = realpath($file);
+ if (!$realpath) {
+ throw new Minify_Source_FactoryException("File failed realpath(): $file");
+ }
+
+ $basename = basename($file);
+ if (0 === strpos($basename, '.')) {
+ throw new Minify_Source_FactoryException("Filename starts with period (may be hidden): $basename");
+ }
+
+ if (!is_file($realpath) || !is_readable($realpath)) {
+ throw new Minify_Source_FactoryException("Not a file or isn't readable: $file");
+ }
+
+ return $realpath;
+ }
+
+ /**
+ * @param mixed $spec
+ *
+ * @return Minify_SourceInterface
+ *
+ * @throws Minify_Source_FactoryException
+ */
+ public function makeSource($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);
+ }
+
+ if ($this->options['resolveDocRoot'] && 0 === strpos($spec['filepath'], '//')) {
+ $spec['filepath'] = $this->env->getDocRoot() . substr($spec['filepath'], 1);
+ }
+
+ if (!empty($this->options['fileChecker'])) {
+ $spec['filepath'] = call_user_func($this->options['fileChecker'], $spec['filepath']);
+ }
+
+ if ($this->options['checkAllowDirs']) {
+ $allowDirs = (array)$this->options['allowDirs'];
+ $inAllowedDir = false;
+ $filePath = $this->env->normalizePath($spec['filepath']);
+ foreach ($allowDirs as $allowDir) {
+ if (strpos($filePath, $this->env->normalizePath($allowDir)) === 0) {
+ $inAllowedDir = true;
+ }
+ }
+
+ if (!$inAllowedDir) {
+ $allowDirsStr = implode(';', $allowDirs);
+ throw new Minify_Source_FactoryException("File '{$spec['filepath']}' is outside \$allowDirs "
+ . "($allowDirsStr). If the path is resolved via an alias/symlink, look into the "
+ . "\$min_symlinks option.");
+ }
+ }
+
+ $basename = basename($spec['filepath']);
+
+ if ($this->options['noMinPattern'] && preg_match($this->options['noMinPattern'], $basename)) {
+ if (preg_match('~\.(css|less)$~i', $basename)) {
+ $spec['minifyOptions']['compress'] = false;
+ // we still want URI rewriting to work for CSS
+ } else {
+ $spec['minifier'] = 'Minify::nullMinifier';
+ }
+ }
+
+ $hoursBehind = $this->options['uploaderHoursBehind'];
+ if ($hoursBehind != 0) {
+ $spec['uploaderHoursBehind'] = $hoursBehind;
+ }
+
+ foreach ($this->handlers as $basenamePattern => $handler) {
+ if (preg_match($basenamePattern, $basename)) {
+ $source = call_user_func($handler, $spec);
+ break;
+ }
+ }
+
+ if (!$source) {
+ throw new Minify_Source_FactoryException("Handler not found for file: $basename");
+ }
+
+ return $source;
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/Source/FactoryException.php b/admin/survey/minify/lib/Minify/Source/FactoryException.php
new file mode 100644
index 0000000..bbc9833
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/Source/FactoryException.php
@@ -0,0 +1,5 @@
+<?php
+
+class Minify_Source_FactoryException extends Exception
+{
+}
diff --git a/admin/survey/minify/lib/Minify/SourceInterface.php b/admin/survey/minify/lib/Minify/SourceInterface.php
new file mode 100644
index 0000000..ef281b9
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/SourceInterface.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Interface Minify_SourceInterface
+ * @package Minify
+ */
+
+/**
+ * A content source to be minified by Minify.
+ *
+ * This allows per-source minification options and the mixing of files with
+ * content from other sources.
+ *
+ * @package Minify
+ */
+interface Minify_SourceInterface
+{
+
+ /**
+ * Get the minifier
+ *
+ * @return callable|null
+ */
+ public function getMinifier();
+
+ /**
+ * Set the minifier
+ *
+ * @param callable $minifier
+ * @return void
+ */
+ public function setMinifier($minifier = null);
+
+ /**
+ * Get options for the minifier
+ *
+ * @return array
+ */
+ public function getMinifierOptions();
+
+ /**
+ * Set options for the minifier
+ *
+ * @param array $options
+ * @return void
+ */
+ public function setMinifierOptions(array $options);
+
+ /**
+ * Get the content type
+ *
+ * @return string|null
+ */
+ public function getContentType();
+
+ /**
+ * Get content
+ *
+ * @return string
+ */
+ public function getContent();
+
+ /**
+ * Get last modified timestamp
+ *
+ * @return int
+ */
+ public function getLastModified();
+
+ /**
+ * Get id
+ *
+ * @return string
+ */
+ public function getId();
+
+ /**
+ * Get the path of the file that this source is based on (may be null)
+ *
+ * @return string|null
+ */
+ public function getFilePath();
+}
diff --git a/admin/survey/minify/lib/Minify/SourceSet.php b/admin/survey/minify/lib/Minify/SourceSet.php
new file mode 100644
index 0000000..86f550f
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/SourceSet.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Class Minify_SourceSet
+ * @package Minify
+ */
+
+/**
+ * @package Minify
+ */
+class Minify_SourceSet
+{
+
+ /**
+ * Get unique string for a set of sources
+ *
+ * @param Minify_SourceInterface[] $sources Minify_Source instances
+ *
+ * @return string
+ */
+ public static function getDigest($sources)
+ {
+ $info = array();
+ foreach ($sources as $source) {
+ $info[] = array(
+ $source->getId(), $source->getMinifier(), $source->getMinifierOptions()
+ );
+ }
+
+ return md5(serialize($info));
+ }
+}
diff --git a/admin/survey/minify/lib/Minify/YUICompressor.php b/admin/survey/minify/lib/Minify/YUICompressor.php
new file mode 100644
index 0000000..40fd02c
--- /dev/null
+++ b/admin/survey/minify/lib/Minify/YUICompressor.php
@@ -0,0 +1,157 @@
+<?php
+/**
+ * Class Minify_YUICompressor
+ * @package Minify
+ */
+
+/**
+ * Compress Javascript/CSS using the YUI Compressor
+ *
+ * You must set $jarFile and $tempDir before calling the minify functions.
+ * Also, depending on your shell's environment, you may need to specify
+ * the full path to java in $javaExecutable or use putenv() to setup the
+ * Java environment.
+ *
+ * <code>
+ * Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.4.6.jar';
+ * Minify_YUICompressor::$tempDir = '/tmp';
+ * $code = Minify_YUICompressor::minifyJs(
+ * $code
+ * ,array('nomunge' => true, 'line-break' => 1000)
+ * );
+ * </code>
+ *
+ * Note: In case you run out stack (default is 512k), you may increase stack size in $options:
+ * array('stack-size' => '2048k')
+ *
+ * @todo unit tests, $options docs
+ *
+ * @package Minify
+ * @author Stephen Clay <steve@mrclay.org>
+ */
+class Minify_YUICompressor
+{
+
+ /**
+ * Filepath of the YUI Compressor jar file. This must be set before
+ * calling minifyJs() or minifyCss().
+ *
+ * @var string
+ */
+ public static $jarFile;
+
+ /**
+ * Writable temp directory. This must be set before calling minifyJs()
+ * or minifyCss().
+ *
+ * @var string
+ */
+ public static $tempDir;
+
+ /**
+ * Filepath of "java" executable (may be needed if not in shell's PATH)
+ *
+ * @var string
+ */
+ public static $javaExecutable = 'java';
+
+ /**
+ * Minify a Javascript string
+ *
+ * @param string $js
+ *
+ * @param array $options (verbose is ignored)
+ *
+ * @see http://www.julienlecomte.net/yuicompressor/README
+ *
+ * @return string
+ */
+ public static function minifyJs($js, $options = array())
+ {
+ return self::_minify('js', $js, $options);
+ }
+
+ /**
+ * Minify a CSS string
+ *
+ * @param string $css
+ *
+ * @param array $options (verbose is ignored)
+ *
+ * @see http://www.julienlecomte.net/yuicompressor/README
+ *
+ * @return string
+ */
+ public static function minifyCss($css, $options = array())
+ {
+ return self::_minify('css', $css, $options);
+ }
+
+ private static function _minify($type, $content, $options)
+ {
+ self::_prepare();
+ if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
+ throw new Exception('Minify_YUICompressor : could not create temp file in "'.self::$tempDir.'".');
+ }
+
+ file_put_contents($tmpFile, $content);
+ exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code);
+ unlink($tmpFile);
+ if ($result_code != 0) {
+ throw new Exception('Minify_YUICompressor : YUI compressor execution failed.');
+ }
+
+ return implode("\n", $output);
+ }
+
+ private static function _getCmd($userOptions, $type, $tmpFile)
+ {
+ $defaults = array(
+ 'charset' => '',
+ 'line-break' => 5000,
+ 'type' => $type,
+ 'nomunge' => false,
+ 'preserve-semi' => false,
+ 'disable-optimizations' => false,
+ 'stack-size' => '',
+ );
+ $o = array_merge($defaults, $userOptions);
+
+ $cmd = self::$javaExecutable
+ . (!empty($o['stack-size']) ? ' -Xss' . $o['stack-size'] : '')
+ . ' -jar ' . escapeshellarg(self::$jarFile)
+ . " --type {$type}"
+ . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
+ ? " --charset {$o['charset']}"
+ : '')
+ . (is_numeric($o['line-break']) && $o['line-break'] >= 0
+ ? ' --line-break ' . (int)$o['line-break']
+ : '');
+ if ($type === 'js') {
+ foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
+ $cmd .= $o[$opt]
+ ? " --{$opt}"
+ : '';
+ }
+ }
+
+ return $cmd . ' ' . escapeshellarg($tmpFile);
+ }
+
+ private static function _prepare()
+ {
+ if (! is_file(self::$jarFile)) {
+ throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.');
+ }
+ if (! is_readable(self::$jarFile)) {
+ throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not readable.');
+ }
+ if (! is_dir(self::$tempDir)) {
+ throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.');
+ }
+ if (! is_writable(self::$tempDir)) {
+ throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not writable.');
+ }
+ }
+}
+