PluginProbe
FrontBlocks Site Tools / trunk
FrontBlocks Site Tools vtrunk
1.5.3 1.5.2 1.5.1 1.4.0 1.5.0 trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 All 28 releases
frontblocks / includes / Frontend / Maintenance.php

Maintenance.php in FrontBlocks Site Tools trunk, at includes/Frontend/Maintenance.php

169 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Maintenance Mode module for FrontBlocks.
4 *
5 * @package FrontBlocks
6 * @author Closemarketing
7 * @copyright 2025 Closemarketing
8 * @version 1.0
9 */
10
11 namespace FrontBlocks\Frontend;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * Maintenance class.
17 *
18 * @since 1.0.0
19 */
20 class Maintenance {
21
22 /**
23 * Constructor.
24 */
25 public function __construct() {
26 // Only intercept the frontend if maintenance mode is enabled.
27 if ( ! is_admin() && $this->is_enabled() ) {
28 add_action( 'template_redirect', array( $this, 'maybe_render_maintenance_page' ) );
29 }
30
31 // Flag maintenance mode in the admin bar (front and back office) so admins don't forget it's on.
32 if ( $this->is_enabled() ) {
33 add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_node' ), 999 );
34 }
35 }
36
37 /**
38 * Add a visible "Maintenance: ON" node to the admin bar.
39 *
40 * @param \WP_Admin_Bar $wp_admin_bar Admin bar instance.
41 * @return void
42 */
43 public function add_admin_bar_node( $wp_admin_bar ) {
44 if ( ! current_user_can( 'manage_options' ) ) {
45 return;
46 }
47
48 $wp_admin_bar->add_node(
49 array(
50 'id' => 'frbl-maintenance-status',
51 'title' => '<span style="background:#d63638;color:#fff;padding:2px 8px;border-radius:3px;font-weight:600;">' . esc_html__( 'Maintenance: ON', 'frontblocks' ) . '</span>',
52 'href' => admin_url( 'themes.php?page=frontblocks-settings' ),
53 'meta' => array(
54 'title' => esc_attr__( 'Maintenance mode is currently enabled. Click to manage it.', 'frontblocks' ),
55 ),
56 )
57 );
58 }
59
60 /**
61 * Check if maintenance mode is enabled.
62 *
63 * @return bool
64 */
65 private function is_enabled() {
66 $options = get_option( 'frontblocks_settings', array() );
67 return (bool) ( $options['enable_maintenance'] ?? false );
68 }
69
70 /**
71 * Render the maintenance curtain page and stop further execution,
72 * unless the current request should be allowed through.
73 *
74 * @return void
75 */
76 public function maybe_render_maintenance_page() {
77 if ( $this->should_bypass() ) {
78 return;
79 }
80
81 $this->render_maintenance_page();
82 exit;
83 }
84
85 /**
86 * Determine whether the current request should bypass the maintenance page.
87 *
88 * @return bool
89 */
90 private function should_bypass() {
91 // Never intercept AJAX, cron or REST requests.
92 if ( wp_doing_ajax() || wp_doing_cron() ) {
93 return true;
94 }
95
96 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
97 return true;
98 }
99
100 if ( is_customize_preview() ) {
101 return true;
102 }
103
104 // Let logged-in administrators browse the real site to be able to turn the mode off.
105 if ( current_user_can( 'manage_options' ) ) {
106 return true;
107 }
108
109 return false;
110 }
111
112 /**
113 * Output the maintenance curtain page.
114 *
115 * @return void
116 */
117 private function render_maintenance_page() {
118 $options = get_option( 'frontblocks_settings', array() );
119 $title = trim( (string) ( $options['maintenance_title'] ?? '' ) );
120 $image_id = (int) ( $options['maintenance_image'] ?? 0 );
121 $image_url = $image_id ? wp_get_attachment_image_url( $image_id, 'full' ) : '';
122
123 if ( '' === $title ) {
124 $title = __( 'We are currently performing maintenance', 'frontblocks' );
125 }
126
127 status_header( 503 );
128 header( 'Retry-After: 3600' );
129 nocache_headers();
130 ?>
131 <!DOCTYPE html>
132 <html <?php language_attributes(); ?>>
133 <head>
134 <meta charset="<?php bloginfo( 'charset' ); ?>">
135 <meta name="viewport" content="width=device-width, initial-scale=1">
136 <meta name="robots" content="noindex, nofollow">
137 <title><?php echo esc_html( $title ); ?></title>
138 <style><?php echo $this->get_maintenance_css(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></style>
139 </head>
140 <body class="frbl-maintenance-body">
141 <div class="frbl-maintenance-overlay" <?php echo $image_url ? 'style="background-image: url(\'' . esc_url( $image_url ) . '\');"' : ''; ?>>
142 <div class="frbl-maintenance-content">
143 <h1 class="frbl-maintenance-title"><?php echo esc_html( $title ); ?></h1>
144 </div>
145 </div>
146 </body>
147 </html>
148 <?php
149 }
150
151 /**
152 * Read the maintenance page CSS to inline it.
153 *
154 * There is no theme/template context on this page (we bypass wp_head/wp_footer
155 * entirely), so the stylesheet is inlined instead of enqueued.
156 *
157 * @return string
158 */
159 private function get_maintenance_css() {
160 $css_path = FRBL_PLUGIN_PATH . 'assets/maintenance/frontblocks-maintenance.css';
161
162 if ( ! file_exists( $css_path ) ) {
163 return '';
164 }
165
166 return file_get_contents( $css_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
167 }
168 }
169