Merge pull request #13839 from nijel/scripts
Remove get_scripts wrapper to download javascript
This commit is contained in:
commit
7ec4059dbb
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,8 +32,6 @@ web.config
|
||||
/twig-templates/
|
||||
# Backups
|
||||
*~
|
||||
# Javascript line counts
|
||||
/js/line_counts.php
|
||||
# API documentation
|
||||
/apidoc/
|
||||
/doc/linkcheck/
|
||||
|
||||
@ -686,7 +686,7 @@ A list of files and corresponding functionality which degrade gracefully when re
|
||||
* :file:`./locale/` folder, or unused subfolders (interface translations)
|
||||
* Any unused themes in :file:`./themes/`
|
||||
* :file:`./js/vendor/jquery/src/` (included for licensing reasons)
|
||||
* :file:`./js/line_counts.php`
|
||||
* :file:`./js/line_counts.php` (removed in phpMyAdmin 4.8)
|
||||
* :file:`./doc/` (documentation)
|
||||
* :file:`./setup/` (setup script)
|
||||
* :file:`./examples/`
|
||||
|
||||
65
js/ajax.js
65
js/ajax.js
@ -534,9 +534,10 @@ var AJAX = {
|
||||
_scriptsToBeLoaded: [],
|
||||
/**
|
||||
* @var array _scriptsToBeFired The list of files for which
|
||||
* to fire the onload event
|
||||
* to fire the onload and unload events
|
||||
*/
|
||||
_scriptsToBeFired: [],
|
||||
_scriptsCompleted: false,
|
||||
/**
|
||||
* Records that a file has been downloaded
|
||||
*
|
||||
@ -572,7 +573,7 @@ var AJAX = {
|
||||
self._scripts = [];
|
||||
self._scriptsVersion = PMA_commonParams.get('PMA_VERSION');
|
||||
}
|
||||
self._scriptsToBeLoaded = [];
|
||||
self._scriptsCompleted = false;
|
||||
self._scriptsToBeFired = [];
|
||||
for (var i in files) {
|
||||
self._scriptsToBeLoaded.push(files[i].name);
|
||||
@ -580,64 +581,60 @@ var AJAX = {
|
||||
self._scriptsToBeFired.push(files[i].name);
|
||||
}
|
||||
}
|
||||
// Generate a request string
|
||||
var request = [];
|
||||
var needRequest = false;
|
||||
for (var index in self._scriptsToBeLoaded) {
|
||||
var script = self._scriptsToBeLoaded[index];
|
||||
for (var i in files) {
|
||||
var script = files[i].name;
|
||||
// Only for scripts that we don't already have
|
||||
if ($.inArray(script, self._scripts) === -1) {
|
||||
needRequest = true;
|
||||
this.add(script);
|
||||
request.push('scripts%5B%5D=' + script);
|
||||
if (request.length >= 10) {
|
||||
// Download scripts in chunks
|
||||
this.appendScript(request);
|
||||
request = [];
|
||||
needRequest = false;
|
||||
}
|
||||
this.appendScript(script, callback);
|
||||
} else {
|
||||
self.done(script, callback);
|
||||
}
|
||||
}
|
||||
request.push('call_done=1');
|
||||
request.push('v=' + encodeURIComponent(PMA_commonParams.get('PMA_VERSION')));
|
||||
// Download the composite js file, if necessary
|
||||
if (needRequest) {
|
||||
this.appendScript(request);
|
||||
} else {
|
||||
self.done(callback);
|
||||
}
|
||||
// Trigger callback if there is nothing to load
|
||||
self.done(null, callback);
|
||||
},
|
||||
/**
|
||||
* Called whenever all files are loaded
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
done: function (callback) {
|
||||
if ($.isFunction(callback)) {
|
||||
callback();
|
||||
}
|
||||
done: function (script, callback) {
|
||||
if (typeof ErrorReport !== 'undefined') {
|
||||
ErrorReport.wrap_global_functions();
|
||||
}
|
||||
for (var i in this._scriptsToBeFired) {
|
||||
AJAX.fireOnload(this._scriptsToBeFired[i]);
|
||||
if ($.inArray(script, this._scriptsToBeFired)) {
|
||||
AJAX.fireOnload(script);
|
||||
}
|
||||
if ($.inArray(script, this._scriptsToBeLoaded)) {
|
||||
this._scriptsToBeLoaded.splice($.inArray(script, this._scriptsToBeLoaded), 1);
|
||||
}
|
||||
if (script === null) {
|
||||
this._scriptsCompleted = true;
|
||||
}
|
||||
/* We need to wait for last signal (with null) or last script load */
|
||||
AJAX.active = (this._scriptsToBeLoaded.length > 0) || ! this._scriptsCompleted;
|
||||
/* Run callback on last script */
|
||||
if (! AJAX.active && $.isFunction(callback)) {
|
||||
callback();
|
||||
}
|
||||
AJAX.active = false;
|
||||
},
|
||||
/**
|
||||
* Appends a script element to the head to load the scripts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
appendScript: function (request) {
|
||||
appendScript: function (name, callback) {
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
var script = document.createElement('script');
|
||||
var self = this;
|
||||
|
||||
request.push('call_done=1');
|
||||
request.push('v=' + encodeURIComponent(PMA_commonParams.get('PMA_VERSION')));
|
||||
script.type = 'text/javascript';
|
||||
script.src = 'js/get_scripts.js.php?' + request.join('&');
|
||||
script.src = 'js/' + name + '?' + 'v=' + encodeURIComponent(PMA_commonParams.get('PMA_VERSION'));
|
||||
script.async = false;
|
||||
script.onload = function () {
|
||||
self.done(name, callback);
|
||||
};
|
||||
head.appendChild(script);
|
||||
},
|
||||
/**
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Concatenates several js files to reduce the number of
|
||||
* http requests sent to the server
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
if (! isset($_GET['scripts'])) {
|
||||
die('Missing parameter');
|
||||
}
|
||||
|
||||
if (!defined('TESTSUITE')) {
|
||||
chdir('..');
|
||||
|
||||
// Close session early as we won't write anything there
|
||||
session_write_close();
|
||||
|
||||
// Send correct type
|
||||
header('Content-Type: text/javascript; charset=UTF-8');
|
||||
// Enable browser cache for 1 hour
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
|
||||
|
||||
// When a token is not presented, even though whitelisted arrays are removed
|
||||
// in PMA_removeRequestVars(). This is a workaround for that.
|
||||
$_GET['scripts'] = json_encode($_GET['scripts']);
|
||||
|
||||
// Avoid loading the full common.inc.php because this would add many
|
||||
// non-js-compatible stuff like DOCTYPE
|
||||
define('PMA_MINIMUM_COMMON', true);
|
||||
define('PMA_PATH_TO_BASEDIR', '../');
|
||||
require_once './libraries/common.inc.php';
|
||||
}
|
||||
|
||||
$buffer = PhpMyAdmin\OutputBuffering::getInstance();
|
||||
$buffer->start();
|
||||
if (!defined('TESTSUITE')) {
|
||||
register_shutdown_function(
|
||||
function () {
|
||||
echo PhpMyAdmin\OutputBuffering::getInstance()->getContents();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$_GET['scripts'] = json_decode($_GET['scripts']);
|
||||
if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) {
|
||||
// Only up to 10 scripts as this is what we generate
|
||||
foreach (array_slice($_GET['scripts'], 0, 10) as $script) {
|
||||
// Sanitise filename
|
||||
$script_name = 'js';
|
||||
|
||||
$path = explode("/", $script);
|
||||
foreach ($path as $filename) {
|
||||
// Allow alphanumeric, "." and "-" chars only, no files starting
|
||||
// with .
|
||||
if (preg_match("@^[\w][\w\.-]+$@", $filename)) {
|
||||
$script_name .= DIRECTORY_SEPARATOR . $filename;
|
||||
}
|
||||
}
|
||||
|
||||
// Output file contents
|
||||
if (preg_match("@\.js$@", $script_name) && is_readable($script_name)) {
|
||||
readfile($script_name);
|
||||
echo ";\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['call_done'])) {
|
||||
echo "AJAX.scriptHandler.done();";
|
||||
}
|
||||
@ -119,6 +119,7 @@ class DatabaseStructureController extends DatabaseController
|
||||
array(
|
||||
'db_structure.js',
|
||||
'tbl_change.js',
|
||||
'vendor/jquery/jquery.validate.js',
|
||||
'vendor/jquery/jquery-ui-timepicker-addon.js'
|
||||
)
|
||||
);
|
||||
|
||||
@ -201,6 +201,7 @@ class TableSearchController extends TableController
|
||||
'sql.js',
|
||||
'tbl_select.js',
|
||||
'tbl_change.js',
|
||||
'vendor/jquery/jquery.validate.js',
|
||||
'vendor/jquery/jquery-ui-timepicker-addon.js',
|
||||
'vendor/jquery/jquery.uitablefilter.js',
|
||||
'gis_data_editor.js',
|
||||
@ -239,6 +240,7 @@ class TableSearchController extends TableController
|
||||
'vendor/jqplot/plugins/jqplot.highlighter.js',
|
||||
'vendor/jqplot/plugins/jqplot.cursor.js',
|
||||
'vendor/jquery/jquery-ui-timepicker-addon.js',
|
||||
'vendor/jquery/jquery.validate.js',
|
||||
'tbl_zoom_plot_jqplot.js',
|
||||
'tbl_change.js',
|
||||
)
|
||||
|
||||
@ -188,89 +188,6 @@ class ErrorReport
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of lines in given javascript file.
|
||||
*
|
||||
* @param string $filename javascript filename
|
||||
*
|
||||
* @return Number of lines
|
||||
*
|
||||
* @todo Should gracefully handle non existing files
|
||||
*/
|
||||
public static function countLines($filename)
|
||||
{
|
||||
/**
|
||||
* The generated file that contains the line numbers for the js files
|
||||
* If you change any of the js files you can run the scripts/line-counts.sh
|
||||
*/
|
||||
if (is_readable('js/line_counts.php')) {
|
||||
include_once 'js/line_counts.php';
|
||||
}
|
||||
|
||||
global $LINE_COUNT;
|
||||
if (defined('LINE_COUNTS')) {
|
||||
return $LINE_COUNT[$filename];
|
||||
}
|
||||
|
||||
// ensure that the file is inside the phpMyAdmin folder
|
||||
$depath = 1;
|
||||
foreach (explode('/', $filename) as $part) {
|
||||
if ($part == '..') {
|
||||
$depath--;
|
||||
} elseif ($part != '.' || $part === '') {
|
||||
$depath++;
|
||||
}
|
||||
if ($depath < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
$linecount = 0;
|
||||
$handle = fopen('./js/' . $filename, 'r');
|
||||
while (!feof($handle)) {
|
||||
$line = fgets($handle);
|
||||
if ($line === false) {
|
||||
break;
|
||||
}
|
||||
$linecount++;
|
||||
}
|
||||
fclose($handle);
|
||||
return $linecount;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the translated line number and the file name from the cumulative line
|
||||
* number and an array of files
|
||||
*
|
||||
* uses the $LINE_COUNT global array of file names and line numbers
|
||||
*
|
||||
* @param array $filenames list of files in order of concatenation
|
||||
* @param Integer $cumulative_number the cumulative line number in the
|
||||
* concatenated files
|
||||
*
|
||||
* @return array the filename and line number
|
||||
* Returns two variables in an array:
|
||||
* - A String $filename the filename where the requested cumulative number
|
||||
* exists
|
||||
* - Integer $linenumber the translated line number in the returned file
|
||||
*/
|
||||
public static function getLineNumber(array $filenames, $cumulative_number)
|
||||
{
|
||||
$cumulative_sum = 0;
|
||||
foreach ($filenames as $filename) {
|
||||
$filecount = self::countLines($filename);
|
||||
if ($cumulative_number <= $cumulative_sum + $filecount + 2) {
|
||||
$linenumber = $cumulative_number - $cumulative_sum;
|
||||
break;
|
||||
}
|
||||
$cumulative_sum += $filecount + 2;
|
||||
}
|
||||
if (! isset($filename)) {
|
||||
$filename = '';
|
||||
}
|
||||
return array($filename, $linenumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* translates the cumulative line numbers in the stack trace as well as sanitize
|
||||
* urls and trim long lines in the context
|
||||
@ -287,19 +204,10 @@ class ErrorReport
|
||||
$line = mb_substr($line, 0, 75) . "//...";
|
||||
}
|
||||
}
|
||||
if (preg_match("<js/get_scripts.js.php\?(.*)>", $level["url"], $matches)) {
|
||||
parse_str($matches[1], $vars);
|
||||
List($file_name, $line_number) = self::getLineNumber(
|
||||
$vars["scripts"], $level["line"]
|
||||
);
|
||||
$level["filename"] = $file_name;
|
||||
$level["line"] = $line_number;
|
||||
} else {
|
||||
unset($level["context"]);
|
||||
List($uri, $script_name) = self::sanitizeUrl($level["url"]);
|
||||
$level["uri"] = $uri;
|
||||
$level["scriptname"] = $script_name;
|
||||
}
|
||||
unset($level["context"]);
|
||||
List($uri, $script_name) = self::sanitizeUrl($level["url"]);
|
||||
$level["uri"] = $uri;
|
||||
$level["scriptname"] = $script_name;
|
||||
unset($level["url"]);
|
||||
}
|
||||
unset($level);
|
||||
|
||||
@ -184,7 +184,7 @@ class Header
|
||||
// Here would not be a good place to add CodeMirror because
|
||||
// the user preferences have not been merged at this point
|
||||
|
||||
$this->_scripts->addFile('messages.php', false, array('l' => $GLOBALS['lang']));
|
||||
$this->_scripts->addFile('messages.php', array('l' => $GLOBALS['lang']));
|
||||
// Append the theme id to this url to invalidate
|
||||
// the cache on a theme change. Though this might be
|
||||
// unavailable for fatal errors.
|
||||
|
||||
@ -1871,6 +1871,9 @@ class InsertEdit
|
||||
$response = Response::getInstance();
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('vendor/jquery/jquery-ui-timepicker-addon.js');
|
||||
$scripts->addFile('vendor/jquery/jquery.validate.js');
|
||||
$scripts->addFile('vendor/jquery/additional-methods.js');
|
||||
$scripts->addFile('tbl_change.js');
|
||||
if (!defined('TESTSUITE')) {
|
||||
include 'tbl_change.php';
|
||||
|
||||
@ -44,42 +44,19 @@ class Scripts
|
||||
*/
|
||||
private function _includeFiles(array $files)
|
||||
{
|
||||
$first = [];
|
||||
$result = [];
|
||||
$scripts = array();
|
||||
$separator = Url::getArgSeparator();
|
||||
$result = '';
|
||||
foreach ($files as $value) {
|
||||
if (strpos($value['filename'], ".php") !== false) {
|
||||
$file_name = $value['filename'] . Url::getCommon($value['params'] + array('v' => PMA_VERSION));
|
||||
if ($value['before_statics'] === true) {
|
||||
$first[]
|
||||
= "<script data-cfasync='false' type='text/javascript' "
|
||||
. "src='js/" . $file_name . "'></script>";
|
||||
} else {
|
||||
$result[] = "<script data-cfasync='false' "
|
||||
. "type='text/javascript' src='js/" . $file_name
|
||||
. "'></script>";
|
||||
}
|
||||
$result .= "<script data-cfasync='false' "
|
||||
. "type='text/javascript' src='js/" . $file_name
|
||||
. "'></script>\n";
|
||||
} else {
|
||||
$scripts[] = "scripts%5B%5D=" . $value['filename'];
|
||||
$result .= '<script data-cfasync="false" type="text/javascript" src="js/'
|
||||
. $value['filename'] . '?' . Header::getVersionParameter() . '"></script>' . "\n";
|
||||
}
|
||||
}
|
||||
$separator = Url::getArgSeparator();
|
||||
// Using chunks of 10 files to avoid too long URLs
|
||||
// as some servers are set to 512 bytes URL limit
|
||||
$script_chunks = array_chunk($scripts, 10);
|
||||
foreach ($script_chunks as $script_chunk) {
|
||||
$url = 'js/get_scripts.js.php?'
|
||||
. implode($separator, $script_chunk)
|
||||
. $separator . Header::getVersionParameter();
|
||||
|
||||
$result[] = sprintf(
|
||||
'<script data-cfasync="false" type="text/javascript" src="%s">' .
|
||||
'</script>',
|
||||
htmlspecialchars($url)
|
||||
);
|
||||
}
|
||||
return implode("\n", $first) . implode("\n", $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,15 +74,12 @@ class Scripts
|
||||
* Adds a new file to the list of scripts
|
||||
*
|
||||
* @param string $filename The name of the file to include
|
||||
* @param bool $before_statics Whether this dynamic script should be
|
||||
* included before the static ones
|
||||
* @param array $params Additional parameters to pass to the file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addFile(
|
||||
$filename,
|
||||
$before_statics = false,
|
||||
array $params = array()
|
||||
) {
|
||||
$hash = md5($filename);
|
||||
@ -118,7 +92,6 @@ class Scripts
|
||||
'has_onload' => $has_onload,
|
||||
'filename' => $filename,
|
||||
'params' => $params,
|
||||
'before_statics' => $before_statics
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Do not run as CGI
|
||||
if [ -n "$GATEWAY_INTERFACE" ] ; then
|
||||
echo 'Can not invoke as CGI!'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > js/line_counts.php <<EOF
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* An autogenerated file that stores the line counts of javascript files
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
define('LINE_COUNTS', true);
|
||||
\$LINE_COUNT = array();
|
||||
EOF
|
||||
|
||||
php_code=""
|
||||
for file in `find js -name '*.js'` ; do
|
||||
lc=`wc -l $file | sed 's/\([0-9]*\).*/\1/'`
|
||||
file=${file:3}
|
||||
entry="\$LINE_COUNT['$file'] = $lc;"
|
||||
php_code="$php_code\n$entry"
|
||||
done
|
||||
echo -e $php_code >> js/line_counts.php
|
||||
@ -454,6 +454,9 @@ if (! empty($return_to_sql_query)) {
|
||||
$GLOBALS['sql_query'] = $return_to_sql_query;
|
||||
}
|
||||
|
||||
$scripts->addFile('vendor/jquery/jquery-ui-timepicker-addon.js');
|
||||
$scripts->addFile('vendor/jquery/jquery.validate.js');
|
||||
$scripts->addFile('vendor/jquery/additional-methods.js');
|
||||
$scripts->addFile('tbl_change.js');
|
||||
|
||||
$active_page = $goto_include;
|
||||
|
||||
@ -1842,7 +1842,7 @@ class InsertEditTest extends TestCase
|
||||
->setMethods(array('addFile'))
|
||||
->getMock();
|
||||
|
||||
$scriptsMock->expects($this->once())
|
||||
$scriptsMock->expects($this->exactly(4))
|
||||
->method('addFile');
|
||||
|
||||
$headerMock = $this->getMockBuilder('PhpMyAdmin\Header')
|
||||
|
||||
@ -77,8 +77,7 @@ class ScriptsTest extends PmaTestCase
|
||||
{
|
||||
$this->assertEquals(
|
||||
'<script data-cfasync="false" type="text/javascript" '
|
||||
. 'src="js/get_scripts.js.php?'
|
||||
. 'scripts%5B%5D=common.js&v=' . PMA_VERSION . '"></script>',
|
||||
. 'src="js/common.js?v=' . PMA_VERSION . '"></script>' . "\n",
|
||||
$this->_callPrivateFunction(
|
||||
'_includeFiles',
|
||||
array(
|
||||
@ -105,8 +104,7 @@ class ScriptsTest extends PmaTestCase
|
||||
|
||||
$this->assertRegExp(
|
||||
'@<script data-cfasync="false" type="text/javascript" '
|
||||
. 'src="js/get_scripts.js.php\\?'
|
||||
. 'scripts%5B%5D=common.js&v=' . PMA_VERSION . '"></script>'
|
||||
. 'src="js/common.js\?v=' . PMA_VERSION . '"></script>' . "\n"
|
||||
. '<script data-cfasync="false" type="text/'
|
||||
. 'javascript">// <!\\[CDATA\\[' . "\n"
|
||||
. 'AJAX.scriptHandler.add\\("common.js",1\\);' . "\n"
|
||||
@ -180,7 +178,6 @@ $(function() {});
|
||||
$hash => array(
|
||||
'has_onload' => 1,
|
||||
'filename' => 'common.js',
|
||||
'before_statics' => false,
|
||||
'params' => array(),
|
||||
)
|
||||
);
|
||||
@ -209,13 +206,11 @@ $(function() {});
|
||||
'd7716810d825f4b55d18727c3ccb24e6' => array(
|
||||
'has_onload' => 1,
|
||||
'filename' => 'common.js',
|
||||
'before_statics' => false,
|
||||
'params' => array(),
|
||||
),
|
||||
'347a57484fcd6ea6d8a125e6e1d31f78' => array(
|
||||
'has_onload' => 1,
|
||||
'filename' => 'sql.js',
|
||||
'before_statics' => false,
|
||||
'params' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
@ -68,7 +68,6 @@ class FilesTest extends TestCase
|
||||
return array(
|
||||
array('js/whitelist.php', 'var PMA_gotoWhitelist'),
|
||||
array('js/messages.php', 'var PMA_messages = new Array();'),
|
||||
array('js/get_scripts.js.php', 'var AJAX'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user