array( 'DBSR.php', 'DBSR_GUI_Resources', 'DBSR_GUI.php', 'Bootstrapper.php', 'DBSR_GUI_Bootstrapper.php' ), 'DBSearchReplace-CLI.php' => array( 'DBSR.php', 'DBSR_CLI.php', 'Bootstrapper.php', 'DBSR_CLI_Bootstrapper.php' ), ); // Stop throwing irritating errors, we're simply compiling! error_reporting(0); // Uses UglifyJS... if you don't have it, get the latest version from GitHub function jsCompiler($code) { // Start uglifyjs $process = proc_open('.' . DIRECTORY_SEPARATOR . 'node_modules' . DIRECTORY_SEPARATOR . '.bin' . DIRECTORY_SEPARATOR . 'uglifyjs -c unsafe=true -b beautify=false,ascii_only=true', array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'), ), $pipes); // Check if uglifyjs could be found / started if(is_resource($process)) { // Write the code to STDIN for uglifyjs fwrite($pipes[0], $code, strlen($code)); // Close the pipe so uglifyjs knows it's time to start fclose($pipes[0]); // Read the compressed output from STDOUT $code_compressed = trim(stream_get_contents($pipes[1])); // Close STDOUT to prevent deadlocks fclose($pipes[1]); // Read any errors from STDERR $errors = stream_get_contents($pipes[2]); // Close STDERR to prevent deadlocks fclose($pipes[2]); // Close the process handle $return_value = proc_close($process); // Check if the code compression completed succesfully if($return_value > 0) { // Something went wrong, return the old code echo 'Warning: UglifyJS returned a non-zero value!', PHP_EOL; if(!empty($errors)) echo $errors, PHP_EOL; return $code; } else { // Return the compressed code return $code_compressed; } } else { // No uglifyjs, so just return the raw code echo 'Warning: failed to run UglifyJS!', PHP_EOL; return $code; } } // Process dir function function add_resources($dir, $prefix, &$source) { global $minimize_php, $minimize_html, $minimize_js, $minimize_css, $minimize_svg; // Record any winnings by compression $compression_winnings = 0; // Load up all resources in this directory $resources = glob($dir . DIRECTORY_SEPARATOR . '*'); // Special case: CSS/JS compression if((preg_match('#/?js$#', $dir) && $minimize_js) || (preg_match('#/?css$#', $dir) && $minimize_css)) { if(preg_match('#/?js$#', $dir)) { // JS order $order = array( 'jquery', 'jquery-ui', 'jquery-liteaccordion', 'jquery-blockui', 'script', ); } else { // CSS order $order = array( 'SourceSansPro', 'SourceCodePro', 'reset', 'jquery-ui', 'jquery-liteaccordion', 'style', ); } // Webfonts CSS special case if(preg_match('#/?css$#', $dir)) { $resources = array_merge($resources, glob(str_replace('css', 'webfonts', $dir) . DIRECTORY_SEPARATOR . '*.css')); } // Collect resource content $resource_content = ''; foreach($order as $o) { foreach($resources as $key => $resource) { if(strpos($resource, $o) !== FALSE) { if($resource_file_content = file_get_contents($resource)) { $resource_content .= "\n" . $resource_file_content; } else { exit('Unable to load file ' . basename($resource)); } unset($resources[$key]); } } } foreach($resources as $key => $resource) { if(!is_file($resource)) continue; if(is_readable($resource) && ($resource_file_content = file_get_contents($resource))) { $resource_content .= "\n" . $resource_file_content; } else { exit('Unable to load file ' . basename($resource)); } unset($resources[$key]); } // Save length to calculate winnings $resource_content_length = strlen($resource_content); // Compile / minimize if(preg_match('#/?js$#', $dir)) { // JS using Closure Compiler $resource_content = jsCompiler($resource_content); } else { // CSS using regexes $resource_content = preg_replace('#/\*.*?\*/#s', '', $resource_content); $resource_content = preg_replace('/[\r\n]+/', '', $resource_content); $resource_content = preg_replace('/\s*([:,])\s*/', '$1', $resource_content); $resource_content = preg_replace('/\s*{\s*/', '{', $resource_content); $resource_content = preg_replace('/\s*;?\s*}\s*/', '}', $resource_content); $resource_content = preg_replace('/\s+/', ' ', $resource_content); $resource_content = trim($resource_content); } // Calculate improvement by compression / minimization $compression_winnings += $resource_content_length - strlen($resource_content); // Write to source if(preg_match('/[^\w\s[:print:]]/', $resource_content, $matches)) { $resource_content = 'base64:' . base64_encode($resource_content); } else { $resource_content = 'normal:' . $resource_content; } if(preg_match('#/?js$#', $dir)) { $source .= 'public static $js_scriptjs = ' . var_export($resource_content, TRUE) . ';' . "\n"; } else { $source .= 'public static $css_stylecss = ' . var_export($resource_content, TRUE) . ';' . "\n"; } } elseif(preg_match('#/?webfonts$#', $dir) && $minimize_css) { foreach($resources as $key => $resource) { if(preg_match('#\.css$#', $resource)) { unset($resources[$key]); } } } // Loop through dir foreach($resources as $resource) { if(is_readable($resource) && is_file($resource)) { if(!($resource_content = file_get_contents($resource))) { exit('Unable to load file ' . basename($resource)); } // Save length to calculate winnings $resource_content_length = strlen($resource_content); // Special case: template file if(basename($resource) == 'template.html') { // Remove all JS tags to account for compression if($minimize_js) $resource_content = preg_replace('#(\s*]+>)+(\s+]+script.js[^>]+>)#', '$2', $resource_content); // Remove all LINK tags to account for CSS compression if($minimize_css) $resource_content = preg_replace('#(\s*]*rel="stylesheet"[^>]*/>)+(\s+]+style.css[^>]+/>)#', '$2', $resource_content); // Remove useless HTML whitespace if($minimize_html) { $resource_content = preg_replace('/\s+/', ' ', $resource_content); $resource_content = str_replace('> <', '><', $resource_content); } } // Special case: SVG font files if(substr(basename($resource), -4) == '.svg' && $minimize_svg) { $resource_content = preg_replace('/\s+/', ' ', $resource_content); $resource_content = str_replace('> <', '><', $resource_content); } // Calculate improvement by compression / minimization $compression_winnings += $resource_content_length - strlen($resource_content); if(preg_match('/[^\w\s[:print:]]/', $resource_content)) { $resource_content = 'base64:' . base64_encode($resource_content); } else { $resource_content = 'normal:' . $resource_content; } $source .= 'public static $' . preg_replace('/[^\w]/', '', preg_replace('#[/\\\\]#', '_', ($prefix == '' ? '' : ($prefix . '/')) . basename($resource))) . ' = ' . var_export($resource_content, TRUE) . ';' . "\n"; } elseif(is_readable($resource) && is_dir($resource)) { $compression_winnings += add_resources($resource, ($prefix == '' ? '' : ($prefix . '/')) . basename($resource), $source); } else { exit('Unable to load file ' . basename($resource)); } } return $compression_winnings; } function normalizeFileSize($size) { $filesizename = array(' bytes', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB'); return $size ? round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i] : '0 bytes'; } // Process each file set foreach($compile_sets as $name => $files) { $compression_winnings = 0; $source = ' $file) { $file_path = $input_directory . DIRECTORY_SEPARATOR . $file; if(is_readable($file_path) && is_dir($file_path)) { $source .= ' class ' . $file . ' { '; $compression_winnings += add_resources($file_path, '', $source); $source .= ' /** * Get the resource file content. * @param string $resource The filename of the resource. * @return mixed The content of the file as string, or FALSE if unsuccessful. */ public static function getResource($resource) { // Clean the resource name $resource = preg_replace(\'/[^\w]/\', \'\', preg_replace(\'#[/\\\\\\\\]#\', \'_\', $resource)); // Look it up and return it if(isset(static::$$resource)) { // Check for base64 encoding switch(substr(static::$$resource, 0, 6)) { case \'base64\': return base64_decode(substr(static::$$resource, 7)); default: case \'normal\': return substr(static::$$resource, 7); } } else { return FALSE; } }'; $source .= '}'; } elseif(is_readable($file_path) && is_file($file_path)) { $source .= substr(file_get_contents($file_path), 5); } else { exit('Unable to load file ' . $file); } } if($minimize_php) { $compressed = ''; $tokens = token_get_all($source); $previous_token_keyword = FALSE; $previous_token_char = FALSE; foreach($tokens as $token) { if(is_array($token)) { switch($token[0]) { case T_DOC_COMMENT: case T_COMMENT: case T_WHITESPACE: continue 2; } $current_token_keyword = FALSE; switch($token[0]) { case T_ABSTRACT: case T_AS: case T_BREAK: case T_CALLABLE: case T_CASE: case T_CLASS: case T_CLONE: case T_CONST: case T_CONTINUE: case T_ECHO: case T_ELSE: case T_ELSEIF: case T_EXTENDS: case T_FINAL: case T_FUNCTION: case T_GLOBAL: case T_GOTO: case T_IMPLEMENTS: case T_INCLUDE: case T_INCLUDE_ONCE: case T_INSTANCEOF: case T_INSTEADOF: case T_INTERFACE: case T_LOGICAL_AND: case T_LOGICAL_OR: case T_LOGICAL_XOR: case T_NAMESPACE: case T_NEW: case T_PRIVATE: case T_PUBLIC: case T_PROTECTED: case T_REQUIRE: case T_REQUIRE_ONCE: case T_RETURN: case T_STATIC: case T_THROW: case T_TRAIT: case T_USE: case T_VAR: case T_RETURN: $current_token_keyword = TRUE; break; } $compressed .= (!$previous_token_char && ($previous_token_keyword || $current_token_keyword) ? ' ' : '') . $token[1]; $previous_token_keyword = $current_token_keyword; $previous_token_char = FALSE; } else { $compressed .= $token; $previous_token_keyword = FALSE; $previous_token_char = TRUE; } } $compressed = trim(substr($compressed, 5)); switch($compress) { case 'gzip': $compressed = 'eval(gzuncompress(base64_decode(\'' . base64_encode(gzcompress($compressed, 9)) . '\')));'; break; } // Re-insert the GPL into the compressed $compressed = '.' . "\n" . ' */' . "\n" . $compressed; file_put_contents($output_directory . DIRECTORY_SEPARATOR . $name, $compressed); echo 'Compiled file ', $name, ', total size is ' . normalizeFileSize(strlen($compressed)) . ' (including ', round(100 * (1 - (strlen($compressed) / (strlen($source) + $compression_winnings))), 1), '% reduction by compression)' . (PHP_SAPI == 'cli' ? '' : '
') . PHP_EOL; } else { file_put_contents($output_directory . DIRECTORY_SEPARATOR . $name, $source); echo 'Compiled file ', $name, ', total size is ' . normalizeFileSize(strlen($source)) . (PHP_SAPI == 'cli' ? '' : '
') . PHP_EOL; } }