Make WordPress Core

Opened 5 years ago

Last modified 2 years ago

#48937 new enhancement

Auto-refresh maintenance mode screen

Reported by: paddy-landau's profile Paddy Landau Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Upgrade/Install Keywords: good-first-bug has-patch dev-feedback
Focuses: ui Cc:

Description

I already posted this on the community forums, and was advised to post here instead.

While WordPress updates a theme, a plugin or its core, it conveniently displays a message to any visitor:

Briefly unavailable for maintenance. Check back in a minute.

Unfortunately, when presented with such a bland screen, most visitors will immediately leave and find a different website.

If the visitor hasn’t disabled Javascript in his browser, it would be most helpful to make this a little more informative and add some automation:

Briefly unavailable for maintenance.
This page will automatically load when it is available.

Have the webpage automatically refresh the page every (say) 10 seconds.

Obviously, if the user has disabled Javascript, you can only display the brief message.

Solution

I’m not really a programmer, but I’ve taken the default WordPress method and modified it to do just this — see below. You are welcome to use it as is, or to use the ideas and code within, to implement this feature automatically. I have tested this and it seems to work perfectly. A programmer might find a better way to implement it than I have done.

There is one problem with what I’ve done, and that is the lack of translation for other languages. I don’t know how to cater for that.

Thank you

Revised contents

I took the file /wp-content/maintenance.php and modified it as follows. All that I did was to add a <script> section and modify the <div> section within the <body>. I changed nothing else.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" dir='ltr'>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<meta name="viewport" content="width=device-width">
			<title>Maintenance</title>
	<style type="text/css">
		html {
			background: #f1f1f1;
		}
		body {
			background: #fff;
			color: #444;
			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
			margin: 2em auto;
			padding: 1em 2em;
			max-width: 700px;
			-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.13);
			box-shadow: 0 1px 3px rgba(0, 0, 0, 0.13);
		}
		h1 {
			border-bottom: 1px solid #dadada;
			clear: both;
			color: #666;
			font-size: 24px;
			margin: 30px 0 0 0;
			padding: 0;
			padding-bottom: 7px;
		}
		#error-page {
			margin-top: 50px;
		}
		#error-page p,
		#error-page .wp-die-message {
			font-size: 14px;
			line-height: 1.5;
			margin: 25px 0 20px;
		}
		#error-page code {
			font-family: Consolas, Monaco, monospace;
		}
		ul li {
			margin-bottom: 10px;
			font-size: 14px ;
		}
		a {
			color: #0073aa;
		}
		a:hover,
		a:active {
			color: #00a0d2;
		}
		a:focus {
			color: #124964;
			-webkit-box-shadow:
				0 0 0 1px #5b9dd9,
				0 0 2px 1px rgba(30, 140, 190, 0.8);
			box-shadow:
				0 0 0 1px #5b9dd9,
				0 0 2px 1px rgba(30, 140, 190, 0.8);
			outline: none;
		}
		.button {
			background: #f7f7f7;
			border: 1px solid #ccc;
			color: #555;
			display: inline-block;
			text-decoration: none;
			font-size: 13px;
			line-height: 2;
			height: 28px;
			margin: 0;
			padding: 0 10px 1px;
			cursor: pointer;
			-webkit-border-radius: 3px;
			-webkit-appearance: none;
			border-radius: 3px;
			white-space: nowrap;
			-webkit-box-sizing: border-box;
			-moz-box-sizing:    border-box;
			box-sizing:         border-box;

			-webkit-box-shadow: 0 1px 0 #ccc;
			box-shadow: 0 1px 0 #ccc;
			vertical-align: top;
		}

		.button.button-large {
			height: 30px;
			line-height: 2.15384615;
			padding: 0 12px 2px;
		}

		.button:hover,
		.button:focus {
			background: #fafafa;
			border-color: #999;
			color: #23282d;
		}

		.button:focus {
			border-color: #5b9dd9;
			-webkit-box-shadow: 0 0 3px rgba(0, 115, 170, 0.8);
			box-shadow: 0 0 3px rgba(0, 115, 170, 0.8);
			outline: none;
		}

		.button:active {
			background: #eee;
			border-color: #999;
			-webkit-box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
			box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
		}

	</style>

	<script type='text/javascript'>
		// Return "sleep for a while".
		function sleep(ms)
		{
			return new Promise(resolve => setTimeout(resolve, ms));
		}

		// Sleep before doing refreshing.
		async function refreshAfterPause()
		{
			await sleep(100);			// Pause to allow the page to fully load.

			// Fill the relevant prompts, only if Javascript is enabled.
			document.getElementById('reload').innerHTML = 'This page will automatically reload when it is available.';
			document.getElementById('refresh').innerHTML = 'Waiting&hellip;';

			await sleep(5000);			// Wait 5 seconds.

			// Show that I'm about to check.
			document.getElementById('refresh').innerHTML = 'Checking&hellip;';

			await sleep(5000);			// Wait another 5 seconds.
			window.location.reload(true);		// Reload the page, not from the cache.
		}

		refreshAfterPause();				// Refresh the screen after a pause.
	</script>
</head>
<body id="error-page">
	<div class="wp-die-message">
		<p>Sorry&hellip; Briefly unavailable for scheduled maintenance.</p>
		<p id="reload">Please try again in a minute.</p>
		<p>Thank you for your patience.</p>
		<p id="refresh"></p>
	</div>
</body>
</html>

Attachments (5)

48937.diff (1.9 KB) - added by apieschel 5 years ago.
patch that implements proposed solution by checking for maintenance mode in the _default_wp_die_handler() function
48937.2.diff (2.2 KB) - added by apieschel 5 years ago.
adds i18n functions
48937.3.diff (2.2 KB) - added by apieschel 5 years ago.
deleted line added for testing
48937.4.diff (2.1 KB) - added by apieschel 5 years ago.
Rephrased "Will reload soon..." to "Checking again...". Changed "echo ()" lines to use the more succinct _e() function.
48937.patch (2.3 KB) - added by jdamner 2 years ago.
new patch with <progress> indicator and new wording

Download all attachments as: .zip

Change History (18)

#1 @johnbillion
5 years ago

  • Keywords needs-patch good-first-bug added
  • Milestone changed from Awaiting Review to Future Release
  • Version 5.3 deleted

Welcome to WordPress Trac @paddy-landau. I think this is a good idea.

@apieschel
5 years ago

patch that implements proposed solution by checking for maintenance mode in the _default_wp_die_handler() function

@apieschel
5 years ago

adds i18n functions

#2 @apieschel
5 years ago

  • Keywords has-patch added; needs-patch removed

@apieschel
5 years ago

deleted line added for testing

#3 @apieschel
5 years ago

I have added a patch that implements a slightly modified version of @paddy-landau 's original solution with the i18n functions. Since the maintenance mode HTML is displayed as a result of the wp_die() function being called, my original inclination was to modify wp_die() to check for maintenance mode and add a new custom _maintenance_wp_die_handler() in wp-includes/functions.php. However, this resulted in a lot of duplicate code, so I incorporated the check inside the _default_wp_die_handler() instead.

If anyone thinks I should add the custom die handler instead of modifying the default handler, or if I should do something completely different, please let me know!

For the check for maintenance mode itself, I imitated the check in the wp_maintenance() function in wp-includes/load.php, which uses the global $upgrading variable:

// If the $upgrading timestamp is older than 10 minutes, don't die.
if ( ( time() - $upgrading ) >= 600 ) {
	return;
}

The proposed patch does the reverse: check if the $upgrading timestamp is younger than 10 minutes, and if so, then it echoes the new maintenance-specific markup and script.

I am very new to this, so any feedback/suggestions/alternate approaches would be greatly appreciated!

Last edited 5 years ago by apieschel (previous) (diff)

#4 follow-up: @Paddy Landau
5 years ago

@apieschel — Thank you for this work!

I'd love to help out by testing the patch, but I have no idea how to go about it.

Is there a dummy's guide to incorporating the patch for testing?

#5 in reply to: ↑ 4 @apieschel
5 years ago

Replying to Paddy Landau:

@apieschel — Thank you for this work!

I'd love to help out by testing the patch, but I have no idea how to go about it.

Is there a dummy's guide to incorporating the patch for testing?

There is a guide https://make.wordpress.org/core/handbook/testing/patch/, though it requires some prior knowledge of setting up a local development environment, which is by no means intuitive. I can try to answer any questions you have though.

In terms of more informal, manual testing, another option would be to manually download a clean copy of WordPress, set up an install on a local server, and simply copy and paste the code to the relevant files.

To try it out, you would need to force maintenance mode by creating a file called ".maintenance." in the root directory (where wp-config.php lives), and add this line of code:

<?php $upgrading = time(); ?>
Last edited 5 years ago by apieschel (previous) (diff)

#6 @apieschel
5 years ago

Another question that just occurred to me for anyone out there: Would it be a better solution to just add a wp-content/maintenance.php template to core?

Last edited 5 years ago by apieschel (previous) (diff)

#7 @Paddy Landau
5 years ago

@apieschel — Thank you. I don't have a local development environment, so I manually changed the two files according to your 48937.3.diff (after making a suitable backup, of course).

The system seemed to work perfectly.

A couple of things…

  • I'm wondering if the wording, "Will reload soon…" is misleading. To the non-technical person, it sounds as though the website is running again. I would prefer something like "Will recheck soon" or even just "Rechecking…" Words like "loading" and "reload" are technical, and you'd be surprised how few laypeople know what it really means.
  • You asked, "Would it be a better solution to just add a wp-content/maintenance.php template to core?" Well, if the only language were English, yes, I'd agree, absolutely. But, from the little that I understand about WordPress, this doesn't allow for translations into other languages. Maybe it's possible to add the translation API directly into wp-content/maintenance.php? Unfortunately, I know nothing about how WordPress handles different languages.

Thank you again for your work!

@apieschel
5 years ago

Rephrased "Will reload soon..." to "Checking again...". Changed "echo ()" lines to use the more succinct _e() function.

#8 follow-up: @xkon
5 years ago

I like the idea a lot but do we really need all those messages?

Can't we simply keep a This page is automatically refreshed every ten seconds., in my opinion there's not much need of changing the text just to mention "waiting" or anything else.

If it's so important visually at least a standard refresh timer with a countdown could be a better choice but I'm not sure how OK that would be regarding accessibility, that's why I would just prefer a simple message that the page refreshes every X seconds, it's kind of a "statement" since we're already there :) .

Just my 2c!

#9 in reply to: ↑ 8 @apieschel
5 years ago

Replying to xkon:

I like the idea a lot but do we really need all those messages?

Can't we simply keep a This page is automatically refreshed every ten seconds., in my opinion there's not much need of changing the text just to mention "waiting" or anything else.

If it's so important visually at least a standard refresh timer with a countdown could be a better choice but I'm not sure how OK that would be regarding accessibility, that's why I would just prefer a simple message that the page refreshes every X seconds, it's kind of a "statement" since we're already there :) .

Just my 2c!

This is a good point, and I'm inclined to agree. @paddy-landau do you disagree?

#10 @Paddy Landau
5 years ago

My primary concern is for understanding on the part of non-technical people.

As long as it's absolutely clear what's going on, that's fine.

My standard is that if my father has to call me to ask what's going on and why isn't the website showing when it says that it will refresh in ten seconds, then the message isn't clear enough!

So, to merely say, "This page is automatically refreshed every ten seconds," doesn't fit the bill. For you and me, it's fine, because we understand what's going on and it seems blatantly obvious, but for a non-technical user, it's not at all obvious.

A agree that a visual counter would be nice, if easily doable and easily maintainable.

I'll leave it to you, now, and I repeat my thanks for your excellent work!

#11 @apieschel
5 years ago

  • Keywords dev-feedback added

This ticket was mentioned in Slack in #core-auto-updates by pbiron. View the logs.


4 years ago

@jdamner
2 years ago

new patch with <progress> indicator and new wording

#13 @jdamner
2 years ago

I've offered a patch with a <progress> indicator, since this is universally supported by browsers. I've used an indeterminate progress indicator since this is not a determined amount of time waiting for the maintenance mode to finish. Lastly, I've added a filter to set the polling period that the browser reloads the page to allow any concerns about traffic caused by automatic reloading to be configurable.

I'm not 100% sure about the wording I've chosen, but as a non-technical person having the words to say the page will reload it does not indicate wether the maintenance mode is over. Having the wording state that the page will automatically reload once maintenance mode is over is the actual 'effect' of this change for a non-technical user.

Note: See TracTickets for help on using tickets.