Animations.php
3 months ago
BackButton.php
9 months ago
BeforeAfter.php
3 months ago
BlockPatterns.php
6 months ago
Carousel.php
2 months ago
ColumnsSameHeight.php
2 months ago
ContainerEdgeAlignment.php
1 week ago
CookieNotice.php
5 days ago
Counter.php
3 months ago
DownloadButton.php
2 months ago
Events.php
2 months ago
FaqSchema.php
2 months ago
FluidTypography.php
2 months ago
Gallery.php
1 week ago
GravityFormsInline.php
3 months ago
Headline.php
2 months ago
InsertPost.php
3 months ago
Maintenance.php
1 week ago
ProductCategories.php
2 months ago
ReadingProgress.php
9 months ago
ReadingTime.php
1 week ago
ScrollTop.php
1 week ago
ShapeAnimations.php
1 week ago
StackedImages.php
6 months ago
StickyColumn.php
2 months ago
SvgUpload.php
2 months ago
Testimonials.php
10 months ago
TextAnimation.php
3 months ago
UserText.php
2 months ago
Maintenance.php
169 lines
| 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 |