Changeset 3431166
- Timestamp:
- 01/02/2026 05:26:53 PM (12 days ago)
- Location:
- kabook-auto-rank-math-snippet
- Files:
-
- 1 added
- 15 edited
-
assets/screenshot-1.png (modified) (previous)
-
assets/screenshot-2.png (modified) (previous)
-
assets/screenshot-3.png (modified) (previous)
-
assets/screenshot-4.png (modified) (previous)
-
assets/screenshot-5.png (added)
-
trunk/assets/css/admin-style.css (modified) (1 diff)
-
trunk/assets/css/frontend-counter.css (modified) (2 diffs)
-
trunk/assets/css/frontend-style.css (modified) (4 diffs)
-
trunk/assets/js/admin-script.js (modified) (1 diff)
-
trunk/assets/js/frontend-script.js (modified) (2 diffs)
-
trunk/kabook-auto-rank-math-snippet.php (modified) (6 diffs)
-
trunk/languages/kabook-auto-rank-math-snippet-fa_IR.mo (modified) (previous)
-
trunk/languages/kabook-auto-rank-math-snippet-fa_IR.po (modified) (2 diffs)
-
trunk/languages/kabook-auto-rank-math-snippet.pot (modified) (2 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/uninstall.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
kabook-auto-rank-math-snippet/trunk/assets/css/admin-style.css
r3413121 r3431166 1 /* Kabook ARMS Admin Styles */ 2 3 /* Tab Navigation Styles */ 4 .karms-settings-wrap .nav-tab-wrapper { 5 margin-bottom: 20px; 6 border-bottom: 1px solid #c3c4c7; 7 } 8 9 /* Form Table Spacing */ 10 .form-table th { 11 padding: 20px 10px 20px 0; 12 width: 220px; 13 } 14 15 /* Small Input Fields (Numbers) */ 16 input.small-text { 17 width: 80px; 18 text-align: center; 19 } 20 21 /* Color Picker Container Alignment */ 22 .wp-picker-container { 23 display: inline-block; 24 vertical-align: middle; 25 } 26 27 /* Reset Button Styles */ 1 /** 2 * Admin Stylesheet for Kabook Auto Schema & Accordion 3 * * Handles the visual presentation of the plugin settings page within the WordPress admin area. 4 * Supports both LTR and RTL directions automatically based on WordPress core classes. 5 * 6 * @package Kabook Auto Rank Math Snippet 7 * @version 1.2.0 8 */ 9 10 /* ----------------------------------------------------------------------------- 11 * 1. Main Wrapper & Container 12 * ----------------------------------------------------------------------------- */ 13 .karms-admin-wrapper { 14 background: #fff; 15 padding: 0; 16 border-radius: 16px; 17 box-shadow: 0 5px 25px rgba(0, 0, 0, 0.05); 18 max-width: 1100px; 19 margin: 30px auto; 20 border: 1px solid #e0e0e0; 21 position: relative; 22 overflow: hidden; 23 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 24 direction: ltr; /* Default LTR orientation */ 25 } 26 27 /* RTL Support */ 28 body.rtl .karms-admin-wrapper { 29 direction: rtl; 30 } 31 32 /* ----------------------------------------------------------------------------- 33 * 2. Header Section 34 * ----------------------------------------------------------------------------- */ 35 .karms-header { 36 background: linear-gradient(135deg, #005bea 0%, #00c6fb 100%); 37 color: #fff; 38 padding: 25px 40px; 39 display: flex; 40 align-items: center; 41 justify-content: space-between; 42 } 43 44 body.rtl .karms-header { 45 flex-direction: row-reverse; 46 } 47 48 .karms-header h1 { 49 color: #fff !important; 50 margin: 0 !important; 51 font-size: 22px !important; 52 font-weight: 800 !important; 53 } 54 55 .karms-logo { 56 width: 45px; 57 height: 45px; 58 background: #fff; 59 border-radius: 50%; 60 display: flex; 61 align-items: center; 62 justify-content: center; 63 box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); 64 } 65 66 .karms-logo img { 67 max-width: 80%; 68 height: auto; 69 } 70 71 /* ----------------------------------------------------------------------------- 72 * 3. Navigation Tabs 73 * ----------------------------------------------------------------------------- */ 74 .karms-inner-content { 75 padding: 30px; 76 } 77 78 .karms-nav-tab-wrapper { 79 border-bottom: 1px solid #f0f0f0 !important; 80 padding-bottom: 20px !important; 81 margin-bottom: 35px !important; 82 display: flex; 83 gap: 12px; 84 } 85 86 body.rtl .karms-nav-tab-wrapper { 87 justify-content: flex-start; 88 } 89 90 .karms-nav-tab { 91 background: #f5f7fa !important; 92 border: none !important; 93 padding: 12px 30px !important; 94 border-radius: 50px !important; 95 color: #607d8b !important; 96 font-weight: 600 !important; 97 text-decoration: none; 98 transition: all 0.3s ease; 99 font-size: 14px; 100 } 101 102 .karms-nav-tab-active { 103 background: #005bea !important; 104 color: #fff !important; 105 box-shadow: 0 4px 12px rgba(0, 91, 234, 0.25); 106 } 107 108 /* ----------------------------------------------------------------------------- 109 * 4. Settings Field Rows 110 * ----------------------------------------------------------------------------- */ 111 .karms-settings-section-wrap h2 { 112 font-size: 1.3em; 113 color: #005bea; 114 margin: 40px 0 20px; 115 padding-bottom: 10px; 116 border-bottom: 2px solid #f8f9fa; 117 } 118 119 .karms-field-row { 120 display: flex; 121 align-items: center; 122 padding: 22px 0; 123 border-bottom: 1px solid #f8f9fa; 124 gap: 40px; 125 } 126 127 /* Flex direction handles RTL automatically via parent context */ 128 body.rtl .karms-field-row { 129 flex-direction: row; 130 } 131 132 .karms-field-label { 133 flex: 0 0 280px; 134 text-align: left; 135 } 136 137 body.rtl .karms-field-label { 138 text-align: right; 139 } 140 141 .karms-field-label label { 142 font-weight: 700; 143 color: #2c3338; 144 font-size: 15px; 145 } 146 147 .karms-field-input { 148 flex: 1; 149 } 150 151 .karms-field-input .description { 152 display: block; 153 margin-top: 8px; 154 font-size: 13px; 155 color: #646970; 156 line-height: 1.6; 157 } 158 159 /* ----------------------------------------------------------------------------- 160 * 5. Inputs & Form Controls 161 * ----------------------------------------------------------------------------- */ 162 .karms-admin-wrapper input[type="text"], 163 .karms-admin-wrapper input[type="number"], 164 .karms-admin-wrapper select { 165 border: 1px solid #d1d5db; 166 border-radius: 10px; 167 height: 44px; 168 padding: 0 15px; 169 width: 100%; 170 max-width: 400px; 171 background-color: #fdfdfd; 172 } 173 174 .karms-admin-wrapper input:focus { 175 border-color: #005bea; 176 box-shadow: 0 0 0 3px rgba(0, 91, 234, 0.08); 177 outline: none; 178 } 179 180 .karms-admin-wrapper input[type="checkbox"] { 181 width: 20px; 182 height: 20px; 183 margin: 0 8px; 184 border-radius: 6px; 185 } 186 187 /* ----------------------------------------------------------------------------- 188 * 6. Footer Actions 189 * ----------------------------------------------------------------------------- */ 190 .karms-submit-area { 191 margin-top: 40px; 192 padding-top: 25px; 193 border-top: 1px solid #eee; 194 display: flex; 195 justify-content: space-between; 196 align-items: center; 197 } 198 199 body.rtl .karms-submit-area { 200 flex-direction: row-reverse; 201 } 202 203 .button-primary.karms-save-btn { 204 background: #005bea !important; 205 border: none !important; 206 height: 48px !important; 207 padding: 0 40px !important; 208 border-radius: 12px !important; 209 font-weight: 700 !important; 210 font-size: 15px !important; 211 box-shadow: 0 4px 15px rgba(0, 91, 234, 0.2) !important; 212 } 213 28 214 #karms_reset_btn { 29 margin-top: 10px; 215 border-radius: 10px; 216 color: #d63638; 30 217 border-color: #d63638; 31 color: #d63638;32 218 } 33 219 34 220 #karms_reset_btn:hover { 35 background: #d63638; 36 color: #fff; 37 border-color: #d63638; 38 } 39 40 /* Field Descriptions */ 41 .description { 42 color: #646970; 43 font-style: italic; 44 margin-left: 5px; 45 } 221 background: #fcf2f2; 222 } -
kabook-auto-rank-math-snippet/trunk/assets/css/frontend-counter.css
r3413121 r3431166 1 /* Kabook ARMS Counter Styles (Fixed RTL & Icon Conflict) */ 1 /** 2 * Frontend Counter Stylesheet for Kabook Auto Schema & Accordion 3 * * Manages the automatic numbering of accordion items using CSS counters. 4 * Handles both LTR and RTL layouts correctly. 5 * 6 * @package Kabook Auto Rank Math Snippet 7 * @version 1.2.0 8 */ 2 9 3 /* 1. Initialize Counter */ 4 #rank-math-faq .rank-math-list-item { 5 counter-increment: karms-question-counter; 10 /* ----------------------------------------------------------------------------- 11 * 1. Initialize Counter Scope 12 * ----------------------------------------------------------------------------- */ 13 #rank-math-faq { 14 counter-reset: karms-counter; 6 15 } 7 16 8 /* 2. Number Styling (::before pseudo-element) */ 17 #rank-math-faq .rank-math-list-item { 18 counter-increment: karms-counter; 19 } 20 21 /* ----------------------------------------------------------------------------- 22 * 2. Number Styling & Positioning 23 * ----------------------------------------------------------------------------- */ 9 24 #rank-math-faq .rm-faq-question-btn::before { 10 content: counter(karms- question-counter) ".";25 content: counter(karms-counter) "."; 11 26 position: absolute; 12 27 top: 50%; 13 width: 25px; 28 transform: translateY(-50%); 29 font-weight: bold; 30 opacity: 0.8; 31 color: inherit; 32 width: 30px; /* Width reserved for the number */ 14 33 text-align: center; 15 color: inherit;16 font-weight: bold;17 transform: translateY(-50%);18 opacity: 0.7;19 z-index: 1;20 34 } 21 35 22 /* ========================================= 23 LTR Styles (Default/English) 24 ========================================= */ 25 #rank-math-faq .rank-math-question { 26 /* Right padding: Icon space | Left padding: Number space */ 27 padding: 15px 54px 15px 35px !important; 28 } 29 30 /* Position number on the left */ 36 /* ----------------------------------------------------------------------------- 37 * 3. LTR Positioning (Default) 38 * ----------------------------------------------------------------------------- */ 31 39 #rank-math-faq .rm-faq-question-btn::before { 32 40 left: 10px; … … 34 42 } 35 43 36 /* ========================================= 37 RTL Styles (Persian/Arabic) - Final Fix 38 ========================================= */ 39 40 /* A) Fix Padding (Swap spaces) */ 41 body.rtl #rank-math-faq .rank-math-question, 42 [dir="rtl"] #rank-math-faq .rank-math-question { 43 /* Right padding: Number space | Left padding: Icon space */ 44 padding: 15px 35px 15px 54px !important; 44 /* Adjust padding to prevent text overlap with the number */ 45 #rank-math-faq .rank-math-question { 46 padding-left: 45px !important; /* Space for number on the left */ 45 47 } 46 48 47 /* B) Fix Number Positioning (Move to right) */ 49 /* ----------------------------------------------------------------------------- 50 * 4. RTL Positioning (Right-to-Left Support) 51 * ----------------------------------------------------------------------------- */ 48 52 body.rtl #rank-math-faq .rm-faq-question-btn::before, 49 53 [dir="rtl"] #rank-math-faq .rm-faq-question-btn::before { 50 left: auto !important;51 right: 10px !important;54 left: auto; 55 right: 10px; 52 56 } 53 57 54 /* C) Fix +/- Icon Positioning (Move to left) */ 55 /* This resolves the overlap conflict between the number and the icon */ 56 body.rtl #rank-math-faq .rank-math-question::after, 57 [dir="rtl"] #rank-math-faq .rank-math-question::after { 58 right: auto !important; /* Remove from right */ 59 left: 0 !important; /* Move to left */ 58 /* Adjust padding for RTL layouts */ 59 body.rtl #rank-math-faq .rank-math-question { 60 padding-left: 54px !important; /* Space for the toggle icon on the left */ 61 padding-right: 45px !important; /* Space for the number on the right */ 60 62 } -
kabook-auto-rank-math-snippet/trunk/assets/css/frontend-style.css
r3413121 r3431166 1 /** 2 * Frontend Stylesheet for Kabook Auto Schema & Accordion 3 * * Controls the visual appearance of the accordion, including layout, colors, 4 * typography, and animations. Supports dynamic CSS variables injected by PHP. 5 * 6 * @package Kabook Auto Rank Math Snippet 7 * @version 1.2.0 8 */ 9 10 /* ----------------------------------------------------------------------------- 11 * 1. Global Variables & Defaults 12 * ----------------------------------------------------------------------------- */ 13 :root { 14 --karms-anim-speed: 300ms; 15 } 16 17 /* ----------------------------------------------------------------------------- 18 * 2. Container Styles 19 * ----------------------------------------------------------------------------- */ 1 20 #rank-math-faq .rank-math-list-item { 2 21 border: var(--karms-border-width) var(--karms-border-style) var(--karms-border-color); 3 border-radius: var(--karms-border-radius) ;22 border-radius: var(--karms-border-radius) !important; 4 23 margin-bottom: 20px; 5 position: relative; 6 overflow: hidden; 24 overflow: hidden; /* Ensures content doesn't overflow rounded corners */ 7 25 } 8 26 27 /* ----------------------------------------------------------------------------- 28 * 3. Question Block Styles 29 * ----------------------------------------------------------------------------- */ 9 30 #rank-math-faq .rank-math-question { 10 31 display: block; … … 16 37 background-color: var(--karms-question-bg-color); 17 38 margin: 0 !important; 18 padding: 15px 54px 15px 1 2px;39 padding: 15px 54px 15px 15px !important; /* Default LTR padding (Icon on right) */ 19 40 position: relative; 20 41 cursor: pointer; … … 22 43 } 23 44 24 #rank-math-faq .rank-math-question.rm-faq-question-active { 25 border-bottom: var(--karms-border-width) var(--karms-border-style) var(--karms-border-color); 26 } 27 45 /* Toggle Icon (+/-) Positioning */ 28 46 #rank-math-faq .rank-math-question::after { 29 47 content: "+"; … … 33 51 width: 54px; 34 52 text-align: center; 35 font-weight: 700;36 color: inherit;37 53 font-size: 20px; 38 54 transform: translateY(-50%); 55 transition: transform 0.3s ease; 39 56 } 40 57 58 /* Active State Icon */ 41 59 #rank-math-faq .rank-math-question.rm-faq-question-active::after { 42 60 content: "-"; 43 61 } 44 62 63 /* Accessibility Button Reset */ 64 #rank-math-faq .rm-faq-question-btn { 65 all: unset !important; 66 width: 100%; 67 display: block; 68 } 69 70 /* ----------------------------------------------------------------------------- 71 * 4. RTL Support (Right-to-Left) 72 * ----------------------------------------------------------------------------- */ 73 body.rtl #rank-math-faq .rank-math-question, 74 [dir="rtl"] #rank-math-faq .rank-math-question { 75 padding: 15px 15px 15px 54px !important; /* Swap padding for icon on left */ 76 } 77 78 body.rtl #rank-math-faq .rank-math-question::after, 79 [dir="rtl"] #rank-math-faq .rank-math-question::after { 80 right: auto; 81 left: 0; 82 } 83 84 /* ----------------------------------------------------------------------------- 85 * 5. Answer Block Styles 86 * ----------------------------------------------------------------------------- */ 45 87 #rank-math-faq .rank-math-answer { 88 display: none; 46 89 font-size: var(--karms-answer-font-size); 47 line-height: 1. 4!important;90 line-height: 1.6 !important; 48 91 text-align: var(--karms-answer-text-align); 49 92 color: var(--karms-answer-color); 50 93 background-color: var(--karms-answer-bg-color); 51 margin: 0; 52 padding: 12px; 53 display: none; 94 padding: 15px; 95 border-top: var(--karms-border-width) var(--karms-border-style) var(--karms-border-color); 54 96 } 55 97 56 #rank-math-faq .rank-math-answer p { 57 margin-bottom: .5em; 98 /* ----------------------------------------------------------------------------- 99 * 6. Animations 100 * ----------------------------------------------------------------------------- */ 101 102 /* Fade Animation Class */ 103 .karms-animate-fade { 104 animation: karmsFadeIn var(--karms-anim-speed, 300ms) ease-out forwards; 58 105 } 59 106 60 #rank-math-faq .rm-faq-question-btn { 61 all: unset !important; 107 /* Zoom Animation Class */ 108 .karms-animate-zoom { 109 animation: karmsZoomIn var(--karms-anim-speed, 300ms) cubic-bezier(0.34, 1.56, 0.64, 1) forwards; 62 110 } 111 112 /* Keyframes: Fade In */ 113 @keyframes karmsFadeIn { 114 from { opacity: 0; } 115 to { opacity: 1; } 116 } 117 118 /* Keyframes: Zoom In (with bounce effect) */ 119 @keyframes karmsZoomIn { 120 from { 121 opacity: 0; 122 transform: scale(0.85); 123 } 124 to { 125 opacity: 1; 126 transform: scale(1); 127 } 128 } -
kabook-auto-rank-math-snippet/trunk/assets/js/admin-script.js
r3413121 r3431166 1 /** 2 * Admin Script for Kabook Auto Schema & Accordion 3 * 4 * Handles administrative interface interactions, specifically the WordPress 5 * Color Picker initialization and the AJAX-based settings reset functionality. 6 * 7 * @package Kabook Auto Rank Math Snippet 8 * @version 1.2.0 9 */ 10 1 11 jQuery(document).ready(function($) { 2 // Initialize WordPress Color Picker 12 'use strict'; 13 14 /** 15 * Initialize WordPress Color Picker. 16 * Applies to all inputs with the .karms-color-picker class. 17 */ 3 18 $('.karms-color-picker').wpColorPicker(); 4 19 5 // Handle Reset Button Click 20 /** 21 * Handle Reset Button Click. 22 * Sends an AJAX request to reset all plugin settings to defaults. 23 */ 6 24 $('#karms_reset_btn').on('click', function(e) { 7 25 e.preventDefault(); 8 26 9 // Use localized confirmation message 10 if (confirm(karms_vars.confirm)) { 27 // Ensure localization object exists to prevent errors 28 if (typeof karms_vars === 'undefined') { 29 console.error('KARMS: Localization variable "karms_vars" not found.'); 30 return; 31 } 32 33 // Define fallback messages just in case PHP didn't pass them 34 const msgConfirm = karms_vars.confirm || 'Are you sure you want to reset all settings?'; 35 const msgSuccess = karms_vars.msg_success || 'Settings reset successfully.'; 36 const msgError = karms_vars.msg_error || 'Error resetting settings.'; 37 38 // 1. Confirm the action using localized text 39 if (confirm(msgConfirm)) { 40 41 // Disable button to prevent multiple clicks during request 42 const $btn = $(this); 43 $btn.prop('disabled', true); 44 11 45 $.ajax({ 12 url: ajaxurl, 46 url: ajaxurl, // Global WordPress AJAX URL 13 47 type: 'POST', 14 48 data: { 15 49 action: 'karms_reset_settings', 16 security: karms_vars.nonce // S ECURITY TOKEN50 security: karms_vars.nonce // Security Token 17 51 }, 18 52 success: function(response) { 19 53 if (response.success) { 20 alert('Settings reset to default. Please refresh the page.'); 54 // 2. Show success message (Localized) and reload 55 alert(msgSuccess); 21 56 location.reload(); 22 57 } else { 23 alert('Error resetting settings.'); 58 // 3. Show error message (Localized) 59 alert(msgError); 60 $btn.prop('disabled', false); 24 61 } 62 }, 63 error: function() { 64 // Handle network/server errors 65 alert(msgError); 66 $btn.prop('disabled', false); 25 67 } 26 68 }); -
kabook-auto-rank-math-snippet/trunk/assets/js/frontend-script.js
r3414326 r3431166 1 /** 2 * Frontend Script for Kabook Auto Schema & Accordion 3 * Handles the accordion functionality, ARIA accessibility attributes, 4 * and animation logic for the Rank Math FAQ schema. 5 * 6 * @package Kabook Auto Rank Math Snippet 7 */ 8 1 9 document.addEventListener('DOMContentLoaded', function() { 10 'use strict'; 11 2 12 const faqItems = document.querySelectorAll('#rank-math-faq .rank-math-list-item'); 3 13 if (!faqItems.length) return; 4 14 5 // 1. Setup Structure (Buttons & Attributes) 15 // Counter to ensure unique IDs without Math.random collision risk 16 let uniqueIdCounter = 0; 17 18 /** 19 * 1. Initialize Button Structure & ARIA Attributes 20 * Wraps the question text in a button for better accessibility. 21 */ 6 22 faqItems.forEach(item => { 7 const questionHeader = item.querySelector(' h3');23 const questionHeader = item.querySelector('.rank-math-question'); 8 24 if (!questionHeader) return; 9 25 10 // Generate unique ID 11 let idSuffix = item.id ? item.id.split('-')[2] : Math.floor(Math.random() * 1000); 12 if (!idSuffix) idSuffix = Math.floor(Math.random() * 1000); 26 // Increment counter for each item 27 uniqueIdCounter++; 28 const btnId = 'rm-accordion-' + uniqueIdCounter; 29 const panelId = 'rm-accordion-panel-' + uniqueIdCounter; 13 30 14 const btnId = 'rm-accordion-' + idSuffix;15 const panelId = 'rm-accordion-panel-' + idSuffix;16 17 // Convert H3 content to Button18 31 const innerHTML = questionHeader.innerHTML; 19 32 questionHeader.innerHTML = `<button class="rm-faq-question-btn" type="button" id="${btnId}" aria-controls="${panelId}" aria-expanded="false">${innerHTML}</button>`; 20 33 21 // Setup Panel22 34 const answerDiv = item.querySelector('.rank-math-answer'); 23 35 if (answerDiv) { 24 36 answerDiv.id = panelId; 25 37 answerDiv.setAttribute('aria-labelledby', btnId); 26 // Initial styling for JS toggle27 38 answerDiv.style.display = 'none'; 28 answerDiv.style.overflow = 'hidden';29 39 } 30 40 }); 31 41 32 // 2. Handle Click Events33 42 const questions = document.querySelectorAll('#rank-math-faq .rank-math-question'); 43 // Ensure config object is safe 44 const config = (typeof karms_settings !== 'undefined') ? karms_settings : { animation: 'slide', initial_expand_first: 0 }; 34 45 35 46 questions.forEach(question => { 36 47 question.addEventListener('click', function(e) { 37 // Prevent triggering if clicking inside the answer48 // Prevent triggering when clicking inside the answer content 38 49 if (e.target.closest('.rank-math-answer')) return; 39 50 … … 41 52 const currentBtn = currentItem.querySelector('button'); 42 53 const currentAnswer = currentItem.nextElementSibling; 43 44 54 const isActive = currentItem.classList.contains('rm-faq-question-active'); 45 55 46 // Close all others 56 /** 57 * 2. Accordion Mode: Close other items 58 * Loops through all questions and closes them if they are not the current item. 59 */ 47 60 questions.forEach(q => { 48 if (q !== currentItem ) {61 if (q !== currentItem && q.classList.contains('rm-faq-question-active')) { 49 62 q.classList.remove('rm-faq-question-active'); 50 63 const btn = q.querySelector('button'); 51 if (btn) btn.setAttribute('aria-expanded', 'false');64 if (btn) btn.setAttribute('aria-expanded', 'false'); 52 65 53 66 const ans = q.nextElementSibling; 54 if (ans && ans.classList.contains('rank-math-answer')) { 55 ans.classList.remove('rm-faq-answer-active'); 67 if (ans) { 56 68 ans.style.display = 'none'; 69 ans.classList.remove('karms-animate-fade', 'karms-animate-zoom'); 57 70 } 58 71 } 59 72 }); 60 73 61 // Toggle current 62 if (isActive) { 63 currentItem.classList.remove('rm-faq-question-active'); 64 if(currentBtn) currentBtn.setAttribute('aria-expanded', 'false'); 65 currentAnswer.classList.remove('rm-faq-answer-active'); 66 currentAnswer.style.display = 'none'; 67 } else { 68 currentItem.classList.add('rm-faq-question-active'); 69 if(currentBtn) currentBtn.setAttribute('aria-expanded', 'true'); 70 currentAnswer.classList.add('rm-faq-answer-active'); 71 currentAnswer.style.display = 'block'; 72 // Simple height animation can be added via CSS if needed 74 if (currentAnswer) { 75 /** 76 * 3. Reset Animation 77 * Removes animation classes and forces a reflow to restart the animation. 78 */ 79 currentAnswer.classList.remove('karms-animate-fade', 'karms-animate-zoom'); 80 void currentAnswer.offsetWidth; // Force Reflow 81 82 if (isActive) { 83 // Close the current item 84 currentItem.classList.remove('rm-faq-question-active'); 85 if (currentBtn) currentBtn.setAttribute('aria-expanded', 'false'); 86 currentAnswer.style.display = 'none'; 87 } else { 88 // Open the current item 89 currentItem.classList.add('rm-faq-question-active'); 90 if (currentBtn) currentBtn.setAttribute('aria-expanded', 'true'); 91 92 // Apply animation based on admin settings 93 if (config.animation === 'fade') { 94 currentAnswer.classList.add('karms-animate-fade'); 95 } else if (config.animation === 'zoom') { 96 currentAnswer.classList.add('karms-animate-zoom'); 97 } 98 99 currentAnswer.style.display = 'block'; 100 } 73 101 } 74 102 }); 75 103 }); 76 104 77 // 3. Initial Expand Logic 78 if (typeof karms_settings !== 'undefined' && karms_settings.initial_expand_first === '1') { 79 const firstQuestion = questions[0]; 80 if (firstQuestion) { 81 firstQuestion.classList.add('rm-faq-question-active'); 82 const btn = firstQuestion.querySelector('button'); 83 if(btn) btn.setAttribute('aria-expanded', 'true'); 84 85 const firstAnswer = firstQuestion.nextElementSibling; 86 if (firstAnswer) { 87 firstAnswer.classList.add('rm-faq-answer-active'); 88 firstAnswer.style.display = 'block'; 89 } 90 } 105 /** 106 * 4. Initial State 107 * Expand the first item if the option is enabled in settings. 108 */ 109 if (String(config.initial_expand_first) === '1' && questions[0]) { 110 // Use a small timeout to ensure DOM is fully ready for the click simulation 111 setTimeout(() => { 112 const firstBtn = questions[0].querySelector('button'); 113 if (firstBtn) firstBtn.click(); 114 }, 50); 91 115 } 92 116 }); -
kabook-auto-rank-math-snippet/trunk/kabook-auto-rank-math-snippet.php
r3414326 r3431166 3 3 * Plugin Name: Kabook Auto Schema & Accordion for Rank Math 4 4 * Description: Automatically injects Rank Math FAQ schema and converts it to a stylish, customizable accordion. 5 * Version: 1. 1.05 * Version: 1.2.0 6 6 * Author: Kabook (Saeid Afshari) 7 * Author URI: https:// kabook.ir/7 * Author URI: https://www.kabook.ir/ 8 8 * License: GPL-2.0+ 9 9 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt … … 11 11 * Domain Path: /languages 12 12 * Requires at least: 5.6 13 * Requires PHP: 8.0 14 * 15 * Credits: 16 * This plugin utilizes styling logic inspired by the "Convert Rank Math FAQ to Accordion" plugin. 13 * Requires PHP: 7.4 17 14 */ 18 15 19 16 if ( ! defined( 'ABSPATH' ) ) { 20 exit;17 exit; 21 18 } 22 19 … … 24 21 // 1. CONSTANTS 25 22 // ----------------------------------------------------------------------------- 26 define( 'KARMS_VERSION', '1. 1.0' );23 define( 'KARMS_VERSION', '1.2.0' ); 27 24 define( 'KARMS_PATH', plugin_dir_path( __FILE__ ) ); 28 25 define( 'KARMS_URL', plugin_dir_url( __FILE__ ) ); … … 32 29 // ----------------------------------------------------------------------------- 33 30 class KARMS_Loader { 34 public static function init() { 35 // Note: load_plugin_textdomain is removed to comply with WP.org standards. 36 // WordPress automatically loads translations defined in the "Domain Path" header. 37 38 // Core & Frontend 39 add_action( 'init', [ 'KARMS_Core', 'init' ] ); 40 add_action( 'wp_enqueue_scripts', [ 'KARMS_Accordion', 'enqueue_assets' ] ); 41 42 // Admin Hooks 43 add_action( 'admin_menu', [ 'KARMS_Admin', 'add_settings_page' ] ); 44 add_action( 'admin_init', [ 'KARMS_Admin', 'register_settings' ] ); 45 add_action( 'admin_enqueue_scripts', [ 'KARMS_Admin', 'enqueue_assets' ] ); 46 add_action( 'wp_ajax_karms_reset_settings', [ 'KARMS_Admin', 'ajax_reset_settings' ] ); 47 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), [ __CLASS__, 'add_settings_link' ] ); 48 49 // Dependency Check Notice 50 add_action( 'admin_notices', [ __CLASS__, 'check_rank_math_dependency' ] ); 51 52 // Meta Box Hooks 53 add_action( 'add_meta_boxes', [ 'KARMS_MetaBox', 'add_meta_box' ] ); 54 add_action( 'save_post', [ 'KARMS_MetaBox', 'save_meta_box' ] ); 55 } 56 57 public static function check_rank_math_dependency() { 58 if ( ! defined( 'RANK_MATH_PRO_FILE' ) ) { 59 ?> 60 <div class="notice notice-error is-dismissible"> 61 <p> 62 <?php 63 echo wp_kses_post( 64 sprintf( 65 /* translators: %s: Plugin Name */ 66 __( '%s requires Rank Math SEO PRO to be installed and active.', 'kabook-auto-rank-math-snippet' ), 67 '<strong>Kabook Auto Schema & Accordion</strong>' 68 ) 69 ); 70 ?> 71 </p> 72 </div> 73 <?php 74 } 75 } 76 77 public static function activate_plugin() { 78 if ( get_option( 'karms_options' ) === false ) { 79 update_option( 'karms_options', KARMS_Admin::get_default_options() ); 80 } 81 } 82 83 public static function add_settings_link( $links ) { 84 $settings_link = '<a href="options-general.php?page=karms-settings">' . esc_html__( 'Settings', 'kabook-auto-rank-math-snippet' ) . '</a>'; 85 array_unshift( $links, $settings_link ); 86 return $links; 87 } 88 } 31 32 public static function init() { 33 add_action( 'init', [ 'KARMS_Core', 'init' ] ); 34 add_action( 'wp_enqueue_scripts', [ 'KARMS_Accordion', 'enqueue_assets' ] ); 35 add_action( 'admin_menu', [ 'KARMS_Admin', 'add_settings_page' ] ); 36 add_action( 'admin_init', [ 'KARMS_Admin', 'register_settings' ] ); 37 add_action( 'admin_enqueue_scripts', [ 'KARMS_Admin', 'enqueue_assets' ] ); 38 add_action( 'wp_ajax_karms_reset_settings', [ 'KARMS_Admin', 'ajax_reset_settings' ] ); 39 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), [ __CLASS__, 'add_settings_link' ] ); 40 add_action( 'admin_notices', [ __CLASS__, 'check_rank_math_dependency' ] ); 41 add_action( 'add_meta_boxes', [ 'KARMS_MetaBox', 'add_meta_box' ] ); 42 add_action( 'save_post', [ 'KARMS_MetaBox', 'save_meta_box' ] ); 43 } 44 45 public static function check_rank_math_dependency() { 46 if ( ! defined( 'RANK_MATH_PRO_FILE' ) ) { 47 $msg = sprintf( 48 /* translators: 1: Plugin Name, 2: Dependency Name */ 49 esc_html__( '%1$s requires %2$s to be installed and active.', 'kabook-auto-rank-math-snippet' ), 50 '<strong>' . esc_html__( 'Kabook Auto Schema & Accordion', 'kabook-auto-rank-math-snippet' ) . '</strong>', 51 '<strong>' . esc_html__( 'Rank Math SEO PRO', 'kabook-auto-rank-math-snippet' ) . '</strong>' 52 ); 53 ?> 54 <div class="notice notice-error is-dismissible"> 55 <p><?php echo wp_kses_post( $msg ); ?></p> 56 </div> 57 <?php 58 } 59 } 60 61 public static function activate_plugin() { 62 if ( get_option( 'karms_options' ) === false ) { 63 update_option( 'karms_options', KARMS_Admin::get_default_options() ); 64 } 65 } 66 67 public static function add_settings_link( $links ) { 68 $label = esc_html__( 'Settings', 'kabook-auto-rank-math-snippet' ); 69 $settings_link = '<a href="options-general.php?page=karms-settings">' . $label . '</a>'; 70 array_unshift( $links, $settings_link ); 71 return $links; 72 } 73 } 74 89 75 // ----------------------------------------------------------------------------- 90 76 // 3. CORE LOGIC CLASS 91 77 // ----------------------------------------------------------------------------- 92 78 class KARMS_Core { 93 public static function init() { 94 add_filter( 'the_content', [ __CLASS__, 'maybe_inject_shortcode' ], 999 ); 95 } 96 97 public static function maybe_inject_shortcode( $content ) { 98 // Dependency Check 99 if ( ! defined( 'RANK_MATH_PRO_FILE' ) ) { return $content; } 100 101 // Context Check 102 if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { return $content; } 103 if ( ! is_single() || ! in_the_loop() || ! is_main_query() ) { return $content; } 104 105 global $post; 106 if ( ! $post instanceof WP_Post ) { return $content; } 107 108 // Check Meta Box Control & Global Settings 109 if ( ! self::should_inject( $post->ID ) ) { 110 return $content; 111 } 112 113 // 1. Check rendered content (Safety) 114 if ( has_shortcode( $content, 'rank_math_rich_snippet' ) ) { 115 return $content; 116 } 117 118 // 2. Check RAW post content (Anti-Duplication) 119 if ( has_shortcode( $post->post_content, 'rank_math_rich_snippet' ) ) { 120 return $content; 121 } 122 123 // 3. String check fallback 124 if ( strpos( $post->post_content, '[rank_math_rich_snippet' ) !== false ) { 125 return $content; 126 } 127 128 // Logic: Try specific ID, fallback to generic 129 $shortcode = self::get_shortcode_for_post( $post->ID ); 130 if ( $shortcode ) { 131 $content .= "\n\n" . do_shortcode( $shortcode ); 132 } 133 return $content; 134 } 135 136 protected static function should_inject( $post_id ) { 137 // 1. Check Local Override First 138 $local_override = get_post_meta( $post_id, '_karms_auto_inject_override', true ); 139 140 if ( 'enabled' === $local_override ) return true; 141 if ( 'disabled' === $local_override ) return false; 142 143 // 2. Fallback to Global Settings 144 $options = get_option( 'karms_options' ); 145 return isset( $options['auto_insert'] ) && $options['auto_insert'] == 1; 146 } 147 148 protected static function get_shortcode_for_post( $post_id ) { 149 $schema_id = get_post_meta( $post_id, 'rank_math_schema_id', true ); 150 if ( $schema_id ) { 151 return '[rank_math_rich_snippet id="' . esc_attr( $schema_id ) . '"]'; 152 } 153 return '[rank_math_rich_snippet]'; 154 } 79 80 public static function init() { 81 add_filter( 'the_content', [ __CLASS__, 'maybe_inject_shortcode' ], 999 ); 82 } 83 84 public static function maybe_inject_shortcode( $content ) { 85 if ( ! defined( 'RANK_MATH_PRO_FILE' ) ) { return $content; } 86 if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { return $content; } 87 if ( ! is_single() || ! in_the_loop() || ! is_main_query() ) { return $content; } 88 89 global $post; 90 if ( ! $post instanceof WP_Post ) { return $content; } 91 if ( ! self::should_inject( $post->ID ) ) { return $content; } 92 93 // Check if shortcode already exists to avoid duplication 94 if ( has_shortcode( $content, 'rank_math_rich_snippet' ) || 95 has_shortcode( $post->post_content, 'rank_math_rich_snippet' ) || 96 strpos( $post->post_content, '[rank_math_rich_snippet' ) !== false ) { 97 return $content; 98 } 99 100 $shortcode = self::get_shortcode_for_post( $post->ID ); 101 if ( $shortcode ) { 102 $content .= "\n\n" . do_shortcode( $shortcode ); 103 } 104 return $content; 105 } 106 107 protected static function should_inject( $post_id ) { 108 $local_override = get_post_meta( $post_id, '_karms_auto_inject_override', true ); 109 if ( 'enabled' === $local_override ) return true; 110 if ( 'disabled' === $local_override ) return false; 111 $options = get_option( 'karms_options' ); 112 return isset( $options['auto_insert'] ) && $options['auto_insert'] == 1; 113 } 114 115 protected static function get_shortcode_for_post( $post_id ) { 116 $schema_id = get_post_meta( $post_id, 'rank_math_schema_id', true ); 117 if ( $schema_id ) { 118 return '[rank_math_rich_snippet id="' . esc_attr( $schema_id ) . '"]'; 119 } 120 return '[rank_math_rich_snippet]'; 121 } 155 122 } 156 123 … … 159 126 // ----------------------------------------------------------------------------- 160 127 class KARMS_Accordion { 161 public static function enqueue_assets() { 162 $options = get_option( 'karms_options' ); 163 if ( ! $options || ! is_array( $options ) ) { 164 $options = KARMS_Admin::get_default_options(); 165 } 166 167 if ( empty( $options['accordion_enabled'] ) ) { 168 return; 169 } 170 171 wp_enqueue_style( 'karms-frontend-style', KARMS_URL . 'assets/css/frontend-style.css', [], KARMS_VERSION ); 172 173 // Vanilla JS - Loading in footer 174 wp_enqueue_script( 'karms-frontend-script', KARMS_URL . 'assets/js/frontend-script.js', [], KARMS_VERSION, true ); 175 176 $js_settings = [ 177 'initial_expand_first' => isset( $options['initial_expand_first'] ) ? $options['initial_expand_first'] : 0, 178 ]; 179 wp_localize_script( 'karms-frontend-script', 'karms_settings', $js_settings ); 180 181 if ( ! empty( $options['counter_enabled'] ) ) { 182 wp_enqueue_style( 'karms-frontend-counter', KARMS_URL . 'assets/css/frontend-counter.css', [], KARMS_VERSION ); 183 } 184 185 self::add_inline_styles( $options ); 186 } 187 188 private static function add_inline_styles( $opts ) { 189 $defaults = KARMS_Admin::get_default_options(); 190 $get_opt = function( $key ) use ( $opts, $defaults ) { 191 return isset( $opts[ $key ] ) && $opts[ $key ] !== '' ? $opts[ $key ] : $defaults[ $key ]; 192 }; 193 194 // Mapping options to CSS Variables 195 $css_vars = [ 196 'border-color' => $get_opt( 'border_color' ), 197 'border-width' => absint( $get_opt( 'border_width' ) ), 198 'border-style' => $get_opt( 'border_style' ), 199 'border-radius' => absint( $get_opt( 'border_radius' ) ), 200 'question-font-size' => absint( $get_opt( 'question_font_size' ) ), 201 'question-color' => $get_opt( 'question_color' ), 202 'question-bg-color' => $get_opt( 'question_background_color' ), 203 'question-text-align'=> $get_opt( 'question_text_align' ), 204 'answer-font-size' => absint( $get_opt( 'answer_font_size' ) ), 205 'answer-color' => $get_opt( 'answer_color' ), 206 'answer-bg-color' => $get_opt( 'answer_background_color' ), 207 'answer-text-align' => $get_opt( 'answer_text_align' ), 208 ]; 209 210 $custom_css = ":root {"; 211 foreach( $css_vars as $key => $val ) { 212 if( strpos($key, 'width') !== false || strpos($key, 'size') !== false || strpos($key, 'radius') !== false ) { 213 $val .= 'px'; 214 } 215 $custom_css .= sprintf( '--karms-%s: %s;', esc_attr( $key ), esc_attr( $val ) ); 216 } 217 $custom_css .= "}"; 218 219 wp_add_inline_style( 'karms-frontend-style', $custom_css ); 220 } 128 129 public static function enqueue_assets() { 130 if ( ! is_singular() ) { return; } 131 global $post; 132 if ( ! $post ) { return; } 133 134 $options = get_option( 'karms_options', KARMS_Admin::get_default_options() ); 135 if ( empty( $options['accordion_enabled'] ) ) { return; } 136 137 $has_shortcode = has_shortcode( $post->post_content, 'rank_math_rich_snippet' ); 138 $auto_inject = isset( $options['auto_insert'] ) && $options['auto_insert'] == 1; 139 140 if ( ! $has_shortcode && ! $auto_inject ) { return; } 141 142 wp_enqueue_style( 'karms-frontend-style', KARMS_URL . 'assets/css/frontend-style.css', [], KARMS_VERSION ); 143 wp_enqueue_script( 'karms-frontend-script', KARMS_URL . 'assets/js/frontend-script.js', [], KARMS_VERSION, true ); 144 145 $js_settings = [ 146 'initial_expand_first' => isset( $options['initial_expand_first'] ) ? $options['initial_expand_first'] : 0, 147 'animation' => isset( $options['accordion_animation'] ) ? $options['accordion_animation'] : 'slide', 148 ]; 149 wp_localize_script( 'karms-frontend-script', 'karms_settings', $js_settings ); 150 151 if ( ! empty( $options['counter_enabled'] ) ) { 152 wp_enqueue_style( 'karms-frontend-counter', KARMS_URL . 'assets/css/frontend-counter.css', [], KARMS_VERSION ); 153 } 154 155 self::add_inline_styles( $options ); 156 } 157 158 private static function add_inline_styles( $opts ) { 159 $defaults = KARMS_Admin::get_default_options(); 160 $get_opt = function( $key ) use ( $opts, $defaults ) { 161 return isset( $opts[ $key ] ) && $opts[ $key ] !== '' ? $opts[ $key ] : $defaults[ $key ]; 162 }; 163 164 $css_vars = [ 165 'border-color' => $get_opt( 'border_color' ), 166 'border-width' => absint( $get_opt( 'border_width' ) ), 167 'border-style' => $get_opt( 'border_style' ), 168 'border-radius' => absint( $get_opt( 'border_radius' ) ), 169 'question-font-size' => absint( $get_opt( 'question_font_size' ) ), 170 'question-color' => $get_opt( 'question_color' ), 171 'question-bg-color' => $get_opt( 'question_background_color' ), 172 'question-text-align' => $get_opt( 'question_text_align' ), 173 'answer-font-size' => absint( $get_opt( 'answer_font_size' ) ), 174 'answer-color' => $get_opt( 'answer_color' ), 175 'answer-bg-color' => $get_opt( 'answer_background_color' ), 176 'answer-text-align' => $get_opt( 'answer_text_align' ), 177 ]; 178 179 $custom_css = ":root {"; 180 foreach( $css_vars as $key => $val ) { 181 if( strpos($key, 'width') !== false || strpos($key, 'size') !== false || strpos($key, 'radius') !== false ) { 182 $val .= 'px'; 183 } 184 $custom_css .= sprintf( '--karms-%s: %s;', esc_attr( $key ), esc_attr( $val ) ); 185 } 186 $custom_css .= sprintf( '--karms-anim-speed: %dms;', absint( $get_opt( 'accordion_speed' ) ) ); 187 $custom_css .= "}"; 188 wp_add_inline_style( 'karms-frontend-style', $custom_css ); 189 } 221 190 } 222 191 … … 225 194 // ----------------------------------------------------------------------------- 226 195 class KARMS_MetaBox { 227 public static function add_meta_box() { 228 $options = get_option( 'karms_options' ); 229 if ( empty( $options['show_meta_box'] ) ) { 230 return; 231 } 232 233 $screens = [ 'post', 'page', 'product' ]; 234 foreach ( $screens as $screen ) { 235 add_meta_box( 236 'karms_injection_metabox', 237 esc_html__( 'Schema Injection Settings', 'kabook-auto-rank-math-snippet' ), 238 [ __CLASS__, 'render_meta_box' ], 239 $screen, 240 'side', 241 'default' 242 ); 243 } 244 } 245 246 public static function render_meta_box( $post ) { 247 $value = get_post_meta( $post->ID, '_karms_auto_inject_override', true ); 248 if ( empty( $value ) ) { 249 $value = 'default'; 250 } 251 252 wp_nonce_field( 'karms_save_meta_box_data', 'karms_meta_box_nonce' ); 253 254 echo '<label for="karms_auto_inject_override">'; 255 esc_html_e( 'Auto Inject Schema for this post:', 'kabook-auto-rank-math-snippet' ); 256 echo '</label><br>'; 257 258 echo '<select name="karms_auto_inject_override" id="karms_auto_inject_override" style="width:100%; margin-top:5px;">'; 259 echo '<option value="default" ' . selected( $value, 'default', false ) . '>' . esc_html__( 'Default (Global Settings)', 'kabook-auto-rank-math-snippet' ) . '</option>'; 260 echo '<option value="enabled" ' . selected( $value, 'enabled', false ) . '>' . esc_html__( 'Enable / Force Inject', 'kabook-auto-rank-math-snippet' ) . '</option>'; 261 echo '<option value="disabled" ' . selected( $value, 'disabled', false ) . '>' . esc_html__( 'Disable', 'kabook-auto-rank-math-snippet' ) . '</option>'; 262 echo '</select>'; 263 264 echo '<p class="description" style="margin-top: 8px;">'; 265 esc_html_e( 'Override the global auto-injection setting for this specific post.', 'kabook-auto-rank-math-snippet' ); 266 echo '</p>'; 267 } 268 269 public static function save_meta_box( $post_id ) { 270 if ( ! isset( $_POST['karms_meta_box_nonce'] ) ) { return; } 271 272 $nonce = sanitize_text_field( wp_unslash( $_POST['karms_meta_box_nonce'] ) ); 273 if ( ! wp_verify_nonce( $nonce, 'karms_save_meta_box_data' ) ) { return; } 274 275 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } 276 if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } 277 278 if ( isset( $_POST['karms_auto_inject_override'] ) ) { 279 $new_val = sanitize_key( $_POST['karms_auto_inject_override'] ); 280 if ( in_array( $new_val, [ 'default', 'enabled', 'disabled' ] ) ) { 281 update_post_meta( $post_id, '_karms_auto_inject_override', $new_val ); 282 } 283 } 284 } 285 } 286 287 // ----------------------------------------------------------------------------- 288 // 6. ADMIN CLASS 196 197 public static function add_meta_box() { 198 $options = get_option( 'karms_options' ); 199 if ( empty( $options['show_meta_box'] ) ) { return; } 200 201 $screens = [ 'post', 'page', 'product' ]; 202 foreach ( $screens as $screen ) { 203 add_meta_box( 204 'karms_injection_metabox', 205 esc_html__( 'Schema Injection Settings', 'kabook-auto-rank-math-snippet' ), 206 [ __CLASS__, 'render_meta_box' ], 207 $screen, 208 'side', 209 'default' 210 ); 211 } 212 } 213 214 public static function render_meta_box( $post ) { 215 $value = get_post_meta( $post->ID, '_karms_auto_inject_override', true ); 216 if ( empty( $value ) ) { $value = 'default'; } 217 218 wp_nonce_field( 'karms_save_meta_box_data', 'karms_meta_box_nonce' ); 219 220 echo '<label for="karms_auto_inject_override">'; 221 esc_html_e( 'Auto Inject Schema for this post:', 'kabook-auto-rank-math-snippet' ); 222 echo '</label><br>'; 223 224 echo '<select name="karms_auto_inject_override" id="karms_auto_inject_override" style="width:100%; margin-top:5px;">'; 225 echo '<option value="default" ' . selected( $value, 'default', false ) . '>' . esc_html__( 'Default (Global Settings)', 'kabook-auto-rank-math-snippet' ) . '</option>'; 226 echo '<option value="enabled" ' . selected( $value, 'enabled', false ) . '>' . esc_html__( 'Enable / Force Inject', 'kabook-auto-rank-math-snippet' ) . '</option>'; 227 echo '<option value="disabled" ' . selected( $value, 'disabled', false ) . '>' . esc_html__( 'Disable', 'kabook-auto-rank-math-snippet' ) . '</option>'; 228 echo '</select>'; 229 230 echo '<p class="description" style="margin-top: 8px;">'; 231 esc_html_e( 'Override the global auto-injection setting for this specific post.', 'kabook-auto-rank-math-snippet' ); 232 echo '</p>'; 233 } 234 235 public static function save_meta_box( $post_id ) { 236 if ( ! isset( $_POST['karms_meta_box_nonce'] ) ) { return; } 237 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['karms_meta_box_nonce'] ) ), 'karms_save_meta_box_data' ) ) { return; } 238 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } 239 if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } 240 241 if ( isset( $_POST['karms_auto_inject_override'] ) ) { 242 $new_val = sanitize_key( $_POST['karms_auto_inject_override'] ); 243 if ( in_array( $new_val, [ 'default', 'enabled', 'disabled' ] ) ) { 244 update_post_meta( $post_id, '_karms_auto_inject_override', $new_val ); 245 } 246 } 247 } 248 } 249 250 // ----------------------------------------------------------------------------- 251 // 6. ADMIN SETTINGS CLASS 289 252 // ----------------------------------------------------------------------------- 290 253 class KARMS_Admin { 291 public static function get_default_options() { 292 return [ 293 'auto_insert' => 1, 294 'show_meta_box' => 0, 295 'accordion_enabled' => 1, 296 'counter_enabled' => 0, 297 'initial_expand_first' => 0, 298 'question_font_size' => 18, 299 'question_color' => '#003952', 300 'question_background_color' => '#e2f6ff', 301 'question_text_align' => 'left', 302 'answer_font_size' => 16, 303 'answer_color' => '#003952', 304 'answer_background_color' => '#f3fbff', 305 'answer_text_align' => 'left', 306 'border_width' => 1, 307 'border_style' => 'solid', 308 'border_color' => '#c1ecff', 309 'border_radius' => 4, 310 ]; 311 } 312 313 public static function add_settings_page() { 314 add_options_page( 315 esc_html__( 'Settings for Rank Math Snippet', 'kabook-auto-rank-math-snippet' ), 316 esc_html__( 'Kabook RM Snippet', 'kabook-auto-rank-math-snippet' ), 317 'manage_options', 318 'karms-settings', 319 [ __CLASS__, 'render_settings_page' ] 320 ); 321 } 322 323 public static function enqueue_assets( $hook ) { 324 if ( 'settings_page_karms-settings' !== $hook ) { return; } 325 326 wp_enqueue_style( 'wp-color-picker' ); 327 wp_enqueue_style( 'karms-admin-css', KARMS_URL . 'assets/css/admin-style.css', [], KARMS_VERSION ); 328 wp_enqueue_script( 'karms-admin-js', KARMS_URL . 'assets/js/admin-script.js', [ 'jquery', 'wp-color-picker' ], KARMS_VERSION, true ); 329 330 wp_localize_script( 'karms-admin-js', 'karms_vars', [ 331 'nonce' => wp_create_nonce( 'karms_reset_nonce_action' ), 332 'confirm' => esc_html__( 'Are you sure you want to reset all settings to default?', 'kabook-auto-rank-math-snippet' ) 333 ]); 334 } 335 336 public static function register_settings() { 337 register_setting( 'karms_options_group', 'karms_options', [ __CLASS__, 'sanitize_options' ] ); 338 339 add_settings_section( 'karms_general_section', esc_html__( 'General Settings', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-general' ); 340 341 add_settings_field( 'auto_insert', esc_html__( 'Auto Inject Schema', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 342 'label_for' => 'auto_insert', 343 'desc' => esc_html__( 'Automatically add [rank_math_rich_snippet] to posts if missing.', 'kabook-auto-rank-math-snippet' ) . 344 '<br><br><span style="color:#d63638; font-weight:600;">' . esc_html__( 'Important:', 'kabook-auto-rank-math-snippet' ) . '</span> ' . 345 esc_html__( 'If you use other schemas like "HowTo" in a specific post, please DISABLE auto-injection for that post using the "Injection Control Meta Box" (in the post editor) and insert shortcodes manually to avoid conflicts.', 'kabook-auto-rank-math-snippet' ), 346 ] ); 347 348 add_settings_field( 'show_meta_box', esc_html__( 'Show Injection Control Meta Box', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 349 'label_for' => 'show_meta_box', 350 'desc' => esc_html__( 'Display a meta box in the post editor to manually Enable/Disable injection per post.', 'kabook-auto-rank-math-snippet' ), 351 ] ); 352 353 add_settings_field( 'accordion_enabled', esc_html__( 'Enable Accordion Style', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 354 'label_for' => 'accordion_enabled', 355 'desc' => esc_html__( 'Convert the FAQ schema into an accordion style.', 'kabook-auto-rank-math-snippet' ), 356 ] ); 357 add_settings_field( 'counter_enabled', esc_html__( 'Enable Numbering', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'counter_enabled' ] ); 358 add_settings_field( 'initial_expand_first', esc_html__( 'Expand First Item', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'initial_expand_first' ] ); 359 360 add_settings_section( 'karms_style_question', esc_html__( 'Question Styling', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 361 add_settings_field( 'question_font_size', esc_html__( 'Font Size (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_question', [ 'label_for' => 'question_font_size' ] ); 362 add_settings_field( 'question_color', esc_html__( 'Text Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_question', [ 'label_for' => 'question_color' ] ); 363 add_settings_field( 'question_background_color', esc_html__( 'Background Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_question', [ 'label_for' => 'question_background_color' ] ); 364 add_settings_field( 'question_text_align', esc_html__( 'Text Align', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_align' ], 'karms-settings-style', 'karms_style_question', [ 'label_for' => 'question_text_align' ] ); 365 366 add_settings_section( 'karms_style_answer', esc_html__( 'Answer Styling', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 367 add_settings_field( 'answer_font_size', esc_html__( 'Font Size (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_answer', [ 'label_for' => 'answer_font_size' ] ); 368 add_settings_field( 'answer_color', esc_html__( 'Text Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_answer', [ 'label_for' => 'answer_color' ] ); 369 add_settings_field( 'answer_background_color', esc_html__( 'Background Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_answer', [ 'label_for' => 'answer_background_color' ] ); 370 add_settings_field( 'answer_text_align', esc_html__( 'Text Align', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_align' ], 'karms-settings-style', 'karms_style_answer', [ 'label_for' => 'answer_text_align' ] ); 371 372 add_settings_section( 'karms_style_border', esc_html__( 'Border Styling', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 373 add_settings_field( 'border_width', esc_html__( 'Width (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_width' ] ); 374 add_settings_field( 'border_style', esc_html__( 'Style', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_border' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_style' ] ); 375 add_settings_field( 'border_color', esc_html__( 'Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_color' ] ); 376 add_settings_field( 'border_radius', esc_html__( 'Radius (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_radius' ] ); 377 } 378 379 public static function render_settings_page() { 380 if ( ! current_user_can( 'manage_options' ) ) { return; } 381 382 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 383 $active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'general'; 384 $base_url = admin_url( 'options-general.php?page=karms-settings' ); 385 386 ?> 387 <div class="wrap karms-settings-wrap" style="position: relative;"> 388 <h1 style="margin-bottom: 20px;"><?php esc_html_e( 'Kabook Auto Schema & Accordion for Rank Math', 'kabook-auto-rank-math-snippet' ); ?></h1> 389 390 <div style="border-bottom: 1px solid #c3c4c7; margin-bottom: 20px; padding-bottom: 0; position: relative; z-index: 99;"> 391 <?php 392 $tab_style_base = 'text-decoration: none; padding: 10px 15px; border: 1px solid #c3c4c7; border-bottom: none; margin-left: 5px; display: inline-block; background: #e5e5e5; color: #50575e; font-weight: 500; font-size: 14px;'; 393 $tab_style_active = 'background: #f0f0f1; border-bottom: 1px solid #f0f0f1; color: #000; margin-bottom: -1px;'; 394 ?> 395 <a href="<?php echo esc_url( $base_url . '&tab=general' ); ?>" style="<?php echo esc_attr( $tab_style_base . ( $active_tab == 'general' ? $tab_style_active : '' ) ); ?>"> 396 <?php esc_html_e( 'General', 'kabook-auto-rank-math-snippet' ); ?> 397 </a> 398 <a href="<?php echo esc_url( $base_url . '&tab=style' ); ?>" style="<?php echo esc_attr( $tab_style_base . ( $active_tab == 'style' ? $tab_style_active : '' ) ); ?>"> 399 <?php esc_html_e( 'Accordion Styles', 'kabook-auto-rank-math-snippet' ); ?> 400 </a> 401 </div> 402 403 <form action="options.php" method="post"> 404 <?php 405 settings_fields( 'karms_options_group' ); 406 echo '<input type="hidden" name="karms_current_tab_context" value="' . esc_attr( $active_tab ) . '">'; 407 408 if ( $active_tab == 'general' ) { 409 do_settings_sections( 'karms-settings-general' ); 410 } else { 411 do_settings_sections( 'karms-settings-style' ); 412 } 413 submit_button(); 414 ?> 415 <div style="margin-top: 20px; border-top: 1px solid #ccc; padding-top: 20px;"> 416 <button type="button" id="karms_reset_btn" class="button button-secondary" style="color: #a00; border-color: #a00;"> 417 <?php esc_html_e( 'Reset to Defaults', 'kabook-auto-rank-math-snippet' ); ?> 418 </button> 419 </div> 420 </form> 421 </div> 422 <?php 423 } 424 425 public static function sanitize_options( $input ) { 426 $current_options = get_option( 'karms_options', self::get_default_options() ); 427 if ( ! is_array( $current_options ) ) { $current_options = self::get_default_options(); } 428 429 $defaults = self::get_default_options(); 430 $new_input = $current_options; 431 432 // phpcs:ignore WordPress.Security.NonceVerification.Missing 433 $context = isset( $_POST['karms_current_tab_context'] ) ? sanitize_text_field( wp_unslash( $_POST['karms_current_tab_context'] ) ) : 'general'; 434 435 $general_keys = [ 'auto_insert', 'show_meta_box', 'accordion_enabled', 'counter_enabled', 'initial_expand_first' ]; 436 437 if ( $context === 'general' ) { 438 foreach ( $general_keys as $key ) { 439 $new_input[ $key ] = isset( $input[ $key ] ) ? 1 : 0; 440 } 441 } else { 442 foreach ( $defaults as $key => $default ) { 443 if ( ! in_array( $key, $general_keys, true ) ) { 444 if ( isset( $input[ $key ] ) ) { 445 if ( strpos( $key, 'color' ) !== false ) { 446 $new_input[ $key ] = sanitize_hex_color( $input[ $key ] ); 447 } elseif ( is_numeric( $default ) ) { 448 $new_input[ $key ] = absint( $input[ $key ] ); 449 } else { 450 $new_input[ $key ] = sanitize_text_field( $input[ $key ] ); 451 } 452 } 453 } 454 } 455 } 456 return $new_input; 457 } 458 459 public static function field_checkbox( $args ) { 460 $options = get_option( 'karms_options', self::get_default_options() ); 461 $key = $args['label_for']; 462 $checked = isset( $options[ $key ] ) ? $options[ $key ] : 0; 463 echo '<input type="checkbox" name="karms_options[' . esc_attr( $key ) . ']" value="1" ' . checked( 1, $checked, false ) . ' /> '; 464 if ( ! empty( $args['desc'] ) ) { 465 echo '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>'; 466 } 467 } 468 public static function field_number( $args ) { 469 $options = get_option( 'karms_options', self::get_default_options() ); 470 $key = $args['label_for']; 471 $val = isset( $options[ $key ] ) ? $options[ $key ] : ''; 472 echo '<input type="number" name="karms_options[' . esc_attr( $key ) . ']" value="' . esc_attr( $val ) . '" class="small-text" />'; 473 } 474 public static function field_color( $args ) { 475 $options = get_option( 'karms_options', self::get_default_options() ); 476 $key = $args['label_for']; 477 $val = isset( $options[ $key ] ) ? $options[ $key ] : ''; 478 $defaults = self::get_default_options(); 479 $def = isset( $defaults[ $key ] ) ? $defaults[ $key ] : ''; 480 echo '<input type="text" name="karms_options[' . esc_attr( $key ) . ']" value="' . esc_attr( $val ) . '" class="karms-color-picker" data-default-color="' . esc_attr( $def ) . '" />'; 481 } 482 public static function field_select_align( $args ) { 483 $options = get_option( 'karms_options', self::get_default_options() ); 484 $key = $args['label_for']; 485 $val = isset( $options[ $key ] ) ? $options[ $key ] : 'left'; 486 echo '<select name="karms_options[' . esc_attr( $key ) . ']">'; 487 foreach ( [ 'left', 'center', 'right' ] as $item ) { 488 echo '<option value="' . esc_attr( $item ) . '" ' . selected( $item, $val, false ) . '>' . esc_html( ucfirst( $item ) ) . '</option>'; 489 } 490 echo '</select>'; 491 } 492 public static function field_select_border( $args ) { 493 $options = get_option( 'karms_options', self::get_default_options() ); 494 $key = $args['label_for']; 495 $val = isset( $options[ $key ] ) ? $options[ $key ] : 'solid'; 496 echo '<select name="karms_options[' . esc_attr( $key ) . ']">'; 497 foreach ( [ 'solid', 'dashed', 'dotted', 'none' ] as $item ) { 498 echo '<option value="' . esc_attr( $item ) . '" ' . selected( $item, $val, false ) . '>' . esc_html( ucfirst( $item ) ) . '</option>'; 499 } 500 echo '</select>'; 501 } 502 503 public static function ajax_reset_settings() { 504 check_ajax_referer( 'karms_reset_nonce_action', 'security' ); 505 if ( ! current_user_can( 'manage_options' ) ) { 506 wp_send_json_error(); 507 } 508 remove_filter( 'sanitize_option_karms_options', [ __CLASS__, 'sanitize_options' ] ); 509 update_option( 'karms_options', self::get_default_options() ); 510 wp_send_json_success(); 511 } 512 } 513 514 // ----------------------------------------------------------------------------- 515 // 7. INIT 254 255 public static function get_default_options() { 256 return [ 257 'auto_insert' => 1, 258 'show_meta_box' => 0, 259 'accordion_enabled' => 1, 260 'counter_enabled' => 0, 261 'initial_expand_first' => 0, 262 'accordion_animation' => 'slide', 263 'accordion_speed' => 300, 264 'question_font_size' => 18, 265 'question_color' => '#003952', 266 'question_background_color' => '#e2f6ff', 267 'question_text_align' => 'left', 268 'answer_font_size' => 16, 269 'answer_color' => '#003952', 270 'answer_background_color' => '#f3fbff', 271 'answer_text_align' => 'left', 272 'border_width' => 1, 273 'border_style' => 'solid', 274 'border_color' => '#c1ecff', 275 'border_radius' => 12, 276 ]; 277 } 278 279 public static function add_settings_page() { 280 add_options_page( 281 esc_html__( 'Kabook Auto Schema Settings', 'kabook-auto-rank-math-snippet' ), 282 esc_html__( 'Kabook RM Snippet', 'kabook-auto-rank-math-snippet' ), 283 'manage_options', 284 'karms-settings', 285 [ __CLASS__, 'render_settings_page' ] 286 ); 287 } 288 289 public static function enqueue_assets( $hook ) { 290 if ( 'settings_page_karms-settings' !== $hook ) { return; } 291 292 wp_enqueue_style( 'wp-color-picker' ); 293 wp_enqueue_style( 'karms-admin-css', KARMS_URL . 'assets/css/admin-style.css', [], KARMS_VERSION ); 294 wp_enqueue_script( 'karms-admin-js', KARMS_URL . 'assets/js/admin-script.js', [ 'jquery', 'wp-color-picker' ], KARMS_VERSION, true ); 295 296 wp_localize_script( 'karms-admin-js', 'karms_vars', [ 297 'nonce' => wp_create_nonce( 'karms_reset_nonce_action' ), 298 'confirm' => esc_html__( 'Are you sure you want to reset all settings to default?', 'kabook-auto-rank-math-snippet' ), 299 'msg_success' => esc_html__( 'Settings reset successfully. Reloading...', 'kabook-auto-rank-math-snippet' ), 300 'msg_error' => esc_html__( 'Error resetting settings. Please try again.', 'kabook-auto-rank-math-snippet' ), 301 ]); 302 } 303 304 public static function register_settings() { 305 register_setting( 'karms_options_group', 'karms_options', [ __CLASS__, 'sanitize_options' ] ); 306 307 // TAB 1: General Settings 308 add_settings_section( 'karms_general_section', esc_html__( 'General Settings', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-general' ); 309 add_settings_field( 'auto_insert', esc_html__( 'Auto Inject Schema', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'auto_insert', 'desc' => esc_html__( 'Automatically add [rank_math_rich_snippet] to posts if missing.', 'kabook-auto-rank-math-snippet' ) ] ); 310 add_settings_field( 'show_meta_box', esc_html__( 'Show Meta Box', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'show_meta_box', 'desc' => esc_html__( 'Show per-post injection control.', 'kabook-auto-rank-math-snippet' ) ] ); 311 add_settings_field( 'accordion_enabled', esc_html__( 'Enable Accordion', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'accordion_enabled' ] ); 312 add_settings_field( 'counter_enabled', esc_html__( 'Enable Numbering', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'counter_enabled' ] ); 313 add_settings_field( 'initial_expand_first', esc_html__( 'Expand First Item', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_checkbox' ], 'karms-settings-general', 'karms_general_section', [ 'label_for' => 'initial_expand_first' ] ); 314 315 // TAB 2: Styles & Animations 316 add_settings_section( 'karms_style_main', esc_html__( 'Animation Settings', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 317 add_settings_field( 'accordion_animation', esc_html__( 'Opening Animation', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_animation' ], 'karms-settings-style', 'karms_style_main', [ 'label_for' => 'accordion_animation' ] ); 318 add_settings_field( 'accordion_speed', esc_html__( 'Animation Speed (ms)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_main', [ 'label_for' => 'accordion_speed', 'desc' => esc_html__( 'e.g. 300 for fast, 1200 for slow.', 'kabook-auto-rank-math-snippet' ) ] ); 319 320 add_settings_section( 'karms_style_q', esc_html__( 'Question Styles', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 321 add_settings_field( 'question_font_size', esc_html__( 'Font Size (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_q', [ 'label_for' => 'question_font_size' ] ); 322 add_settings_field( 'question_color', esc_html__( 'Text Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_q', [ 'label_for' => 'question_color' ] ); 323 add_settings_field( 'question_background_color', esc_html__( 'Background Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_q', [ 'label_for' => 'question_background_color' ] ); 324 add_settings_field( 'question_text_align', esc_html__( 'Text Alignment', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_align' ], 'karms-settings-style', 'karms_style_q', [ 'label_for' => 'question_text_align' ] ); 325 326 add_settings_section( 'karms_style_a', esc_html__( 'Answer Styles', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 327 add_settings_field( 'answer_font_size', esc_html__( 'Font Size (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_a', [ 'label_for' => 'answer_font_size' ] ); 328 add_settings_field( 'answer_color', esc_html__( 'Text Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_a', [ 'label_for' => 'answer_color' ] ); 329 add_settings_field( 'answer_background_color', esc_html__( 'Background Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_a', [ 'label_for' => 'answer_background_color' ] ); 330 add_settings_field( 'answer_text_align', esc_html__( 'Text Alignment', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_select_align' ], 'karms-settings-style', 'karms_style_a', [ 'label_for' => 'answer_text_align' ] ); 331 332 add_settings_section( 'karms_style_border', esc_html__( 'Border & Radius', 'kabook-auto-rank-math-snippet' ), null, 'karms-settings-style' ); 333 add_settings_field( 'border_width', esc_html__( 'Border Width (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_width' ] ); 334 add_settings_field( 'border_radius', esc_html__( 'Corner Radius (px)', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_number' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_radius' ] ); 335 add_settings_field( 'border_color', esc_html__( 'Border Color', 'kabook-auto-rank-math-snippet' ), [ __CLASS__, 'field_color' ], 'karms-settings-style', 'karms_style_border', [ 'label_for' => 'border_color' ] ); 336 } 337 338 public static function render_settings_page() { 339 if ( ! current_user_can( 'manage_options' ) ) { return; } 340 341 $raw_tab = filter_input( INPUT_GET, 'tab' ); 342 $active_tab = $raw_tab ? sanitize_key( $raw_tab ) : 'general'; 343 344 $base_url = admin_url( 'options-general.php?page=karms-settings' ); 345 $logo_url = KARMS_URL . 'assets/images/icon-kabook.png'; 346 ?> 347 <div class="karms-admin-wrapper"> 348 <header class="karms-header"> 349 <h1><?php esc_html_e( 'Kabook Auto Schema Settings', 'kabook-auto-rank-math-snippet' ); ?></h1> 350 <div class="karms-logo"><img src="<?php echo esc_url( $logo_url ); ?>" alt="Kabook"></div> 351 </header> 352 <div class="karms-inner-content"> 353 <nav class="karms-nav-tab-wrapper"> 354 <a href="<?php echo esc_url( $base_url . '&tab=general' ); ?>" class="karms-nav-tab <?php echo $active_tab == 'general' ? 'karms-nav-tab-active' : ''; ?>"><?php esc_html_e( 'General System', 'kabook-auto-rank-math-snippet' ); ?></a> 355 <a href="<?php echo esc_url( $base_url . '&tab=style' ); ?>" class="karms-nav-tab <?php echo $active_tab == 'style' ? 'karms-nav-tab-active' : ''; ?>"><?php esc_html_e( 'Accordion Styles', 'kabook-auto-rank-math-snippet' ); ?></a> 356 </nav> 357 <form action="options.php" method="post"> 358 <?php 359 settings_fields( 'karms_options_group' ); 360 echo '<input type="hidden" name="karms_current_tab_context" value="' . esc_attr( $active_tab ) . '">'; 361 362 echo '<div class="karms-settings-section-wrap">'; 363 if ( $active_tab == 'general' ) { self::render_custom_section( 'karms-settings-general' ); } 364 else { self::render_custom_section( 'karms-settings-style' ); } 365 echo '</div>'; 366 ?> 367 <div class="karms-submit-area"> 368 <?php submit_button( __( 'Save Changes', 'kabook-auto-rank-math-snippet' ), 'primary karms-save-btn' ); ?> 369 <button type="button" id="karms_reset_btn" class="button"><?php esc_html_e( 'Reset Defaults', 'kabook-auto-rank-math-snippet' ); ?></button> 370 </div> 371 </form> 372 </div> 373 </div> 374 <?php 375 } 376 377 private static function render_custom_section( $page_slug ) { 378 global $wp_settings_sections, $wp_settings_fields; 379 if ( ! isset( $wp_settings_sections[ $page_slug ] ) ) { return; } 380 381 foreach ( (array) $wp_settings_sections[ $page_slug ] as $section ) { 382 if ( $section['title'] ) { echo "<h2>" . esc_html( $section['title'] ) . "</h2>"; } 383 if ( ! isset( $wp_settings_fields[ $page_slug ][ $section['id'] ] ) ) { continue; } 384 foreach ( (array) $wp_settings_fields[ $page_slug ][ $section['id'] ] as $field ) { 385 echo '<div class="karms-field-row">'; 386 echo '<div class="karms-field-label"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['title'] ) . '</label></div>'; 387 echo '<div class="karms-field-input">'; 388 call_user_func( $field['callback'], $field['args'] ); 389 echo '</div></div>'; 390 } 391 } 392 } 393 394 public static function sanitize_options( $input ) { 395 // SECURITY CHECK: Verify nonce for options.php form submission 396 if ( isset( $_POST['_wpnonce'] ) ) { 397 if ( ! wp_verify_nonce( sanitize_key( $_POST['_wpnonce'] ), 'karms_options_group-options' ) ) { 398 add_settings_error( 'karms_options', 'invalid_nonce', esc_html__( 'Security check failed. Please try again.', 'kabook-auto-rank-math-snippet' ) ); 399 return get_option( 'karms_options', self::get_default_options() ); 400 } 401 } 402 403 $current_options = get_option( 'karms_options', self::get_default_options() ); 404 $defaults = self::get_default_options(); 405 $new_input = is_array( $current_options ) ? $current_options : $defaults; 406 407 $context = filter_input( INPUT_POST, 'karms_current_tab_context' ); 408 if ( $context ) { 409 $context = sanitize_key( $context ); 410 } 411 412 foreach ( $defaults as $key => $default ) { 413 if ( isset( $input[$key] ) ) { 414 if ( strpos( $key, 'color' ) !== false ) { 415 $new_input[$key] = sanitize_hex_color( $input[$key] ); 416 } 417 elseif ( is_numeric( $default ) ) { 418 $new_input[$key] = absint( $input[$key] ); 419 } 420 else { 421 $new_input[$key] = sanitize_text_field( $input[$key] ); 422 } 423 } else { 424 $tab_checkboxes = ($context === 'general') ? ['auto_insert', 'show_meta_box', 'accordion_enabled', 'counter_enabled', 'initial_expand_first'] : []; 425 if ( in_array($key, $tab_checkboxes) ) { 426 $new_input[$key] = 0; 427 } 428 } 429 } 430 return $new_input; 431 } 432 433 public static function field_checkbox( $args ) { 434 $options = get_option( 'karms_options', self::get_default_options() ); 435 $key = $args['label_for']; 436 $checked = isset( $options[ $key ] ) ? $options[ $key ] : 0; 437 echo '<input type="checkbox" name="karms_options[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '" value="1" ' . checked( 1, $checked, false ) . ' /> '; 438 if ( ! empty( $args['desc'] ) ) { echo '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>'; } 439 } 440 441 public static function field_select_align( $args ) { 442 $options = get_option( 'karms_options', self::get_default_options() ); 443 $key = $args['label_for']; 444 $val = isset( $options[$key] ) ? $options[$key] : 'left'; 445 446 $alignments = [ 447 'left' => esc_html__( 'Left', 'kabook-auto-rank-math-snippet' ), 448 'center' => esc_html__( 'Center', 'kabook-auto-rank-math-snippet' ), 449 'right' => esc_html__( 'Right', 'kabook-auto-rank-math-snippet' ), 450 ]; 451 452 echo '<select name="karms_options[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '">'; 453 foreach ( $alignments as $value => $label ) { 454 echo '<option value="' . esc_attr( $value ) . '" ' . selected( $value, $val, false ) . '>' . esc_html( $label ) . '</option>'; 455 } 456 echo '</select>'; 457 } 458 459 public static function field_select_animation( $args ) { 460 $options = get_option( 'karms_options', self::get_default_options() ); 461 $key = $args['label_for']; 462 $val = isset( $options[$key] ) ? $options[$key] : 'slide'; 463 echo '<select name="karms_options[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '">'; 464 echo '<option value="slide" ' . selected( 'slide', $val, false ) . '>' . esc_html__( 'Slide Down', 'kabook-auto-rank-math-snippet' ) . '</option>'; 465 echo '<option value="fade" ' . selected( 'fade', $val, false ) . '>' . esc_html__( 'Fade In', 'kabook-auto-rank-math-snippet' ) . '</option>'; 466 echo '<option value="zoom" ' . selected( 'zoom', $val, false ) . '>' . esc_html__( 'Zoom In', 'kabook-auto-rank-math-snippet' ) . '</option>'; 467 echo '</select>'; 468 } 469 470 public static function field_number( $args ) { 471 $options = get_option( 'karms_options', self::get_default_options() ); 472 $key = $args['label_for']; 473 $val = isset( $options[ $key ] ) ? $options[ $key ] : ''; 474 echo '<input type="number" name="karms_options[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" />'; 475 if ( ! empty( $args['desc'] ) ) { echo '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>'; } 476 } 477 478 public static function field_color( $args ) { 479 $options = get_option( 'karms_options', self::get_default_options() ); 480 $key = $args['label_for']; 481 $val = isset( $options[ $key ] ) ? $options[ $key ] : ''; 482 echo '<input type="text" name="karms_options[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" class="karms-color-picker" />'; 483 } 484 485 public static function ajax_reset_settings() { 486 check_ajax_referer( 'karms_reset_nonce_action', 'security' ); 487 if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error(); } 488 update_option( 'karms_options', self::get_default_options() ); 489 wp_send_json_success(); 490 } 491 } 492 493 // ----------------------------------------------------------------------------- 494 // 7. INITIALIZATION 516 495 // ----------------------------------------------------------------------------- 517 496 KARMS_Loader::init(); -
kabook-auto-rank-math-snippet/trunk/languages/kabook-auto-rank-math-snippet-fa_IR.po
r3414326 r3431166 1 1 msgid "" 2 2 msgstr "" 3 "Project-Id-Version: Kabook Auto Schema & Accordion for Rank Math 1.1.0\n" 4 "Report-Msgid-Bugs-To: https://kabook.ir/contact/\n" 5 "POT-Creation-Date: 2025-12-08 15:27+0330\n" 6 "PO-Revision-Date: 2025-12-08 15:30+0330\n" 7 "Last-Translator: Saeid Afshari <info@kabook.ir>\n" 8 "Language-Team: Kabook Dev Team <admin@kabook.ir>\n" 3 "Project-Id-Version: Kabook Auto Schema & Accordion for Rank Math\n" 4 "POT-Creation-Date: 2026-01-02 19:51+0330\n" 5 "PO-Revision-Date: 2026-01-02 19:52+0330\n" 6 "Last-Translator: Saeid Afshari <admin@kabook.ir>\n" 7 "Language-Team: Kabook Team <https://www.kabook.ir>\n" 9 8 "Language: fa_IR\n" 10 9 "MIME-Version: 1.0\n" 11 10 "Content-Type: text/plain; charset=UTF-8\n" 12 11 "Content-Transfer-Encoding: 8bit\n" 13 "X-Generator: Poedit 3.5\n" 14 "X-Domain: kabook-auto-rank-math-snippet\n" 15 #. translators: %s: Plugin Name 16 #: kabook-auto-rank-math-snippet.php:73 12 "Plural-Forms: nplurals=2; plural=(n==0 || n==1);\n" 13 "X-Generator: Poedit 3.7\n" 14 "X-Poedit-Basepath: ..\n" 15 "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 "X-Poedit-WPHeader: kabook-auto-rank-math-snippet.php\n" 17 "X-Poedit-SourceCharset: UTF-8\n" 18 "X-Poedit-KeywordsList: " 19 "__;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 20 "X-Poedit-SearchPath-0: .\n" 21 "X-Poedit-SearchPathExcluded-0: *.js\n" 22 23 #. translators: 1: Plugin Name, 2: Dependency Name 24 #: kabook-auto-rank-math-snippet.php:49 17 25 #, php-format 18 msgid "%s requires Rank Math SEO PRO to be installed and active." 19 msgstr "افزونه %s نیاز دارد که Rank Math SEO PRO نصب و فعال باشد." 20 21 #: kabook-auto-rank-math-snippet.php:91 26 msgid "%1$s requires %2$s to be installed and active." 27 msgstr "افزونه %1$s نیاز دارد که %2$s نصب و فعال باشد." 28 29 #: kabook-auto-rank-math-snippet.php:50 30 msgid "Kabook Auto Schema & Accordion" 31 msgstr "اسکیما و آکاردئون خودکار کابوک" 32 33 #: kabook-auto-rank-math-snippet.php:51 34 msgid "Rank Math SEO PRO" 35 msgstr "Rank Math SEO PRO" 36 37 #: kabook-auto-rank-math-snippet.php:68 22 38 msgid "Settings" 23 39 msgstr "تنظیمات" 24 40 25 #: kabook-auto-rank-math-snippet.php:2 4341 #: kabook-auto-rank-math-snippet.php:205 26 42 msgid "Schema Injection Settings" 27 msgstr "تنظیمات درجاسکیما"28 29 #: kabook-auto-rank-math-snippet.php:2 6143 msgstr "تنظیمات افزودن اسکیما" 44 45 #: kabook-auto-rank-math-snippet.php:221 30 46 msgid "Auto Inject Schema for this post:" 31 msgstr " درجخودکار اسکیما برای این نوشته:"32 33 #: kabook-auto-rank-math-snippet.php:2 6547 msgstr "افزودن خودکار اسکیما برای این نوشته:" 48 49 #: kabook-auto-rank-math-snippet.php:225 34 50 msgid "Default (Global Settings)" 35 51 msgstr "پیشفرض (تنظیمات سراسری)" 36 52 37 #: kabook-auto-rank-math-snippet.php:2 6653 #: kabook-auto-rank-math-snippet.php:226 38 54 msgid "Enable / Force Inject" 39 msgstr "فعالسازی / درج اجباری"40 41 #: kabook-auto-rank-math-snippet.php:2 6755 msgstr "فعالسازی / اجبار به افزودن" 56 57 #: kabook-auto-rank-math-snippet.php:227 42 58 msgid "Disable" 43 59 msgstr "غیرفعالسازی" 44 60 45 #: kabook-auto-rank-math-snippet.php:2 7161 #: kabook-auto-rank-math-snippet.php:231 46 62 msgid "Override the global auto-injection setting for this specific post." 47 msgstr "بازنویسی تنظیمات سراسری درجخودکار برای این نوشته خاص."48 49 #: kabook-auto-rank-math-snippet.php: 31950 msgid " Settings for Rank Math Snippet"51 msgstr "تنظیمات اس نیپت رنکمث"52 53 #: kabook-auto-rank-math-snippet.php: 32063 msgstr "بازنویسی تنظیمات سراسری افزودن خودکار برای این نوشته خاص." 64 65 #: kabook-auto-rank-math-snippet.php:281 kabook-auto-rank-math-snippet.php:349 66 msgid "Kabook Auto Schema Settings" 67 msgstr "تنظیمات اسکیما خودکار کابوک" 68 69 #: kabook-auto-rank-math-snippet.php:282 54 70 msgid "Kabook RM Snippet" 55 71 msgstr "اسنیپت Kabook RM" 56 72 57 #: kabook-auto-rank-math-snippet.php: 33673 #: kabook-auto-rank-math-snippet.php:298 58 74 msgid "Are you sure you want to reset all settings to default?" 59 75 msgstr "آیا مطمئن هستید که میخواهید تمام تنظیمات را به حالت پیشفرض بازگردانید؟" 60 76 61 #: kabook-auto-rank-math-snippet.php:343 77 #: kabook-auto-rank-math-snippet.php:299 78 msgid "Settings reset successfully. Reloading..." 79 msgstr "تنظیمات با موفقیت بازنشانی شدند. در حال بارگیری مجدد..." 80 81 #: kabook-auto-rank-math-snippet.php:300 82 msgid "Error resetting settings. Please try again." 83 msgstr "خطا در بازنشانی تنظیمات. لطفا دوباره امتحان کنید." 84 85 #: kabook-auto-rank-math-snippet.php:308 62 86 msgid "General Settings" 63 87 msgstr "تنظیمات عمومی" 64 88 65 #: kabook-auto-rank-math-snippet.php:3 4689 #: kabook-auto-rank-math-snippet.php:309 66 90 msgid "Auto Inject Schema" 67 msgstr " درجخودکار اسکیما"68 69 #: kabook-auto-rank-math-snippet.php:3 4891 msgstr "افزودن خودکار اسکیما" 92 93 #: kabook-auto-rank-math-snippet.php:309 70 94 msgid "Automatically add [rank_math_rich_snippet] to posts if missing." 71 msgstr "افزودن خودکار شورتکد [rank_math_rich_snippet] به نوشتهها در صورت موجود نبودن."72 73 #: kabook-auto-rank-math-snippet.php:34974 msgid "Important:"75 msgstr "مهم:"76 77 #: kabook-auto-rank-math-snippet.php:35078 msgid ""79 "If you use other schemas like \"HowTo\" in a specific post, please DISABLE "80 "auto-injection for that post using the \"Injection Control Meta Box\" (in "81 "the post editor) and insert shortcodes manually to avoid conflicts."82 95 msgstr "" 83 "اگر از اسکیماهای دیگر مانند \"HowTo\" در یک نوشته خاص استفاده میکنید، لطفاً " 84 "درج خودکار را برای آن نوشته از طریق «متاباکس کنترل درج» (در ویرایشگر نوشته) " 85 "غیرفعال کرده و شورتکدها را دستی وارد کنید تا از تداخل جلوگیری شود." 86 87 #: kabook-auto-rank-math-snippet.php:353 88 msgid "Show Injection Control Meta Box" 89 msgstr "نمایش متاباکس کنترل درج" 90 91 #: kabook-auto-rank-math-snippet.php:355 92 msgid "" 93 "Display a meta box in the post editor to manually Enable/Disable injection " 94 "per post." 95 msgstr "" 96 "نمایش یک متاباکس در ویرایشگر نوشته برای فعال یا غیرفعال کردن دستی عملیات درج " 97 "برای هر نوشته." 98 99 #: kabook-auto-rank-math-snippet.php:358 100 msgid "Enable Accordion Style" 101 msgstr "فعالسازی استایل آکاردئونی" 102 103 #: kabook-auto-rank-math-snippet.php:360 104 msgid "Convert the FAQ schema into an accordion style." 105 msgstr "تبدیل اسکیمای سوالات متداول (FAQ) به استایل آکاردئونی." 106 107 #: kabook-auto-rank-math-snippet.php:362 96 "افزودن خودکار شورتکد [rank_math_rich_snippet] به نوشتهها در صورت عدم وجود." 97 98 #: kabook-auto-rank-math-snippet.php:310 99 msgid "Show Meta Box" 100 msgstr "نمایش متاباکس" 101 102 #: kabook-auto-rank-math-snippet.php:310 103 msgid "Show per-post injection control." 104 msgstr "نمایش کنترل افزودن اسکیما در هر نوشته." 105 106 #: kabook-auto-rank-math-snippet.php:311 107 msgid "Enable Accordion" 108 msgstr "فعالسازی آکاردئون" 109 110 #: kabook-auto-rank-math-snippet.php:312 108 111 msgid "Enable Numbering" 109 112 msgstr "فعالسازی شمارهگذاری" 110 113 111 #: kabook-auto-rank-math-snippet.php:3 63114 #: kabook-auto-rank-math-snippet.php:313 112 115 msgid "Expand First Item" 113 116 msgstr "باز بودن اولین آیتم" 114 117 115 #: kabook-auto-rank-math-snippet.php:365 116 msgid "Question Styling" 117 msgstr "استایلدهی سوال" 118 119 #: kabook-auto-rank-math-snippet.php:366 kabook-auto-rank-math-snippet.php:372 118 #: kabook-auto-rank-math-snippet.php:316 119 msgid "Animation Settings" 120 msgstr "تنظیمات انیمیشن" 121 122 #: kabook-auto-rank-math-snippet.php:317 123 msgid "Opening Animation" 124 msgstr "انیمیشن باز شدن" 125 126 #: kabook-auto-rank-math-snippet.php:318 127 msgid "Animation Speed (ms)" 128 msgstr "سرعت انیمیشن (میلیثانیه)" 129 130 #: kabook-auto-rank-math-snippet.php:318 131 msgid "e.g. 300 for fast, 1200 for slow." 132 msgstr "مثلاً ۳۰۰ برای سریع، ۱۲۰۰ برای کند." 133 134 #: kabook-auto-rank-math-snippet.php:320 135 msgid "Question Styles" 136 msgstr "استایلهای سوال" 137 138 #: kabook-auto-rank-math-snippet.php:321 kabook-auto-rank-math-snippet.php:327 120 139 msgid "Font Size (px)" 121 140 msgstr "اندازه فونت (پیکسل)" 122 141 123 #: kabook-auto-rank-math-snippet.php:3 67 kabook-auto-rank-math-snippet.php:373142 #: kabook-auto-rank-math-snippet.php:322 kabook-auto-rank-math-snippet.php:328 124 143 msgid "Text Color" 125 144 msgstr "رنگ متن" 126 145 127 #: kabook-auto-rank-math-snippet.php:3 68 kabook-auto-rank-math-snippet.php:374146 #: kabook-auto-rank-math-snippet.php:323 kabook-auto-rank-math-snippet.php:329 128 147 msgid "Background Color" 129 148 msgstr "رنگ پسزمینه" 130 149 131 #: kabook-auto-rank-math-snippet.php:3 69 kabook-auto-rank-math-snippet.php:375132 msgid "Text Align "150 #: kabook-auto-rank-math-snippet.php:324 kabook-auto-rank-math-snippet.php:330 151 msgid "Text Alignment" 133 152 msgstr "تراز متن" 134 153 135 #: kabook-auto-rank-math-snippet.php:371 136 msgid "Answer Styling" 137 msgstr "استایلدهی پاسخ" 138 139 #: kabook-auto-rank-math-snippet.php:377 140 msgid "Border Styling" 141 msgstr "استایلدهی حاشیه (Border)" 142 143 #: kabook-auto-rank-math-snippet.php:378 144 msgid "Width (px)" 145 msgstr "عرض (پیکسل)" 146 147 #: kabook-auto-rank-math-snippet.php:379 148 msgid "Style" 149 msgstr "نوع استایل" 150 151 #: kabook-auto-rank-math-snippet.php:380 152 msgid "Color" 153 msgstr "رنگ" 154 155 #: kabook-auto-rank-math-snippet.php:381 156 msgid "Radius (px)" 157 msgstr "شعاع گردی (پیکسل)" 154 #: kabook-auto-rank-math-snippet.php:326 155 msgid "Answer Styles" 156 msgstr "استایلهای پاسخ" 157 158 #: kabook-auto-rank-math-snippet.php:332 159 msgid "Border & Radius" 160 msgstr "حاشیه و شعاع گردی" 161 162 #: kabook-auto-rank-math-snippet.php:333 163 msgid "Border Width (px)" 164 msgstr "عرض حاشیه (پیکسل)" 165 166 #: kabook-auto-rank-math-snippet.php:334 167 msgid "Corner Radius (px)" 168 msgstr "شعاع گوشهها (پیکسل)" 169 170 #: kabook-auto-rank-math-snippet.php:335 171 msgid "Border Color" 172 msgstr "رنگ حاشیه" 173 174 #: kabook-auto-rank-math-snippet.php:354 175 msgid "General System" 176 msgstr "سیستم عمومی" 177 178 #: kabook-auto-rank-math-snippet.php:355 179 msgid "Accordion Styles" 180 msgstr "استایلهای آکاردئون" 181 182 #: kabook-auto-rank-math-snippet.php:368 183 msgid "Save Changes" 184 msgstr "ذخیره تغییرات" 185 186 #: kabook-auto-rank-math-snippet.php:369 187 msgid "Reset Defaults" 188 msgstr "بازنشانی به پیشفرضها" 189 190 #: kabook-auto-rank-math-snippet.php:398 191 msgid "Security check failed. Please try again." 192 msgstr "بررسی امنیتی با شکست مواجه شد. لطفاً دوباره تلاش کنید." 193 194 #: kabook-auto-rank-math-snippet.php:447 195 msgid "Left" 196 msgstr "چپ" 197 198 #: kabook-auto-rank-math-snippet.php:448 199 msgid "Center" 200 msgstr "وسط" 201 202 #: kabook-auto-rank-math-snippet.php:449 203 msgid "Right" 204 msgstr "راست" 205 206 #: kabook-auto-rank-math-snippet.php:464 207 msgid "Slide Down" 208 msgstr "کشویی به پایین" 209 210 #: kabook-auto-rank-math-snippet.php:465 211 msgid "Fade In" 212 msgstr "محو شدن (Fade)" 213 214 #: kabook-auto-rank-math-snippet.php:466 215 msgid "Zoom In" 216 msgstr "بزرگنمایی (Zoom)" 158 217 159 218 #. Plugin Name of the plugin/theme 160 #: kabook-auto-rank-math-snippet.php:393161 219 msgid "Kabook Auto Schema & Accordion for Rank Math" 162 220 msgstr "اسکیما و آکاردئون خودکار کابوک برای رنکمث" 163 221 164 #: kabook-auto-rank-math-snippet.php:401165 msgid "General"166 msgstr "عمومی"167 168 #: kabook-auto-rank-math-snippet.php:404169 msgid "Accordion Styles"170 msgstr "استایلهای آکاردئون"171 172 #: kabook-auto-rank-math-snippet.php:422173 msgid "Reset to Defaults"174 msgstr "بازنشانی به پیشفرضها"175 176 222 #. Description of the plugin/theme 177 223 msgid "" 178 "Automatically injects Rank Math FAQ schema and converts it to a stylish "179 " accordion."224 "Automatically injects Rank Math FAQ schema and converts it to a stylish, " 225 "customizable accordion." 180 226 msgstr "" 181 "درج خودکار اسکیمای سوالات متداول (FAQ) رنکمث و تبدیل آن به یک آکاردئون شیک." 227 "افزودن خودکار اسکیمای سوالات متداول (FAQ) رنکمث و تبدیل آن به یک آکاردئون شیک " 228 "و قابل شخصیسازی." 182 229 183 230 #. Author of the plugin/theme … … 186 233 187 234 #. Author URI of the plugin/theme 188 msgid "https:// kabook.ir/"189 msgstr "https:// kabook.ir/"235 msgid "https://www.kabook.ir/" 236 msgstr "https://www.kabook.ir/" -
kabook-auto-rank-math-snippet/trunk/languages/kabook-auto-rank-math-snippet.pot
r3414326 r3431166 1 #, fuzzy 1 2 msgid "" 2 3 msgstr "" 3 "Project-Id-Version: Kabook Auto Schema & Accordion for Rank Math 1.1.0\n" 4 "Report-Msgid-Bugs-To: https://kabook.ir/contact/\n" 5 "POT-Creation-Date: 2025-12-08 15:27+0330\n" 6 "PO-Revision-Date: 2025-12-08 15:30+0330\n" 7 "Last-Translator: Saeid Afshari <info@kabook.ir>\n" 8 "Language-Team: Kabook Dev Team <admin@kabook.ir>\n" 9 "Language: fa_IR\n" 4 "Project-Id-Version: Kabook Auto Schema & Accordion for Rank Math\n" 5 "POT-Creation-Date: 2026-01-02 19:51+0330\n" 6 "PO-Revision-Date: 2026-01-02 19:20+0330\n" 7 "Last-Translator: \n" 8 "Language-Team: \n" 10 9 "MIME-Version: 1.0\n" 11 10 "Content-Type: text/plain; charset=UTF-8\n" 12 11 "Content-Transfer-Encoding: 8bit\n" 13 "X-Generator: Poedit 3.5\n" 14 "X-Domain: kabook-auto-rank-math-snippet\n" 15 16 #. translators: %s: Plugin Name 17 #: kabook-auto-rank-math-snippet.php:73 12 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 13 "X-Generator: Poedit 3.7\n" 14 "X-Poedit-Basepath: ..\n" 15 "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 "X-Poedit-WPHeader: kabook-auto-rank-math-snippet.php\n" 17 "X-Poedit-SourceCharset: UTF-8\n" 18 "X-Poedit-KeywordsList: " 19 "__;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 20 "X-Poedit-SearchPath-0: .\n" 21 "X-Poedit-SearchPathExcluded-0: *.js\n" 22 23 #. translators: 1: Plugin Name, 2: Dependency Name 24 #: kabook-auto-rank-math-snippet.php:49 18 25 #, php-format 19 msgid "%s requires Rank Math SEO PRO to be installed and active." 20 msgstr "" 21 22 #: kabook-auto-rank-math-snippet.php:91 26 msgid "%1$s requires %2$s to be installed and active." 27 msgstr "" 28 29 #: kabook-auto-rank-math-snippet.php:50 30 msgid "Kabook Auto Schema & Accordion" 31 msgstr "" 32 33 #: kabook-auto-rank-math-snippet.php:51 34 msgid "Rank Math SEO PRO" 35 msgstr "" 36 37 #: kabook-auto-rank-math-snippet.php:68 23 38 msgid "Settings" 24 39 msgstr "" 25 40 26 #: kabook-auto-rank-math-snippet.php:2 4341 #: kabook-auto-rank-math-snippet.php:205 27 42 msgid "Schema Injection Settings" 28 43 msgstr "" 29 44 30 #: kabook-auto-rank-math-snippet.php:2 6145 #: kabook-auto-rank-math-snippet.php:221 31 46 msgid "Auto Inject Schema for this post:" 32 47 msgstr "" 33 48 34 #: kabook-auto-rank-math-snippet.php:2 6549 #: kabook-auto-rank-math-snippet.php:225 35 50 msgid "Default (Global Settings)" 36 51 msgstr "" 37 52 38 #: kabook-auto-rank-math-snippet.php:2 6653 #: kabook-auto-rank-math-snippet.php:226 39 54 msgid "Enable / Force Inject" 40 55 msgstr "" 41 56 42 #: kabook-auto-rank-math-snippet.php:2 6757 #: kabook-auto-rank-math-snippet.php:227 43 58 msgid "Disable" 44 59 msgstr "" 45 60 46 #: kabook-auto-rank-math-snippet.php:2 7161 #: kabook-auto-rank-math-snippet.php:231 47 62 msgid "Override the global auto-injection setting for this specific post." 48 63 msgstr "" 49 64 50 #: kabook-auto-rank-math-snippet.php:319 51 msgid "Settings for Rank Math Snippet" 65 #: kabook-auto-rank-math-snippet.php:281 kabook-auto-rank-math-snippet.php:349 66 msgid "Kabook Auto Schema Settings" 67 msgstr "" 68 69 #: kabook-auto-rank-math-snippet.php:282 70 msgid "Kabook RM Snippet" 71 msgstr "" 72 73 #: kabook-auto-rank-math-snippet.php:298 74 msgid "Are you sure you want to reset all settings to default?" 75 msgstr "" 76 77 #: kabook-auto-rank-math-snippet.php:299 78 msgid "Settings reset successfully. Reloading..." 79 msgstr "" 80 81 #: kabook-auto-rank-math-snippet.php:300 82 msgid "Error resetting settings. Please try again." 83 msgstr "" 84 85 #: kabook-auto-rank-math-snippet.php:308 86 msgid "General Settings" 87 msgstr "" 88 89 #: kabook-auto-rank-math-snippet.php:309 90 msgid "Auto Inject Schema" 91 msgstr "" 92 93 #: kabook-auto-rank-math-snippet.php:309 94 msgid "Automatically add [rank_math_rich_snippet] to posts if missing." 95 msgstr "" 96 97 #: kabook-auto-rank-math-snippet.php:310 98 msgid "Show Meta Box" 99 msgstr "" 100 101 #: kabook-auto-rank-math-snippet.php:310 102 msgid "Show per-post injection control." 103 msgstr "" 104 105 #: kabook-auto-rank-math-snippet.php:311 106 msgid "Enable Accordion" 107 msgstr "" 108 109 #: kabook-auto-rank-math-snippet.php:312 110 msgid "Enable Numbering" 111 msgstr "" 112 113 #: kabook-auto-rank-math-snippet.php:313 114 msgid "Expand First Item" 115 msgstr "" 116 117 #: kabook-auto-rank-math-snippet.php:316 118 msgid "Animation Settings" 119 msgstr "" 120 121 #: kabook-auto-rank-math-snippet.php:317 122 msgid "Opening Animation" 123 msgstr "" 124 125 #: kabook-auto-rank-math-snippet.php:318 126 msgid "Animation Speed (ms)" 127 msgstr "" 128 129 #: kabook-auto-rank-math-snippet.php:318 130 msgid "e.g. 300 for fast, 1200 for slow." 52 131 msgstr "" 53 132 54 133 #: kabook-auto-rank-math-snippet.php:320 55 msgid "Kabook RM Snippet" 56 msgstr "" 57 58 #: kabook-auto-rank-math-snippet.php:336 59 msgid "Are you sure you want to reset all settings to default?" 60 msgstr "" 61 62 #: kabook-auto-rank-math-snippet.php:343 63 msgid "General Settings" 64 msgstr "" 65 66 #: kabook-auto-rank-math-snippet.php:346 67 msgid "Auto Inject Schema" 68 msgstr "" 69 70 #: kabook-auto-rank-math-snippet.php:348 71 msgid "Automatically add [rank_math_rich_snippet] to posts if missing." 72 msgstr "" 73 74 #: kabook-auto-rank-math-snippet.php:349 75 msgid "Important:" 76 msgstr "" 77 78 #: kabook-auto-rank-math-snippet.php:350 79 msgid "" 80 "If you use other schemas like \"HowTo\" in a specific post, please DISABLE " 81 "auto-injection for that post using the \"Injection Control Meta Box\" (in " 82 "the post editor) and insert shortcodes manually to avoid conflicts." 83 msgstr "" 84 85 #: kabook-auto-rank-math-snippet.php:353 86 msgid "Show Injection Control Meta Box" 134 msgid "Question Styles" 135 msgstr "" 136 137 #: kabook-auto-rank-math-snippet.php:321 kabook-auto-rank-math-snippet.php:327 138 msgid "Font Size (px)" 139 msgstr "" 140 141 #: kabook-auto-rank-math-snippet.php:322 kabook-auto-rank-math-snippet.php:328 142 msgid "Text Color" 143 msgstr "" 144 145 #: kabook-auto-rank-math-snippet.php:323 kabook-auto-rank-math-snippet.php:329 146 msgid "Background Color" 147 msgstr "" 148 149 #: kabook-auto-rank-math-snippet.php:324 kabook-auto-rank-math-snippet.php:330 150 msgid "Text Alignment" 151 msgstr "" 152 153 #: kabook-auto-rank-math-snippet.php:326 154 msgid "Answer Styles" 155 msgstr "" 156 157 #: kabook-auto-rank-math-snippet.php:332 158 msgid "Border & Radius" 159 msgstr "" 160 161 #: kabook-auto-rank-math-snippet.php:333 162 msgid "Border Width (px)" 163 msgstr "" 164 165 #: kabook-auto-rank-math-snippet.php:334 166 msgid "Corner Radius (px)" 167 msgstr "" 168 169 #: kabook-auto-rank-math-snippet.php:335 170 msgid "Border Color" 171 msgstr "" 172 173 #: kabook-auto-rank-math-snippet.php:354 174 msgid "General System" 87 175 msgstr "" 88 176 89 177 #: kabook-auto-rank-math-snippet.php:355 90 msgid "" 91 "Display a meta box in the post editor to manually Enable/Disable injection " 92 "per post." 93 msgstr "" 94 95 #: kabook-auto-rank-math-snippet.php:358 96 msgid "Enable Accordion Style" 97 msgstr "" 98 99 #: kabook-auto-rank-math-snippet.php:360 100 msgid "Convert the FAQ schema into an accordion style." 101 msgstr "" 102 103 #: kabook-auto-rank-math-snippet.php:362 104 msgid "Enable Numbering" 105 msgstr "" 106 107 #: kabook-auto-rank-math-snippet.php:363 108 msgid "Expand First Item" 109 msgstr "" 110 111 #: kabook-auto-rank-math-snippet.php:365 112 msgid "Question Styling" 113 msgstr "" 114 115 #: kabook-auto-rank-math-snippet.php:366 kabook-auto-rank-math-snippet.php:372 116 msgid "Font Size (px)" 117 msgstr "" 118 119 #: kabook-auto-rank-math-snippet.php:367 kabook-auto-rank-math-snippet.php:373 120 msgid "Text Color" 121 msgstr "" 122 123 #: kabook-auto-rank-math-snippet.php:368 kabook-auto-rank-math-snippet.php:374 124 msgid "Background Color" 125 msgstr "" 126 127 #: kabook-auto-rank-math-snippet.php:369 kabook-auto-rank-math-snippet.php:375 128 msgid "Text Align" 129 msgstr "" 130 131 #: kabook-auto-rank-math-snippet.php:371 132 msgid "Answer Styling" 133 msgstr "" 134 135 #: kabook-auto-rank-math-snippet.php:377 136 msgid "Border Styling" 137 msgstr "" 138 139 #: kabook-auto-rank-math-snippet.php:378 140 msgid "Width (px)" 141 msgstr "" 142 143 #: kabook-auto-rank-math-snippet.php:379 144 msgid "Style" 145 msgstr "" 146 147 #: kabook-auto-rank-math-snippet.php:380 148 msgid "Color" 149 msgstr "" 150 151 #: kabook-auto-rank-math-snippet.php:381 152 msgid "Radius (px)" 178 msgid "Accordion Styles" 179 msgstr "" 180 181 #: kabook-auto-rank-math-snippet.php:368 182 msgid "Save Changes" 183 msgstr "" 184 185 #: kabook-auto-rank-math-snippet.php:369 186 msgid "Reset Defaults" 187 msgstr "" 188 189 #: kabook-auto-rank-math-snippet.php:398 190 msgid "Security check failed. Please try again." 191 msgstr "" 192 193 #: kabook-auto-rank-math-snippet.php:447 194 msgid "Left" 195 msgstr "" 196 197 #: kabook-auto-rank-math-snippet.php:448 198 msgid "Center" 199 msgstr "" 200 201 #: kabook-auto-rank-math-snippet.php:449 202 msgid "Right" 203 msgstr "" 204 205 #: kabook-auto-rank-math-snippet.php:464 206 msgid "Slide Down" 207 msgstr "" 208 209 #: kabook-auto-rank-math-snippet.php:465 210 msgid "Fade In" 211 msgstr "" 212 213 #: kabook-auto-rank-math-snippet.php:466 214 msgid "Zoom In" 153 215 msgstr "" 154 216 155 217 #. Plugin Name of the plugin/theme 156 #: kabook-auto-rank-math-snippet.php:393157 218 msgid "Kabook Auto Schema & Accordion for Rank Math" 158 msgstr ""159 160 #: kabook-auto-rank-math-snippet.php:401161 msgid "General"162 msgstr ""163 164 #: kabook-auto-rank-math-snippet.php:404165 msgid "Accordion Styles"166 msgstr ""167 168 #: kabook-auto-rank-math-snippet.php:422169 msgid "Reset to Defaults"170 219 msgstr "" 171 220 172 221 #. Description of the plugin/theme 173 222 msgid "" 174 "Automatically injects Rank Math FAQ schema and converts it to a stylish "175 " accordion."223 "Automatically injects Rank Math FAQ schema and converts it to a stylish, " 224 "customizable accordion." 176 225 msgstr "" 177 226 … … 181 230 182 231 #. Author URI of the plugin/theme 183 msgid "https:// kabook.ir/"184 msgstr "" 232 msgid "https://www.kabook.ir/" 233 msgstr "" -
kabook-auto-rank-math-snippet/trunk/readme.txt
r3414326 r3431166 1 1 === Kabook Auto Schema & Accordion for Rank Math === 2 2 Contributors: saeidafshari 3 Tags: rank math, schema, faq, accordion, s eo3 Tags: rank math, schema, faq, accordion, schema-injection 4 4 Requires at least: 5.6 5 5 Tested up to: 6.9 6 Requires PHP: 8.07 Stable tag: 1. 1.06 Requires PHP: 7.4 7 Stable tag: 1.2.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Automatically injects Rank Math FAQ schema and converts it to a stylish, customizable accordion on the frontend.11 Automatically injects Rank Math FAQ schema and converts it to a stylish, customizable accordion with smooth animations. 12 12 13 13 == Description == 14 14 15 15 This plugin is a power-up for **Rank Math SEO PRO** users. 16 It solves two common problems: 17 1. Forgetting to insert the FAQ schema shortcode into posts. 18 2. The default, plain look of the FAQ schema output. 16 It solves common SEO and UX problems by ensuring your FAQ Schema is always present and looks professional. 19 17 20 18 **Key Features:** 21 19 22 20 * **Auto Injection:** Automatically adds the `[rank_math_rich_snippet]` shortcode to your single posts if you have defined an FAQ schema but forgot to insert the block. 23 * **Per-Post Control:** (New) Manually enable or disable schema injection for specific posts via a simple checkbox in the editor. 24 * **Smart Detection:** Checks the raw database content to ensure the shortcode is never duplicated if you manually added it. 21 * **New: Animation Effects:** Choose between Slide, Fade, or Zoom effects for your accordion opening. 22 * **New: Speed Control:** Fully customize the animation duration (ms) to match your site's feel. 23 * **Per-Post Control:** Manually enable or disable schema injection for specific posts via a simple checkbox in the editor. 24 * **Smart Detection:** Checks the raw database content to ensure the shortcode is never duplicated. 25 25 * **Stylish Accordion:** Converts the boring list format into a beautiful, interactive accordion. 26 * **Fully Customizable:** Change colors, fonts, borders, and alignment via a simplesettings panel.27 * ** Lightweight:** Rebuilt with Vanilla JS (No jQuery) for maximum performance.28 * ** RTL Support:** Fully supportsRight-to-Left languages like Persian and Arabic.26 * **Fully Customizable:** Change colors, fonts, borders, and alignment via a modern "Blue Harmony" settings panel. 27 * **Ultra Lightweight:** Rebuilt with Vanilla JS (No jQuery) for maximum performance. 28 * **Perfect RTL Support:** Deep integration for Right-to-Left languages like Persian and Arabic. 29 29 30 30 **Note:** This plugin relies on the schema data generated by the **Rank Math SEO PRO** plugin. … … 33 33 == Installation == 34 34 35 1. Upload the plugin files to the `/wp-content/plugins/kabook-auto-rank-math-snippet` directory, or install the plugin through the WordPress plugins screen directly. 36 2. Activate the plugin through the 'Plugins' screen in WordPress. 37 3. Go to **Settings > Kabook RM Snippet** to configure the styling options. 38 4. (Optional) Enable the "Injection Control Meta Box" in settings to control injection on a per-post basis. 35 1. Upload the plugin files to the `/wp-content/plugins/kabook-auto-rank-math-snippet` directory. 36 2. Activate the plugin through the 'Plugins' screen in WordPress. 37 3. Go to **Settings > Kabook RM Snippet** to configure the styling and animation options. 39 38 40 39 == Frequently Asked Questions == 41 40 42 41 = Does this plugin work without Rank Math PRO? = 43 No. This plugin acts as an add-on. 44 It depends on the schema data generated by the Rank Math SEO PRO plugin to function. 42 No. This plugin acts as an add-on and depends on the schema data generated by the Rank Math SEO PRO plugin. 43 44 = Can I change the opening speed of the accordion? = 45 Yes! In version 1.2.0, we added an "Animation Speed" setting where you can define the speed in milliseconds (e.g., 300ms for fast or 1200ms for slow). 46 47 = Does it load scripts on every page? = 48 No. To ensure maximum performance, the plugin only loads its CSS and JS files on pages where an FAQ schema or shortcode is actually detected. 45 49 46 50 = Will it slow down my site? = 47 No. The plugin is highly optimized (Vanilla JS) and only loads assets on pages where an FAQ schema is detected.51 Absolutely not. The plugin uses Vanilla JS instead of jQuery, making it extremely fast and lightweight. 48 52 49 53 == Screenshots == 50 54 51 1. **General Settings:** Enable or disable auto-injection and the new meta box feature. 52 2. **Style Customization:** Easily change colors and styles to match your theme. 53 3. **Frontend Example:** How the FAQ Accordion looks to your visitors. 54 4. **RTL Support:** Full support for Persian/Arabic layouts. 55 1. **General Settings:** The new "Blue Harmony" UI for managing global plugin options and auto-injection. 56 2. **Animation Controls:** Choose your desired opening effect (Slide, Fade, Zoom) and set the animation speed. 57 3. **Style Customization:** Full control over colors, typography, borders, and corner radius to match your theme. 58 4. **Frontend Example (LTR):** A beautiful, animated FAQ accordion as seen on an English site. 59 5. **RTL Support (Persian):** Perfect alignment and styling for Right-to-Left languages. 55 60 56 61 == Changelog == 57 62 63 = 1.2.0 = 64 * New: Added Opening Animations (Slide, Fade, Zoom). 65 * New: Added Animation Speed control setting. 66 * New: Brand new "Blue Harmony" Admin UI for better user experience. 67 * Improvement: Optimized Asset Loading (scripts only load when needed). 68 * Improvement: Enhanced RTL support for both Admin and Frontend. 69 * Security: Implemented Nonce verification and better output escaping for WP.org standards. 70 * Compatibility: PHP requirement lowered to 7.4 for better compatibility. 71 58 72 = 1.1.0 = 59 * New: Added "Injection Control Meta Box" to Enable/Disable auto-injection per post. 60 * New: Added option to show/hide the Meta Box in plugin settings. 61 * New: Added helpful notice in settings regarding schema conflicts. 62 * Improvement: Rewrote frontend logic in Vanilla JS (removed jQuery dependency) for better performance. 63 * Improvement: Added uninstall.php for proper data cleanup. 64 * Security: Fixed non-sanitized input variable warnings (Plugin Check standards). 65 * Compatibility: Tested up to WordPress 6.9. 73 * New: Added "Injection Control Meta Box" per post. 74 * Improvement: Rewrote frontend logic in Vanilla JS (removed jQuery). 75 * Security: Fixed non-sanitized input variable warnings. 66 76 67 77 = 1.0.0 = -
kabook-auto-rank-math-snippet/trunk/uninstall.php
r3414326 r3431166 3 3 * Fired when the plugin is uninstalled. 4 4 * 5 * @package Kabook_Auto_Rank_Math_Snippet 5 * Removes all settings and database entries created by the plugin 6 * to ensure a clean uninstallation process. 7 * 8 * @package Kabook Auto Rank Math Snippet 6 9 */ 7 10 8 11 if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { 9 exit;12 exit; 10 13 } 11 14 12 // 1. Delete Options15 // 1. Delete Plugin Options 13 16 delete_option( 'karms_options' ); 14 17 15 // 2. Clean up post meta (Uncommented for fullcleanup)18 // 2. Clean up Post Meta (Database cleanup) 16 19 global $wpdb; 20 17 21 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 18 22 $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_karms_auto_inject_override'" );
Note: See TracChangeset
for help on using the changeset viewer.