Changeset 3381077
- Timestamp:
- 10/20/2025 07:05:59 AM (5 months ago)
- Location:
- kombatoptimizer/trunk
- Files:
-
- 4 added
- 3 deleted
- 4 edited
-
assets/KombatOptim_Logo.png (deleted)
-
assets/KombatOptim_Logo_128-128.png (added)
-
assets/KombatOptim_Logo_256-256.png (added)
-
assets/KombatOptim_banner_1544-500.jpg (added)
-
assets/KombatOptim_banner_772-250.jpg (added)
-
assets/KombatOptimizer_Banner.png (deleted)
-
assets/admin.css (modified) (1 diff)
-
assets/admin.js (modified) (1 diff)
-
inc/generate-webp.php (modified) (9 diffs)
-
kombat-optimizer.php (modified) (5 diffs)
-
readme.txt (deleted)
Legend:
- Unmodified
- Added
- Removed
-
kombatoptimizer/trunk/assets/admin.css
r3379089 r3381077 115 115 100% { opacity: 0; display: none; } 116 116 } 117 118 119 /* 🔄 Loader vizual Kombat Optimizer */ 120 #kombat-loader { 121 display: none; 122 margin-top: 20px; 123 text-align: center; 124 } 125 126 #kombat-loader .spinner { 127 width: 40px; 128 height: 40px; 129 border: 4px solid #ccc; 130 border-top: 4px solid #2271b1; 131 border-radius: 50%; 132 animation: kombat-spin 0.8s linear infinite; 133 margin: 0 auto; 134 } 135 136 @keyframes kombat-spin { 137 0% { transform: rotate(0deg); } 138 100% { transform: rotate(360deg); } 139 } 140 141 #close-info-box { 142 position: absolute; 143 top: 8px; 144 right: 10px; 145 background: none; 146 border: none; 147 font-size: 16px; 148 color: #666; 149 cursor: pointer; 150 } 151 152 #close-info-box:hover { 153 color: #000; 154 } 155 156 #kombat-info-restore { 157 text-align: center; 158 } -
kombatoptimizer/trunk/assets/admin.js
r3379089 r3381077 1 1 document.addEventListener("DOMContentLoaded", function () { 2 const buttons = document.querySelectorAll(".kombat-tab-buttons button"); 3 const contents = document.querySelectorAll(".kombat-tab-content"); 2 // 🔁 Tabs 3 const buttons = document.querySelectorAll(".kombat-tab-buttons button"); 4 const contents = document.querySelectorAll(".kombat-tab-content"); 4 5 5 function activateTab(tabId) { 6 buttons.forEach((b) => b.classList.remove("active")); 7 contents.forEach((c) => c.classList.remove("active")); 8 const btn = document.querySelector(`.kombat-tab-buttons button[data-target="${tabId}"]`); 9 const content = document.getElementById(tabId); 10 if (btn && content) { 11 btn.classList.add("active"); 12 content.classList.add("active"); 13 } 6 function activateTab(tabId) { 7 buttons.forEach((b) => b.classList.remove("active")); 8 contents.forEach((c) => c.classList.remove("active")); 9 const btn = document.querySelector(`.kombat-tab-buttons button[data-target="${tabId}"]`); 10 const content = document.getElementById(tabId); 11 if (btn && content) { 12 btn.classList.add("active"); 13 content.classList.add("active"); 14 14 } 15 } 15 16 16 buttons.forEach((btn) => { 17 btn.addEventListener("click", function () { 18 const target = btn.dataset.target; 19 localStorage.setItem("kombatoptimizer_active_tab", target); 20 activateTab(target); 21 }); 17 buttons.forEach((btn) => { 18 btn.addEventListener("click", function () { 19 const target = btn.dataset.target; 20 localStorage.setItem("kombatoptimizer_active_tab", target); 21 activateTab(target); 22 22 }); 23 }); 23 24 24 const savedTab = localStorage.getItem("kombatoptimizer_active_tab"); 25 activateTab(savedTab || "tab-generator"); 25 const savedTab = localStorage.getItem("kombatoptimizer_active_tab"); 26 activateTab(savedTab || "tab-generator"); 27 28 // ✅ Mesaje temporare 29 const messages = document.querySelectorAll('.kombat-success:not(.kombat-persistent)'); 30 messages.forEach(msg => { 31 setTimeout(() => { 32 msg.style.display = 'none'; 33 }, 3000); 34 }); 35 36 // ✖ Închide mesajul informativ și salvează preferința 37 const closeBtn = document.getElementById("close-info-box"); 38 const infoBox = document.getElementById("kombat-info-box"); 39 const restoreBox = document.getElementById("kombat-info-restore"); 40 const restoreLink = restoreBox ? restoreBox.querySelector("a") : null; 41 42 if (localStorage.getItem("kombatoptimizer_info_closed") === "true") { 43 if (infoBox) infoBox.style.display = "none"; 44 if (restoreBox) restoreBox.style.display = "block"; 45 } else { 46 if (restoreBox) restoreBox.style.display = "none"; 47 } 48 49 if (closeBtn && infoBox) { 50 closeBtn.addEventListener("click", function () { 51 infoBox.style.display = "none"; 52 localStorage.setItem("kombatoptimizer_info_closed", "true"); 53 if (restoreBox) restoreBox.style.display = "block"; 54 }); 55 } 56 57 if (restoreLink && infoBox) { 58 restoreLink.addEventListener("click", function () { 59 localStorage.removeItem("kombatoptimizer_info_closed"); 60 infoBox.style.display = "block"; 61 if (restoreBox) restoreBox.style.display = "none"; 62 }); 63 } 64 65 // 🔄 Loader vizual la submit 66 const form = document.querySelector("#tab-generator form"); 67 const loader = document.getElementById("kombat-loader"); 68 69 if (form && loader) { 70 form.addEventListener("submit", function () { 71 loader.style.display = "block"; 72 }); 73 } 26 74 }); 27 28 document.addEventListener("DOMContentLoaded", function () {29 const messages = document.querySelectorAll('.kombat-success:not(.kombat-persistent)');30 messages.forEach(msg => {31 setTimeout(() => {32 msg.style.display = 'none';33 }, 3000); // doar cele fără .kombat-persistent dispar34 });35 });36 37 -
kombatoptimizer/trunk/inc/generate-webp.php
r3379089 r3381077 2 2 if (!defined('ABSPATH')) exit; 3 3 4 // 🔧 Generează WebP din folderul selectat 4 // 🔧 Generează WebP din folderul selectat, cu limită de procesare 5 5 if (!function_exists('generate_webp_from_folder')) { 6 6 function generate_webp_from_folder($subfolder) { … … 13 13 $target_dir = trailingslashit($upload_dir['basedir']) . 'kombatoptimizer/' . $subfolder; 14 14 15 // 🛑 Verificare existență folder sursă 15 16 if (!is_dir($source_dir)) { 16 17 kombatoptimizer_log("Folder sursă invalid: $source_dir"); … … 18 19 } 19 20 21 // 📦 Creează folderul destinație dacă nu există 20 22 if (!file_exists($target_dir)) { 21 23 wp_mkdir_p($target_dir); … … 24 26 $converted = 0; 25 27 $skipped = 0; 28 $processed = 0; 29 $max_images = 150; // 🔒 Limită maximă de imagini procesate 26 30 31 // 🔁 Iterare recursivă prin fișierele din folderul sursă 27 32 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source_dir)); 28 33 foreach ($rii as $file) { 29 34 if ($file->isDir()) continue; 30 35 36 // 🛑 Oprire dacă s-a atins limita 37 if ($processed >= $max_images) { 38 kombatoptimizer_log("Limită atinsă: s-au procesat doar $max_images imagini."); 39 break; 40 } 41 31 42 $image_path = $file->getPathname(); 43 44 // 🎯 Filtrare doar JPG/JPEG/PNG 32 45 if (!preg_match('/\.(jpg|jpeg|png)$/i', $image_path)) continue; 33 46 … … 45 58 } 46 59 60 // ⏭️ Dacă fișierul WebP există deja, îl ignorăm 47 61 if (file_exists($webp_path)) { 48 62 $skipped++; 63 $processed++; 49 64 continue; 50 65 } … … 53 68 if (preg_match('/\.png$/i', $image_path)) { 54 69 $image = @imagecreatefrompng($image_path); 55 if (!$image) { $skipped++; continue; }70 if (!$image) { $skipped++; $processed++; continue; } 56 71 if (!imageistruecolor($image)) imagepalettetotruecolor($image); 57 72 imagealphablending($image, false); … … 59 74 } else { 60 75 $image = @imagecreatefromstring(file_get_contents($image_path)); 61 if (!$image) { $skipped++; continue; }76 if (!$image) { $skipped++; $processed++; continue; } 62 77 } 63 78 79 // 💾 Salvare WebP 64 80 imagewebp($image, $webp_path, 85); 65 81 82 // 🧼 Verificare fișier corupt 66 83 if (filesize($webp_path) < 100) { 67 84 wp_delete_file($webp_path); … … 73 90 74 91 imagedestroy($image); 92 $processed++; 75 93 } 76 94 95 // 📊 Log final 77 96 kombatoptimizer_log("Generare WebP din '$subfolder': convertite=$converted, ignorate=$skipped"); 78 97 … … 80 99 } 81 100 } 101 102 /** 103 * 🔍 Returnează doar folderele de tip an (ex: 2025, 2024) din wp-content/uploads/ 104 * Ignoră folderele non-media (kombatoptimizer, rank_math, etc.) 105 */ 106 function get_year_folders() { 107 $upload_dir = wp_upload_dir()['basedir']; 108 $excluded = ['kombatoptimizer', 'rank_math', 'elementor', 'wpforms', 'woocommerce', 'siteorigin']; 109 110 // 📁 Obține toate subfolderele din uploads/ 111 $folders = glob($upload_dir . '/*', GLOB_ONLYDIR); 112 113 // 🧹 Filtrare: doar cele care sunt ani și nu conțin nume excluse 114 $year_folders = array_filter($folders, function($folder) use ($excluded) { 115 $basename = basename($folder); 116 117 // ✅ Trebuie să fie format de an (ex: 2025) 118 if (!preg_match('/^\d{4}$/', $basename)) return false; 119 120 // ❌ Excludem folderele non-media 121 foreach ($excluded as $ex) { 122 if (stripos($folder, $ex) !== false) return false; 123 } 124 125 return true; 126 }); 127 128 return $year_folders; // 🔙 Returnează array cu căi complete 129 } -
kombatoptimizer/trunk/kombat-optimizer.php
r3379089 r3381077 4 4 Plugin URI: https://webdesign-profesional.com/kombat-optimizer 5 5 Description: Optimizare automată WebP, preload inteligent și monitorizare TTFB. Include cron săptămânal și scanare pe foldere. 6 Version: 1.2. 16 Version: 1.2.2 7 7 Author: Alin 8 8 Author URI: https://webdesign-profesional.com … … 72 72 73 73 // 🔧 Tab 1: Generator WebP 74 74 75 echo '<div id="tab-generator" class="kombat-tab-content">'; 75 76 echo '<h3>🔧 Generator & Optimizare WebP</h3>'; … … 79 80 echo '<p><label for="webp_folder"><strong>Selectează folderul:</strong></label><br>'; 80 81 echo '<select name="webp_folder" id="webp_folder">'; 81 foreach ( $foldersas $folder) {82 foreach (get_year_folders() as $folder) { 82 83 $name = str_replace($base_dir, '', $folder); 83 84 echo '<option value="' . esc_attr($name) . '">' . esc_html($name) . '</option>'; 84 85 } 85 echo '</select> </p>';86 echo '</select> </p>'; 86 87 87 88 echo '<p>'; … … 89 90 echo '<button type="submit" name="optimize_webp" class="kombat-btn">Optimizează imaginile WebP</button>'; 90 91 echo '</p>'; 91 echo '</form>'; 92 93 echo '<div id="kombat-loader">'; 94 echo '<div class="spinner"></div>'; 95 echo '<p>Se procesează imaginile... te rugăm să aștepți.</p>'; 96 echo '</div>'; 97 98 99 echo '</form>'; 100 101 102 // ℹ️ Mesaj explicativ permanent sub butoane 103 echo '<div id="kombat-info-box" class="notice notice-info" style="margin-top:20px; position:relative;">'; 104 echo '<button type="button" id="close-info-box" style="position:absolute; top:8px; right:10px; background:none; border:none; font-size:16px; cursor:pointer;">✖</button>'; 105 echo '<p><strong>ℹ️ Cum funcționează:</strong></p>'; 106 echo '<ul style="margin-left:20px;">'; 107 echo '<li>Se afișează doar folderele de tip <code>uploads/2025</code>, <code>uploads/2024</code> etc. — cele care conțin imagini media.</li>'; 108 echo '<li>Folderele interne ale pluginurilor (ex: <code>rank_math</code>, <code>kombatoptimizer</code>) sunt automat excluse.</li>'; 109 echo '<li>Se procesează maxim <strong>150 imagini</strong> per folder, pentru a evita blocarea serverului.</li>'; 110 echo '<li>Imaginile deja convertite în WebP sunt ignorate automat.</li>'; 111 echo '</ul>'; 112 echo '<p>Pentru rezultate optime, selectează folderul corespunzător anului în care au fost încărcate imaginile.</p>'; 113 echo '</div>'; 114 echo '<p id="kombat-info-restore" style="margin-top:10px;">'; 115 echo '<a href="#" style="text-decoration:none;" onclick="return false;">🔄 Afișează din nou explicația</a>'; 116 echo '</p>'; 92 117 93 118 // 🔁 Procesare acțiuni POST … … 187 212 188 213 echo '<select name="scan_folder">'; 189 foreach ( $foldersas $folder) {214 foreach (get_year_folders() as $folder) { 190 215 $name = str_replace($base_dir, '', $folder); 191 216 echo '<option value="' . esc_attr($name) . '">' . esc_html($name) . '</option>';
Note: See TracChangeset
for help on using the changeset viewer.