Luigi Cavalieri - Authoring Open Source Code

The 'db-error.php' Plugin

The 'db-error.php' plugin is a Drop-in Plugin that WordPress attempts to load whenever there is a problem connecting to the database, an example is given in this post.

The 'db-error.php' Plugin

In the WordPress jargon a Drop-in Plugin is a PHP script that replaces a functionality of WordPress, somehow becoming part of the core. In fact these special plugins don't need to be activated to be loaded, they just have to be dropped in the wp-content folder.

The db-error.php plugin is actually a Drop-in Plugin that WordPress attempts to load whenever there is a problem connecting to the database, giving us in this way the chance of showing a custom error page in place of the page carrying the message "Error establishing a database connection".

What follows is more or less the content of the db-error.php file I have written for this website:

1<?php
2/**
3 * Whenever there is a problem connecting to the database this Drop-in
4 * plugin shows to the visitor a custom error page and sends to your 
5 * inbox a notification about the insurrection.
6 *
7 * Version: 1.0
8 * 
9 * 
10 * Copyright 2020 Luigi Cavalieri.
11 * 
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 * 
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 * 
22 * You should have received a copy of the GNU General Public License
23 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 *
25 * *********************************************************************** */
26
27
28// Direct script access denied.
29if (! defined( 'ABSPATH' ) ) {
30    exit;
31}
32
33define( 'FROM_EMAIL_ADDRESS', 'your_admin@email.address' );
34define( 'TO_EMAIL_ADDRESS', 'your_private@email.address' );
35define( 'THIRTY_MINUTES', 1800 );
36
37session_start();
38
39$now = time();
40
41// Timestamp of the last email sent.
42// Used to limit the number of notifications 
43// sent via email.
44//
45// It is saved both to a text file 
46// and to a session variable, 
47// so that the text file is read only 
48// once per visit.
49$last_email_time = 0;
50
51// Full path to the text file 
52// where $last_email_time is saved.
53$timestamp_file_path = WP_CONTENT_DIR . '/db-error.txt';
54
55if (
56    isset( $_SESSION['last_email_time'] ) && 
57    is_int( $_SESSION['last_email_time'] ) 
58) {
59    $last_email_time = $_SESSION['last_email_time'];
60}
61else {
62    $last_email_time = (int) file_get_contents( $timestamp_file_path );
63    
64    $_SESSION['last_email_time'] = $last_email_time;
65}
66
67// Makes sure that the inbox doesn't catch fire.
68if ( ( $now - $last_email_time ) > THIRTY_MINUTES ) {
69    $email_subject = 'Database error';
70    $error_message = 'Database unreachable: ' . $_SERVER['REQUEST_URI'];
71    $extra_headers = 'From: ' . FROM_EMAIL_ADDRESS;
72    $email_sent    = mail(
73        TO_EMAIL_ADDRESS,
74        $email_subject,
75        $error_message,
76        $extra_headers
77    );
78
79    if ( $email_sent ) {
80        $_SESSION['last_email_time'] = $now;
81        
82        file_put_contents( $timestamp_file_path, $now );
83    }
84
85    error_log( $error_message );
86}
87
88// Some HTTP headers for search engines.
89header( 'HTTP/1.1 503 Service Temporarily Unavailable' );
90header( 'Status: 503 Service Temporarily Unavailable' );
91header( 'Retry-After: ' . THIRTY_MINUTES );
92
93// The database connection problem
94// might be only temporary.
95header( 'Refresh: 10' );
96
97?><!DOCTYPE html>
98<html>
99<head>
100<meta charset="UTF-8">
101
102<title>Error</title>
103</head>
104
105<body>
106    <p>A few lines for the visitor.</p>
107</body>
108</html>

How to Test it

There is more than one way of testing this plugin, but the most convenient I have found is to paste the following three-liner somewhere in the wp-config.php file:

1global $wpdb;
2
3$wpdb        = new stdClass();
4$wpdb->error = 'crash';

Hacky, but impermanent after all.