'no', 'mode' => 'soon', // soon | maintenance 'headline' => '', 'message' => '', 'logo' => '', 'bg' => '#f6f5f2', 'bg_image' => '', 'text' => '#1d1d1f', 'accent' => '#111111', 'end' => '', // Site-local Y-m-d\TH:i. Turns itself off after this. 'countdown' => 'yes', 'contact' => '', // Email shown on the page. 'staff_link' => 'yes', // Small "Staff login" link. 'noindex' => 'yes', // Coming soon: ask search engines not to index the page. 'roles' => array( 'administrator', 'shop_manager', 'editor' ), 'ips' => '', 'paths' => '', 'token' => '', ); } public function settings() { if ( null === $this->settings ) { $saved = get_option( self::OPTION, array() ); $this->settings = wp_parse_args( is_array( $saved ) ? $saved : array(), self::defaults() ); } return $this->settings; } public function init() { add_filter( 'bylt_settings_tabs', array( $this, 'settings_tab' ) ); add_action( 'bylt_settings_tab_maintenance', array( $this, 'render_settings' ) ); add_action( 'admin_post_bylt_maintenance_save', array( $this, 'save_settings' ) ); add_action( 'template_redirect', array( $this, 'gate' ), 0 ); add_action( 'admin_bar_menu', array( $this, 'admin_bar' ), 99 ); add_action( 'wp_enqueue_scripts', array( $this, 'admin_bar_css' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_bar_css' ) ); } /* --------------------------------------------------------------------- * State * ------------------------------------------------------------------- */ private function end_time() { $end = $this->settings()['end']; if ( ! $end ) { return 0; } try { $d = new DateTime( $end, wp_timezone() ); return $d->getTimestamp(); } catch ( Exception $e ) { return 0; } } /** On, and not past its end time. */ public function is_on() { if ( 'yes' !== $this->settings()['enabled'] ) { return false; } $end = $this->end_time(); return ! $end || time() < $end; } private function token() { return (string) $this->settings()['token']; } public function preview_url() { return $this->token() ? add_query_arg( 'bylt_preview', $this->token(), home_url( '/' ) ) : ''; } private function cookie_value() { return wp_hash( 'bylt_mm|' . $this->token() ); } /** Who sees the real site. */ public function can_bypass() { if ( is_user_logged_in() ) { $user = wp_get_current_user(); if ( array_intersect( (array) $user->roles, (array) $this->settings()['roles'] ) || is_super_admin() ) { return true; } } if ( Bylt_Ip::in_list( Bylt_Ip::client(), Bylt_Ip::parse_list( $this->settings()['ips'] ) ) ) { return true; } return $this->token() && isset( $_COOKIE[ self::COOKIE ] ) && hash_equals( $this->cookie_value(), sanitize_text_field( wp_unslash( $_COOKIE[ self::COOKIE ] ) ) ); } private static function path() { $uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/'; $path = (string) wp_parse_url( $uri, PHP_URL_PATH ); $home = (string) wp_parse_url( home_url( '/' ), PHP_URL_PATH ); return '/' . ltrim( substr( $path, strlen( rtrim( $home, '/' ) ) ), '/' ); } private function always_open() { if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) ) { return true; } // phpcs:ignore WordPress.Security.NonceVerification -- routing only. if ( isset( $_GET['wc-api'] ) || isset( $_GET['rest_route'] ) || is_robots() ) { return true; } $path = self::path(); if ( 0 === strpos( $path, '/wc-api/' ) || 0 === strpos( $path, '/' . rest_get_url_prefix() . '/' ) ) { return true; } foreach ( preg_split( '/\r\n|\r|\n/', (string) $this->settings()['paths'] ) as $p ) { $p = trim( $p ); if ( '' !== $p && 0 === strpos( $path, '/' . ltrim( $p, '/' ) ) ) { return true; } } return false; } /* --------------------------------------------------------------------- * Front end * ------------------------------------------------------------------- */ public function gate() { // Private preview link: remember this browser, then show the clean URL. // phpcs:disable WordPress.Security.NonceVerification -- the token is the check. if ( isset( $_GET['bylt_preview'] ) && $this->token() && hash_equals( $this->token(), sanitize_text_field( wp_unslash( $_GET['bylt_preview'] ) ) ) ) { setcookie( self::COOKIE, $this->cookie_value(), time() + WEEK_IN_SECONDS, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, is_ssl(), true ); $_COOKIE[ self::COOKIE ] = $this->cookie_value(); wp_safe_redirect( remove_query_arg( 'bylt_preview' ) ); exit; } // Staff can look at the page while it's off (Settings โ "See the page"). $peek = isset( $_GET['bylt_mm_peek'] ) && current_user_can( Bylt_Admin::cap() ); // phpcs:enable if ( ! $peek && ( ! $this->is_on() || $this->always_open() || $this->can_bypass() ) ) { return; } $this->render_page( $peek ); } private function render_page( $peek = false ) { $s = $this->settings(); $maint = 'maintenance' === $s['mode']; $end = $this->end_time(); $name = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ); $head = $s['headline'] ? $s['headline'] : ( $maint ? __( 'We\'ll be right back', 'byltcommerce-toolkit' ) : __( 'Coming soon', 'byltcommerce-toolkit' ) ); $msg = $s['message'] ? $s['message'] : ( $maint ? __( 'We\'re making some improvements. Please check back shortly.', 'byltcommerce-toolkit' ) : __( 'Our new site is almost ready. Check back soon.', 'byltcommerce-toolkit' ) ); nocache_headers(); if ( $maint && ! $peek ) { status_header( 503 ); header( 'Retry-After: ' . ( $end ? max( 60, $end - time() ) : HOUR_IN_SECONDS ) ); } else { status_header( 200 ); } if ( ( $maint || 'yes' === $s['noindex'] ) ) { header( 'X-Robots-Tag: noindex, nofollow' ); } header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) ); $logo = $s['logo']; if ( ! $logo ) { // The theme's logo. $id = (int) get_theme_mod( 'custom_logo' ); $id = $id ? $id : (int) get_option( 'site_logo' ); $logo = $id ? (string) wp_get_attachment_image_url( $id, 'medium' ) : ''; } $bg = $s['bg_image'] ? 'background:' . $s['bg'] . ' url(' . esc_url( $s['bg_image'] ) . ') center/cover no-repeat fixed;' : 'background:' . $s['bg'] . ';'; // This page skips the theme, so its own styles and script are printed directly (registered the WordPress way). wp_register_style( 'bylt-maintenance', $this->url( 'assets/maintenance.css' ), array(), BYLT_VERSION ); wp_add_inline_style( 'bylt-maintenance', 'body{' . esc_html( $bg ) . 'color:' . esc_html( $s['text'] ) . '}.bylt-mm-contact a{color:' . esc_html( $s['accent'] ) . '}' ); wp_register_script( 'bylt-maintenance-countdown', $this->url( 'assets/countdown.js' ), array(), BYLT_VERSION, true ); ?> >
' . esc_html__( 'Settings saved.', 'byltcommerce-toolkit' ) . '
' . esc_html( 'maintenance' === $s['mode'] ? __( 'Maintenance mode is on: visitors see the maintenance page.', 'byltcommerce-toolkit' ) : __( 'Coming soon mode is on: visitors see the coming soon page.', 'byltcommerce-toolkit' ) ) . '
' . esc_html__( 'The end time has passed, so the site is open again. Clear or change the end time to switch it back on.', 'byltcommerce-toolkit' ) . '