mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
84c650489a
We now include more polyfills than we have ever done, and some of these cause false-positives on our code to address modules which do not have a name. We started adding module names to modules in Moodle 3.8 at _build_ time and kept support for modules which were not transpiled using Babel before that point. We no longer need to support this as all pre-3.8 Moodle versions are long out of support. The most recent to go out of support was Moodle 3.5, which went completely out of support in May 2021. We should not support code written and minified without a transpilation phase from this time any longer.
171 lines
6.5 KiB
PHP
171 lines
6.5 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* This file is serving optimised JS for RequireJS.
|
|
*
|
|
* @package core
|
|
* @copyright 2015 Damyon Wiese
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
// Disable moodle specific debug messages and any errors in output,
|
|
// comment out when debugging or better look into error log!
|
|
define('NO_DEBUG_DISPLAY', true);
|
|
|
|
// We need just the values from config.php and minlib.php.
|
|
define('ABORT_AFTER_CONFIG', true);
|
|
require('../config.php'); // This stops immediately at the beginning of lib/setup.php.
|
|
require_once("$CFG->dirroot/lib/jslib.php");
|
|
require_once("$CFG->dirroot/lib/classes/requirejs.php");
|
|
|
|
$slashargument = min_get_slash_argument();
|
|
if (!$slashargument) {
|
|
// The above call to min_get_slash_argument should always work.
|
|
die('Invalid request');
|
|
}
|
|
|
|
$slashargument = ltrim($slashargument, '/');
|
|
if (substr_count($slashargument, '/') < 1) {
|
|
header('HTTP/1.0 404 not found');
|
|
die('Slash argument must contain both a revision and a file path');
|
|
}
|
|
// Split into revision and module name.
|
|
list($rev, $file) = explode('/', $slashargument, 2);
|
|
$rev = min_clean_param($rev, 'INT');
|
|
$file = '/' . min_clean_param($file, 'SAFEPATH');
|
|
|
|
// Only load js files from the js modules folder from the components.
|
|
$jsfiles = array();
|
|
list($unused, $component, $module) = explode('/', $file, 3);
|
|
|
|
// Use the caching only for meaningful revision numbers which prevents future cache poisoning.
|
|
if ($rev > 0 and $rev < (time() + 60 * 60)) {
|
|
// This is "production mode".
|
|
// Some (huge) modules are better loaded lazily (when they are used). If we are requesting
|
|
// one of these modules, only return the one module, not the combo.
|
|
$lazysuffix = "-lazy.js";
|
|
$lazyload = (strpos($module, $lazysuffix) !== false);
|
|
|
|
if ($lazyload) {
|
|
// We are lazy loading a single file - so include the component/filename pair in the etag.
|
|
$etag = sha1($rev . '/' . $component . '/' . $module);
|
|
} else {
|
|
// We loading all (non-lazy) files - so only the rev makes this request unique.
|
|
$etag = sha1($rev);
|
|
}
|
|
|
|
$candidate = $CFG->localcachedir . '/requirejs/' . $etag;
|
|
|
|
if (file_exists($candidate)) {
|
|
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
|
// We do not actually need to verify the etag value because our files
|
|
// never change in cache because we increment the rev parameter.
|
|
js_send_unmodified(filemtime($candidate), $etag);
|
|
}
|
|
js_send_cached($candidate, $etag, 'requirejs.php');
|
|
exit(0);
|
|
|
|
} else {
|
|
$jsfiles = array();
|
|
if ($lazyload) {
|
|
$jsfiles = core_requirejs::find_one_amd_module($component, $module);
|
|
} else {
|
|
// Here we respond to the request by returning ALL amd modules. This saves
|
|
// round trips in production.
|
|
|
|
$jsfiles = core_requirejs::find_all_amd_modules();
|
|
}
|
|
|
|
$content = '';
|
|
foreach ($jsfiles as $modulename => $jsfile) {
|
|
$js = file_get_contents($jsfile);
|
|
if ($js === false) {
|
|
error_log('Failed to load JavaScript file ' . $jsfile);
|
|
$js = "/* Failed to load JavaScript file {$jsfile}. */\n";
|
|
$content = $js . $content;
|
|
continue;
|
|
}
|
|
// Remove source map link.
|
|
$js = preg_replace('~//# sourceMappingURL.*$~s', '', $js);
|
|
$js = rtrim($js);
|
|
$js .= "\n";
|
|
|
|
if (!preg_match('/define\(\s*["\']/', $js)) {
|
|
$shortfilename = str_replace($CFG->dirroot, '', $jsfile);
|
|
error_log(
|
|
"JS file: '{$shortfilename}' cannot be loaded, or does not contain a javascript" .
|
|
' module in AMD format. "define()" not found.'
|
|
);
|
|
}
|
|
|
|
$content .= $js;
|
|
}
|
|
|
|
js_write_cache_file_content($candidate, $content);
|
|
// Verify nothing failed in cache file creation.
|
|
clearstatcache();
|
|
if (file_exists($candidate)) {
|
|
js_send_cached($candidate, $etag, 'requirejs.php');
|
|
exit(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we've made it here then we're in "dev mode" where everything is lazy loaded.
|
|
// So all files will be served one at a time.
|
|
$jsfiles = core_requirejs::find_one_amd_module($component, $module);
|
|
|
|
if (!empty($jsfiles)) {
|
|
$modulename = array_keys($jsfiles)[0];
|
|
$jsfile = $jsfiles[$modulename];
|
|
$shortfilename = str_replace($CFG->dirroot, '', $jsfile);
|
|
$mapfile = $jsfile . '.map';
|
|
|
|
if (file_exists($mapfile)) {
|
|
// We've got a a source map file so we can return the minified file here and
|
|
// the source map will be used by the browser to debug.
|
|
$js = file_get_contents($jsfile);
|
|
// Fix the source map link for the file.
|
|
$js = preg_replace(
|
|
'~//# sourceMappingURL.*$~s',
|
|
"//# sourceMappingURL={$CFG->wwwroot}/lib/jssourcemap.php{$file}",
|
|
$js
|
|
);
|
|
$js = rtrim($js);
|
|
} else {
|
|
// This file doesn't have a map file. We might be dealing with an older source file from
|
|
// a plugin or previous version of Moodle so we should just return the full original source
|
|
// like we used to.
|
|
$originalsource = str_replace('/amd/build/', '/amd/src/', $jsfile);
|
|
$originalsource = str_replace('.min.js', '.js', $originalsource);
|
|
$js = file_get_contents($originalsource);
|
|
$js = rtrim($js);
|
|
}
|
|
|
|
if (!preg_match('/define\(\s*["\']/', $js)) {
|
|
error_log(
|
|
"JS file: '{$shortfilename}' cannot be loaded, or does not contain a javascript" .
|
|
' module in AMD format. "define()" not found.'
|
|
);
|
|
}
|
|
|
|
js_send_uncached($js, 'requirejs.php');
|
|
} else {
|
|
// We can't find the requested file.
|
|
header('HTTP/1.0 404 not found');
|
|
}
|