PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.1
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / assets / js / mainwp.js

mainwp.js in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.1, at assets/js/mainwp.js

5,610 lines 226.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* eslint-disable complexity */
2 // current complexity is the only way to achieve desired results, pull request solutions appreciated.
3
4 globalThis.mainwpVars = globalThis.mainwpVars || {};
5
6 jQuery(function ($) {
7
8 if (jQuery('.mainwp-ui-page').length) {
9 jQuery('.mainwp-popup-tooltip').popup()
10 }
11
12 jQuery(document).on('click', '#mainwp-help-menu-item, #mainwp-help-menu-item-mobile', function () {
13 jQuery('#mainwp-help-modal').modal({
14 inverted: true,
15 blurring: false,
16 closable: false,
17 onShow: function() {
18 jQuery('#mainwp-help-modal').parent('.ui.dimmer').removeClass('dimmer');
19 jQuery('#mainwp-help-modal').css({
20 'top':(jQuery(globalThis).height() - jQuery('#mainwp-help-modal').outerHeight()) / 2 + 'px',
21 'left':(jQuery(globalThis).width() - jQuery('#mainwp-help-modal').outerWidth()) / 2 + 'px'
22 });
23 },
24
25 }).modal('show').draggable().resizable({
26 handles: "n, e, s, w, ne, nw, se, sw", // Allows resizing from all edges
27 minWidth: 300, // Set minimum width
28 minHeight: 640, // Set minimum height
29 });
30 return false;
31 });
32
33 // review for new UI update
34 jQuery(document).on('click', '#mainwp-category-add-submit', function () {
35 let newCat = jQuery('#newcategory').val();
36 newCat = encodeURIComponent(newCat).replaceAll('%20', ' ');
37
38 if (jQuery('#categorychecklist .menu').find('.item[data-value="' + newCat + '"]').length > 0) {
39 jQuery('#newcategory').val('');
40 return;
41 }
42 let selected_categories = jQuery('#categorychecklist').dropdown('get value');
43 jQuery('#categorychecklist .menu').append('<div class="item" data-value="' + newCat + '">' + newCat + '</div>');
44 jQuery('#categorychecklist .menu').dropdown('set selected', selected_categories); // to refresh.
45 jQuery('#newcategory').val('');
46 });
47
48 // Show/Hide new category field and button
49 jQuery(document).on('click', '#category-add-toggle', function () {
50 jQuery('#newcategory-field').toggle();
51 jQuery('#mainwp-category-add-submit-field').toggle();
52 return false;
53 });
54
55 // Manage Child options
56 $('.mainwp-parent-toggle input[type="checkbox"]').on('change', function () {
57 if (this.checked) {
58 $(this).closest('.mainwp-parent-toggle').next('.mainwp-child-field').fadeIn();
59 } else {
60 $(this).closest('.mainwp-parent-toggle').next('.mainwp-child-field').fadeOut();
61 }
62 });
63
64 //Toggle Add Site form
65 jQuery('#mainwp_managesites_verify_installed_child').on('change', function () {
66 if (jQuery(this).is(':checked')) {
67 jQuery('#mainwp-add-site-hidden-form').fadeIn(500);
68 } else {
69 jQuery('#mainwp-add-site-hidden-form').fadeOut(500);
70 }
71 });
72
73 // Toggle Add Site / Optional Settings section
74 jQuery('#mainwp-add-site-advanced-options-toggle').on('click', function () {
75 jQuery('#mainwp-add-site-advanced-options').toggle(500);
76 return false;
77 });
78
79 jQuery('.mainwp-remove-site-button').on('click', function () {
80 let side_id = jQuery(this).attr('site-id');
81 let confirmation = "Are you sure you want to remove this site from your MainWP Dashboard?";
82
83 let _confirm_callback = mainwp_get_remove_calback(side_id);
84
85 mainwp_confirm(confirmation, _confirm_callback, false, false, false, 'REMOVE');
86
87 return false;
88 });
89
90 });
91
92 let mainwp_get_remove_calback = function (side_id) {
93 return function () {
94 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Removing the site. Please wait...', 'mainwp'), '');
95 let data = mainwp_secure_data({
96 action: 'mainwp_removesite',
97 id: side_id
98 });
99
100 jQuery.post(ajaxurl, data, function (response) {
101
102 let error = false;
103
104 if (response.error != undefined) {
105 error = response.error;
106 } else if (response.result == 'SUCCESS') {
107 feedback('mainwp-message-zone', __('The site has been removed and the MainWP Child plugin has been disabled. You will be redirected to the Sites page right away.', 'mainwp'), 'green');
108 } else if (response.result == 'NOSITE') {
109 feedback('mainwp-message-zone', __('Site could not be removed. Please reload the page and try again.', 'mainwp'), 'red');
110 error = true;
111 } else {
112 feedback('mainwp-message-zone', __('The site has been removed. Please make sure that the MainWP Child plugin has been deactivated properly. You will be redirected to the Sites page right away.', 'mainwp'), 'green');
113 }
114
115 if (!error) {
116 setTimeout(function () {
117 mainwp_forceReload('admin.php?page=managesites');
118 }, 3000);
119 }
120
121 }, 'json');
122 }
123
124 }
125
126 globalThis.mainwp_set_message_zone = globalThis.mainwp_set_message_zone || function (zone_selector, msg_html, colors, show) {
127 if (msg_html) {
128 jQuery(zone_selector).html(msg_html);
129 } else if (msg_html === '' || msg_html === undefined) {
130 jQuery(zone_selector).html('');
131 }
132
133 if ( colors !== undefined && colors != '') {
134 jQuery(zone_selector).removeClass('green yellow red');
135 jQuery(zone_selector).addClass(colors);
136 } else if (colors === '' || colors === undefined) {
137 jQuery(zone_selector).removeClass('green yellow red');
138 }
139
140 if (true === show || (false !== show && msg_html)) {
141 jQuery(zone_selector).show();
142 } else {
143 jQuery(zone_selector).hide();
144 }
145 };
146
147 let bulkInstallMaxThreads = mainwpParams['maximumInstallUpdateRequests'] == undefined ? 3 : mainwpParams['maximumInstallUpdateRequests'];
148 let bulkInstallCurrentThreads = 0;
149 let bulkInstallDone = 0;
150
151 /**
152 * Global
153 */
154 jQuery(function () {
155 jQuery('.mainwp-row').on({
156 mouseenter: function () {
157 rowMouseEnter(this);
158 },
159 mouseleave: function () {
160 rowMouseLeave(this);
161 }
162 });
163 });
164 let rowMouseEnter = function (elem) {
165 if (!jQuery(elem).children('.mainwp-row-actions-working').is(":visible"))
166 jQuery(elem).children('.mainwp-row-actions').show();
167 };
168 let rowMouseLeave = function (elem) {
169 if (jQuery(elem).children('.mainwp-row-actions').is(":visible"))
170 jQuery(elem).children('.mainwp-row-actions').hide();
171 };
172
173 /**
174 * Recent posts
175 */
176 jQuery(function () {
177 jQuery(document).on('click', '.mainwp-post-unpublish', function () {
178 postAction(jQuery(this), 'unpublish');
179 return false;
180 });
181 jQuery(document).on('click', '.mainwp-post-publish', function () {
182 postAction(jQuery(this), 'publish');
183 return false;
184 });
185 jQuery(document).on('click', '.mainwp-post-trash', function () {
186 postAction(jQuery(this), 'trash');
187 return false;
188 });
189 jQuery(document).on('click', '.mainwp-post-restore', function () {
190 postAction(jQuery(this), 'restore');
191 return false;
192 });
193 jQuery(document).on('click', '.mainwp-post-delete', function () {
194 postAction(jQuery(this), 'delete');
195 return false;
196 });
197
198 });
199
200 // Publish, Unpublish, Trash, ... posts and pages
201 let postAction = function (elem, what) {
202 let rowElement = jQuery(elem).closest('.grid');
203 let postId = rowElement.children('.postId').val();
204 let websiteId = rowElement.children('.websiteId').val();
205
206 let data = mainwp_secure_data({
207 action: 'mainwp_post_' + what,
208 postId: postId,
209 websiteId: websiteId
210 });
211 rowElement.hide();
212 rowElement.next('.mainwp-row-actions-working').show();
213 jQuery.post(ajaxurl, data, function (response) {
214 if (response.error) {
215 rowElement.show();
216 rowElement.next('.mainwp-row-actions-working').hide();
217 rowElement.html('<div class="sixteen wide column"><i class="times red icon"></i> ' + response.error + '</div>');
218 } else if (response.result) {
219 rowElement.show();
220 rowElement.next('.mainwp-row-actions-working').hide();
221 rowElement.html('<div class="sixteen wide column"><i class="check green icon"></i>' + response.result + '</div>');
222 } else {
223 rowElement.show();
224 rowElement.next('.mainwp-row-actions-working').hide();
225 }
226 }, 'json');
227 return false;
228 };
229
230
231 let mainwp_post_posting_start_next = function (start) {
232 if (start !== undefined && start) {
233 bulkInstallDone = 0;
234 bulkInstallCurrentThreads = 0;
235 mainwpVars.bulkInstallTotal = jQuery('.site-bulk-posting[status="queue"]').length;
236 }
237 while ((siteToPosting = jQuery('.site-bulk-posting[status="queue"]:first')) && (siteToPosting.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR -- modified out side the function.
238 mainwp_post_posting_start_specific(siteToPosting);
239 }
240 };
241
242 let mainwp_post_posting_start_specific = function (siteToPosting) {
243 siteToPosting.attr('status', 'progress');
244 bulkInstallDone++;
245 bulkInstallCurrentThreads++;
246 let data = mainwp_secure_data({
247 action: 'mainwp_post_postingbulk',
248 post_id: jQuery('#bulk_posting_id').val(),
249 site_id: jQuery(siteToPosting).attr('site-id'),
250 count: bulkInstallDone,
251 total: mainwpVars.bulkInstallTotal,
252 delete_bulkpost: (bulkInstallDone == mainwpVars.bulkInstallTotal)
253 });
254 siteToPosting.find('.progress').html('<i class="notched circle loading icon"></i>');
255 jQuery.post(ajaxurl, data, function (response) {
256 bulkInstallCurrentThreads--;
257 if (response?.result) {
258 siteToPosting.find('.progress').html(response.result);
259 if (response.edit_link !== '') {
260 siteToPosting.after(response.edit_link);
261 }
262 }
263 mainwp_post_posting_start_next();
264 }, 'json');
265 }
266
267
268 /**
269 * Plugins Widget
270 */
271 jQuery(function () {
272 jQuery(document).on('click', '.mainwp-plugin-deactivate', function () {
273 pluginAction(jQuery(this), 'deactivate');
274 return false;
275 });
276 jQuery(document).on('click', '.mainwp-plugin-activate', function () {
277 pluginAction(jQuery(this), 'activate');
278 return false;
279 });
280 jQuery(document).on('click', '.mainwp-plugin-delete', function () {
281 let name = jQuery(this).closest('.row-manage-item').attr('plugin-title');
282 let confirmMsg = __('You are about to delete the %1?', name);
283 mainwp_confirm(confirmMsg, () =>{
284 pluginAction(jQuery(this), 'delete');
285 });
286 return false;
287 });
288 });
289
290
291 let pluginAction = function (elem, what) {
292 let rowElement = jQuery(elem).closest('.row-manage-item');
293 let plugin = rowElement.children('.pluginSlug').val();
294 let websiteId = rowElement.children('.websiteId').val();
295
296 let data = mainwp_secure_data({
297 action: 'mainwp_widget_plugin_' + what,
298 plugin: plugin,
299 websiteId: websiteId
300 });
301 plugin_theme_doAction(data, rowElement);
302 return false;
303 };
304
305 /**
306 * Themes Widget
307 */
308 jQuery(function () {
309 jQuery(document).on('click', '.mainwp-theme-activate', function () {
310 themeAction(jQuery(this), 'activate');
311 return false;
312 });
313 jQuery(document).on('click', '.mainwp-theme-delete', function () {
314 let name = jQuery(this).closest('.row-manage-item').children('.themeName').val();
315 let confirmMsg = __('You are about to delete the %1?', name);
316 mainwp_confirm(confirmMsg, () => {
317 themeAction(jQuery(this), 'delete');
318 });
319 return false;
320 });
321 });
322
323 let themeAction = function (elem, what) {
324 let rowElement = jQuery(elem).closest('.row-manage-item');
325 let theme = rowElement.children('.themeSlug').val();
326 let websiteId = rowElement.children('.websiteId').val();
327 let data = mainwp_secure_data({
328 action: 'mainwp_widget_theme_' + what,
329 theme: theme,
330 websiteId: websiteId
331 });
332 plugin_theme_doAction(data, rowElement);
333 return false;
334 };
335
336 let plugin_theme_doAction = function (data, rowElement) {
337 rowElement.children().hide();
338 rowElement.children('.mainwp-row-actions-working').show();
339 jQuery.post(ajaxurl, data, function (response) {
340 if (response?.error) {
341 rowElement.children().show();
342 rowElement.html(response.error);
343 } else if (response?.result) {
344 rowElement.children().show();
345 rowElement.html(response.result);
346 } else {
347 rowElement.children('.mainwp-row-actions-working').hide();
348 }
349 }, 'json');
350 };
351
352
353 // offsetRelative (or, if you prefer, positionRelative)
354 (function ($) {
355 $.fn.offsetRelative = function (top) {
356 let $this = $(this);
357 let $parent = $this.offsetParent();
358 let offset = $this.position();
359 if (!top)
360 return offset; // Didn't pass a 'top' element
361 else if ($parent.get(0).tagName == "BODY")
362 return offset; // Reached top of document
363 else if ($(top, $parent).length)
364 return offset; // Parent element contains the 'top' element we want the offset to be relative to
365 else if ($parent[0] == $(top)[0])
366 return offset; // Reached the 'top' element we want the offset to be relative to
367 else { // Get parent's relative offset
368 let parent_offset = $parent.offsetRelative(top);
369 offset.top += parent_offset.top;
370 offset.left += parent_offset.left;
371 return offset;
372 }
373 };
374 $.fn.positionRelative = function (top) {
375 return $(this).offsetRelative(top);
376 };
377 })(jQuery);
378
379 let hidingSubMenuTimers = {};
380 jQuery(function () {
381 jQuery('.mainwp-submenu-wrapper').on({
382 mouseenter: function () {
383 let spanId = /^menu-mainwp-(.*)$/.exec(jQuery(this).attr('id'));
384 if (spanId) {
385 if (hidingSubMenuTimers[spanId[1]]) {
386 clearTimeout(hidingSubMenuTimers[spanId[1]]);
387 }
388 }
389 },
390 mouseleave: function () {
391 let spanId = /^menu-mainwp-(.*)$/.exec(jQuery(this).attr('id'));
392 if (spanId) {
393 hidingSubMenuTimers[spanId[1]] = setTimeout(function (span) {
394 return function () {
395 subMenuOut(span);
396 };
397 }(spanId[1]), 30);
398 }
399 }
400 });
401 });
402 let subMenuOut = function (subName) {
403 jQuery('#menu-mainwp-' + subName).hide();
404 jQuery('#mainwp-' + subName).parent().parent().css('background-color', '');
405 jQuery('#mainwp-' + subName).parent().parent().removeClass('hoverli');
406 jQuery('#mainwp-' + subName).css('color', '');
407 };
408 // eslint-disable-next-line complexity
409 globalThis.mainwp_js_get_error_not_detected_connect = function (jsonStr, what, elemId, retErrText) { // NOSONAR - complexity.
410 if (undefined !== jsonStr && '' != jsonStr && undefined !== what && 'html_msg' === what) {
411 try {
412 let obj_err = JSON.parse(jsonStr);
413 if (typeof obj_err === 'object') {
414 if (obj_err?.el_before && obj_err?.el_link && obj_err?.el_text) {
415 let elafter = obj_err.el_after === undefined ? '' : obj_err.el_after;
416 if (true === retErrText) {
417 return obj_err.el_before + obj_err.el_text + elafter;
418 }
419 if (undefined !== elemId && '' != elemId) {
420 let el = document.createElement('a');
421 el.text = obj_err.el_text;
422 el.href = obj_err.el_link;
423 el.target = "_blank";
424 console.log(el);
425 jQuery('#' + elemId).html('').append(document.createTextNode(obj_err.el_before), el, document.createTextNode(elafter));
426 feedback_scroll(elemId, 'red');
427 }
428 return true;
429 }
430 } else {
431 return false; // it is not or invalid json.
432 }
433 } catch (e) {
434 console.log(e);
435 return false; // it is not or invalid json.
436 }
437 }
438 return __('MainWP Child plugin not detected or could not be reached! Ensure the MainWP Child plugin is installed and activated on the child site, and there are no security rules blocking requests. If you continue experiencing this issue, check the MainWP Community for help.');
439 }
440
441 globalThis.mainwp_get_reconnect_error = function (response, siteId) { // NOSONAR - complexity.
442 if ('reconnect_failed' === response) {
443 return __('Reconnect failed. Please try again from the %1Site Settings page%2.', '<a href="admin.php?page=managesites&id=' + siteId + '">', '</a>');
444 } else {
445 return response;
446 }
447 }
448
449 function shake_element(select) {
450 let pos = jQuery(select).position();
451 let type = jQuery(select).css('position');
452
453 if (type == 'static') {
454 jQuery(select).css({
455 position: 'relative'
456 });
457 }
458
459 if (type == 'static' || type == 'relative') {
460 pos.top = 0;
461 pos.left = 0;
462 }
463
464 jQuery(select).data('init-type', type);
465
466 let shake = [[0, 5, 60], [0, 0, 60], [0, -5, 60], [0, 0, 60], [0, 2, 30], [0, 0, 30], [0, -2, 30], [0, 0, 30]];
467
468 for (let s of shake) {
469 jQuery(select).animate({
470 top: pos.top + s[0],
471 left: pos.left + s[1]
472 }, s[2], 'linear');
473 }
474 }
475
476
477 /**
478 * Required
479 */
480 globalThis.feedback = function (id, text, type, append) {
481 if (append) {
482 let currentHtml = jQuery('#' + id).html();
483 if (currentHtml == null)
484 currentHtml = "";
485 if (currentHtml == '') {
486 currentHtml = text;
487 } else {
488 currentHtml += '<br />' + text;
489 }
490 jQuery('#' + id).html(currentHtml);
491 jQuery('#' + id).removeClass('yellow');
492 jQuery('#' + id).removeClass('green');
493 jQuery('#' + id).removeClass('red');
494 jQuery('#' + id).addClass(type);
495 } else {
496 jQuery('#' + id).html(text);
497 jQuery('#' + id).removeClass('yellow');
498 jQuery('#' + id).removeClass('green');
499 jQuery('#' + id).removeClass('red');
500 jQuery('#' + id).addClass(type);
501 }
502 jQuery('#' + id).show();
503
504 // automatically scroll to error message if it's not visible
505 scrollElementTop(id);
506 };
507
508 globalThis.feedback_scroll = function (id, color) {
509 jQuery('#' + id).removeClass('green red yellow');
510 jQuery('#' + id).addClass(color);
511 jQuery('#' + id).show();
512 // automatically scroll to error message if it's not visible
513 scrollElementTop(id);
514 }
515
516 globalThis.scrollElementTop = function (id) {
517 let scrolltop = jQuery(globalThis).scrollTop();
518 if (jQuery('#' + id).length == 0) {
519 return;
520 }
521 let off = jQuery('#' + id).offset();
522 if (scrolltop > off.top - 40)
523 jQuery('html, body').animate({
524 scrollTop: off.top - 40
525 }, 1000, function () {
526 shake_element('#' + id)
527 });
528 else
529 shake_element('#' + id); // shake the error message to get attention :)
530 }
531
532 globalThis.mainwp_showhide_message = function (id, content, cls, append, scroll) {
533
534 if ('' === content) {
535 jQuery('#' + id).html('').fadeOut(500);
536 return;
537 }
538
539 if (append) {
540 let html = jQuery('#' + id).html();
541 if (html == null)
542 html = "";
543 if (html == '') {
544 html = content;
545 } else {
546 html += '<br />' + content;
547 }
548 jQuery('#' + id).html(html);
549 } else {
550 jQuery('#' + id).html(content);
551 }
552
553 jQuery('#' + id).removeClass('yellow green red');
554 jQuery('#' + id).addClass(cls);
555 jQuery('#' + id).show();
556
557 if (scroll === undefined && scroll) {
558 scrollElementTop(id);
559 }
560
561 };
562
563 jQuery(function () {
564 jQuery('div.mainwp-hidden').parent().parent().css("display", "none");
565 });
566
567 /**
568 * Security Issues
569 */
570
571 let securityIssues_fixes = ['core_updates', 'plugin_updates', 'theme_updates', 'db_reporting', 'php_reporting', 'wp_uptodate', 'phpversion_matched', 'sslprotocol', 'debug_disabled', 'sec_outdated_plugins', 'sec_inactive_plugins', 'sec_outdated_themes', 'sec_inactive_themes'];
572 jQuery(function () {
573 let securityIssueSite = jQuery('#securityIssueSite');
574 if ((securityIssueSite.val() != null) && (securityIssueSite.val() != "")) {
575 jQuery(document).on('click', '#securityIssues_refresh', function () {
576 for (let ise of securityIssues_fixes) {
577 let securityIssueCurrentIssue = jQuery('#' + ise + '_fix');
578 if (securityIssueCurrentIssue) {
579 securityIssueCurrentIssue.hide();
580 }
581 jQuery('#' + ise + '_extra').hide();
582 jQuery('#' + ise + '_ok').hide();
583 jQuery('#' + ise + '_nok').hide();
584 jQuery('#' + ise + '_loading').show();
585 }
586 securityIssues_request(jQuery('#securityIssueSite').val());
587 });
588
589 for (let ise of securityIssues_fixes) {
590 if (ise === 'wp_uptodate' || ise === 'sec_inactive_themes' || ise === 'sec_inactive_plugins' || ise === 'sec_outdated_plugins' || ise === 'sec_outdated_themes') {
591 continue;
592 }
593 jQuery('#' + ise + '_fix').on('click', function (what) {
594 return function () {
595 securityIssues_fix(what);
596 return false;
597 }
598 }(ise));
599
600 jQuery('#' + ise + '_unfix').on('click', function (what) {
601 return function () {
602 securityIssues_unfix(what);
603 return false;
604 }
605 }(ise));
606 }
607 securityIssues_request(securityIssueSite.val());
608 }
609 });
610 globalThis.securityIssues_fix = function (feature) {
611 if (jQuery('#' + feature + '_fix')) {
612 jQuery('#' + feature + '_fix').hide();
613 }
614 jQuery('#' + feature + '_extra').hide();
615 jQuery('#' + feature + '_ok').hide();
616 jQuery('#' + feature + '_nok').hide();
617 jQuery('#' + feature + '_loading').show();
618
619 let data = mainwp_secure_data({
620 action: 'mainwp_security_issues_fix',
621 feature: feature,
622 id: jQuery('#securityIssueSite').val()
623 });
624
625 jQuery.post(ajaxurl, data, function (response) {
626 securityIssues_handle(response);
627 }, 'json');
628 };
629
630 let securityIssues_unfix = function (feature) {
631 if (jQuery('#' + feature + '_unfix')) {
632 jQuery('#' + feature + '_unfix').hide();
633 }
634 jQuery('#' + feature + '_extra').hide();
635 jQuery('#' + feature + '_ok').hide();
636 jQuery('#' + feature + '_nok').hide();
637 jQuery('#' + feature + '_loading').show();
638
639 let data = mainwp_secure_data({
640 action: 'mainwp_security_issues_unfix',
641 feature: feature,
642 id: jQuery('#securityIssueSite').val()
643 });
644 jQuery.post(ajaxurl, data, function (response) {
645 securityIssues_handle(response);
646 }, 'json');
647 };
648 let securityIssues_request = function (websiteId) {
649 let data = mainwp_secure_data({
650 action: 'mainwp_security_issues_request',
651 id: websiteId
652 });
653 jQuery.post(ajaxurl, data, function (response) {
654 securityIssues_handle(response);
655 }, 'json');
656 };
657 // eslint-disable-next-line complexity
658 let securityIssues_handle = function (response) { // NOSONAR - complex.
659 let result = '';
660 if (response.error) {
661 result = getErrorMessage(response.error);
662 } else {
663 try {
664 let res = response.result;
665 for (let issue in res) {
666 if (jQuery('#' + issue + '_loading')) {
667 jQuery('#' + issue + '_loading').hide();
668 if (res[issue] == 'Y' || res[issue] == 'Y_UNABLE') {
669 jQuery('#' + issue + '_extra').hide();
670 jQuery('#' + issue + '_nok').hide();
671 if (jQuery('#' + issue + '_fix')) {
672 jQuery('#' + issue + '_fix').hide();
673 }
674
675 if (jQuery('#' + issue + '_unfix')) {
676 jQuery('#' + issue + '_unfix').show();
677 if (res[issue] == 'Y_UNABLE') { // Y_UNABLE will disable unfix.
678 jQuery('#' + issue + '_unfix').hide();
679 }
680 }
681
682 jQuery('#' + issue + '_ok').show();
683 jQuery('#' + issue + '-status-ok').show();
684 jQuery('#' + issue + '-status-nok').hide();
685 } else if (res[issue] == 'N' || res[issue] == 'N_UNABLE') {
686 jQuery('#' + issue + '_extra').hide();
687 jQuery('#' + issue + '_ok').hide();
688 jQuery('#' + issue + '_nok').show();
689
690 if (jQuery('#' + issue + '_fix')) {
691 jQuery('#' + issue + '_fix').show();
692 if (res[issue] == 'N_UNABLE') { // N_UNABLE will disable fix.
693 jQuery('#' + issue + '_fix').hide().after('<a href="javascript:void(0);" class="ui mini fluid button" disabled="disabled">fix</a>');
694 }
695 }
696
697 if (jQuery('#' + issue + '_unfix')) {
698 jQuery('#' + issue + '_unfix').hide();
699 }
700 if (res[issue] != 'N') {
701 jQuery('#' + issue + '_extra').html(res[issue]);
702 jQuery('#' + issue + '_extra').show();
703 }
704
705 if ('wp_uptodate' === issue) {
706 jQuery('#wp_upgrades').find('div[updated="-1"]').each(function () {
707 jQuery(this).attr('updated', 0);
708 });
709 }
710 jQuery('#' + issue + '-status-ok').hide();
711 jQuery('#' + issue + '-status-nok').show();
712 }
713 }
714 }
715 } catch {
716 result = '<i class="exclamation circle icon"></i> ' + __('Undefined error!');
717 }
718 }
719 if (result != '') {
720 //show error!
721 }
722 };
723
724 globalThis.updatesoverview_bulk_check_abandoned = function (which) {
725 let confirmMsg;
726 if ('plugin' == which) {
727 confirmMsg = __("You are about to check abandoned plugins on the sites?");
728 } else {
729 confirmMsg = __("You are about to check abandoned themes on the sites?");
730 }
731 mainwp_confirm(confirmMsg, function () { mainwp_managesites_bulk_check_abandoned('all', which); });
732 }
733
734 globalThis.mainwp_managesites_bulk_check_abandoned = function (siteIds, which) {
735 let allWebsiteIds = jQuery('.dashboard_wp_id[error-status=0]').map(function (indx, el) {
736 return jQuery(el).val();
737 });
738
739 if ('all' == siteIds) {
740 siteIds = allWebsiteIds;
741 }
742
743 let selectedIds = [], excludeIds = [];
744 if (Array.isArray(siteIds)) {
745 jQuery.grep(allWebsiteIds, function (el) {
746 if (jQuery.inArray(el, siteIds) === -1) {
747 excludeIds.push(el);
748 } else {
749 selectedIds.push(el);
750 }
751 });
752 for (let id of excludeIds) {
753 dashboard_update_site_hide(id);
754 }
755 allWebsiteIds = selectedIds;
756 }
757
758 let nrOfWebsites = allWebsiteIds.length;
759
760 if (nrOfWebsites == 0) {
761 managesites_reset_bulk_actions_params();
762 return;
763 }
764
765 let siteNames = {};
766
767 for (let id of allWebsiteIds) {
768 dashboard_update_site_status(id, '<i class="clock outline icon"></i>');
769 siteNames[id] = jQuery('.sync-site-status[siteid="' + id + '"]').attr('niceurl');
770 }
771 let initData = {
772 progressMax: nrOfWebsites,
773 title: 'Check abandoned ' + ('plugin' == which ? 'plugins' : 'themes'),
774 statusText: __('started'),
775 callback: function () {
776 mainwpVars.bulkManageSitesTaskRunning = false;
777 mainwp_forceReload();
778 }
779 };
780 mainwpPopup('#mainwp-sync-sites-modal').init(initData);
781
782 mainwp_managesites_check_abandoned_all_int(allWebsiteIds, which);
783 };
784
785 let mainwp_managesites_check_abandoned_all_int = function (websiteIds, which) {
786 mainwpVars.websitesToUpgrade = websiteIds;
787 mainwpVars.currentWebsite = 0;
788 mainwpVars.websitesDone = 0;
789 mainwpVars.websitesTotal = mainwpVars.websitesToUpgrade.length;
790 mainwpVars.websitesLeft = mainwpVars.websitesToUpgrade.length;
791
792 mainwpVars.bulkTaskRunning = true;
793 mainwp_managesites_check_abandoned_all_loop_next(which);
794 };
795
796 let mainwp_managesites_check_abandoned_all_loop_next = function (which) {
797 while (mainwpVars.bulkTaskRunning && (mainwpVars.currentThreads < mainwpVars.maxThreads) && (mainwpVars.websitesLeft > 0)) {
798 mainwp_managesites_check_abandoned_all_upgrade_next(which);
799 }
800 };
801 let mainwp_managesites_check_abandoned_all_upgrade_next = function (which) {
802 mainwpVars.currentThreads++;
803 mainwpVars.websitesLeft--;
804
805 let websiteId = mainwpVars.websitesToUpgrade[mainwpVars.currentWebsite++];
806 dashboard_update_site_status(websiteId, '<i class="sync alternate loading icon"></i>');
807
808 mainwp_managesites_check_abandoned_int(websiteId, which);
809 };
810
811 let mainwp_managesites_check_abandoned_int = function (siteid, which) {
812
813 let data = mainwp_secure_data({
814 action: 'mainwp_check_abandoned',
815 siteId: siteid,
816 which: which
817 });
818
819 jQuery.ajax({
820 type: 'POST',
821 url: ajaxurl,
822 data: data,
823 success: function (pSiteid) {
824 return function (response) {
825 mainwpVars.currentThreads--;
826 mainwpVars.websitesDone++;
827 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(mainwpVars.websitesDone);
828 if (response.error != undefined) {
829 dashboard_update_site_status(pSiteid, '<i class="red times icon"></i>');
830 } else if (response.result && response.result == 'success') {
831 dashboard_update_site_status(pSiteid, '<i class="green check icon"></i>', true);
832 } else {
833 dashboard_update_site_status(pSiteid, '<i class="red times icon"></i>');
834 }
835 mainwp_managesites_check_abandoned_all_loop_next(which);
836 }
837 }(siteid),
838 dataType: 'json'
839 });
840 };
841
842 /**
843 * MainWP UI.
844 */
845 jQuery(function () {
846 jQuery('#reset-overview-settings').on('click', function () {
847 mainwp_confirm(__('Are you sure?'), function () {
848 let which_set = jQuery('input[name=reset_overview_which_settings]').val();
849 if ('sidebar_settings' == which_set) {
850 jQuery('#mainwp_sidebarPosition').dropdown('set selected', 1);
851 } else if ('overview_settings' == which_set) {
852 jQuery('input[name=hide_update_everything]').prop('checked', false);
853 jQuery('.mainwp_hide_wpmenu_checkboxes input[name="mainwp_show_widgets[]"]').prop('checked', true);
854 }
855 if (jQuery('input[name=mainwp_manageposts_show_columns_settings]').length > 0 || jQuery('input[name=mainwp_managepages_show_columns_settings]').length > 0 || jQuery('input[name=mainwp_manageusers_show_columns_settings]').length > 0) {
856 jQuery('input[name="mainwp_show_columns[]"]').prop('checked', true);
857 }
858 jQuery('input[name=reset_overview_settings]').attr('value', 1);
859 jQuery('#submit-overview-settings').click();
860 }, false, false, true);
861 return false;
862 });
863 });
864
865 /**
866 * Sync Sites
867 */
868
869 jQuery(function () {
870 jQuery('#mainwp-sync-sites').on('click', function () {
871 mainwp_sync_sites_data();
872 });
873
874 // to compatible with extensions
875 jQuery('#dashboard_refresh').on('click', function () {
876 mainwp_sync_sites_data();
877 });
878 jQuery('.mainwp-sync-this-site').on('click', function () {
879 let syncSiteIds = [];
880 syncSiteIds.push(jQuery(this).attr('site-id'));
881 mainwp_sync_sites_data(syncSiteIds);
882 });
883 });
884
885 globalThis.mainwp_sync_sites_data = function (syncSiteIds, pAction) {
886 let allWebsiteIds = [];
887 jQuery('.dashboard_wp_id[error-status=0]').map(function (indx, el) {
888 allWebsiteIds.push(jQuery(el).val());
889 });
890 let globalSync = true;
891 let selectedIds = [], excludeIds = [];
892 if (Array.isArray(syncSiteIds)) {
893 jQuery.grep(allWebsiteIds, function (el) {
894 if (jQuery.inArray(el, syncSiteIds) === -1) {
895 excludeIds.push(el);
896 } else {
897 selectedIds.push(el);
898 }
899 });
900 for (let id of excludeIds) {
901 dashboard_update_site_hide(id);
902 }
903 allWebsiteIds = selectedIds;
904 globalSync = false;
905 }
906
907 for (let id of allWebsiteIds) {
908 dashboard_update_site_status(id, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Pending', 'mainwp') + '"><i class="clock outline icon"></i></span>');
909 }
910
911 let nrOfWebsites = allWebsiteIds.length;
912
913 mainwpPopup('#mainwp-sync-sites-modal').init({
914 title: (pAction == 'checknow' ? __('Check Now') : __('Data Synchronization')),
915 progressMax: nrOfWebsites,
916 statusText: (pAction == 'checknow' ? 'checked' : 'synced'),
917 callback: function () {
918 mainwpVars.bulkTaskRunning = false;
919 history.pushState("", document.title, globalThis.location.pathname + globalThis.location.search); // to fix issue for url with hash
920 mainwp_forceReload();
921 }
922 });
923
924 if (jQuery('#mainwp-sync-sites-modal').attr('current-wpid') > 0) {
925 globalSync = false;
926 }
927
928 dashboard_update(allWebsiteIds, globalSync, pAction);
929
930 if (pAction != 'checknow') {
931 if (nrOfWebsites > 0) {
932 let data = {
933 action: 'mainwp_status_saving',
934 status: 'last_sync_sites',
935 isGlobalSync: globalSync ? 1 : 0
936 };
937 jQuery.post(ajaxurl, mainwp_secure_data(data), function () {
938
939 });
940 }
941 }
942 };
943
944 mainwpVars.websitesToUpdate = [];
945 mainwpVars.websitesTotal = 0;
946 mainwpVars.websitesLeft = 0;
947 mainwpVars.websitesDone = 0;
948 mainwpVars.currentWebsite = 0;
949 mainwpVars.bulkTaskRunning = false;
950 mainwpVars.currentThreads = 0;
951 mainwpVars.maxThreads = mainwpParams['maximumSyncRequests'] == undefined ? 8 : mainwpParams['maximumSyncRequests'];
952 mainwpVars.maxUpdateThreads = mainwpParams['maximumInstallUpdateRequests'] == undefined ? 3 : mainwpParams['maximumInstallUpdateRequests'];
953
954 let globalSync = true;
955
956 globalThis.dashboard_update = function (websiteIds, isGlobalSync, pAction) {
957 mainwpVars.websitesToUpdate = websiteIds;
958 mainwpVars.currentWebsite = 0;
959 mainwpVars.websitesDone = 0;
960 mainwpVars.successCount = 0;
961 mainwpVars.websitesTotal = mainwpVars.websitesLeft = mainwpVars.websitesToUpdate.length;
962 globalSync = isGlobalSync;
963
964 mainwpVars.bulkTaskRunning = true;
965
966 if (mainwpVars.websitesTotal == 0) {
967 dashboard_update_done(pAction);
968 } else {
969 dashboard_loop_next(pAction);
970 }
971 };
972
973 (function () {
974 // Create global namespace
975 const sync = globalThis.dashboardSync = globalThis.dashboardSync || {
976 container: null,
977 statusMap: new Map(),
978 rowMap: new Map(),
979
980 data: new Map(),
981 queue: [],
982
983 scheduled: false,
984 initialized: false,
985
986 BATCH_SIZE: 50
987 };
988
989 // -----------------------------
990 // INIT CACHE
991 // -----------------------------
992 function init() {
993 if (sync.initialized) return;
994
995 sync.container = document.getElementById('sync-sites-status');
996 if (!sync.container) return;
997
998 const nodes = sync.container.querySelectorAll('.sync-site-status');
999
1000 for (const el of nodes) {
1001 const siteId = el.getAttribute('siteid');
1002 sync.statusMap.set(siteId, el);
1003 sync.rowMap.set(siteId, el.closest('.item'));
1004 }
1005
1006 sync.initialized = true;
1007 }
1008
1009 // Ensure DOM ready
1010 if (document.readyState === 'loading') {
1011 document.addEventListener('DOMContentLoaded', init);
1012 } else {
1013 init();
1014 }
1015
1016 // -----------------------------
1017 // PUBLIC API
1018 // -----------------------------
1019 globalThis.dashboard_update_site_status = function (siteId, newStatus, isSuccess) {
1020 if (!sync.initialized) return;
1021
1022 sync.data.set(siteId, {
1023 status: newStatus,
1024 success: isSuccess
1025 });
1026
1027 sync.queue.push(siteId);
1028
1029 // �
1030 increment success count ONCE
1031 if (isSuccess) {
1032 mainwpVars.successCount = (mainwpVars.successCount || 0) + 1;
1033 }
1034
1035 if (!sync.scheduled) {
1036 sync.scheduled = true;
1037 requestAnimationFrame(processQueue);
1038 }
1039 };
1040
1041 globalThis.dashboard_update_site_hide = function (siteId) {
1042 const sync = globalThis.dashboardSync;
1043 if (!sync?.initialized) return;
1044
1045 const rowEl = sync.rowMap.get(siteId);
1046 if (!rowEl) return;
1047
1048 rowEl.style.display = 'none';
1049 };
1050
1051 // -----------------------------
1052 // PROCESS QUEUE (BATCHED)
1053 // -----------------------------
1054 function processQueue() {
1055 sync.scheduled = false;
1056
1057 let count = 0;
1058
1059 while (sync.queue.length && count < sync.BATCH_SIZE) {
1060 const siteId = sync.queue.shift();
1061 const data = sync.data.get(siteId);
1062
1063 const statusEl = sync.statusMap.get(siteId);
1064 const rowEl = sync.rowMap.get(siteId);
1065
1066 if (!statusEl || !rowEl) continue;
1067
1068 // Avoid DOM read → use dataset cache
1069 if (statusEl.dataset.last !== data.status) {
1070 statusEl.innerHTML = data.status;
1071 statusEl.dataset.last = data.status;
1072 }
1073
1074 // No DOM move → just class toggle
1075 if (data.success) {
1076 rowEl.classList.add('is-success');
1077 }
1078
1079 count++;
1080 }
1081
1082 // Continue next frame if still pending
1083 if (sync.queue.length) {
1084 requestAnimationFrame(processQueue);
1085 }
1086 }
1087 })();
1088
1089 globalThis.dashboard_update_site_status_legacy = function (siteId, newStatus, isSuccess) {
1090 jQuery('.sync-site-status[siteid="' + siteId + '"]').html(newStatus);
1091 // Move successfully synced site to the bottom of the sync list
1092 if ( isSuccess !== undefined && isSuccess) {
1093 let row = jQuery('.sync-site-status[siteid="' + siteId + '"]').closest('.item');
1094 jQuery(row).insertAfter(jQuery("#sync-sites-status .item").not('.disconnected-site').last());
1095 }
1096 };
1097
1098 globalThis.dashboard_update_site_hide_legacy = function (siteId) {
1099 jQuery('.sync-site-status[siteid="' + siteId + '"]').closest('.item').hide();
1100 };
1101
1102 let dashboard_loop_next = function (pAction) {
1103 while (mainwpVars.bulkTaskRunning && (mainwpVars.currentThreads < mainwpVars.maxThreads) && (mainwpVars.websitesLeft > 0)) {
1104 dashboard_update_next(pAction);
1105 }
1106 };
1107
1108 let dashboard_update_done = function (pAction) {
1109 mainwpVars.currentThreads--;
1110
1111 if (!mainwpVars.bulkTaskRunning) return;
1112
1113 mainwpVars.websitesDone++;
1114 if (mainwpVars.websitesDone > mainwpVars.websitesTotal) {
1115 mainwpVars.websitesDone = mainwpVars.websitesTotal;
1116 }
1117
1118 // �
1119 Cache popup instance (avoid re-query)
1120 const popup = mainwpVars._popup || (
1121 mainwpVars._popup = mainwpPopup('#mainwp-sync-sites-modal')
1122 );
1123
1124 popup.setProgressSite(mainwpVars.websitesDone);
1125
1126 // �
1127 Avoid DOM query for success count → track in JS
1128 if (mainwpVars.websitesDone === mainwpVars.websitesTotal) {
1129
1130 const successSites = mainwpVars.successCount || 0;
1131
1132 mainwpVars.bulkTaskRunning = false;
1133
1134 if (mainwpVars.websitesDone === successSites) {
1135 setTimeout(() => popup.close(true), 3000);
1136 }
1137
1138 return;
1139 }
1140
1141 dashboard_loop_next(pAction);
1142 };
1143
1144 let dashboard_update_done_legacy = function (pAction) {
1145 mainwpVars.currentThreads--;
1146 if (!mainwpVars.bulkTaskRunning)
1147 return;
1148 mainwpVars.websitesDone++;
1149 if (mainwpVars.websitesDone > mainwpVars.websitesTotal)
1150 mainwpVars.websitesDone = mainwpVars.websitesTotal;
1151
1152 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(mainwpVars.websitesDone);
1153
1154 if (mainwpVars.websitesDone == mainwpVars.websitesTotal) {
1155 let successSites = jQuery('#mainwp-sync-sites-modal .check.green.icon').length;
1156 if (mainwpVars.websitesDone == successSites) {
1157 mainwpVars.bulkTaskRunning = false;
1158 setTimeout(function () {
1159 mainwpPopup('#mainwp-sync-sites-modal').close(true);
1160 }, 3000);
1161 } else {
1162 mainwpVars.bulkTaskRunning = false;
1163 }
1164 return;
1165 }
1166
1167 dashboard_loop_next(pAction);
1168 };
1169
1170 let dashboard_update_next = function (pAction) {
1171 mainwpVars.currentThreads++;
1172 mainwpVars.websitesLeft--;
1173 let websiteId = mainwpVars.websitesToUpdate[mainwpVars.currentWebsite++];
1174 if ('checknow' == pAction) {
1175 dashboard_update_site_status(websiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Checking uptime status...', 'mainwp') + '"><i class="sync alternate loading icon"></i></span>');
1176 } else {
1177 dashboard_update_site_status(websiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Syncing data...', 'mainwp') + '"><i class="sync alternate loading icon"></i></span>');
1178 }
1179
1180 let data = mainwp_secure_data({
1181 action: ('checknow' == pAction ? 'mainwp_checksites' : 'mainwp_syncsites'),
1182 wp_id: websiteId,
1183 isGlobalSync: globalSync,
1184 bulkSync: mainwpVars.websitesTotal > 1 ? 1 : 0
1185 });
1186
1187
1188
1189 dashboard_update_next_int(websiteId, data, 0, pAction);
1190 };
1191
1192 let dashboard_update_next_int = function (websiteId, data, errors, action) {
1193 jQuery.ajax({
1194 type: 'POST',
1195 url: ajaxurl,
1196 data: data,
1197 success: function (pWebsiteId, pAction) {
1198 return function (response) {
1199 if (response.error) {
1200 let extErr = response.error;
1201 dashboard_update_site_status(pWebsiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + extErr + '"><i class="exclamation red icon"></i></span>');
1202 } else {
1203 dashboard_update_site_status(websiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Synchronization process completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>', true);
1204 }
1205 dashboard_update_done(pAction);
1206 }
1207 }(websiteId, action),
1208 error: function (pWebsiteId, pData, pErrors, pAction) {
1209 return function () {
1210 if (pErrors > 5) {
1211 dashboard_update_site_status(pWebsiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Process timed out. Please try again.', 'mainwp') + '"><i class="exclamation yellow icon"></i></span>');
1212 dashboard_update_done(pAction);
1213 } else {
1214 pErrors++;
1215 dashboard_update_next_int(pWebsiteId, pData, pErrors, pAction);
1216 }
1217 }
1218 }(websiteId, data, errors, action),
1219 dataType: 'json'
1220 });
1221 };
1222
1223
1224 /**
1225 * Delete site changes actions.
1226 */
1227
1228 let mainwp_delete_nonmainwp_data_start = function () {
1229 mainwp_delete_nonmainwp_data_start_next();
1230 }
1231
1232 let mainwp_delete_nonmainwp_data_start_next = function () {
1233 while ((checkedBox = jQuery('#mainwp-module-log-records-body-table .check-column INPUT:checkbox:checked:first')) && (checkedBox.length > 0) && (bulkManageClientsCurrentThreads < bulkManageClientsMaxThreads)) { // NOSONAR -- modified out side the function.
1234 mainwp_delete_nonmainwp_data_next();
1235 }
1236 }
1237
1238 let mainwp_delete_nonmainwp_data_next = function () {
1239 mainwpVars.currentThreads++;
1240 mainwpVars.websitesLeft--;
1241 let websiteId = mainwpVars.websitesToUpdate[mainwpVars.currentWebsite++];
1242 dashboard_update_site_status(websiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Deleting...', 'mainwp') + '"><i class="sync alternate loading icon"></i></span>');
1243 let data = mainwp_secure_data({
1244 action: 'mainwp_delete_non_mainwp_actions',
1245 wp_id: websiteId,
1246 });
1247 mainwp_delete_nonmainwp_data_next_int(websiteId, data, 0);
1248 };
1249
1250 let mainwp_delete_nonmainwp_data_next_int = function (websiteId, data, errors) {
1251 jQuery.ajax({
1252 type: 'POST',
1253 url: ajaxurl,
1254 data: data,
1255 success: function (pWebsiteId) {
1256 return function (response) {
1257 if (response.error) {
1258 let extErr = response.error;
1259 dashboard_update_site_status(pWebsiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + extErr + '"><i class="exclamation red icon"></i></span>');
1260 } else {
1261 dashboard_update_site_status(websiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Process completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>', true);
1262 }
1263 mainwp_delete_nonmainwp_data_done();
1264 }
1265 }(websiteId),
1266 error: function (pWebsiteId, pData, pErrors) {
1267 return function () {
1268 if (pErrors > 5) {
1269 dashboard_update_site_status(pWebsiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Process timed out. Please try again.', 'mainwp') + '"><i class="exclamation yellow icon"></i></span>');
1270 mainwp_delete_nonmainwp_data_done();
1271 } else {
1272 pErrors++;
1273 mainwp_delete_nonmainwp_data_next_int(pWebsiteId, pData, pErrors);
1274 }
1275 }
1276 }(websiteId, data, errors),
1277 dataType: 'json'
1278 });
1279 };
1280
1281
1282 let mainwp_delete_nonmainwp_data_done = function () {
1283 mainwpVars.currentThreads--;
1284 if (!mainwpVars.bulkTaskRunning)
1285 return;
1286 mainwpVars.websitesDone++;
1287 if (mainwpVars.websitesDone > mainwpVars.websitesTotal)
1288 mainwpVars.websitesDone = mainwpVars.websitesTotal;
1289
1290 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(mainwpVars.websitesDone);
1291
1292 if (mainwpVars.websitesDone == mainwpVars.websitesTotal) {
1293 jQuery("#mainwp-non-mainwp-changes-table tbody").fadeOut("slow");
1294 let successSites = jQuery('#mainwp-sync-sites-modal .check.green.icon').length;
1295 if (mainwpVars.websitesDone == successSites) {
1296 mainwpVars.bulkTaskRunning = false;
1297 setTimeout(function () {
1298 mainwpPopup('#mainwp-sync-sites-modal').close(true);
1299 }, 3000);
1300 } else {
1301 mainwpVars.bulkTaskRunning = false;
1302 }
1303 return;
1304 }
1305 mainwp_delete_nonmainwp_data_loop_next();
1306 };
1307
1308
1309 let mainwp_tool_disconnect_sites = function () {
1310
1311 mainwp_confirm('Are you sure that you want to disconnect your sites? This will function will break the connection and leave the MainWP Child plugin active and which makes your sites vulnerable.', function () {
1312 let allWebsiteIds = jQuery('.dashboard_wp_id[error-status=0]').map(function (indx, el) {
1313 return jQuery(el).val();
1314 });
1315
1316 for (let id of allWebsiteIds) {
1317 dashboard_update_site_status(id, '<i class="clock outline icon"></i>');
1318 }
1319
1320 let nrOfWebsites = allWebsiteIds.length;
1321
1322 mainwpPopup('#mainwp-sync-sites-modal').init({
1323 title: __('Disconnect All Sites'),
1324 progressMax: nrOfWebsites,
1325 statusText: __('disconnected'),
1326 callback: function () {
1327 mainwp_forceReload();
1328 }
1329 });
1330
1331 mainwpVars.websitesToUpdate = allWebsiteIds;
1332 mainwpVars.currentWebsite = 0;
1333 mainwpVars.websitesDone = 0;
1334 mainwpVars.websitesTotal = mainwpVars.websitesLeft = mainwpVars.websitesToUpdate.length;
1335
1336 mainwpVars.bulkTaskRunning = true;
1337
1338 if (mainwpVars.websitesTotal == 0) {
1339 mainwp_tool_disconnect_sites_done();
1340 } else {
1341 mainwp_tool_disconnect_sites_loop_next();
1342 }
1343 }, false, false, false, 'DISCONNECT');
1344 };
1345
1346 let mainwp_tool_disconnect_sites_done = function () {
1347 mainwpVars.currentThreads--;
1348 if (!mainwpVars.bulkTaskRunning)
1349 return;
1350 mainwpVars.websitesDone++;
1351 if (mainwpVars.websitesDone > mainwpVars.websitesTotal)
1352 mainwpVars.websitesDone = mainwpVars.websitesTotal;
1353
1354 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(mainwpVars.websitesDone);
1355
1356 mainwp_tool_disconnect_sites_loop_next();
1357 };
1358
1359 let mainwp_tool_disconnect_sites_loop_next = function () {
1360 while (mainwpVars.bulkTaskRunning && (mainwpVars.currentThreads < mainwpVars.maxThreads) && (mainwpVars.websitesLeft > 0)) { // NOSONAR - vars modified outside function.
1361 mainwp_tool_disconnect_sites_next();
1362 }
1363 };
1364
1365 let mainwp_tool_disconnect_sites_next = function () {
1366 mainwpVars.currentThreads++;
1367 mainwpVars.websitesLeft--;
1368 let websiteId = mainwpVars.websitesToUpdate[mainwpVars.currentWebsite++];
1369 dashboard_update_site_status(websiteId, '<i class="sync alternate loading icon"></i>');
1370 let data = mainwp_secure_data({
1371 action: 'mainwp_disconnect_site',
1372 wp_id: websiteId
1373 });
1374 mainwp_tool_disconnect_sites_next_int(websiteId, data, 0);
1375 };
1376
1377 let mainwp_tool_disconnect_sites_next_int = function (websiteId, data, errors) {
1378 jQuery.ajax({
1379 type: 'POST',
1380 url: ajaxurl,
1381 data: data,
1382 success: function (pWebsiteId) {
1383 return function (response) {
1384 if (response?.error) {
1385 dashboard_update_site_status(pWebsiteId, response.error + '<i class="exclamation red icon"></i>');
1386 } else if (response?.result == 'success') {
1387 dashboard_update_site_status(websiteId, '<i class="check green icon"></i>', true);
1388 } else {
1389 dashboard_update_site_status(pWebsiteId, __('Undefined error!') + ' <i class="exclamation red icon"></i>');
1390 }
1391 mainwp_tool_disconnect_sites_done();
1392 }
1393 }(websiteId),
1394 error: function (pWebsiteId, pData, pErrors) {
1395 return function () {
1396 if (pErrors > 5) {
1397 dashboard_update_site_status(pWebsiteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Process timed out. Please try again.', 'mainwp') + '"><i class="exclamation yellow icon"></i></span>');
1398 mainwp_tool_disconnect_sites_done();
1399 } else {
1400 pErrors++;
1401 mainwp_tool_disconnect_sites_next_int(pWebsiteId, pData, pErrors);
1402 }
1403 }
1404 }(websiteId, data, errors),
1405 dataType: 'json'
1406 });
1407 };
1408
1409 let mainwp_tool_confirm_to_process = function (pObj) {
1410 let loc = jQuery(pObj).attr('href');
1411 mainwp_confirm('Are you sure?', function () {
1412 globalThis.location = loc;
1413 });
1414 };
1415
1416
1417 /**
1418 * Manage sites page
1419 */
1420
1421 jQuery(function ($) {
1422 jQuery('#mainwp-backup-type').on('change', function () {
1423 if (jQuery(this).val() == 'full')
1424 jQuery('.mainwp-backup-full-exclude').show();
1425 else
1426 jQuery('.mainwp-backup-full-exclude').hide();
1427 });
1428 jQuery('.mainwp-checkbox-showhide-elements').on('click', function () {
1429 let hiel = $(this).attr('hide-parent');
1430 // support multi hide values.
1431 hiel.split(';').forEach( (hi) => {
1432 mainwp_showhide_elements(hi, $(this).find('input').is(':checked'));
1433 });
1434 let hideEvent = $(this).attr('fire-event-parent') ?? '';
1435 if (hideEvent != '') {
1436 // to sure click events finished.
1437 setTimeout(function () {
1438 document.dispatchEvent(new Event(hideEvent));
1439 }, 200);
1440 }
1441 });
1442
1443 jQuery('.mainwp-selecter-showhide-elements').on('change', function () {
1444 let hiel = $(this).attr('hide-parent');
1445 let hival = $(this).attr('hide-value');
1446 hival = hival.split(';'); // support multi hide values.
1447 let selectedval = $(this).val();
1448 mainwp_showhide_elements(hiel, hival.includes(selectedval));
1449 });
1450 });
1451
1452 function mainwp_showhide_elements(attEl, valHi) {
1453 // support multi attr to hide.
1454 if (valHi) {
1455 attEl.split(';').forEach(function (att) {
1456 jQuery('[hide-element=' + att.trim() + ']').fadeOut(300);
1457 jQuery('[hide-sub-element=' + att.trim() + ']').fadeOut(300);
1458 });
1459 } else {
1460 attEl.split(';').forEach(function (att) {
1461 jQuery('[hide-element=' + att.trim() + ']').fadeIn(300);
1462 jQuery('[hide-sub-element=' + att.trim() + ']').fadeIn(300);
1463 });
1464 }
1465 }
1466
1467
1468 jQuery(function ($) {
1469 $('#mainwp_settings_verify_connection_method').on('change', function () {
1470 let selectedval = $(this).val();
1471 if (selectedval == 2) { // phpseclib.
1472 $('.mainwp-hide-elemenent-sign-algo').fadeOut(200);
1473 } else {
1474 $('.mainwp-hide-elemenent-sign-algo').fadeIn(200);
1475 }
1476 });
1477
1478 $('#mainwp_managesites_edit_verify_connection_method').on('change', function () {
1479 let selectedval = $(this).val();
1480 if (selectedval == 2 || selectedval == 3) { // phpseclib.
1481 $('.mainwp-hide-elemenent-sign-algo').fadeOut(200);
1482 } else {
1483 $('.mainwp-hide-elemenent-sign-algo').fadeIn(200);
1484 }
1485 });
1486
1487
1488 $('#mainwp_managesites_edit_openssl_alg').on('change', function () {
1489 let selectedval = $(this).val();
1490 if (selectedval == 1) {
1491 $('.mainwp-hide-elemenent-sign-algo-note').fadeIn(200);
1492 } else {
1493 $('.mainwp-hide-elemenent-sign-algo-note').fadeOut(200);
1494 }
1495 });
1496
1497 $('#mainwp_settings_openssl_alg').on('change', function () {
1498 let selectedval = $(this).val();
1499 if (selectedval == 1) {
1500 $('.mainwp-hide-elemenent-sign-algo-note').fadeIn(200);
1501 } else {
1502 $('.mainwp-hide-elemenent-sign-algo-note').fadeOut(200);
1503 }
1504 });
1505
1506 })
1507
1508 jQuery(function () {
1509 jQuery(document).on('change', '#mainwp_managesites_add_wpurl', function () {
1510 let url = jQuery('#mainwp_managesites_add_wpurl').val().trim();
1511 let protocol = jQuery('#mainwp_managesites_add_wpurl_protocol').val();
1512
1513 if (url.lastIndexOf('http://') === 0) {
1514 protocol = 'http';
1515 url = url.substring(7);
1516 } else if (url.lastIndexOf('https://') === 0) {
1517 protocol = 'https';
1518 url = url.substring(8);
1519 }
1520
1521 if (jQuery('#mainwp_managesites_add_wpname').val() == '') {
1522 jQuery('#mainwp_managesites_add_wpname').val(url);
1523 }
1524 jQuery('#mainwp_managesites_add_wpurl').val(url);
1525 jQuery('#mainwp_managesites_add_wpurl_protocol').val(protocol).trigger("change");
1526 });
1527
1528 // Trigger the single site reconnect process
1529 jQuery('.mainwp-manage-wpsites-table').on('click', '.mainwp_site_reconnect', function () {
1530 mainwp_managesites_reconnect(jQuery(this));
1531 return false;
1532 });
1533
1534 jQuery('#mainwp-sites-previews').on('click', '.mainwp_site_card_reconnect', function () {
1535 mainwp_managesites_cards_reconnect(jQuery(this));
1536 return false;
1537 });
1538
1539 jQuery('.mainwp-updates-overview-reconnect-site').on('click', function () {
1540 mainwp_site_overview_reconnect(jQuery(this));
1541 return false;
1542 });
1543
1544 jQuery(".chk-sync-install-plugin").on('change', function () {
1545 let parent = jQuery(this).closest('.sync-ext-row');
1546 let opts = parent.find(".sync-options input[type='checkbox']");
1547 if (jQuery(this).is(':checked')) {
1548 opts.prop("checked", true);
1549 } else {
1550 opts.prop("checked", false);
1551 ///opts.attr( "disabled", "disabled" );
1552 }
1553 });
1554
1555 managesites_init();
1556 });
1557
1558 jQuery(document).on('change', '#mainwp_managesites_verify_installed_child', function () {
1559 if (jQuery(this).is(':checked')) {
1560 jQuery('#mainwp_message_verify_installed_child').hide();
1561 }
1562 });
1563
1564 globalThis.managesites_init = function () {
1565 mainwp_set_message_zone('#mainwp-message-zone');
1566 jQuery('.sync-ext-row span.status').html('');
1567 jQuery('.sync-ext-row span.status').css('color', '#0073aa');
1568 };
1569
1570 let mainwp_site_overview_reconnect = function (pElement) {
1571 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + 'Trying to reconnect. Please wait...', '');
1572 let data = mainwp_secure_data({
1573 action: 'mainwp_reconnectwp',
1574 siteid: pElement.attr('siteid')
1575 });
1576
1577 jQuery.post(ajaxurl, data, function () {
1578 return function (response) {
1579 response = response.trim();
1580 if (response.substring(0, 5) == 'ERROR') {
1581 let error;
1582 if (response.length == 5) {
1583 error = 'Undefined error! Please try again. If the process keeps failing, please review <a href="https://docs.mainwp.com/">MainWP Knowledgebase</a>, and if you still have issues, please let us know in the <a href="https://community.mainwp.com/c/community-support/5">MainWP Community</a>.'; // NOSONAR - noopener - open safe.
1584 feedback('mainwp-message-zone', error, 'red');
1585 } else {
1586 error = response.substring(6);
1587 let err = mainwp_js_get_error_not_detected_connect(error, 'html_msg', 'mainwp-message-zone');
1588 if (false === err) {
1589 feedback('mainwp-message-zone', error, 'red'); // it is not json error string.
1590 }
1591 }
1592 } else if ('reconnect_failed' === response) {
1593 mainwp_set_message_zone('#mainwp-message-zone');
1594
1595 jQuery('#mainwp-reconnect-site-with-user-passwd-modal').modal({
1596 onHide: function () {
1597 mainwp_forceReload();
1598 },
1599 closable: false
1600 }).modal('show');
1601 jQuery('#mainwp_managesites_add_wpadmin').val(pElement.attr('adminuser'));
1602 jQuery(document).on('click', '#mainwp-popup-reconnect-site-btn', function () {
1603 mainwp_reconnect_with_pw(pElement.attr('siteid'));
1604 return false;
1605 });
1606 } else {
1607 mainwp_set_message_zone('#mainwp-message-zone');
1608 mainwp_forceReload();
1609 }
1610 }
1611 }());
1612 };
1613
1614 let mainwp_reconnect_with_pw = function (siteid) {
1615 mainwp_set_message_zone('#mainwp-message-zone-reconnect');
1616 let errors = [];
1617 if (jQuery('#mainwp_managesites_add_wpadmin').val().trim() == '') {
1618 errors.push('Please enter a username of the website administrator.');
1619 }
1620
1621 if (jQuery('#mainwp_managesites_add_admin_pwd').val().trim() == '') {
1622 errors.push('Please enter password of the website administrator.');
1623 }
1624
1625 if (errors.length > 0) {
1626 mainwp_set_message_zone('#mainwp-message-zone-reconnect', errors.join('</br>'), 'red');
1627 return;
1628 }
1629
1630 mainwp_set_message_zone('#mainwp-message-zone-reconnect', '<i class="notched circle loading icon"></i> ' + 'Trying to reconnect. Please wait...', 'green');
1631 let data = mainwp_secure_data({
1632 action: 'mainwp_reconnectwp',
1633 managesites_add_wpadmin: jQuery('#mainwp_managesites_add_wpadmin').val(),
1634 managesites_add_adminpwd: encodeURIComponent(jQuery('#mainwp_managesites_add_admin_pwd').val()),
1635 siteid: siteid
1636 });
1637
1638 jQuery.post(ajaxurl, data, function (response) {
1639 response = response.trim();
1640 mainwp_set_message_zone('#mainwp-message-zone-reconnect');
1641 if (response.substring(0, 5) == 'ERROR') {
1642 let error;
1643 if (response.length == 5) {
1644 error = 'Undefined error! Please try again. If the process keeps failing, please review this <a href="https://docs.mainwp.com/troubleshooting/potential-issues">Knowledgebase document</a>, and if you still have issues, please let us know in the <a href="https://community.mainwp.com/c/community-support/5">MainWP Community</a>.'; // NOSONAR - noopener - open safe.
1645 mainwp_set_message_zone('#mainwp-message-zone-reconnect', error, 'red');
1646 } else {
1647 error = response.substring(6);
1648 let err = mainwp_js_get_error_not_detected_connect(error, 'html_msg', 'mainwp-message-zone-reconnect');
1649 if (false === err) {
1650 mainwp_set_message_zone('#mainwp-message-zone-reconnect', error, 'red'); // it is not json error string.
1651 }
1652 }
1653 } else if ('reconnect_failed' === response) {
1654 // do not show reconnect popup again.
1655 mainwp_set_message_zone('#mainwp-message-zone-reconnect', mainwp_get_reconnect_error(response, siteid), 'red');
1656 } else {
1657 mainwp_set_message_zone('#mainwp-message-zone-reconnect', response, 'green');
1658 mainwp_forceReload();
1659 }
1660 });
1661 };
1662
1663
1664 let mainwp_managesites_reconnect = function (pElement) {
1665 let wrapElement = pElement.closest('tr');
1666 wrapElement.html('<td colspan="999"><i class="notched circle loading icon"></i> ' + 'Trying to reconnect. Please wait...' + '</td>');
1667 let siteid = wrapElement.attr('siteid');
1668 let data = mainwp_secure_data({
1669 action: 'mainwp_reconnectwp',
1670 siteid: siteid
1671 });
1672
1673 jQuery.post(ajaxurl, data, function (pWrapElement) {
1674 return function (response) {
1675 response = response.trim();
1676 pWrapElement.hide(); // hide reconnect item
1677 if (response.substring(0, 5) == 'ERROR') {
1678 let error;
1679 if (response.length == 5) {
1680 error = 'Undefined error! Please try again. If the process keeps failing, please review this <a href="https://docs.mainwp.com/troubleshooting/potential-issues">Knowledgebase document</a>, and if you still have issues, please let us know in the <a href="https://community.mainwp.com/c/community-support/5">MainWP Community</a>.'; // NOSONAR - noopener - open safe.
1681 feedback('mainwp-message-zone', error, 'red');
1682 } else {
1683 error = response.substring(6);
1684 let err = mainwp_js_get_error_not_detected_connect(error, 'html_msg', 'mainwp-message-zone');
1685 if (false === err) {
1686 feedback('mainwp-message-zone', error, 'red'); // it is not json error string.
1687 }
1688 }
1689 } else if ('reconnect_failed' === response) {
1690 feedback('mainwp-message-zone', mainwp_get_reconnect_error(response, siteid), 'error');
1691 } else {
1692 feedback('mainwp-message-zone', response, 'green');
1693 }
1694 setTimeout(function () {
1695 mainwp_forceReload();
1696 }, 6000);
1697 }
1698
1699 }(wrapElement));
1700 };
1701
1702 let mainwp_managesites_cards_reconnect = function (element) {
1703 element.html('<i class="notched loading circle icon"></i> Reconnecting...');
1704 let siteid = element.attr('site-id');
1705 let data = mainwp_secure_data({
1706 action: 'mainwp_reconnectwp',
1707 siteid: siteid
1708 });
1709
1710 jQuery.post(ajaxurl, data, function (element) {
1711 return function (response) {
1712 response = response.trim();
1713 element.hide();
1714 if (response.substring(0, 5) == 'ERROR') {
1715 let error;
1716 if (response.length == 5) {
1717 error = 'Undefined error! Please try again. If the process keeps failing, please review this <a href="https://docs.mainwp.com/troubleshooting/potential-issues">Knowledgebase document</a>, and if you still have issues, please let us know in the <a href="https://community.mainwp.com/c/community-support/5">MainWP Community</a>.'; // NOSONAR - noopener - open safe.
1718 feedback('mainwp-message-zone', error, 'red');
1719 } else {
1720 error = response.substring(6);
1721 let err = mainwp_js_get_error_not_detected_connect(error, 'html_msg', 'mainwp-message-zone');
1722 if (false === err) {
1723 feedback('mainwp-message-zone', error, 'red'); // it is not json error string.
1724 }
1725 }
1726 } else if ('reconnect_failed' === response) {
1727 feedback('mainwp-message-zone', mainwp_get_reconnect_error(response, siteid), 'error');
1728 } else {
1729 feedback('mainwp-message-zone', response, 'green');
1730 }
1731 setTimeout(function () {
1732 mainwp_forceReload();
1733 }, 6000);
1734 }
1735
1736 }(element));
1737 };
1738
1739 // Connect a new website
1740 let mainwp_managesites_add = function () {
1741
1742 managesites_init();
1743
1744 let valid_input = mainwp_managesites_add_valid();
1745
1746 if (!valid_input) {
1747 return;
1748 }
1749
1750 feedback('mainwp-message-zone', __('Adding the site to your MainWP Dashboard. Please wait...'), 'green');
1751
1752 jQuery('#mainwp_managesites_add').attr('disabled', 'true'); //disable button to add..
1753
1754 //Check if valid user & rulewp is installed?
1755 let url = jQuery('#mainwp_managesites_add_wpurl_protocol').val() + '://' + jQuery('#mainwp_managesites_add_wpurl').val().trim();
1756
1757 if (!url.endsWith('/')) {
1758 url += '/';
1759 }
1760
1761 let name = jQuery('#mainwp_managesites_add_wpname').val().trim();
1762 name = name.replaceAll('"', '&quot;');
1763
1764 let data = mainwp_secure_data({
1765 action: 'mainwp_checkwp',
1766 name: name,
1767 url: url,
1768 admin: jQuery('#mainwp_managesites_add_wpadmin').val().trim(),
1769 verify_certificate: jQuery('#mainwp_managesites_verify_certificate').is(':checked') ? 1 : 0,
1770 ssl_version: jQuery('#mainwp_managesites_add_ssl_version').val(),
1771 http_user: jQuery('#mainwp_managesites_add_http_user').val().trim(),
1772 http_pass: jQuery('#mainwp_managesites_add_http_pass').val().trim()
1773 });
1774
1775 jQuery.post(ajaxurl, data, function (res_things) { // NOSONAR - function complexity.
1776 let response = res_things.response;
1777 response = response.trim();
1778 let errors = [];
1779 let url = jQuery('#mainwp_managesites_add_wpurl_protocol').val() + '://' + jQuery('#mainwp_managesites_add_wpurl').val().trim();
1780 if (!url.endsWith('/')) {
1781 url += '/';
1782 }
1783
1784 url = url.replaceAll('"', '&quot;');
1785
1786 let show_resp = __('Click %1here%2 to see response from the child site.', '<a href="javascript:void(0)" class="mainwp-show-response">', '</a>');
1787
1788 let resp_data = res_things.resp_data ? res_things.resp_data : '';
1789 if ('0' == resp_data) {
1790 resp_data = '';
1791 }
1792 jQuery('#mainwp-response-data-container').attr('resp-data', resp_data);
1793
1794 if (response == 'HTTPERROR') {
1795 errors.push(__('This site can not be reached! Please use the Test Connection feature and see if the positive response will be returned. For additional help, please review this <a href="https://docs.mainwp.com/troubleshooting/potential-issues/">Knowledgebase document</a>, and if you still have issues, please let us know in the <a href="https://managers.mainwp.com/c/community-support/5">MainWP Community</a>.')); // NOSONAR - noopener - open safe.
1796 } else if (response == 'NOMAINWP') {
1797 errors.push(mainwp_js_get_error_not_detected_connect());
1798 } else if (response.substring(0, 5) == 'ERROR') {
1799 if (response.length == 5) {
1800 errors.push(__('Undefined error occurred. Please try again. If the issue does not resolve, please review this <a href="https://docs.mainwp.com/troubleshooting/potential-issues/">Knowledgebase document</a>, and if you still have issues, please let us know in the <a href="https://managers.mainwp.com/c/community-support/5">MainWP Community</a>.')); // NOSONAR - noopener - open safe.
1801 } else {
1802 errors.push(__('Error detected: ') + response.substring(6));
1803 }
1804 } else if (response == 'OK') {
1805 jQuery('#mainwp_managesites_add').attr('disabled', 'true'); //Disable add button
1806
1807 let name = jQuery('#mainwp_managesites_add_wpname').val();
1808 name = name.replaceAll('"', '&quot;');
1809 let group_ids = jQuery('#mainwp_managesites_add_addgroups').dropdown('get value');
1810 let client_id = jQuery('#mainwp_managesites_add_client_id').length ? jQuery('#mainwp_managesites_add_client_id').dropdown('get value') : 0;
1811 let data = mainwp_secure_data({
1812 action: 'mainwp_addwp',
1813 managesites_add_wpname: name,
1814 managesites_add_wpurl: url,
1815 managesites_add_wpadmin: jQuery('#mainwp_managesites_add_wpadmin').val(),
1816 managesites_add_adminpwd: encodeURIComponent(jQuery('#mainwp_managesites_add_admin_pwd').val().trim()),
1817 managesites_add_uniqueId: jQuery('#mainwp_managesites_add_uniqueId').val(),
1818 ssl_verify: jQuery('#mainwp_managesites_verify_certificate').is(':checked') ? 1 : 0,
1819 ssl_version: jQuery('#mainwp_managesites_add_ssl_version').val(),
1820 groupids: group_ids,
1821 clientid: client_id,
1822 selected_icon: jQuery('#mainwp_managesites_add_site_select_icon_hidden').val(),
1823 cust_color: jQuery('#mainwp_managesites_add_site_color').val(),
1824 uploaded_icon: jQuery('#mainwp_managesites_add_site_uploaded_icon_hidden').val(),
1825 managesites_add_http_user: jQuery('#mainwp_managesites_add_http_user').val(),
1826 managesites_add_http_pass: jQuery('#mainwp_managesites_add_http_pass').val(),
1827 });
1828
1829 // to support add client reports tokens values
1830 jQuery("input[name^='creport_token_']").each(function () {
1831 let tname = jQuery(this).attr('name');
1832 let tvalue = jQuery(this).val();
1833 data[tname] = tvalue;
1834 });
1835
1836 // support hooks fields
1837 jQuery(".mainwp_addition_fields_addsite input").each(function () {
1838 let tname = jQuery(this).attr('name');
1839 let tvalue = jQuery(this).val();
1840 data[tname] = tvalue;
1841 });
1842
1843 jQuery.post(ajaxurl, data, function (res_things) {
1844 let site_id = 0;
1845 if (res_things.error) {
1846 response = 'Error detected: ' + res_things.error;
1847 } else {
1848 response = res_things.response;
1849 site_id = res_things.siteid;
1850 }
1851 response = response.trim();
1852 managesites_init();
1853
1854 resp_data = res_things.resp_data ? res_things.resp_data : '';
1855 if ('0' == resp_data) {
1856 resp_data = '';
1857 }
1858 jQuery('#mainwp-response-data-container').attr('resp-data', resp_data);
1859
1860 if (response.substring(0, 5) == 'ERROR') {
1861 mainwp_set_message_zone('#mainwp-message-zone', '', '', true);
1862 feedback('mainwp-message-zone', response.substring(6) + (resp_data == '' ? '' : '<br>' + show_resp), 'red');
1863 } else {
1864 mainwp_set_message_zone('#mainwp-message-zone', '', '', true);
1865 feedback('mainwp-message-zone', response, 'green');
1866
1867 if (site_id > 0) {
1868 jQuery('.sync-ext-row').attr('status', 'queue');
1869 setTimeout(function () {
1870 mainwp_managesites_sync_extension_start_next(site_id);
1871 }, 1000);
1872 }
1873
1874 //Reset fields
1875 jQuery('#mainwp_managesites_add_wpname').val('');
1876 jQuery('#mainwp_managesites_add_wpurl').val('');
1877 jQuery('#mainwp_managesites_add_wpurl_protocol').val('https');
1878 jQuery('#mainwp_managesites_add_wpadmin').val('');
1879 jQuery('#mainwp_managesites_add_admin_pwd').val('');
1880 jQuery('#mainwp_managesites_add_uniqueId').val('');
1881 jQuery('#mainwp_managesites_add_addgroups').dropdown('clear');
1882 jQuery('#mainwp_managesites_verify_certificate').val(1);
1883
1884 jQuery("input[name^='creport_token_']").each(function () {
1885 jQuery(this).val('');
1886 });
1887
1888 // support hooks fields
1889 jQuery(".mainwp_addition_fields_addsite input").each(function () {
1890 jQuery(this).val('');
1891 });
1892 }
1893
1894 jQuery('#mainwp_managesites_add').prop("disabled", false); //Enable add button
1895 }, 'json');
1896 }
1897 if (errors.length > 0) {
1898 mainwp_set_message_zone('#mainwp-message-zone', '', '', true);
1899 managesites_init();
1900 jQuery('#mainwp_managesites_add').prop("disabled", false); //Enable add button
1901 if (resp_data != '') {
1902 errors.push(show_resp);
1903 }
1904 feedback('mainwp-message-zone', errors.join('<br />'), 'red');
1905 }
1906 }, 'json');
1907 };
1908
1909 let mainwp_managesites_add_valid = function () {
1910
1911 if (jQuery('#mainwp_managesites_verify_installed_child').is(':checked')) {
1912 jQuery('#mainwp_message_verify_installed_child').hide();
1913 } else {
1914 jQuery('#mainwp_message_verify_installed_child').show();
1915 scrollElementTop('mainwp_message_verify_installed_child');
1916 return false;
1917 }
1918
1919 let errors = [];
1920
1921 if (jQuery('#mainwp_managesites_add_wpname').val().trim() == '') {
1922 errors.push(__('Please enter a name for the website.'));
1923 }
1924 if (jQuery('#mainwp_managesites_add_wpurl').val().trim() == '') {
1925 errors.push(__('Please enter a valid URL for your site.'));
1926 } else {
1927 let url = jQuery('#mainwp_managesites_add_wpurl').val().trim();
1928 if (!url.endsWith('/')) {
1929 url += '/';
1930 }
1931
1932 jQuery('#mainwp_managesites_add_wpurl').val(url);
1933
1934 if (!isUrl(jQuery('#mainwp_managesites_add_wpurl_protocol').val() + '://' + jQuery('#mainwp_managesites_add_wpurl').val())) {
1935 errors.push(__('Please enter a valid URL for your site.'));
1936 }
1937 }
1938 if (jQuery('#mainwp_managesites_add_wpadmin').val().trim() == '') {
1939 errors.push(__('Please enter a username of the website administrator.'));
1940 }
1941
1942 if (errors.length > 0) {
1943 feedback('mainwp-message-zone', errors.join('<br />'), 'yellow');
1944 return false;
1945 }
1946 return true;
1947 }
1948
1949
1950 let mainwp_managesites_sync_extension_start_next = function (siteId) {
1951 let pluginToInstall = jQuery('.sync-ext-row[status="queue"]:first')
1952 while (pluginToInstall && (pluginToInstall.length > 0) && (bulkInstallCurrentThreads < 1)) { // NOSONAR - modified outside the function, bulkInstallMaxThreads - to fix install plugins and apply settings failed issue.
1953 pluginToInstall.attr('status', 'progress');
1954 mainwp_managesites_sync_extension_start_specific(pluginToInstall, siteId);
1955 pluginToInstall = jQuery('.sync-ext-row[status="queue"]:first');
1956 }
1957
1958 if ((pluginToInstall.length == 0) && (bulkInstallCurrentThreads == 0)) { // NOSONAR - modified outside the function.
1959 jQuery('#mwp_applying_ext_settings').remove();
1960 }
1961 };
1962
1963 let mainwp_managesites_sync_extension_start_specific = function (pPluginToInstall, pSiteId) {
1964 let syncGlobalSettings = pPluginToInstall.find(".sync-global-options input[type='checkbox']:checked").length > 0;
1965 let install_plugin = pPluginToInstall.find(".sync-install-plugin input[type='checkbox']:checked").length > 0;
1966 let apply_settings = pPluginToInstall.find(".sync-options input[type='checkbox']:checked").length > 0;
1967
1968 if (syncGlobalSettings) {
1969 mainwp_extension_apply_plugin_settings(pPluginToInstall, pSiteId, true);
1970 } else if (install_plugin) {
1971 mainwp_extension_prepareinstallplugin(pPluginToInstall, pSiteId);
1972 } else if (apply_settings) {
1973 mainwp_extension_apply_plugin_settings(pPluginToInstall, pSiteId, false);
1974 } else {
1975 mainwp_managesites_sync_extension_start_next(pSiteId);
1976 return;
1977 }
1978 };
1979
1980 let mainwp_extension_prepareinstallplugin = function (pPluginToInstall, pSiteId) {
1981 let site_Ids = [];
1982 site_Ids.push(pSiteId);
1983 bulkInstallCurrentThreads++;
1984 let plugin_slug = pPluginToInstall.find(".sync-install-plugin").attr('slug');
1985 let workingEl = pPluginToInstall.find(".sync-install-plugin i");
1986 let statusEl = pPluginToInstall.find(".sync-install-plugin span.status");
1987
1988 let data = {
1989 action: 'mainwp_ext_prepareinstallplugintheme',
1990 type: 'plugin',
1991 slug: plugin_slug,
1992 'selected_sites[]': site_Ids,
1993 selected_by: 'site',
1994 };
1995
1996 workingEl.show();
1997 statusEl.html(__('Preparing for installation...'));
1998
1999 jQuery.post(ajaxurl, data, function (response) {
2000 workingEl.hide();
2001 if (response?.sites[pSiteId] === undefined) {
2002 statusEl.css('color', 'red');
2003 statusEl.html(__('Error while preparing the installation. Please, try again.'));
2004 bulkInstallCurrentThreads--;
2005 } else {
2006 statusEl.html(__('Installing...'));
2007 let data = mainwp_secure_data({
2008 action: 'mainwp_ext_performinstallplugintheme',
2009 type: 'plugin',
2010 url: response.url,
2011 siteId: pSiteId,
2012 activatePlugin: true,
2013 overwrite: false,
2014 });
2015 workingEl.show();
2016 jQuery.post(ajaxurl, data, function (response) {
2017 workingEl.hide();
2018 let apply_settings = false;
2019 let syc_msg = '';
2020 let _success = false;
2021 if ((response?.ok[pSiteId] != undefined)) {
2022 syc_msg = __('Installation successful!');
2023 statusEl.html(syc_msg);
2024 apply_settings = pPluginToInstall.find(".sync-options input[type='checkbox']:checked").length > 0;
2025 if (apply_settings) {
2026 mainwp_extension_apply_plugin_settings(pPluginToInstall, pSiteId, false);
2027 }
2028 _success = true;
2029 } else if (response?.errors[pSiteId] === undefined) {
2030 syc_msg = __('Installation failed!');
2031 statusEl.html(syc_msg);
2032 statusEl.css('color', 'red');
2033 } else {
2034 syc_msg = __('Installation failed!') + ': ' + response.errors[pSiteId][1];
2035 statusEl.html(syc_msg);
2036 statusEl.css('color', 'red');
2037 }
2038
2039 if (syc_msg != '') {
2040 if (_success)
2041 syc_msg = '<span style="color:#0073aa">' + syc_msg + '!</span>';
2042 else
2043 syc_msg = '<span style="color:red">' + syc_msg + '!</span>';
2044 jQuery('#mainwp-message-zone').append('<br/>' + pPluginToInstall.find(".sync-install-plugin").attr('plugin_name') + ' ' + syc_msg);
2045 }
2046
2047 if (!apply_settings) {
2048 bulkInstallCurrentThreads--;
2049 mainwp_managesites_sync_extension_start_next(pSiteId);
2050 }
2051 }, 'json');
2052 }
2053 }, 'json');
2054 }
2055
2056 let mainwp_extension_apply_plugin_settings = function (pPluginToInstall, pSiteId, pGlobal) {
2057 let extSlug = pPluginToInstall.attr('slug');
2058 let workingEl = pPluginToInstall.find(".options-row i");
2059 let statusEl = pPluginToInstall.find(".options-row span.status");
2060 if (pGlobal)
2061 bulkInstallCurrentThreads++;
2062
2063 let data = mainwp_secure_data({
2064 action: 'mainwp_ext_applypluginsettings',
2065 ext_dir_slug: extSlug,
2066 siteId: pSiteId
2067 });
2068
2069 workingEl.show();
2070 statusEl.html(__('Applying settings...'));
2071 jQuery.post(ajaxurl, data, function (response) { // NOSONAR - complex.
2072 workingEl.hide();
2073 let syc_msg = '';
2074 let _success = false;
2075 if (response) {
2076 if (response.result && response.result == 'success') {
2077 let msg = '';
2078 if (response.message != undefined) {
2079 msg = ' ' + response.message;
2080 }
2081 statusEl.html(__('Applying settings successful!') + msg);
2082 syc_msg = __('Successful');
2083 _success = true
2084 } else if (response.error === undefined) {
2085 statusEl.html(__('Applying settings failed!'));
2086 statusEl.css('color', 'red');
2087 syc_msg = __('failed');
2088 } else {
2089 statusEl.html(response.error);
2090 statusEl.css('color', 'red');
2091 syc_msg = response.error;
2092 }
2093 } else {
2094 statusEl.html(__('Undefined error!'));
2095 statusEl.css('color', 'red');
2096 syc_msg = __('failed');
2097 }
2098
2099 if (syc_msg != '') {
2100 if (_success)
2101 syc_msg = '<span style="color:#0073aa">' + syc_msg + '!</span>';
2102 else
2103 syc_msg = '<span style="color:red">' + syc_msg + '!</span>';
2104 if (pGlobal) {
2105 syc_msg = __('Apply global %1 options', pPluginToInstall.attr('ext_name')) + ' ' + syc_msg;
2106 } else {
2107 syc_msg = __('Apply %1 settings', pPluginToInstall.find('.sync-install-plugin').attr('plugin_name')) + ' ' + syc_msg;
2108 }
2109 jQuery('#mainwp-message-zone').append('<br/>' + syc_msg);
2110 }
2111 bulkInstallCurrentThreads--;
2112 mainwp_managesites_sync_extension_start_next(pSiteId);
2113 }, 'json');
2114 }
2115
2116 // Test Connection (Add Site Page)
2117 let mainwp_managesites_test = function () {
2118
2119 let errors = [];
2120
2121 if (jQuery('#mainwp_managesites_add_wpurl').val().trim() == '') {
2122 errors.push(__('Please enter a valid URL for your site.'));
2123 } else {
2124 let clean_url = jQuery('#mainwp_managesites_add_wpurl').val().trim();
2125 let protocol = jQuery('#mainwp_managesites_add_wpurl_protocol').val();
2126 let url = protocol + '://' + clean_url;
2127 if (!url.endsWith('/')) {
2128 url += '/';
2129 }
2130
2131 if (!isUrl(url)) {
2132 errors.push(__('Please enter a valid URL for your site'));
2133 }
2134 }
2135
2136 if (errors.length > 0) {
2137 feedback('mainwp-message-zone', errors.join('<br />'), 'red');
2138 } else {
2139 jQuery('#mainwp-test-connection-modal').modal('setting', 'closable', false).modal('show');
2140 jQuery('#mainwp-test-connection-modal .dimmer').show();
2141 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').hide();
2142
2143 let clean_url = jQuery('#mainwp_managesites_add_wpurl').val().trim();
2144 let protocol = jQuery('#mainwp_managesites_add_wpurl_protocol').val();
2145 let url = protocol + '://' + clean_url;
2146
2147 if (!url.endsWith('/')) {
2148 url += '/';
2149 }
2150
2151 let data = mainwp_secure_data({
2152 action: 'mainwp_testwp',
2153 url: url,
2154 test_verify_cert: jQuery('#mainwp_managesites_verify_certificate').is(':checked') ? 1 : 0,
2155 ssl_version: jQuery('#mainwp_managesites_add_ssl_version').val(),
2156 http_user: jQuery('#mainwp_managesites_add_http_user').val(),
2157 http_pass: jQuery('#mainwp_managesites_add_http_pass').val()
2158 });
2159
2160 jQuery.post(ajaxurl, data, function (response) { // NOSONAR - complex.
2161 jQuery('#mainwp-test-connection-modal .dimmer').hide();
2162 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').removeClass('red green check times');
2163 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html('');
2164 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html('');
2165 if (response.error) {
2166 if (response.httpCode) {
2167 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2168 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2169 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection failed!'));
2170 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + ' - ' + __('HTTP-code:') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : '') + ' - ' + __('Error message: ') + ' ' + response.error);
2171 } else {
2172 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2173 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2174 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2175 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('Error message:') + ' ' + response.error);
2176 }
2177 } else if (response.httpCode) {
2178 if (response.httpCode == '200') {
2179 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2180 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('green check');
2181 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection successful!'));
2182 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + (response.ip === undefined ? '' : ' (IP: ' + response.ip + ')') + ' - ' + __('Received HTTP-code') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : ''));
2183 } else {
2184 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2185 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2186 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2187 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + (response.ip === undefined ? '' : ' (IP: ' + response.ip + ')') + ' - ' + __('Received HTTP-code:') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : ''));
2188 }
2189 } else {
2190 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show('');
2191 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2192 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2193 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('Invalid response from the server, please try again.'));
2194 }
2195 }, 'json');
2196 }
2197 };
2198
2199 // Test Connection (Edit Site Page)
2200 let mainwp_managesites_edit_test = function () {
2201
2202 let clean_url = jQuery('#mainwp_managesites_edit_siteurl').val();
2203 let protocol = jQuery('#mainwp_managesites_edit_siteurl_protocol').val();
2204 let with_www = jQuery('input[name=mainwp_managesites_edit_wpurl_with_www]').val();
2205 with_www = with_www === 'www' ? with_www + '.' : '';
2206
2207 let url = protocol + '://' + with_www + clean_url;
2208
2209 if (!url.endsWith('/')) {
2210 url += '/';
2211 }
2212
2213 jQuery('#mainwp-test-connection-modal').modal('setting', 'closable', false).modal('show');
2214 jQuery('#mainwp-test-connection-modal .dimmer').show();
2215 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').hide();
2216
2217 let data = mainwp_secure_data({
2218 action: 'mainwp_testwp',
2219 url: url,
2220 test_verify_cert: jQuery('#mainwp_managesites_edit_verifycertificate').val(),
2221 ssl_version: jQuery('#mainwp_managesites_edit_ssl_version').val(),
2222 http_user: jQuery('#mainwp_managesites_edit_http_user').val(),
2223 http_pass: jQuery('#mainwp_managesites_edit_http_pass').val()
2224 });
2225
2226 jQuery.post(ajaxurl, data, function (response) { // NOSONAR - complex.
2227 jQuery('#mainwp-test-connection-modal .dimmer').hide();
2228 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').removeClass('red green check times');
2229 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html('');
2230 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html('');
2231 if (response.error) {
2232 if (response.httpCode) {
2233 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2234 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2235 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection failed!'));
2236 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + ' - ' + __('HTTP-code:') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : '') + ' - ' + __('Error message: ') + ' ' + response.error);
2237 } else {
2238 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2239 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2240 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2241 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('Error message:') + ' ' + response.error);
2242 }
2243 } else if (response.httpCode) {
2244 if (response.httpCode == '200') {
2245 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2246 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('green check');
2247 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection successful!'));
2248 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + (response.ip === undefined ? '' : ' (IP: ' + response.ip + ')') + ' - ' + __('Received HTTP-code') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : ''));
2249 } else {
2250 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show();
2251 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2252 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2253 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('URL:') + ' ' + response.host + (response.ip === undefined ? '' : ' (IP: ' + response.ip + ')') + ' - ' + __('Received HTTP-code:') + ' ' + response.httpCode + (response.httpCodeString ? ' (' + response.httpCodeString + ')' : ''));
2254 }
2255 } else {
2256 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result').show('');
2257 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result i').addClass('red times');
2258 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content span').html(__('Connection test failed.'));
2259 jQuery('#mainwp-test-connection-modal .content #mainwp-test-connection-result .content .sub.header').html(__('Invalid response from the server, please try again.'));
2260 }
2261 }, 'json');
2262 };
2263
2264 let managesites_remove = function (obj) {
2265 managesites_init();
2266
2267 let name = jQuery(obj).attr('site-name');
2268 let id = jQuery(obj).attr('site-id');
2269
2270 let msg = __('Are you sure you want to remove', 'mainwp') + ' ' + name + ' ' + __('from your MainWP Dashboard?', 'mainwp');
2271
2272 mainwp_confirm(msg, function () {
2273 jQuery('tr#child-site-' + id).html('<td colspan="999"><i class="notched circle loading icon"></i> ' + 'Removing and deactivating the MainWP Child plugin! Please wait...' + '</td>');
2274 let data = mainwp_secure_data({
2275 action: 'mainwp_removesite',
2276 id: id
2277 });
2278
2279 jQuery.post(ajaxurl, data, function (response) {
2280
2281 managesites_init();
2282
2283 let result = '';
2284 let error = '';
2285
2286 if (response.error != undefined) {
2287 error = response.error;
2288 } else if (response.result == 'SUCCESS') {
2289 result = '<i class="close icon"></i>' + __('The site has been removed and the MainWP Child plugin has been disabled.');
2290 } else if (response.result == 'NOSITE') {
2291 error = '<i class="close icon"></i>' + __('The requested site has not been found.');
2292 } else {
2293 result = '<i class="close icon"></i>' + __('The site has been removed. Please make sure that the MainWP Child plugin has been deactivated properly.');
2294 }
2295
2296 if (error != '') {
2297 feedback('mainwp-message-zone', error, 'red');
2298 }
2299
2300 if (result != '') {
2301 feedback('mainwp-message-zone', result, 'green');
2302 }
2303
2304 jQuery('tr#child-site-' + id).remove();
2305
2306 }, 'json');
2307 }, false, false, false, 'REMOVE');
2308 return false;
2309 };
2310
2311 jQuery(function () {
2312
2313 jQuery(document).on('click', '#mainwp_managesites_add', function () {
2314 mainwp_managesites_add();
2315 });
2316
2317 // Hanlde click submit form import website
2318 jQuery(document).on('click', '#mainwp_managesites_bulkadd', function () {
2319
2320 let error_messages = mainwp_managesites_import_handle_form_before_submit();
2321 // If there is an error, prevent submission and display the error
2322 if (error_messages.length > 0) {
2323 feedback('mainwp-message-zone', error_messages.join("<br/>"), "red");
2324 } else {
2325 jQuery('#mainwp_managesites_bulkadd_form').submit();
2326 }
2327 return false;
2328 });
2329
2330 // Trigger Connection Test (Add Site Page)
2331 jQuery(document).on('click', '#mainwp_managesites_test', function () {
2332 mainwp_managesites_test();
2333 });
2334
2335 // Trigger Connection Test (Edit Site Page)
2336 jQuery(document).on('click', '#mainwp_managesites_edit_test', function () {
2337 mainwp_managesites_edit_test();
2338 });
2339
2340 // Handle submit add multi website
2341 jQuery(document).on('click', '#mainwp_managesites_add_multi_site', function () {
2342 let error_messages = [];
2343 let has_table_data = false;
2344 has_table_data = mainwp_managesites_validate_import_rows(error_messages, true);
2345 // If there is an error, prevent submission and display the error
2346 if (error_messages.length > 0 && !has_table_data) {
2347 feedback('mainwp-add-multi-new-site-message-zone', error_messages.join("<br/>"), "red");
2348 } else {
2349 jQuery('#mainwp_managesites_add_form').submit();
2350 }
2351 return false;
2352 });
2353
2354 // Handle click remove website on management webiste.
2355 jQuery(document).on('click', '#mainwp-managesites-remove-site', function () {
2356 jQuery('#mainwp-remove-site-button').trigger('click');
2357 });
2358 });
2359
2360 /**
2361 * Add new user
2362 */
2363 function mainwp_gen_passsword(len = 24) {
2364 const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+{}[]<>?';
2365 const arr = new Uint32Array(len);
2366 crypto.getRandomValues(arr);
2367 return Array.from(arr, x => chars[x % chars.length]).join('');
2368 }
2369
2370 jQuery('.mainwp-generate-password-button').on('click', function (e) {
2371 e.preventDefault();
2372 jQuery('#createuser #password, #mainwp-update-admin-password-form #password').val(mainwp_gen_passsword(24)).trigger('change');
2373 });
2374
2375 jQuery(function () {
2376 jQuery(document).on('click', '#bulk_add_createuser', function () {
2377 mainwp_createuser();
2378 });
2379 jQuery('#bulk_import_createuser').on('click', function () {
2380 mainwp_bulkupload_users();
2381 });
2382 });
2383
2384 let mainwp_createuser = function () {
2385 let cont = true;
2386 if (jQuery('#user_login').val() == '') {
2387 feedback('mainwp-message-zone', __('Username field is required! Please enter a username.'), 'yellow');
2388 cont = false;
2389 }
2390
2391 if (jQuery('#email').val() == '') {
2392 feedback('mainwp-message-zone', __('E-mail field is required! Please enter an email address.'), 'yellow');
2393 cont = false;
2394 }
2395
2396 if (jQuery('#password').val() == '') {
2397 feedback('mainwp-message-zone', __('Password field is required! Please enter the wanted password or generate a random one.'), 'yellow');
2398 cont = false;
2399 }
2400
2401 let selected_sites = [];
2402 let selected_clients = [];
2403 let selected_groups = [];
2404
2405 if (jQuery('input[name="select_by"]').val() == 'site') {
2406 jQuery("input[name='selected_sites[]']:checked").each(function () {
2407 selected_sites.push(jQuery(this).val());
2408 });
2409 if (selected_sites.length == 0) {
2410 feedback('mainwp-message-zone', __('Please select at least one website or group or client.'), 'yellow');
2411 cont = false;
2412 }
2413 } else if (jQuery('input[name="select_by"]').val() == 'client') {
2414 jQuery("input[name='selected_clients[]']:checked").each(function () {
2415 selected_clients.push(jQuery(this).val());
2416 });
2417 if (selected_clients.length == 0) {
2418 feedback('mainwp-message-zone', __('Please select at least one website or group or client.'), 'yellow');
2419 cont = false;
2420 }
2421 } else {
2422 jQuery("input[name='selected_groups[]']:checked").each(function () {
2423 selected_groups.push(jQuery(this).val());
2424 });
2425 if (selected_groups.length == 0) {
2426 feedback('mainwp-message-zone', __('Please select at least one website or group or client.'), 'yellow');
2427 cont = false;
2428 }
2429 }
2430
2431 if (cont) {
2432 mainwp_set_message_zone('#mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Creating the user. Please wait...'), '', true);
2433 jQuery('#bulk_add_createuser').attr('disabled', 'disabled');
2434 const is_send_password = jQuery('#send_password').is(':checked') ? 1 : 0;
2435 //Add user via ajax!!
2436 let data = mainwp_secure_data({
2437 action: "mainwp_bulkadduser",
2438 select_by: jQuery("input[name='select_by']").val(),
2439 "selected_groups[]": selected_groups,
2440 "selected_sites[]": selected_sites,
2441 "selected_clients[]": selected_clients,
2442 user_login: jQuery("#user_login").val(),
2443 email: jQuery("#email").val(),
2444 url: jQuery("#url").val(),
2445 first_name: jQuery("#first_name").val(),
2446 last_name: jQuery("#last_name").val(),
2447 pass1: jQuery("#password").val(),
2448 pass2: jQuery("#password").val(),
2449 send_password: is_send_password,
2450 role: jQuery("#role").val(),
2451 });
2452
2453 jQuery.post(ajaxurl, data, function (response) {
2454 response = response.trim();
2455 mainwp_set_message_zone('#mainwp-message-zone');
2456 jQuery('#bulk_add_createuser').prop("disabled", false);
2457 if (response.substring(0, 5) == 'ERROR') {
2458 let responseObj = JSON.parse(response.substring(6));
2459 if (responseObj.error == undefined) {
2460 let errorMessageList = responseObj[1];
2461 let errorMessage = '';
2462 for (let iem of errorMessageList) {
2463 if (errorMessage != '') {
2464 errorMessage = errorMessage + "<br />";
2465 }
2466 errorMessage = errorMessage + iem;
2467 }
2468 if (errorMessage != '') {
2469 feedback('mainwp-message-zone', errorMessage, 'red');
2470 }
2471 }
2472 } else {
2473 jQuery('#mainwp-add-new-user-form').append(response);
2474 jQuery('#mainwp-creating-new-user-modal').modal( {
2475 closable: false,
2476 } ).modal( 'show' );
2477 }
2478 });
2479 }
2480 };
2481
2482 /**
2483 * InstallPlugins/Themes
2484 */
2485 jQuery(function () {
2486 jQuery('#MainWPInstallBulkNavSearch').on('click', function (event) {
2487 event.preventDefault();
2488 jQuery('#mainwp_plugin_bulk_install_btn').attr('bulk-action', 'install');
2489 jQuery('.mainwp-bulk-install-showhide-content').hide();
2490 jQuery('.mainwp-browse-plugins').show();
2491 jQuery('#mainwp-search-plugins-form').show();
2492 jQuery('.mainwp-bulk-install-tabs-header-btn').removeClass('green');
2493 jQuery(this).addClass('green');
2494 });
2495 jQuery('#MainWPInstallBulkNavUpload').on('click', function (event) {
2496 event.preventDefault();
2497 jQuery('#mainwp_plugin_bulk_install_btn').attr('bulk-action', 'upload');
2498 jQuery('.mainwp-bulk-install-showhide-content').hide();
2499 jQuery('.mainwp-upload-plugin').show();
2500 jQuery('.mainwp-bulk-install-tabs-header-btn').removeClass('green');
2501 jQuery(this).addClass('green');
2502 });
2503
2504 // not used?
2505 jQuery(document).on('click', '.filter-links li.plugin-install a', function (event) {
2506 event.preventDefault();
2507 jQuery('.filter-links li.plugin-install a').removeClass('current');
2508 jQuery(this).addClass('current');
2509 let tab = jQuery(this).parent().attr('tab');
2510 if (tab == 'search') {
2511 mainwp_install_search(event);
2512 } else {
2513 jQuery('#mainwp_installbulk_s').val('');
2514 jQuery('#mainwp_installbulk_tab').val(tab);
2515 mainwp_install_plugin_tab_search('tab:' + tab);
2516 }
2517 });
2518
2519 jQuery(document).on('click', '#mainwp_plugin_bulk_install_btn', function () {
2520 let act = jQuery(this).attr('bulk-action');
2521 if (act == 'install') {
2522 let selected = jQuery("input[type='radio'][name='install-plugin']:checked");
2523 if (selected.length == 0) {
2524 feedback('mainwp-message-zone', __('Please select plugin to install files.'), 'yellow');
2525 } else {
2526 let selectedId = /^install-([^-]*)-(.*)$/.exec(selected.attr('id'));
2527 if (selectedId) {
2528 mainwp_install_bulk('plugin', selectedId[2], selected.attr('plugin-name'));
2529 }
2530 }
2531 } else if (act == 'upload') {
2532 mainwp_upload_bulk('plugins');
2533 }
2534
2535 return false;
2536 });
2537
2538 jQuery(document).on('click', '#mainwp_theme_bulk_install_btn', function () {
2539 let act = jQuery(this).attr('bulk-action');
2540 if (act == 'install') {
2541 let selected = jQuery("input[type='radio'][name='install-theme']:checked");
2542 if (selected.length == 0) {
2543 feedback('mainwp-message-zone', __('Please select theme to install files.'), 'yellow');
2544 } else {
2545 let selectedId = /^install-([^-]*)-(.*)$/.exec(selected.attr('id'));
2546 if (selectedId)
2547 mainwp_install_bulk('theme', selectedId[2], selected.attr('theme-name'));
2548 }
2549 } else if (act == 'upload') {
2550 mainwp_upload_bulk('themes');
2551 }
2552 return false;
2553 });
2554 });
2555
2556 // Generate the Go to WP Admin link
2557 globalThis.mainwp_links_visit_site_and_admin = function (url, siteId) {
2558 let links = '';
2559 if (url != '') {
2560 links += '<a href="' + url + '" target="_blank" class="mainwp-may-hide-referrer"><i class="external alternate icon"></i></a> ';
2561 }
2562 links += '<a href="admin.php?page=SiteOpen&newWindow=yes&websiteid=' + siteId + '&_opennonce=' + mainwpParams._wpnonce + '" target="_blank"><i class="sign in alternate icon"></i></a>';
2563 return links;
2564 }
2565
2566 mainwpVars.bulkInstallTotal = 0;
2567 bulkInstallDone = 0;
2568
2569 /**
2570 * Install Plugin/Theme from WP.org.
2571 *
2572 * Initiate the process.
2573 *
2574 * @param string type Plugin or theme.
2575 * @param string slug Plugin or theme slug.
2576 *
2577 * @return void
2578 */
2579 let mainwp_install_bulk = function (type, slug, name) {
2580 let data = mainwp_secure_data({
2581 action: 'mainwp_preparebulkinstallplugintheme',
2582 type: type,
2583 slug: slug,
2584 name: name,
2585 selected_by: jQuery('input[name="select_by"]').val()
2586 });
2587 let placeholder = '<div class="ui placeholder"><div class="paragraph"><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div></div></div>';
2588
2589 if (jQuery('input[name="select_by"]').val() == 'site') {
2590
2591 let selected_sites = [];
2592
2593 jQuery("input[name='selected_sites[]']:checked").each(function () {
2594 selected_sites.push(jQuery(this).val());
2595 });
2596
2597 if (selected_sites.length == 0) {
2598 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2599 return;
2600 }
2601
2602 data['selected_sites[]'] = selected_sites;
2603
2604 } else if (jQuery('input[name="select_by"]').val() == 'client') {
2605
2606 let selected_clients = [];
2607
2608 jQuery("input[name='selected_clients[]']:checked").each(function () {
2609 selected_clients.push(jQuery(this).val());
2610 });
2611
2612 if (selected_clients.length == 0) {
2613 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2614 return;
2615 }
2616
2617 data['selected_clients[]'] = selected_clients;
2618
2619 } else {
2620 let selected_groups = [];
2621
2622 jQuery("input[name='selected_groups[]']:checked").each(function () {
2623 selected_groups.push(jQuery(this).val());
2624 });
2625
2626 if (selected_groups.length == 0) {
2627 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2628 return;
2629 }
2630
2631 data['selected_groups[]'] = selected_groups;
2632
2633 }
2634
2635 jQuery('#plugintheme-installation-queue').html(placeholder);
2636 jQuery.post(ajaxurl, data, function (type, activatePlugin, overwrite) {
2637 return function (response) {
2638 let installQueueContent = '';
2639 bulkInstallDone = 0;
2640 installQueueContent += '<div id="bulk_install_info"></div>';
2641 installQueueContent += '<div class="ui middle aligned divided list">';
2642
2643 for (let siteId in response.sites) {
2644 let site = response.sites[siteId];
2645 installQueueContent +=
2646 '<div class="siteBulkInstall item" siteid="' + siteId + '" status="queue">' +
2647 '<div class="right floated content">' +
2648 '<span class="queue" data-inverted="" data-position="left center" data-tooltip="' + __('Queued') + '"><i class="clock outline icon"></i></span>' +
2649 '<span class="progress" data-inverted="" data-position="left center" data-tooltip="' + __('Installing...') + '" style="display:none"><i class="notched circle loading icon"></i></span>' +
2650 '<span class="status"></span>' +
2651 '</div>' +
2652 '<div class="content">' + mainwp_links_visit_site_and_admin('', siteId) + ' ' + '<a href="' + site['url'] + '">' + site.name.replace(/\\(.)/g, '$1') + '</a></div>' + // NOSONAR - no safe replaceAll alternative.
2653 '</div>';
2654 mainwpVars.bulkInstallTotal++;
2655 }
2656
2657 installQueueContent += '</div>';
2658
2659 jQuery('#plugintheme-installation-queue').html(installQueueContent);
2660 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').progress({ value: 0, total: mainwpVars.bulkInstallTotal });
2661 mainwp_install_bulk_start_next(type, response.url, activatePlugin, overwrite, slug, response);
2662 }
2663 }(type, jQuery('#chk_activate_plugin').is(':checked'), jQuery('#chk_overwrite').is(':checked')), 'json');
2664
2665 jQuery('#plugintheme-installation-progress-modal').modal('setting', 'closable', false).modal('show');
2666
2667 };
2668
2669
2670 /**
2671 * Install Plugin/Theme from WP.org.
2672 *
2673 * Loop through sites.
2674 *
2675 * @param string type Plugin or theme.
2676 * @param string url URL.
2677 * @param bool activatePlugin Determines if the item should be activated or not upon installation.
2678 * @param bool overwrite Determines if the item should overwrite exisitng version.
2679 *
2680 * @return void
2681 */
2682 let mainwp_install_bulk_start_next = function (type, url, activatePlugin, overwrite, slug, installResults) { // NOSONAR - complex.
2683 while ((siteToInstall = jQuery('.siteBulkInstall[status="queue"]:first')) && (siteToInstall.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR - modified outside the function.
2684 mainwp_install_bulk_start_specific(type, url, activatePlugin, overwrite, siteToInstall, slug, installResults);
2685 }
2686 if (bulkInstallDone == mainwpVars.bulkInstallTotal && mainwpVars.bulkInstallTotal != 0) {
2687 jQuery('#bulk_install_info').before('<div class="ui info message">' + mainwp_install_bulk_you_know_msg(type, 1) + '</div>');
2688 if (jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').length > 0) { // to support add to cost tracker pro.
2689 if (installResults.add_to_cost_tracker_id != undefined) {
2690 if (installResults.add_to_cost_tracker_id > 0) {
2691 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').text(_('Edit Cost Tracker'));
2692 jQuery('#mainwp-cost-tracker-assistant-add-to-tracker-modal .header').text(_('Edit Cost Tracker'));
2693 }
2694 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('disabled', false);
2695 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').removeClass('disabled');
2696 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('item-slug', slug);
2697 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('item-type', type);
2698 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('item-name', installResults.name);
2699 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('cost-id', installResults.add_to_cost_tracker_id);
2700 if (installResults.installed_sites != undefined) {
2701 jQuery('.mainwp-cost-tracker-assistant-add-to-cost-tracker-button').attr('installed-sites', installResults.installed_sites.join(','));
2702 }
2703 }
2704 }
2705 }
2706 };
2707
2708 /**
2709 * Install Plugin/Theme from WP.org.
2710 *
2711 * Install specific item.
2712 *
2713 * @param string type Plugin or theme.
2714 * @param string url URL.
2715 * @param bool activatePlugin Determines if the item should be activated or not upon installation.
2716 * @param bool overwrite Determines if the item should overwrite exisitng version.
2717 * @param object siteToInstall Site to install the item to.
2718 *
2719 * @return void
2720 */
2721 let mainwp_install_bulk_start_specific = function (type, url, activatePlugin, overwrite, siteToInstall, slug, installResults) {
2722 bulkInstallCurrentThreads++;
2723
2724 siteToInstall.attr('status', 'progress');
2725 siteToInstall.find('.queue').hide();
2726 siteToInstall.find('.progress').show();
2727 let data = mainwp_secure_data({
2728 action: 'mainwp_installbulkinstallplugintheme',
2729 type: type,
2730 url: url,
2731 activatePlugin: activatePlugin,
2732 overwrite: overwrite,
2733 siteId: siteToInstall.attr('siteid')
2734 });
2735
2736 jQuery.post(ajaxurl, data, function (type, url, activatePlugin, overwrite, siteToInstall) {
2737 return function (response) {
2738 siteToInstall.attr('status', 'done');
2739 siteToInstall.find('.progress').hide();
2740 let statusEl = siteToInstall.find('.status');
2741 statusEl.show();
2742 let _error = '';
2743 if (response.error != undefined) {
2744 statusEl.html(response.error);
2745 statusEl.css('color', 'red');
2746 } else if (response?.ok[siteToInstall.attr('siteid')]) {
2747 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + __('Installation completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>');
2748 if (installResults.installed_sites == undefined) {
2749 installResults.installed_sites = [];
2750 }
2751 installResults.installed_sites.push(siteToInstall.attr('siteid'));
2752 } else if (response?.errors[siteToInstall.attr('siteid')]) {
2753 _error = response.errors[siteToInstall.attr('siteid')][1];
2754 } else {
2755 _error = __('Undefined error occurred. Please try again.', 'mainwp');
2756 }
2757
2758 if (_error !== '') {
2759 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + _error + '"><i class="times red icon"></i></span>');
2760 }
2761
2762 bulkInstallCurrentThreads--;
2763 bulkInstallDone++;
2764
2765 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').progress('set progress', bulkInstallDone);
2766 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').find('.label').html(bulkInstallDone + '/' + mainwpVars.bulkInstallTotal + ' ' + __('Installed'));
2767 mainwp_install_bulk_start_next(type, url, activatePlugin, overwrite, slug, installResults);
2768 }
2769 }(type, url, activatePlugin, overwrite, siteToInstall), 'json');
2770 };
2771
2772
2773 let mainwp_install_bulk_you_know_msg = function (type, total) { // NOSONAR - complex.
2774 let msg = '';
2775 if (mainwpParams.installedBulkSettingsManager && mainwpParams.installedBulkSettingsManager == 1) {
2776 if (type == 'plugin') {
2777 if (total == 1)
2778 msg = __('Would you like to use the Bulk Settings Manager with this plugin? Check out the %1Documentation%2.', '<a href="https://docs.mainwp.com/add-ons/administrative/bulk-settings-manager-extension" target="_blank">', '</a>'); // NOSONAR - noopener - open safe.
2779 else
2780 msg = __('Would you like to use the Bulk Settings Manager with these plugins? Check out the %1Documentation%2.', '<a href="https://docs.mainwp.com/add-ons/administrative/bulk-settings-manager-extension" target="_blank">', '</a>'); // NOSONAR - noopener - open safe.
2781 } else if (type == 'theme') {
2782 if (total == 1)
2783 msg = __('Would you like to use the Bulk Settings Manager with this theme? Check out the %1Documentation%2.', '<a href="https://docs.mainwp.com/add-ons/administrative/bulk-settings-manager-extension" target="_blank">', '</a>'); // NOSONAR - noopener - open safe.
2784 else
2785 msg = __('Would you like to use the Bulk Settings Manager with these themes? Check out the %1Documentation%2.', '<a href="https://docs.mainwp.com/add-ons/administrative/bulk-settings-manager-extension" target="_blank">', '</a>'); // NOSONAR - noopener - open safe.
2786 }
2787 } else if (type == 'plugin') {
2788 if (total == 1)
2789 msg = __('Did you know with the %1 you can control the settings of this plugin directly from your MainWP Dashboard?', '<a href="https://mainwp.com/add-on/bulk-settings-manager/" target="_blank">Bulk Settings Extension</a>'); // NOSONAR - noopener - open safe.
2790 else
2791 msg = __('Did you know with the %1 you can control the settings of these plugins directly from your MainWP Dashboard?', '<a href="https://mainwp.com/add-on/bulk-settings-manager/" target="_blank">Bulk Settings Extension</a>'); // NOSONAR - noopener - open safe.
2792 } else if (type == 'theme') {
2793 if (total == 1)
2794 msg = __('Did you know with the %1 you can control the settings of this theme directly from your MainWP Dashboard?', '<a href="https://mainwp.com/add-on/bulk-settings-manager/" target="_blank">Bulk Settings Extension</a>'); // NOSONAR - noopener - open safe.
2795 else
2796 msg = __('Did you know with the %1 you can control the settings of these themes directly from your MainWP Dashboard?', '<a href="https://mainwp.com/add-on/bulk-settings-manager/" target="_blank">Bulk Settings Extension</a>'); // NOSONAR - noopener - open safe.
2797 }
2798 return msg;
2799 }
2800
2801 /**
2802 * Install Plugin/Theme by Upload.
2803 *
2804 * Initiate the process.
2805 *
2806 * @param string type Plugin or theme.
2807 *
2808 * @return void
2809 */
2810 let mainwp_upload_bulk = function (type) {
2811
2812 if (type == 'plugins') {
2813 type = 'plugin';
2814 } else {
2815 type = 'theme';
2816 }
2817
2818 let files = [];
2819
2820 jQuery(".qq-upload-file").each(function () {
2821 if (jQuery(this).closest('.file-uploaded-item').hasClass('qq-upload-success')) {
2822 files.push(jQuery(this).attr('filename'));
2823 }
2824 });
2825
2826 if (files.length == 0) {
2827 if (type == 'plugin') {
2828 feedback('mainwp-message-zone', __('Please upload at least one plugin to install.', 'mainwp'), 'yellow');
2829 } else {
2830 feedback('mainwp-message-zone', __('Please upload at least one theme to install.', 'mainwp'), 'yellow');
2831 }
2832 return;
2833 }
2834
2835 let data = mainwp_secure_data({
2836 action: 'mainwp_preparebulkuploadplugintheme',
2837 type: type,
2838 selected_by: jQuery('input[name="select_by"]').val()
2839 });
2840
2841 let placeholder = '<div class="ui placeholder"><div class="paragraph"><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div></div></div>';
2842
2843 if (jQuery('input[name="select_by"]').val() == 'site') {
2844 let selected_sites = [];
2845 jQuery("input[name='selected_sites[]']:checked").each(function () {
2846 selected_sites.push(jQuery(this).val());
2847 });
2848
2849 if (selected_sites.length == 0) {
2850 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2851 return;
2852 }
2853 data['selected_sites[]'] = selected_sites;
2854 } else if (jQuery('input[name="select_by"]').val() == 'client') {
2855 let selected_clients = [];
2856 jQuery("input[name='selected_clients[]']:checked").each(function () {
2857 selected_clients.push(jQuery(this).val());
2858 });
2859
2860 if (selected_clients.length == 0) {
2861 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2862 return;
2863 }
2864 data['selected_clients[]'] = selected_clients;
2865 } else {
2866 let selected_groups = [];
2867 jQuery("input[name='selected_groups[]']:checked").each(function () {
2868 selected_groups.push(jQuery(this).val());
2869 });
2870 if (selected_groups.length == 0) {
2871 feedback('mainwp-message-zone', __('Please select at least one website or a group or client.', 'mainwp'), 'yellow');
2872 return;
2873 }
2874 data['selected_groups[]'] = selected_groups;
2875 }
2876
2877 data['files[]'] = files;
2878
2879 jQuery('#plugintheme-installation-queue').html(placeholder);
2880
2881 jQuery.post(ajaxurl, data, function (type, files, activatePlugin, overwrite) {
2882 return function (response) {
2883 let installQueue = '';
2884 mainwpVars.bulkInstallTotal = 0;
2885 bulkInstallDone = 0;
2886
2887 installQueue += '<div class="ui middle aligned selection divided list">';
2888
2889 for (let siteId in response.sites) {
2890 let site = response.sites[siteId];
2891
2892 installQueue +=
2893 '<div class="siteBulkInstall item" siteid="' + siteId + '" status="queue">' +
2894 '<div class="right floated content">' +
2895 '<span class="queue" data-inverted="" data-position="left center" data-tooltip="' + __('Queued', 'mainwp') + '"><i class="clock outline icon"></i></span>' +
2896 '<span class="progress" data-inverted="" data-position="left center" data-tooltip="' + __('Installing...', 'mainwp') + '" style="display:none"><i class="notched circle loading icon"></i></span>' +
2897 '<span class="status"></span>' +
2898 '</div>' +
2899 '<div class="content">' + mainwp_links_visit_site_and_admin('', siteId) + ' ' + '<a href="' + site['url'] + '">' + site.name.replace(/\\(.)/g, '$1') + '</a></div>' + // NOSONAR - no safe replaceAll alternative.
2900 '<div class="installation-entries"></div>' +
2901 '</div>';
2902 mainwpVars.bulkInstallTotal++;
2903 }
2904
2905 installQueue += '</div>';
2906
2907 jQuery('#plugintheme-installation-queue').html(installQueue);
2908
2909 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').progress({ value: 0, total: mainwpVars.bulkInstallTotal });
2910 mainwp_upload_bulk_start_next(type, response.urls, activatePlugin, overwrite);
2911 }
2912 }(type, files, jQuery('#chk_activate_plugin').is(':checked'), jQuery('#chk_overwrite').is(':checked')), 'json');
2913
2914 jQuery('#plugintheme-installation-progress-modal').modal('setting', 'closable', false).modal('show');
2915
2916 jQuery('.qq-upload-list').html(''); // empty files list!
2917
2918 return false;
2919 };
2920
2921 /**
2922 * Install Plugin/Theme by Upload.
2923 *
2924 * Loop through sites.
2925 *
2926 * @param string type Plugin or theme.
2927 * @param string urls URLs.
2928 * @param bool activatePlugin Determines if the item should be activated or not upon installation.
2929 * @param bool overwrite Determines if the item should overwrite exisitng version.
2930 *
2931 * @return void
2932 */
2933 let mainwp_upload_bulk_start_next = function (type, urls, activatePlugin, overwrite) {
2934 while ((siteToInstall = jQuery('.siteBulkInstall[status="queue"]:first')) && (siteToInstall.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR - modified outside the function.
2935 mainwp_upload_bulk_start_specific(type, urls, activatePlugin, overwrite, siteToInstall);
2936 }
2937
2938 if ((siteToInstall.length == 0) && (bulkInstallCurrentThreads == 0)) { // NOSONAR - modified outside the function.
2939 let data = mainwp_secure_data({
2940 action: 'mainwp_cleanbulkuploadplugintheme',
2941 });
2942
2943 jQuery.post(ajaxurl, data, function () {
2944 jQuery('.file-uploaded-item.qq-upload-completed').remove();
2945 });
2946
2947 let msg = mainwp_install_bulk_you_know_msg(type, jQuery('#bulk_upload_info').attr('number-files'));
2948
2949 jQuery('#bulk_upload_info').html('<div class="bui blue message">' + msg + '</div>');
2950
2951 if (jQuery('.mainwp_cost_tracker_assistant_installed_items').length > 0) { // to support add to cost tracker pro.
2952 let cost_tracker_items = [];
2953 let cost_tracker_check_slugs = [];
2954 jQuery('.mainwp_cost_tracker_assistant_installed_items').each(function () {
2955 let slug = jQuery(this).attr('item-slug');
2956 let items_slug = {};
2957 if (!cost_tracker_check_slugs.includes(slug)) {
2958 cost_tracker_check_slugs.push(slug);
2959 let siteids = [];
2960 jQuery('.mainwp_cost_tracker_assistant_installed_items[item-slug="' + slug + '"]').each(function () {
2961 siteids.push(jQuery(this).attr('item-siteid'));
2962 });
2963 items_slug.slug = slug;
2964 items_slug.name = jQuery(this).attr('item-name');
2965 items_slug.type = jQuery(this).attr('item-type');
2966 items_slug.cost_id = jQuery(this).attr('cost-id');
2967 items_slug.sites_ids = siteids;
2968 cost_tracker_items.push(items_slug);
2969 }
2970 });
2971
2972 if (cost_tracker_items.length > 0) {
2973 jQuery('.mainwp-cost-tracker-assistant-add-buttons-wrapper').html('');
2974 let multiAddTo = cost_tracker_items.length > 1 ? 1 : 0;
2975 cost_tracker_items.forEach(item => {
2976 jQuery('.mainwp-cost-tracker-assistant-add-buttons-wrapper').append('<a href="javascript:void(0)" item-type="' + item.type + '" item-slug="' + item.slug + '" cost-id="' + item.cost_id + '" item-name="' + item.name + '" installed-sites="' + item.sites_ids.join(',') + '" multi-add-to="' + multiAddTo + '" class="ui mini button mainwp-cost-tracker-assistant-add-to-cost-tracker-button">' + ((item.cost_id != undefined && item.cost_id > 0) ? __('Edit Cost Tracker') + ' (' + item.name + ')' : __('Add to Cost Tracker') + ' (' + item.name + ')') + '</a>');
2977 });
2978 }
2979 }
2980 }
2981 };
2982
2983 /**
2984 * Install Plugin/Theme by Upload.
2985 *
2986 * Install specific item.
2987 *
2988 * @param string type Plugin or theme.
2989 * @param string urls URLs.
2990 * @param bool activatePlugin Determines if the item should be activated or not upon installation.
2991 * @param bool overwrite Determines if the item should overwrite exisitng version.
2992 * @param object siteToInstall Site to install the item to.
2993 *
2994 * @return void
2995 */
2996 let mainwp_upload_bulk_start_specific = function (type, urls, activatePlugin, overwrite, siteToInstall) {
2997 bulkInstallCurrentThreads++;
2998 siteToInstall.attr('status', 'progress');
2999
3000 siteToInstall.find('.queue').hide();
3001 siteToInstall.find('.progress').show();
3002
3003 let data = mainwp_secure_data({
3004 action: 'mainwp_installbulkuploadplugintheme',
3005 type: type,
3006 urls: urls,
3007 activatePlugin: activatePlugin,
3008 overwrite: overwrite,
3009 siteId: siteToInstall.attr('siteid')
3010 });
3011
3012 jQuery.post(ajaxurl, data, function (type, urls, activatePlugin, overwrite, siteToInstall) {
3013 return function (response) {
3014 siteToInstall.attr('status', 'done');
3015 siteToInstall.find('.progress').hide();
3016 let statusEl = siteToInstall.find('.status');
3017 let siteid = siteToInstall.attr('siteid');
3018 statusEl.show();
3019
3020 if (response.error != undefined) {
3021 statusEl.html(response.error);
3022 statusEl.css('color', 'red');
3023 } else if (response?.ok[siteid] != undefined) {
3024 let results = '';
3025 if (response?.results[siteid] != undefined) {
3026 let entries = Object.entries(response.results[siteid]);
3027 results += '<div class="ui tiny middle aligned list">';
3028 for (let entry of entries) {
3029 results += '<div class="item"><div class="right floated content">' + (entry[1] ? '<i class="check green icon"></i>' : '<i class="times red icon"></i>') + '</div><div class="content">' + entry[0] + '</div></div>';
3030 }
3031 results += '</div>';
3032 }
3033 jQuery('div[siteId="' + siteid + '"] .installation-entries').html(results);
3034 if (response.cost_tracker_installed_info != undefined) { // to support add to cost tracker pro.
3035 jQuery('div[siteId="' + siteid + '"] .installation-entries').after(response.cost_tracker_installed_info);
3036 }
3037 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + __('Installation completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>');
3038 } else if (response?.errors[siteid] === undefined) {
3039 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + __('Undefined error occurred. Please try again.', 'mainwp') + '"><i class="times red icon"></i></span>');
3040 } else {
3041 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + response.errors[siteid][1] + '"><i class="times red icon"></i></span>');
3042 }
3043
3044 bulkInstallCurrentThreads--;
3045 bulkInstallDone++;
3046 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').progress('set progress', bulkInstallDone);
3047 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').find('.label').html(bulkInstallDone + '/' + mainwpVars.bulkInstallTotal + ' ' + __('Installed'));
3048 mainwp_upload_bulk_start_next(type, urls, activatePlugin, overwrite);
3049 }
3050 }(type, urls, activatePlugin, overwrite, siteToInstall), 'json');
3051 };
3052
3053 jQuery(function ($) {
3054 jQuery(document).on('click', '.open-plugin-details-modal', (event) => {
3055
3056 const $el = jQuery(event.currentTarget);
3057
3058 const openwpp = $el.attr('open-wpplugin');
3059 let openwpp_site = '';
3060
3061 if (openwpp === 'yes') {
3062 const findNext = $el
3063 .closest('tr')
3064 .next()
3065 .find('tr[open-wpplugin-siteid]');
3066
3067 if (findNext.length > 0) {
3068 openwpp_site =
3069 '&wpplugin=' + findNext.attr('open-wpplugin-siteid');
3070 }
3071 }
3072
3073 $('#mainwp-plugin-details-modal')
3074 .modal({
3075 onHide: function () {},
3076 onShow: () => {
3077 $('#mainwp-plugin-details-modal')
3078 .find('.ui.embed')
3079 .embed({
3080 source: 'WP',
3081 url: $el.attr('href') + openwpp_site,
3082 });
3083 }
3084 })
3085 .modal('show');
3086
3087 return false;
3088 });
3089 });
3090
3091
3092 /**
3093 *
3094 * Widget plugins/themes changes history
3095 *
3096 */
3097
3098 let pluginChangesLoadData = {};
3099 let themeChangesLoadData = {};
3100
3101 jQuery(function ($) {
3102
3103 $(document).on('click', '.mainwp-show-history', function (e) {
3104
3105 e.preventDefault();
3106 e.stopPropagation();
3107
3108 const view = $(this).attr('history-view');
3109 let parent = false;
3110 let type = 'plugin'; // default.
3111 let title = '';
3112 let info = '';
3113 let name = '';
3114 let slug = '';
3115 let siteId = 0;
3116
3117 switch (view) {
3118 case 'update-plugins-individual':
3119 parent = $(this).closest('.plugins-bulk-updates');
3120 siteId = $(parent).attr('site_id');
3121 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3122 title = $(this).closest('tr').attr('plugin_name');
3123 slug = decodeURIComponent( $(this).closest('tr').attr('plugin_slug') );
3124 name = $(this).closest('tr').attr('plugin_name');
3125 break;
3126 case 'update-themes-individual':
3127 parent = $(this).closest('.themes-bulk-updates');
3128 siteId = $(parent).attr('site_id');
3129 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3130 title = $(this).closest('tr').attr('theme_name');
3131 slug = $(this).closest('tr').attr('theme_slug');
3132 name = $(this).closest('tr').attr('theme_name');
3133 type = 'theme';
3134 break;
3135 case 'manage-plugins-per-sites':
3136 case 'manage-plugins-per-items':
3137 parent = $(this).closest('.mainwp-manage-plugin-item-website');
3138 title = $(parent).attr('plugin-name');
3139 info = $(parent).attr('site-name') + ' (' + $(parent).attr('site-url') + ') ' + $(parent).attr('tz-info');
3140 slug = decodeURIComponent($(parent).attr('plugin-slug'));
3141 siteId = $(parent).attr('site-id');
3142 break;
3143 case 'manage-themes-per-sites':
3144 case 'manage-themes-per-items':
3145 parent = $(this).closest('.mainwp-manage-theme-item-website');
3146 title = $(parent).attr('theme-name');
3147 name = $(parent).attr('theme-name');
3148 info = $(parent).attr('site-name') + ' (' + $(parent).attr('site-url') + ') ' + $(parent).attr('tz-info');
3149 slug = decodeURIComponent($(parent).attr('theme-slug'));
3150 siteId = $(parent).attr('site-id');
3151 type = 'theme';
3152 break;
3153 case 'widget-plugins':
3154 parent = $(this).closest('.row-manage-item');
3155 title = $(parent).attr('plugin-name');
3156 info = $('#mainwp-widget-active-plugins').attr('site-info');
3157 slug = $(parent).attr('plugin-slug');
3158 siteId = $('#mainwp-widget-active-plugins').attr('site-id');
3159 break;
3160 case 'widget-themes':
3161 parent = $(this).closest('.row-manage-item');
3162 title = $(parent).find('.themeName').val();
3163 info = $('#mainwp-widget-inactive-themes').attr('site-info');
3164 slug = $(parent).find('.themeSlug').val();
3165 name = $(parent).find('.themeName').val();
3166 siteId = $('#mainwp-widget-inactive-themes').attr('site-id');
3167 type = 'theme';
3168 break;
3169 case 'update-plugin-per-item':
3170 parent = $(this).closest('tr');
3171 siteId = $(parent).attr('site_id');
3172 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3173 title = $(parent).attr('plugin_name');
3174 slug = decodeURIComponent($(parent).attr('plugin_slug'));
3175 break;
3176 case 'update-theme-per-item':
3177 parent = $(this).closest('tr');
3178 siteId = $(parent).attr('site_id');
3179 info = $(parent).attr('site_name') + ' (' + decodeURIComponent( $(parent).attr('site_url') ) + ') ' + $(parent).attr('tz-info');
3180 title = $(parent).attr('theme_name');
3181 name = $(parent).attr('theme_name');
3182 slug = decodeURIComponent($(parent).attr('theme_slug'));
3183 type = 'theme';
3184 break;
3185 case 'update-plugin-per-site': // NOSONAR - same as above.
3186 parent = $(this).closest('.plugins-bulk-updates');
3187 siteId = $(parent).attr('site_id');
3188 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3189 title = $(this).closest('tr').attr('plugin_name');
3190 slug = decodeURIComponent( $(this).closest('tr').attr('plugin_slug') );
3191 name = $(this).closest('tr').attr('plugin_name');
3192 break;
3193 case 'update-theme-per-site': // NOSONAR - same above.
3194 parent = $(this).closest('.themes-bulk-updates');
3195 siteId = $(parent).attr('site_id');
3196 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3197 title = $(this).closest('tr').attr('theme_name');
3198 slug = $(this).closest('tr').attr('theme_slug');
3199 name = $(this).closest('tr').attr('theme_name');
3200 type = 'theme';
3201 break;
3202 case 'update-plugin-per-tag':
3203 parent = $(this).closest('.plugins-bulk-updates');
3204 siteId = $(parent).attr('site_id');
3205 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3206 title = $(this).closest('tr').attr('plugin_name');
3207 slug = decodeURIComponent($(this).closest('tr').attr('plugin_slug'));
3208 break;
3209 case 'update-theme-per-tag':
3210 parent = $(this).closest('.themes-bulk-updates');
3211 siteId = $(parent).attr('site_id');
3212 info = $(parent).attr('site_name') + ' (' + $(parent).attr('site_url') + ') ' + $(parent).attr('tz-info');
3213 title = $(this).closest('tr').attr('theme_name');
3214 name = $(this).closest('tr').attr('theme_name');
3215 slug = $(this).closest('tr').attr('theme_slug');
3216 type = 'theme';
3217 break;
3218 }
3219
3220 if (type === 'plugin') {
3221 pluginChangesLoadData = mainwp_secure_data({
3222 action: 'mainwp_changes_logs_get_item_changes',
3223 type: 'plugin',
3224 slug: slug,
3225 siteId: siteId,
3226 from_date: '' // current date.
3227 });
3228 } else if (type === 'theme') {
3229 themeChangesLoadData = mainwp_secure_data({
3230 action: 'mainwp_changes_logs_get_item_changes',
3231 type: 'theme',
3232 slug: slug,
3233 siteId: siteId,
3234 name: name,
3235 from_date: '' // current date.
3236 });
3237 }
3238
3239 $('#mainwp-plugin-theme-history-changes-modal').modal({
3240 onHide: function () {
3241 },
3242 onShow: function () {
3243 mainwp_changes_history_box_init(type, title, info);
3244 jQuery('#mainwp-plugin-theme-history-changes-modal').find('.content.ui').html('<div class="ui active centered inline loader history-actions-loading"></div>');
3245 mainwp_item_changes_load();
3246 }
3247 }).modal('show');
3248 });
3249 });
3250
3251 let mainwp_changes_history_box_init = function ( type, title, info ) {
3252 const hd = jQuery('#mainwp-plugin-theme-history-changes-modal > div.header');
3253 hd.find('.main-text').text(title + ' ' + __('History')); // safe for escape.
3254 hd.find('.sub.header').text(info).show();
3255 jQuery('#mainwp-plugin-theme-history-changes-modal').attr('history-type', type);
3256 jQuery('#mainwp-plugin-theme-history-changes-modal').find('.scrolling.content').html('');
3257 }
3258
3259 let mainwp_item_changes_load = function ( btnObj, load_more_date = '' ) {
3260
3261 let md = jQuery('#mainwp-plugin-theme-history-changes-modal');
3262 let parentContent = false;
3263 if(btnObj){
3264 parentContent = jQuery(btnObj).closest('.ui.accordion').find('.ui.content');
3265 } else {
3266 parentContent = jQuery(md).find('.scrolling.content')
3267 }
3268
3269 jQuery(md).find('.actions .col-left').html('');
3270 jQuery(md).find('.actions .col-right').html('');
3271
3272 const type = jQuery(md).attr('history-type');
3273 let load_more = false;
3274
3275 // set load date if provided
3276 if(typeof load_more_date === 'string' && load_more_date !== ''){
3277 if('theme' === type){
3278 themeChangesLoadData.from_date = load_more_date;
3279 }else{
3280 pluginChangesLoadData.from_date = load_more_date;
3281 }
3282 load_more = true;
3283 }
3284
3285 let data = 'plugin' === type ? pluginChangesLoadData : themeChangesLoadData;
3286
3287
3288 jQuery.post(ajaxurl, data, function (response) { // NOSONAR - complex.
3289 jQuery(md).find('.history-actions-loading').remove();
3290 if (response?.error) {
3291 if(parentContent){
3292 let err_content = '<div class="ui message red">' + response.error + '</div>';
3293 jQuery(parentContent).html(err_content);
3294 }
3295 } else if (response?.list) {
3296 if (response.list.length == 0) {
3297 let msg = __('This plugin has no recorded activity in Dashboard Insights.') ;
3298 if('theme' === type){
3299 msg = __('This theme has no recorded activity in Dashboard Insights.') ;
3300 }
3301 if(parentContent){
3302 let msg_content = '<div class="ui info message">' + msg + '</div>';
3303 jQuery(parentContent).html(msg_content);
3304 }
3305 } else {
3306 let content = '';
3307 Object.entries(response.list).forEach(([indexdt, records]) => {
3308 const dt = records[0].date;
3309 content += `<div class="ui accordion" data-date="${indexdt}">
3310 <div class="title" format-date="${dt}">
3311 <div class="ui container">
3312 <div class="ui grid">
3313 <div class="ten wide column middle aligned">
3314 <i class="dropdown icon"></i>
3315 ${dt}
3316 </div>
3317 <div class="six wide column right aligned">
3318 <button type="button" class="ui circular blue mini button mainwp-day-history-switch-view">` + __('Day History') + `</button> <button class="ui basic mini button actions-count1">${records.length} ` + __('Actions') + `</button>
3319 </div>
3320 </div>
3321 </div>
3322 </div>
3323 <div class="content ui list">`;
3324 records.forEach(record => {
3325 content += `<div class="item" log-id="${record.details.log_id}">
3326 <div class="ui grid">
3327 <div class="eight wide column middle aligned">
3328 <i class="` + get_icon_history_event(record.details.action) + ` icon"></i>
3329 <span class="ui text ` + get_color_changes_event(record.details.action) + `">${record.details.event}</span> ` + __('by') + ` <strong>${record.details.author_name}</strong> ` + __('from') + `
3330 <strong>${record.details.source}</strong>
3331 </div>
3332 <div class="six wide column middle aligned">
3333 ` + (record.details?.old_version && record.details?.version ? record.details.old_version + '&rarr;' + record.details.version : '') + `
3334 </div>
3335 <div class="two wide column right aligned">
3336 ${record.details.at_hour}
3337 </div>
3338 </div>
3339 </div>`;
3340 });
3341 content += `</div>
3342 </div>`;
3343 });
3344
3345 if ('' !== content) {
3346 let accordWrapper = jQuery("<div>", {
3347 id: "change-history-according-wrapper",
3348 html: content
3349 });
3350
3351 let name_title = '';
3352
3353 if ((data?.name || data?.slug) && response?.name_title) {
3354 name_title = response.name_title;
3355 }
3356
3357 if (name_title != '') {
3358 jQuery(md).find('.ui.header .main-text').text(name_title + ' ' + __('History'));
3359 }
3360
3361 if (load_more) {
3362 jQuery(md).find('.scrolling.content').append(accordWrapper);
3363 } else {
3364 jQuery(md).find('.scrolling.content').html(accordWrapper);
3365 }
3366
3367 jQuery('#change-history-according-wrapper .ui.accordion').accordion({exclusive: true});
3368
3369 jQuery('.mainwp-day-history-switch-view').off('click.accordionFix').on('click.accordionFix', function(e){
3370 e.preventDefault();
3371 e.stopPropagation(); // now it runs before ancestor handlers
3372 dayHistory_SwitchViewHandler(this);
3373 return false;
3374 });
3375 }
3376
3377 if ( response?.onward_date ) {
3378 jQuery(md).find('.actions .col-left').html('Data available from ' + response.onward_date + ' onward.');
3379 }
3380 if ( response?.more_date ) {
3381 jQuery(md).find('.actions .col-right').html('<a href="javascript:void(0);" onclick="mainwp_item_changes_load(false,\'' + ( response.more_date ?? get_local_date_string() ) + '\');return false;">' + __('Load More') + '</a>');
3382 }
3383 }
3384 } else if(parentContent){
3385 let err_content = '<div class="ui message red">' + __('Undefined error occurred. Please try again.') + '</div>';
3386 jQuery(parentContent).html(err_content);
3387 }
3388 }, 'json');
3389 }
3390
3391 let get_icon_history_event = function( act ){
3392 let icon = '';
3393
3394 if (act === 'delete' || act === 'deleted') {
3395 icon = 'trash red';
3396 } else if (act === 'deactivated' || act === 'deactivate') {
3397 icon = 'toggle off red';
3398 } else if (act === 'activated' || act === 'activate') {
3399 icon = 'toggle on green';
3400 } else if (act === 'updated' || act === 'update') {
3401 icon = 'sync orange';
3402 } else if (act === 'installed' || act === 'install') {
3403 icon = 'download teal';
3404 } else {
3405 icon = 'circle grey';
3406 }
3407
3408 return icon;
3409 }
3410
3411 let get_color_changes_event = function( act ){
3412 const actColorMap = {
3413 red: ['deleted','removed','revoked','delete','deactivated','disabled','suspended','deactivate'],
3414 orange: ['updated','modified','update'],
3415 grey: ['opened'],
3416 blue: ['logged-in','logged-out'],
3417 teal: ['sync','installed','install','uploaded'],
3418 green: ['activated','activate','created','published','enabled','added']
3419 };
3420
3421 let color = '';
3422
3423 for (const [c, acts] of Object.entries(actColorMap)) {
3424 if (acts.includes(act)) {
3425 color = c;
3426 break;
3427 }
3428 }
3429 return color;
3430 }
3431
3432 let dayHistory_SwitchViewHandler = function (btn) {
3433
3434 const parent = jQuery(btn).closest('.ui.accordion');
3435 const his_date = jQuery(btn).closest('.title').attr('format-date');
3436
3437 jQuery(btn).closest('.title').hasClass('active') || jQuery(btn).closest('.title').trigger('click');
3438
3439 jQuery(parent).find('.content.ui').html('<div class="ui active centered inline loader history-actions-loading"></div>');
3440
3441 const dt = jQuery(parent).data('date');
3442 let md = jQuery('#mainwp-plugin-theme-history-changes-modal');
3443 const type = jQuery(md).attr('history-type');
3444
3445 let siteId = ('plugin' === type ? pluginChangesLoadData.siteId : themeChangesLoadData.siteId) || 0;
3446
3447 let data = mainwp_secure_data({
3448 action: 'mainwp_changes_logs_get_item_changes',
3449 type: type,
3450 target_date: dt,
3451 siteId: siteId
3452 });
3453
3454 jQuery.post(ajaxurl, data, function (response) { // NOSONAR - complex.
3455
3456 jQuery(parent).find('.history-actions-loading').remove();
3457
3458 let dayContent = jQuery(parent).find('.content');
3459
3460 if (response.error != undefined) {
3461 dayContent.append('<div class="ui message red changes-history-status">' + response.error + '</div>');
3462 } else if (response?.list) {
3463 if (response.list.length == 0) {
3464 let msg = __('This plugin has no recorded activity in Dashboard Insights.');
3465 if ('theme' === type && '' === dt) {
3466 msg = __('This theme has no recorded activity in Dashboard Insights.');
3467 } else if ('' !== dt) {
3468 if ('plugin' === type) {
3469 msg = __('No history changes found for the plugin on this day.');
3470 } else {
3471 msg = __('No history changes found for the theme on this day.');
3472 }
3473 }
3474 dayContent.append('<div class="ui message changes-history-status">' + msg + '</div>');
3475 } else {
3476 let content = '';
3477 let count_acts = 0;
3478 Object.entries(response.list).forEach(([idxslug, records]) => {
3479 const name = records[0].name;
3480 content += `<div class="ui accordion list-all-actions-in-day" data-slug="${records[0].item_slug}" data-name="${records[0].item_name}" data-siteid="${records[0].site_id}">
3481 <div class="title">
3482 <div class="ui container">
3483 <div class="ui grid">
3484 <div class="ten wide column middle aligned">
3485 <i class="dropdown icon"></i>
3486 ${name}
3487 </div>
3488 <div class="six wide column right aligned">
3489 <button type="button" class="ui circular blue mini button mainwp-list-history-switch-view">` + ( 'plugin' === type ? __('Plugin History') : __('Theme History') ) + `</button> <button class="ui basic mini button ">${records.length} ` + __('Actions') + `</button>
3490 </div>
3491 </div>
3492 </div>
3493 </div>
3494 <div class="content ui list">`;
3495 records.forEach(record => {
3496 content += `<div class="item" log-id="${record.details.log_id}">
3497 <div class="ui grid">
3498 <div class="eight wide column middle aligned">
3499 <i class="` + get_icon_history_event(record.details.action) + ` icon"></i>
3500 <span class="ui text ` + get_color_changes_event(record.details.action) + `">${record.details.event}</span> ` + __('by') + ` <strong>${record.details.author_name}</strong> ` + __('from') + `
3501 <strong>${record.details.source}</strong>
3502 </div>
3503 <div class="six wide column middle aligned">
3504 ` + (record.details?.old_version && record.details?.version ? record.details.old_version + '&rarr;' + record.details.version : '') + `
3505 </div>
3506 <div class="two wide column right aligned">
3507 ${record.details.at_hour}
3508 </div>
3509 </div>
3510 </div>`;
3511 count_acts++;
3512 });
3513 content += `</div>
3514 </div>`;
3515 });
3516
3517 if ('' !== content) {
3518 jQuery(md).find('.ui.header .main-text').text(his_date + ' ' + __('History'));
3519 let accordWrapper = jQuery("<div>", {
3520 id: "change-history-according-wrapper",
3521 html: content
3522 });
3523 jQuery(md).find('.scrolling.content').html(accordWrapper);
3524 jQuery('#change-history-according-wrapper .ui.accordion').accordion({exclusive: true});
3525
3526 jQuery('.mainwp-list-history-switch-view').off('click.accordionFix2').on('click.accordionFix2', function(e){
3527 e.preventDefault();
3528 e.stopPropagation(); // now it runs before ancestor handlers
3529 listHistory_SwitchViewHandler(this);
3530 return false;
3531 });
3532 }
3533 }
3534 } else {
3535 dayContent.html('<div class="ui message red changes-history-status">' + __('Undefined error occurred. Please try again.') + '</div>');
3536 }
3537 }, 'json');
3538
3539 return false;
3540 }
3541
3542
3543 let listHistory_SwitchViewHandler = function (btn) {
3544
3545 const parent = jQuery(btn).closest('.ui.accordion');
3546
3547 jQuery(btn).closest('.title').hasClass('active') || jQuery(btn).closest('.title').trigger('click');
3548
3549 jQuery(parent).find('.content.ui').html('<div class="ui active centered inline loader history-actions-loading"></div>');
3550
3551 let md = jQuery('#mainwp-plugin-theme-history-changes-modal');
3552 const type = jQuery(md).attr('history-type');
3553
3554 if('theme' === type){
3555 themeChangesLoadData.slug = jQuery(parent).data('slug');
3556 themeChangesLoadData.name = jQuery(parent).data('name');
3557 themeChangesLoadData.siteId = jQuery(parent).data('siteid');
3558 themeChangesLoadData.from_date = '';
3559 }else{
3560 pluginChangesLoadData.slug = jQuery(parent).data('slug');;
3561 pluginChangesLoadData.siteId = jQuery(parent).data('siteid');;
3562 pluginChangesLoadData.from_date = '';
3563 }
3564 mainwp_item_changes_load( btn );
3565 }
3566
3567
3568 /**
3569 * Install check plugins.
3570 *
3571 */
3572
3573 globalThis.mainwp_install_check_plugin_prepare = function (slug) {
3574 let selected = jQuery("input[name='install_checker[]']:checked");
3575 if (selected.length == 0) {
3576 feedback('mainwp-message-zone-install', __('Please select website to install plugin.'), 'yellow');
3577 return;
3578 } else {
3579 selected.each(function () {
3580 jQuery(this).closest('.siteBulkInstall').attr('status', 'queue');
3581 });
3582 }
3583 jQuery('#mainwp-install-check-btn').addClass('disabled');
3584 mainwp_set_message_zone('#mainwp-message-zone-install', '<i class="notched circle loading icon"></i> ', false, true); // false: not change the color class.
3585 let data = mainwp_secure_data({
3586 action: 'mainwp_preparebulkinstallcheckplugin',
3587 slug: slug,
3588 });
3589 jQuery.post(ajaxurl, data, function (response) {
3590 mainwp_set_message_zone('#mainwp-message-zone-install');
3591 mainwp_install_check_plugin_start_next(response.url);
3592 }, 'json');
3593 };
3594
3595 let mainwp_install_check_plugin_start_next = function (url) {
3596 while ((siteToInstall = jQuery('.siteBulkInstall[status="queue"]:first')) && (siteToInstall.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR - modified outside the function.
3597 mainwp_install_check_plugin_start_specific(url, siteToInstall);
3598 }
3599 };
3600
3601 let mainwp_install_check_plugin_start_specific = function (url, siteToInstall) {
3602 bulkInstallCurrentThreads++;
3603
3604 siteToInstall.attr('status', 'progress');
3605 siteToInstall.find('.queue').hide();
3606 siteToInstall.find('.progress').show();
3607
3608 let data = mainwp_secure_data({
3609 action: 'mainwp_installbulkinstallplugintheme',
3610 type: 'plugin',
3611 url: url,
3612 activatePlugin: 'true',
3613 siteId: siteToInstall.attr('siteid')
3614 });
3615
3616 jQuery.post(ajaxurl, data, function (url, siteToInstall) {
3617 return function (response) {
3618 siteToInstall.attr('status', 'done');
3619 siteToInstall.find('.progress').hide();
3620
3621 let statusEl = siteToInstall.find('.status');
3622 statusEl.show();
3623
3624 if (response.error != undefined) {
3625 statusEl.html(response.error);
3626 statusEl.css('color', 'red');
3627 } else if (response?.ok[siteToInstall.attr('siteid')]) {
3628 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + __('Installation completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>');
3629 } else if (response?.errors[siteToInstall.attr('siteid')]) {
3630 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + response.errors[siteToInstall.attr('siteid')][1] + '"><i class="times red icon"></i></span>');
3631 } else {
3632 statusEl.html('<span data-inverted="" data-position="left center" data-tooltip="' + __('Undefined error occurred. Please try again.', 'mainwp') + '"><i class="times red icon"></i></span>');
3633 }
3634
3635 bulkInstallCurrentThreads--;
3636 bulkInstallDone++;
3637 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').progress('set progress', bulkInstallDone);
3638 jQuery('#plugintheme-installation-progress-modal .mainwp-modal-progress').find('.label').html(bulkInstallDone + '/' + mainwpVars.bulkInstallTotal + ' ' + __('Installed'));
3639 mainwp_install_check_plugin_start_next(url);
3640 }
3641 }(url, siteToInstall), 'json');
3642 };
3643
3644 function isUrl(url) {
3645 try {
3646 new URL(url);
3647 return true;
3648 } catch (e) {
3649 console.log(e);
3650 }
3651 return false;
3652 }
3653
3654 function removeUrlParams(url, params) {
3655 try {
3656 const urlObj = new URL(url);
3657 jQuery(params).each(function (idx, param) {
3658 urlObj.searchParams.delete(param);
3659 });
3660 return urlObj.toString();
3661 } catch (e) {
3662 console.log(e);
3663 }
3664 return '';
3665 }
3666
3667 function setVisible(what, vis) {
3668 if (vis) {
3669 jQuery(what).show();
3670 } else {
3671 jQuery(what).hide();
3672 }
3673 }
3674
3675 const mainwp_scrollToElement = () => {
3676 jQuery('html,body').animate({
3677 scrollTop: 0
3678 }, 1000);
3679
3680 return false;
3681 }
3682
3683 function setHtml(what, text, ptag) {
3684 if (ptag === undefined)
3685 ptag = true;
3686
3687 setVisible(what, true);
3688 if (ptag)
3689 jQuery(what).html('<span>' + text + '</span>');
3690 else
3691 jQuery(what).html(text);
3692 mainwp_scrollToElement(); // to fix js conflict error from some other add-ons.
3693 }
3694
3695
3696 /**
3697 * Notes
3698 */
3699 jQuery(function () {
3700
3701 jQuery(document).on('click', '#mainwp-notes-cancel', function () {
3702 jQuery('#mainwp-notes-status').html('');
3703 jQuery('#mainwp-notes-status').removeClass('red green');
3704 mainwp_notes_hide();
3705 return false;
3706 });
3707
3708 jQuery(document).on('click', '#mainwp-notes-save', function () {
3709 let which = jQuery('#mainwp-which-note').val();
3710 if (which == 'site') {
3711 mainwp_notes_site_save();
3712 } else if (which == 'theme') {
3713 mainwp_notes_theme_save();
3714 } else if (which == 'plugin') {
3715 mainwp_notes_plugin_save();
3716 } else if (which == 'client') {
3717 mainwp_notes_client_save();
3718 }
3719 return false;
3720 });
3721
3722 jQuery(document).on('click', '.mainwp-edit-site-note', function () {
3723 let id = jQuery(this).attr('id').substring(13);
3724 let note = jQuery('#mainwp-notes-' + id + '-note').html();
3725 jQuery('#mainwp-notes-html').html(note == '' ? __('No saved notes. Click the Edit button to edit site notes.') : note);
3726 jQuery('#mainwp-notes-note').val(note);
3727 jQuery('#mainwp-notes-websiteid').val(id);
3728 jQuery('#mainwp-which-note').val('site'); // to fix conflict.
3729 mainwp_notes_show();
3730 if (jQuery(this).attr('add-new')) {
3731 jQuery('#mainwp-notes-edit').trigger("click");
3732 }
3733 return false;
3734 });
3735
3736 jQuery(document).on('click', '#mainwp-notes-edit', function () {
3737 jQuery('#mainwp-notes-html').hide();
3738 jQuery('#mainwp-notes-editor').show();
3739 jQuery(this).hide();
3740 jQuery('#mainwp-notes-save').show();
3741 jQuery('#mainwp-notes-status').html('');
3742 jQuery('#mainwp-notes-status').removeClass('red green');
3743 return false;
3744 });
3745 jQuery('#redirectForm').trigger("submit");
3746 if (jQuery('div.ui.open-site-close-window').length > 0) {
3747 setTimeout(function () {
3748 globalThis.close()
3749 }, 3000);
3750 }
3751 });
3752
3753 globalThis.mainwp_notes_show = function (reloadClose) {
3754 if (reloadClose) {
3755 jQuery('#mainwp-notes-modal').modal({
3756 onHide: function () {
3757 mainwp_forceReload();
3758 }
3759 }).modal('show');
3760 } else {
3761 jQuery('#mainwp-notes-modal').modal({ closable: false }).modal('show');
3762 }
3763
3764 jQuery('#mainwp-notes-html').show();
3765 jQuery('#mainwp-notes-editor').hide();
3766 jQuery('#mainwp-notes-save').hide();
3767 jQuery('#mainwp-notes-edit').show();
3768 };
3769 let mainwp_notes_hide = function () {
3770 jQuery('#mainwp-notes-modal').modal('hide');
3771 };
3772 let mainwp_notes_site_save = function () {
3773 let normalid = jQuery('#mainwp-notes-websiteid').val();
3774 let newnote = jQuery('#mainwp-notes-note').val();
3775 newnote = newnote.replaceAll(/\r\n|\r|\n/g, '<br>');
3776 let data = mainwp_secure_data({
3777 action: 'mainwp_notes_save',
3778 websiteid: normalid,
3779 note: newnote
3780 });
3781
3782 jQuery('#mainwp-notes-status').html('<i class="notched circle loading icon"></i> ' + __('Saving note. Please wait...')).show();
3783
3784 jQuery.post(ajaxurl, data, function (response) {
3785 if (response.error != undefined) {
3786 jQuery('#mainwp-notes-status').html(response.error).addClass('red');
3787 } else if (response.result == 'SUCCESS') {
3788 jQuery('#mainwp-notes-status').html(__('Note saved successfully.')).addClass('green');
3789 if (jQuery('#mainwp-notes-' + normalid + '-note').length > 0) {
3790 jQuery('#mainwp-notes-' + normalid + '-note').html(response?.esc_note_content ?? '');
3791 jQuery('#mainwp-notes-html').html(response?.esc_note_content ?? '');
3792 }
3793 } else {
3794 jQuery('#mainwp-notes-status').html(__('Undefined error occured while saving your note!')).addClass('red');
3795 }
3796 }, 'json');
3797
3798 setTimeout(function () {
3799 jQuery('#mainwp-notes-status').fadeOut(300);
3800 }, 3000);
3801
3802 jQuery('#mainwp-notes-html').show();
3803 jQuery('#mainwp-notes-editor').hide();
3804 jQuery('#mainwp-notes-save').hide();
3805 jQuery('#mainwp-notes-edit').show();
3806
3807 };
3808
3809 globalThis.getErrorMessage = function (pError, msgOnly) { // NOSONAR - complex.
3810 if (pError.message == 'HTTPERROR') {
3811 return __('HTTP error') + '! ' + pError.extra;
3812 } else if (pError.message == 'NOMAINWP' || pError == 'NOMAINWP') {
3813 return mainwp_js_get_error_not_detected_connect();
3814 } else if (pError.message == 'ERROR') {
3815 return 'ERROR' + ((pError.extra != '') && (pError.extra != undefined) ? ': ' + pError.extra : '');
3816 } else if (pError.message == 'WPERROR') {
3817 let extrMsg = (pError.extra != '') && (pError.extra != undefined) ? pError.extra : '';
3818 if (msgOnly != undefined && msgOnly && extrMsg != '') {
3819 return extrMsg;
3820 } else {
3821 return __('ERROR on the child site') + ': ' + extrMsg;
3822 }
3823
3824 } else if (pError.message != undefined && pError.message != '') {
3825 return pError.message;
3826 } else {
3827 return pError;
3828 }
3829 };
3830
3831 globalThis.getErrorMessageInfo = function (repError, outputType) { // NOSONAR - complex.
3832 let msg = '';
3833 let msgUI = '<i class="red times icon"></i>';
3834
3835 if (repError.errorCode != undefined && repError.errorCode == 'SUSPENDED_SITE') {
3836 msg = __('Suspended site.');
3837 msgUI = '<span data-inverted="" data-position="left center" data-tooltip="' + __('Suspended site.') + '"><i class="pause yellow icon"></i></span>';
3838 }
3839
3840 if (repError.errorCode != undefined && repError.errorCode == 'MAINWP_NOTICE') {
3841 if (repError.message != undefined) {
3842 msg = repError.message;
3843 msgUI = '<span data-inverted="" data-position="left center" data-tooltip="' + msg + '"><i class="pause circular yellow inverted icon"></i></span>';
3844 }
3845 }
3846
3847 if (msg == '') {
3848 msg = getErrorMessage(repError);
3849
3850 if (repError.message == 'NOMAINWP' || repError == 'NOMAINWP') {
3851 msg = mainwp_js_get_error_not_detected_connect();
3852 }
3853
3854 if (msg != '') {
3855 msgUI = '<span data-inverted="" data-position="left center" data-tooltip="' + msg + '"><i class="red times icon"></i></span>';
3856 }
3857 }
3858
3859 if (msg != '') {
3860 if (outputType != undefined && outputType == 'ui') {
3861 return msgUI;
3862 } else {
3863 return msg;
3864 }
3865 }
3866
3867 return repError;
3868 }
3869
3870 globalThis.dateToHMS = function (date) {
3871 if (mainwpParams?.time_format) {
3872 let time = moment(date);
3873 let format = mainwpParams['time_format'];
3874 format = format.replaceAll('g', 'h');
3875 format = format.replaceAll('i', 'mm');
3876 format = format.replaceAll('s', 'ss');
3877 format = format.replaceAll('F', 'MMMM');
3878 format = format.replaceAll('j', 'D');
3879 format = format.replaceAll('Y', 'YYYY');
3880 return time.format(format);
3881 }
3882 let h = date.getHours();
3883 let m = date.getMinutes();
3884 let s = date.getSeconds();
3885 return '' + (h <= 9 ? '0' + h : h) + ':' + (m <= 9 ? '0' + m : m) + ':' + (s <= 9 ? '0' + s : s);
3886 };
3887 globalThis.appendToDiv = function (pSelector, pText, pScrolldown, pShowTime) {
3888 if (pScrolldown == undefined)
3889 pScrolldown = true;
3890 if (pShowTime == undefined)
3891 pShowTime = true;
3892
3893 let theDiv = jQuery(pSelector);
3894 theDiv.append('<br />' + (pShowTime ? dateToHMS(new Date()) + ' ' : '') + pText);
3895 if (pScrolldown)
3896 theDiv.animate({ scrollTop: theDiv.prop("scrollHeight") }, 100);
3897 };
3898
3899 jQuery.fn.exists = function () {
3900 return (this.length !== 0);
3901 };
3902
3903
3904 function __(text, _var1, _var2, _var3) {
3905 if (text == undefined || text == '')
3906 return text;
3907 let strippedText = text.replaceAll(/\W/g, '_');
3908
3909 if (strippedText == '')
3910 return text.replace('%1', _var1).replace('%2', _var2).replace('%3', _var3);
3911
3912 if (mainwpTranslations == undefined)
3913 return text.replace('%1', _var1).replace('%2', _var2).replace('%3', _var3);
3914 if (mainwpTranslations[strippedText] == undefined)
3915 return text.replace('%1', _var1).replace('%2', _var2).replace('%3', _var3);
3916
3917 return mainwpTranslations[strippedText].replace('%1', _var1).replace('%2', _var2).replace('%3', _var3);
3918 }
3919
3920 globalThis.mainwp_secure_data = function (data, includeDts) {
3921 if (data['action'] == undefined)
3922 return data;
3923
3924 if (security_nonces[data['action']] == undefined)
3925 return data;
3926
3927 data['security'] = security_nonces[data['action']];
3928 if (includeDts)
3929 data['dts'] = Math.round(Date.now() / 1000);
3930 return data;
3931 };
3932
3933
3934 globalThis.mainwp_uid = function () {
3935 // always start with a letter (for DOM friendlyness)
3936 let idstr = String.fromCodePoint(Math.floor((Math.random() * 25) + 65)); // NOSONAR - safe, it's id.
3937 do {
3938 // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
3939 let ascicode = Math.floor((Math.random() * 42) + 48); // NOSONAR - safe, it's id.
3940 if (ascicode < 58 || ascicode > 64) {
3941 // exclude all chars between : (58) and @ (64)
3942 idstr += String.fromCodePoint(ascicode);
3943 }
3944 } while (idstr.length < 32);
3945
3946 return (idstr);
3947 };
3948
3949 globalThis.scrollToElement = function () {
3950 jQuery('html,body').animate({
3951 scrollTop: 0
3952 }, 1000);
3953
3954 return false;
3955 };
3956
3957 jQuery(function () {
3958 jQuery('#backup_filename').on('keypress', function (e) {
3959 let chr = String.fromCodePoint(e.which);
3960 return !"$^&*/".includes(chr);
3961 });
3962 jQuery('#backup_filename').on('change', function () {
3963 let value = jQuery(this).val();
3964 let notAllowed = ['$', '^', '&', '*', '/'];
3965 for (let char of notAllowed) {
3966 if (value.includes(char)) {
3967 value = value.replaceAll(char, '');
3968 jQuery(this).val(value);
3969 }
3970 }
3971 });
3972 });
3973
3974 /*
3975 * Server Info
3976 */
3977
3978 globalThis.serverinfo_prepare_download_info = function (communi) {
3979 let report = "";
3980 jQuery('.mainwp-system-info-table thead, .mainwp-system-info-table tbody').each(function () {
3981 let td_len = [35, 55, 45, 12, 12];
3982 let th_count = 0;
3983 let i;
3984 if (jQuery(this).is('thead')) {
3985 i = 0;
3986 report = report + "\n### ";
3987 th_count = jQuery(this).find('th:not(".mwp-not-generate-row")').length;
3988 jQuery(this).find('th:not(".mwp-not-generate-row")').each(function () {
3989 let len = td_len[i];
3990 if (i == 0 || i == th_count - 1)
3991 len = len - 4;
3992 report = report + jQuery.mwp_strCut(jQuery.mwp_get_serverinfo_export_text(jQuery(this), communi), len, ' ');
3993 i++;
3994 });
3995 report = report + " ###\n\n";
3996 } else {
3997 jQuery('tr', jQuery(this)).each(function () {
3998 if (communi && jQuery(this).hasClass('mwp-not-generate-row'))
3999 return;
4000 i = 0;
4001 jQuery(this).find('td:not(".mwp-not-generate-row")').each(function () {
4002 if (jQuery(this).hasClass('mwp-hide-generate-row')) {
4003 report = report + jQuery.mwp_strCut(' ', td_len[i], ' ');
4004 i++;
4005 return;
4006 }
4007 let outputText = jQuery.mwp_get_serverinfo_export_text(jQuery(this), communi);
4008 report = report + jQuery.mwp_strCut(outputText, td_len[i], ' ');
4009 i++;
4010 });
4011 report = report + "\n";
4012 });
4013
4014 }
4015 });
4016
4017 try {
4018 if (communi) {
4019 report = '```' + "\n" + report + "\n" + '```';
4020 }
4021 jQuery("#download-server-information textarea").val(report).trigger("select");
4022 } catch {
4023 console.log('Error:');
4024 }
4025 return false;
4026 }
4027
4028 jQuery.mwp_get_serverinfo_export_text = function (element, communi) {
4029 let cellExportText = element.attr('data-export-text');
4030 if (typeof cellExportText !== 'undefined' && cellExportText !== '') {
4031 return cellExportText.trim();
4032 }
4033
4034 let descendantExportElement = element.find('[data-export-text]').first();
4035 if (descendantExportElement.length > 0) {
4036 let descendantExportText = descendantExportElement.attr('data-export-text');
4037 if (typeof descendantExportText !== 'undefined' && descendantExportText !== '') {
4038 return descendantExportText.trim();
4039 }
4040 }
4041
4042 let communityValue = element.attr('data-community-value');
4043 if (communi && typeof communityValue !== 'undefined') {
4044 return communityValue;
4045 }
4046
4047 return element.text().trim();
4048 }
4049
4050 jQuery(document).on('click', '#mainwp-download-system-report', function () {
4051 serverinfo_prepare_download_info(false);
4052 let server_info = jQuery('#download-server-information textarea').val();
4053 let blob = new Blob([server_info], { type: "text/plain;charset=utf-8" });
4054 saveAs(blob, "mainwp-system-report.txt");
4055 return false;
4056 });
4057 jQuery(document).on('click', '#mainwp-download-community-system-report', function () {
4058 serverinfo_prepare_download_info(true);
4059 let server_info = jQuery('#download-server-information textarea').val();
4060 let blob = new Blob([server_info], { type: "text/plain;charset=utf-8" });
4061 saveAs(blob, "mainwp-community-system-report.txt");
4062 return false;
4063 });
4064
4065
4066 jQuery.mwp_strCut = function (i, l, s, w) {
4067 let o = i.toString();
4068 if (!s) {
4069 s = '0';
4070 }
4071 while (o.length < Number.parseInt(l)) {
4072 // empty
4073 if (w == 'undefined') {
4074 o = s + o;
4075 } else {
4076 o = o + s;
4077 }
4078 }
4079 return o;
4080 };
4081
4082 globalThis.updateExcludedFolders = function () {
4083 let excludedBackupFiles = jQuery('#excludedBackupFiles').html();
4084 jQuery('#mainwp-kbl-content').val(excludedBackupFiles == undefined ? '' : excludedBackupFiles);
4085
4086 let excludedCacheFiles = jQuery('#excludedCacheFiles').html();
4087 jQuery('#mainwp-kcl-content').val(excludedCacheFiles == undefined ? '' : excludedCacheFiles);
4088
4089 let excludedNonWPFiles = jQuery('#excludedNonWPFiles').html();
4090 jQuery('#mainwp-nwl-content').val(excludedNonWPFiles == undefined ? '' : excludedNonWPFiles);
4091 };
4092
4093
4094 jQuery(document).on('click', '.mainwp-events-notice-dismiss', function () {
4095 let notice = jQuery(this).attr('notice');
4096 jQuery(this).closest('.ui.message').fadeOut(500);
4097 let data = mainwp_secure_data({
4098 action: 'mainwp_events_notice_hide',
4099 notice: notice
4100 });
4101 jQuery.post(ajaxurl, data, function () {
4102 });
4103 return false;
4104 });
4105
4106 // Turn On child plugin auto update
4107 jQuery(document).on('click', '#mainwp_btn_autoupdate_and_trust', function () {
4108 jQuery(this).attr('disabled', 'true');
4109 let data = mainwp_secure_data({
4110 action: 'mainwp_autoupdate_and_trust_child'
4111 });
4112 jQuery.post(ajaxurl, data, function (res) {
4113 if (res == 'ok') {
4114 location.reload(true);
4115 } else {
4116 jQuery(this).prop("disabled", false);
4117 }
4118 });
4119 return false;
4120 });
4121
4122 // Hide installation warning
4123 jQuery(document).on('click', '#remove-mainwp-installation-warning', function () {
4124 jQuery(this).closest('.ui.message').fadeOut("slow");
4125 let data = mainwp_secure_data({
4126 action: 'mainwp_installation_warning_hide'
4127 });
4128 jQuery.post(ajaxurl, data, function () { });
4129 return false;
4130 });
4131
4132 jQuery(document).on('click', '.mainwp-notice-hide', function () {
4133 jQuery(this).closest('.ui.message').fadeOut("slow");
4134 return false;
4135 });
4136
4137 // Hide after installtion notices (PHP version, Trust MainWP Child, Multisite Warning and OpenSSL warning)
4138 jQuery(document).on('click', '.mainwp-notice-dismiss', function () {
4139 let notice_id = jQuery(this).attr('notice-id');
4140 jQuery(this).closest('.ui.message').fadeOut("slow");
4141 let data = {
4142 action: 'mainwp_notice_status_update'
4143 };
4144 data['notice_id'] = notice_id;
4145 jQuery.post(ajaxurl, mainwp_secure_data(data), function () { });
4146 return false;
4147 });
4148
4149
4150 globalThis.mainwp_notice_dismiss = function (notice_id, time_set) {
4151 let data = {
4152 action: 'mainwp_notice_status_update'
4153 };
4154 data['notice_id'] = notice_id;
4155 if ( time_set !== undefined ) {
4156 data['time_set'] = time_set ? 1 : 0;
4157 }
4158 jQuery.post(ajaxurl, mainwp_secure_data(data), function () {
4159 });
4160 return false;
4161 }
4162
4163
4164 jQuery(document).on('click', '.mainwp-activate-notice-dismiss', function () {
4165 jQuery(this).closest('tr').fadeOut("slow");
4166 let data = mainwp_secure_data({
4167 action: 'mainwp_dismiss_activate_notice',
4168 slug: jQuery(this).closest('tr').attr('slug')
4169 });
4170 jQuery.post(ajaxurl, data, function () {
4171 });
4172 return false;
4173 });
4174
4175 jQuery(document).on('click', '.mainwp-install-check-dismiss', function () {
4176 let notice_id = jQuery(this).attr('notice-id');
4177 jQuery(this).closest('.ui.message').fadeOut("slow");
4178 let data = {
4179 action: 'mainwp_notice_status_update'
4180 };
4181 data['notice_id'] = notice_id;
4182 jQuery.post(ajaxurl, mainwp_secure_data(data), function () { });
4183 return false;
4184 });
4185
4186 jQuery(document).on('click', '#mainwp-dismiss-sites-changes-actions-button', function () {
4187 mainwp_confirm('You are about to dismiss the selected changes?', function () {
4188 mainwp_delete_nonmainwp_data_start();
4189 });
4190 return false;
4191 });
4192
4193 let mainwp_managesites_update_childsite_value = function (siteId, uniqueId) {
4194 let data = mainwp_secure_data({
4195 action: 'mainwp_updatechildsite_value',
4196 site_id: siteId,
4197 unique_id: uniqueId
4198 });
4199 jQuery.post(ajaxurl, data, function () {
4200 });
4201 return false;
4202 };
4203
4204 jQuery(document).on('keyup', '#managegroups-filter', function () {
4205 let filter = jQuery(this).val();
4206 let groupItems = jQuery(this).parent().parent().find('li.managegroups-listitem');
4207 for (let igr of groupItems) {
4208 let currentElement = jQuery(igr);
4209 if (currentElement.hasClass('managegroups-group-add')) {
4210 continue;
4211 }
4212 let value = currentElement.find('span.text').text();
4213 if (value.includes(filter)) {
4214 currentElement.show();
4215 } else {
4216 currentElement.hide();
4217 }
4218 }
4219 });
4220
4221 // for normal checkboxes
4222 jQuery(document).on('change', '#cb-select-all-top, #cb-select-all-bottom', function () {
4223 let $this = jQuery(this), $table, controlChecked = $this.prop('checked');
4224
4225 $table = $this.closest('.dt-scroll').find('.dt-scroll-body table'); // for dt with scroll enabled.
4226
4227 // if no scrollable table.
4228 if ($table.length == 0) {
4229 $table = $this.closest('table.table.dataTable');
4230 }
4231
4232 if ($table.length == 0)
4233 return false;
4234
4235 $table.children('tbody').filter(':visible')
4236 .children().children('.check-column').find(':checkbox')
4237 .prop('checked', function () {
4238 if (jQuery(this).is(':hidden,:disabled')) {
4239 return false;
4240 }
4241 if (controlChecked) {
4242 jQuery(this).closest('tr').addClass('selected');
4243 return true;
4244 }
4245 jQuery(this).closest('tr').removeClass('selected');
4246 return false;
4247 });
4248
4249 $table.children('thead, tfoot').filter(':visible')
4250 .children().children('.check-column').find(':checkbox')
4251 .prop('checked', function () {
4252 if (controlChecked) {
4253 jQuery(this).closest('tr').addClass('selected');
4254 return true;
4255 }
4256 jQuery(this).closest('tr').removeClass('selected');
4257 return false;
4258 });
4259 let dtApi = jQuery($table).dataTable().api();
4260 let setStatus = controlChecked ? 'selected' : 'deselected';
4261 mainwp_datatable_fix_to_update_selected_rows_status(dtApi, setStatus);
4262 });
4263
4264
4265 jQuery(document).on('change', '.cb-select-all-parent-top, .cb-select-all-parent-bottom', function () {
4266
4267 let parentChecked = jQuery(this).is(":checked");
4268 let parentSelector = jQuery(this).attr('cb-parent-selector') ?? false;
4269
4270 if (false === parentSelector) {
4271 return;
4272 }
4273 jQuery(parentSelector + ' .ui.checkbox').find(':checkbox')
4274 .prop('checked', function () {
4275 if (parentChecked) {
4276 jQuery(this).closest('tr').addClass('selected');
4277 return true;
4278 }
4279 jQuery(this).closest('tr').removeClass('selected');
4280 return false;
4281 });
4282
4283 });
4284
4285 jQuery(function ($) {
4286 // Trigger the bulk actions
4287 $('#mainwp_sites_changes_bulk_dismiss_selected_btn').on('click', function () {
4288 if (jQuery('#mainwp-module-log-records-body-table tr').find('input[type="checkbox"]:checked').length == 0) {
4289 return;
4290 }
4291 let confirmMsg = __("You are about to dismiss the selected changes?");
4292 mainwp_confirm(confirmMsg, function () { mainwp_sites_changes_actions_bulk_action('dismiss-selected'); });
4293 });
4294
4295 $('#mainwp_sites_changes_bulk_dismiss_all_btn').on('click', function () {
4296 let confirmMsg = __("You are about to dismiss all changes?");
4297 mainwp_confirm(confirmMsg, function () { mainwp_sites_changes_actions_bulk_action('dismiss-all'); });
4298 });
4299
4300 // Trigger the bulk actions
4301 $('#mainwp_widget_sites_changes_bulk_dismiss_selected_btn').on('click', function () {
4302 if (jQuery('#mainwp-module-log-records-body-table tr').find('input[type="checkbox"]:checked').length == 0) {
4303 return;
4304 }
4305 let confirmMsg = __("You are about to dismiss the selected changes?");
4306 mainwp_confirm(confirmMsg, function () { mainwp_sites_changes_actions_bulk_action('dismiss-selected', 'widget'); });
4307 });
4308
4309 $(document).on('click', '.insights-actions-row-dismiss', function () {
4310 return mainwp_insights_row_actions_dismiss(this);
4311 });
4312
4313 globalThis.mainwp_sites_changes_update_dismiss_button_state = function () {
4314 let checkedCount = jQuery('#mainwp-module-log-records-body-table tr').find('input[type="checkbox"]:checked').length;
4315 let totalRows = jQuery('#mainwp-module-log-records-body-table tr').not('.dt-empty').length;
4316
4317 if (checkedCount > 0) {
4318 jQuery('#mainwp_sites_changes_bulk_dismiss_selected_btn').removeClass('disabled');
4319 } else {
4320 jQuery('#mainwp_sites_changes_bulk_dismiss_selected_btn').addClass('disabled');
4321 }
4322
4323 if (totalRows > 0) {
4324 jQuery('#mainwp_sites_changes_bulk_dismiss_all_btn').removeClass('disabled');
4325 } else {
4326 jQuery('#mainwp_sites_changes_bulk_dismiss_all_btn').addClass('disabled');
4327 }
4328 }
4329
4330 jQuery(document).on('change', '#mainwp-module-log-records-body-table input[type="checkbox"]', function () {
4331 mainwp_sites_changes_update_dismiss_button_state();
4332 });
4333
4334 jQuery(document).on('change', '#cb-select-all-top, #cb-select-all-bottom', function () {
4335 mainwp_sites_changes_update_dismiss_button_state();
4336 });
4337 })
4338
4339 let mainwp_insights_row_actions_dismiss = function (obj) {
4340 let row = jQuery(obj).closest('tr');
4341 let confirmMsg = __("You are about to dismiss the selected change?");
4342
4343 const renderMessage = (icon, message) => {
4344 row.html(
4345 '<td></td><td colspan="999"><i class="' +
4346 icon +
4347 ' icon"></i> ' +
4348 message +
4349 '</td>'
4350 );
4351 };
4352
4353 const updateDismissButtonState = () => {
4354 if (typeof mainwp_sites_changes_update_dismiss_button_state !== 'undefined') {
4355 mainwp_sites_changes_update_dismiss_button_state();
4356 }
4357 };
4358
4359 const fadeRow = () => {
4360 setTimeout(() => {
4361 jQuery(row).fadeOut('slow', updateDismissButtonState);
4362 }, 2000);
4363 };
4364
4365 let _callback = () => {
4366 row.html('<td></td><td colspan="999"><i class="notched circle loading icon"></i> Please wait...</td>');
4367 let data = mainwp_secure_data({
4368 action: 'mainwp_insight_events_dismiss_actions',
4369 log_id: jQuery(row).attr('log-id')
4370 });
4371 jQuery.post(ajaxurl, data, function (response) {
4372 if (response?.success !== 'yes') {
4373
4374 if (response?.error) {
4375 renderMessage('times red', response.error);
4376 } else {
4377 renderMessage('times red', 'The change could not be dismissed.');
4378 }
4379
4380 return;
4381 }
4382 renderMessage('green check', 'The change has been dismissed.');
4383 fadeRow();
4384 }, 'json');
4385 };
4386 mainwp_confirm(confirmMsg, _callback);
4387 return false;
4388 }
4389
4390
4391 // Manage Bulk Actions
4392 let mainwp_sites_changes_actions_bulk_action = function (act, which_act) {
4393 mainwpVars.bulkInstallTotal = 0;
4394 bulkInstallCurrentThreads = 0;
4395 bulkInstallDone = 0;
4396 mainwpVars.bulkActionIndent = '';
4397 if (which_act === 'widget') {
4398 mainwpVars.bulkActionIndent = 'widget';
4399 }
4400 if (act === 'dismiss-selected') {
4401 jQuery('#mainwp_sites_changes_bulk_dismiss_selected_btn').addClass('disabled');
4402 let selector = '#mainwp-module-log-records-body-table tr';
4403 mainwpVars.bulkInstallTotal = jQuery(selector).find('input[type="checkbox"]:checked').length;
4404 jQuery(selector).addClass('queue');
4405 if (jQuery(selector).length) {
4406 if (mainwpVars.bulkActionIndent === 'widget') {
4407 jQuery('#mainwp_widget_sites_changes_bulk_dismiss_selected_btn').addClass('disabled');
4408 } else {
4409 jQuery('#mainwp_sites_changes_bulk_dismiss_selected_btn').addClass('disabled');
4410 }
4411 }
4412 mainwp_sites_changes_actions_dismiss_start_next(selector);
4413 } else if (act === 'dismiss-all') {
4414 jQuery('#mainwp_sites_changes_bulk_dismiss_all_btn').addClass('disabled');
4415 mainwp_sites_changes_actions_dismiss_all();
4416 }
4417 }
4418
4419 let mainwp_sites_changes_actions_dismiss_start_next = function (selector) {
4420 while ((objProcess = jQuery(selector + '.queue:first')) && (objProcess.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR - modified outside the function.
4421 objProcess.removeClass('queue');
4422 if (objProcess.closest('tr').find('input[type="checkbox"]:checked').length == 0) {
4423 continue;
4424 }
4425 mainwp_sites_changes_actions_dismiss_specific(objProcess, selector);
4426 }
4427
4428 if (mainwpVars.bulkInstallTotal == bulkInstallDone) {
4429 if (mainwpVars.bulkActionIndent === 'widget') {
4430 jQuery('#mainwp_widget_sites_changes_bulk_dismiss_selected_btn').removeClass('disabled');
4431 } else {
4432 jQuery('#mainwp_sites_changes_bulk_dismiss_selected_btn').removeClass('disabled');
4433 }
4434 if (typeof mainwp_sites_changes_update_dismiss_button_state !== 'undefined') {
4435 mainwp_sites_changes_update_dismiss_button_state();
4436 }
4437 }
4438 }
4439
4440 let mainwp_sites_changes_actions_dismiss_specific = function (pObj, selector) {
4441 let row = pObj.closest('tr');
4442 let act_id = jQuery(row).attr('log-id');
4443
4444 bulkInstallCurrentThreads++;
4445
4446 let data = mainwp_secure_data({
4447 action: 'mainwp_insight_events_dismiss_actions',
4448 log_id: act_id
4449 });
4450
4451 row.html('<td></td><td colspan="999"><i class="notched circle loading icon"></i> Please wait...</td>');
4452
4453 jQuery.post(ajaxurl, data, function (response) {
4454 pObj.removeClass('queue');
4455 if (response) {
4456 if (response['error']) {
4457 row.html('<td></td><td colspan="999"><i class="times red icon"></i> ' + response['error'] + '</td>');
4458 } else if (response['success'] == 'yes') {
4459 row.html('<td></td><td colspan="999"><i class="green check icon"></i> The change has been dismissed.</td>');
4460 setTimeout(function () {
4461 jQuery(row).fadeOut("slow");
4462 }, 2000);
4463 } else {
4464 row.html('<td></td><td colspan="999"><i class="times red icon"></i> Failed. Please try again.</td>');
4465 }
4466 } else {
4467 row.html('<td></td><td colspan="999"><i class="times red icon"></i> Failed. Please try again.</td>');
4468 }
4469
4470 bulkInstallCurrentThreads--;
4471 bulkInstallDone++;
4472 mainwp_sites_changes_actions_dismiss_start_next(selector);
4473 }, 'json');
4474 return false;
4475 }
4476
4477 let mainwp_sites_changes_actions_dismiss_all = function () {
4478 let data = mainwp_secure_data({
4479 action: 'mainwp_insight_events_dismiss_all',
4480 });
4481 mainwp_showhide_message('mainwp-message-zone-top', '<i class="notched circle loading icon"></i> Please wait...', '');
4482 jQuery.post(ajaxurl, data, function (response) {
4483 if (response) {
4484 if (response['error']) {
4485 mainwp_showhide_message('mainwp-message-zone-top', response['error'], 'red');
4486 } else if (response['success'] == 'yes') {
4487 mainwp_showhide_message('mainwp-message-zone-top', 'All changes have been dismissed.', 'green');
4488 setTimeout(function () {
4489 mainwp_forceReload();
4490 }, 2000);
4491 } else {
4492 mainwp_showhide_message('mainwp-message-zone-top', 'Failed. Please try again.', 'red');
4493 }
4494 } else {
4495 mainwp_showhide_message('mainwp-message-zone-top', 'Failed. Please try again.', 'red');
4496 }
4497 }, 'json');
4498 return false;
4499
4500 }
4501
4502
4503 globalThis.mainwp_datatable_fix_to_update_selected_rows_status = function (dtApi, setStatus) {
4504 if (dtApi) {
4505 if ('selected' === setStatus) {
4506 dtApi.rows('.selected').select(); // update selected status.
4507 } else if ('deselected' === setStatus) {
4508 dtApi.rows().deselect(); // update deselected status.
4509 }
4510 }
4511 }
4512
4513 globalThis.mainwp_datatable_fix_to_update_rows_state = function (tblSelect) {
4514 if (jQuery(tblSelect).length) {
4515 let $table = jQuery(tblSelect);
4516
4517 let dtApi = jQuery($table).dataTable().api(); // NOTE: not use DataTable().
4518
4519 mainwp_datatable_fix_to_update_selected_rows_status(dtApi, 'deselected'); // clear saved state.
4520
4521 $table.children('tbody').filter(':visible').find('tr').each(function () {
4522 if (jQuery(this).children('.check-column').find(':checkbox').is(':checked')) {
4523 jQuery(this).addClass('selected');
4524 } else if (jQuery(this).hasClass('selected')) {
4525 jQuery(this).removeClass('selected');
4526 }
4527 });
4528
4529 mainwp_datatable_fix_to_update_selected_rows_status(dtApi, 'selected'); // to update selected state.
4530 }
4531 }
4532
4533 globalThis.mainwp_datatable_fix_reorder_selected_rows_status = function () {
4534 jQuery('.table.dataTable tbody').filter(':visible').children('tr.selected').find(':checkbox').prop('checked', true);
4535 };
4536
4537 // fix menu overflow with scroll tables.
4538 globalThis.mainwp_datatable_fix_menu_overflow = function (pTableSelector, pTop, pRight) {
4539 if (pTableSelector === undefined) {
4540 console.warn('mainwp_datatable_fix_menu_overflow: requires params - $pTableSelector');
4541 }
4542 let dtScrollBdCls = '.dt-scroll-body';
4543 let dtScrollCls = '.dt-scroll';
4544 let fix_overflow = jQuery('.mainwp-content-wrap').attr('menu-overflow');
4545 jQuery(document).on('click', 'table td.check-column.dtr-control', function () {
4546 if (jQuery(this).parent().hasClass('parent')) {
4547 let chilRow = jQuery(this).parent().next();
4548 jQuery(chilRow).find('.ui.dropdown').dropdown();
4549 mainwp_datatable_fix_child_menu_overflow(chilRow, fix_overflow);
4550 }
4551 });
4552 let tblSelect = pTableSelector ?? 'table';
4553
4554 // to prevent double events.
4555 jQuery(tblSelect + ' tr td .ui.right.pointing.dropdown').each(function () {
4556 let parentTB = jQuery(this).closest('table');
4557 if (parentTB.attr('fixed-menu-overflow') === undefined) {
4558 parentTB.attr('fixed-menu-overflow', 'no'); // to init click menu events.
4559 }
4560 });
4561
4562 jQuery(tblSelect + ' tr td .ui.left.pointing.dropdown').each(function () {
4563 let parentTB = jQuery(this).closest('table');
4564 if (parentTB.attr('fixed-menu-overflow') === undefined) {
4565 parentTB.attr('fixed-menu-overflow', 'no'); // to init click menu events.
4566 }
4567 });
4568
4569 // if table selector specific.
4570 if (pTableSelector !== undefined) {
4571 if (jQuery(pTableSelector + '[fixed-menu-overflow="yes"]').length) {
4572 jQuery(pTableSelector + '[fixed-menu-overflow="yes"]').attr('fixed-menu-overflow', 'no'); // to init menus events click.
4573 }
4574 }
4575
4576
4577 // Fix the overflow prbolem for the actions menu element (right pointing menu).
4578 jQuery(tblSelect + '[fixed-menu-overflow="no"] tr td .ui.right.pointing.dropdown').on('click', function () {
4579 jQuery(this).closest(dtScrollBdCls).css('position', '');
4580 jQuery(this).closest(dtScrollCls).css('position', 'relative');
4581 jQuery(this).css('position', 'static');
4582 let fix_overflow = jQuery('.mainwp-content-wrap').attr('menu-overflow');
4583 let position = jQuery(this).position();
4584 let top = position.top;
4585 let right = 50;
4586 if (fix_overflow > 1) {
4587 position = jQuery(this).closest('td').position();
4588 top = position.top + 85; //85
4589 }
4590
4591 if (pTop !== undefined) {
4592 top = top + pTop;
4593 }
4594 if (pRight !== undefined) {
4595 right = right + pRight;
4596 }
4597
4598 jQuery(this).find('.menu').css('min-width', '170px');
4599 jQuery(this).find('.menu').css('top', top);
4600 jQuery(this).find('.menu')[0].style.setProperty('right', right + 'px', 'important');
4601 });
4602
4603 // Fix the overflow prbolem for the actions menu element (left pointing menu).
4604 jQuery(tblSelect + '[fixed-menu-overflow="no"] tr td .ui.left.pointing.dropdown').on('click', function () {
4605 jQuery(this).closest(dtScrollBdCls).css('position', '');
4606 jQuery(this).closest(dtScrollCls).css('position', 'relative');
4607 jQuery(this).css('position', 'static');
4608 let position = jQuery(this).position();
4609
4610 let top = position.top;
4611 let left = position.left - 159;
4612
4613 if (fix_overflow > 1) {
4614 position = jQuery(this).closest('td').position();
4615 let scroll_left = jQuery(this).closest(dtScrollBdCls).scrollLeft();
4616 top = position.top + 85;
4617 left = position.left - scroll_left - 145;
4618 }
4619
4620 if (pTop !== undefined) {
4621 top = top + pTop;
4622 }
4623
4624 jQuery(this).find('.menu').css('min-width', '150px');
4625 jQuery(this).removeClass('left');
4626 jQuery(this).addClass('right');
4627 jQuery(this).find('.menu').css('top', top);
4628 jQuery(this).find('.menu')[0].style.setProperty('left', left + 'px', 'important');
4629 });
4630
4631 jQuery(tblSelect + '[fixed-menu-overflow="no"]').each(function () {
4632 jQuery(this).attr('fixed-menu-overflow', 'yes');
4633 });
4634
4635 mainwp_datatable_fix_reorder_selected_rows_status();
4636 }
4637
4638
4639 let mainwp_datatable_fix_child_menu_overflow = function (chilRow, fix_overflow) {
4640 let dtScrollBdCls = '.dt-scroll-body';
4641 let dtScrollCls = '.dt-scroll';
4642 // Fix the overflow prbolem for the actions child menu element (pointing menu).
4643 jQuery(chilRow).find('.ui.pointing.dropdown').on('click', function () {
4644
4645 let position = jQuery(this).position();
4646 let left = position.left + 30;
4647 let top = position.top;
4648
4649 if (fix_overflow > 1) {
4650 position = jQuery(this).closest('td.child').position();
4651 top = position.top + jQuery(this).closest('td.child').height() + 85;
4652 }
4653
4654 jQuery(this).closest(dtScrollBdCls).css('position', '');
4655 jQuery(this).closest(dtScrollCls).css('position', 'relative');
4656 jQuery(this).css('position', 'static');
4657 jQuery(this).find('.menu').css('top', top);
4658 jQuery(this).find('.menu').css('left', left);
4659 jQuery(this).find('.menu').css('min-width', '170px');
4660 });
4661 }
4662
4663
4664 globalThis.mainwp_responsive_fix_remove_child_row = function (el) {
4665 if (jQuery(el).hasClass('dt-hasChild')) { // to fix.
4666 jQuery(el).next().remove();
4667 }
4668 }
4669
4670 /* eslint-disable complexity */
4671 function mainwp_according_table_sorting(pObj) { // NOSONAR - complex.
4672 let table, th, rows, switching, i, x, y, xVal, yVal, campare = false, shouldSwitch = false, dir, switchcount = 0, n, skip = 1;
4673 table = jQuery(pObj).closest('table')[0];
4674 let subline_skip = 2;
4675 if ('mainwp-wordpress-updates-table' == jQuery(table).attr('id')) {
4676 subline_skip = 1; // for rows without subline.
4677 skip = 0;
4678 }
4679
4680 // get TH element
4681 if (jQuery(pObj)[0].tagName == 'TH') {
4682 th = jQuery(pObj)[0];
4683 } else {
4684 th = jQuery(pObj).closest('th')[0];
4685 }
4686
4687 n = th.cellIndex;
4688 switching = true;
4689
4690 // check header and footer of according table
4691 if (jQuery(table).children('thead,tfoot').length > 0)
4692 skip += jQuery(table).children('thead,tfoot').length; // skip sorting header, footer
4693
4694 dir = "asc";
4695 /* loop until switching has been done: */
4696 while (switching) {
4697 switching = false;
4698 rows = table.rows;
4699 /* Loop through all table rows */
4700 for (i = 1; i < (rows.length - skip); i += subline_skip) { // skip content according rows, sort by title rows only
4701 shouldSwitch = false;
4702 /* Get the two elements you want to compare,
4703 one from current row and one from the next-next: */
4704 x = rows[i].getElementsByTagName("TD")[n];
4705 y = rows[i + subline_skip].getElementsByTagName("TD")[n];
4706
4707 // if sort value attribute existed then sorting on that else sorting on cell value
4708 if (x.hasAttribute('sort-value')) {
4709 xVal = Number.parseInt(x.getAttribute('sort-value'));
4710 yVal = Number.parseInt(y.getAttribute('sort-value'));
4711 let tmp = xVal > yVal ? -1 : 1;
4712 campare = (xVal == yVal) ? 0 : tmp;
4713 } else {
4714 // to prevent text() clear text content
4715 xVal = '<p>' + x.innerHTML + '</p>';
4716 yVal = '<p>' + y.innerHTML + '</p>';
4717 xVal = jQuery(xVal).text().trim().toLowerCase();
4718 yVal = jQuery(yVal).text().trim().toLowerCase();
4719 campare = yVal.localeCompare(xVal);
4720 }
4721
4722 /* Check if the two rows should switch place */
4723 if (dir == "asc") {
4724 if (campare < 0) { //xVal > yVal
4725 shouldSwitch = true;
4726 // break the loop:
4727 break;
4728 }
4729 } else if (dir == "desc") {
4730 if (campare > 0) { //xVal < yVal
4731 // break the loop:
4732 shouldSwitch = true;
4733 break;
4734 }
4735 }
4736 }
4737 if (shouldSwitch) {
4738 if (2 == subline_skip) {
4739 rows[i].parentNode.insertBefore(rows[i + 2], rows[i]);
4740 rows[i + 1].parentNode.insertBefore(rows[i + 3], rows[i + 1]);
4741 } else {
4742 rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); // switch 2 rows.
4743 }
4744 switching = true;
4745 // increase this count by 1, that is ok
4746 switchcount++;
4747 } else if (switchcount == 0 && dir == "asc") {
4748 /* If no switching has been done AND the direction is "asc",
4749 set the direction to "desc" and run the while loop again. */
4750 dir = "desc";
4751 switching = true;
4752 }
4753 }
4754
4755 // no row sorting so change direction for arrows switch
4756 if (switchcount == 0) {
4757 if (jQuery(pObj).hasClass('ascending')) {
4758 dir = "desc";
4759 } else {
4760 dir = "asc";
4761 }
4762 }
4763
4764 // add/remove class for arrows displaying
4765 if (dir == "asc") {
4766 jQuery(pObj).addClass('ascending');
4767 jQuery(pObj).removeClass('descending');
4768 } else {
4769 jQuery(pObj).removeClass('ascending');
4770 jQuery(pObj).addClass('descending');
4771 }
4772 }
4773 /* eslint-enable complexity */
4774
4775 jQuery(function () {
4776 jQuery('.handle-accordion-sorting').on('click', function () {
4777 mainwp_according_table_sorting(this);
4778 return false;
4779 });
4780 });
4781
4782 // Force Dashboard to reestablish connection by destroying sessions - Part 1
4783 let mainwp_force_destroy_sessions = function () {
4784 let confirmMsg = __('Are you sure you want to force your MainWP Dashboard to reconnect with your child sites?');
4785 mainwp_confirm(confirmMsg, function () {
4786 mainwp_force_destroy_sessions_websites = jQuery('.dashboard_wp_id[error-status=0]').map(function (indx, el) {
4787 return jQuery(el).val();
4788 });
4789 mainwpPopup('#mainwp-sync-sites-modal').setTitle(__('Re-establish Connection')); // popup displayed.
4790 mainwpPopup('#mainwp-sync-sites-modal').init({ progressMax: mainwp_force_destroy_sessions_websites.length });
4791 mainwp_force_destroy_sessions_part_2(0);
4792 });
4793 };
4794
4795 let mainwp_force_destroy_sessions_part_2 = function (id) {
4796 if (id >= mainwp_force_destroy_sessions_websites.length) {
4797 mainwp_force_destroy_sessions_websites = [];
4798 if (mainwp_force_destroy_sessions_successed == mainwp_force_destroy_sessions_websites.length) {
4799 setTimeout(function () {
4800 mainwpPopup('#mainwp-sync-sites-modal').close(true);
4801 }, 3000);
4802 }
4803 mainwpPopup('#mainwp-sync-sites-modal').close(true);
4804 return;
4805 }
4806
4807 let website_id = mainwp_force_destroy_sessions_websites[id];
4808 dashboard_update_site_status(website_id, '<i class="sync alternate loading icon"></i>');
4809
4810 jQuery.post(ajaxurl, { 'action': 'mainwp_force_destroy_sessions', 'website_id': website_id, 'security': security_nonces['mainwp_force_destroy_sessions'] }, function (response) {
4811 let counter = id + 1;
4812 mainwp_force_destroy_sessions_part_2(counter);
4813
4814 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(counter);
4815
4816 if ('error' in response) {
4817 dashboard_update_site_status(website_id, '<i class="exclamation red icon"></i>');
4818 } else if ('success' in response) {
4819 mainwp_force_destroy_sessions_successed += 1;
4820 dashboard_update_site_status(website_id, '<i class="check green icon"></i>', true);
4821 } else {
4822 dashboard_update_site_status(website_id, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Process timed out. Please try again.', 'mainwp') + '">');
4823 }
4824 }, 'json').fail(function () {
4825 let counter = id + 1;
4826 mainwp_force_destroy_sessions_part_2(counter);
4827 mainwpPopup('#mainwp-sync-sites-modal').setProgressSite(counter);
4828
4829 dashboard_update_site_status(website_id, '<i class="exclamation red icon"></i>');
4830 });
4831
4832 };
4833
4834 let mainwp_force_destroy_sessions_successed = 0;
4835 let mainwp_force_destroy_sessions_websites = [];
4836
4837
4838 jQuery(document).on('change', '#mainwp_archiveFormat', function () {
4839 let zipMethod = jQuery(this).val();
4840 zipMethod = zipMethod.replaceAll('.', '\\.'); // NOSONAR - escape is correct.
4841 jQuery('span.archive_info').hide();
4842 jQuery('span#info_' + zipMethod).show();
4843
4844 jQuery('tr.archive_method').hide();
4845 jQuery('tr.archive_' + zipMethod).show();
4846
4847 // compare new layout
4848 jQuery('div.archive_method').hide();
4849 jQuery('div.archive_' + zipMethod).show();
4850 });
4851
4852 let mainwp_import_demo_data_action = function (obj) {
4853 let confirmation = "Are you sure you want to import demo content into your MainWP Dashboard?";
4854 let msg_import = (jQuery(obj).attr('page-import') == 'qsw-import') ? '&message=qsw-import' : '';
4855 mainwp_confirm(confirmation, function () {
4856 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Importing. Please wait...', 'mainwp'), '');
4857 let data = mainwp_secure_data({
4858 action: 'mainwp_import_demo_data',
4859 });
4860
4861 jQuery.post(ajaxurl, data, function (response) {
4862 let error = false;
4863 if (response.count === undefined) {
4864 error = true;
4865 feedback('mainwp-message-zone', __('Undefined error. Please try again.', 'mainwp'), 'green');
4866 } else {
4867 feedback('mainwp-message-zone', __('The demo content has been imported into your MainWP Dashboard.', 'mainwp'), 'green');
4868 }
4869
4870 if (!error) {
4871 setTimeout(function () {
4872 mainwp_forceReload('admin.php?page=mainwp_tab' + msg_import);
4873 }, 3000);
4874 }
4875 }, 'json');
4876 });
4877 }
4878
4879 let mainwp_remove_demo_data_action = function () {
4880 let confirmation = "Are you sure you want to delete demo content from your MainWP Dashboard?";
4881 mainwp_confirm(confirmation, function () {
4882 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Deleting. Please wait...', 'mainwp'), '');
4883 let data = mainwp_secure_data({
4884 action: 'mainwp_delete_demo_data',
4885 });
4886 jQuery.post(ajaxurl, data, function (response) {
4887 let error = false;
4888 if (response.success === undefined) {
4889 error = true;
4890 feedback('mainwp-message-zone', __('Undefined error. Please try again.', 'mainwp'), 'green');
4891 } else {
4892 feedback('mainwp-message-zone', __('The demo content has been deleted from your MainWP Dashboard.', 'mainwp'), 'green');
4893 }
4894
4895 if (!error) {
4896 setTimeout(function () {
4897 mainwp_forceReload('admin.php?page=mainwp-setup');
4898 }, 3000);
4899 }
4900
4901 }, 'json');
4902 });
4903 }
4904
4905 // MainWP Tools
4906 jQuery(function () {
4907 jQuery(document).on('click', '#force-destroy-sessions-button', function () {
4908 mainwp_force_destroy_sessions();
4909 });
4910
4911 jQuery(document).on('click', '.mainwp-import-demo-data-button', function (event) {
4912 mainwp_import_demo_data_action(this);
4913 event.preventDefault();
4914 });
4915
4916 jQuery(document).on('click', '.mainwp-remove-demo-data-button', function () {
4917 mainwp_remove_demo_data_action();
4918 return false; //required this return.
4919 });
4920 });
4921
4922
4923 let mainwp_tool_renew_connections_show = function () {
4924 jQuery('#mainwp-tool-renew-connect-modal').modal({
4925 allowMultiple: true,
4926 closable: false,
4927 onHide: function () {
4928 mainwp_forceReload('admin.php?page=MainWPTools');
4929 },
4930 onShow: function () {
4931 if (jQuery('#mainwp-tool-renew-connect-modal .mainwp_selected_sites_item.item.warning').length == 0) {
4932 jQuery('#mainwp-tool-renew-connect-modal .mainwp-ss-select-disconnected').hide();
4933 jQuery('#mainwp-tool-renew-connect-modal .mainwp-ss-deselect-disconnected').hide();
4934 }
4935 }
4936 }).modal('show');
4937 };
4938
4939 let mainwp_tool_prepare_renew_connections = function (objBtn) {
4940
4941 let errors = [];
4942 let selected_sites = [];
4943 mainwp_set_message_zone('#mainwp-message-zone-modal');
4944
4945 jQuery("input[name='selected_sites[]']:checked").each(function () {
4946 selected_sites.push(jQuery(this).val());
4947 });
4948 if (selected_sites.length == 0) {
4949 errors.push(__('Please select at least one website to start.'));
4950 }
4951
4952 if (errors.length > 0) {
4953 mainwp_set_message_zone('#mainwp-message-zone-modal', errors.join('<br />'), 'yellow');
4954 return;
4955 } else {
4956 mainwp_set_message_zone('#mainwp-message-zone-modal');
4957 }
4958
4959 let confirmation = __("This process will create a new OpenSSL Key Pair on your MainWP Dashboard and Set the new Public Key to your Child site(s). Are you sure you want to proceed?");
4960
4961 mainwp_confirm(confirmation, function () {
4962 jQuery(objBtn).attr('disabled', true);
4963
4964 jQuery('#mainwp-tool-renew-connect-modal .mainwp-select-sites-wrapper').hide();
4965
4966 let statusEl = jQuery('#mainwp-message-zone-modal');
4967 statusEl.html('<i class="notched circle loading icon"></i> ' + __('Please wait...'));
4968 statusEl.show();
4969
4970 let data = mainwp_secure_data({
4971 action: 'mainwp_prepare_renew_connections',
4972 'sites[]': selected_sites,
4973 });
4974
4975 jQuery.post(ajaxurl, data, function (response) {
4976 let undefError = false;
4977 if (response) {
4978 if (response.result != '') {
4979 jQuery('#mainwp-tool-renew-connect-modal').find('#mainwp-renew-connections-list').html(response.result);
4980 mainwpVars.bulkInstallTotal = jQuery('#mainwp-renew-connections-list .item').length;
4981 jQuery('#mainwp-tool-renew-connect-modal .mainwp-modal-progress').show();
4982 jQuery('#mainwp-tool-renew-connect-modal .mainwp-modal-progress').progress({ value: 0, total: mainwpVars.bulkInstallTotal });
4983 mainwp_tool_renew_connections_start_next();
4984 statusEl.hide();
4985 } else if (response.error) {
4986 statusEl.addClass('red');
4987 statusEl.html(response.error).fadeIn();
4988 } else {
4989 undefError = true;
4990 }
4991 } else {
4992 undefError = true;
4993 }
4994
4995 if (undefError) {
4996 statusEl.addClass('red');
4997 statusEl.html(__('Undefined error occurred. Please try again.')).fadeIn();
4998 }
4999 }, 'json');
5000 }, false, false, true);
5001 }
5002
5003 let connection_renew_status = function (siteId, newStatus) {
5004 jQuery('#mainwp-renew-connections-list .renew-site-status[siteid="' + siteId + '"]').html(newStatus);
5005 };
5006
5007 let mainwp_tool_renew_connections_start_next = function () {
5008 while ((siteToReNew = jQuery('#mainwp-renew-connections-list .item[status="queue"]:first')) && (siteToReNew.length > 0) && (bulkInstallCurrentThreads < bulkInstallMaxThreads)) { // NOSONAR - modified outside the function.
5009 mainwp_tool_renew_connections_start_specific(siteToReNew);
5010 }
5011 }
5012
5013 let mainwp_tool_renew_connections_start_specific = function (siteItem) {
5014
5015 bulkInstallCurrentThreads++;
5016
5017 siteItem.attr('status', 'progress');
5018 let siteId = siteItem.find('.renew-site-status').attr('siteid');
5019
5020 let data = mainwp_secure_data({
5021 action: 'mainwp_renew_connections',
5022 siteid: siteId
5023 });
5024
5025 connection_renew_status(siteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Processing...', 'mainwp') + '"><i class="sync alternate loading icon"></i></span>');
5026 jQuery.post(ajaxurl, data, function (response) {
5027 if (response.error) {
5028 connection_renew_status(siteId, '<span data-inverted="" data-position="left center" data-tooltip="' + response.error + '"><i class="times red icon"></i></span>');
5029 } else if (response.result == 'success') {
5030 connection_renew_status(siteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Renew connnection process completed successfully.', 'mainwp') + '"><i class="check green icon"></i></span>');
5031 } else {
5032 connection_renew_status(siteId, '<span data-inverted="" data-position="left center" data-tooltip="' + __('Undefined error.') + '"><i class="times red icon"></i></span>');
5033
5034 }
5035 bulkInstallCurrentThreads--;
5036 bulkInstallDone++;
5037 jQuery('#mainwp-tool-renew-connect-modal .mainwp-modal-progress').progress('set progress', bulkInstallDone);
5038 jQuery('#mainwp-tool-renew-connect-modal .mainwp-modal-progress').find('.label').html(bulkInstallDone + '/' + mainwpVars.bulkInstallTotal + ' ' + __('Processed'));
5039 mainwp_tool_renew_connections_start_next();
5040 }, 'json');
5041 }
5042
5043
5044 jQuery(function () {
5045 if (jQuery('body.mainwp-ui').length > 0) {
5046 jQuery('.mainwp-ui-page .ui.dropdown:not(.not-auto-init)').dropdown();
5047 jQuery('.mainwp-ui-page .ui.checkbox:not(.not-auto-init)').checkbox();
5048 jQuery('.mainwp-ui-page .ui.dropdown').filter('[init-value]').each(function () {
5049 let values = jQuery(this).attr('init-value').split(',');
5050 jQuery(this).dropdown('set selected', values);
5051 });
5052 }
5053 });
5054
5055 // MainWP Action Logs
5056 jQuery(document).on('click', '.mainwp-action-log-show-more', function () {
5057 let content = jQuery(this).closest('.item').find('.mainwp-action-log-site-response').text();
5058 jQuery('#mainwp-action-log-response-modal').modal({
5059 closable: false,
5060 onHide: function () {
5061 location.reload();
5062 }
5063 }).modal('show');
5064 jQuery('#mainwp-action-log-response-modal .content-response').text(content);
5065 });
5066
5067 // MainWP Show Response
5068 jQuery(document).on('click', '.mainwp-show-response', function () {
5069 let content = jQuery('#mainwp-response-data-container').attr('resp-data');
5070 jQuery('#mainwp-response-data-modal').modal({
5071 closable: false,
5072 onHide: function () {
5073 jQuery('#mainwp-response-data-modal .content-response').text('');
5074 }
5075 }).modal('show');
5076 jQuery('#mainwp-response-data-modal .content-response').text(content);
5077 });
5078
5079 // Copy to clipboard for response modals.
5080 jQuery(document).on('click', '.mainwp-response-copy-button', function (event) {
5081 let modal = jQuery(this).closest('.ui.modal');
5082 let data = jQuery(modal).find('.content.content-response').text();
5083 let $temp_txtarea = jQuery('<textarea style="opacity:0">');
5084 jQuery('body').append($temp_txtarea);
5085 $temp_txtarea.val(data).trigger("select"); // to support 'copy' method.
5086 mainwp_copy_to_clipboard(data, event);
5087 $temp_txtarea.remove();
5088 return false;
5089 });
5090
5091 jQuery(function () {
5092 if (typeof postboxes !== "undefined" && typeof mainwp_postbox_page !== "undefined") {
5093 postboxes.add_postbox_toggles(mainwp_postbox_page);
5094 }
5095 mainwp_setCookie();
5096 mainwp_getCookie();
5097 });
5098
5099 jQuery(document).on('click', '.close.icon', function () {
5100 jQuery(this).parent().hide();
5101 });
5102
5103 /*
5104 * to compatible
5105 */
5106 function mainwp_setCookie() {
5107 return false;
5108 }
5109
5110 function mainwp_getCookie() {
5111 return false;
5112 }
5113
5114 let mainwp_setttings_fields_indicator_show = function (specific_header_indicator) {
5115 if (specific_header_indicator !== undefined) {
5116 mainwp_setttings_fields_indicator_specific_show(specific_header_indicator);
5117 return;
5118 }
5119 // for each header indicator.
5120 jQuery('.settings-field-header-indicator').each(function () {
5121 mainwp_setttings_fields_indicator_specific_show(this);
5122 });
5123 }
5124
5125 let mainwp_setttings_fields_indicator_specific_show = function (obj) {
5126 let cls = jQuery(obj).attr('field-indicator-wrapper-class');
5127 if ('' != cls && jQuery('.' + cls + ' .settings-field-icon-indicator.visible-indicator').length > 0) {
5128 jQuery(this).attr('style', 'display:inline-block;');
5129 jQuery(this).addClass('visible-indicator');
5130 }
5131 }
5132
5133
5134 jQuery(function ($) {
5135 if (jQuery('.mainwp-ui-page').length) {
5136 mainwp_setttings_fields_indicator_show();
5137 }
5138
5139 jQuery(document).on('input', '.settings-field-value-change-handler', function () {
5140 let val = $(this).val();
5141 mainwp_settings_fields_value_on_change(this, val);
5142 });
5143
5144 jQuery(document).on('change', '.settings-field-value-change-handler', function () { // NOSONAR - complex ok.
5145 let objName = $(this).prop('tagName'), val;
5146 let me; // to fix some special case indicator not at same level with input, need to find by name.
5147
5148 if ('DIV' === objName) { // ui dropdown select.
5149 val = $(this).dropdown('get value');
5150 } else if ($(this).is(':checkbox')) {
5151 val = $(this).is(":checked") ? '1' : '0';
5152 if ($(this).attr('name') === 'mainwp_show_widgets[]') {
5153 if ($('input[type="checkbox"][name="mainwp_show_widgets[]"]:not(:checked)').length == 0) {
5154 val = 'all';
5155 }
5156 } else if ($(this).attr('inverted-value')) {
5157 val = val === '1' ? '0' : '1'; // to fix compatible with some case checked is disable, value is 0.
5158 }
5159 } else {
5160 val = $(this).val();
5161 if ($(this).attr('name') === 'mainwp_rest_api_key_edit_pers') {
5162 val = val.split(',').length;
5163 } else if ($(this).attr('name') === 'cost_tracker_custom_product_types[title][]') {
5164 val = $('input[name="cost_tracker_custom_product_types[title][]"]').length; // default 0.
5165 me = $('.settings-field-indicator-wrapper.default-product-categories');
5166 } else if ($(this).attr('name') === 'cost_tracker_custom_payment_methods[title][]') {
5167 val = $('input[name="cost_tracker_custom_payment_methods[title][]"]').length; // default 0.
5168 me = $('.settings-field-indicator-wrapper.custom-payment-methods');
5169 }
5170 }
5171
5172 if(me === undefined) {
5173 mainwp_settings_fields_value_on_change(this, val);
5174 } else {
5175 mainwp_settings_fields_value_on_change(me, val);
5176 }
5177 });
5178
5179 let mainwp_settings_fields_value_on_change = function (obj, val) {
5180 let parent = $(obj).closest('.settings-field-indicator-wrapper');
5181 if (parent.length) {
5182 let defval = $(parent).attr('default-indi-value') ?? ''; // put default-indi-value at wrapper because semantic ui some case move class of input too input's parent.
5183 let indiObj = parent.find('.settings-field-icon-indicator');
5184 if (indiObj.length) {
5185 if (val == defval || ('0' == val && '' === defval)) { // empty and zero are same.
5186 $(indiObj).removeClass('visible-indicator');
5187 } else {
5188 $(indiObj).addClass('visible-indicator');
5189 }
5190 }
5191 }
5192 }
5193 });
5194
5195
5196
5197 let mainwp_common_filter_show_segments_modal = function (loadCallback) {
5198 jQuery('#mainwp-common-filter-segment-modal').modal({
5199 allowMultiple: false,
5200 onShow: function () {
5201 if (typeof loadCallback == 'function') {
5202 loadCallback();
5203 }
5204 }
5205 }).modal('show');
5206 };
5207
5208 jQuery(function ($) {
5209 if (!globalThis.mainwpSegmentModalUiHandle) {
5210 globalThis.mainwpSegmentModalUiHandle = (function () {
5211 let _instance = {
5212 loadingStatus: function () {
5213 $('#mainwp-common-filter-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Loading segments. Please wait...')).show();
5214 },
5215 savingStatus: function () {
5216 $('#mainwp-common-filter-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Saving segment. Please wait...')).show();
5217 },
5218 deletingStatus: function () {
5219 $('#mainwp-common-filter-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Deleting segment. Please wait...')).show();
5220
5221 },
5222 showStatus: function (status, addClass) {
5223 if (addClass) {
5224 $('#mainwp-common-filter-edit-segment-status').addClass(addClass);
5225 }
5226 $('#mainwp-common-filter-edit-segment-status').html(status).show();
5227 },
5228 hideSegmentStatus: function () {
5229 $('#mainwp-common-filter-edit-segment-status').removeClass('red green').hide();
5230 },
5231 showSegment: function (btnObj) {
5232 jQuery('#mainwp-common-filter-segment-modal > div.header').html(__('Save Segment'));
5233 jQuery('#mainwp-common-filter-segment-edit-fields').show();
5234 jQuery('#mainwp-common-filter-edit-segment-save').show();
5235 jQuery('#mainwp-common-filter-segment-select-fields').hide();
5236 jQuery('#mainwp-common-filter-select-segment-choose-button').hide();
5237 jQuery('#mainwp-common-filter-select-segment-delete-button').hide();
5238 jQuery('#mainwp-common-filter-edit-segment-name').val(jQuery(btnObj).attr('selected-segment-name'));
5239 this.hideSegmentStatus();
5240 mainwp_common_filter_show_segments_modal();
5241 },
5242 loadSegment: function (loadCallback) {
5243 jQuery('#mainwp-common-filter-segment-edit-fields').hide();
5244 jQuery('#mainwp-common-filter-edit-segment-save').hide();
5245 jQuery('#mainwp-common-filter-segment-modal > div.header').html(__('Load Segment'));
5246 jQuery('#mainwp-common-filter-segment-select-fields').show();
5247 jQuery('#mainwp-common-filter-select-segment-choose-button').show();
5248 jQuery('#mainwp-common-filter-select-segment-delete-button').show();
5249 this.hideSegmentStatus();
5250 mainwp_common_filter_show_segments_modal(loadCallback);
5251 },
5252 showResults: function (result) {
5253 jQuery('#mainwp-common-filter-edit-segment-status').hide();
5254 jQuery('#mainwp-common-filter-segments-lists-wrapper').html(result);
5255 jQuery('#mainwp-common-filter-segments-lists-wrapper .ui.dropdown').dropdown();
5256 jQuery('#mainwp-common-filter-segment-select-fields').show();
5257 }
5258 }
5259 return _instance;
5260 })();
5261 }
5262
5263 });
5264
5265 let mainwp_overview_gridstack_save_layout = function (item_id, grid) {
5266
5267 if (!grid?.engine?.nodes) {
5268 return;
5269 }
5270
5271 let orders = [];
5272 let wgIds = [];
5273
5274 grid.engine.nodes.forEach(function (node) {
5275 if (!node?.el?.id) {
5276 return;
5277 }
5278
5279 let obj = {
5280 "x": node.x ?? 0,
5281 "y": node.y ?? 0,
5282 "w": node.w ?? 4,
5283 "h": node.h ?? 4
5284 };
5285 orders.push(obj);
5286 wgIds.push(node.el.id);
5287 });
5288
5289 if (wgIds.length === 0) {
5290 return;
5291 }
5292
5293 let postVars = {
5294 action: 'mainwp_widgets_order',
5295 page: page_sortablewidgets,
5296 order: JSON.stringify(orders),
5297 wgids: JSON.stringify(wgIds),
5298 item_id: item_id,
5299 page_widget: page_widget
5300 };
5301 jQuery.post(ajaxurl, mainwp_secure_data(postVars), function () {});
5302 }
5303
5304 globalThis.mainwp_init_ui_calendar = ($selectors) => {
5305 jQuery($selectors).calendar({
5306 type: 'date',
5307 monthFirst: false,
5308 today: true,
5309 touchReadonly: false,
5310 formatter: {
5311 date: function (date) {
5312 if (!date) return '';
5313 let day = date.getDate();
5314 let month = date.getMonth() + 1;
5315 let year = date.getFullYear();
5316
5317 if (month < 10) {
5318 month = '0' + month;
5319 }
5320 if (day < 10) {
5321 day = '0' + day;
5322 }
5323 return year + '-' + month + '-' + day;
5324 }
5325 }
5326 });
5327
5328 }
5329
5330
5331 jQuery(document).ready(function () {
5332 jQuery('.dt-scroll-head').css({
5333 'overflow-x': 'auto'
5334 }).on('scroll', function () {
5335 let scrollBody = jQuery(this).parent().find('.dt-scroll-body').get(0);
5336 scrollBody.scrollLeft = this.scrollLeft;
5337 jQuery(scrollBody).trigger('scroll');
5338 });
5339 });
5340
5341 // Function to check valid email using regular expression.
5342 const mainwp_validate_email = function (email) {
5343 const re = /^[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,}$/;
5344 return re.test(email);
5345 }
5346
5347
5348 jQuery(function ($) {
5349
5350 $(document).on('click', '#delete_uptime_monitor_btn', function () {
5351 let is_sub = $('#monitor_edit_is_sub_url')?.val();
5352
5353 let confirmation = __("Are you sure you want to delete this uptime monitor?");
5354
5355 if (is_sub) {
5356 confirmation = __("Are you sure you want to delete this uptime sub-page monitor?");
5357 }
5358
5359 mainwp_confirm(confirmation, () => {
5360 let wpid = $('#mainwp_edit_monitor_site_id').val();
5361 let moid = $('#mainwp_edit_monitor_id').val();
5362
5363 mainwp_uptime_monitoring_remove(wpid, moid);
5364 }, false, false, true);
5365 });
5366
5367 let mainwp_uptime_monitoring_remove = function (wpid, moid) {
5368
5369 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Removing Uptime Monitor...'), 'green');
5370
5371 let data = mainwp_secure_data({
5372 action: 'mainwp_uptime_monitoring_remove_monitor',
5373 wpid: wpid,
5374 moid: moid
5375 });
5376
5377 jQuery.post(ajaxurl, data, function (response) {
5378 if (response?.success) {
5379 feedback('mainwp-message-zone', __('Monitor have been removed.'), 'green');
5380 setTimeout(function () {
5381 mainwp_forceReload('admin.php?page=managesites&id=' + wpid);
5382 }, 2000);
5383
5384 } else if (response?.error) {
5385 feedback('mainwp-message-zone', response.error, 'red');
5386 } else {
5387 feedback('mainwp-message-zone', __('Undefined error. Please try again.'), 'red');
5388 }
5389 }, 'json');
5390 return false;
5391 };
5392
5393 $(document).on('click', '#increase-connection-security-btn', function () {
5394 feedback('mainwp-message-zone', '<i class="notched circle loading icon"></i> ' + __('Encryption in progress! Securing your OpenSSL private keys, this may take a few moments. Please wait until completed.'), 'green');
5395 let data = mainwp_secure_data({
5396 action: 'mainwp_increase_connection_security',
5397 });
5398 jQuery.post(ajaxurl, data, function (response) {
5399 if (response?.success) {
5400 setTimeout(function () {
5401 mainwp_forceReload();
5402 }, 2000);
5403
5404 } else if (response?.error) {
5405 feedback('mainwp-message-zone', response.error, 'red');
5406 } else {
5407 feedback('mainwp-message-zone', __('Undefined error. Please try again.'), 'red');
5408 }
5409 }, 'json');
5410 return false;
5411 });
5412 jQuery('#module-update-logs-db-requirement').on('click', function () {
5413 let msg = __('Are you sure?');
5414 mainwp_confirm(msg, () => {
5415 jQuery(this).closest('.ui.message').fadeOut();
5416 mainwp_module_logs_start_update_dismissed_db();
5417 });
5418 return false;
5419 });
5420 });
5421
5422
5423 jQuery(document).on('click', '#mainwp-sites-changes-filter-toggle-button', function () {
5424 jQuery('#mainwp-module-log-filters-row').toggle(300);
5425 return false;
5426 });
5427
5428 jQuery(document).on('click', '#mainwp-insights-filter-toggle-button', function () {
5429 jQuery('#mainwp-module-log-overview-sub-header').toggle(300);
5430 return false;
5431 });
5432
5433
5434
5435 let logs_update_db_cancelled = false;
5436 let mainwp_module_logs_start_update_dismissed_db = function () {
5437 let data = mainwp_secure_data({
5438 action: 'mainwp_module_log_update_dismissed_db',
5439 });
5440 if (logs_update_db_cancelled) {
5441 mainwp_set_message_zone('#module-log-update-dissmised-logs-running', '<i class="close icon"></i>' + __("User cancelled the 'Sites Changes' database update process."), 'green');
5442 } else {
5443 mainwp_set_message_zone('#module-log-update-dissmised-logs-running', '<i class="ui active inline loader tiny"></i> ' + __('Updating the \'Sites Changes\' database. Click %1here%2 to cancel.', '<a href="javascript:void(0);" id="module-update-logs-db-cancel">', '</a>'), 'green');
5444 }
5445 jQuery.post(ajaxurl, data, function (response) {
5446 let status = response?.status ?? '';
5447 if (response.error) {
5448 mainwp_set_message_zone('#module-log-update-dissmised-logs-running', '<i class="close icon"></i>' + response.error, 'red');
5449 } else if (status === 'finished') {
5450 mainwp_set_message_zone('#module-log-update-dissmised-logs-running', '<i class="close icon"></i>' + __('Logs records has been updated successfully.'), 'green');
5451 } else if (status === 'running' && !logs_update_db_cancelled) {
5452 setTimeout(function () {
5453 mainwp_module_logs_start_update_dismissed_db();
5454 }, 500);
5455 }
5456 }, 'json');
5457 }
5458
5459 jQuery(document).on('click', '#module-update-logs-db-cancel', function () {
5460 logs_update_db_cancelled = true;
5461 let data = mainwp_secure_data({
5462 action: 'mainwp_module_log_cancel_update_dismissed_db',
5463 });
5464 jQuery(this).closest('.ui.message').fadeOut(300);
5465 jQuery.post(ajaxurl, data, function (response) {
5466 //ok.
5467 }, 'json');
5468 return false;
5469 });
5470
5471
5472
5473 let get_local_date_string = function () {
5474 const today = new Date();
5475 const y = today.getFullYear();
5476 const m = String(today.getMonth() + 1).padStart(2, '0'); // month starts from 0
5477 const d = String(today.getDate()).padStart(2, '0');
5478 return `${y}-${m}-${d}`;
5479 }
5480
5481 function mainwp_forceReload(targetUrl) {
5482 const url = targetUrl || globalThis.location.href;
5483 // Navigate to URL (force reload from server)
5484 globalThis.location.href = url;
5485 }
5486
5487 class TablePersistentState {
5488 constructor(table, options = {}) {
5489 if (!table || !(table instanceof HTMLElement)) {
5490 throw new Error('TablePersistentState requires a table element');
5491 }
5492
5493 this.table = table;
5494 this.tableId = table.id;
5495 this.headers = table.querySelectorAll(
5496 options.headerSelector || '.handle-cols-sorting'
5497 );
5498
5499 this.options = {
5500 storage: options.storage !== false, // default true
5501 storagePrefix: options.storagePrefix || 'mainwp_tables_sort_state',
5502 onPersist: options.onPersist || null,
5503 defaultSort: options.defaultSort || null, // column, direction
5504 };
5505
5506 this.init();
5507 }
5508
5509 /* ---------- Storage ---------- */
5510
5511 get storageKey() {
5512 return `${this.options.storagePrefix}:${this.tableId}`;
5513 }
5514
5515 saveState(column, direction) {
5516 if (!this.options.storage || !this.tableId) return;
5517
5518 localStorage.setItem(
5519 this.storageKey,
5520 JSON.stringify({ column, direction })
5521 );
5522 }
5523
5524 loadState() {
5525 if (!this.options.storage || !this.tableId) return null;
5526
5527 try {
5528 return JSON.parse(localStorage.getItem(this.storageKey));
5529 } catch {
5530 return null;
5531 }
5532 }
5533
5534 /* ---------- UI helpers ---------- */
5535
5536 clearIndicators() {
5537 this.headers.forEach(th => {
5538 th.classList.remove('sorted-asc', 'sorted-desc');
5539 th.removeAttribute('aria-sort');
5540 });
5541 }
5542
5543 applyIndicator(th, direction) {
5544 th.classList.add(direction === 'asc' ? 'sorted-asc' : 'sorted-desc');
5545 th.setAttribute('aria-sort', direction);
5546 }
5547
5548 toggleDirection(current) {
5549 return current === 'asc' ? 'desc' : 'asc';
5550 }
5551
5552 /* ---------- Sorting flow ---------- */
5553
5554 persistState(column, direction, th = null, persist = true, isrestore = false ) {
5555 if (th) {
5556 this.clearIndicators();
5557 this.applyIndicator(th, direction);
5558 }
5559
5560 if (persist) {
5561 this.saveState(column, direction);
5562 }
5563
5564 if (typeof this.options.onPersist === 'function') {
5565 this.options.onPersist({
5566 table: this.table,
5567 column,
5568 direction,
5569 isrestore
5570 });
5571 }
5572 }
5573
5574 /* ---------- Init ---------- */
5575
5576 restore() {
5577 const saved = this.loadState() || this.options.defaultSort;
5578 if (!saved) return;
5579
5580 const th = this.table.querySelector(
5581 `[data-key="${saved.column}"]`
5582 );
5583
5584 if (th) {
5585 this.persistState(saved.column, saved.direction, th, false, true );
5586 }
5587 }
5588
5589 bindEvents() {
5590 this.headers.forEach(th => {
5591 th.addEventListener('click', () => {
5592 const column = th.dataset.key;
5593 const isAsc = th.classList.contains('sorted-asc');
5594 const direction = this.toggleDirection(isAsc ? 'asc' : 'desc');
5595
5596 this.persistState(column, direction, th);
5597 });
5598 });
5599 }
5600
5601 init() {
5602 if (!this.tableId && this.options.storage) {
5603 console.warn('TablePersistentState: table has no id, storage disabled');
5604 }
5605
5606 this.restore();
5607 this.bindEvents();
5608 }
5609 }
5610