mirror of
https://github.com/vrana/adminer.git
synced 2025-08-06 06:37:33 +02:00
Compile: Add tests for php_shrink
This commit is contained in:
135
compile.php
135
compile.php
@@ -2,12 +2,9 @@
|
|||||||
<?php
|
<?php
|
||||||
include __DIR__ . "/adminer/include/version.inc.php";
|
include __DIR__ . "/adminer/include/version.inc.php";
|
||||||
include __DIR__ . "/adminer/include/errors.inc.php";
|
include __DIR__ . "/adminer/include/errors.inc.php";
|
||||||
|
include __DIR__ . "/php_shrink.inc.php";
|
||||||
include __DIR__ . "/externals/JsShrink/jsShrink.php";
|
include __DIR__ . "/externals/JsShrink/jsShrink.php";
|
||||||
|
|
||||||
function add_apo_slashes($s) {
|
|
||||||
return addcslashes($s, "\\'");
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_quo_slashes($s) {
|
function add_quo_slashes($s) {
|
||||||
$return = $s;
|
$return = $s;
|
||||||
$return = addcslashes($return, "\n\r\$\"\\");
|
$return = addcslashes($return, "\n\r\$\"\\");
|
||||||
@@ -212,127 +209,6 @@ if (!$translations) {
|
|||||||
';
|
';
|
||||||
}
|
}
|
||||||
|
|
||||||
function short_identifier($number, $chars) {
|
|
||||||
$return = '';
|
|
||||||
while ($number >= 0) {
|
|
||||||
$return .= $chars[$number % strlen($chars)];
|
|
||||||
$number = floor($number / strlen($chars)) - 1;
|
|
||||||
}
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// based on http://latrine.dgx.cz/jak-zredukovat-php-skripty
|
|
||||||
function php_shrink($input) {
|
|
||||||
global $VERSION;
|
|
||||||
$special_variables = array_flip(array('$this', '$GLOBALS', '$_GET', '$_POST', '$_FILES', '$_COOKIE', '$_SESSION', '$_SERVER', '$http_response_header', '$php_errormsg'));
|
|
||||||
$short_variables = array();
|
|
||||||
$shortening = true;
|
|
||||||
$tokens = token_get_all($input);
|
|
||||||
|
|
||||||
// remove unnecessary { }
|
|
||||||
//! change also `while () { if () {;} }` to `while () if () ;` but be careful about `if () { if () { } } else { }
|
|
||||||
$shorten = 0;
|
|
||||||
$opening = -1;
|
|
||||||
foreach ($tokens as $i => $token) {
|
|
||||||
if (in_array($token[0], array(T_IF, T_ELSE, T_ELSEIF, T_WHILE, T_DO, T_FOR, T_FOREACH), true)) {
|
|
||||||
$shorten = ($token[0] == T_FOR ? 4 : 2);
|
|
||||||
$opening = -1;
|
|
||||||
} elseif (in_array($token[0], array(T_SWITCH, T_FUNCTION, T_CLASS, T_CLOSE_TAG), true)) {
|
|
||||||
$shorten = 0;
|
|
||||||
} elseif ($token === ';') {
|
|
||||||
$shorten--;
|
|
||||||
} elseif ($token === '{') {
|
|
||||||
if ($opening < 0) {
|
|
||||||
$opening = $i;
|
|
||||||
} elseif ($shorten > 1) {
|
|
||||||
$shorten = 0;
|
|
||||||
}
|
|
||||||
} elseif ($token === '}' && $opening >= 0 && $shorten == 1) {
|
|
||||||
unset($tokens[$opening]);
|
|
||||||
unset($tokens[$i]);
|
|
||||||
$shorten = 0;
|
|
||||||
$opening = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$tokens = array_values($tokens);
|
|
||||||
|
|
||||||
foreach ($tokens as $i => $token) {
|
|
||||||
if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
|
|
||||||
$short_variables[$token[1]]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arsort($short_variables);
|
|
||||||
$chars = implode(range('a', 'z')) . '_' . implode(range('A', 'Z'));
|
|
||||||
// preserve variable names between versions if possible
|
|
||||||
$short_variables2 = array_splice($short_variables, strlen($chars));
|
|
||||||
ksort($short_variables);
|
|
||||||
ksort($short_variables2);
|
|
||||||
$short_variables += $short_variables2;
|
|
||||||
foreach (array_keys($short_variables) as $number => $key) {
|
|
||||||
$short_variables[$key] = short_identifier($number, $chars); // could use also numbers and \x7f-\xff
|
|
||||||
}
|
|
||||||
|
|
||||||
$set = array_flip(preg_split('//', '!"#$%&\'()*+,-./:;<=>?@[]^`{|}'));
|
|
||||||
$space = '';
|
|
||||||
$output = '';
|
|
||||||
$in_echo = false;
|
|
||||||
$doc_comment = false; // include only first /**
|
|
||||||
for (reset($tokens); list($i, $token) = each($tokens);) {
|
|
||||||
if (!is_array($token)) {
|
|
||||||
$token = array(0, $token);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
$tokens[$i+2][0] === T_CLOSE_TAG && $tokens[$i+3][0] === T_INLINE_HTML && $tokens[$i+4][0] === T_OPEN_TAG
|
|
||||||
&& strlen(add_apo_slashes($tokens[$i+3][1])) < strlen($tokens[$i+3][1]) + 3
|
|
||||||
) {
|
|
||||||
$tokens[$i+2] = array(T_ECHO, 'echo');
|
|
||||||
$tokens[$i+3] = array(T_CONSTANT_ENCAPSED_STRING, "'" . add_apo_slashes($tokens[$i+3][1]) . "'");
|
|
||||||
$tokens[$i+4] = array(0, ';');
|
|
||||||
}
|
|
||||||
if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
|
|
||||||
$space = "\n";
|
|
||||||
} else {
|
|
||||||
if ($token[0] == T_DOC_COMMENT) {
|
|
||||||
$doc_comment = true;
|
|
||||||
$token[1] = substr_replace($token[1], "* @version $VERSION\n", -2, 0);
|
|
||||||
}
|
|
||||||
if ($token[0] == T_VAR || $token[0] == T_PUBLIC || $token[0] == T_PROTECTED || $token[0] == T_PRIVATE) {
|
|
||||||
if ($token[0] == T_PUBLIC && $tokens[$i+2][1][0] == '$') {
|
|
||||||
$token[1] = 'var';
|
|
||||||
}
|
|
||||||
$shortening = false;
|
|
||||||
} elseif (!$shortening) {
|
|
||||||
if ($token[1] == ';' || $token[0] == T_FUNCTION) {
|
|
||||||
$shortening = true;
|
|
||||||
}
|
|
||||||
} elseif ($token[0] == T_ECHO) {
|
|
||||||
$in_echo = true;
|
|
||||||
} elseif ($token[1] == ';' && $in_echo) {
|
|
||||||
if ($tokens[$i+1][0] === T_WHITESPACE && $tokens[$i+2][0] === T_ECHO) {
|
|
||||||
next($tokens);
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
if ($tokens[$i+1][0] === T_ECHO) {
|
|
||||||
// join two consecutive echos
|
|
||||||
next($tokens);
|
|
||||||
$token[1] = ','; // '.' would conflict with "a".1+2 and would use more memory //! remove ',' and "," but not $var","
|
|
||||||
} else {
|
|
||||||
$in_echo = false;
|
|
||||||
}
|
|
||||||
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
|
|
||||||
$token[1] = '$' . $short_variables[$token[1]];
|
|
||||||
}
|
|
||||||
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
|
|
||||||
$space = '';
|
|
||||||
}
|
|
||||||
$output .= $space . $token[1];
|
|
||||||
$space = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
function minify_css($file) {
|
function minify_css($file) {
|
||||||
return lzw_compress(preg_replace('~\s*([:;{},])\s*~', '\1', preg_replace('~/\*.*\*/~sU', '', $file)));
|
return lzw_compress(preg_replace('~\s*([:;{},])\s*~', '\1', preg_replace('~/\*.*\*/~sU', '', $file)));
|
||||||
}
|
}
|
||||||
@@ -359,14 +235,6 @@ function compile_file($match) {
|
|||||||
return '"' . add_quo_slashes($file) . '"';
|
return '"' . add_quo_slashes($file) . '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists("each")) {
|
|
||||||
function each(&$arr) {
|
|
||||||
$key = key($arr);
|
|
||||||
next($arr);
|
|
||||||
return $key === null ? false : array($key, $arr[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function min_version() {
|
function min_version() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -414,6 +282,7 @@ include __DIR__ . "/adminer/include/driver.inc.php";
|
|||||||
$features = array("check", "call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view");
|
$features = array("check", "call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view");
|
||||||
$lang_ids = array(); // global variable simplifies usage in a callback function
|
$lang_ids = array(); // global variable simplifies usage in a callback function
|
||||||
$file = file_get_contents(__DIR__ . "/$project/index.php");
|
$file = file_get_contents(__DIR__ . "/$project/index.php");
|
||||||
|
$file = preg_replace('~\*/~', "* @version $VERSION\n*/", $file, 1);
|
||||||
if ($driver) {
|
if ($driver) {
|
||||||
$_GET[$driver] = true; // to load the driver
|
$_GET[$driver] = true; // to load the driver
|
||||||
include_once __DIR__ . $driver_path;
|
include_once __DIR__ . $driver_path;
|
||||||
|
132
php_shrink.inc.php
Normal file
132
php_shrink.inc.php
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// based on http://latrine.dgx.cz/jak-zredukovat-php-skripty
|
||||||
|
function php_shrink($input) {
|
||||||
|
$special_variables = array_flip(array('$this', '$GLOBALS', '$_GET', '$_POST', '$_FILES', '$_COOKIE', '$_SESSION', '$_SERVER', '$http_response_header', '$php_errormsg'));
|
||||||
|
$short_variables = array();
|
||||||
|
$shortening = true;
|
||||||
|
$tokens = token_get_all($input);
|
||||||
|
|
||||||
|
// remove unnecessary { }
|
||||||
|
//! change also `while () { if () {;} }` to `while () if () ;` but be careful about `if () { if () { } } else { }
|
||||||
|
$shorten = 0;
|
||||||
|
$opening = -1;
|
||||||
|
foreach ($tokens as $i => $token) {
|
||||||
|
if (in_array($token[0], array(T_IF, T_ELSE, T_ELSEIF, T_WHILE, T_DO, T_FOR, T_FOREACH), true)) {
|
||||||
|
$shorten = ($token[0] == T_FOR ? 4 : 2);
|
||||||
|
$opening = -1;
|
||||||
|
} elseif (in_array($token[0], array(T_SWITCH, T_FUNCTION, T_CLASS, T_CLOSE_TAG), true)) {
|
||||||
|
$shorten = 0;
|
||||||
|
} elseif ($token === ';') {
|
||||||
|
$shorten--;
|
||||||
|
} elseif ($token === '{') {
|
||||||
|
if ($opening < 0) {
|
||||||
|
$opening = $i;
|
||||||
|
} elseif ($shorten > 1) {
|
||||||
|
$shorten = 0;
|
||||||
|
}
|
||||||
|
} elseif ($token === '}' && $opening >= 0 && $shorten == 1) {
|
||||||
|
unset($tokens[$opening]);
|
||||||
|
unset($tokens[$i]);
|
||||||
|
$shorten = 0;
|
||||||
|
$opening = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tokens = array_values($tokens);
|
||||||
|
|
||||||
|
foreach ($tokens as $i => $token) {
|
||||||
|
if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
|
||||||
|
$short_variables[$token[1]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arsort($short_variables);
|
||||||
|
$chars = implode(range('a', 'z')) . '_' . implode(range('A', 'Z'));
|
||||||
|
// preserve variable names between versions if possible
|
||||||
|
$short_variables2 = array_splice($short_variables, strlen($chars));
|
||||||
|
ksort($short_variables);
|
||||||
|
ksort($short_variables2);
|
||||||
|
$short_variables += $short_variables2;
|
||||||
|
foreach (array_keys($short_variables) as $number => $key) {
|
||||||
|
$short_variables[$key] = short_identifier($number, $chars); // could use also numbers and \x7f-\xff
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = array_flip(preg_split('//', '!"#$%&\'()*+,-./:;<=>?@[]^`{|}'));
|
||||||
|
$space = '';
|
||||||
|
$output = '';
|
||||||
|
$in_echo = false;
|
||||||
|
$doc_comment = false; // include only first /**
|
||||||
|
for (reset($tokens); list($i, $token) = each($tokens);) {
|
||||||
|
if (!is_array($token)) {
|
||||||
|
$token = array(0, $token);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$tokens[$i+2][0] === T_CLOSE_TAG && $tokens[$i+3][0] === T_INLINE_HTML && $tokens[$i+4][0] === T_OPEN_TAG
|
||||||
|
&& strlen(add_apo_slashes($tokens[$i+3][1])) < strlen($tokens[$i+3][1]) + 3
|
||||||
|
) {
|
||||||
|
$tokens[$i+2] = array(T_ECHO, 'echo');
|
||||||
|
$tokens[$i+3] = array(T_CONSTANT_ENCAPSED_STRING, "'" . add_apo_slashes($tokens[$i+3][1]) . "'");
|
||||||
|
$tokens[$i+4] = array(0, ';');
|
||||||
|
}
|
||||||
|
if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
|
||||||
|
$space = "\n";
|
||||||
|
} else {
|
||||||
|
if ($token[0] == T_DOC_COMMENT) {
|
||||||
|
$doc_comment = true;
|
||||||
|
}
|
||||||
|
if ($token[0] == T_VAR || $token[0] == T_PUBLIC || $token[0] == T_PROTECTED || $token[0] == T_PRIVATE) {
|
||||||
|
if ($token[0] == T_PUBLIC && $tokens[$i+2][1][0] == '$') {
|
||||||
|
$token[1] = 'var';
|
||||||
|
}
|
||||||
|
$shortening = false;
|
||||||
|
} elseif (!$shortening) {
|
||||||
|
if ($token[1] == ';' || $token[0] == T_FUNCTION) {
|
||||||
|
$shortening = true;
|
||||||
|
}
|
||||||
|
} elseif ($token[0] == T_ECHO) {
|
||||||
|
$in_echo = true;
|
||||||
|
} elseif ($token[1] == ';' && $in_echo) {
|
||||||
|
if ($tokens[$i+1][0] === T_WHITESPACE && $tokens[$i+2][0] === T_ECHO) {
|
||||||
|
next($tokens);
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
if ($tokens[$i+1][0] === T_ECHO) {
|
||||||
|
// join two consecutive echos
|
||||||
|
next($tokens);
|
||||||
|
$token[1] = ','; // '.' would conflict with "a".1+2 and would use more memory //! remove ',' and "," but not $var","
|
||||||
|
} else {
|
||||||
|
$in_echo = false;
|
||||||
|
}
|
||||||
|
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
|
||||||
|
$token[1] = '$' . $short_variables[$token[1]];
|
||||||
|
}
|
||||||
|
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
|
||||||
|
$space = '';
|
||||||
|
}
|
||||||
|
$output .= $space . $token[1];
|
||||||
|
$space = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function short_identifier($number, $chars) {
|
||||||
|
$return = '';
|
||||||
|
while ($number >= 0) {
|
||||||
|
$return .= $chars[$number % strlen($chars)];
|
||||||
|
$number = floor($number / strlen($chars)) - 1;
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_apo_slashes($s) {
|
||||||
|
return addcslashes($s, "\\'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists("each")) {
|
||||||
|
function each(&$arr) {
|
||||||
|
$key = key($arr);
|
||||||
|
next($arr);
|
||||||
|
return $key === null ? false : array($key, $arr[$key]);
|
||||||
|
}
|
||||||
|
}
|
23
tests/php_shrink.php
Normal file
23
tests/php_shrink.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
include __DIR__ . "/../adminer/include/errors.inc.php";
|
||||||
|
include __DIR__ . "/../php_shrink.inc.php";
|
||||||
|
|
||||||
|
function check($code, $expected) {
|
||||||
|
$shrinked = php_shrink("<?php\n$code");
|
||||||
|
if ("<?php\n" . str_replace(" ", "\n", $expected) . "" != $shrinked) {
|
||||||
|
$backtrace = reset(debug_backtrace());
|
||||||
|
echo "$backtrace[file]:$backtrace[line]:" . str_replace("\n", " ", substr($shrinked, 6)) . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check('$ab = 1;', '$a=1;');
|
||||||
|
check('function f($ab, $cd = 1) { return $ab; }', 'function f($a,$b=1){return$a;}');
|
||||||
|
check('class C { var $ab = 1; }', 'class C{var$ab=1;}');
|
||||||
|
check('class C { public $ab = 1; }', 'class C{var$ab=1;}');
|
||||||
|
check('class C { protected $ab = 1; }', 'class C{protected$ab=1;}');
|
||||||
|
check('class C { private $ab = 1; }', 'class C{private$ab=1;}');
|
||||||
|
check('class C { private $ab = 1; }', 'class C{private$ab=1;}');
|
||||||
|
check('class C { private function f($ab) { return $ab; }}', 'class C{private function f($a){return$a;}}');
|
||||||
|
check('class C { public function f($ab) { return $ab; }}', 'class C{function f($a){return$a;}}');
|
||||||
|
check('class C { private static $ab; }', 'class C{private static$ab;}');
|
||||||
|
check('new \stdClass;', 'new \stdClass;');
|
Reference in New Issue
Block a user