Changeset 3451104
- Timestamp:
- 01/31/2026 05:25:05 PM (3 weeks ago)
- Location:
- blaminhor-essentials
- Files:
-
- 100 added
- 27 edited
-
tags/1.4.6 (added)
-
tags/1.4.6/assets (added)
-
tags/1.4.6/assets/css (added)
-
tags/1.4.6/assets/css/admin.css (added)
-
tags/1.4.6/assets/css/admin.min.css (added)
-
tags/1.4.6/assets/css/index.php (added)
-
tags/1.4.6/assets/css/modules.css (added)
-
tags/1.4.6/assets/images (added)
-
tags/1.4.6/assets/index.php (added)
-
tags/1.4.6/assets/js (added)
-
tags/1.4.6/assets/js/admin.js (added)
-
tags/1.4.6/assets/js/admin.min.js (added)
-
tags/1.4.6/assets/js/index.php (added)
-
tags/1.4.6/assets/js/modules.js (added)
-
tags/1.4.6/blaminhor-essentials.php (added)
-
tags/1.4.6/includes (added)
-
tags/1.4.6/includes/class-blaminhor-essentials-admin.php (added)
-
tags/1.4.6/includes/class-blaminhor-essentials-module.php (added)
-
tags/1.4.6/includes/functions.php (added)
-
tags/1.4.6/includes/index.php (added)
-
tags/1.4.6/index.php (added)
-
tags/1.4.6/languages (added)
-
tags/1.4.6/languages/blaminhor-essentials-de_DE.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-de_DE.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-es_ES.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-es_ES.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-fr_FR.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-fr_FR.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-id_ID.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-id_ID.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-it_IT.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-it_IT.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-ja.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-ja.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-nl_NL.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-nl_NL.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-pt_BR.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-pt_BR.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-pt_PT.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-pt_PT.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-ru_RU.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-ru_RU.po (added)
-
tags/1.4.6/languages/blaminhor-essentials-tr_TR.mo (added)
-
tags/1.4.6/languages/blaminhor-essentials-tr_TR.po (added)
-
tags/1.4.6/languages/blaminhor-essentials.pot (added)
-
tags/1.4.6/languages/index.php (added)
-
tags/1.4.6/languages/messages.mo (added)
-
tags/1.4.6/modules (added)
-
tags/1.4.6/modules/backup (added)
-
tags/1.4.6/modules/backup/class-module-backup.php (added)
-
tags/1.4.6/modules/backup/index.php (added)
-
tags/1.4.6/modules/broken-links (added)
-
tags/1.4.6/modules/broken-links/class-module-broken-links.php (added)
-
tags/1.4.6/modules/broken-links/index.php (added)
-
tags/1.4.6/modules/classic-editor (added)
-
tags/1.4.6/modules/classic-editor/class-module-classic-editor.php (added)
-
tags/1.4.6/modules/db-optimizer (added)
-
tags/1.4.6/modules/db-optimizer/class-module-db-optimizer.php (added)
-
tags/1.4.6/modules/db-optimizer/index.php (added)
-
tags/1.4.6/modules/domain-changer (added)
-
tags/1.4.6/modules/domain-changer/class-module-domain-changer.php (added)
-
tags/1.4.6/modules/domain-changer/index.php (added)
-
tags/1.4.6/modules/duplicator (added)
-
tags/1.4.6/modules/duplicator/class-module-duplicator.php (added)
-
tags/1.4.6/modules/duplicator/index.php (added)
-
tags/1.4.6/modules/duplicator/views (added)
-
tags/1.4.6/modules/fatal-error-recovery (added)
-
tags/1.4.6/modules/fatal-error-recovery/class-module-fatal-error-recovery.php (added)
-
tags/1.4.6/modules/favicon (added)
-
tags/1.4.6/modules/favicon/class-module-favicon.php (added)
-
tags/1.4.6/modules/favicon/index.php (added)
-
tags/1.4.6/modules/https-redirect (added)
-
tags/1.4.6/modules/https-redirect/class-module-https-redirect.php (added)
-
tags/1.4.6/modules/https-redirect/index.php (added)
-
tags/1.4.6/modules/image-sizes (added)
-
tags/1.4.6/modules/image-sizes/class-module-image-sizes.php (added)
-
tags/1.4.6/modules/image-sizes/index.php (added)
-
tags/1.4.6/modules/index.php (added)
-
tags/1.4.6/modules/maintenance (added)
-
tags/1.4.6/modules/maintenance/class-module-maintenance.php (added)
-
tags/1.4.6/modules/maintenance/index.php (added)
-
tags/1.4.6/modules/mute-core-emails (added)
-
tags/1.4.6/modules/mute-core-emails/class-module-mute-core-emails.php (added)
-
tags/1.4.6/modules/mute-core-emails/index.php (added)
-
tags/1.4.6/modules/post-types-order (added)
-
tags/1.4.6/modules/post-types-order/class-module-post-types-order.php (added)
-
tags/1.4.6/modules/post-types-order/index.php (added)
-
tags/1.4.6/modules/redirections (added)
-
tags/1.4.6/modules/redirections/class-module-redirections.php (added)
-
tags/1.4.6/modules/redirections/index.php (added)
-
tags/1.4.6/modules/seo-manager (added)
-
tags/1.4.6/modules/seo-manager/class-module-seo-manager.php (added)
-
tags/1.4.6/modules/seo-manager/index.php (added)
-
tags/1.4.6/modules/smtp (added)
-
tags/1.4.6/modules/smtp/class-module-smtp.php (added)
-
tags/1.4.6/modules/smtp/index.php (added)
-
tags/1.4.6/modules/smtp/views (added)
-
tags/1.4.6/readme.txt (added)
-
tags/1.4.6/uninstall.php (added)
-
trunk/assets/js/modules.js (modified) (7 diffs)
-
trunk/blaminhor-essentials.php (modified) (2 diffs)
-
trunk/languages/blaminhor-essentials-de_DE.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-de_DE.po (modified) (13 diffs)
-
trunk/languages/blaminhor-essentials-es_ES.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-es_ES.po (modified) (11 diffs)
-
trunk/languages/blaminhor-essentials-fr_FR.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-fr_FR.po (modified) (12 diffs)
-
trunk/languages/blaminhor-essentials-id_ID.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-id_ID.po (modified) (11 diffs)
-
trunk/languages/blaminhor-essentials-it_IT.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-it_IT.po (modified) (11 diffs)
-
trunk/languages/blaminhor-essentials-ja.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-ja.po (modified) (11 diffs)
-
trunk/languages/blaminhor-essentials-nl_NL.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-nl_NL.po (modified) (12 diffs)
-
trunk/languages/blaminhor-essentials-pt_BR.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-pt_BR.po (modified) (12 diffs)
-
trunk/languages/blaminhor-essentials-pt_PT.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-pt_PT.po (modified) (11 diffs)
-
trunk/languages/blaminhor-essentials-ru_RU.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-ru_RU.po (modified) (10 diffs)
-
trunk/languages/blaminhor-essentials-tr_TR.mo (modified) (previous)
-
trunk/languages/blaminhor-essentials-tr_TR.po (modified) (12 diffs)
-
trunk/languages/messages.mo (added)
-
trunk/modules/backup/class-module-backup.php (modified) (23 diffs)
-
trunk/modules/post-types-order/class-module-post-types-order.php (modified) (4 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
blaminhor-essentials/trunk/assets/js/modules.js
r3450705 r3451104 876 876 this.ajaxurl = config.ajaxurl || ajaxurl; 877 877 this.strings = config.strings || {}; 878 this.maxUploadSize = config.maxUploadSize || 0; 879 this.maxUploadLabel = config.maxUploadLabel || ''; 878 880 this.bindEvents(); 879 881 this.checkAutoBackup(); … … 890 892 891 893 $(document).off('click' + ns, '.ap-backup-download').on('click' + ns, '.ap-backup-download', function() { 892 var $row = $(this).closest('tr'); 893 var archives = $row.data('archives'); 894 if (archives && archives.length) { 895 self.downloadBackupArchives(archives); 896 } 894 self.downloadBackupBundle($(this)); 897 895 }); 898 896 … … 1208 1206 var self = this; 1209 1207 var validExtensions = ['.zip']; 1208 var skippedTooLarge = []; 1210 1209 1211 1210 for (var i = 0; i < files.length; i++) { … … 1215 1214 if (validExtensions.indexOf(ext) === -1) { 1216 1215 continue; // Skip non-ZIP files 1216 } 1217 1218 // Check file size against server limit. 1219 if (this.maxUploadSize && file.size > this.maxUploadSize) { 1220 skippedTooLarge.push(file.name + ' (' + this.formatFileSize(file.size) + ')'); 1221 continue; 1217 1222 } 1218 1223 … … 1229 1234 this.uploadQueue.push(file); 1230 1235 } 1236 } 1237 1238 // Show warning for files that exceed the server upload limit. 1239 if (skippedTooLarge.length > 0) { 1240 var $tabContent = $('[data-tab-content="upload"]'); 1241 $tabContent.find('.ap-upload-size-notice').remove(); 1242 var notice = '<div class="blaminhor-essentials-notice error ap-upload-size-notice" style="margin-bottom: 15px;">' + 1243 '<span class="dashicons dashicons-warning"></span> ' + 1244 (this.strings.fileTooLarge || 'The following file(s) exceed the server upload limit') + 1245 ' (' + (this.maxUploadLabel || '') + '):<br>' + 1246 skippedTooLarge.join('<br>') + 1247 '</div>'; 1248 $tabContent.prepend(notice); 1231 1249 } 1232 1250 … … 1461 1479 }, 1462 1480 1463 downloadBackupArchives: function(archives) { 1464 var self = this; 1465 var urls = []; 1466 var loaded = 0; 1467 1468 // Step 1: Fetch all download URLs in parallel. 1469 $.each(archives, function(i, filename) { 1470 $.post(self.ajaxurl, { 1471 action: 'ap_backup_download', 1472 nonce: self.nonce, 1473 filename: filename 1474 }, function(response) { 1475 if (response.success) { 1476 urls[i] = response.data.url; 1477 } 1478 loaded++; 1479 if (loaded === archives.length) { 1480 triggerDownloads(); 1481 } 1482 }); 1483 }); 1484 1485 // Step 2: Trigger downloads sequentially via window.location.href. 1486 function triggerDownloads() { 1487 var index = 0; 1488 function next() { 1489 if (index >= urls.length) { 1490 return; 1491 } 1492 if (urls[index]) { 1493 window.location.href = urls[index]; 1494 } 1495 index++; 1496 if (index < urls.length) { 1497 setTimeout(next, 1500); 1498 } 1499 } 1500 next(); 1501 } 1481 downloadBackupBundle: function($btn) { 1482 var label = $btn.text(); 1483 $btn.prop('disabled', true).html('<span class="spinner is-active" style="float: none; margin: 0 5px 0 0;"></span>' + (this.strings.preparing || 'Preparing...')); 1484 $.post(this.ajaxurl, { 1485 action: 'ap_backup_download_bundle', 1486 nonce: this.nonce, 1487 prefix: $btn.data('prefix') 1488 }, function(response) { 1489 $btn.prop('disabled', false).text(label); 1490 if (response.success) { 1491 window.location.href = response.data.url; 1492 } else { 1493 alert(response.data); 1494 } 1495 }).fail(function() { 1496 $btn.prop('disabled', false).text(label); 1497 }); 1502 1498 }, 1503 1499 … … 1834 1830 $('#ap-restore-new-domain').val(''); 1835 1831 1836 // For uploaded backups, check domain info 1837 if (type === 'uploaded' || components.indexOf('uploaded') !== -1) { 1838 // Get the first file from the backup 1839 var $row = $btn.closest('tr'); 1840 var files = $row.data('files') || []; 1841 var filename = files.length > 0 ? files[0].filename : (prefix + '-uploaded.zip'); 1842 1843 $.post(this.ajaxurl, { 1844 action: 'ap_backup_get_domain_info', 1845 nonce: this.nonce, 1846 filename: filename 1847 }, function(response) { 1848 if (response.success && response.data.domain_differs) { 1849 $('#ap-restore-domain-option').show(); 1850 $('#ap-restore-domain-info').html( 1851 (self.strings.backupFrom || 'This backup is from') + ' <strong>' + response.data.backup_domain + '</strong>. ' + 1852 (self.strings.currentDomain || 'Current domain is') + ' <strong>' + response.data.current_domain + '</strong>.' 1853 ); 1854 $('#ap-restore-old-domain').val(response.data.backup_url); 1855 $('#ap-restore-new-domain').val(response.data.current_url); 1856 } 1857 }); 1858 } 1832 // Check domain info for all backup types 1833 $.post(this.ajaxurl, { 1834 action: 'ap_backup_get_domain_info', 1835 nonce: this.nonce, 1836 prefix: prefix 1837 }, function(response) { 1838 if (response.success && response.data.domain_differs) { 1839 $('#ap-restore-domain-option').show(); 1840 $('#ap-restore-domain-info').html( 1841 (self.strings.backupFrom || 'This backup is from') + ' <strong>' + response.data.backup_domain + '</strong>. ' + 1842 (self.strings.currentDomain || 'Current domain is') + ' <strong>' + response.data.current_domain + '</strong>.' 1843 ); 1844 $('#ap-restore-old-domain').val(response.data.backup_url); 1845 $('#ap-restore-new-domain').val(response.data.current_url); 1846 } 1847 }); 1859 1848 1860 1849 $('#ap-restore-modal').fadeIn(200); -
blaminhor-essentials/trunk/blaminhor-essentials.php
r3450705 r3451104 4 4 * Plugin URI: https://wp.blaminhor.com/ 5 5 * Description: A modular toolkit for WordPress with activatable features. Lightweight, secure, and reliable. 6 * Version: 1.4. 56 * Version: 1.4.6 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 7.4 … … 23 23 24 24 // Plugin constants 25 define('BLAMINHOR_ESSENTIALS_VERSION', '1.4. 5');25 define('BLAMINHOR_ESSENTIALS_VERSION', '1.4.6'); 26 26 define('BLAMINHOR_ESSENTIALS_PLUGIN_FILE', __FILE__); 27 27 define('BLAMINHOR_ESSENTIALS_PLUGIN_DIR', plugin_dir_path(__FILE__)); -
blaminhor-essentials/trunk/languages/blaminhor-essentials-de_DE.po
r3450351 r3451104 27 27 msgstr "%1$s: %2$d Vorschaubilder gelöscht" 28 28 29 #. translators: %d: number of backup archives extracted from the bundle 30 msgid "%d archives extracted" 31 msgstr "%d Archive extrahiert" 32 29 33 msgid "%d Broken Link" 30 34 msgstr "%d defekter Link" … … 111 115 msgid "A backup was created before your last restore operation on %1$s (%2$s). You can undo the restore to revert to this state." 112 116 msgstr "Vor Ihrer letzten Wiederherstellung am %1$s (%2$s) wurde eine Sicherung erstellt. Sie können die Wiederherstellung rückgängig machen, um zu diesem Zustand zurückzukehren." 117 118 msgid "A full backup of your current site will be created automatically before restoring." 119 msgstr "Vor der Wiederherstellung wird automatisch eine vollständige Sicherung Ihrer aktuellen Website erstellt." 113 120 114 121 msgid "A PHP extension stopped the file upload." … … 411 418 msgstr "Domain nach Wiederherstellung ändern" 412 419 420 msgid "Change domain automatically after restore" 421 msgstr "Domain nach der Wiederherstellung automatisch ändern" 422 413 423 msgid "Change Domain Now" 414 424 msgstr "Domain jetzt ändern" … … 703 713 msgstr "Erkanntes Plugin:" 704 714 715 msgid "Different domain detected" 716 msgstr "Anderer Domain erkannt" 717 705 718 msgid "Disable" 706 719 msgstr "Deaktivieren" … … 961 974 msgstr "Fehler beim Erstellen des Sicherungsarchivs." 962 975 976 msgid "Failed to create bundle archive." 977 msgstr "Fehler beim Erstellen des gebündelten Archivs." 978 963 979 msgid "Failed to create pre-restore backup." 964 980 msgstr "Fehler beim Erstellen der Vor-Wiederherstellungs-Sicherung." … … 972 988 msgid "Failed to open backup archive." 973 989 msgstr "Fehler beim Öffnen des Sicherungsarchivs." 990 991 msgid "Failed to read the bundle archive." 992 msgstr "Das Paketarchiv konnte nicht gelesen werden." 974 993 975 994 msgid "Failed to regenerate thumbnails." … … 1257 1276 msgid "Invalid backup identifier" 1258 1277 msgstr "Ungültiger Backup-Bezeichner" 1278 1279 msgid "Invalid backup prefix." 1280 msgstr "Ungültiges Backup-Präfix." 1259 1281 1260 1282 msgid "Invalid backup parameters." … … 1492 1514 msgstr "Keine Datenbanktabellen gefunden." 1493 1515 1516 msgid "No database.sql found in the database archive." 1517 msgstr "Keine database.sql in der Datenbank-Archivdatei gefunden." 1518 1494 1519 msgid "No file uploaded." 1495 1520 msgstr "Keine Datei hochgeladen." … … 1532 1557 msgid "No type specified." 1533 1558 msgstr "Kein Typ angegeben." 1559 1560 msgid "No valid backup archives found in the bundle." 1561 msgstr "Keine gültigen Sicherungsarchive im Paket gefunden." 1534 1562 1535 1563 msgid "Not set" … … 1776 1804 msgid "Pre-update Backup" 1777 1805 msgstr "Sicherung vor Updates" 1806 1807 msgid "Preparing..." 1808 msgstr "Vorbereitung..." 1778 1809 1779 1810 msgid "Press Enter or comma to add a keyword. Click × to remove." … … 2262 2293 msgstr "Wiederherstellungsmodus testen" 2263 2294 2295 msgid "The archive does not contain any recognizable backup data." 2296 msgstr "Das Archiv enthält keine erkennbaren Sicherungsdaten." 2297 2264 2298 msgid "The Backup module is not active." 2265 2299 msgstr "Das Backup-Modul ist nicht aktiv." … … 2267 2301 msgid "The Block Editor is currently disabled." 2268 2302 msgstr "Der Block-Editor ist derzeit deaktiviert." 2303 2304 msgid "The database backup file is empty or contains no valid SQL statements." 2305 msgstr "Die Datenbank-Sicherungsdatei ist leer oder enthält keine gültigen SQL-Anweisungen." 2306 2307 msgid "The following file(s) exceed the server upload limit" 2308 msgstr "Die folgenden Datei(en) überschreiten das Server-Upload-Limit" 2269 2309 2270 2310 msgid "The new domain is the same as the current domain." … … 2528 2568 msgstr "Warnung:" 2529 2569 2570 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 2571 msgstr "Warnung: Die Wiederherstellung einer Sicherung überschreibt Ihre aktuellen Daten. Diese Aktion kann nicht rückgängig gemacht werden." 2572 2530 2573 msgid "We are working hard to bring you something amazing. Stay tuned!" 2531 2574 msgstr "" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-es_ES.po
r3450351 r3451104 18 18 msgstr " - copia" 19 19 20 #. translators: %d: number of backup archives extracted from the bundle 21 msgid "%d archives extracted" 22 msgstr "%d archivos extraídos" 23 20 24 #. translators: %d: number of selected items 21 25 msgid "%d selected" … … 44 48 msgstr "Un nombre amigable para identificar este relay." 45 49 50 msgid "A full backup of your current site will be created automatically before restoring." 51 msgstr "Se creará automáticamente una copia de seguridad completa de su sitio actual antes de la restauración." 52 46 53 msgid "A PHP extension stopped the file upload." 47 54 msgstr "Una extensión PHP detuvo la subida del archivo." … … 203 210 msgstr "Archivos de categorías y etiquetas" 204 211 212 msgid "Change domain automatically after restore" 213 msgstr "Cambiar el dominio automáticamente después de la restauración" 214 205 215 msgid "Change this setting" 206 216 msgstr "Cambiar este ajuste" … … 323 333 msgstr "Descripción" 324 334 335 msgid "Different domain detected" 336 msgstr "Dominio diferente detectado" 337 325 338 msgid "Disable HTTPS Redirect" 326 339 msgstr "Desactivar redirección HTTPS" … … 449 462 msgstr "Error al crear la copia de seguridad." 450 463 464 msgid "Failed to create bundle archive." 465 msgstr "Error al crear el archivo del paquete." 466 467 msgid "Failed to read the bundle archive." 468 msgstr "Error al leer el archivo del paquete." 469 451 470 msgid "Failed to save the uploaded file." 452 471 msgstr "Error al guardar el archivo subido." … … 557 576 msgstr "Inicializando..." 558 577 578 msgid "Invalid backup prefix." 579 msgstr "Prefijo de copia de seguridad no válido." 580 559 581 msgid "Invalid email address." 560 582 msgstr "Dirección de correo no válida." … … 661 683 msgid "No backups selected." 662 684 msgstr "No se han seleccionado copias de seguridad." 685 686 msgid "No database.sql found in the database archive." 687 msgstr "No se encontró database.sql en el archivo de base de datos." 663 688 664 689 msgid "No file uploaded." … … 690 715 msgid "No type specified." 691 716 msgstr "Ningún tipo especificado." 717 718 msgid "No valid backup archives found in the bundle." 719 msgstr "No se encontraron archivos de respaldo válidos en el paquete." 692 720 693 721 msgid "None" … … 803 831 msgstr "Copia de seguridad antes de actualizar" 804 832 833 msgid "Preparing..." 834 msgstr "Preparando..." 835 805 836 msgid "Preview" 806 837 msgstr "Vista previa" … … 1043 1074 msgstr "¡Gracias por tus comentarios!" 1044 1075 1076 msgid "The archive does not contain any recognizable backup data." 1077 msgstr "El archivo no contiene datos de copia de seguridad reconocibles." 1078 1045 1079 msgid "The Block Editor is currently disabled." 1046 1080 msgstr "El editor de bloques está actualmente desactivado." 1047 1081 1082 msgid "The database backup file is empty or contains no valid SQL statements." 1083 msgstr "El archivo de copia de seguridad de la base de datos está vacío o no contiene instrucciones SQL válidas." 1084 1085 msgid "The following file(s) exceed the server upload limit" 1086 msgstr "Los siguientes archivos exceden el límite de subida del servidor" 1087 1048 1088 msgid "The uploaded file exceeds the MAX_FILE_SIZE directive." 1049 1089 msgstr "El archivo subido excede la directiva MAX_FILE_SIZE." … … 1147 1187 msgid "Warning" 1148 1188 msgstr "Advertencia" 1189 1190 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 1191 msgstr "Advertencia: la restauración de una copia de seguridad sobrescribirá sus datos actuales. Esta acción no se puede deshacer." 1149 1192 1150 1193 msgid "Weekly" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-fr_FR.po
r3450351 r3451104 27 27 msgstr "%1$s : %2$d miniatures supprimées" 28 28 29 #. translators: %d: number of backup archives extracted from the bundle 30 msgid "%d archives extracted" 31 msgstr "%d archives extraites" 32 29 33 msgid "%d Broken Link" 30 34 msgstr "%d lien cassé" … … 119 123 msgid "A friendly name to identify this relay." 120 124 msgstr "Un nom convivial pour identifier ce relais." 125 126 msgid "A full backup of your current site will be created automatically before restoring." 127 msgstr "Une sauvegarde complète de votre site actuel sera créée automatiquement avant la restauration." 121 128 122 129 msgid "A PHP extension stopped the file upload." … … 514 521 msgstr "Changer le domaine après la restauration" 515 522 523 msgid "Change domain automatically after restore" 524 msgstr "Changer le domaine automatiquement après la restauration" 525 516 526 msgid "Change Domain Now" 517 527 msgstr "Changer le domaine maintenant" … … 931 941 msgstr "Développeurs, intégration API" 932 942 943 msgid "Different domain detected" 944 msgstr "Domaine différent détecté" 945 933 946 msgid "Dimensions" 934 947 msgstr "Dimensions" … … 1255 1268 msgstr "Échec de la création de l'archive de sauvegarde." 1256 1269 1270 msgid "Failed to create bundle archive." 1271 msgstr "Échec de la création de l'archive groupée." 1272 1257 1273 msgid "Failed to create pre-restore backup." 1258 1274 msgstr "Échec de la création de la sauvegarde pré-restauration." … … 1266 1282 msgid "Failed to open backup archive." 1267 1283 msgstr "Échec de l'ouverture de l'archive de sauvegarde." 1284 1285 msgid "Failed to read the bundle archive." 1286 msgstr "Échec de la lecture de l'archive groupée." 1268 1287 1269 1288 msgid "Failed to regenerate thumbnails." … … 1638 1657 msgid "Invalid backup identifier" 1639 1658 msgstr "Identifiant de sauvegarde invalide" 1659 1660 msgid "Invalid backup prefix." 1661 msgstr "Préfixe de sauvegarde invalide." 1640 1662 1641 1663 msgid "Invalid backup parameters." … … 1942 1964 msgstr "Aucune table de base de données trouvée." 1943 1965 1966 msgid "No database.sql found in the database archive." 1967 msgstr "Aucun fichier database.sql trouvé dans l'archive de base de données." 1968 1944 1969 msgid "No emails logged yet." 1945 1970 msgstr "Aucun email enregistré pour l'instant." … … 1988 2013 msgid "No type specified." 1989 2014 msgstr "Aucun type spécifié." 2015 2016 msgid "No valid backup archives found in the bundle." 2017 msgstr "Aucune archive de sauvegarde valide trouvée dans le lot." 1990 2018 1991 2019 msgid "None" … … 2999 3027 msgstr "L'email d'expédition authentifié pour ce relais." 3000 3028 3029 msgid "The archive does not contain any recognizable backup data." 3030 msgstr "L'archive ne contient aucune donnée de sauvegarde reconnaissable." 3031 3001 3032 msgid "The Backup module is not active." 3002 3033 msgstr "Le module de sauvegarde n'est pas actif." … … 3006 3037 msgstr "L'éditeur de blocs est actuellement désactivé." 3007 3038 3039 msgid "The database backup file is empty or contains no valid SQL statements." 3040 msgstr "Le fichier de sauvegarde de la base de données est vide ou ne contient aucune instruction SQL valide." 3041 3042 msgid "The following file(s) exceed the server upload limit" 3043 msgstr "Le(s) fichier(s) suivant(s) dépassent la limite d'envoi du serveur" 3044 3008 3045 msgid "The new domain is the same as the current domain." 3009 3046 msgstr "Le nouveau domaine est identique au domaine actuel." … … 3323 3360 msgstr "Attention :" 3324 3361 3362 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 3363 msgstr "Attention : la restauration d'une sauvegarde écrasera vos données actuelles. Cette action est irréversible." 3364 3325 3365 msgid "We are working hard to bring you something amazing. Stay tuned!" 3326 3366 msgstr "" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-id_ID.po
r3450351 r3451104 18 18 msgstr " - salinan" 19 19 20 #. translators: %d: number of backup archives extracted from the bundle 21 msgid "%d archives extracted" 22 msgstr "%d arsip diekstrak" 23 20 24 #. translators: %d: number of selected items 21 25 msgid "%d selected" … … 44 48 msgstr "Nama yang mudah dikenali untuk mengidentifikasi relay ini." 45 49 50 msgid "A full backup of your current site will be created automatically before restoring." 51 msgstr "Cadangan lengkap situs Anda saat ini akan dibuat secara otomatis sebelum pemulihan." 52 46 53 msgid "A PHP extension stopped the file upload." 47 54 msgstr "Ekstensi PHP menghentikan unggahan berkas." … … 203 210 msgstr "Arsip kategori dan tag" 204 211 212 msgid "Change domain automatically after restore" 213 msgstr "Ubah domain secara otomatis setelah pemulihan" 214 205 215 msgid "Change this setting" 206 216 msgstr "Ubah pengaturan ini" … … 323 333 msgstr "Deskripsi" 324 334 335 msgid "Different domain detected" 336 msgstr "Domain berbeda terdeteksi" 337 325 338 msgid "Disable HTTPS Redirect" 326 339 msgstr "Nonaktifkan Pengalihan HTTPS" … … 449 462 msgstr "Gagal membuat cadangan." 450 463 464 msgid "Failed to create bundle archive." 465 msgstr "Gagal membuat arsip bundel." 466 467 msgid "Failed to read the bundle archive." 468 msgstr "Gagal membaca arsip bundel." 469 451 470 msgid "Failed to save the uploaded file." 452 471 msgstr "Gagal menyimpan berkas yang diunggah." … … 557 576 msgstr "Menginisialisasi..." 558 577 578 msgid "Invalid backup prefix." 579 msgstr "Awalan cadangan tidak valid." 580 559 581 msgid "Invalid email address." 560 582 msgstr "Alamat email tidak valid." … … 662 684 msgstr "Tidak ada cadangan yang dipilih." 663 685 686 msgid "No database.sql found in the database archive." 687 msgstr "database.sql tidak ditemukan dalam arsip database." 688 664 689 msgid "No file uploaded." 665 690 msgstr "Tidak ada berkas yang diunggah." … … 688 713 msgid "No type specified." 689 714 msgstr "Tidak ada tipe yang ditentukan." 715 716 msgid "No valid backup archives found in the bundle." 717 msgstr "Tidak ditemukan arsip cadangan yang valid dalam bundel." 690 718 691 719 msgid "None" … … 799 827 msgstr "Cadangan Sebelum Pembaruan" 800 828 829 msgid "Preparing..." 830 msgstr "Mempersiapkan..." 831 801 832 msgid "Preview" 802 833 msgstr "Pratinjau" … … 1039 1070 msgstr "Terima kasih atas umpan balik Anda!" 1040 1071 1072 msgid "The archive does not contain any recognizable backup data." 1073 msgstr "Arsip tidak berisi data cadangan yang dapat dikenali." 1074 1041 1075 msgid "The Block Editor is currently disabled." 1042 1076 msgstr "Editor Blok saat ini dinonaktifkan." 1043 1077 1078 msgid "The database backup file is empty or contains no valid SQL statements." 1079 msgstr "File cadangan database kosong atau tidak berisi pernyataan SQL yang valid." 1080 1081 msgid "The following file(s) exceed the server upload limit" 1082 msgstr "File berikut melebihi batas unggah server" 1083 1044 1084 msgid "The uploaded file exceeds the MAX_FILE_SIZE directive." 1045 1085 msgstr "Berkas yang diunggah melebihi direktif MAX_FILE_SIZE." … … 1144 1184 msgstr "Peringatan" 1145 1185 1186 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 1187 msgstr "Peringatan: memulihkan cadangan akan menimpa data Anda saat ini. Tindakan ini tidak dapat dibatalkan." 1188 1146 1189 msgid "Weekly" 1147 1190 msgstr "Mingguan" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-it_IT.po
r3450351 r3451104 18 18 msgstr " - copia" 19 19 20 #. translators: %d: number of backup archives extracted from the bundle 21 msgid "%d archives extracted" 22 msgstr "%d archivi estratti" 23 20 24 #. translators: %d: number of selected items 21 25 msgid "%d selected" … … 44 48 msgstr "Un nome amichevole per identificare questo relay." 45 49 50 msgid "A full backup of your current site will be created automatically before restoring." 51 msgstr "Un backup completo del sito attuale verrà creato automaticamente prima del ripristino." 52 46 53 msgid "A PHP extension stopped the file upload." 47 54 msgstr "Un'estensione PHP ha interrotto il caricamento del file." … … 203 210 msgstr "Archivi categorie e tag" 204 211 212 msgid "Change domain automatically after restore" 213 msgstr "Cambia il dominio automaticamente dopo il ripristino" 214 205 215 msgid "Change this setting" 206 216 msgstr "Modifica questa impostazione" … … 323 333 msgstr "Descrizione" 324 334 335 msgid "Different domain detected" 336 msgstr "Dominio diverso rilevato" 337 325 338 msgid "Disable HTTPS Redirect" 326 339 msgstr "Disattiva reindirizzamento HTTPS" … … 449 462 msgstr "Impossibile creare il backup." 450 463 464 msgid "Failed to create bundle archive." 465 msgstr "Impossibile creare l'archivio del pacchetto." 466 467 msgid "Failed to read the bundle archive." 468 msgstr "Impossibile leggere l'archivio del pacchetto." 469 451 470 msgid "Failed to save the uploaded file." 452 471 msgstr "Impossibile salvare il file caricato." … … 557 576 msgstr "Inizializzazione..." 558 577 578 msgid "Invalid backup prefix." 579 msgstr "Prefisso di backup non valido." 580 559 581 msgid "Invalid email address." 560 582 msgstr "Indirizzo email non valido." … … 662 684 msgstr "Nessun backup selezionato." 663 685 686 msgid "No database.sql found in the database archive." 687 msgstr "Nessun file database.sql trovato nell'archivio del database." 688 664 689 msgid "No file uploaded." 665 690 msgstr "Nessun file caricato." … … 688 713 msgid "No type specified." 689 714 msgstr "Nessun tipo specificato." 715 716 msgid "No valid backup archives found in the bundle." 717 msgstr "Nessun archivio di backup valido trovato nel pacchetto." 690 718 691 719 msgid "None" … … 799 827 msgstr "Backup prima dell'aggiornamento" 800 828 829 msgid "Preparing..." 830 msgstr "Preparazione..." 831 801 832 msgid "Preview" 802 833 msgstr "Anteprima" … … 1039 1070 msgstr "Grazie per il tuo feedback!" 1040 1071 1072 msgid "The archive does not contain any recognizable backup data." 1073 msgstr "L'archivio non contiene dati di backup riconoscibili." 1074 1041 1075 msgid "The Block Editor is currently disabled." 1042 1076 msgstr "L'editor a blocchi è attualmente disattivato." 1043 1077 1078 msgid "The database backup file is empty or contains no valid SQL statements." 1079 msgstr "Il file di backup del database è vuoto o non contiene istruzioni SQL valide." 1080 1081 msgid "The following file(s) exceed the server upload limit" 1082 msgstr "I seguenti file superano il limite di caricamento del server" 1083 1044 1084 msgid "The uploaded file exceeds the MAX_FILE_SIZE directive." 1045 1085 msgstr "Il file caricato supera la direttiva MAX_FILE_SIZE." … … 1144 1184 msgstr "Avviso" 1145 1185 1186 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 1187 msgstr "Attenzione: il ripristino di un backup sovrascriverà i dati attuali. Questa azione non può essere annullata." 1188 1146 1189 msgid "Weekly" 1147 1190 msgstr "Settimanale" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-ja.po
r3450351 r3451104 21 21 msgstr "%2$d 件中 %1$d 件のメールタイプがミュートされました。" 22 22 23 #. translators: %d: number of backup archives extracted from the bundle 24 msgid "%d archives extracted" 25 msgstr "%d 個のアーカイブを展開しました" 26 23 27 msgid "%d redirections imported." 24 28 msgstr "%d 件のリダイレクトをインポートしました。" … … 71 75 msgstr "このリレーを識別するための名前。" 72 76 77 msgid "A full backup of your current site will be created automatically before restoring." 78 msgstr "復元前に現在のサイトの完全バックアップが自動的に作成されます。" 79 73 80 msgid "Accepted format: .zip" 74 81 msgstr "受け入れ形式: .zip" … … 302 309 msgstr "ドメインを変更" 303 310 311 msgid "Change domain automatically after restore" 312 msgstr "復元後にドメインを自動的に変更する" 313 304 314 msgid "Change Domain Now" 305 315 msgstr "今すぐドメインを変更" … … 524 534 msgstr "デスクトップ" 525 535 536 msgid "Different domain detected" 537 msgstr "異なるドメインが検出されました" 538 526 539 msgid "Disable" 527 540 msgstr "無効" … … 758 771 msgstr "失敗" 759 772 773 msgid "Failed to create bundle archive." 774 msgstr "バンドルアーカイブの作成に失敗しました。" 775 776 msgid "Failed to read the bundle archive." 777 msgstr "バンドルアーカイブの読み取りに失敗しました。" 778 760 779 msgid "Failed to send feedback. Please try again or contact us directly." 761 780 msgstr "フィードバックの送信に失敗しました。もう一度お試しいただくか、直接ご連絡ください。" … … 944 963 msgstr "初期化中..." 945 964 965 msgid "Invalid backup prefix." 966 msgstr "無効なバックアッププレフィックス。" 967 946 968 msgid "Invalid module." 947 969 msgstr "無効なモジュール。" … … 1130 1152 msgstr "データが見つかりません。" 1131 1153 1154 msgid "No database.sql found in the database archive." 1155 msgstr "データベースアーカイブにdatabase.sqlが見つかりません。" 1156 1132 1157 msgid "No emails logged yet." 1133 1158 msgstr "まだメールは記録されていません。" … … 1156 1181 msgid "No type specified." 1157 1182 msgstr "タイプが指定されていません。" 1183 1184 msgid "No valid backup archives found in the bundle." 1185 msgstr "バンドル内に有効なバックアップアーカイブが見つかりませんでした。" 1158 1186 1159 1187 msgid "None" … … 1360 1388 msgstr "更新前バックアップ" 1361 1389 1390 msgid "Preparing..." 1391 msgstr "準備中..." 1392 1362 1393 msgid "Preview" 1363 1394 msgstr "プレビュー" … … 1798 1829 msgstr "フィードバックありがとうございます!" 1799 1830 1831 msgid "The archive does not contain any recognizable backup data." 1832 msgstr "アーカイブに認識可能なバックアップデータが含まれていません。" 1833 1800 1834 msgid "The authenticated sender email for this relay." 1801 1835 msgstr "このリレーの認証済み送信者メール。" … … 1807 1841 msgstr "ブロックエディターは現在無効になっています。" 1808 1842 1843 msgid "The database backup file is empty or contains no valid SQL statements." 1844 msgstr "データベースバックアップファイルが空か、有効なSQL文が含まれていません。" 1845 1846 msgid "The following file(s) exceed the server upload limit" 1847 msgstr "次のファイルはサーバーのアップロード制限を超えています" 1848 1809 1849 msgid "The URL path to redirect from. Example: /old-page/" 1810 1850 msgstr "リダイレクト元のURLパス。例: /old-page/" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-nl_NL.po
r3450351 r3451104 21 21 msgstr "%1$d van %2$d e-mailtypes gedempt." 22 22 23 #. translators: %d: number of backup archives extracted from the bundle 24 msgid "%d archives extracted" 25 msgstr "%d archieven uitgepakt" 26 23 27 msgid "%d redirections imported." 24 28 msgstr "%d omleidingen geimporteerd." … … 86 90 msgstr "Een herkenbare naam om dit relais te identificeren." 87 91 92 msgid "A full backup of your current site will be created automatically before restoring." 93 msgstr "Er wordt automatisch een volledige back-up van uw huidige site gemaakt voordat het herstel begint." 94 88 95 msgid "About" 89 96 msgstr "Over" … … 309 316 msgstr "Domein wijzigen" 310 317 318 msgid "Change domain automatically after restore" 319 msgstr "Domein automatisch wijzigen na herstel" 320 311 321 msgid "Change Domain Now" 312 322 msgstr "Domein nu wijzigen" … … 513 523 msgstr "Alles deselecteren" 514 524 525 msgid "Different domain detected" 526 msgstr "Ander domein gedetecteerd" 527 515 528 msgid "Disable" 516 529 msgstr "Uitschakelen" … … 762 775 msgstr "Omleiding toevoegen mislukt." 763 776 777 msgid "Failed to create bundle archive." 778 msgstr "Kan bundelarchief niet aanmaken." 779 780 msgid "Failed to read the bundle archive." 781 msgstr "Kan het bundelarchief niet lezen." 782 764 783 msgid "Failed to delete redirection." 765 784 msgstr "Omleiding verwijderen mislukt." … … 972 991 msgstr "Instagram-URL" 973 992 993 msgid "Invalid backup prefix." 994 msgstr "Ongeldig back-upvoorvoegsel." 995 974 996 msgid "Invalid data." 975 997 msgstr "Ongeldige gegevens." … … 1146 1168 msgstr "Geen CSV-inhoud opgegeven." 1147 1169 1170 msgid "No database.sql found in the database archive." 1171 msgstr "Geen database.sql gevonden in het database-archief." 1172 1148 1173 msgid "No emails logged yet." 1149 1174 msgstr "Nog geen e-mails geregistreerd." … … 1190 1215 msgid "No type specified." 1191 1216 msgstr "Geen type opgegeven." 1217 1218 msgid "No valid backup archives found in the bundle." 1219 msgstr "Geen geldige back-uparchieven gevonden in de bundel." 1192 1220 1193 1221 msgid "None" … … 1376 1404 msgstr "Back-up voor update" 1377 1405 1406 msgid "Preparing..." 1407 msgstr "Voorbereiden..." 1408 1378 1409 msgid "Preview" 1379 1410 msgstr "Voorbeeld" … … 1835 1866 msgstr "Bedankt voor uw feedback!" 1836 1867 1868 msgid "The archive does not contain any recognizable backup data." 1869 msgstr "Het archief bevat geen herkenbare back-upgegevens." 1870 1837 1871 msgid "The authenticated sender email for this relay." 1838 1872 msgstr "Het geverifieerde afzender-e-mailadres voor dit relais." … … 1844 1878 msgstr "De blokeditor is momenteel uitgeschakeld." 1845 1879 1880 msgid "The database backup file is empty or contains no valid SQL statements." 1881 msgstr "Het database-back-upbestand is leeg of bevat geen geldige SQL-instructies." 1882 1883 msgid "The following file(s) exceed the server upload limit" 1884 msgstr "De volgende bestanden overschrijden de uploadlimiet van de server" 1885 1846 1886 msgid "The new domain is the same as the current domain." 1847 1887 msgstr "Het nieuwe domein is hetzelfde als het huidige domein." … … 2018 2058 msgstr "Waarschuwing: Zodra HSTS door browsers is gecached, moet uw site op HTTPS blijven. Het uitschakelen van deze instelling maakt de browsercache niet onmiddellijk ongedaan." 2019 2059 2060 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 2061 msgstr "Waarschuwing: het herstellen van een back-up overschrijft uw huidige gegevens. Deze actie kan niet ongedaan worden gemaakt." 2062 2020 2063 msgid "We strongly recommend creating a database backup before changing your domain." 2021 2064 msgstr "We raden sterk aan om een databaseback-up te maken voordat u uw domein wijzigt." -
blaminhor-essentials/trunk/languages/blaminhor-essentials-pt_BR.po
r3450351 r3451104 21 21 msgstr "%1$d de %2$d tipos de e-mail silenciados." 22 22 23 #. translators: %d: number of backup archives extracted from the bundle 24 msgid "%d archives extracted" 25 msgstr "%d arquivos extraídos" 26 23 27 msgid "%d redirections imported." 24 28 msgstr "%d redirecionamentos importados." … … 92 96 msgstr "Um nome amigavel para identificar este relay." 93 97 98 msgid "A full backup of your current site will be created automatically before restoring." 99 msgstr "Um backup completo do seu site atual será criado automaticamente antes da restauração." 100 94 101 msgid "A PHP extension stopped the file upload." 95 102 msgstr "Uma extensao PHP interrompeu o upload do arquivo." … … 314 321 msgstr "Alterar Dominio" 315 322 323 msgid "Change domain automatically after restore" 324 msgstr "Alterar o domínio automaticamente após a restauração" 325 316 326 msgid "Change Domain Now" 317 327 msgstr "Alterar Dominio Agora" … … 515 525 msgstr "Descricao" 516 526 527 msgid "Different domain detected" 528 msgstr "Domínio diferente detectado" 529 517 530 msgid "Disable" 518 531 msgstr "Desativar" … … 773 786 msgstr "Falha ao criar backup." 774 787 788 msgid "Failed to create bundle archive." 789 msgstr "Falha ao criar arquivo do pacote." 790 791 msgid "Failed to read the bundle archive." 792 msgstr "Falha ao ler o arquivo do pacote." 793 775 794 msgid "Failed to delete redirection." 776 795 msgstr "Falha ao excluir redirecionamento." … … 962 981 msgstr "Inicializando..." 963 982 983 msgid "Invalid backup prefix." 984 msgstr "Prefixo de backup invalido." 985 964 986 msgid "Invalid data." 965 987 msgstr "Dados invalidos." … … 1136 1158 msgstr "Nenhum conteudo CSV fornecido." 1137 1159 1160 msgid "No database.sql found in the database archive." 1161 msgstr "Arquivo database.sql não encontrado no arquivo de banco de dados." 1162 1138 1163 msgid "No emails logged yet." 1139 1164 msgstr "Nenhum e-mail registrado ainda." … … 1171 1196 msgid "No type specified." 1172 1197 msgstr "Nenhum tipo especificado." 1198 1199 msgid "No valid backup archives found in the bundle." 1200 msgstr "Nenhum arquivo de backup válido encontrado no pacote." 1173 1201 1174 1202 msgid "None" … … 1357 1385 msgstr "Backup antes da atualização" 1358 1386 1387 msgid "Preparing..." 1388 msgstr "Preparando..." 1389 1359 1390 msgid "Preview" 1360 1391 msgstr "Visualizar" … … 1765 1796 msgstr "Obrigado pelo seu feedback!" 1766 1797 1798 msgid "The archive does not contain any recognizable backup data." 1799 msgstr "O arquivo não contém dados de backup reconhecíveis." 1800 1767 1801 msgid "The authenticated sender email for this relay." 1768 1802 msgstr "O e-mail do remetente autenticado para este relay." … … 1774 1808 msgstr "O editor de blocos está atualmente desativado." 1775 1809 1810 msgid "The database backup file is empty or contains no valid SQL statements." 1811 msgstr "O arquivo de backup do banco de dados está vazio ou não contém instruções SQL válidas." 1812 1813 msgid "The following file(s) exceed the server upload limit" 1814 msgstr "Os seguintes arquivos excedem o limite de envio do servidor" 1815 1776 1816 msgid "The new domain is the same as the current domain." 1777 1817 msgstr "O novo dominio e o mesmo que o dominio atual." … … 1957 1997 msgstr "Aviso: Uma vez que o HSTS e armazenado em cache pelos navegadores, seu site deve permanecer em HTTPS. Desativar esta configuracao nao desfara imediatamente o cache do navegador." 1958 1998 1999 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 2000 msgstr "Aviso: a restauração de um backup substituirá seus dados atuais. Esta ação não pode ser desfeita." 2001 1959 2002 msgid "We strongly recommend creating a database backup before changing your domain." 1960 2003 msgstr "Recomendamos fortemente criar um backup do banco de dados antes de alterar seu dominio." -
blaminhor-essentials/trunk/languages/blaminhor-essentials-pt_PT.po
r3450351 r3451104 18 18 msgstr " - cópia" 19 19 20 #. translators: %d: number of backup archives extracted from the bundle 21 msgid "%d archives extracted" 22 msgstr "%d arquivos extraídos" 23 20 24 #. translators: %d: number of selected items 21 25 msgid "%d selected" … … 44 48 msgstr "Um nome amigável para identificar este relay." 45 49 50 msgid "A full backup of your current site will be created automatically before restoring." 51 msgstr "Uma cópia de segurança completa do seu site atual será criada automaticamente antes da restauração." 52 46 53 msgid "A PHP extension stopped the file upload." 47 54 msgstr "Uma extensão PHP parou o carregamento do ficheiro." … … 203 210 msgstr "Arquivos de categorias e etiquetas" 204 211 212 msgid "Change domain automatically after restore" 213 msgstr "Alterar o domínio automaticamente após a restauração" 214 205 215 msgid "Change this setting" 206 216 msgstr "Alterar esta definição" … … 323 333 msgstr "Descrição" 324 334 335 msgid "Different domain detected" 336 msgstr "Domínio diferente detetado" 337 325 338 msgid "Disable HTTPS Redirect" 326 339 msgstr "Desativar redirecionamento HTTPS" … … 449 462 msgstr "Falha ao criar cópia de segurança." 450 463 464 msgid "Failed to create bundle archive." 465 msgstr "Falha ao criar o arquivo do pacote." 466 467 msgid "Failed to read the bundle archive." 468 msgstr "Falha ao ler o arquivo do pacote." 469 451 470 msgid "Failed to save the uploaded file." 452 471 msgstr "Falha ao guardar o ficheiro carregado." … … 557 576 msgstr "A inicializar..." 558 577 578 msgid "Invalid backup prefix." 579 msgstr "Prefixo de cópia de segurança inválido." 580 559 581 msgid "Invalid email address." 560 582 msgstr "Endereço de email inválido." … … 662 684 msgstr "Nenhuma cópia de segurança selecionada." 663 685 686 msgid "No database.sql found in the database archive." 687 msgstr "Ficheiro database.sql não encontrado no arquivo da base de dados." 688 664 689 msgid "No file uploaded." 665 690 msgstr "Nenhum ficheiro carregado." … … 688 713 msgid "No type specified." 689 714 msgstr "Nenhum tipo especificado." 715 716 msgid "No valid backup archives found in the bundle." 717 msgstr "Nenhum arquivo de backup válido encontrado no pacote." 690 718 691 719 msgid "None" … … 799 827 msgstr "Cópia de segurança antes da atualização" 800 828 829 msgid "Preparing..." 830 msgstr "A preparar..." 831 801 832 msgid "Preview" 802 833 msgstr "Pré-visualizar" … … 1039 1070 msgstr "Obrigado pelo seu feedback!" 1040 1071 1072 msgid "The archive does not contain any recognizable backup data." 1073 msgstr "O arquivo não contém dados de cópia de segurança reconhecíveis." 1074 1041 1075 msgid "The Block Editor is currently disabled." 1042 1076 msgstr "O editor de blocos está atualmente desativado." 1043 1077 1078 msgid "The database backup file is empty or contains no valid SQL statements." 1079 msgstr "O ficheiro de cópia de segurança da base de dados está vazio ou não contém instruções SQL válidas." 1080 1081 msgid "The following file(s) exceed the server upload limit" 1082 msgstr "Os seguintes ficheiros excedem o limite de envio do servidor" 1083 1044 1084 msgid "The uploaded file exceeds the MAX_FILE_SIZE directive." 1045 1085 msgstr "O ficheiro carregado excede a diretiva MAX_FILE_SIZE." … … 1144 1184 msgstr "Aviso" 1145 1185 1186 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 1187 msgstr "Aviso: a restauração de uma cópia de segurança irá substituir os seus dados atuais. Esta ação não pode ser revertida." 1188 1146 1189 msgid "Weekly" 1147 1190 msgstr "Semanal" -
blaminhor-essentials/trunk/languages/blaminhor-essentials-ru_RU.po
r3450351 r3451104 27 27 msgstr "%1$s: удалено миниатюр: %2$d" 28 28 29 #. translators: %d: number of backup archives extracted from the bundle 30 msgid "%d archives extracted" 31 msgstr "%d архивов извлечено" 32 29 33 msgid "%d Broken Link" 30 34 msgstr "%d битая ссылка" … … 506 510 msgstr "Сменить домен после восстановления" 507 511 512 msgid "Change domain automatically after restore" 513 msgstr "Автоматически изменить домен после восстановления" 514 508 515 msgid "Change Domain Now" 509 516 msgstr "Сменить домен сейчас" … … 884 891 msgstr "Разработчиков, API-интеграция" 885 892 893 msgid "Different domain detected" 894 msgstr "Обнаружен другой домен" 895 886 896 msgid "Dimensions" 887 897 msgstr "Размеры" … … 1193 1203 msgstr "Не удалось создать архив резервной копии." 1194 1204 1205 msgid "Failed to create bundle archive." 1206 msgstr "Не удалось создать архив-пакет." 1207 1195 1208 msgid "Failed to create pre-restore backup." 1196 1209 msgstr "Не удалось создать резервную копию перед восстановлением." … … 1205 1218 msgstr "Не удалось открыть архив резервной копии." 1206 1219 1220 msgid "Failed to read the bundle archive." 1221 msgstr "Не удалось прочитать архив пакета." 1222 1207 1223 msgid "Failed to regenerate thumbnails." 1208 1224 msgstr "Не удалось перегенерировать миниатюры." … … 1511 1527 msgstr "Недействительные параметры резервного копирования." 1512 1528 1529 msgid "Invalid backup prefix." 1530 msgstr "Недействительный префикс резервной копии." 1531 1513 1532 msgid "Invalid data." 1514 1533 msgstr "Недействительные данные." … … 1781 1800 msgstr "Таблицы базы данных не найдены." 1782 1801 1802 msgid "No database.sql found in the database archive." 1803 msgstr "Файл database.sql не найден в архиве базы данных." 1804 1783 1805 msgid "No emails logged yet." 1784 1806 msgstr "Письма ещё не записаны." … … 1825 1847 msgid "No type specified." 1826 1848 msgstr "Тип не указан." 1849 1850 msgid "No valid backup archives found in the bundle." 1851 msgstr "В пакете не найдено допустимых архивов резервного копирования." 1827 1852 1828 1853 msgid "None" … … 2788 2813 msgstr "Модуль %s активен. Сохраните URL восстановления перед включением HTTPS-перенаправления." 2789 2814 2815 msgid "The archive does not contain any recognizable backup data." 2816 msgstr "Архив не содержит распознаваемых данных резервной копии." 2817 2790 2818 msgid "The authenticated sender email for this relay." 2791 2819 msgstr "Авторизованный email отправителя для этого ретранслятора." … … 2797 2825 msgstr "Блочный редактор в настоящее время отключен." 2798 2826 2827 msgid "The database backup file is empty or contains no valid SQL statements." 2828 msgstr "Файл резервной копии базы данных пуст или не содержит допустимых SQL-запросов." 2829 2830 msgid "The following file(s) exceed the server upload limit" 2831 msgstr "Следующие файлы превышают лимит загрузки сервера" 2832 2799 2833 msgid "The new domain is the same as the current domain." 2800 2834 msgstr "Новый домен совпадает с текущим доменом." -
blaminhor-essentials/trunk/languages/blaminhor-essentials-tr_TR.po
r3450351 r3451104 21 21 msgstr "%2$d e-posta turunden %1$d tanesi sessize alindi." 22 22 23 #. translators: %d: number of backup archives extracted from the bundle 24 msgid "%d archives extracted" 25 msgstr "%d arşiv çıkarıldı" 26 23 27 msgid "%d redirections imported." 24 28 msgstr "%d yonlendirme ice aktarildi." … … 83 87 msgstr "Bu aktariciyi tanimlamak icin kolay bir ad." 84 88 89 msgid "A full backup of your current site will be created automatically before restoring." 90 msgstr "Geri yüklemeden önce mevcut sitenizin tam bir yedeği otomatik olarak oluşturulacaktır." 91 85 92 msgid "About" 86 93 msgstr "Hakkinda" … … 297 304 msgstr "Alan Adi Degistir" 298 305 306 msgid "Change domain automatically after restore" 307 msgstr "Geri yüklemeden sonra alan adını otomatik olarak değiştir" 308 299 309 msgid "Change Domain Now" 300 310 msgstr "Alan Adini Simdi Degistir" … … 495 505 msgstr "Tumunun Secimini Kaldir" 496 506 507 msgid "Different domain detected" 508 msgstr "Farklı alan adı algılandı" 509 497 510 msgid "Disable" 498 511 msgstr "Devre Disi Birak" … … 732 745 msgstr "Yonlendirme eklenemedi." 733 746 747 msgid "Failed to create bundle archive." 748 msgstr "Paket arsivi olusturulamadi." 749 750 msgid "Failed to read the bundle archive." 751 msgstr "Paket arşivi okunamadı." 752 734 753 msgid "Failed to delete redirection." 735 754 msgstr "Yonlendirme silinemedi." … … 900 919 msgstr "Bilgi" 901 920 921 msgid "Invalid backup prefix." 922 msgstr "Gecersiz yedek oneki." 923 902 924 msgid "Invalid data." 903 925 msgstr "Gecersiz veri." … … 1092 1114 msgstr "CSV icerigi saglanmadi." 1093 1115 1116 msgid "No database.sql found in the database archive." 1117 msgstr "Veritabanı arşivinde database.sql bulunamadı." 1118 1094 1119 msgid "No emails logged yet." 1095 1120 msgstr "Henuz kayitli e-posta yok." … … 1118 1143 msgid "No type specified." 1119 1144 msgstr "Tür belirtilmedi." 1145 1146 msgid "No valid backup archives found in the bundle." 1147 msgstr "Pakette geçerli yedekleme arşivi bulunamadı." 1120 1148 1121 1149 msgid "Nobody" … … 1286 1314 msgstr "Güncelleme Öncesi Yedekleme" 1287 1315 1316 msgid "Preparing..." 1317 msgstr "Hazirlaniyor..." 1318 1288 1319 msgid "Preview" 1289 1320 msgstr "Onizleme" … … 1667 1698 msgstr "Geri bildiriminiz icin tesekkurler!" 1668 1699 1700 msgid "The archive does not contain any recognizable backup data." 1701 msgstr "Arşiv tanınabilir yedekleme verisi içermiyor." 1702 1669 1703 msgid "The authenticated sender email for this relay." 1670 1704 msgstr "Bu aktarici icin kimlik dogrulanmis gonderen e-postasi." … … 1676 1710 msgstr "Blok Düzenleyici şu anda devre dışı." 1677 1711 1712 msgid "The database backup file is empty or contains no valid SQL statements." 1713 msgstr "Veritabanı yedekleme dosyası boş veya geçerli SQL ifadeleri içermiyor." 1714 1715 msgid "The following file(s) exceed the server upload limit" 1716 msgstr "Aşağıdaki dosyalar sunucu yükleme sınırını aşıyor" 1717 1678 1718 msgid "The new domain is the same as the current domain." 1679 1719 msgstr "Yeni alan adi mevcut alan adiyla ayni." … … 1817 1857 msgstr "Uyari: HSTS tarayicilar tarafindan onbellege alindiktan sonra siteniz HTTPS'de kalmalidir. Bu ayari devre disi birakmak tarayici onbellegini hemen geri almaz." 1818 1858 1859 msgid "Warning: Restoring a backup will overwrite your current data. This action cannot be undone." 1860 msgstr "Uyarı: bir yedeği geri yüklemek mevcut verilerinizin üzerine yazacaktır. Bu işlem geri alınamaz." 1861 1819 1862 msgid "We strongly recommend creating a database backup before changing your domain." 1820 1863 msgstr "Alan adinizi degistirmeden once bir veritabani yedegi olusturmanizi siddetle oneririz." -
blaminhor-essentials/trunk/modules/backup/class-module-backup.php
r3450705 r3451104 86 86 add_action( 'wp_ajax_ap_backup_delete', array( $this, 'ajax_delete_backup' ) ); 87 87 add_action( 'wp_ajax_ap_backup_download', array( $this, 'ajax_download_backup' ) ); 88 add_action( 'wp_ajax_ap_backup_download_bundle', array( $this, 'ajax_download_bundle' ) ); 88 89 add_action( 'wp_ajax_ap_backup_restore', array( $this, 'ajax_restore_backup' ) ); 89 90 add_action( 'wp_ajax_ap_backup_undo_restore', array( $this, 'ajax_undo_restore' ) ); … … 121 122 122 123 $config = array( 123 'nonce' => wp_create_nonce( 'blaminhor_essentials_admin' ), 124 'ajaxurl' => admin_url( 'admin-ajax.php' ), 125 'strings' => array( 124 'nonce' => wp_create_nonce( 'blaminhor_essentials_admin' ), 125 'ajaxurl' => admin_url( 'admin-ajax.php' ), 126 'maxUploadSize' => wp_max_upload_size(), 127 'maxUploadLabel' => size_format( wp_max_upload_size() ), 128 'strings' => array( 126 129 'error' => __( 'An error occurred. Please try again.', 'blaminhor-essentials' ), 127 130 'confirmDelete' => __( 'Are you sure you want to delete this backup?', 'blaminhor-essentials' ), … … 142 145 'uploadSuccess' => __( 'Backup uploaded successfully!', 'blaminhor-essentials' ), 143 146 'uploading' => __( 'Uploading', 'blaminhor-essentials' ), 147 'preparing' => __( 'Preparing...', 'blaminhor-essentials' ), 144 148 'backupsUploaded' => __( 'backups uploaded successfully!', 'blaminhor-essentials' ), 145 149 'uploadsFailed' => __( 'file(s) failed to upload.', 'blaminhor-essentials' ), 150 'fileTooLarge' => __( 'The following file(s) exceed the server upload limit', 'blaminhor-essentials' ), 146 151 ), 147 152 ); … … 616 621 617 622 // Known components. 618 $components = array( 'database', 'plugins', 'themes', 'uploads', 'wp-content', 'wp-core', 'full', 'files', 'custom', 'pre-restore', 'uploaded', 'scheduled' );623 $components = array( 'database', 'plugins', 'themes', 'uploads', 'wp-content', 'wp-core', 'full', 'files', 'custom', 'pre-restore', 'uploaded', 'scheduled', 'bundle' ); 619 624 620 625 $component = 'unknown'; … … 972 977 return 'NULL'; 973 978 } 974 return "'" . $wpdb-> _real_escape( $value) . "'";979 return "'" . $wpdb->remove_placeholder_escape( esc_sql( $value ) ) . "'"; 975 980 }, $row ); 976 981 $values[] = '(' . implode( ', ', $row_values ) . ')'; … … 1259 1264 } 1260 1265 1266 // Detect bundle: a ZIP containing multiple .zip files. 1267 $is_bundle = false; 1268 $zip_entries = array(); 1269 $num_entries = $zip->numFiles; 1270 1271 for ( $i = 0; $i < $num_entries; $i++ ) { 1272 $entry_name = $zip->getNameIndex( $i ); 1273 if ( false === $entry_name ) { 1274 continue; 1275 } 1276 // Skip directory entries. 1277 if ( substr( $entry_name, -1 ) === '/' ) { 1278 continue; 1279 } 1280 if ( strtolower( pathinfo( $entry_name, PATHINFO_EXTENSION ) ) === 'zip' ) { 1281 $zip_entries[] = $entry_name; 1282 } 1283 } 1284 1285 if ( count( $zip_entries ) > 1 ) { 1286 $is_bundle = true; 1287 } 1288 1261 1289 // Check for manifest or database file to validate it's a backup. 1262 1290 $has_manifest = ( $zip->locateName( 'manifest.json' ) !== false ); … … 1270 1298 } 1271 1299 1272 if ( ! $has_manifest && ! $has_database && ! $is_component_backup ) {1300 if ( ! $has_manifest && ! $has_database && ! $is_component_backup && ! $is_bundle ) { 1273 1301 $zip->close(); 1274 1302 wp_send_json_error( __( 'This does not appear to be a valid backup file. It must contain a manifest.json or database.sql file.', 'blaminhor-essentials' ) ); … … 1292 1320 $zip->close(); 1293 1321 1294 // Generate a new filename with current site name and timestamp.1322 // Prepare site name and timestamp for destination filenames. 1295 1323 $site_name = sanitize_title( get_bloginfo( 'name' ) ); 1296 1324 if ( empty( $site_name ) ) { 1297 1325 $site_name = 'backup'; 1298 1326 } 1299 $timestamp = current_time( 'Y-m-d-H-i-s' ); 1300 $new_filename = $site_name . '-' . $timestamp . '-uploaded.zip'; 1301 1302 // Move file to backup directory using WordPress Filesystem API. 1303 $destination = $this->backup_dir . '/' . $new_filename; 1327 $timestamp = current_time( 'Y-m-d-H-i-s' ); 1304 1328 1305 1329 global $wp_filesystem; … … 1307 1331 require_once ABSPATH . 'wp-admin/includes/file.php'; 1308 1332 WP_Filesystem(); 1333 } 1334 1335 if ( $is_bundle ) { 1336 // Bundle: extract sub-archives to disk (avoids loading large files into memory). 1337 $extracted_files = array(); 1338 $extract_zip = new ZipArchive(); 1339 1340 if ( $extract_zip->open( $file['tmp_name'] ) !== true ) { 1341 wp_send_json_error( __( 'Failed to read the bundle archive.', 'blaminhor-essentials' ) ); 1342 } 1343 1344 // Create a temporary directory for extraction. 1345 $temp_dir = $this->backup_dir . '/tmp-upload-' . wp_generate_password( 8, false ); 1346 wp_mkdir_p( $temp_dir ); 1347 1348 // Collect entries to extract. 1349 $entries_to_process = array(); 1350 for ( $i = 0; $i < $extract_zip->numFiles; $i++ ) { 1351 $entry_name = $extract_zip->getNameIndex( $i ); 1352 if ( false === $entry_name || substr( $entry_name, -1 ) === '/' ) { 1353 continue; 1354 } 1355 if ( strtolower( pathinfo( $entry_name, PATHINFO_EXTENSION ) ) !== 'zip' ) { 1356 continue; 1357 } 1358 $entries_to_process[] = $entry_name; 1359 } 1360 1361 // Extract all sub-archives to temp directory (streams to disk, no memory issue). 1362 if ( ! $extract_zip->extractTo( $temp_dir, $entries_to_process ) ) { 1363 $extract_zip->close(); 1364 $wp_filesystem->rmdir( $temp_dir, true ); 1365 wp_send_json_error( __( 'Failed to save the uploaded file.', 'blaminhor-essentials' ) ); 1366 } 1367 1368 $extract_zip->close(); 1369 1370 // Rename each extracted file to the proper destination. 1371 foreach ( $entries_to_process as $entry_name ) { 1372 $extracted_path = $temp_dir . '/' . basename( $entry_name ); 1373 if ( ! file_exists( $extracted_path ) ) { 1374 continue; 1375 } 1376 1377 // Determine the component from the sub-archive filename. 1378 $entry_base = sanitize_file_name( pathinfo( $entry_name, PATHINFO_FILENAME ) ); 1379 $entry_info = $this->parse_backup_filename( $entry_base . '.zip' ); 1380 $component = $entry_info['component']; 1381 1382 // If parse_backup_filename didn't recognize the component, 1383 // check if the filename itself IS a known component name (e.g. "database.zip"). 1384 if ( 'unknown' === $component || 'bundle' === $component ) { 1385 $known_components = array( 'database', 'plugins', 'themes', 'uploads', 'wp-content', 'wp-core' ); 1386 if ( in_array( $entry_base, $known_components, true ) ) { 1387 $component = $entry_base; 1388 } else { 1389 $component = 'uploaded'; 1390 } 1391 } 1392 1393 $new_filename = $site_name . '-' . $timestamp . '-' . $component . '.zip'; 1394 $destination = $this->backup_dir . '/' . $new_filename; 1395 1396 // Avoid collisions. 1397 $counter = 2; 1398 while ( file_exists( $destination ) ) { 1399 $new_filename = $site_name . '-' . $timestamp . '-' . $component . '-' . $counter . '.zip'; 1400 $destination = $this->backup_dir . '/' . $new_filename; 1401 $counter++; 1402 } 1403 1404 if ( ! $wp_filesystem->move( $extracted_path, $destination ) ) { 1405 // Fallback: try copy + delete if rename fails (cross-device move). 1406 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- File operations may fail silently. 1407 $content = @file_get_contents( $extracted_path ); 1408 if ( false === $content || ! $wp_filesystem->put_contents( $destination, $content, FS_CHMOD_FILE ) ) { 1409 // Clean up on failure. 1410 foreach ( $extracted_files as $extracted ) { 1411 $wp_filesystem->delete( $this->backup_dir . '/' . $extracted ); 1412 } 1413 $wp_filesystem->rmdir( $temp_dir, true ); 1414 wp_send_json_error( __( 'Failed to save the uploaded file.', 'blaminhor-essentials' ) ); 1415 } 1416 } 1417 1418 $extracted_files[] = $new_filename; 1419 } 1420 1421 // Clean up temp directory. 1422 $wp_filesystem->rmdir( $temp_dir, true ); 1423 1424 // Clean up temp file. 1425 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.unlink_unlink -- Cleaning up PHP temp file. 1426 @unlink( $file['tmp_name'] ); 1427 1428 if ( empty( $extracted_files ) ) { 1429 wp_send_json_error( __( 'No valid backup archives found in the bundle.', 'blaminhor-essentials' ) ); 1430 } 1431 1432 // Get current domain for comparison. 1433 $current_url = home_url(); 1434 $parsed_current = wp_parse_url( $current_url ); 1435 $current_domain = isset( $parsed_current['host'] ) ? $parsed_current['host'] : ''; 1436 1437 $domain_differs = ! empty( $backup_domain ) && $backup_domain !== $current_domain; 1438 1439 wp_send_json_success( 1440 array( 1441 'is_bundle' => true, 1442 'files' => $extracted_files, 1443 'file_count' => count( $extracted_files ), 1444 /* translators: %d: number of backup archives extracted from the bundle */ 1445 'filename' => sprintf( __( '%d archives extracted', 'blaminhor-essentials' ), count( $extracted_files ) ), 1446 'domain_differs' => $domain_differs, 1447 'backup_domain' => $backup_domain, 1448 'backup_url' => $backup_url, 1449 'current_domain' => $current_domain, 1450 'current_url' => $current_url, 1451 ) 1452 ); 1453 } 1454 1455 // Single file upload: preserve component suffix from original filename. 1456 $original_info = $this->parse_backup_filename( $original_name . '.zip' ); 1457 $component = $original_info['component']; 1458 1459 // Use original component if recognized, otherwise default to 'uploaded'. 1460 $valid_components = array( 'database', 'plugins', 'themes', 'uploads', 'wp-content', 'wp-core', 'full', 'files' ); 1461 if ( ! in_array( $component, $valid_components, true ) ) { 1462 $component = 'uploaded'; 1463 } 1464 1465 $new_filename = $site_name . '-' . $timestamp . '-' . $component . '.zip'; 1466 $destination = $this->backup_dir . '/' . $new_filename; 1467 1468 // Avoid collisions. 1469 $counter = 2; 1470 while ( file_exists( $destination ) ) { 1471 $new_filename = $site_name . '-' . $timestamp . '-' . $component . '-' . $counter . '.zip'; 1472 $destination = $this->backup_dir . '/' . $new_filename; 1473 $counter++; 1309 1474 } 1310 1475 … … 1351 1516 1352 1517 $filename = isset( $_POST['filename'] ) ? sanitize_file_name( wp_unslash( $_POST['filename'] ) ) : ''; 1518 $prefix = isset( $_POST['prefix'] ) ? sanitize_file_name( wp_unslash( $_POST['prefix'] ) ) : ''; 1519 1520 // If prefix is provided, find the first matching archive. 1521 if ( ! empty( $prefix ) && empty( $filename ) ) { 1522 $archives = glob( $this->backup_dir . '/' . $prefix . '-*.zip' ); 1523 if ( ! empty( $archives ) ) { 1524 $filename = basename( $archives[0] ); 1525 } 1526 } 1527 1353 1528 if ( empty( $filename ) ) { 1354 1529 wp_send_json_error( __( 'No filename provided.', 'blaminhor-essentials' ) ); … … 1495 1670 } 1496 1671 1672 $restored_components = array(); 1673 1497 1674 // Restore each archive based on its component type. 1498 1675 foreach ( $archives as $archive_path ) { … … 1518 1695 return $result; 1519 1696 } 1520 } 1521 1522 return true; 1697 1698 $restored_components[] = $component; 1699 1700 // Collect database stats if available. 1701 if ( is_array( $result ) && isset( $result['executed'] ) ) { 1702 $db_stats = $result; 1703 } 1704 } 1705 1706 // Verify that the database was actually restored when requested. 1707 if ( $options['database'] && ! in_array( 'database', $restored_components, true ) ) { 1708 return new WP_Error( 1709 'database_not_restored', 1710 sprintf( 1711 /* translators: %s: comma-separated list of component names found in the backup */ 1712 __( 'Database restoration was requested but no database archive was found. Components found: %s', 'blaminhor-essentials' ), 1713 implode( ', ', $restored_components ) 1714 ) 1715 ); 1716 } 1717 1718 return array( 1719 'components' => $restored_components, 1720 'db_stats' => isset( $db_stats ) ? $db_stats : null, 1721 ); 1523 1722 } 1524 1723 … … 1539 1738 // Restore database. 1540 1739 $sql_content = $zip->getFromName( 'database.sql' ); 1541 if ( $sql_content ) { 1542 $result = $this->import_database( $sql_content ); 1543 if ( is_wp_error( $result ) ) { 1544 $zip->close(); 1545 return $result; 1546 } 1547 } 1740 if ( false === $sql_content ) { 1741 $zip->close(); 1742 return new WP_Error( 'no_sql', __( 'No database.sql found in the database archive.', 'blaminhor-essentials' ) ); 1743 } 1744 $db_result = $this->import_database( $sql_content ); 1745 if ( is_wp_error( $db_result ) ) { 1746 $zip->close(); 1747 return $db_result; 1748 } 1749 $zip->close(); 1750 return $db_result; // Return array with executed/failed stats. 1548 1751 } else { 1549 1752 // Restore files. … … 1566 1769 list( $source, $dest ) = $destinations[ $component ]; 1567 1770 if ( is_dir( $source ) ) { 1771 // Clear destination before restoring to replace contents, not merge. 1772 if ( in_array( $component, array( 'plugins', 'themes', 'uploads' ), true ) ) { 1773 $this->clear_directory_contents( $dest ); 1774 } 1568 1775 $this->copy_directory( $source, $dest ); 1569 1776 } … … 1573 1780 $dirs = glob( $temp_dir . '/*', GLOB_ONLYDIR ); 1574 1781 foreach ( $dirs as $dir ) { 1575 $this->copy_directory( $dir, $dest . '/' . basename( $dir ) ); 1782 $target = $dest . '/' . basename( $dir ); 1783 // Clear the specific plugin/theme folder before restoring. 1784 if ( is_dir( $target ) ) { 1785 $this->delete_directory( $target ); 1786 } 1787 $this->copy_directory( $dir, $target ); 1576 1788 } 1577 1789 } … … 1593 1805 private function import_database( $sql_content ) { 1594 1806 global $wpdb; 1807 1808 // Clean up wpdb placeholder escape hashes left by _real_escape() in older backups. 1809 // Pattern: {64-char hex SHA-256 hash} that replaced % characters during export. 1810 $sql_content = preg_replace( '/\{[a-f0-9]{64}\}/', '%', $sql_content ); 1811 1812 // Detect source table prefix and replace with current prefix if different. 1813 $source_prefix = ''; 1814 if ( preg_match( '/DROP TABLE IF EXISTS `([a-zA-Z0-9_]+?)options`/', $sql_content, $matches ) ) { 1815 $source_prefix = $matches[1]; 1816 } 1817 1818 if ( ! empty( $source_prefix ) && $source_prefix !== $wpdb->prefix ) { 1819 $escaped_prefix = preg_quote( $source_prefix, '/' ); 1820 // Only replace prefix in SQL identifiers (backtick-quoted table/column names). 1821 $sql_content = preg_replace( 1822 '/`' . $escaped_prefix . '([a-zA-Z0-9_]+)`/', 1823 '`' . $wpdb->prefix . '$1`', 1824 $sql_content 1825 ); 1826 } 1595 1827 1596 1828 // Split into statements. … … 1614 1846 } 1615 1847 1848 if ( empty( $statements ) ) { 1849 return new WP_Error( 'empty_sql', __( 'The database backup file is empty or contains no valid SQL statements.', 'blaminhor-essentials' ) ); 1850 } 1851 1616 1852 // Execute statements. 1853 $executed = 0; 1854 $failed = 0; 1855 $last_error = ''; 1856 1617 1857 foreach ( $statements as $statement ) { 1618 1858 if ( empty( trim( $statement ) ) ) { … … 1626 1866 1627 1867 if ( false === $result ) { 1628 // Log error but continue (only in debug mode). 1629 if ( defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { 1630 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Only logs in debug mode 1631 error_log( 'Blaminhor Essentials Backup: SQL Error - ' . $wpdb->last_error ); 1632 } 1633 } 1634 } 1635 1636 return true; 1868 $failed++; 1869 $last_error = $wpdb->last_error; 1870 } else { 1871 $executed++; 1872 } 1873 } 1874 1875 // Fix prefix-dependent meta keys and options after prefix replacement. 1876 if ( ! empty( $source_prefix ) && $source_prefix !== $wpdb->prefix ) { 1877 $old_prefix_like = $wpdb->esc_like( $source_prefix ) . '%'; 1878 $old_prefix_len = strlen( $source_prefix ); 1879 1880 // Update all usermeta keys that start with the old prefix. 1881 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Fixing prefix-dependent meta keys after restore 1882 $wpdb->query( 1883 $wpdb->prepare( 1884 "UPDATE `{$wpdb->usermeta}` SET `meta_key` = CONCAT(%s, SUBSTRING(`meta_key`, %d)) WHERE `meta_key` LIKE %s", 1885 $wpdb->prefix, 1886 $old_prefix_len + 1, 1887 $old_prefix_like 1888 ) 1889 ); 1890 1891 // Fix user_roles option: delete any existing one first to avoid duplicate key error. 1892 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Fixing prefix-dependent option after restore 1893 $wpdb->query( 1894 $wpdb->prepare( 1895 "DELETE FROM `{$wpdb->options}` WHERE `option_name` = %s", 1896 $wpdb->prefix . 'user_roles' 1897 ) 1898 ); 1899 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Fixing prefix-dependent option after restore 1900 $wpdb->query( 1901 $wpdb->prepare( 1902 "UPDATE `{$wpdb->options}` SET `option_name` = %s WHERE `option_name` = %s", 1903 $wpdb->prefix . 'user_roles', 1904 $source_prefix . 'user_roles' 1905 ) 1906 ); 1907 } 1908 1909 if ( 0 === $executed ) { 1910 return new WP_Error( 1911 'sql_all_failed', 1912 sprintf( 1913 /* translators: 1: number of failed statements, 2: last SQL error message */ 1914 __( 'Database import failed: %1$d statements failed. Last error: %2$s', 'blaminhor-essentials' ), 1915 $failed, 1916 $last_error 1917 ) 1918 ); 1919 } 1920 1921 return array( 1922 'executed' => $executed, 1923 'failed' => $failed, 1924 ); 1925 } 1926 1927 /** 1928 * Clear directory contents without removing the directory itself 1929 * 1930 * @param string $dir Directory path. 1931 */ 1932 private function clear_directory_contents( $dir ) { 1933 if ( ! is_dir( $dir ) ) { 1934 return; 1935 } 1936 1937 $files = array_diff( scandir( $dir ), array( '.', '..' ) ); 1938 foreach ( $files as $file ) { 1939 $path = $dir . '/' . $file; 1940 if ( is_dir( $path ) ) { 1941 $this->delete_directory( $path ); 1942 } else { 1943 unlink( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink 1944 } 1945 } 1637 1946 } 1638 1947 … … 1968 2277 <tbody> 1969 2278 <?php foreach ( $backups as $backup ) : ?> 1970 <tr data-prefix="<?php echo esc_attr( $backup['prefix'] ); ?>" data-type="<?php echo esc_attr( $backup['type'] ); ?>" data-size="<?php echo esc_attr( $backup['total_size'] ); ?>" data-date="<?php echo esc_attr( $backup['date'] ); ?>" data-archives="<?php echo esc_attr( wp_json_encode( wp_list_pluck( $backup['archives'], 'filename' ) ) ); ?>">2279 <tr data-prefix="<?php echo esc_attr( $backup['prefix'] ); ?>" data-type="<?php echo esc_attr( $backup['type'] ); ?>" data-size="<?php echo esc_attr( $backup['total_size'] ); ?>" data-date="<?php echo esc_attr( $backup['date'] ); ?>"> 1971 2280 <td> 1972 2281 <code style="font-size: 12px;"><?php echo esc_html( $backup['prefix'] ); ?></code> … … 2109 2418 2110 2419 /** 2420 * AJAX: Download backup as a single bundle ZIP 2421 * 2422 * Creates a ZIP containing all archives for a given prefix, 2423 * or returns a direct download URL if only one archive exists. 2424 */ 2425 public function ajax_download_bundle() { 2426 check_ajax_referer( 'blaminhor_essentials_admin', 'nonce' ); 2427 2428 if ( ! current_user_can( 'manage_options' ) ) { 2429 wp_send_json_error( __( 'Unauthorized', 'blaminhor-essentials' ) ); 2430 } 2431 2432 $prefix = isset( $_POST['prefix'] ) ? sanitize_file_name( wp_unslash( $_POST['prefix'] ) ) : ''; 2433 if ( empty( $prefix ) ) { 2434 wp_send_json_error( __( 'Invalid backup prefix.', 'blaminhor-essentials' ) ); 2435 } 2436 2437 $files = glob( $this->backup_dir . '/' . $prefix . '-*.zip' ); 2438 if ( empty( $files ) ) { 2439 wp_send_json_error( __( 'Backup file not found.', 'blaminhor-essentials' ) ); 2440 } 2441 2442 // Filter out any existing bundle files. 2443 $archives = array(); 2444 foreach ( $files as $file ) { 2445 if ( strpos( basename( $file ), '-bundle.zip' ) === false ) { 2446 $archives[] = $file; 2447 } 2448 } 2449 2450 if ( empty( $archives ) ) { 2451 wp_send_json_error( __( 'Backup file not found.', 'blaminhor-essentials' ) ); 2452 } 2453 2454 // Single archive: download directly without creating a bundle. 2455 if ( count( $archives ) === 1 ) { 2456 $filename = basename( $archives[0] ); 2457 wp_send_json_success( array( 2458 'url' => admin_url( 'admin.php?page=blaminhor-essentials-backup&ap_backup_action=download&file=' . rawurlencode( $filename ) . '&_wpnonce=' . wp_create_nonce( 'ap_backup_action' ) ), 2459 ) ); 2460 } 2461 2462 // Multiple archives: create a bundle ZIP. 2463 $bundle_name = $prefix . '-bundle.zip'; 2464 $bundle_path = $this->backup_dir . '/' . $bundle_name; 2465 2466 if ( file_exists( $bundle_path ) ) { 2467 wp_delete_file( $bundle_path ); 2468 } 2469 2470 $zip = new ZipArchive(); 2471 if ( true !== $zip->open( $bundle_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) { 2472 wp_send_json_error( __( 'Failed to create bundle archive.', 'blaminhor-essentials' ) ); 2473 } 2474 2475 foreach ( $archives as $archive ) { 2476 $zip->addFile( $archive, basename( $archive ) ); 2477 } 2478 $zip->close(); 2479 2480 wp_send_json_success( array( 2481 'url' => admin_url( 'admin.php?page=blaminhor-essentials-backup&ap_backup_action=download&file=' . rawurlencode( $bundle_name ) . '&_wpnonce=' . wp_create_nonce( 'ap_backup_action' ) ), 2482 ) ); 2483 } 2484 2485 /** 2111 2486 * AJAX: Restore backup 2112 2487 */ … … 2164 2539 } 2165 2540 2541 // Build success message with restore details. 2542 $message = __( 'Backup restored successfully!', 'blaminhor-essentials' ); 2543 if ( is_array( $result ) ) { 2544 $components = isset( $result['components'] ) ? $result['components'] : array(); 2545 $db_stats = isset( $result['db_stats'] ) ? $result['db_stats'] : null; 2546 2547 if ( $db_stats ) { 2548 $message .= sprintf( ' [DB: %d executed, %d failed]', $db_stats['executed'], $db_stats['failed'] ); 2549 } 2550 $message .= sprintf( ' [Components: %s]', implode( ', ', $components ) ); 2551 } 2552 2166 2553 wp_send_json_success( 2167 2554 array( 2168 'message' => __( 'Backup restored successfully!', 'blaminhor-essentials' ),2555 'message' => $message, 2169 2556 'redirect_url' => $redirect_url, 2170 2557 ) … … 2190 2577 } 2191 2578 2192 // Enable Domain Changer module if not active. 2193 $active_modules = get_option( 'blaminhor_essentials_active_modules', array() ); 2194 if ( ! in_array( 'domain-changer', $active_modules, true ) ) { 2195 $active_modules[] = 'domain-changer'; 2196 update_option( 'blaminhor_essentials_active_modules', $active_modules ); 2197 } 2198 2199 // Update WordPress site URLs first. 2200 update_option( 'siteurl', $new_url ); 2201 update_option( 'home', $new_url ); 2202 2203 // Replace in posts. 2579 // Extract domains for protocol-agnostic replacement. 2580 $old_domain = preg_replace( '#^https?://#', '', $old_url ); 2581 $new_domain = preg_replace( '#^https?://#', '', $new_url ); 2582 2583 // Flush object cache: after a raw SQL database import, the cache is stale 2584 // and update_option() would compare against cached (pre-import) values, 2585 // causing it to skip the update if cached value matches new value. 2586 wp_cache_flush(); 2587 2588 // Update siteurl and home using direct SQL to bypass cache. 2589 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2590 $wpdb->update( 2591 $wpdb->options, 2592 array( 'option_value' => $new_url ), 2593 array( 'option_name' => 'siteurl' ) 2594 ); 2595 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2596 $wpdb->update( 2597 $wpdb->options, 2598 array( 'option_value' => $new_url ), 2599 array( 'option_name' => 'home' ) 2600 ); 2601 2602 // Update other options with serialized data handling. 2603 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2604 $options = $wpdb->get_results( 2605 $wpdb->prepare( 2606 "SELECT option_id, option_value FROM {$wpdb->options} WHERE option_value LIKE %s AND option_name NOT IN ('siteurl', 'home')", 2607 '%' . $wpdb->esc_like( $old_domain ) . '%' 2608 ) 2609 ); 2610 2611 foreach ( $options as $option ) { 2612 $new_value = $this->replace_domain_in_data( $option->option_value, $old_domain, $new_domain ); 2613 if ( $new_value !== $option->option_value ) { 2614 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2615 $wpdb->update( 2616 $wpdb->options, 2617 array( 'option_value' => $new_value ), 2618 array( 'option_id' => $option->option_id ) 2619 ); 2620 } 2621 } 2622 2623 // Replace in posts (plain text, no serialized data). 2204 2624 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2205 2625 $wpdb->query( 2206 2626 $wpdb->prepare( 2207 2627 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", 2208 $old_url,2209 $new_url2628 'https://' . $old_domain, 2629 'https://' . $new_domain 2210 2630 ) 2211 2631 ); 2212 2632 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2633 $wpdb->query( 2634 $wpdb->prepare( 2635 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", 2636 'http://' . $old_domain, 2637 'http://' . $new_domain 2638 ) 2639 ); 2213 2640 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2214 2641 $wpdb->query( 2215 2642 $wpdb->prepare( 2216 2643 "UPDATE {$wpdb->posts} SET guid = REPLACE(guid, %s, %s)", 2217 $old_ url,2218 $new_ url2644 $old_domain, 2645 $new_domain 2219 2646 ) 2220 2647 ); 2221 2648 2222 // Replace in postmeta. 2649 // Update postmeta with serialized data handling. 2650 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2651 $postmeta = $wpdb->get_results( 2652 $wpdb->prepare( 2653 "SELECT meta_id, meta_value FROM {$wpdb->postmeta} WHERE meta_value LIKE %s", 2654 '%' . $wpdb->esc_like( $old_domain ) . '%' 2655 ) 2656 ); 2657 2658 foreach ( $postmeta as $meta ) { 2659 $new_value = $this->replace_domain_in_data( $meta->meta_value, $old_domain, $new_domain ); 2660 if ( $new_value !== $meta->meta_value ) { 2661 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 2662 $wpdb->update( 2663 $wpdb->postmeta, 2664 array( 'meta_value' => $new_value ), 2665 array( 'meta_id' => $meta->meta_id ) 2666 ); 2667 } 2668 } 2669 2670 // Replace in comments (plain text). 2223 2671 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2224 2672 $wpdb->query( 2225 2673 $wpdb->prepare( 2226 "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_value LIKE %s", 2227 $old_url, 2228 $new_url, 2229 '%' . $wpdb->esc_like( $old_url ) . '%' 2674 "UPDATE {$wpdb->comments} SET comment_content = REPLACE(comment_content, %s, %s)", 2675 $old_domain, 2676 $new_domain 2230 2677 ) 2231 2678 ); 2232 2233 // Replace in options (excluding siteurl and home which we already updated).2234 2679 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2235 2680 $wpdb->query( 2236 2681 $wpdb->prepare( 2237 "UPDATE {$wpdb->options} SET option_value = REPLACE(option_value, %s, %s) WHERE option_name NOT IN ('siteurl', 'home') AND option_value LIKE %s", 2238 $old_url, 2239 $new_url, 2240 '%' . $wpdb->esc_like( $old_url ) . '%' 2682 "UPDATE {$wpdb->comments} SET comment_author_url = REPLACE(comment_author_url, %s, %s)", 2683 $old_domain, 2684 $new_domain 2241 2685 ) 2242 2686 ); 2243 2687 2244 // Clear caches. 2688 // Update commentmeta with serialized data handling. 2689 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2690 $commentmeta = $wpdb->get_results( 2691 $wpdb->prepare( 2692 "SELECT meta_id, meta_value FROM {$wpdb->commentmeta} WHERE meta_value LIKE %s", 2693 '%' . $wpdb->esc_like( $old_domain ) . '%' 2694 ) 2695 ); 2696 2697 foreach ( $commentmeta as $meta ) { 2698 $new_value = $this->replace_domain_in_data( $meta->meta_value, $old_domain, $new_domain ); 2699 if ( $new_value !== $meta->meta_value ) { 2700 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 2701 $wpdb->update( 2702 $wpdb->commentmeta, 2703 array( 'meta_value' => $new_value ), 2704 array( 'meta_id' => $meta->meta_id ) 2705 ); 2706 } 2707 } 2708 2709 // Update termmeta with serialized data handling. 2710 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2711 $termmeta = $wpdb->get_results( 2712 $wpdb->prepare( 2713 "SELECT meta_id, meta_value FROM {$wpdb->termmeta} WHERE meta_value LIKE %s", 2714 '%' . $wpdb->esc_like( $old_domain ) . '%' 2715 ) 2716 ); 2717 2718 foreach ( $termmeta as $meta ) { 2719 $new_value = $this->replace_domain_in_data( $meta->meta_value, $old_domain, $new_domain ); 2720 if ( $new_value !== $meta->meta_value ) { 2721 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 2722 $wpdb->update( 2723 $wpdb->termmeta, 2724 array( 'meta_value' => $new_value ), 2725 array( 'meta_id' => $meta->meta_id ) 2726 ); 2727 } 2728 } 2729 2730 // Update usermeta with serialized data handling. 2731 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2732 $usermeta = $wpdb->get_results( 2733 $wpdb->prepare( 2734 "SELECT umeta_id, meta_value FROM {$wpdb->usermeta} WHERE meta_value LIKE %s", 2735 '%' . $wpdb->esc_like( $old_domain ) . '%' 2736 ) 2737 ); 2738 2739 foreach ( $usermeta as $meta ) { 2740 $new_value = $this->replace_domain_in_data( $meta->meta_value, $old_domain, $new_domain ); 2741 if ( $new_value !== $meta->meta_value ) { 2742 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 2743 $wpdb->update( 2744 $wpdb->usermeta, 2745 array( 'meta_value' => $new_value ), 2746 array( 'umeta_id' => $meta->umeta_id ) 2747 ); 2748 } 2749 } 2750 2751 // Replace in links (plain text). 2752 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2753 $wpdb->query( 2754 $wpdb->prepare( 2755 "UPDATE {$wpdb->links} SET link_url = REPLACE(link_url, %s, %s)", 2756 $old_domain, 2757 $new_domain 2758 ) 2759 ); 2760 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2761 $wpdb->query( 2762 $wpdb->prepare( 2763 "UPDATE {$wpdb->links} SET link_image = REPLACE(link_image, %s, %s)", 2764 $old_domain, 2765 $new_domain 2766 ) 2767 ); 2768 2769 // Flush cache after all replacements. 2245 2770 wp_cache_flush(); 2246 2771 2772 // If restoring from HTTPS to HTTP, deactivate the HTTPS Redirect module. 2773 if ( strpos( $old_url, 'https://' ) === 0 && strpos( $new_url, 'https://' ) !== 0 ) { 2774 $active_modules = get_option( 'blaminhor_essentials_active_modules', array() ); 2775 $key = array_search( 'https-redirect', $active_modules, true ); 2776 if ( false !== $key ) { 2777 unset( $active_modules[ $key ] ); 2778 update_option( 'blaminhor_essentials_active_modules', array_values( $active_modules ) ); 2779 } 2780 } 2781 2782 // Final cache flush. 2783 wp_cache_flush(); 2784 2247 2785 return true; 2786 } 2787 2788 /** 2789 * Replace domain in data, handling serialized PHP and JSON safely. 2790 * 2791 * Unserializes data before replacing, then re-serializes so that 2792 * string length prefixes remain correct (prevents data corruption). 2793 * 2794 * @param mixed $data Data to process. 2795 * @param string $old_domain Old domain (without protocol). 2796 * @param string $new_domain New domain (without protocol). 2797 * @return mixed Processed data. 2798 */ 2799 private function replace_domain_in_data( $data, $old_domain, $new_domain ) { 2800 if ( is_string( $data ) ) { 2801 // Check if it's serialized data. 2802 $unserialized = @unserialize( $data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize, WordPress.PHP.NoSilencedErrors.Discouraged 2803 if ( false !== $unserialized && is_array( $unserialized ) ) { 2804 $processed = $this->replace_domain_in_data( $unserialized, $old_domain, $new_domain ); 2805 return serialize( $processed ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize 2806 } 2807 2808 // Check if it's JSON. 2809 $json = json_decode( $data, true ); 2810 if ( json_last_error() === JSON_ERROR_NONE && is_array( $json ) ) { 2811 $processed = $this->replace_domain_in_data( $json, $old_domain, $new_domain ); 2812 return wp_json_encode( $processed ); 2813 } 2814 2815 // Plain string: replace across all protocols. 2816 $data = str_replace( 'https://' . $old_domain, 'https://' . $new_domain, $data ); 2817 $data = str_replace( 'http://' . $old_domain, 'http://' . $new_domain, $data ); 2818 $data = str_replace( '//' . $old_domain, '//' . $new_domain, $data ); 2819 2820 return $data; 2821 } 2822 2823 if ( is_array( $data ) ) { 2824 foreach ( $data as $key => $value ) { 2825 $data[ $key ] = $this->replace_domain_in_data( $value, $old_domain, $new_domain ); 2826 } 2827 return $data; 2828 } 2829 2830 return $data; 2248 2831 } 2249 2832 … … 2515 3098 <tbody> 2516 3099 <?php foreach ( $backups as $backup ) : ?> 2517 <tr data-prefix="<?php echo esc_attr( $backup['prefix'] ); ?>" data-type="<?php echo esc_attr( $backup['type'] ); ?>" data-size="<?php echo esc_attr( $backup['total_size'] ); ?>" data-date="<?php echo esc_attr( $backup['date'] ); ?>" data-archives="<?php echo esc_attr( wp_json_encode( wp_list_pluck( $backup['archives'], 'filename' ) ) ); ?>">3100 <tr data-prefix="<?php echo esc_attr( $backup['prefix'] ); ?>" data-type="<?php echo esc_attr( $backup['type'] ); ?>" data-size="<?php echo esc_attr( $backup['total_size'] ); ?>" data-date="<?php echo esc_attr( $backup['date'] ); ?>"> 2518 3101 <td style="text-align: center;"><input type="checkbox" class="ap-backup-checkbox" value="<?php echo esc_attr( $backup['prefix'] ); ?>"></td> 2519 3102 <td> -
blaminhor-essentials/trunk/modules/post-types-order/class-module-post-types-order.php
r3450526 r3451104 76 76 // Auto-sort on frontend and admin list screens. 77 77 if ( $this->get_setting( 'auto_sort', true ) ) { 78 add_ action( 'pre_get_posts', array( $this, 'auto_sort_posts' ));78 add_filter( 'posts_clauses', array( $this, 'auto_sort_posts_clauses' ), 99, 2 ); 79 79 add_filter( 'terms_clauses', array( $this, 'auto_sort_terms_clauses' ), 10, 3 ); 80 80 } … … 187 187 188 188 /** 189 * Modify main queries to sort by menu_order (frontend and admin edit.php) 190 * 191 * @param WP_Query $query The query object. 192 */ 193 public function auto_sort_posts( $query ) { 189 * Modify SQL clauses to sort by menu_order (frontend and admin edit.php) 190 * 191 * Uses posts_clauses filter at priority 99 to override the ORDER BY clause 192 * directly at the SQL level. This ensures the custom order is respected even 193 * when page builders (Elementor, JetEngine) modify the query via their own 194 * posts_clauses or posts_orderby filters at lower priorities. 195 * 196 * @param array $clauses SQL clauses (fields, join, where, groupby, orderby, distinct, limits). 197 * @param WP_Query $query The query object. 198 * @return array 199 */ 200 public function auto_sort_posts_clauses( $clauses, $query ) { 194 201 // In admin, only apply on edit.php list screens and only for the main query. 195 202 if ( is_admin() ) { 196 203 if ( ! $query->is_main_query() ) { 197 return ;204 return $clauses; 198 205 } 199 206 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; 200 207 if ( ! $screen || 'edit' !== $screen->base ) { 201 return; 208 return $clauses; 209 } 210 // In admin, don't override explicit column sorting (user clicked a column header). 211 if ( '' !== $query->get( 'orderby' ) ) { 212 return $clauses; 202 213 } 203 214 } … … 210 221 211 222 if ( is_array( $post_type ) ) { 212 return; 223 if ( 1 === count( $post_type ) ) { 224 $post_type = reset( $post_type ); 225 } else { 226 return $clauses; 227 } 213 228 } 214 229 … … 217 232 218 233 if ( ! in_array( $post_type, $enabled, true ) ) { 219 return ;220 } 221 222 // On frontend: always apply custom order for enabled post types.223 // On admin: only override if no explicit orderby was set (column click). 224 if ( ! is_admin() || '' === $query->get( 'orderby' ) ) {225 $query->set( 'orderby', 'menu_order date' );226 $query->set( 'order', 'ASC' ); 227 }234 return $clauses; 235 } 236 237 global $wpdb; 238 239 $clauses['orderby'] = "{$wpdb->posts}.menu_order ASC, {$wpdb->posts}.post_date DESC"; 240 $clauses['order'] = ''; 241 242 return $clauses; 228 243 } 229 244 -
blaminhor-essentials/trunk/readme.txt
r3450705 r3451104 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.4. 57 Stable tag: 1.4.6 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 203 203 204 204 == Changelog == 205 206 = 1.4.6 = 207 * Fixed: Post Types Order - Custom post order now applies correctly on the frontend with Elementor and other page builders. 208 * Fixed: Backup - Corrupted permalinks during SQL export caused by placeholder escaping. 209 * Fixed: Backup - Data corruption during restore when source and target table prefixes differ. 210 * Fixed: Backup - Lost admin permissions after restore with different table prefix. 211 * Fixed: Backup - HTTP/HTTPS protocol difference between source and target sites is now handled correctly during restore. 212 * Fixed: Backup - Serialized data from plugins like Elementor is now properly updated during restore (correct string length recalculation). 213 * Fixed: Backup - Restore now replaces directory contents instead of merging, preventing leftover files from previous installations. 205 214 206 215 = 1.4.5 = … … 326 335 == Upgrade Notice == 327 336 337 = 1.4.6 = 338 Backup restore fixes (prefix, permissions, permalinks, serialized data, HTTP/HTTPS). Post Types Order now works with Elementor. 339 328 340 = 1.4.5 = 329 341 Fixed Download button crash on PHP 8+ and multi-archive download support.
Note: See TracChangeset
for help on using the changeset viewer.