.dev/useful/pack_zend.php
<?php
//-----------------------------------------------------------
// settings
//-----------------------------------------------------------
$base_path = 'd:/www/htdocs/zend/';
$source_dir = $base_path . 'library/';
$packed_dir = $base_path . 'packed/';
$compiled_dir = $base_path;
$compiled_file = $compiled_dir . 'zend_framework_min.php';
$ADD_SOURCE_FILE_NAMES = 1;
$pattern_require = "/(require_once[\s\t]*[\"\'\(]+([^\'\"\(\)]+?)[\'\"\)]+[\s\t]*;[\s\t]*)/ims";
//-----------------------------------------------------------
$GLOBALS['CLASSES'] = [];
$GLOBALS['CLASSES_PATHS'] = [];
$GLOBALS['BUILT_IN_CLASSES'] = array_merge(get_declared_classes(), spl_classes(), get_declared_interfaces());
$GLOBALS['INHERIT_TREE'] = [];
$GLOBALS['INHERIT_CHILDREN'] = [];
$GLOBALS['INHERIT_PARENTS'] = [];
$GLOBALS['INHERIT_TOP'] = [];
$GLOBALS['INHERIT_NONE'] = [];
$GLOBALS['ABSTRACT_CLASSES'] = [];
$GLOBALS['INTERFACES'] = [];
//-----------------------------------------------------------
$time_start = array_sum(explode(' ', microtime()));
//-----------------------------------------------------------
/**
* Put string contents to the file.
*/
if ( ! function_exists('file_put_contents')) {
function file_put_contents($filename, $data)
{
if ( ! $fp = @fopen($filename, 'w')) {
return false;
}
flock($fp, LOCK_EX);
$res = fwrite($fp, $data, strlen($data));
flock($fp, LOCK_UN);
fclose($fp);
return $res;
}
}
if ( ! defined('T_ML_COMMENT')) {
define('T_ML_COMMENT', T_COMMENT);
} else {
define('T_DOC_COMMENT', T_ML_COMMENT);
}
// Method that allows to compress PHP code (removing comments, spaces, tabs, etc)
function _do_compress_php_file($file_to_open = '', $file_to_save = '')
{
$source = file_get_contents($file_to_open);
// Removes comments
foreach ((array) token_get_all($source) as $token) {
if (is_string($token)) {
// simple 1-character token
$output .= $token;
} else {
// token array
list($id, $text) = $token;
switch ($id) {
case T_COMMENT:
case T_ML_COMMENT: // we've defined this
case T_DOC_COMMENT: // and this
// no action on comments
$output .= ' ';
break;
default:
// anything else -> output "as is"
$output .= $text;
break;
}
}
}
$output = str_replace(["\r", "\n"], '', $output);
$output = str_replace("\t", ' ', $output);
$output = preg_replace("/[\s\t]{2,}/ims", ' ', $output);
// Write the file
$fh = @fopen($file_to_save, 'w');
fwrite($fh, $output);
@fclose($fh);
// Display compress ratio
$body .= 'compressed file "' . $file_to_open . '" saved into "' . $file_to_save . "\"<br />\r\n";
$body .= '<b>compress ratio: ' . (round(@filesize($file_to_open) / @filesize($file_to_save), 2) * 100) . '% (' . @filesize($file_to_open) . ' / ' . @filesize($file_to_save) . " bytes)</b><br />\r\n";
return $body;
}
/**
* Create dir structure.
* @param mixed $dir_name
* @param mixed $dir_mode
* @param mixed $create_index_htmls
* @param mixed $start_folder
*/
function _mkdir_m($dir_name, $dir_mode = 0755, $create_index_htmls = 0, $start_folder = '')
{
if ( ! $dir_name || ! strlen($dir_name)) {
return 0;
}
$dir_name = rtrim($dir_name, '/');
// Default start folder to look at
if ( ! strlen($start_folder)) {
$start_folder = INCLUDE_PATH;
}
$start_folder = str_replace(['\\', '//'], '/', realpath($start_folder) . '/');
$dir_name = str_replace(['\\', '//'], '/', $dir_name);
$old_mask = umask(0);
// Default dir mode
if (empty($dir_mode)) {
$dir_mode = 0755;
}
// Process given file name
if ( ! file_exists($dir_name)) {
$base_path = substr(PHP_OS, 0, 3) == 'WIN' ? '' : '/';
preg_match_all('/([^\/]+)\/?/i', $dir_name, $atmp);
foreach ((array) $atmp[0] as $val) {
$base_path = $base_path . $val;
// Skip paths while we are out of base_folder
if ( ! empty($start_folder) && false === strpos($base_path, $start_folder)) {
continue;
}
// Skip if already exists
if (file_exists($base_path)) {
continue;
}
// Try to create sub dir
if ( ! mkdir($base_path, $dir_mode)) {
trigger_error('DIR: Cannot create "' . $base_path . '"', E_USER_WARNING);
return -1;
}
chmod($base_path, $dir_mode);
}
} elseif ( ! is_dir($dir_name)) {
trigger_error('DIR: ' . $dir_name . ' exists and is not a directory', E_USER_WARNING);
return -2;
}
// Create empty index.html in new folder if needed
if ($create_index_htmls) {
$index_file_path = $dir_name . '/index.html';
if ( ! file_exists($index_file_path)) {
file_put_contents($index_file_path, '');
}
}
umask($old_mask);
return 0;
}
/**
* Recursively scanning directory structure (including subdirectories) //.
* @param mixed $start_dir
* @param mixed $FLAT_MODE
* @param mixed $include_pattern
* @param mixed $exclude_pattern
*/
function scan_dir($start_dir, $FLAT_MODE = true, $include_pattern = '', $exclude_pattern = '')
{
if ( ! file_exists($start_dir)) {
return false;
}
// Cut trailing slash
if (substr($start_dir, -1) == '/') {
$start_dir = substr($start_dir, 0, -1);
}
$files = [];
$dh = opendir($start_dir);
while (false !== ($f = readdir($dh))) {
if ($f == '.' || $f == '..') {
continue;
}
$item_name = $start_dir . '/' . $f;
// "Flat" mode (all filenames are stored as 1-dimension array, else - multi-dimension array)
if (is_dir($item_name)) {
$tmp_file = scan_dir($item_name, $FLAT_MODE, $include_pattern, $exclude_pattern);
} else {
$tmp_file = $FLAT_MODE ? $item_name : $f;
// Include files only if they match the mask
if ( ! empty($include_pattern)) {
if ( ! preg_match($include_pattern . 'ims', $tmp_file)) {
continue;
}
}
// Exclude files from list by mask
if ( ! empty($exclude_pattern)) {
if (preg_match($exclude_pattern . 'ims', $tmp_file)) {
continue;
}
}
}
// Add item to the result array
$files[$item_name] = $tmp_file;
}
closedir($dh);
// Prepare for the flat mode (if needed)
if (is_array($files)) {
if ($FLAT_MODE) {
$files = array_values_recursive($files);
}
ksort($files);
}
return $files;
}
/**
* Get values from the multi-dimensional array.
* @param mixed $ary
*/
function array_values_recursive($ary)
{
$lst = [];
foreach (array_keys($ary) as $k) {
$v = $ary[$k];
if (is_scalar($v)) {
$lst[] = $v;
} elseif (is_array($v)) {
$lst = array_merge($lst, array_values_recursive($v));
}
}
return $lst;
}
/**
* Build other inheritance arrays.
* @param mixed $parent
*/
function _build_inherit_parents($parent = '')
{
$next_parent = $GLOBALS['INHERIT_TREE'][$parent];
$parents = [];
$parents[$parent] = $next_parent;
if ( ! $next_parent) {
$GLOBALS['INHERIT_TOP'][$parent]++;
} else {
$parents[$next_parent] = $GLOBALS['INHERIT_TREE'][$next_parent];
foreach ((array) _build_inherit_parents($next_parent) as $k => $v) {
if ( ! isset($parents[$k])) {
$parents[$k] = $v;
}
}
}
return $parents;
}
//-----------------------------------------------------------
// START
//-----------------------------------------------------------
_mkdir_m($packed_dir, 0777);
_mkdir_m($compiled_dir, 0777);
// Get files array
$files_to_compress = scan_dir($source_dir, 1, "#.*\.(php)\$#");
//print_r($files_to_compress);
foreach ((array) $files_to_compress as $cur_file_path) {
$compressed_file_path = $packed_dir . substr($cur_file_path, strlen($source_dir));
$compressed_file_dir = dirname($compressed_file_path);
if ( ! file_exists($compressed_file_dir)) {
_mkdir_m($compressed_file_dir, 0777);
}
// Do compress
_do_compress_php_file($cur_file_path, $compressed_file_path);
}
// Get classes names and paths
$new_files_to_compile = [];
foreach ((array) scan_dir($packed_dir, 1, "#.*\.(php)\$#", $exclude_pattern_user) as $cur_file_path) {
$class_name = str_replace('/', '_', str_replace("\/", '/', substr($cur_file_path, strlen($packed_dir), -4)));
$GLOBALS['CLASSES'][$class_name] = $class_name;
$GLOBALS['CLASSES_PATHS'][$class_name] = $cur_file_path;
}
// Build inheritance tree
foreach ((array) $GLOBALS['CLASSES'] as $class_name) {
$text = substr(file_get_contents($GLOBALS['CLASSES_PATHS'][$class_name]), 6) . "\r\n";
$text = preg_replace($pattern_require, '', $text);
if (preg_match("/abstract class ([a-z\_]+)/ims", $text, $m)) {
$GLOBALS['ABSTRACT_CLASSES'][$class_name] = $class_name;
}
if (preg_match("/interface ([a-z\_]+)/ims", $text, $m)) {
$GLOBALS['INTERFACES'][$class_name] = $class_name;
}
if (preg_match("/(class|interface) ([a-z\_]+) (extends|implements) ([a-z\_]+)/ims", $text, $m)) {
$_child = $m[2];
$_parent = $m[4];
if ( ! in_array($_parent, $GLOBALS['BUILT_IN_CLASSES'])) {
$GLOBALS['INHERIT_TREE'][$_child] = $_parent;
$GLOBALS['INHERIT_CHILDREN'][$_parent][$_child] = $_child;
}
} else {
$GLOBALS['INHERIT_NONE'][$class_name] = $class_name;
}
}
// Build parents array
foreach ((array) $GLOBALS['INHERIT_TREE'] as $_child => $_parent) {
$GLOBALS['INHERIT_PARENTS'][$_child] = _build_inherit_parents($_parent);
}
ksort($GLOBALS['INHERIT_NONE']);
ksort($GLOBALS['INHERIT_TOP']);
// Build result array
$CLASSES_NEW = [];
foreach (array_keys($GLOBALS['ABSTRACT_CLASSES']) as $v) {
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
foreach (array_keys($GLOBALS['INTERFACES']) as $v) {
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
foreach (array_keys($GLOBALS['INHERIT_NONE']) as $v) {
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
foreach (array_keys($GLOBALS['INHERIT_TOP']) as $v) {
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
foreach ((array) $GLOBALS['INHERIT_PARENTS'] as $v => $_parents) {
foreach (array_reverse((array) $_parents, true) as $_parent => $_tmp) {
if ( ! isset($CLASSES_NEW[$_parent])) {
$CLASSES_NEW[$_parent] = $_parent;
}
}
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
foreach (array_keys($GLOBALS['CLASSES']) as $v) {
if ( ! isset($CLASSES_NEW[$v])) {
$CLASSES_NEW[$v] = $v;
}
}
$GLOBALS['CLASSES'] = $CLASSES_NEW;
$output .= '<pre>';
$output .= '<h1>INHERIT_TREE</h1>';
$output .= print_r($GLOBALS['INHERIT_TREE'], 1);
$output .= '<h1>INHERIT_CHILDREN</h1>';
$output .= print_r($GLOBALS['INHERIT_CHILDREN'], 1);
$output .= '<h1>INHERIT_PARENTS</h1>';
$output .= print_r($GLOBALS['INHERIT_PARENTS'], 1);
$output .= '<h1>INHERIT_TOP</h1>';
$output .= print_r($GLOBALS['INHERIT_TOP'], 1);
$output .= '<h1>INHERIT_NONE</h1>';
$output .= print_r($GLOBALS['INHERIT_NONE'], 1);
$output .= '<h1>ABSTRACT_CLASSES</h1>';
$output .= print_r($GLOBALS['ABSTRACT_CLASSES'], 1);
$output .= '<h1>INTERFACES</h1>';
$output .= print_r($GLOBALS['INTERFACES'], 1);
$output .= '<h1>RESULT_CLASSES</h1>';
$output .= print_r($GLOBALS['CLASSES'], 1);
$output .= '</pre>';
//------------------------------------------
// Finish
//------------------------------------------
$fh = fopen($compiled_file, 'w');
fwrite($fh, "<?php\r\n");
$counter = 0;
foreach ((array) $GLOBALS['CLASSES'] as $name) {
if ( ! $name) {
continue;
}
$cur_file_path = $GLOBALS['CLASSES_PATHS'][$name];
$cur_file_text = file_get_contents($cur_file_path);
$text = substr($cur_file_text, 6) . "\r\n";
$text = preg_replace($pattern_require, '', $text);
if ( ! strlen($text)) {
continue;
}
if ($ADD_SOURCE_FILE_NAMES) {
$text = '// source: ' . $cur_file_path . "\r\n" . $text;
}
fwrite($fh, $text);
$counter++;
$output .= $name . ' # ' . $cur_file_path . ' <b>' . strlen($text) . '</b><br />';
}
fclose($fh);
// prepare output info
$output2 .= "\r\n<br /><b>" . $counter . '</b> files from dir "' . $source_dir . "\"<br />\r\n compiled into result file \"" . $compiled_file . "\"<br />\r\n";
$output2 .= 'result file size: <b>' . filesize($compiled_file) . "</b> bytes<br />\r\n";
$output2 .= 'Generation time: <b>' . round(array_sum(explode(' ', microtime())) - $time_start, 3) . " secs</b>\r\n";
$output = $output2 . $output;
echo $output;