Version 1.0.0
This commit is contained in:
parent
96c723a26e
commit
3f07806aaf
49
README.md
49
README.md
@ -1,3 +1,48 @@
|
||||
# pausera
|
||||
# Pausera – Elegant Maintenance Mode for WordPress
|
||||
|
||||
**Pausera** is a lightweight and elegant maintenance mode plugin for WordPress.
|
||||
It gives you full control over access, redirection, and visibility based on user roles, usernames, or IPs.
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- 🔐 Enable/disable maintenance mode instantly from the dashboard.
|
||||
- 🔁 Redirect visitors to a custom page.
|
||||
- 👥 Whitelist specific **user roles**.
|
||||
- 👤 Whitelist specific **usernames**.
|
||||
- 🌐 Whitelist **IP addresses** (comma-separated).
|
||||
- 🧩 Select the redirect page using a clean Select2 UI.
|
||||
- 🖥️ Fully redesigned admin panel with smooth UX.
|
||||
- 📦 Optimized asset loading – only in plugin page.
|
||||
- 🌓 Dark mode–friendly design.
|
||||
- 🔍 Select2 integrated for multi-role/user selections.
|
||||
|
||||
## 🛠️ Installation
|
||||
|
||||
1. Upload the plugin to the `/wp-content/plugins/` directory.
|
||||
2. Activate it from the **Plugins** menu.
|
||||
3. Go to **Pausera** in the admin sidebar to configure.
|
||||
|
||||
## 🧪 Tested with
|
||||
|
||||
- WordPress: 6.5+
|
||||
- PHP: 7.4+
|
||||
|
||||
## 📜 License
|
||||
|
||||
[GNU General Public License v2.0 or later](https://www.gnu.org/licenses/gpl-2.0.html)
|
||||
|
||||
---
|
||||
|
||||
## ✨ Screenshots
|
||||
|
||||
1. Main admin interface
|
||||
2. IP and role/user access control
|
||||
3. Admin bar status indicator (ON/OFF)
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Author
|
||||
|
||||
**Moh Farawati** – [mohfarawati.de](https://mohfarawati.de)
|
||||
Frontend developer, WordPress expert & plugin builder.
|
||||
|
||||
Lightweight and elegant maintenance mode plugin for WordPress. Full control over access, roles, users, IPs, and redirects. Ideal for freelancers and agencies.
|
||||
|
||||
98
assets/admin.js
Normal file
98
assets/admin.js
Normal file
@ -0,0 +1,98 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
// ============================
|
||||
// Tabs Switching
|
||||
// ============================
|
||||
const tabs = document.querySelectorAll(".pausera-tab-button");
|
||||
const contents = document.querySelectorAll(".pausera-tab-content");
|
||||
|
||||
tabs.forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
tabs.forEach(b => b.classList.remove("active"));
|
||||
contents.forEach(c => c.classList.remove("active"));
|
||||
btn.classList.add("active");
|
||||
document.querySelector(`#${btn.dataset.tab}`).classList.add("active");
|
||||
});
|
||||
});
|
||||
|
||||
// ============================
|
||||
// Form & Save Button Logic
|
||||
// ============================
|
||||
const form = document.getElementById("pausera-form");
|
||||
if (!form) return;
|
||||
const saveButton = form.querySelector(".pausera-save");
|
||||
|
||||
const enableSave = (name, value) => {
|
||||
console.log(`✏️ Changed: [${name}] → ${value}`);
|
||||
saveButton.disabled = false;
|
||||
};
|
||||
|
||||
form.querySelectorAll("input, select, textarea").forEach(field => {
|
||||
const type = field.type;
|
||||
|
||||
if (type === "checkbox") {
|
||||
field.addEventListener("change", () => {
|
||||
enableSave(field.name, field.checked);
|
||||
});
|
||||
} else if (field.tagName === "SELECT") {
|
||||
field.addEventListener("change", () => {
|
||||
const val = field.multiple
|
||||
? Array.from(field.selectedOptions).map(opt => opt.value).join(', ')
|
||||
: field.value;
|
||||
enableSave(field.name, val);
|
||||
});
|
||||
|
||||
// Handle Select2
|
||||
if (jQuery && jQuery(field).hasClass('acf-style-select')) {
|
||||
jQuery(field).on('select2:select select2:unselect', () => {
|
||||
const val = field.multiple
|
||||
? Array.from(field.selectedOptions).map(opt => opt.value).join(', ')
|
||||
: field.value;
|
||||
enableSave(field.name, val);
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
field.addEventListener("input", () => {
|
||||
enableSave(field.name, field.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ============================
|
||||
// Maintenance Toggle Switch
|
||||
// ============================
|
||||
const toggleBox = document.getElementById("maintenance-toggle");
|
||||
if (toggleBox) {
|
||||
toggleBox.addEventListener("click", () => {
|
||||
const checkbox = toggleBox.querySelector("input[type=checkbox]");
|
||||
const label = toggleBox.querySelector(".pausera-toggle-label");
|
||||
|
||||
checkbox.checked = !checkbox.checked;
|
||||
toggleBox.classList.toggle("active", checkbox.checked);
|
||||
label.textContent = checkbox.checked ? label.dataset.labelOn : label.dataset.labelOff;
|
||||
|
||||
checkbox.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
console.log("🟢 Maintenance toggled:", checkbox.checked);
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// On Form Submit
|
||||
// ============================
|
||||
form.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
document.getElementById("pausera-confirm-box").style.display = "flex";
|
||||
});
|
||||
|
||||
document.getElementById("confirm-save").addEventListener("click", function () {
|
||||
document.getElementById("pausera-confirm-box").style.display = "none";
|
||||
form.submit();
|
||||
});
|
||||
|
||||
document.getElementById("cancel-save").addEventListener("click", function () {
|
||||
document.getElementById("pausera-confirm-box").style.display = "none";
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
BIN
assets/select2/.DS_Store
vendored
Normal file
BIN
assets/select2/.DS_Store
vendored
Normal file
Binary file not shown.
1
assets/select2/select2.min.css
vendored
Normal file
1
assets/select2/select2.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
assets/select2/select2.min.js
vendored
Normal file
2
assets/select2/select2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
477
assets/style.css
Normal file
477
assets/style.css
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
==============================
|
||||
Pausera Admin Panel Styles (Grid-Based)
|
||||
==============================
|
||||
*/
|
||||
|
||||
:root {
|
||||
--color-primary: #e57e00;
|
||||
--color-primary-hover: #985300;
|
||||
--color-white: #fff;
|
||||
--color-black: #000;
|
||||
--color-bg: #f2f3f5;
|
||||
--color-box: #fff;
|
||||
--color-text: #222;
|
||||
--color-border: #ddd;
|
||||
|
||||
|
||||
|
||||
|
||||
--top-bar-bg: #f3f3f3;
|
||||
--top-bar-text: #000000;
|
||||
--top-bar-height: 50px;
|
||||
|
||||
--head-bar-bg: #fff;
|
||||
--head-bar-text: #fff;
|
||||
--head-bar-height: 100px;
|
||||
--head-bar-shadow: 0 2px 6px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--radius: 24px;
|
||||
--radius-inner: 16px;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Top Info Bar
|
||||
============================ */
|
||||
.pausera-support-bar {
|
||||
width: 100%;
|
||||
padding: 12px 32px;
|
||||
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #ffcc99;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Status Bar
|
||||
============================ */
|
||||
.pausera-status-bar {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: center;
|
||||
|
||||
background: var(--top-bar-bg);
|
||||
color: var(--top-bar-text);
|
||||
height: var(--top-bar-height);
|
||||
|
||||
padding: 0 32px;
|
||||
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Header Area
|
||||
============================ */
|
||||
.pausera-header {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
|
||||
|
||||
background: var(--head-bar-bg);
|
||||
color: var(--head-bar-text);
|
||||
height: var(--head-bar-height);
|
||||
box-shadow: var(--head-bar-shadow);
|
||||
padding: 0 32px;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.pausera-title {
|
||||
font-size: 28px;
|
||||
font-weight: 900;
|
||||
color: var(--color-text);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Main Grid Layout
|
||||
============================ */
|
||||
.pausera-wrap {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 250px;
|
||||
gap: 10px;
|
||||
max-width: 1200px;
|
||||
margin: 32px auto;
|
||||
padding: 0 16px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Form Area
|
||||
============================ */
|
||||
.formular {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
.formular div{
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
/* ============================
|
||||
Cards
|
||||
============================ */
|
||||
.pausera-card {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
background: var(--color-white);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius);
|
||||
padding: 24px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.pausera-card h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.pausera-card label {
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.pausera-card input[type="text"],
|
||||
.pausera-card select {
|
||||
width: 100%;
|
||||
padding: 10px 16px;
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-box);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Toggle Switch
|
||||
============================ */
|
||||
.pausera-card.toggle-box {
|
||||
|
||||
background: #f8f8f8;
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: var(--radius);
|
||||
padding: 24px;
|
||||
transition: 0.2s ease;
|
||||
text-align: center;
|
||||
min-height: 200px;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pausera-card.toggle-box:hover {
|
||||
border-color: #aaa;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pausera-card.toggle-box.active {
|
||||
background: var(--color-primary);
|
||||
border-color: var(--color-primary-hover);
|
||||
}
|
||||
|
||||
.pausera-card.toggle-box input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pausera-card.toggle-box label {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
|
||||
.pausera-card.toggle-box.active label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.pausera-toggle-label {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Buttons
|
||||
============================ */
|
||||
.pausera-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pausera-save,
|
||||
.pausera-reset {
|
||||
padding: 14px 30px;
|
||||
border-radius: var(--radius);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.pausera-save {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
.pausera-save:hover {
|
||||
background: var(--color-primary-hover);
|
||||
}
|
||||
|
||||
.pausera-reset {
|
||||
background: #444;
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
.pausera-reset:hover {
|
||||
background: #222;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Sidebar
|
||||
============================ */
|
||||
.pausera-sidebar {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 24px;
|
||||
background: var(--color-white);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius);
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.pausera-sidebar h4 {
|
||||
margin-top: 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.pausera-sidebar ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.pausera-sidebar a {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.pausera-sidebar a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Responsive
|
||||
============================ */
|
||||
@media (max-width: 1024px) {
|
||||
.pausera-wrap {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.pausera-sidebar {
|
||||
order: 2;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.formular {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
/* ============================
|
||||
WordPress Admin Fixes
|
||||
============================ */
|
||||
body.toplevel_page_pausera #wpcontent {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
body.toplevel_page_pausera .updated,
|
||||
body.toplevel_page_pausera .notice-success {
|
||||
display: none !important;
|
||||
}
|
||||
body.toplevel_page_pausera .notice,
|
||||
body.toplevel_page_pausera .updated,
|
||||
body.toplevel_page_pausera .notice-success {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* ============================
|
||||
POPUp SAVE
|
||||
============================ */
|
||||
.pausera-confirm-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.pausera-confirm-dialog {
|
||||
background: #fff;
|
||||
border-radius: var(--radius);
|
||||
padding: 32px;
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
/* ============================
|
||||
WordPress Admin notice
|
||||
============================ */
|
||||
|
||||
.pausera-notice {
|
||||
background: #e7f7ec;
|
||||
color: #007c43;
|
||||
border: 1px solid #b8e1c0;
|
||||
padding: 16px 20px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-weight: bold;
|
||||
margin: 16px 32px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||
}
|
||||
.pausera-header-status {
|
||||
font-weight: bold;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.pausera-status-on {
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.pausera-status-off {
|
||||
color: #999;
|
||||
}
|
||||
/* ============================
|
||||
Unified Input / Select / Select2 Styling
|
||||
============================ */
|
||||
.pausera-card input[type="text"],
|
||||
.pausera-card select,
|
||||
.select2-container--default .select2-selection--single,
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
width: 100% !important;
|
||||
padding: 10px 16px !important;
|
||||
border-radius: var(--radius) !important;
|
||||
border: 1px solid var(--color-border) !important;
|
||||
background: var(--color-box) !important;
|
||||
color: var(--color-text) !important;
|
||||
font-size: 15px !important;
|
||||
line-height: 1.5;
|
||||
box-sizing: border-box;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Select2 Placeholder & Text
|
||||
============================ */
|
||||
.select2-container--default .select2-selection__rendered {
|
||||
color: var(--color-text) !important;
|
||||
padding-left: 4px;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Select2 Dropdown Arrow
|
||||
============================ */
|
||||
.select2-container--default .select2-selection__arrow {
|
||||
height: 100% !important;
|
||||
right: 10px !important;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Multi-Select Chips (Tags)
|
||||
============================ */
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background: var(--color-primary) !important;
|
||||
border: none !important;
|
||||
border-radius: var(--radius-inner) !important;
|
||||
padding: 4px 4px 4px 25px!important;
|
||||
font-size: 13px;
|
||||
color: #fff !important;
|
||||
margin: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
Field Focus Styling
|
||||
============================ */
|
||||
.pausera-card input[type="text"]:focus,
|
||||
.pausera-card select:focus,
|
||||
.select2-container--default .select2-selection:focus {
|
||||
outline: none !important;
|
||||
border-color: var(--color-primary-hover) !important;
|
||||
box-shadow: 0 0 0 1px var(--color-primary-hover) !important;
|
||||
}
|
||||
/* ============================
|
||||
Select2 Dropdown Customization
|
||||
============================ */
|
||||
|
||||
.select2-container--default .select2-dropdown {
|
||||
background-color: var(--color-box) !important;
|
||||
border: 1px solid var(--color-border) !important;
|
||||
border-radius: var(--radius) !important;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option {
|
||||
padding: 10px 16px !important;
|
||||
font-size: 15px;
|
||||
color: var(--color-text);
|
||||
border-radius: 0 !important;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: var(--color-primary) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected="true"] {
|
||||
background-color: var(--color-primary-hover) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__display {
|
||||
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
padding: 6px!important;
|
||||
background-color: rgba(0, 0, 0, 0.3)!important;
|
||||
border-right: none!important;
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
|
||||
background-color: rgba(208, 0, 0, 0.87)!important;
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove span {
|
||||
|
||||
color: #fff!important;
|
||||
padding: 0px 0px 2px 2px;
|
||||
margin-top: -12px!important;
|
||||
|
||||
}
|
||||
39
includes/access-control.php
Normal file
39
includes/access-control.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
if (!class_exists('Pausera')) return;
|
||||
|
||||
if (!method_exists('Pausera', 'handle_redirect')) {
|
||||
Pausera::add_method('handle_redirect', function () {
|
||||
$options = $this->options;
|
||||
|
||||
if (empty($options['enable_maintenance'])) return;
|
||||
|
||||
if (is_user_logged_in()) {
|
||||
$user = wp_get_current_user();
|
||||
foreach ($user->roles as $role) {
|
||||
if (in_array($role, $options['excluded_roles'])) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($_SERVER['REMOTE_ADDR'], $options['excluded_ips'])) return;
|
||||
|
||||
global $wp_query;
|
||||
if (!$options['enable_maintenance'] && $wp_query->is_404()) return;
|
||||
|
||||
$current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
||||
$redirect_path = trim($options['redirect_url'], '/');
|
||||
|
||||
if ($current_path === $redirect_path) return;
|
||||
|
||||
foreach ($options['excluded_slugs'] as $slug) {
|
||||
if (stripos($current_path, $slug) !== false) return;
|
||||
}
|
||||
|
||||
if (!is_admin()) {
|
||||
wp_redirect(home_url($options['redirect_url']));
|
||||
exit;
|
||||
}
|
||||
});
|
||||
}
|
||||
147
includes/admin-ui.php
Normal file
147
includes/admin-ui.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
add_action('pausera_render_ui', function () {
|
||||
$settings = get_option('pausera_settings', []);
|
||||
$enabled = !empty($settings['enable_maintenance']);
|
||||
$excluded_ips = isset($settings['excluded_ips']) ? implode(',', $settings['excluded_ips']) : '';
|
||||
$redirect_url = $settings['redirect_url'] ?? '/maintenance';
|
||||
$excluded_roles = $settings['excluded_roles'] ?? [];
|
||||
$allowed_users = $settings['allowed_users'] ?? [];
|
||||
$plugin_data = get_plugin_data(PAUSERA_PATH . 'pausera.php');
|
||||
|
||||
global $wp_roles;
|
||||
$all_users = get_users(['fields' => ['user_login']]);
|
||||
$usernames = array_map(function ($u) {
|
||||
return $u->user_login;
|
||||
}, $all_users);
|
||||
?>
|
||||
|
||||
<div class="pausera-status-bar">
|
||||
Aktueller Status: <?php echo $enabled ? 'Wartungsmodus AKTIV' : 'Deaktiviert'; ?>
|
||||
</div>
|
||||
|
||||
<div class="pausera-header">
|
||||
<div class="pausera-title">Pausera</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['settings-updated']) && $_GET['settings-updated'] === 'true') : ?>
|
||||
<div class="pausera-notice success">
|
||||
<?php echo esc_html(__('Settings saved successfully.', 'pausera')); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pausera-wrap">
|
||||
<div class="formular">
|
||||
<form method="post" action="options.php" id="pausera-form">
|
||||
<?php settings_fields('pausera_group'); ?>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="pausera-card toggle-box <?php echo $enabled ? 'active' : ''; ?>" id="maintenance-toggle">
|
||||
<input type="checkbox" id="maintenance_toggle_input" name="pausera_settings[enable_maintenance]" value="1" <?php checked($enabled); ?> />
|
||||
<label for="maintenance_toggle_input">
|
||||
<strong class="pausera-toggle-label" data-label-on="Deaktivieren" data-label-off="Aktivieren">
|
||||
<?php echo $enabled ? 'Deaktivieren' : 'Aktivieren'; ?>
|
||||
</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="pausera-card">
|
||||
<h3>Weiterleitungsseite</h3>
|
||||
<label>Seite auswählen</label>
|
||||
<select name="pausera_settings[redirect_url]" class="acf-style-select">
|
||||
<?php foreach (get_pages() as $page) :
|
||||
$slug = '/' . basename(get_permalink($page->ID));
|
||||
$selected = selected($redirect_url, $slug, false);
|
||||
echo "<option value='{$slug}' {$selected}>{$page->post_title}</option>";
|
||||
endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="pausera-card">
|
||||
<h3>Erlaubte Benutzer</h3>
|
||||
<label>Mehrere Benutzernamen mit Komma trennen</label>
|
||||
<select name="pausera_settings[allowed_users][]" multiple class="acf-style-select">
|
||||
<?php foreach ($usernames as $username) :
|
||||
$selected = in_array($username, $allowed_users) ? 'selected' : '';
|
||||
echo "<option value='{$username}' {$selected}>{$username}</option>";
|
||||
endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="pausera-card">
|
||||
<h3>Benutzerrollen</h3>
|
||||
<label>Mehrfachauswahl möglich</label>
|
||||
<select name="pausera_settings[excluded_roles][]" multiple class="acf-style-select">
|
||||
<?php foreach ($wp_roles->roles as $key => $role) :
|
||||
$selected = in_array($key, $excluded_roles) ? 'selected' : '';
|
||||
echo "<option value='{$key}' {$selected}>{$role['name']}</option>";
|
||||
endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="pausera-card">
|
||||
<h3>Ausgeschlossene IP-Adressen</h3>
|
||||
<label>Mehrere IPs mit Komma trennen</label>
|
||||
<input type="text" name="pausera_settings[excluded_ips]" value="<?php echo esc_attr($excluded_ips); ?>" placeholder="127.0.0.1, 88.99.99.99">
|
||||
</div>
|
||||
|
||||
<div class="pausera-buttons">
|
||||
<button type="submit" class="pausera-save">Speichern</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pausera-confirm-overlay" id="pausera-confirm-box">
|
||||
<div class="pausera-confirm-dialog">
|
||||
<h3>Einstellungen speichern?</h3>
|
||||
<p>Bitte bestätigen Sie, dass Sie die Änderungen speichern möchten.</p>
|
||||
<div class="pausera-buttons">
|
||||
<button type="button" id="confirm-save" class="pausera-save">Ja, speichern</button>
|
||||
<button type="button" id="cancel-save" class="pausera-reset">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="pausera-sidebar">
|
||||
<h4>Plugin-Informationen</h4>
|
||||
<ul>
|
||||
<li><strong>Version:</strong> <?php echo esc_html($plugin_data['Version']); ?></li>
|
||||
<li><strong>Autor:</strong> Ihr Name</li>
|
||||
<li><strong>Website:</strong> <a href="https://example.com" target="_blank">example.com</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>Plugin-Links</h4>
|
||||
<ul>
|
||||
<li><a href="https://example.com/docs" target="_blank">📄 Dokumentation</a></li>
|
||||
<li><a href="mailto:support@example.com">Kontaktieren Sie uns</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php });
|
||||
51
includes/assets.php
Normal file
51
includes/assets.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
function pausera_enqueue_assets() {
|
||||
if (!isset($_GET['page']) || $_GET['page'] !== 'pausera') {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'pausera-style',
|
||||
PAUSERA_URL . 'assets/style.css',
|
||||
array(),
|
||||
filemtime(PAUSERA_PATH . 'assets/style.css')
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'pausera-js',
|
||||
PAUSERA_URL . 'assets/admin.js',
|
||||
array(),
|
||||
filemtime(PAUSERA_PATH . 'assets/admin.js'),
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'select2',
|
||||
PAUSERA_URL . 'assets/select2/select2.min.js',
|
||||
array('jquery'),
|
||||
'4.1.0',
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'select2-css',
|
||||
PAUSERA_URL . 'assets/select2/select2.min.css',
|
||||
array(),
|
||||
'4.1.0'
|
||||
);
|
||||
|
||||
add_action('admin_footer', 'pausera_footer_script');
|
||||
}
|
||||
|
||||
function pausera_footer_script() {
|
||||
echo '<script>
|
||||
jQuery(document).ready(function($){
|
||||
$(".acf-style-select").select2();
|
||||
$(".nav-tab").on("mousedown", function(e){ e.preventDefault(); });
|
||||
});
|
||||
</script>';
|
||||
}
|
||||
|
||||
add_action('admin_enqueue_scripts', 'pausera_enqueue_assets');
|
||||
118
includes/settings-handler.php
Normal file
118
includes/settings-handler.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
if (class_exists('Pausera')) return;
|
||||
|
||||
class Pausera {
|
||||
private $options;
|
||||
|
||||
public function __construct() {
|
||||
$defaults = [
|
||||
'enable_maintenance' => false,
|
||||
'excluded_slugs' => [],
|
||||
'excluded_ips' => [],
|
||||
'excluded_roles' => [],
|
||||
'allowed_users' => [],
|
||||
'redirect_url' => '/maintenance',
|
||||
];
|
||||
|
||||
$saved_options = get_option('pausera_settings', []);
|
||||
$this->options = wp_parse_args($saved_options, $defaults);
|
||||
|
||||
add_action('admin_menu', [$this, 'admin_menu']);
|
||||
add_action('admin_init', [$this, 'register_settings']);
|
||||
add_action('template_redirect', [$this, 'handle_redirect']);
|
||||
add_action('admin_notices', [$this, 'admin_notice']);
|
||||
add_action('admin_bar_menu', [$this, 'add_admin_bar_status'], 100);
|
||||
}
|
||||
|
||||
public function register_settings() {
|
||||
register_setting('pausera_group', 'pausera_settings', [
|
||||
'sanitize_callback' => [$this, 'sanitize_settings']
|
||||
]);
|
||||
}
|
||||
|
||||
public function sanitize_settings($input) {
|
||||
add_option('pausera_settings_saved', 1);
|
||||
return [
|
||||
'enable_maintenance' => !empty($input['enable_maintenance']),
|
||||
'excluded_slugs' => isset($input['excluded_slugs']) ? array_filter(array_map('sanitize_title', (array) $input['excluded_slugs'])) : [],
|
||||
'excluded_ips' => array_filter(array_map('trim', explode(',', sanitize_text_field($input['excluded_ips'] ?? '')))),
|
||||
'excluded_roles' => isset($input['excluded_roles']) ? array_filter(array_map('sanitize_text_field', (array) $input['excluded_roles'])) : [],
|
||||
'redirect_url' => esc_url_raw($input['redirect_url'] ?? '/maintenance'),
|
||||
'allowed_users' => isset($input['allowed_users']) ? array_filter(array_map('sanitize_user', (array) $input['allowed_users'])) : [],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
public function admin_notice() {
|
||||
if (get_option('pausera_settings_saved')) {
|
||||
delete_option('pausera_settings_saved');
|
||||
echo '<div class="notice notice-success is-dismissible"><p>Settings saved successfully.</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
add_menu_page(
|
||||
'Pausera',
|
||||
'Pausera',
|
||||
'manage_options',
|
||||
'pausera',
|
||||
[$this, 'settings_page'],
|
||||
'dashicons-shield-alt',
|
||||
80
|
||||
);
|
||||
}
|
||||
|
||||
public function handle_redirect() {
|
||||
if (empty($this->options['enable_maintenance'])) return;
|
||||
|
||||
if (is_user_logged_in()) {
|
||||
$user = wp_get_current_user();
|
||||
if (in_array($user->user_login, $this->options['allowed_users'] ?? [])) return;
|
||||
|
||||
foreach ($user->roles as $role) {
|
||||
if (in_array($role, $this->options['excluded_roles'])) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($_SERVER['REMOTE_ADDR'], $this->options['excluded_ips'])) return;
|
||||
|
||||
global $wp_query;
|
||||
if (!$this->options['enable_maintenance'] && $wp_query->is_404()) return;
|
||||
|
||||
$current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
||||
$redirect_path = trim($this->options['redirect_url'], '/');
|
||||
|
||||
if ($current_path === $redirect_path) return;
|
||||
|
||||
foreach ($this->options['excluded_slugs'] as $slug) {
|
||||
if (stripos($current_path, $slug) !== false) return;
|
||||
}
|
||||
|
||||
if (!is_admin()) {
|
||||
wp_redirect(home_url($this->options['redirect_url']));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
public function settings_page() {
|
||||
do_action('pausera_render_ui');
|
||||
}
|
||||
|
||||
public function add_admin_bar_status($wp_admin_bar) {
|
||||
if (!current_user_can('manage_options')) return;
|
||||
|
||||
$enabled = !empty($this->options['enable_maintenance']);
|
||||
$label = 'Pausera: ' . ($enabled ? 'ON' : 'OFF');
|
||||
$color = $enabled ? 'orange' : '#999';
|
||||
|
||||
$wp_admin_bar->add_node([
|
||||
'id' => 'pausera_status',
|
||||
'title' => '<span style="color:' . esc_attr($color) . '; font-weight: bold;">' . esc_html($label) . '</span>',
|
||||
'href' => admin_url('admin.php?page=pausera'),
|
||||
'meta' => ['title' => 'Pausera Status']
|
||||
]);
|
||||
}
|
||||
}
|
||||
25
pausera.php
Normal file
25
pausera.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Pausera
|
||||
* Description: Elegant maintenance mode with full control over access, roles, pages and redirects.
|
||||
* Version: 1.0.0
|
||||
* Author: Moh Farawati
|
||||
* Text Domain: pausera
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
define('PAUSERA_PATH', plugin_dir_path(__FILE__));
|
||||
define('PAUSERA_URL', plugin_dir_url(__FILE__));
|
||||
|
||||
// Include class only once
|
||||
if (!class_exists('Pausera')) {
|
||||
require_once PAUSERA_PATH . 'includes/settings-handler.php';
|
||||
}
|
||||
|
||||
require_once PAUSERA_PATH . 'includes/access-control.php';
|
||||
require_once PAUSERA_PATH . 'includes/assets.php';
|
||||
require_once PAUSERA_PATH . 'includes/admin-ui.php';
|
||||
|
||||
// Initialize plugin
|
||||
new Pausera();
|
||||
34
readme.txt
Normal file
34
readme.txt
Normal file
@ -0,0 +1,34 @@
|
||||
=== Pausera ===
|
||||
Contributors: mohfarawati
|
||||
Tags: maintenance, maintenance mode, access control, roles, ip whitelist
|
||||
Requires at least: 5.5
|
||||
Tested up to: 6.5
|
||||
Requires PHP: 7.4
|
||||
Stable tag: 3.0.1
|
||||
License: GPLv2 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Elegant maintenance mode with full control over access, roles, users, pages and redirects.
|
||||
|
||||
== Description ==
|
||||
Pausera is a lightweight and powerful maintenance mode plugin for WordPress. It allows you to enable maintenance mode with full control over:
|
||||
- Redirect page
|
||||
- Allowed user roles
|
||||
- Allowed usernames
|
||||
- Whitelisted IPs
|
||||
|
||||
== Installation ==
|
||||
1. Upload the plugin folder to the `/wp-content/plugins/` directory.
|
||||
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
||||
3. Go to the 'Pausera' menu in the admin area to configure.
|
||||
|
||||
== Changelog ==
|
||||
= 3.0.1 =
|
||||
* Feature: Added user-level access control
|
||||
* Feature: Redesigned admin interface
|
||||
* Fix: Minor UI bugs
|
||||
|
||||
== Screenshots ==
|
||||
1. Main admin panel
|
||||
2. IP and role control
|
||||
3. Plugin status indicator
|
||||
Loading…
x
Reference in New Issue
Block a user