WordPress.org

Make WordPress Core

Opened 6 weeks ago

Last modified 5 days ago

#48937 new enhancement

Auto-refresh maintenance mode screen

Reported by: 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:
PR Number:

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 (4)

48937.diff (1.9 KB) - added by apieschel 7 days 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 7 days ago.
adds i18n functions
48937.3.diff (2.2 KB) - added by apieschel 7 days ago.
deleted line added for testing
48937.4.diff (2.1 KB) - added by apieschel 6 days ago.
Rephrased "Will reload soon..." to "Checking again...". Changed "echo ()" lines to use the more succinct _e() function.

Download all attachments as: .zip

Change History (15)

#1 @johnbillion
6 weeks 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
7 days ago

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

@apieschel
7 days ago

adds i18n functions

#2 @apieschel
7 days ago

  • Keywords has-patch added; needs-patch removed

@apieschel
7 days ago

deleted line added for testing

#3 @apieschel
7 days 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 7 days ago by apieschel (previous) (diff)

#4 follow-up: @Paddy Landau
6 days 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
6 days 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 6 days ago by apieschel (previous) (diff)

#6 @apieschel
6 days 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 6 days ago by apieschel (previous) (diff)

#7 @Paddy Landau
6 days 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
6 days ago

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

#8 follow-up: @xkon
6 days 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
6 days 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 days 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 days ago

  • Keywords dev-feedback added
Note: See TracTickets for help on using tickets.