Merge branch 'MDL-79276-master' of https://github.com/raortegar/moodle

This commit is contained in:
Andrew Nicols 2023-10-05 08:55:14 +08:00
commit 805ebbb434
No known key found for this signature in database
GPG Key ID: 6D1E3157C8CFBF14
3 changed files with 61 additions and 22 deletions

View File

@ -195,7 +195,7 @@ class core_shutdown_manager {
* Standard shutdown sequence.
*/
protected static function request_shutdown() {
global $CFG, $OUTPUT;
global $CFG, $OUTPUT, $PERF;
// Help apache server if possible.
$apachereleasemem = false;
@ -216,14 +216,9 @@ class core_shutdown_manager {
$perf = get_performance_info();
error_log("PERF: " . $perf['txt']);
}
if (MDL_PERFTOFOOT || debugging() || (!empty($CFG->perfdebug) && $CFG->perfdebug > 7)) {
if (NO_OUTPUT_BUFFERING) {
// If the performance footer was deferred then print it now.
if (!CLI_SCRIPT && !WS_SERVER) {
$perf = get_performance_info();
echo $OUTPUT->select_element_for_replace('#perfdebugfooter', $perf['html']);
}
}
if (!empty($PERF->perfdebugdeferred)) {
$perf = get_performance_info();
echo $OUTPUT->select_element_for_replace('#perfdebugfooter', $perf['html']);
}
if (MDL_PERFINC) {
$inc = get_included_files();
@ -244,5 +239,15 @@ class core_shutdown_manager {
}
}
}
// Close the current streaming element if any.
if ($OUTPUT->has_started()) {
echo $OUTPUT->close_element_for_append();
}
// Print any closing buffered tags.
if (!empty($CFG->closingtags)) {
echo $CFG->closingtags;
}
}
}

View File

@ -600,6 +600,12 @@ class core_renderer extends renderer_base {
/** @var custom_menu_item language The language menu if created */
protected $language = null;
/** @var string The current selector for an element being streamed into */
protected $currentselector = '';
/** @var string The current element tag which is being streamed into */
protected $currentelement = '';
/**
* Constructor
*
@ -1489,7 +1495,7 @@ class core_renderer extends renderer_base {
* @return string HTML fragment
*/
public function footer() {
global $CFG, $DB;
global $CFG, $DB, $PERF;
$output = '';
@ -1519,6 +1525,7 @@ class core_renderer extends renderer_base {
if (NO_OUTPUT_BUFFERING) {
// If the output buffer was off then we render a placeholder and stream the
// performance debugging into it at the very end in the shutdown handler.
$PERF->perfdebugdeferred = true;
$performanceinfo .= html_writer::tag('div',
get_string('perfdebugdeferred', 'admin'),
[
@ -1549,6 +1556,20 @@ class core_renderer extends renderer_base {
$this->page->set_state(moodle_page::STATE_DONE);
// Here we remove the closing body and html tags and store them to be added back
// in the shutdown handler so we can have valid html with streaming script tags
// which are rendered after the visible footer.
$tags = '';
preg_match('#\<\/body>#i', $footer, $matches);
$tags .= $matches[0];
$footer = str_replace($matches[0], '', $footer);
preg_match('#\<\/html>#i', $footer, $matches);
$tags .= $matches[0];
$footer = str_replace($matches[0], '', $footer);
$CFG->closingtags = $tags;
return $output . $footer;
}
@ -5213,36 +5234,46 @@ EOD;
*
* @param string $selector where new content should be appended
* @param string $element which contains the streamed content
* @return string html to be written
*/
public function select_element_for_append(string $selector = '#region-main [role=main]', string $element = 'div') {
static $currentselector = '';
static $currentelement = '';
if (!CLI_SCRIPT && !NO_OUTPUT_BUFFERING) {
throw new coding_exception('select_element_for_append used in a non-CLI script without setting NO_OUTPUT_BUFFERING.',
DEBUG_DEVELOPER);
}
// We are already streaming into this element so don't change anything.
if ($currentselector === $selector && $currentelement === $element) {
if ($this->currentselector === $selector && $this->currentelement === $element) {
return;
}
$html = '';
// If we have a streaming element close it before starting a new one.
$html = $this->close_element_for_append();
// We have a streaming element so close it before starting a new one.
if ($currentselector !== '') {
$html .= html_writer::end_tag($currentelement);
}
$currentselector = $selector;
$currentelement = $element;
$this->currentselector = $selector;
$this->currentelement = $element;
// Create an unclosed element for the streamed content to append into.
$id = uniqid();
$html .= html_writer::start_tag($element, ['id' => $id]);
$html .= html_writer::tag('script', "document.querySelector('$selector').append(document.getElementById('$id'))");
$html .= "\n";
return $html;
}
/**
* This closes any opened stream elements
*
* @return string html to be written
*/
public function close_element_for_append() {
$html = '';
if ($this->currentselector !== '') {
$html .= html_writer::end_tag($this->currentelement);
$html .= "\n";
$this->currentelement = '';
}
return $html;
}
@ -5259,6 +5290,7 @@ EOD;
* @param string $selector where new content should be replaced
* @param string $html A chunk of well formed html
* @param bool $outer Wether it replaces the innerHTML or the outerHTML
* @return string html to be written
*/
public function select_element_for_replace(string $selector, string $html, bool $outer = false) {
@ -5271,6 +5303,7 @@ EOD;
$html = addslashes_js($html);
$property = $outer ? 'outerHTML' : 'innerHTML';
$output = html_writer::tag('script', "document.querySelector('$selector').$property = '$html';");
$output .= "\n";
return $output;
}
}

View File

@ -21,6 +21,7 @@
* @copyright 2019 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_OUTPUT_BUFFERING', true);
require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/adminlib.php');