' . esc_html__( 'Settings', '1001web-maintenance-launch-pages' ) . ''; array_unshift( $links, $settings_link ); return $links; } /** * Injection CSS minimale pour contraindre l'icône menu sidebar et masquer * le logo header sur fond orange. */ public static function inject_admin_css_fix() { $handle = self::inline_handle(); if ('' === $handle) { return; } wp_add_inline_style($handle, self::get_admin_menu_css()); } /** * CSS correctif du menu admin (icône + logo d'en-tête). * * @return string */ protected static function get_admin_menu_css() { return ' /* Force la taille 20x20 sur l\'icone du menu du plugin, quel que soit le PNG fourni a add_menu_page(). */ #toplevel_page_mgenius-settings .wp-menu-image img, #toplevel_page_mgenius-settings .wp-menu-image.svg img { width: 20px !important; height: 20px !important; max-width: 20px !important; max-height: 20px !important; padding: 6px 0 0 !important; opacity: 0.9; } #toplevel_page_mgenius-settings:hover .wp-menu-image img, #toplevel_page_mgenius-settings.current .wp-menu-image img, #toplevel_page_mgenius-settings.wp-has-current-submenu .wp-menu-image img { opacity: 1; } '; } /** * CSS des widgets du tableau de bord. * * Les widgets sont rendus après admin_enqueue_scripts : y appeler * wp_add_inline_style() serait sans effet. Le style est donc enfilé ici, * uniquement sur l'écran du tableau de bord. * * @param string $hook Écran courant. * @return void */ public static function enqueue_dashboard_widget_css($hook) { if ('index.php' !== $hook) { return; } $handle = self::inline_handle(); if ('' === $handle) { return; } wp_add_inline_style($handle, ' /* Widget MG Core branding refined : - Outline orange brand 4 côtés (#F97316) ; overflow masque les coins carres du pied de page sous le coin arrondi (8px) - Dot vert (ON) / gris (OFF) — convention switch WP - Pulse 5%↔100% pour signaler maintenance ACTIVE - Footer avec version pour debug/support */ #mgenius_dashboard_widget { border: 1px solid #F97316 !important; overflow: hidden; } #mgenius_dashboard_widget .inside { padding: 0 !important; margin: 0 !important; } .mg-dwc { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } .mg-dwc-header { display: flex; align-items: center; gap: 12px; padding: 16px; border-bottom: 1px solid #e5e7eb; } .mg-dwc-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; } .mg-dwc-dot.live { background: #d1d5db; } .mg-dwc-dot.maintenance { background: #22c55e; box-shadow: 0 0 8px rgba(34,197,94,.7); animation: mg-pulse-strong 1.6s ease-in-out infinite; } @keyframes mg-pulse-strong { 0%,100% { opacity:1; } 50% { opacity:.05; } } .mg-dwc-status { flex: 1; } .mg-dwc-status-text { font-size: 14px; font-weight: 600; color: #1f2937; line-height: 1.2; } .mg-dwc-status-sub { font-size: 12px; color: #6b7280; margin-top: 2px; } .mg-dwc-grid { display: grid; grid-template-columns: 1fr 1fr; border-bottom: 1px solid #e5e7eb; } .mg-dwc-cell { padding: 12px 16px; } .mg-dwc-cell + .mg-dwc-cell { border-left: 1px solid #e5e7eb; } .mg-dwc-label { font-size: 10px; color: #9ca3af; text-transform: uppercase; letter-spacing: .6px; font-weight: 600; } .mg-dwc-value { font-size: 18px; color: #111827; font-weight: 700; margin-top: 4px; } .mg-dwc-value-sub { font-size: 11px; color: #6b7280; font-weight: 400; } .mg-dwc-info { padding: 10px 16px; font-size: 12px; color: #4b5563; border-bottom: 1px solid #e5e7eb; background: #fafafa; } .mg-dwc-info strong { color: #F97316; } .mg-dwc-actions { display: flex; gap: 8px; padding: 12px 16px; } .mg-dwc-btn { flex: 1; text-align: center; padding: 8px 10px; font-size: 12px; font-weight: 600; text-decoration: none; border-radius: 4px; transition: opacity .15s; } .mg-dwc-btn:hover { opacity: .85; } .mg-dwc-btn-primary { background: #F97316; color: #fff !important; } .mg-dwc-btn-secondary { background: #f3f4f6; color: #374151 !important; border: 1px solid #e5e7eb; } .mg-dwc-footer { padding: 6px 16px; border-top: 1px solid #f3f4f6; display: flex; justify-content: space-between; align-items: center; font-size: 10px; color: #9ca3af; background: #fafafa; } .mg-dwc-footer a { color: #F97316; text-decoration: none; font-weight: 500; } .mg-dwc-footer a:hover { text-decoration: underline; } '); } /** * Initialisation frontend uniquement: admin bar + toggle */ public static function init_admin_bar() { add_action('admin_bar_menu', [__CLASS__, 'add_admin_bar_menu'], 999); add_action('wp_enqueue_scripts', [__CLASS__, 'admin_bar_toggle_assets']); } /** * Corriger le type MIME pour les fichiers JSON et Lottie */ public static function fix_json_mime_type($data, $file, $filename, $mimes, $real_mime = '') { if (!empty($data['ext']) && !empty($data['type'])) { return $data; } $filetype = wp_check_filetype($filename, $mimes); // JSON only: WordPress often sees it as text/plain, and its content is // checked by upload_lottie() (valid JSON with a Lottie structure). A // .lottie file is a ZIP archive that WordPress recognizes by its // content: its verdict is no longer overridden from the name alone. if ($filetype['ext'] === 'json') { $data['ext'] = 'json'; $data['type'] = 'application/json'; } return $data; } /** * Ajoute le menu et sous-menus dans l'admin WordPress */ public static function add_menu() { // Fallback SVG monochrome si PNG manquant. WordPress affiche l'URL directement. $icon_url = MGENIUS_PLUGIN_URL . 'assets/images/mg-icon-256.png'; $icon_path = MGENIUS_PLUGIN_DIR . 'assets/images/mg-icon-256.png'; if ( ! file_exists( $icon_path ) ) { $icon_url = MGENIUS_PLUGIN_URL . 'assets/images/mg-icon.svg'; } add_menu_page( '1001Web Maintenance & Launch Pages', '1001Web Maintenance', 'manage_options', 'mgenius-settings', [__CLASS__, 'render_page'], $icon_url, 100 ); // Sous-menu "Paramètres" — remplace le doublon WP auto add_submenu_page( 'mgenius-settings', __('Settings', '1001web-maintenance-launch-pages'), '⚙️ ' . __('Settings', '1001web-maintenance-launch-pages'), 'manage_options', 'mgenius-settings' ); // Sous-menu "Aperçu" — JS intercepte pour ouvrir en nouvel onglet add_submenu_page( 'mgenius-settings', __('Preview', '1001web-maintenance-launch-pages'), '👁 ' . __('Preview', '1001web-maintenance-launch-pages'), 'manage_options', 'mgenius-preview-redirect', '__return_null' ); // Sous-menu "Activer/Désactiver" — JS intercepte pour AJAX toggle $settings = MGENIUS_Settings::load(); $is_active = ! empty( $settings['maintenance_enabled'] ); $toggle_label = $is_active ? '❌ ' . __('Disable', '1001web-maintenance-launch-pages') : '✅ ' . __('Enable', '1001web-maintenance-launch-pages'); add_submenu_page( 'mgenius-settings', __('Toggle maintenance', '1001web-maintenance-launch-pages'), '' . $toggle_label . '', 'manage_options', 'mgenius-toggle-redirect', '__return_null' ); } /** * JS pour sous-menus sidebar : Aperçu (nouvel onglet) + Toggle (AJAX) */ public static function sidebar_submenu_js() { if ( ! current_user_can('manage_options') ) { return; } $preview_url = home_url( '/?mgenius_preview=1&_wpnonce=' . wp_create_nonce('mgenius_preview') ); $settings = MGENIUS_Settings::load(); $is_active = ! empty( $settings['maintenance_enabled'] ) ? 1 : 0; // JS du sous-menu : fichier statique, donnees passees en JSON. wp_enqueue_script( 'mgenius-admin-sidebar', MGENIUS_PLUGIN_URL . 'assets/js/admin-sidebar.js', array(), MGENIUS_VERSION, true ); wp_add_inline_script( 'mgenius-admin-sidebar', 'var mgeniusSidebar = ' . wp_json_encode( array( 'previewUrl' => $preview_url, 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'mgenius_nonce' ), 'enabled' => (bool) $is_active, 'i18n' => array( 'disable' => __( 'Disable', '1001web-maintenance-launch-pages' ), 'enable' => __( 'Enable', '1001web-maintenance-launch-pages' ), 'on' => _x( 'ON', 'maintenance status', '1001web-maintenance-launch-pages' ), 'off' => _x( 'OFF', 'maintenance status', '1001web-maintenance-launch-pages' ), 'maintActive' => __( 'Maintenance Active', '1001web-maintenance-launch-pages' ), 'siteLive' => __( 'Site Live', '1001web-maintenance-launch-pages' ), 'visitorsSee' => __( 'Visitors see your maintenance page', '1001web-maintenance-launch-pages' ), 'maintOff' => __( 'Maintenance mode is OFF', '1001web-maintenance-launch-pages' ), 'confirmEnable' => __( 'Turn on maintenance mode? Your visitors will no longer see your normal site until you turn it off.', '1001web-maintenance-launch-pages' ), ), ) ) . ';', 'before' ); } /** * Charge les assets CSS/JS pour l'admin */ public static function enqueue_assets($hook) { if ($hook !== 'toplevel_page_mgenius-settings') { return; } wp_enqueue_style('wp-color-picker'); wp_enqueue_script('wp-color-picker'); wp_enqueue_media(); wp_enqueue_script('jquery'); // Version + date du fichier : évite le CSS admin fantôme après une mise à jour sans changement de version. $mgenius_css_path = MGENIUS_PLUGIN_DIR . 'assets/css/admin.css'; $mgenius_css_ver = file_exists( $mgenius_css_path ) ? MGENIUS_VERSION . '.' . filemtime( $mgenius_css_path ) : MGENIUS_VERSION; wp_enqueue_style( 'mgenius-admin-css', MGENIUS_PLUGIN_URL . 'assets/css/admin.css', [], $mgenius_css_ver ); $mgenius_js_path = MGENIUS_PLUGIN_DIR . 'assets/js/admin.js'; $mgenius_js_ver = file_exists( $mgenius_js_path ) ? MGENIUS_VERSION . '.' . filemtime( $mgenius_js_path ) : MGENIUS_VERSION; wp_enqueue_script( 'mgenius-admin-js', MGENIUS_PLUGIN_URL . 'assets/js/admin.js', ['jquery', 'wp-color-picker', 'wp-i18n'], $mgenius_js_ver, true ); wp_set_script_translations('mgenius-admin-js', '1001web-maintenance-launch-pages'); // CSS de l'assistant d'installation : enfilé plutôt qu'écrit dans le // template, qui est rendu après admin_enqueue_scripts. if (!get_option('mgenius_wizard_completed', false)) { wp_add_inline_style('mgenius-admin-css', '@keyframes mg-rocket-flame { 0%,100%{text-shadow:0 0 8px #ff6b35,0 0 16px #ff4500;transform:scale(1)} 50%{text-shadow:0 0 16px #ff6b35,0 0 32px #ff4500,0 0 48px #ff0;transform:scale(1.15)} } @keyframes mg-rocket-launch { 0%{transform:translateY(0) rotate(0)} 30%{transform:translateY(-8px) rotate(-5deg)} 60%{transform:translateY(-20px) rotate(-15deg)} 100%{transform:translateY(-60px) rotate(-25deg);opacity:0} } @keyframes mg-rocket-shake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-2px)} 75%{transform:translateX(2px)} } .mg-wiz-tip{display:flex;align-items:flex-start;gap:8px;background:#f0f4ff;border:1px solid #d4deff;border-radius:8px;padding:10px 14px;margin-bottom:20px;font-size:13px;color:#4a5568;line-height:1.4} .mg-wiz-tip-icon{flex-shrink:0;font-size:16px} #mg-wiz-rocket{position:absolute;top:-18px;transition:left 0.5s cubic-bezier(0.34,1.56,0.64,1);z-index:2;width:28px;height:28px} #mg-wiz-rocket.launched .mg-rocket-flame{opacity:1;animation:mg-rocket-flame 0.3s ease infinite} #mg-wiz-rocket.launched{animation:mg-rocket-shake 0.1s ease infinite} #mg-wiz-rocket.liftoff{animation:mg-rocket-launch 0.8s ease forwards} .mg-rocket-flame{opacity:0;transition:opacity 0.2s}'); } wp_localize_script('mgenius-admin-js', 'mgeniusAdmin', [ 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('mgenius_nonce'), 'preview_url' => home_url('/?mgenius_preview=1&_wpnonce=' . wp_create_nonce('mgenius_preview')), 'version' => MGENIUS_VERSION, 'lottie_player_url' => MGENIUS_PLUGIN_URL . 'assets/js/vendor/dotlottie/dotlottie-player.mjs?ver=' . MGENIUS_VERSION, // Fin du compte a rebours (ms) : l'ecran se resynchronise a cette heure-la. 'countdown_end' => self::countdown_end_ms(), // Decalage du fuseau du site (s) : les champs du compte a rebours sont en heure du site. 'tz_offset' => (int) wp_timezone()->getOffset(new DateTime('now')), // v2.9.174 — une infobulle sur chaque réglage (injectée par admin.js). // v2.9.175 — une infobulle sur chaque titre de section. 'section_tips' => [ '#tab-general h2' => __('Turn maintenance on or off, choose the page mode, and write what visitors read.', '1001web-maintenance-launch-pages'), '.mg-health-card-title' => __('After maintenance, the plugin compares your key pages with how they looked before. It flags any page that returns an error or lost more than half of its content.', '1001web-maintenance-launch-pages'), '.mg-mode-selector-label' => __('Maintenance: visitors get HTTP 503, so search engines wait and come back later. Coming Soon: HTTP 200 with noindex, for a site that is not launched yet.', '1001web-maintenance-launch-pages'), '#tab-design h2' => __('Colors, fonts, background and animations of the page visitors see. Use Preview to check the result.', '1001web-maintenance-launch-pages'), '.mg-styles-title' => __('The same styles as in the setup wizard. A style changes the colors and the background photo; your fonts and logo stay as they are. To change fonts and animations too, switch to Expert: Complete layouts.', '1001web-maintenance-launch-pages'), '.mg-bg-unified-title' => __('A color gradient, your own image or a ready-made photo behind the page. A dark veil over the photo keeps the text readable.', '1001web-maintenance-launch-pages'), '#tab-access h2' => __('Who can see the real site during maintenance: a shared visitor password, personal access links, allowed and blocked addresses.', '1001web-maintenance-launch-pages'), '#tab-seo h2' => __('Search engine and technical options. Most sites can keep the defaults.', '1001web-maintenance-launch-pages'), '#tab-diagnostic h2' => __('Checks run from your server to confirm that visitors get the maintenance page and that nothing in your setup blocks it.', '1001web-maintenance-launch-pages'), '.mg-needhelp-title' => __('A short guided form. A technical report (versions, theme, plugins, diagnostic) is attached so we can answer without asking for it.', '1001web-maintenance-launch-pages'), '#tab-help h2' => __('Answers to common questions, and the system details to share if you contact support.', '1001web-maintenance-launch-pages'), '.mg-kb-title' => __('Search the answers by keyword, or open a category.', '1001web-maintenance-launch-pages'), ], 'tips' => [ 'mg-show-admin-button' => __('Shows a link to the WordPress login page on the maintenance page. Leave it off if you use a hidden login address.', '1001web-maintenance-launch-pages'), 'mg-schedule-enabled' => __('Turns maintenance on and off by itself at the dates and times below. Choose both a start and an end.', '1001web-maintenance-launch-pages'), 'mg-schedule-start-date' => __('The day maintenance turns on by itself.', '1001web-maintenance-launch-pages'), 'mg-schedule-start-time' => __('The time maintenance turns on, in the time zone shown above.', '1001web-maintenance-launch-pages'), 'mg-schedule-end-date' => __('The day maintenance turns off by itself.', '1001web-maintenance-launch-pages'), 'mg-schedule-end-time' => __('The time maintenance turns off. The countdown, if shown, counts down to this moment.', '1001web-maintenance-launch-pages'), 'mg-notification-enabled' => __('Adds a form where visitors leave their email. They receive one message when the site is back online.', '1001web-maintenance-launch-pages'), 'mg-notification-button-text' => __('The text of the button visitors click to be notified.', '1001web-maintenance-launch-pages'), 'mg-notification-success-msg' => __('The message shown after a visitor leaves their email.', '1001web-maintenance-launch-pages'), 'mg-countdown-enabled' => __('Shows the time left until the site is back. Useful when you know when you will be done.', '1001web-maintenance-launch-pages'), 'mg-countdown-title' => __('The short line shown above the countdown, for example "Back in".', '1001web-maintenance-launch-pages'), 'mg-countdown-end-text' => __('The message shown when the countdown reaches zero.', '1001web-maintenance-launch-pages'), 'mg-countdown-style' => __('How the numbers look: boxes, minimal or circles. Try them with Preview.', '1001web-maintenance-launch-pages'), 'mg-countdown-show-days' => __('Untick to hide the days, for example when you will be back the same day.', '1001web-maintenance-launch-pages'), 'mg-countdown-show-hours' => __('Untick to hide the hours.', '1001web-maintenance-launch-pages'), 'mg-countdown-show-minutes' => __('Untick to hide the minutes.', '1001web-maintenance-launch-pages'), 'mg-countdown-show-seconds' => __('Untick to hide the seconds for a calmer display.', '1001web-maintenance-launch-pages'), 'mg-countdown-auto-disable' => __('At zero, maintenance turns off by itself and the site reopens. Untick it if you prefer to reopen the site yourself.', '1001web-maintenance-launch-pages'), 'mg-logo-size' => __('The width of your logo on the maintenance page, in pixels.', '1001web-maintenance-launch-pages'), 'mg-bg-color-1' => __('The first color of the background gradient.', '1001web-maintenance-launch-pages'), 'mg-bg-color-2' => __('The second color of the background gradient. Use the same color twice for a plain background.', '1001web-maintenance-launch-pages'), 'mg-title-color' => __('The color of the main title.', '1001web-maintenance-launch-pages'), 'mg-message-color' => __('The color of the message under the title.', '1001web-maintenance-launch-pages'), 'mg-button-color' => __('The color of the buttons (Visitor access, Notify me).', '1001web-maintenance-launch-pages'), 'mg-bg-image-enabled' => __('Shows your own photo or image behind the page. Tick it, then choose an image.', '1001web-maintenance-launch-pages'), 'mg-container-bg-color' => __('The color of the card that holds the title and the message.', '1001web-maintenance-launch-pages'), 'mg-container-shadow' => __('Adds a soft shadow under the card so it stands out from the background.', '1001web-maintenance-launch-pages'), 'mg-title-font' => __('The font of the main title. All fonts are included in the plugin: nothing is loaded from Google.', '1001web-maintenance-launch-pages'), 'mg-message-font' => __('The font of the message. All fonts are included in the plugin.', '1001web-maintenance-launch-pages'), 'mg-title-size' => __('The size of the main title, in pixels. It shrinks by itself on small screens.', '1001web-maintenance-launch-pages'), 'mg-message-size' => __('The size of the message, in pixels.', '1001web-maintenance-launch-pages'), 'mg-animation-enabled' => __('Lets the logo, the text and the buttons appear with a short animation. Visitors who prefer less motion see no animation.', '1001web-maintenance-launch-pages'), 'mg-logo-animation' => __('How the logo appears.', '1001web-maintenance-launch-pages'), 'mg-text-animation' => __('How the title and the message appear.', '1001web-maintenance-launch-pages'), 'mg-button-animation' => __('How the buttons appear.', '1001web-maintenance-launch-pages'), 'mg-lottie-enabled' => __('Shows a light animation (Lottie format) on the page, from a file or a web address.', '1001web-maintenance-launch-pages'), 'mg-lottie-url-input' => __('The address of a Lottie animation (.json or .lottie). It is loaded from that site, unless GDPR mode is on.', '1001web-maintenance-launch-pages'), 'mg-lottie-position' => __('Where the animation is placed on the page.', '1001web-maintenance-launch-pages'), 'mg-lottie-size' => __('The size of the animation, in pixels.', '1001web-maintenance-launch-pages'), 'mg-lottie-offset-x' => __('Moves the animation left or right.', '1001web-maintenance-launch-pages'), 'mg-lottie-offset-y' => __('Moves the animation up or down.', '1001web-maintenance-launch-pages'), 'mg-lottie-speed' => __('Plays the animation slower or faster.', '1001web-maintenance-launch-pages'), 'mg-lottie-loop' => __('Plays the animation again and again.', '1001web-maintenance-launch-pages'), 'mg-lottie-autoplay' => __('Starts the animation as soon as the page opens.', '1001web-maintenance-launch-pages'), 'mg-video-bg-enabled' => __('Plays a muted YouTube or Vimeo video behind the page. The video is loaded from that service.', '1001web-maintenance-launch-pages'), 'mg-video-bg-opacity' => __('How visible the video is behind the page. Lower keeps the text easier to read.', '1001web-maintenance-launch-pages'), 'mg-video-bg-muted' => __('Keeps the video silent. Browsers block videos that start with sound.', '1001web-maintenance-launch-pages'), 'mg-parallax-enabled' => __('Moves the background slightly when the mouse moves, for a sense of depth.', '1001web-maintenance-launch-pages'), 'mg-parallax-intensity' => __('How much the background moves.', '1001web-maintenance-launch-pages'), 'mg-sidebar-enabled' => __('Adds a small side tab with your social networks and contact details. It only appears if at least one is filled in.', '1001web-maintenance-launch-pages'), 'mg-sidebar-position' => __('The side of the screen where the tab appears.', '1001web-maintenance-launch-pages'), 'mg-sidebar-tab-color' => __('The color of the side tab.', '1001web-maintenance-launch-pages'), 'mg-social-facebook' => __('The full address of your Facebook page. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-social-twitter' => __('The full address of your X (Twitter) profile. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-social-instagram' => __('The full address of your Instagram profile. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-social-linkedin' => __('The full address of your LinkedIn page. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-social-youtube' => __('The full address of your YouTube channel. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-social-tiktok' => __('The full address of your TikTok profile. Leave empty to hide it.', '1001web-maintenance-launch-pages'), 'mg-contact-email' => __('An email address visitors can write to while the site is closed.', '1001web-maintenance-launch-pages'), 'mg-contact-phone' => __('A phone number visitors can call while the site is closed.', '1001web-maintenance-launch-pages'), 'mg-contact-whatsapp' => __('A WhatsApp number, with the country code (for example 15145550100). It opens WhatsApp when clicked.', '1001web-maintenance-launch-pages'), 'mg-preset-name' => __('Give a name to your current design to reuse it later, here or on another site (export).', '1001web-maintenance-launch-pages'), 'mg-visitor-access' => __('Lets the people you choose see the real site with a password, while everyone else sees the maintenance page.', '1001web-maintenance-launch-pages'), 'mg-visitor-password' => __('The password to share with your clients or collaborators. It is stored as a secure hash, never as plain text.', '1001web-maintenance-launch-pages'), 'mg-clear-visitor-password' => __('Deletes the stored password. Visitor access then needs a new password.', '1001web-maintenance-launch-pages'), 'mg-visitor-duration' => __('How long a visitor stays signed in after entering the password.', '1001web-maintenance-launch-pages'), 'mg-visitor-custom-days' => __('A custom number of days for the visitor access.', '1001web-maintenance-launch-pages'), 'mg-new-token-name' => __('A name to recognize this link later, for example the client\'s name.', '1001web-maintenance-launch-pages'), 'mg-new-token-duration' => __('How long the link works. After that, it stops working by itself.', '1001web-maintenance-launch-pages'), 'mg-turnstile-enabled' => __('Adds a free Cloudflare Turnstile check to stop robots on the password and email forms. It needs your Cloudflare keys.', '1001web-maintenance-launch-pages'), 'mg-turnstile-on-notification' => __('Checks for robots on the "Notify me" form.', '1001web-maintenance-launch-pages'), 'mg-turnstile-on-visitor' => __('Checks for robots on the visitor password form.', '1001web-maintenance-launch-pages'), 'mg-stats-enabled' => __('Counts the visits to the maintenance page. Nothing leaves your site.', '1001web-maintenance-launch-pages'), 'mg-whitelist-enabled' => __('Lets some pages, addresses or roles see the real site during maintenance.', '1001web-maintenance-launch-pages'), 'mg-whitelist-urls' => __('Pages that stay open to everyone, one per line (for example /contact).', '1001web-maintenance-launch-pages'), 'mg-whitelist-ips' => __('IP addresses that see the real site, one per line. Wildcards (192.168.*) and ranges (192.168.0.0/24) work.', '1001web-maintenance-launch-pages'), 'mg-whitelist-user-agents' => __('Browsers or tools allowed by name, one per line (at least 3 characters). A name is easy to fake: use it only for testing.', '1001web-maintenance-launch-pages'), 'mg-blacklist-enabled' => __('Blocks the addresses or tools below, even for administrators.', '1001web-maintenance-launch-pages'), 'mg-blacklist-ips' => __('IP addresses to block, one per line.', '1001web-maintenance-launch-pages'), 'mg-blacklist-user-agents' => __('Browser or robot names to block, one per line (at least 3 characters). Saved when you leave the field.', '1001web-maintenance-launch-pages'), 'mg-blacklist-message' => __('The message shown to a blocked visitor.', '1001web-maintenance-launch-pages'), 'mg-blacklist-logging' => __('Keeps a list of blocked attempts so you can review them.', '1001web-maintenance-launch-pages'), 'mg-seo-503' => __('Tells Google the closure is temporary (HTTP 503), so your search rankings are kept. Leave it on.', '1001web-maintenance-launch-pages'), 'mg-rest-content-block' => __('Hides your pages and posts from the REST API (/wp-json/wp/v2/) while the site is closed. Editors, administrators and the visitors you let in keep access.', '1001web-maintenance-launch-pages'), 'mg-noindex' => __('Asks search engines not to save the maintenance page itself. Leave it on.', '1001web-maintenance-launch-pages'), 'mg-rgpd-mode' => __('Blocks animations hosted on other websites, so no visitor data is sent to animation hosts. Fonts are always included. A YouTube or Vimeo background video, if you add one, still loads from that service.', '1001web-maintenance-launch-pages'), ], 'i18n' => [ 'countdown_past' => __('This date and time are already past: the countdown stays off until you choose a future date and time.', '1001web-maintenance-launch-pages'), 'countdown_prefill' => __('The date was set to one hour from now. Adjust it as needed.', '1001web-maintenance-launch-pages'), 'countdown_mm_off' => __('Maintenance is off: the countdown is only shown while maintenance is on.', '1001web-maintenance-launch-pages'), 'countdown_turn_on' => __('Turn maintenance on now', '1001web-maintenance-launch-pages'), 'visitor_close' => __('Close', '1001web-maintenance-launch-pages'), 'visitor_title' => __('What visitors receive', '1001web-maintenance-launch-pages'), 'health_reenable' => __('Put the site back in maintenance', '1001web-maintenance-launch-pages'), 'health_dismiss' => __('Leave it online', '1001web-maintenance-launch-pages'), 'unsaved' => __('Unsaved', '1001web-maintenance-launch-pages'), 'saving' => __('Saving...', '1001web-maintenance-launch-pages'), 'saved' => __('Saved', '1001web-maintenance-launch-pages'), 'retry' => __('Retry', '1001web-maintenance-launch-pages'), 'access_link' => __('Access link', '1001web-maintenance-launch-pages'), 'delete_link' => __('Delete this access link', '1001web-maintenance-launch-pages'), 'copy_manual' => __('The link is selected: press Ctrl+C (Cmd+C on a Mac) to copy it.', '1001web-maintenance-launch-pages'), 'cancel' => __('Cancel', '1001web-maintenance-launch-pages'), 'confirm_ok' => __('Continue', '1001web-maintenance-launch-pages'), 'wizard_relaunch_confirm' => __('Open the setup wizard again? Nothing changes until its last step: "Launch maintenance!" and "Save without activating" replace your title, message and style. "Skip wizard" changes nothing.', '1001web-maintenance-launch-pages'), 'confirm_enable' => __('Turn on maintenance mode? Your visitors will no longer see your normal site until you turn it off.', '1001web-maintenance-launch-pages'), 'expert_badge' => __('Expert setting', '1001web-maintenance-launch-pages'), 'unsaved_short' => __('Unsaved changes…', '1001web-maintenance-launch-pages'), 'title_default_mt' => MGENIUS_Settings::default_title_for('maintenance'), 'title_default_cs' => MGENIUS_Settings::default_title_for('coming_soon'), 'save_failed' => __('Not saved — click the save button to retry', '1001web-maintenance-launch-pages'), 'h1h2_reset' => __('H1/H2 sizes reset to default values', '1001web-maintenance-launch-pages'), 'csv_exported' => __('CSV export downloaded', '1001web-maintenance-launch-pages'), 'no_email_export' => __('No emails to export', '1001web-maintenance-launch-pages'), 'emails_deleted' => __('Emails deleted', '1001web-maintenance-launch-pages'), 'connection_error' => __('Connection error', '1001web-maintenance-launch-pages'), 'error_prefix' => __('Error:', '1001web-maintenance-launch-pages'), 'unknown' => __('Unknown', '1001web-maintenance-launch-pages'), 'whitelist_saved' => __('Whitelist saved!', '1001web-maintenance-launch-pages'), 'blacklist_saved' => __('Blacklist saved!', '1001web-maintenance-launch-pages'), 'config_exported' => __('Configuration exported successfully!', '1001web-maintenance-launch-pages'), 'export_error' => __('Error during export', '1001web-maintenance-launch-pages'), 'select_json_file' => __('Please select a JSON file', '1001web-maintenance-launch-pages'), 'import_error' => __('Error during import', '1001web-maintenance-launch-pages'), 'error_generic' => __('Error', '1001web-maintenance-launch-pages'), 'confirm_delete_emails' => __('Are you sure you want to delete all collected emails?', '1001web-maintenance-launch-pages'), 'confirm_disconnect_all' => __('Do you really want to disconnect all visitors?', '1001web-maintenance-launch-pages'), 'confirm_reset_design' => __('Do you really want to reset the design?', '1001web-maintenance-launch-pages'), 'confirm_clear_logs' => __('Do you really want to clear all logs?', '1001web-maintenance-launch-pages'), /* translators: %s: name or value */ 'confirm_delete_access' => __('Delete access for "%s"?', '1001web-maintenance-launch-pages'), 'confirm_delete_animation' => __('Delete this animation?', '1001web-maintenance-launch-pages'), // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText -- Multi-line confirm dialog /* translators: %s: preset name */ 'confirm_apply_preset' => __( "Apply preset \"%s\"?\n\nThis will replace your current design settings.", '1001web-maintenance-launch-pages' ), /* translators: %s: name or value */ 'confirm_delete_preset' => __('Permanently delete preset "%s"?', '1001web-maintenance-launch-pages'), 'confirm_reset_stats' => // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText __( "Do you really want to reset all statistics?\n\nThis action is irreversible.", '1001web-maintenance-launch-pages' ), 'confirm_import_settings' => // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText __( "⚠️ This will replace your current settings.\n\nDo you want to continue?", '1001web-maintenance-launch-pages' ), 'preview_url_error' => __('Error: Preview URL not defined', '1001web-maintenance-launch-pages'), 'format_not_supported' => // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText __( "Format not supported.\n\nUse a .json or .lottie file downloaded from LottieFiles.com", '1001web-maintenance-launch-pages' ), 'file_too_large' => __('File too large (max 5 MB)', '1001web-maintenance-launch-pages'), 'upload_failed' => __('Upload failed', '1001web-maintenance-launch-pages'), 'connection_error_retry' => __('Connection error. Please try again.', '1001web-maintenance-launch-pages'), 'save_error' => __('Error saving', '1001web-maintenance-launch-pages'), 'select_json_file_alert' => __('Please select a .json file', '1001web-maintenance-launch-pages'), 'copy_link' => __('Copy link', '1001web-maintenance-launch-pages'), 'copy_report' => __('Copy report', '1001web-maintenance-launch-pages'), 'open_ticket' => __('Open a ticket', '1001web-maintenance-launch-pages'), 'token_created' => __('Access link created:', '1001web-maintenance-launch-pages'), 'lottie_replace_hint' => __('Drop a new file to replace it', '1001web-maintenance-launch-pages'), 'save_to_activate' => __('Changes are saved automatically', '1001web-maintenance-launch-pages'), 'hc_ok' => __('All key pages respond as before', '1001web-maintenance-launch-pages'), 'hc_warn' => __('Some pages look different', '1001web-maintenance-launch-pages'), 'hc_fail' => __('Something broke', '1001web-maintenance-launch-pages'), 'hc_unverified' => __('Could not be checked from the server', '1001web-maintenance-launch-pages'), 'hc_unavailable' => __('No comparison available', '1001web-maintenance-launch-pages'), 'hc_same' => __('Same as before', '1001web-maintenance-launch-pages'), 'hc_just_now' => __('Just now', '1001web-maintenance-launch-pages'), 'hc_checking' => __('Checking…', '1001web-maintenance-launch-pages'), 'no_tokens' => __('No token created', '1001web-maintenance-launch-pages'), 'token_name_required' => __('Name is required', '1001web-maintenance-launch-pages'), 'visitor_password_required' => __('A password is required to enable visitor access.', '1001web-maintenance-launch-pages'), 'visits' => __('visits', '1001web-maintenance-launch-pages'), 'resetting' => __('Resetting...', '1001web-maintenance-launch-pages'), 'deleting' => __('Deleting...', '1001web-maintenance-launch-pages'), 'creating' => __('Creating...', '1001web-maintenance-launch-pages'), 'save' => __('Save', '1001web-maintenance-launch-pages'), 'saving_preset' => __('Saving...', '1001web-maintenance-launch-pages'), 'preset_name_required' => __('Please enter a name for the preset.', '1001web-maintenance-launch-pages'), 'save_preset_btn' => __('💾 Save', '1001web-maintenance-launch-pages'), 'importing' => __('Importing...', '1001web-maintenance-launch-pages'), 'import_preset_btn' => __('📥 Import a preset', '1001web-maintenance-launch-pages'), 'resetting_stats' => __('⏳ Resetting...', '1001web-maintenance-launch-pages'), 'reset_stats_btn' => __('🗑️ Reset statistics', '1001web-maintenance-launch-pages'), 'exporting' => __('⏳ Exporting...', '1001web-maintenance-launch-pages'), 'download_backup_btn' => __('📥 Download Backup', '1001web-maintenance-launch-pages'), 'choose_bg_image' => __('Choose a background image', '1001web-maintenance-launch-pages'), 'use_this_image' => __('Use this image', '1001web-maintenance-launch-pages'), 'choose_logo' => __('Choose a logo', '1001web-maintenance-launch-pages'), 'use' => __('Use', '1001web-maintenance-launch-pages'), 'no_custom_presets' => __('No custom presets saved.', '1001web-maintenance-launch-pages'), 'configure_design_hint' => __('Configure your perfect design, then save it here!', '1001web-maintenance-launch-pages'), 'no_image_selected' => __('No image selected', '1001web-maintenance-launch-pages'), 'drag_drop' => __('Drag and drop', '1001web-maintenance-launch-pages'), 'your_file_here' => __('your .json or .lottie file here', '1001web-maintenance-launch-pages'), 'or_click_select' => __('or click to select', '1001web-maintenance-launch-pages'), 'password_generated' => __('Password generated!', '1001web-maintenance-launch-pages'), 'password_copied' => __('Password copied!', '1001web-maintenance-launch-pages'), 'copied' => __('Copied!', '1001web-maintenance-launch-pages'), 'background_saved' => __('Background saved!', '1001web-maintenance-launch-pages'), 'unsaved_warning' => __('You have unsaved changes. Leave the page anyway?', '1001web-maintenance-launch-pages'), 'text_colors_saved' => __('Text colors saved!', '1001web-maintenance-launch-pages'), 'button_colors_saved' => __('Button colors saved!', '1001web-maintenance-launch-pages'), 'container_saved' => __('Container saved!', '1001web-maintenance-launch-pages'), 'typography_saved' => __('Typography saved!', '1001web-maintenance-launch-pages'), 'dimensions_saved' => __('Dimensions saved!', '1001web-maintenance-launch-pages'), 'animations_saved' => __('Animations saved!', '1001web-maintenance-launch-pages'), 'design_saved' => __('Design saved!', '1001web-maintenance-launch-pages'), 'all_saved' => __('All saved!', '1001web-maintenance-launch-pages'), 'disable_maintenance' => __('Disable maintenance', '1001web-maintenance-launch-pages'), 'enable_maintenance' => __('Enable maintenance', '1001web-maintenance-launch-pages'), 'schedule_configured' => __('Schedule configured:', '1001web-maintenance-launch-pages'), 'start_label' => __('Start:', '1001web-maintenance-launch-pages'), 'end_label' => __('End:', '1001web-maintenance-launch-pages'), 'at' => __('at', '1001web-maintenance-launch-pages'), 'apply' => __('Apply', '1001web-maintenance-launch-pages'), 'upload_backup_btn' => __('📤 Upload Backup', '1001web-maintenance-launch-pages'), 'logs_cleared' => __('Logs cleared', '1001web-maintenance-launch-pages'), // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText -- Confirm dialog with placeholder /* translators: %s: theme label */ 'theme_confirm' => __('Apply theme "%s"? Your own background image is kept, and "Restore my design" brings back the design you had before themes.', '1001web-maintenance-launch-pages'), 'theme_applied_badge' => __('applied', '1001web-maintenance-launch-pages'), 'revert_theme' => __('Restore my design', '1001web-maintenance-launch-pages'), 'coming_soon_label' => __('COMING SOON', '1001web-maintenance-launch-pages'), 'coming_soon_mode' => __('COMING SOON MODE', '1001web-maintenance-launch-pages'), 'maintenance_mode' => __('MAINTENANCE MODE', '1001web-maintenance-launch-pages'), 'status_on' => _x('ON', 'maintenance status', '1001web-maintenance-launch-pages'), 'status_off' => _x('OFF', 'maintenance status', '1001web-maintenance-launch-pages'), 'check_ok' => __('(OK)', '1001web-maintenance-launch-pages'), 'check_problem' => __('(problem)', '1001web-maintenance-launch-pages'), ], ]); } /** * Affiche la page d'administration */ /** * Fin du compte a rebours en millisecondes, ou 0 s'il n'y a * pas de compte a rebours actif a desactivation automatique. * * @return int */ public static function countdown_end_ms() { $settings = MGENIUS_Settings::load(); if (empty($settings['maintenance_enabled']) || empty($settings['countdown_enabled']) || empty($settings['countdown_auto_disable'])) { return 0; } return MGENIUS_Main::countdown_target_timestamp($settings) * 1000; } public static function render_page() { if (!current_user_can('manage_options')) { return; } $settings = MGENIUS_Settings::load(); $fonts = MGENIUS_Settings::get_fonts(); $animations = MGENIUS_Settings::get_animations(); include MGENIUS_PLUGIN_DIR . 'templates/admin-page.php'; } /** * Ajoute le menu dans la barre d'administration avec toggle ON/OFF */ public static function add_admin_bar_menu($wp_admin_bar) { if (!current_user_can('manage_options')) { return; } $preview_url = home_url('/?mgenius_preview=1&_wpnonce=' . wp_create_nonce('mgenius_preview')); $settings_url = admin_url('admin.php?page=mgenius-settings'); $settings = MGENIUS_Settings::load(); $is_active = !empty($settings['maintenance_enabled']); $icon_style = 'font-family:dashicons;font-size:16px;vertical-align:middle;margin-right:5px;'; $toggle_html = ''; $toggle_html .= ''; $toggle_html .= ''; $toggle_html .= ''; $toggle_html .= '' . esc_html($is_active ? _x('ON', 'maintenance status', '1001web-maintenance-launch-pages') : _x('OFF', 'maintenance status', '1001web-maintenance-launch-pages')) . ''; $toggle_html .= ''; $title = ''; $title .= '' . esc_html__('Maintenance', '1001web-maintenance-launch-pages') . ''; $title .= $toggle_html; $wp_admin_bar->add_node([ 'id' => 'mgenius-bar', 'title' => $title, 'href' => $settings_url, 'meta' => [ 'title' => '1001Web Maintenance v' . MGENIUS_VERSION ] ]); $wp_admin_bar->add_node([ 'id' => 'mgenius-settings', 'parent' => 'mgenius-bar', 'title' => '' . __('Settings', '1001web-maintenance-launch-pages'), 'href' => $settings_url, ]); $wp_admin_bar->add_node([ 'id' => 'mgenius-preview', 'parent' => 'mgenius-bar', 'title' => '' . __('Preview', '1001web-maintenance-launch-pages'), 'href' => $preview_url, 'meta' => [ 'target' => '_blank', ] ]); $toggle_icon = $is_active ? 'dashicons-no' : 'dashicons-yes'; $toggle_color = $is_active ? 'color:#dc3545;' : 'color:#4CAF50;'; $toggle_text = $is_active ? __('Disable', '1001web-maintenance-launch-pages') : __('Enable', '1001web-maintenance-launch-pages'); $wp_admin_bar->add_node([ 'id' => 'mgenius-toggle', 'parent' => 'mgenius-bar', 'title' => '' . $toggle_text, 'href' => '#', 'meta' => [ 'class' => 'mg-admin-bar-toggle', ] ]); } /** * CSS/JS inline pour le toggle admin bar (chargé globalement) */ public static function admin_bar_toggle_assets() { if (!current_user_can('manage_options') || !is_admin_bar_showing()) { return; } // CSS et JS de la bascule dans la barre d'admin : servis par les // fonctions d'enfilage de WordPress plutôt que par des balises //