Il Plugin `db-error.php`

Nel gergo di WordPress un Plugin Drop-in è uno script PHP che sostituisce una funzionalità di WordPress, diventando in qualche modo parte del core. Infatti questi speciali plugin non hanno bisogno di essere attivati perché vengano caricati, basta farli cadere nella cartella wp-content.

Il plugin db-error.php è un Drop-in che WordPress prova a caricare ogni qualvolta si presenta un problema di connessione al database, dandoci così la possibilità di mostrare una pagina d'errore personalizzata in luogo della pagina che sfoggia il messaggio Errore nello stabilire una connessione al database.

Quanto segue è più o meno il contenuto del file db-error.php che ho scritto per questo sito web:

<?php
/**
 * Ogni volta che si presenta un problema di connessione al database
 * questo Plugin Drop-in mostra al visitatore una pagina di errore 
 * personalizzata ed invia alla tua inbox una notifica riguardo
 * l'insurrezione.
 *
 * Version: 1.0
 * 
 * 
 * Copyright 2020 Luigi Cavalieri.
 * 
 * This program 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.
 * 
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * *********************************************************************** */


// Accesso diretto allo script non concesso.
if (! defined( 'ABSPATH' ) ) {
    exit;
}

define( 'FROM_EMAIL_ADDRESS', 'your_admin@email.address' );
define( 'TO_EMAIL_ADDRESS', 'your_private@email.address' );
define( 'THIRTY_MINUTES', 1800 );

session_start();

$now = time();

// Timestamp dell'ultima email inviata.
// Usato per limitare il numero di notifiche inviate via email.
//
// Viene salvato sia in un file di testo che in una variabile di
// sessione, in modo che il file venga letto una sola volta per visita.
$last_email_time = 0;

// Path completo al file di testo in cui viene salvato $last_email_time.
$timestamp_file_path = WP_CONTENT_DIR . '/db-error.txt';

if (
    isset( $_SESSION['last_email_time'] ) && 
    is_int( $_SESSION['last_email_time'] ) 
) {
    $last_email_time = $_SESSION['last_email_time'];
}
else {
    $last_email_time = (int) file_get_contents( $timestamp_file_path );
    
    $_SESSION['last_email_time'] = $last_email_time;
}

// Si assicura che l'inbox non prenda fuoco.
if ( ( $now - $last_email_time ) > THIRTY_MINUTES ) {
    $email_subject = 'Database error';
    $error_message = 'Database unreachable: ' . $_SERVER['REQUEST_URI'];
    $extra_headers = 'From: ' . FROM_EMAIL_ADDRESS;
    $email_sent    = mail(
        TO_EMAIL_ADDRESS,
        $email_subject,
        $error_message,
        $extra_headers
    );

    if ( $mail_sent ) {
        $_SESSION['last_email_time'] = $now;
        
        file_put_contents( $timestamp_file_path, $now );
    }

    error_log( $error_message );
}

// Qualche header HTTP per i motori di ricerca.
header( 'HTTP/1.1 503 Service Temporarily Unavailable' );
header( 'Status: 503 Service Temporarily Unavailable' );
header( 'Retry-After: ' . THIRTY_MINUTES );

// Il problema di connessione al database potrebbe essere solo temporaneo.
header( 'Refresh: 10' );

?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

<title>Errore</title>
</head>

<body>
    <p>Qualche righa per il visitatore.</p>
</body>
</html>

Come Testarlo

C'è più di un modo per testare questo plugin, ma quello più pratico che ho trovato è l'incollare le seguenti tre linee di codice da qualche parte nel file wp-config.php:

global $wpdb;

$wpdb        = new stdClass();
$wpdb->error = 'crash';

È un hackeraggio, ma impermanente dopo tutto.