132 lines
4.9 KiB
PHP
132 lines
4.9 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* Plugin Name: Sirius Press Bootstrap
|
||
|
|
* Description: Loads before everything else, so the parts of WordPress that run before plugins do — the installer, and core's pluggable notification functions — behave on a site with no email identity.
|
||
|
|
* Version: 0.1.0
|
||
|
|
* License: GPL-2.0-or-later
|
||
|
|
*
|
||
|
|
* @package SiriusPress
|
||
|
|
*
|
||
|
|
* ---------------------------------------------------------------------------
|
||
|
|
*
|
||
|
|
* Must-use plugins are loaded by `wp-settings.php` at a point where two useful
|
||
|
|
* things are still true: ordinary plugins have not loaded (so this runs during
|
||
|
|
* the installer, when they are skipped entirely), and `pluggable.php` has not
|
||
|
|
* been included yet (so functions declared here win over core's).
|
||
|
|
*
|
||
|
|
* Both properties are needed, and neither is available anywhere else:
|
||
|
|
*
|
||
|
|
* - The patched `wp-admin/install.php` calls two helpers that must exist
|
||
|
|
* before any plugin could have defined them.
|
||
|
|
* - Core's mail notifications are pluggable functions. Overriding them is the
|
||
|
|
* only way to stop the installer and the user system from handing messages
|
||
|
|
* to a mail transport that has nowhere to send them.
|
||
|
|
*
|
||
|
|
* This file is deliberately tiny and dependency-free. Anything that can wait
|
||
|
|
* for `plugins_loaded` belongs in Sirius Press Core instead.
|
||
|
|
*/
|
||
|
|
|
||
|
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
|
||
|
|
define( 'SIRIUS_PRESS_BOOTSTRAP', '0.1.0' );
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate and normalise an address typed into the installer.
|
||
|
|
*
|
||
|
|
* @param string $address
|
||
|
|
* @return string|false Normalised address, '' when blank, false when invalid.
|
||
|
|
*/
|
||
|
|
function sirius_press_install_address( $address ) {
|
||
|
|
$address = trim( (string) $address );
|
||
|
|
if ( '' === $address ) {
|
||
|
|
return '';
|
||
|
|
}
|
||
|
|
$class = WP_PLUGIN_DIR . '/sirius-press-core/includes/class-sp-cashaddr.php';
|
||
|
|
if ( ! class_exists( 'SP_CashAddr' ) && is_readable( $class ) ) {
|
||
|
|
require_once $class;
|
||
|
|
}
|
||
|
|
if ( ! class_exists( 'SP_CashAddr' ) ) {
|
||
|
|
// Core plugin not present. Refusing here would make the site
|
||
|
|
// uninstallable; accepting an unchecked string would attach an
|
||
|
|
// account to an address nobody can prove. Reject the value and let
|
||
|
|
// the operator install without one.
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
$normalised = SP_CashAddr::normalize( $address );
|
||
|
|
return '' === $normalised ? false : $normalised;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A permanently unroutable address for a user, derived from their wallet.
|
||
|
|
*
|
||
|
|
* `wp_install()` and `wp_insert_user()` both want an email string. They get
|
||
|
|
* one that RFC 2606 guarantees can never resolve.
|
||
|
|
*/
|
||
|
|
function sirius_press_install_stub_email( $address ) {
|
||
|
|
$tag = is_string( $address ) && '' !== $address
|
||
|
|
? substr( hash( 'sha256', $address ), 0, 16 )
|
||
|
|
: substr( hash( 'sha256', (string) wp_rand( 0, PHP_INT_MAX ) . microtime() ), 0, 16 );
|
||
|
|
return 'noreply+' . $tag . '@sirius-press.invalid';
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* ---------------------------------------------------------------------------
|
||
|
|
* Core notifications that have nowhere to go.
|
||
|
|
*
|
||
|
|
* These are declared before `pluggable.php` so core's versions never load.
|
||
|
|
* Each one exists in WordPress to email somebody about their own account;
|
||
|
|
* on a site where accounts have no mailbox, the message belongs in the
|
||
|
|
* in-app inbox, and where the inbox is not available yet (during install)
|
||
|
|
* it belongs nowhere at all.
|
||
|
|
*
|
||
|
|
* Deliberately NOT overridden: wp_mail() itself. Contact forms, order
|
||
|
|
* receipts and newsletters go to addresses real people supplied, and those
|
||
|
|
* must keep working for a site owner who has configured SMTP. Only the
|
||
|
|
* account-notification functions are replaced.
|
||
|
|
* ---------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
|
||
|
|
if ( ! function_exists( 'wp_new_blog_notification' ) ) {
|
||
|
|
/**
|
||
|
|
* Core mails the new administrator their own login URL and password.
|
||
|
|
*
|
||
|
|
* Suppressed: the person triggering it is looking at the screen that
|
||
|
|
* already shows both, and the address on file cannot receive mail.
|
||
|
|
*
|
||
|
|
* @param string $blog_title
|
||
|
|
* @param string $blog_url
|
||
|
|
* @param int $user_id
|
||
|
|
* @param string $password
|
||
|
|
*/
|
||
|
|
function wp_new_blog_notification( $blog_title, $blog_url, $user_id, $password ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames
|
||
|
|
// Nothing to send, and nothing to log — the installer's success page
|
||
|
|
// is the notification.
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( ! function_exists( 'wp_password_change_notification' ) ) {
|
||
|
|
/**
|
||
|
|
* Core mails every administrator when a user changes their password.
|
||
|
|
*
|
||
|
|
* Routed to the in-app inbox when it exists. During install it does not,
|
||
|
|
* and no password has changed anyway.
|
||
|
|
*
|
||
|
|
* @param WP_User $user
|
||
|
|
*/
|
||
|
|
function wp_password_change_notification( $user ) {
|
||
|
|
if ( ! class_exists( 'SP_Inbox' ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
SP_Inbox::add(
|
||
|
|
0,
|
||
|
|
__( 'A password was changed', 'sirius-press' ),
|
||
|
|
sprintf(
|
||
|
|
/* translators: %s: the user login whose password changed. */
|
||
|
|
esc_html__( 'The password for %s was changed. On this site passwords are a fallback, not the identity — the account is still controlled by its wallet.', 'sirius-press' ),
|
||
|
|
'<code>' . esc_html( $user->user_login ) . '</code>'
|
||
|
|
),
|
||
|
|
'core'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|