PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.0.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.0.1
6.2.2 6.2.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 All 155 releases
mainwp / pages / page-mainwp-themes.php

page-mainwp-themes.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 5.0.1, at pages/page-mainwp-themes.php

2,883 lines 121.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Themes Page
4 *
5 * This page is used to Manage Themes on Child Sites
6 *
7 * @package MainWP/Themes
8 */
9
10 namespace MainWP\Dashboard;
11
12 /**
13 * Class MainWP_Themes_Page
14 *
15 * @uses MainWP_Install_Bulk
16 */
17 class MainWP_Themes {
18
19 //phpcs:disable Generic.Metrics.CyclomaticComplexity -- complexity.
20
21 /**
22 * Get Class Name
23 *
24 * @return string __CLASS__
25 */
26 public static function get_class_name() {
27 return __CLASS__;
28 }
29
30 /**
31 * Subpages array.
32 *
33 * @var array $subPages Array of SubPages.
34 */
35 public static $subPages;
36
37 /**
38 * Fire on the initialization of WordPress.
39 */
40 public static function init() {
41 /**
42 * This hook allows you to render the Themes page header via the 'mainwp-pageheader-themes' action.
43 *
44 * @link http://codex.mainwp.com/#mainwp-pageheader-themes
45 *
46 * This hook is normally used in the same context of 'mainwp-getsubpages-themes'
47 * @link http://codex.mainwp.com/#mainwp-getsubpages-themes
48 *
49 * @see \MainWP_Themes::render_header
50 */
51 add_action( 'mainwp-pageheader-themes', array( self::get_class_name(), 'render_header' ) );
52
53 /**
54 * This hook allows you to render the Themes page footer via the 'mainwp-pagefooter-themes' action.
55 *
56 * @link http://codex.mainwp.com/#mainwp-pagefooter-themes
57 *
58 * This hook is normally used in the same context of 'mainwp-getsubpages-themes'
59 * @link http://codex.mainwp.com/#mainwp-getsubpages-themes
60 *
61 * @see \MainWP_Themes::render_footer
62 */
63 add_action( 'mainwp-pagefooter-themes', array( self::get_class_name(), 'render_footer' ) );
64
65 add_action( 'mainwp_help_sidebar_content', array( self::get_class_name(), 'mainwp_help_content' ) );
66 }
67
68 /**
69 * Method init_menu()
70 *
71 * Initiate the MainWP Themes SubMenu page.
72 *
73 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
74 */
75 public static function init_menu() {
76
77 $_page = add_submenu_page(
78 'mainwp_tab',
79 __( 'Themes', 'mainwp' ),
80 '<span id="mainwp-Themes">' . esc_html__( 'Themes', 'mainwp' ) . '</span>',
81 'read',
82 'ThemesManage',
83 array(
84 self::get_class_name(),
85 'render',
86 )
87 );
88
89 add_submenu_page(
90 'mainwp_tab',
91 __( 'Themes', 'mainwp' ),
92 '<div class="mainwp-hidden">' . esc_html__( 'Install', 'mainwp' ) . '</div>',
93 'read',
94 'ThemesInstall',
95 array(
96 self::get_class_name(),
97 'render_install',
98 )
99 );
100 add_submenu_page(
101 'mainwp_tab',
102 __( 'Themes', 'mainwp' ),
103 '<div class="mainwp-hidden">' . esc_html__( 'Advanced Auto Updates', 'mainwp' ) . '</div>',
104 'read',
105 'ThemesAutoUpdate',
106 array(
107 self::get_class_name(),
108 'render_auto_update',
109 )
110 );
111 add_submenu_page(
112 'mainwp_tab',
113 __( 'Themes', 'mainwp' ),
114 '<div class="mainwp-hidden">' . esc_html__( 'Ignored Updates', 'mainwp' ) . '</div>',
115 'read',
116 'ThemesIgnore',
117 array(
118 self::get_class_name(),
119 'render_ignore',
120 )
121 );
122 add_submenu_page(
123 'mainwp_tab',
124 __( 'Themes', 'mainwp' ),
125 '<div class="mainwp-hidden">' . esc_html__( 'Ignored Abandoned', 'mainwp' ) . '</div>',
126 'read',
127 'ThemesIgnoredAbandoned',
128 array(
129 self::get_class_name(),
130 'render_ignored_abandoned',
131 )
132 );
133
134 /**
135 * Themes Subpages
136 *
137 * Filters subpages for the Themes page.
138 *
139 * @since Unknown
140 */
141 $sub_pages = apply_filters_deprecated( 'mainwp-getsubpages-themes', array( array() ), '4.0.7.2', 'mainwp_getsubpages_themes' ); // @deprecated Use 'mainwp_getsubpages_themes' instead.
142 self::$subPages = apply_filters( 'mainwp_getsubpages_themes', $sub_pages );
143 if ( isset( self::$subPages ) && is_array( self::$subPages ) ) {
144 foreach ( self::$subPages as $subPage ) {
145 if ( MainWP_Menu::is_disable_menu_item( 3, 'Themes' . $subPage['slug'] ) ) {
146 continue;
147 }
148 add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . $subPage['title'] . '</div>', 'read', 'Themes' . $subPage['slug'], $subPage['callback'] );
149 }
150 }
151 self::init_left_menu( self::$subPages );
152 }
153
154 /**
155 * Method init_subpages_menu()
156 *
157 * Themes Subpage Menu HTML Content.
158 *
159 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
160 */
161 public static function init_subpages_menu() {
162 ?>
163 <div id="menu-mainwp-Themes" class="mainwp-submenu-wrapper">
164 <div class="wp-submenu sub-open">
165 <div class="mainwp_boxout">
166 <div class="mainwp_boxoutin"></div>
167 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ThemesManage' ) ); ?>" class="mainwp-submenu">
168 <?php esc_html_e( 'Manage Themes', 'mainwp' ); ?>
169 </a>
170 <?php if ( mainwp_current_user_have_right( 'dashboard', 'install_themes' ) ) { ?>
171 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesInstall' ) ) { ?>
172 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ThemesInstall' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Install Themes', 'mainwp' ); ?></a>
173 <?php } ?>
174 <?php } ?>
175 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesAutoUpdate' ) ) { ?>
176 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ThemesAutoUpdate' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Advanced Auto Updates', 'mainwp' ); ?></a>
177 <?php } ?>
178 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesIgnore' ) ) { ?>
179 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ThemesIgnore' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Ignored Updates', 'mainwp' ); ?></a>
180 <?php } ?>
181 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesIgnoredAbandoned' ) ) { ?>
182 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ThemesIgnoredAbandoned' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Ignored Abandoned', 'mainwp' ); ?></a>
183 <?php } ?>
184 <?php
185 if ( isset( self::$subPages ) && is_array( self::$subPages ) ) {
186 foreach ( self::$subPages as $subPage ) {
187 if ( MainWP_Menu::is_disable_menu_item( 3, 'Themes' . $subPage['slug'] ) ) {
188 continue;
189 }
190 ?>
191 <a href="<?php echo esc_url( admin_url( 'admin.php?page=Themes' . $subPage['slug'] ) ); ?>" class="mainwp-submenu"><?php echo esc_html( $subPage['title'] ); ?></a>
192 <?php
193 }
194 }
195 ?>
196 </div>
197 </div>
198 </div>
199 <?php
200 }
201
202 /**
203 * Method init_left_menu()
204 *
205 * Build arrays for each SubPage Menu Block.
206 *
207 * @param array $subPages Array of SubPages.
208 *
209 * @uses \MainWP\Dashboard\MainWP_Menu::add_left_menu()
210 * @uses \MainWP\Dashboard\MainWP_Menu::init_subpages_left_menu()
211 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
212 */
213 public static function init_left_menu( $subPages = array() ) {
214 MainWP_Menu::add_left_menu(
215 array(
216 'title' => esc_html__( 'Themes', 'mainwp' ),
217 'parent_key' => 'managesites',
218 'slug' => 'ThemesManage',
219 'href' => 'admin.php?page=ThemesManage',
220 'icon' => '<i class="paint brush icon"></i>',
221 'leftsub_order' => 6,
222 ),
223 1
224 );
225
226 $init_sub_subleftmenu = array(
227 array(
228 'title' => esc_html__( 'Manage Themes', 'mainwp' ),
229 'parent_key' => 'ThemesManage',
230 'href' => 'admin.php?page=ThemesManage',
231 'slug' => 'ThemesManage',
232 'right' => '',
233 'leftsub_order_level2' => 1,
234 ),
235 array(
236 'title' => esc_html__( 'Install', 'mainwp' ),
237 'parent_key' => 'ThemesManage',
238 'href' => 'admin.php?page=ThemesInstall',
239 'slug' => 'ThemesInstall',
240 'right' => 'install_themes',
241 'leftsub_order_level2' => 2,
242 ),
243 array(
244 'title' => esc_html__( 'Advanced Auto Updates', 'mainwp' ),
245 'parent_key' => 'ThemesManage',
246 'href' => 'admin.php?page=ThemesAutoUpdate',
247 'slug' => 'ThemesAutoUpdate',
248 'right' => '',
249 'leftsub_order_level2' => 3,
250 ),
251 array(
252 'title' => esc_html__( 'Ignored Updates', 'mainwp' ),
253 'parent_key' => 'ThemesManage',
254 'href' => 'admin.php?page=ThemesIgnore',
255 'slug' => 'ThemesIgnore',
256 'right' => '',
257 'leftsub_order_level2' => 4,
258 ),
259 array(
260 'title' => esc_html__( 'Abandoned Themes', 'mainwp' ),
261 'parent_key' => 'ThemesManage',
262 'href' => 'admin.php?page=UpdatesManage&tab=abandoned-themes',
263 'slug' => 'ThemesManage',
264 'right' => '',
265 'leftsub_order_level2' => 4.1,
266 ),
267 array(
268 'title' => esc_html__( 'Ignored Abandoned', 'mainwp' ),
269 'parent_key' => 'ThemesManage',
270 'href' => 'admin.php?page=ThemesIgnoredAbandoned',
271 'slug' => 'ThemesIgnoredAbandoned',
272 'right' => '',
273 'leftsub_order_level2' => 5,
274 ),
275 );
276
277 MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'ThemesManage', 'Themes' );
278
279 foreach ( $init_sub_subleftmenu as $item ) {
280 if ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) {
281 continue;
282 }
283 MainWP_Menu::add_left_menu( $item, 2 );
284 }
285 }
286
287 /**
288 * Method render_header()
289 *
290 * Render Themes SubPage Header.
291 *
292 * @param string $shownPage The page slug shown at this moment.
293 *
294 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
295 * @uses \MainWP\Dashboard\MainWP_UI::render_top_header()
296 * @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation()
297 */
298 public static function render_header( $shownPage = '' ) {
299 $params = array( 'title' => esc_html__( 'Themes', 'mainwp' ) );
300
301 MainWP_UI::render_top_header( $params );
302
303 $renderItems = array();
304
305 $renderItems[] = array(
306 'title' => esc_html__( 'Manage Themes', 'mainwp' ),
307 'href' => 'admin.php?page=ThemesManage',
308 'active' => ( 'Manage' === $shownPage ) ? true : false,
309 );
310
311 if ( mainwp_current_user_have_right( 'dashboard', 'install_themes' ) ) {
312 $renderItems[] = array(
313 'title' => esc_html__( 'Install', 'mainwp' ),
314 'href' => 'admin.php?page=ThemesInstall',
315 'active' => ( 'Install' === $shownPage ) ? true : false,
316 );
317 }
318
319 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesAutoUpdate' ) ) {
320 $renderItems[] = array(
321 'title' => esc_html__( 'Advanced Auto Updates', 'mainwp' ),
322 'href' => 'admin.php?page=ThemesAutoUpdate',
323 'active' => ( 'AutoUpdate' === $shownPage ) ? true : false,
324 );
325 }
326
327 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesIgnore' ) ) {
328 $renderItems[] = array(
329 'title' => esc_html__( 'Ignored Updates', 'mainwp' ),
330 'href' => 'admin.php?page=ThemesIgnore',
331 'active' => ( 'Ignore' === $shownPage ) ? true : false,
332 );
333 }
334
335 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ThemesIgnoredAbandoned' ) ) {
336 $renderItems[] = array(
337 'title' => esc_html__( 'Ignored Abandoned', 'mainwp' ),
338 'href' => 'admin.php?page=ThemesIgnoredAbandoned',
339 'active' => ( 'IgnoreAbandoned' === $shownPage ) ? true : false,
340 );
341 }
342
343 if ( isset( self::$subPages ) && is_array( self::$subPages ) ) {
344 foreach ( self::$subPages as $subPage ) {
345 if ( MainWP_Menu::is_disable_menu_item( 3, 'Themes' . $subPage['slug'] ) ) {
346 continue;
347 }
348 $item = array();
349 $item['title'] = $subPage['title'];
350 $item['href'] = 'admin.php?page=Themes' . $subPage['slug'];
351 $item['active'] = ( $subPage['slug'] === $shownPage ) ? true : false;
352 $renderItems[] = $item;
353 }
354 }
355 MainWP_UI::render_page_navigation( $renderItems );
356 }
357
358 /**
359 * Method render_footer()
360 *
361 * Close the page container.
362 */
363 public static function render_footer() {
364 echo '</div>';
365 }
366
367 /**
368 * Method render()
369 *
370 * Render the Theme SubPage content.
371 *
372 * @uses \MainWP\Dashboard\MainWP_Cache::get_cached_context()
373 * @uses \MainWP\Dashboard\MainWP_Cache::get_cached_result()
374 * @uses \MainWP\Dashboard\MainWP_UI::render_empty_bulk_actions()
375 */
376 public static function render() {
377 $cachedSearch = MainWP_Cache::get_cached_context( 'Themes' );
378 $selected_sites = array();
379 $selected_groups = array();
380 $selected_clients = array();
381
382 if ( null !== $cachedSearch ) {
383 if ( is_array( $cachedSearch['sites'] ) ) {
384 $selected_sites = $cachedSearch['sites'];
385 } elseif ( is_array( $cachedSearch['groups'] ) ) {
386 $selected_groups = $cachedSearch['groups'];
387 } elseif ( is_array( $cachedSearch['clients'] ) ) {
388 $selected_clients = $cachedSearch['clients'];
389 }
390 }
391
392 $cachedResult = MainWP_Cache::get_cached_result( 'Themes' );
393
394 if ( isset( $_POST['select_mainwp_options_plugintheme_view'] ) && check_admin_referer( 'mainwp-admin-nonce' ) ) {
395 if ( is_array( $cachedResult ) && isset( $cachedResult['result'] ) ) {
396 unset( $cachedResult['result'] ); // clear cached results.
397 }
398 }
399
400 self::render_header( 'Manage' );
401 ?>
402
403 <div id="mainwp-manage-themes" class="ui alt segment">
404 <div class="mainwp-main-content">
405 <div class="ui mini form mainwp-actions-bar">
406 <div class="ui stackable grid">
407 <div class="ui three column row">
408 <div class="left aligned column">
409 <div id="mainwp-themes-bulk-actions-wapper">
410 <?php
411 if ( is_array( $cachedResult ) && isset( $cachedResult['bulk_actions'] ) ) {
412 echo $cachedResult['bulk_actions']; // phpcs:ignore WordPress.Security.EscapeOutput
413 } else {
414 MainWP_UI::render_empty_bulk_actions();
415 }
416 ?>
417 </div>
418 <?php
419 /**
420 * Action: mainwp_themes_actions_bar_left
421 *
422 * Fires at the left side of the actions bar on the Themes screen, after the Bulk Actions menu.
423 *
424 * @since 4.0
425 */
426 do_action( 'mainwp_themes_actions_bar_left' );
427 ?>
428 </div>
429 <div class="right aligned column" >
430 <?php
431 MainWP_Plugins::render_select_manage_view( 'theme' );
432 ?>
433 </div>
434 <div class="right aligned column">
435 <button id="mainwp-install-themes-to-selected-sites" class="ui mini green basic button" style="display: none"><?php esc_html_e( 'Install to Selected Site(s)', 'mainwp' ); ?></button>
436 <?php
437 /**
438 * Action: mainwp_themes_actions_bar_right
439 *
440 * Fires at the right side of the actions bar on the Themes screen.
441 *
442 * @since 4.0
443 */
444 do_action( 'mainwp_themes_actions_bar_right' );
445 ?>
446 </div>
447 </div>
448 </div>
449 </div>
450 <div class="ui segment" id="mainwp_themes_wrap_table">
451 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-manage-themes-info-message' ) ) : ?>
452 <div class="ui info message">
453 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-manage-themes-info-message"></i>
454 <div><?php echo esc_html__( 'Manage installed themes on your child sites. Here you can activate, deactivate, and delete installed themes.', 'mainwp' ); ?></div>
455 <p><?php echo esc_html__( 'To Activate or Delete a specific theme, you must search only for Inactive themes on your child sites. If you search for Active or both Active and Inactive, the Activate and Delete actions will be disabled.', 'mainwp' ); ?></p>
456 <p><?php printf( esc_html__( 'For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/managing-themes-with-mainwp/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?></p>
457 </div>
458 <?php endif; ?>
459 <div id="mainwp-message-zone" class="ui message" style="display:none"></div>
460 <div id="mainwp-loading-themes-row" class="ui active inverted dimmer" style="display:none">
461 <div class="ui large text loader"><?php esc_html_e( 'Loading Themes...', 'mainwp' ); ?></div>
462 </div>
463 <div id="mainwp-themes-main-content" <?php echo ( null !== $cachedSearch ) ? 'style="display: block;"' : ''; ?> >
464 <div id="mainwp-themes-content">
465 <?php if ( is_array( $cachedResult ) && isset( $cachedResult['result'] ) ) : ?>
466 <?php echo $cachedResult['result']; // phpcs:ignore WordPress.Security.EscapeOutput ?>
467 <?php else : ?>
468 <div class="ui padded segment">
469 <div class="ui hidden divider"></div>
470 <div class="ui hidden divider"></div>
471 <div class="ui hidden divider"></div>
472 <h2 class="ui icon header">
473 <i class="settings icon"></i>
474 <div class="content">
475 <?php esc_html_e( 'Manage Themes', 'mainwp' ); ?>
476 <div class="sub header"><?php esc_html_e( 'Use the search options to find the theme you want to manage.', 'mainwp' ); ?></div>
477 </div>
478 </h2>
479 </div>
480 <?php endif; ?>
481 </div>
482 </div>
483 </div>
484 </div>
485
486 <div class="mainwp-side-content mainwp-no-padding">
487 <?php
488 /**
489 * Action: mainwp_manage_themes_sidebar_top
490 *
491 * Fires at the top of the sidebar on Manage themes.
492 *
493 * @since 4.1
494 */
495 do_action( 'mainwp_manage_themes_sidebar_top' );
496 ?>
497 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
498 <?php
499 /**
500 * Action: mainwp_manage_themes_before_select_sites
501 *
502 * Fires before the Select Sites element on Manage themes.
503 *
504 * @since 4.1
505 */
506 do_action( 'mainwp_manage_themes_before_select_sites' );
507 ?>
508 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
509 <div class="content active">
510 <?php
511 $sel_params = array(
512 'class' => 'mainwp_select_sites_box_left',
513 'selected_sites' => $selected_sites,
514 'selected_groups' => $selected_groups,
515 'selected_clients' => $selected_clients,
516 'show_client' => true,
517 );
518 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
519 ?>
520 </div>
521 <?php
522 /**
523 * Action: mainwp_manage_themes_after_select_sites
524 *
525 * Fires after the Select Sites element on Manage themes.
526 *
527 * @since 4.1
528 */
529 do_action( 'mainwp_manage_themes_after_select_sites' );
530 ?>
531 </div>
532 <div class="ui fitted divider"></div>
533 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
534 <div class="active title"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Status', 'mainwp' ); ?></div>
535 <div class="content active">
536 <?php
537 /**
538 * Action: mainwp_manage_themes_before_search_options
539 *
540 * Fires before the Search Options element on Manage themes.
541 *
542 * @since 4.1
543 */
544 do_action( 'mainwp_manage_themes_before_search_options' );
545 ?>
546 <div class="ui info message">
547 <i class="close icon mainwp-notice-dismiss" notice-id="themes-manage-info"></i>
548 <?php esc_html_e( 'A theme needs to be Inactive for it to be Activated or Deleted.', 'mainwp' ); ?>
549 </div>
550 <div class="ui mini form">
551 <div class="field">
552 <select class="ui fluid dropdown" id="mainwp_themes_search_by_status">
553 <option value=""><?php esc_html_e( 'Select status', 'mainwp' ); ?></option>
554 <option value="active" selected><?php esc_html_e( 'Active', 'mainwp' ); ?></option>
555 <option value="inactive"><?php esc_html_e( 'Inactive', 'mainwp' ); ?></option>
556 <option value="installed"><?php esc_html_e( 'Active & Inactive', 'mainwp' ); ?></option>
557 <option value="not_installed"><?php esc_html_e( 'Not installed', 'mainwp' ); ?></option>
558 </select>
559 </div>
560 </div>
561 <?php
562 /**
563 * Action: mainwp_manage_themes_after_search_options
564 *
565 * Fires after the Search Options element on Manage themes.
566 *
567 * @since 4.1
568 */
569 do_action( 'mainwp_manage_themes_after_search_options' );
570 ?>
571 </div>
572 </div>
573 <div class="ui fitted divider"></div>
574 <?php self::render_search_options(); ?>
575 <div class="ui fitted divider"></div>
576 <div class="mainwp-search-submit">
577 <?php
578 /**
579 * Action: mainwp_manage_themes_before_submit_button
580 *
581 * Fires before the Submit Button element on Manage themes.
582 *
583 * @since 4.1
584 */
585 do_action( 'mainwp_manage_themes_before_submit_button' );
586 ?>
587 <input type="button" name="mainwp_show_themes" id="mainwp_show_themes" class="ui green big fluid button" value="<?php esc_attr_e( 'Show Themes', 'mainwp' ); ?>"/>
588 <?php
589 /**
590 * Action: mainwp_manage_themes_after_submit_button
591 *
592 * Fires after the Submit Button element on Manage themes.
593 *
594 * @since 4.1
595 */
596 do_action( 'mainwp_manage_themes_after_submit_button' );
597 ?>
598 </div>
599 <?php
600 /**
601 * Action: mainwp_manage_themes_sidebar_bottom
602 *
603 * Fires at the bottom of the sidebar on Manage themes.
604 *
605 * @since 4.1
606 */
607 do_action( 'mainwp_manage_themes_sidebar_bottom' );
608 ?>
609 </div>
610 <div style="clear:both"></div>
611 </div>
612 <?php
613 self::render_footer( 'Manage' );
614 }
615
616 /**
617 * Render the Search Options Meta Box.
618 *
619 * @uses \MainWP\Dashboard\MainWP_Cache::get_cached_context()
620 */
621 public static function render_search_options() {
622 $cachedSearch = MainWP_Cache::get_cached_context( 'Themes' );
623 $statuses = isset( $cachedSearch['status'] ) ? $cachedSearch['status'] : array();
624 if ( $cachedSearch && isset( $cachedSearch['keyword'] ) ) {
625 $cachedSearch['keyword'] = trim( $cachedSearch['keyword'] );
626 }
627 $disabledNegative = ( null !== $cachedSearch ) && ! empty( $cachedSearch['keyword'] ) ? false : true;
628 $checkedNegative = ! $disabledNegative && ( null !== $cachedSearch ) && ! empty( $cachedSearch['not_criteria'] ) ? true : false;
629 ?>
630 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
631 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Search Options', 'mainwp' ); ?></div>
632 <div class="content active">
633 <div class="ui mini form">
634 <div class="field">
635 <div class="ui input fluid">
636 <input type="text" placeholder="<?php esc_attr_e( 'Theme name', 'mainwp' ); ?>" id="mainwp_theme_search_by_keyword" size="50" class="text" value="<?php echo ( null !== $cachedSearch ) ? esc_attr( $cachedSearch['keyword'] ) : ''; ?>"/>
637 </div>
638 </div>
639 <div class="ui hidden fitted divider"></div>
640 <div class="field">
641 <div class="ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Display sites not meeting the above search criteria.', 'mainwp' ); ?>" data-position="left center" data-inverted="">
642 <input type="checkbox" <?php echo $disabledNegative ? 'disabled' : ''; ?> <?php echo ( $checkedNegative ? 'checked="true"' : '' ); ?> value="1" id="display_sites_not_meeting_criteria" />
643 <label for="display_sites_not_meeting_criteria"><?php esc_html_e( 'Exclude theme', 'mainwp' ); ?></label>
644 </div>
645 </div>
646 </div>
647 </div>
648 </div>
649 <?php
650 if ( is_array( $statuses ) && 0 < count( $statuses ) ) {
651 $status = '';
652 foreach ( $statuses as $st ) {
653 $status .= "'" . esc_js( $st ) . "',";
654 }
655 $status = rtrim( $status, ',' );
656 ?>
657 <script type="text/javascript">
658 jQuery( document ).ready( function () {
659 jQuery( '#mainwp_themes_search_by_status' ).dropdown( 'set selected', [<?php echo $status; // phpcs:ignore -- safe output, to fix incorrect characters. ?>] );
660 } );
661 </script>
662 <?php
663 }
664 ?>
665 <script type="text/javascript">
666 jQuery( document ).on( 'keyup', '#mainwp_theme_search_by_keyword', function () {
667 if( jQuery(this).val() != '' ){
668 jQuery( '#display_sites_not_meeting_criteria' ).prop("disabled", false);
669 } else {
670 jQuery( '#display_sites_not_meeting_criteria' ).closest('.checkbox').checkbox('set unchecked');
671 jQuery( '#display_sites_not_meeting_criteria' ).attr('disabled', 'true');
672 }
673 });
674 </script>
675 <?php
676 }
677
678 /**
679 * Method render_table()
680 *
681 * Render the Child Sites Bulk action & Sidebar Meta boxes.
682 *
683 * @param string $keyword Search keyword parameter.
684 * @param string $status Search status parameter.
685 * @param array $groups Selected groups of child sites.
686 * @param array $sites Selected child sites.
687 * @param mixed $not_criteria Show not criteria result.
688 * @param mixed $clients Selected Clients.
689 *
690 * @return mixed $result Errors|HTML.
691 *
692 * @uses \MainWP\Dashboard\MainWP_Cache::init_cache()
693 * @uses \MainWP\Dashboard\MainWP_Cache::add_context()
694 * @uses \MainWP\Dashboard\MainWP_Cache::add_result()
695 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
696 * @uses \MainWP\Dashboard\MainWP_DB::query()
697 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id()
698 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
699 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
700 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
701 * @uses \MainWP\Dashboard\MainWP_Themes_Handler::get_class_name()
702 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
703 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
704 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
705 */
706 public static function render_table( $keyword, $status, $groups, $sites, $not_criteria, $clients = '' ) { // phpcs:ignore -- complex function.
707 MainWP_Cache::init_cache( 'Themes' );
708
709 $output = new \stdClass();
710 $output->errors = array();
711 $output->themes = array();
712 $output->themes_installed = array();
713 $output->status = $status;
714 $error_results = '';
715
716 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
717 $data_fields[] = 'themes';
718
719 if ( 1 === (int) get_option( 'mainwp_optimize', 1 ) || MainWP_Demo_Handle::is_demo_mode() ) {
720
721 $keyword = trim( $keyword );
722 $multi_kws = explode( ',', $keyword );
723 $multi_kws = array_filter( array_map( 'trim', $multi_kws ) );
724
725 if ( '' !== $sites ) {
726 foreach ( $sites as $k => $v ) {
727 if ( MainWP_Utility::ctype_digit( $v ) ) {
728 $website = MainWP_DB::instance()->get_website_by_id( $v );
729 $allThemes = json_decode( $website->themes, true );
730 $_count = count( $allThemes );
731 $_count_installed = 0;
732 for ( $i = 0; $i < $_count; $i++ ) {
733 $theme = $allThemes[ $i ];
734 if ( 'active' === $status || 'inactive' === $status ) {
735 if ( 1 === (int) $theme['active'] && 'active' !== $status ) {
736 continue;
737 } elseif ( 1 !== $theme['active'] && 'inactive' !== $status ) {
738 continue;
739 }
740 }
741
742 if ( ! empty( $keyword ) ) {
743 if ( $not_criteria ) {
744 if ( MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
745 continue;
746 }
747 } elseif ( ! MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
748 continue;
749 }
750 }
751
752 $theme['websiteid'] = $website->id;
753 $theme['websiteurl'] = $website->url;
754 $theme['websitename'] = $website->name;
755 $output->themes[] = $theme;
756 ++$_count_installed;
757 }
758 if ( 0 === $_count_installed ) {
759 if ( 'not_installed' === $status ) {
760 for ( $i = 0; $i < $_count; $i++ ) {
761 $theme = $allThemes[ $i ];
762 $theme['websiteid'] = $website->id;
763 $theme['websiteurl'] = $website->url;
764 $theme['websitename'] = $website->name;
765 $output->themes_installed[] = $theme;
766 }
767 }
768 }
769 }
770 }
771 }
772
773 if ( '' !== $groups ) {
774 foreach ( $groups as $k => $v ) {
775 if ( MainWP_Utility::ctype_digit( $v ) ) {
776 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $v ) );
777 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
778 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
779 continue;
780 }
781 $allThemes = json_decode( $website->themes, true );
782 $_count = count( $allThemes );
783 $_count_installed = 0;
784 for ( $i = 0; $i < $_count; $i++ ) {
785 $theme = $allThemes[ $i ];
786 if ( 'active' === $status || 'inactive' === $status ) {
787 if ( 1 === (int) $theme['active'] && 'active' !== $status ) {
788 continue;
789 } elseif ( 1 !== $theme['active'] && 'inactive' !== $status ) {
790 continue;
791 }
792 }
793
794 if ( ! empty( $keyword ) ) {
795 if ( $not_criteria ) {
796 if ( MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
797 continue;
798 }
799 } elseif ( ! MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
800 continue;
801 }
802 }
803
804 $theme['websiteid'] = $website->id;
805 $theme['websiteurl'] = $website->url;
806 $theme['websitename'] = $website->name;
807 $output->themes[] = $theme;
808 ++$_count_installed;
809 }
810 if ( 0 === $_count_installed ) {
811 if ( 'not_installed' === $status ) {
812 for ( $i = 0; $i < $_count; $i++ ) {
813 $theme = $allThemes[ $i ];
814 $theme['websiteid'] = $website->id;
815 $theme['websiteurl'] = $website->url;
816 $theme['websitename'] = $website->name;
817 $output->themes_installed[] = $theme;
818 }
819 }
820 }
821 }
822 MainWP_DB::free_result( $websites );
823 }
824 }
825 }
826
827 if ( '' !== $clients && is_array( $clients ) ) {
828 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
829 $clients,
830 array(
831 'select_data' => $data_fields,
832 )
833 );
834 if ( $websites ) {
835 foreach ( $websites as $website ) {
836 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
837 continue;
838 }
839 $allThemes = json_decode( $website->themes, true );
840 $_count = count( $allThemes );
841 $_count_installed = 0;
842 for ( $i = 0; $i < $_count; $i++ ) {
843 $theme = $allThemes[ $i ];
844
845 if ( 'active' === $status || 'inactive' === $status ) {
846 if ( 1 === (int) $theme['active'] && 'active' !== $status ) {
847 continue;
848 } elseif ( 1 !== $theme['active'] && 'inactive' !== $status ) {
849 continue;
850 }
851 }
852 if ( ! empty( $keyword ) ) {
853 if ( $not_criteria ) {
854 if ( MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
855 continue;
856 }
857 } elseif ( ! MainWP_Utility::multi_find_keywords( $theme['title'], $multi_kws ) ) {
858 continue;
859 }
860 }
861
862 $theme['websiteid'] = $website->id;
863 $theme['websiteurl'] = $website->url;
864 $theme['websitename'] = $website->name;
865 $output->themes[] = $theme;
866 ++$_count_installed;
867 }
868 if ( 0 === $_count_installed ) {
869 if ( 'not_installed' === $status ) {
870 for ( $i = 0; $i < $_count; $i++ ) {
871 $theme = $allThemes[ $i ];
872 $theme['websiteid'] = $website->id;
873 $theme['websiteurl'] = $website->url;
874 $theme['websitename'] = $website->name;
875 $output->themes_installed[] = $theme;
876 }
877 }
878 }
879 }
880 }
881 }
882 } else {
883 $dbwebsites = array();
884
885 if ( '' !== $sites ) {
886 foreach ( $sites as $k => $v ) {
887 if ( MainWP_Utility::ctype_digit( $v ) ) {
888 $website = MainWP_DB::instance()->get_website_by_id( $v );
889 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
890 continue;
891 }
892 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
893 $website,
894 $data_fields
895 );
896 }
897 }
898 }
899
900 if ( '' !== $groups ) {
901 foreach ( $groups as $k => $v ) {
902 if ( MainWP_Utility::ctype_digit( $v ) ) {
903 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $v ) );
904 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
905 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
906 continue;
907 }
908 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
909 $website,
910 $data_fields
911 );
912 }
913 MainWP_DB::free_result( $websites );
914 }
915 }
916 }
917
918 if ( '' !== $clients && is_array( $clients ) ) {
919 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
920 $clients,
921 array(
922 'select_data' => $data_fields,
923 )
924 );
925 if ( $websites ) {
926 foreach ( $websites as $website ) {
927 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
928 continue;
929 }
930 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
931 $website,
932 $data_fields
933 );
934 }
935 }
936 }
937
938 $post_data = array(
939 'keyword' => $keyword,
940 );
941
942 if ( 'active' === $status || 'inactive' === $status ) {
943 $post_data['status'] = $status;
944 $post_data['filter'] = true;
945 } else {
946 $post_data['status'] = '';
947 $post_data['filter'] = false;
948 }
949
950 if ( 'not_installed' === $status ) {
951 $post_data['not_installed'] = true;
952 }
953
954 $post_data['not_criteria'] = $not_criteria ? true : false;
955 MainWP_Connect::fetch_urls_authed( $dbwebsites, 'get_all_themes', $post_data, array( MainWP_Themes_Handler::get_class_name(), 'themes_search_handler' ), $output );
956
957 if ( 0 < count( $output->errors ) ) {
958 foreach ( $output->errors as $siteid => $error ) {
959 $error_results .= MainWP_Utility::get_nice_url( $dbwebsites[ $siteid ]->url ) . ' - ' . $error . '<br/>'; // phpcs:ignore WordPress.Security.EscapeOutput
960 }
961 }
962 }
963
964 MainWP_Cache::add_context(
965 'Themes',
966 array(
967 'keyword' => $keyword,
968 'status' => $status,
969 'sites' => ( '' !== $sites ) ? $sites : '',
970 'groups' => ( '' !== $groups ) ? $groups : '',
971 'clients' => ( '' !== $clients ) ? $clients : '',
972 'not_criteria' => $not_criteria ? true : false,
973 )
974 );
975
976 $view_mode = MainWP_Plugins::get_manage_view( 'theme' );
977
978 $bulkActions = self::render_bulk_actions( $status );
979 ob_start();
980
981 if ( ! empty( $error_results ) ) {
982 // phpcs:disable WordPress.Security.EscapeOutput
983 ?>
984 <div class="ui message yellow"><?php echo $error_results; ?></div>
985 <?php
986 //phpcs:enable
987 }
988
989 if ( 'not_installed' === $status ) {
990 if ( empty( $output->themes_installed ) ) {
991 ?>
992 <div class="ui message yellow"><?php esc_html_e( 'No websites found.', 'mainwp' ); ?></div>
993 <?php
994 } else {
995 $themes_list = $output->themes_installed;
996 $view_mode = MAINWP_VIEW_PER_SITE;
997 }
998 } elseif ( 0 === count( $output->themes ) ) {
999 ?>
1000 <div class="ui message yellow"><?php esc_html_e( 'No themes found.', 'mainwp' ); ?></div>
1001 <?php
1002 } else {
1003 $themes_list = $output->themes;
1004 }
1005
1006 $sites = array();
1007 $siteThemes = array();
1008 $themes = array();
1009 $themesNameSites = array();
1010 $themesRealVersion = array();
1011 $themesSlug = array();
1012
1013 if ( ! empty( $themes_list ) ) {
1014
1015 foreach ( $themes_list as $theme ) {
1016 $slug_ver = esc_html( $theme['name'] . '_' . $theme['version'] );
1017 $theme['name'] = esc_html( $theme['name'] );
1018 $theme['version'] = esc_html( $theme['version'] );
1019 $theme['title'] = esc_html( $theme['title'] );
1020 $theme['slug'] = esc_html( $theme['slug'] );
1021 $theme['active'] = ( 1 === (int) $theme['active'] ) ? 1 : 0;
1022 $theme['websiteurl'] = esc_url_raw( $theme['websiteurl'] );
1023
1024 $sites[ $theme['websiteid'] ] = array(
1025 'websiteurl' => $theme['websiteurl'],
1026 'websitename' => $theme['websitename'],
1027 );
1028 $themesName[ $slug_ver ] = $theme['name'];
1029 $themesSlug[ $slug_ver ] = $theme['slug'];
1030
1031 $themesNameSites[ $theme['name'] ][ $theme['websiteid'] ][] = $slug_ver;
1032
1033 $themesRealVersion[ $slug_ver ] = $theme['version'];
1034 if ( ! isset( $siteThemes[ $theme['websiteid'] ] ) || ! is_array( $siteThemes[ $theme['websiteid'] ] ) ) {
1035 $siteThemes[ $theme['websiteid'] ] = array();
1036 }
1037 $siteThemes[ $theme['websiteid'] ][ $slug_ver ] = $theme;
1038 }
1039
1040 ksort( $themesNameSites, SORT_STRING );
1041
1042 if ( MAINWP_VIEW_PER_PLUGIN_THEME === (int) $view_mode ) {
1043 self::render_manage_table( $sites, $themesName, $siteThemes, $themesSlug, $themesNameSites, $themesRealVersion );
1044 } else {
1045 self::render_manage_per_site_table( $sites, $themesName, $siteThemes, $themesSlug, $themesNameSites, $themesRealVersion );
1046 }
1047 MainWP_UI::render_modal_upload_icon();
1048 }
1049
1050 $newOutput = ob_get_clean();
1051 $result = array(
1052 'result' => $newOutput,
1053 'bulk_actions' => $bulkActions,
1054 );
1055
1056 MainWP_Cache::add_result( 'Themes', $result );
1057 return $result;
1058 }
1059
1060 /**
1061 * Method render_manage_per_site_table()
1062 *
1063 * Render the Manage Themes table
1064 *
1065 * @param array $sites List of sites.
1066 * @param array $themesName List of themes.
1067 * @param array $siteThemes List of themes for the site.
1068 * @param string $themesSlug List of theme slugs.
1069 * @param array $themesNameSites Installed theme version.
1070 * @param string $themesRealVersion Current theme version.
1071 */
1072 public static function render_manage_per_site_table( $sites, $themesName = array(), $siteThemes = array(), $themesSlug = array(), $themesNameSites = array(), $themesRealVersion = array() ) { //phpcs:ignore -- complex method.
1073 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
1074 $decodedIgnoredThemes = json_decode( $userExtension->ignored_themes, true );
1075 $trustedThemes = json_decode( $userExtension->trusted_themes, true );
1076 $is_demo = MainWP_Demo_Handle::is_demo_mode();
1077
1078 if ( ! is_array( $trustedThemes ) ) {
1079 $trustedThemes = array();
1080 }
1081
1082 $updateWebsites = array();
1083
1084 foreach ( $sites as $site_id => $info ) {
1085
1086 $theme_upgrades = array();
1087 $website = MainWP_DB::instance()->get_website_by_id( $site_id );
1088 if ( $website ) {
1089 if ( ! $website->is_ignoreThemeUpdates ) {
1090 $theme_upgrades = json_decode( $website->theme_upgrades, true );
1091 $decodedPremiumUpgrades = MainWP_DB::instance()->get_website_option( $website, 'premium_upgrades' );
1092 $decodedPremiumUpgrades = ! empty( $decodedPremiumUpgrades ) ? json_decode( $decodedPremiumUpgrades, true ) : array();
1093
1094 if ( is_array( $decodedPremiumUpgrades ) ) {
1095 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
1096 $premiumUpgrade['premium'] = true;
1097
1098 if ( 'theme' === $premiumUpgrade['type'] ) {
1099 if ( ! is_array( $theme_upgrades ) ) {
1100 $theme_upgrades = array();
1101 }
1102
1103 $premiumUpgrade = array_filter( $premiumUpgrade );
1104
1105 if ( ! isset( $theme_upgrades[ $crrSlug ] ) ) {
1106 $theme_upgrades[ $crrSlug ] = array();
1107 }
1108 $theme_upgrades[ $crrSlug ] = array_merge( $theme_upgrades[ $crrSlug ], $premiumUpgrade );
1109 }
1110 }
1111 }
1112 $ignored_themes = json_decode( $website->ignored_themes, true );
1113 if ( is_array( $ignored_themes ) ) {
1114 $theme_upgrades = array_diff_key( $theme_upgrades, $ignored_themes );
1115 }
1116
1117 if ( is_array( $decodedIgnoredThemes ) ) {
1118 $theme_upgrades = array_diff_key( $theme_upgrades, $decodedIgnoredThemes );
1119 }
1120 }
1121 }
1122 $updateWebsites[ $site_id ] = $theme_upgrades;
1123 }
1124
1125 /**
1126 * Action: mainwp_before_themes_table
1127 *
1128 * Fires before the Themes table.
1129 *
1130 * @since 4.1
1131 */
1132 do_action( 'mainwp_before_themes_table' );
1133 ?>
1134
1135 <div class="ui secondary segment main-master-checkbox">
1136 <div class="ui stackable grid">
1137 <div class="one wide center aligned middle aligned column">
1138 <span class="trigger-all-accordion"><span class="trigger-handle-arrow"><i class="caret right icon"></i><i class="caret down icon"></i></span></span>
1139 </div>
1140 <div class="one wide center aligned middle aligned column"><div class="ui checkbox main-master not-auto-init"><input type="checkbox"/><label></label></div></div>
1141 <div class="five wide middle aligned column"><?php esc_html_e( 'Theme', 'mainwp' ); ?></div>
1142 <div class="two wide center aligned middle aligned column"></div>
1143 <div class="two wide center aligned middle aligned column"></div>
1144 <div class="two wide center aligned middle aligned column"></div>
1145 <div class="two wide center aligned middle aligned column"><?php esc_html_e( 'Themes', 'mainwp' ); ?></div>
1146 </div>
1147 </div>
1148 <div class="mainwp-manage-themes-wrapper main-child-checkbox">
1149 <?php foreach ( $sites as $site_id => $website ) : ?>
1150 <?php
1151 $site_name = $website['websitename'];
1152 $slugVersions = isset( $siteThemes[ $site_id ] ) ? $siteThemes[ $site_id ] : array();
1153 $item_id = $site_id;
1154 $count_themes = count( $slugVersions );
1155 ?>
1156 <div class="ui accordion mainwp-manage-theme-accordion mainwp-manage-theme-item main-child-checkbox" id="<?php echo esc_html( $item_id ); ?>">
1157 <div class="title master-checkbox">
1158 <div class="ui stackable grid">
1159 <div class="one wide center aligned middle aligned column"><i class="dropdown icon dropdown-trigger"></i></div>
1160 <div class="one wide center aligned middle aligned column"><div class="ui checkbox master"><input type="checkbox"><label></label></div></div>
1161 <div class="three wide middle aligned column"><a target="_blank" href="admin.php?page=SiteOpen&newWindow=yes&websiteid=<?php echo intval( $site_id ); ?>&_opennonce=<?php echo esc_html( wp_create_nonce( 'mainwp-admin-nonce' ) ); ?>"><i class="sign in icon"></i></a> <a href="admin.php?page=managesites&dashboard=<?php echo intval( $site_id ); ?>"><?php echo esc_html( $site_name ); ?></a></div>
1162 <div class="two wide center aligned middle aligned column"></div>
1163 <div class="two wide center aligned middle aligned column"></div>
1164 <div class="two wide center aligned middle aligned column"></div>
1165 <div class="two wide center aligned middle aligned column"></div>
1166 <div class="two wide center aligned middle aligned column"><div class="ui label"><i class="icon tint"></i> <?php echo intval( $count_themes ); ?></div></div>
1167 </div>
1168 </div>
1169 <div class="content child-checkbox">
1170 <?php
1171 foreach ( $slugVersions as $slug_ver => $theme ) :
1172
1173 $theme_slug = $themesSlug[ $slug_ver ];
1174 $theme_title = $theme['title'];
1175 $trusted = in_array( $theme_slug, $trustedThemes ) ? true : false;
1176
1177 $theme_version = $siteThemes[ $site_id ][ $slug_ver ]['version'];
1178
1179 $theme_upgrades = isset( $updateWebsites[ $site_id ] ) ? $updateWebsites[ $site_id ] : array();
1180 if ( ! is_array( $theme_upgrades ) ) {
1181 $theme_upgrades = array();
1182 }
1183
1184 $upgradeInfo = isset( $theme_upgrades[ $theme_slug ] ) ? $theme_upgrades[ $theme_slug ] : false;
1185
1186 $active_status_class = '';
1187 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1188 $active_status_class = 'positive';
1189 } elseif ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && empty( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) ) {
1190 $active_status_class = 'negative';
1191 } else {
1192 $active_status_class = '';
1193 }
1194
1195 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['child_active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['child_active'] ) {
1196 $active_status_class .= ' child-active';
1197 }
1198
1199 $not_delete = false;
1200 $parent_str = '';
1201 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['parent_active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['parent_active'] ) {
1202 $parent_str = '<span data-tooltip="' . sprintf( esc_html__( 'Parent theme of the active theme (%s) on the site can not be deleted.', 'mainwp' ), isset( $siteThemes[ $site_id ][ $slug_ver ]['child_theme'] ) ? $siteThemes[ $site_id ][ $slug_ver ]['child_theme'] : '' ) . '" data-position="right center" data-inverted="" data-variation="mini"><i class="lock icon"></i></span>';
1203 $not_delete = true;
1204 }
1205
1206 $new_version = '';
1207 if ( ! empty( $upgradeInfo ) && isset( $upgradeInfo['update']['new_version'] ) ) {
1208 $new_version = $upgradeInfo['update']['new_version'];
1209 }
1210
1211 if ( isset( $siteThemes[ $site_id ][ $slug_ver ] ) && ( empty( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) || 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) ) {
1212 $actived = true;
1213
1214 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1215 $theme_status = '<span class="ui small green basic label">Active</span>';
1216 } elseif ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && empty( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) ) {
1217 $theme_status = '<span class="ui small red basic label">Inactive</span>';
1218 $actived = false;
1219 } else {
1220 $theme_status = '';
1221 }
1222
1223 $item_id = $slug_ver . '_' . $site_id;
1224 $item_id = strtolower( $item_id );
1225 $item_id = preg_replace( '/[[:space:]]+/', '_', $item_id );
1226 ?>
1227 <div class="ui very compact stackable grid mainwp-manage-theme-item-website <?php echo esc_html( $active_status_class ); ?>" updated="0" site-id="<?php echo intval( $site_id ); ?>" theme-slug="<?php echo esc_attr( $theme_slug ); ?>" theme-name="<?php echo esc_html( wp_strip_all_tags( $themesName[ $slug_ver ] ) ); ?>" site-id="<?php echo intval( $site_id ); ?>" site-name="<?php echo esc_html( $site_name ); ?>" id="<?php echo esc_html( $item_id ); ?>" not-delete="<?php echo $not_delete ? 1 : 0; ?>" >
1228 <div class="one wide center aligned middle aligned column"></div>
1229 <div class="one wide center aligned middle aligned column">
1230
1231 <?php if ( '' !== $parent_str ) : ?>
1232 <?php echo $parent_str; //phpcs:ignore -- escaped. ?>
1233 <?php elseif ( $actived ) : ?>
1234 <span data-tooltip="<?php echo esc_html__( 'Active theme on the site can not be deleted.', 'mainwp' ); ?>" data-position="right center" data-inverted="" data-variation="mini"><i class="lock icon"></i></span>
1235 <?php else : ?>
1236 <div class="ui checkbox">
1237 <input type="checkbox" class="mainwp-selected-theme-site" />
1238 <label></label>
1239 </div>
1240 <?php endif; ?>
1241 </div>
1242 <div class="one wide center aligned middle aligned column"><?php echo MainWP_System_Utility::get_theme_icon( $theme_slug ); // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
1243 <div class="three wide middle aligned column"><strong><?php echo esc_html( $theme_title ); ?></strong></div>
1244 <div class="one wide center aligned middle aligned column"><?php echo $theme_status; // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
1245 <div class="two wide center aligned middle aligned column"><?php echo $trusted ? '<span class="ui tiny basic green label">' . esc_html__( 'Trusted', 'mainwp' ) . '</span>' : '<span class="ui tiny basic grey label">' . esc_html__( 'Not Trusted', 'mainwp' ) . '</span>'; ?></div>
1246 <div class="one wide center aligned middle aligned column"></div>
1247 <div class="two wide center aligned middle aligned column current-version">
1248 <?php echo esc_html( $theme_version ); ?>
1249 <?php if ( ! empty( $new_version ) ) : ?>
1250 &rarr; <?php echo esc_html( $new_version ); ?>
1251 <?php endif; ?>
1252 </div>
1253 <div class="two wide right aligned middle aligned column update-column">
1254 <?php if ( ! empty( $upgradeInfo ) && MainWP_Updates::user_can_update_themes() ) : ?>
1255 <a href="javascript:void(0)" class="ui mini green basic <?php echo $is_demo ? 'disabled' : ''; ?> button" onClick="return manage_themes_upgrade_theme( '<?php echo esc_js( rawurlencode( $theme_slug ) ); ?>', <?php echo esc_attr( $site_id ); ?> )"><?php esc_html_e( 'Update Now', 'mainwp' ); ?></a>
1256 <?php endif; ?>
1257 </div>
1258 <div class="two wide center aligned middle aligned column column-actions">
1259 <?php if ( $actived ) : ?>
1260 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_deactivate_themes' ) ) { ?>
1261 <a href="javascript:void(0)" disabled class="ui mini fluid <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Active theme cannot be deactivated. If you need to activate another theme, go to the list of inactive themes and activate the wanted theme.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Deactivate', 'mainwp' ); ?></a>
1262 <?php } ?>
1263 <?php else : ?>
1264 <div class="ui mini fluid buttons">
1265 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_deactivate_themes' ) ) { ?>
1266 <a href="javascript:void(0)" class="mainwp-manages-theme-activate ui green <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Activate the ', 'mainwp' ) . esc_html( wp_strip_all_tags( $theme_title ) ) . esc_attr_e( ' theme on the child site.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Activate', 'mainwp' ); ?></a>
1267 <?php } ?>
1268 <?php if ( mainwp_current_user_have_right( 'dashboard', 'delete_themes' ) && ! $not_delete ) { ?>
1269 <a href="javascript:void(0)" class="mainwp-manages-theme-delete ui <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Delete the', 'mainwp' ) . ' ' . esc_html( wp_strip_all_tags( $theme_title ) ) . ' ' . esc_attr_e( 'theme from the child site.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1270 <?php } ?>
1271 </div>
1272 <?php endif; ?>
1273 </div>
1274 </div>
1275 <?php
1276 }
1277 endforeach;
1278 ?>
1279 </div>
1280 </div>
1281 <?php endforeach; ?>
1282 </div>
1283 <script type="text/javascript">
1284 jQuery( '.mainwp-manage-theme-accordion' ).accordion( {
1285 "selector": {
1286 "trigger" : '.dropdown-trigger',
1287 }
1288 } );
1289
1290 jQuery( '.trigger-all-accordion' ).on( 'click', function() { // not use document here.
1291 if ( jQuery( this ).hasClass( 'active' ) ) {
1292 jQuery( this ).removeClass( 'active' );
1293 jQuery( '.mainwp-manage-themes-wrapper .ui.accordion div.title' ).each( function( i ) {
1294 if ( jQuery( this ).hasClass( 'active' ) ) {
1295 jQuery( this ).find('.dropdown-trigger').trigger( 'click' );
1296 }
1297 } );
1298 } else {
1299 jQuery( this ).addClass( 'active' );
1300 jQuery( '.mainwp-manage-themes-wrapper .ui.accordion div.title' ).each( function( i ) {
1301 if ( !jQuery( this ).hasClass( 'active' ) ) {
1302 jQuery( this ).find('.dropdown-trigger').trigger( 'click' );
1303 }
1304 } );
1305 }
1306 return false;
1307 } );
1308
1309 jQuery(document).ready(function ($) {
1310 mainwp_master_checkbox_init($);
1311 mainwp_get_icon_start();
1312 mainwp_show_hide_install_to_selected_sites( 'theme' );
1313 });
1314
1315 </script>
1316
1317 <?php
1318 /**
1319 * Action: mainwp_after_themes_table
1320 *
1321 * Fires after the Themes table.
1322 *
1323 * @since 4.1
1324 */
1325 do_action( 'mainwp_after_themes_table' );
1326 }
1327
1328 /**
1329 * Method render_manage_table()
1330 *
1331 * Render the Manage Themes table
1332 *
1333 * @param array $sites List of sites.
1334 * @param array $themesName List of themes.
1335 * @param array $siteThemes List of themes for the site.
1336 * @param string $themesSlug List of theme slugs.
1337 * @param array $themesNameSites Installed theme version.
1338 * @param string $themesRealVersion Current theme version.
1339 */
1340 public static function render_manage_table( $sites, $themesName, $siteThemes, $themesSlug, $themesNameSites, $themesRealVersion ) { //phpcs:ignore -- complex method.
1341
1342 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
1343 $decodedIgnoredThemes = json_decode( $userExtension->ignored_themes, true );
1344 $trustedThemes = json_decode( $userExtension->trusted_themes, true );
1345 $is_demo = MainWP_Demo_Handle::is_demo_mode();
1346
1347 if ( ! is_array( $trustedThemes ) ) {
1348 $trustedThemes = array();
1349 }
1350
1351 $updateWebsites = array();
1352
1353 foreach ( $sites as $site_id => $info ) {
1354
1355 $theme_upgrades = array();
1356 $website = MainWP_DB::instance()->get_website_by_id( $site_id );
1357 if ( $website ) {
1358 if ( ! $website->is_ignoreThemeUpdates ) {
1359 $theme_upgrades = json_decode( $website->theme_upgrades, true );
1360 $decodedPremiumUpgrades = MainWP_DB::instance()->get_website_option( $website, 'premium_upgrades' );
1361 $decodedPremiumUpgrades = ! empty( $decodedPremiumUpgrades ) ? json_decode( $decodedPremiumUpgrades, true ) : array();
1362
1363 if ( is_array( $decodedPremiumUpgrades ) ) {
1364 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
1365 $premiumUpgrade['premium'] = true;
1366
1367 if ( 'theme' === $premiumUpgrade['type'] ) {
1368 if ( ! is_array( $theme_upgrades ) ) {
1369 $theme_upgrades = array();
1370 }
1371
1372 $premiumUpgrade = array_filter( $premiumUpgrade );
1373
1374 if ( ! isset( $theme_upgrades[ $crrSlug ] ) ) {
1375 $theme_upgrades[ $crrSlug ] = array();
1376 }
1377 $theme_upgrades[ $crrSlug ] = array_merge( $theme_upgrades[ $crrSlug ], $premiumUpgrade );
1378 }
1379 }
1380 }
1381 $ignored_themes = json_decode( $website->ignored_themes, true );
1382 if ( is_array( $ignored_themes ) ) {
1383 $theme_upgrades = array_diff_key( $theme_upgrades, $ignored_themes );
1384 }
1385
1386 if ( is_array( $decodedIgnoredThemes ) ) {
1387 $theme_upgrades = array_diff_key( $theme_upgrades, $decodedIgnoredThemes );
1388 }
1389 }
1390 }
1391 $updateWebsites[ $site_id ] = $theme_upgrades;
1392 }
1393
1394 /**
1395 * Action: mainwp_before_themes_table
1396 *
1397 * Fires before the Themes table.
1398 *
1399 * @since 4.1
1400 */
1401 do_action( 'mainwp_before_themes_table' );
1402 ?>
1403
1404 <div class="ui secondary segment main-master-checkbox">
1405 <div class="ui stackable grid">
1406 <div class="one wide center aligned middle aligned column">
1407 <span class="trigger-all-accordion"><span class="trigger-handle-arrow"><i class="caret right icon"></i><i class="caret down icon"></i></span></span>
1408 </div>
1409 <div class="one wide center aligned middle aligned column"><div class="ui checkbox main-master not-auto-init"><input type="checkbox"/><label></label></div></div>
1410 <div class="one wide center aligned middle aligned column"></div>
1411 <div class="five wide middle aligned column"><?php esc_html_e( 'Theme', 'mainwp' ); ?></div>
1412 <div class="two wide center aligned middle aligned column"></div>
1413 <div class="two wide center aligned middle aligned column"><?php esc_html_e( 'Latest Version', 'mainwp' ); ?></div>
1414 <div class="two wide center aligned middle aligned column"></div>
1415 <div class="two wide center aligned middle aligned column"><?php esc_html_e( 'Websites', 'mainwp' ); ?></div>
1416 </div>
1417 </div>
1418 <div class="mainwp-manage-themes-wrapper main-child-checkbox">
1419 <?php foreach ( $themesNameSites as $theme_title => $themeSites ) : ?>
1420 <?php
1421 $slugVersions = current( $themeSites );
1422 $slug_ver_first = $slugVersions[0]; // get the first one [slug]_[version] to get theme [slug].
1423 $theme_slug_first = $themesSlug[ $slug_ver_first ];
1424
1425 $item_id = strtolower( $theme_title );
1426 $item_id = preg_replace( '/[[:space:]]+/', '_', $item_id );
1427
1428 $count_sites = count( $themeSites );
1429 $lastest_version = '';
1430 ?>
1431 <div class="ui accordion mainwp-manage-theme-accordion mainwp-manage-theme-item main-child-checkbox" id="<?php echo esc_html( $item_id ); ?>">
1432 <div class="title master-checkbox">
1433 <div class="ui stackable grid">
1434 <div class="one wide center aligned middle aligned column"><i class="dropdown icon dropdown-trigger"></i></div>
1435 <div class="one wide center aligned middle aligned column"><div class="ui checkbox master"><input type="checkbox"><label></label></div></div>
1436 <div class="one wide center aligned middle aligned column"><?php echo MainWP_System_Utility::get_theme_icon( $theme_slug_first ); // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
1437 <div class="five wide middle aligned column"><strong><?php echo esc_html( $theme_title ); ?></strong></div>
1438 <div class="two wide center aligned middle aligned column"></div>
1439 <div class="two wide center aligned middle aligned column lastest-version-info"></div>
1440 <div class="two wide center aligned middle aligned column"></div>
1441 <div class="two wide center aligned middle aligned column"><div class="ui label"><i class="icon wordpress"></i> <?php echo intval( $count_sites ); // phpcs:ignore -- Prevent modify WP icon. ?></div></div>
1442 </div>
1443 </div>
1444 <div class="content child-checkbox">
1445 <?php
1446 foreach ( $themeSites as $site_id => $slugVersions ) :
1447
1448 $site_name = $sites[ $site_id ]['websitename'];
1449
1450 foreach ( $slugVersions as $slug_ver ) :
1451
1452 $theme_slug = $themesSlug[ $slug_ver ];
1453 $trusted = in_array( $theme_slug, $trustedThemes ) ? true : false;
1454
1455 $theme_version = $siteThemes[ $site_id ][ $slug_ver ]['version'];
1456
1457 $theme_upgrades = isset( $updateWebsites[ $site_id ] ) ? $updateWebsites[ $site_id ] : array();
1458 if ( ! is_array( $theme_upgrades ) ) {
1459 $theme_upgrades = array();
1460 }
1461
1462 $upgradeInfo = isset( $theme_upgrades[ $theme_slug ] ) ? $theme_upgrades[ $theme_slug ] : false;
1463
1464 $active_status_class = '';
1465 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1466 $active_status_class = 'positive';
1467 } elseif ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 0 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1468 $active_status_class = 'negative';
1469 } else {
1470 $active_status_class = '';
1471 }
1472
1473 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['child_active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['child_active'] ) {
1474 $active_status_class .= ' child-active';
1475 }
1476
1477 $not_delete = false;
1478 $parent_str = '';
1479 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['parent_active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['parent_active'] ) {
1480 $parent_str = '<span data-tooltip="' . sprintf( esc_html__( 'Parent theme of the active theme (%s) on the site can not be deleted.', 'mainwp' ), isset( $siteThemes[ $site_id ][ $slug_ver ]['child_theme'] ) ? $siteThemes[ $site_id ][ $slug_ver ]['child_theme'] : '' ) . '" data-position="right center" data-inverted="" data-variation="mini"><i class="lock icon"></i></span>';
1481 $not_delete = true;
1482 }
1483
1484 $new_version = '';
1485 if ( ! empty( $upgradeInfo ) && isset( $upgradeInfo['update']['new_version'] ) ) {
1486 $new_version = $upgradeInfo['update']['new_version'];
1487 }
1488
1489 if ( '' === $lastest_version ) {
1490 $lastest_version = $theme_version;
1491 } elseif ( version_compare( $theme_version, $lastest_version, '>' ) ) {
1492 $lastest_version = $theme_version;
1493 }
1494
1495 if ( '' !== $new_version ) {
1496 if ( version_compare( $new_version, $lastest_version, '>' ) ) {
1497 $lastest_version = $new_version;
1498 }
1499 }
1500
1501 if ( isset( $siteThemes[ $site_id ][ $slug_ver ] ) && ( 0 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] || 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) ) {
1502 $actived = true;
1503
1504 if ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 1 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1505 $theme_status = '<span class="ui small green basic label">Active</span>';
1506 } elseif ( isset( $siteThemes[ $site_id ][ $slug_ver ]['active'] ) && 0 === (int) $siteThemes[ $site_id ][ $slug_ver ]['active'] ) {
1507 $theme_status = '<span class="ui small red basic label">Inactive</span>';
1508 $actived = false;
1509 } else {
1510 $theme_status = '';
1511 }
1512
1513 $item_id = $slug_ver . '_' . $site_id;
1514 $item_id = strtolower( $item_id );
1515 $item_id = preg_replace( '/[[:space:]]+/', '_', $item_id );
1516
1517 ?>
1518 <div class="ui very compact stackable grid mainwp-manage-theme-item-website <?php echo esc_html( $active_status_class ); ?>" updated="0" site-id="<?php echo intval( $site_id ); ?>" theme-slug="<?php echo esc_attr( $theme_slug ); ?>" theme-name="<?php echo esc_html( wp_strip_all_tags( $themesName[ $slug_ver ] ) ); ?>" site-id="<?php echo intval( $site_id ); ?>" site-name="<?php echo esc_html( $site_name ); ?>" id="<?php echo esc_html( $item_id ); ?>" not-delete="<?php echo $not_delete ? 1 : 0; ?>" >
1519 <div class="one wide center aligned middle aligned column"></div>
1520 <div class="one wide center aligned middle aligned column">
1521
1522 <?php if ( '' !== $parent_str ) : ?>
1523 <?php echo $parent_str; //phpcs:ignore -- escaped. ?>
1524 <?php elseif ( $actived ) : ?>
1525 <span data-tooltip="<?php echo esc_html__( 'Active theme on the site can not be deleted.', 'mainwp' ); ?>" data-position="right center" data-inverted="" data-variation="mini"><i class="lock icon"></i></span>
1526 <?php else : ?>
1527 <div class="ui checkbox">
1528 <input type="checkbox" class="mainwp-selected-theme-site" />
1529 <label></label>
1530 </div>
1531 <?php endif; ?>
1532 </div>
1533 <div class="three wide middle aligned column"><a target="_blank" href="admin.php?page=SiteOpen&newWindow=yes&websiteid=<?php echo intval( $site_id ); ?>&_opennonce=<?php echo esc_html( wp_create_nonce( 'mainwp-admin-nonce' ) ); ?>"><i class="sign in icon"></i></a> <a href="admin.php?page=managesites&dashboard=<?php echo intval( $site_id ); ?>"><?php echo esc_html( $site_name ); ?></a></div>
1534 <div class="one wide middle aligned column"></div>
1535 <div class="one wide center aligned middle aligned column"><?php echo $theme_status; // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
1536 <div class="two wide center aligned middle aligned column"><?php echo $trusted ? '<span class="ui tiny basic green label">' . esc_html__( 'Trusted', 'mainwp' ) . '</span>' : '<span class="ui tiny basic grey label">' . esc_html__( 'Not Trusted', 'mainwp' ) . '</span>'; ?></div>
1537 <div class="one wide center aligned middle aligned column"></div>
1538 <div class="two wide center aligned middle aligned column current-version">
1539 <?php echo esc_html( $theme_version ); ?>
1540 <?php if ( ! empty( $new_version ) ) : ?>
1541 &rarr; <?php echo esc_html( $new_version ); ?>
1542 <?php endif; ?>
1543 </div>
1544 <div class="two wide right aligned middle aligned column update-column">
1545 <?php if ( ! empty( $upgradeInfo ) && MainWP_Updates::user_can_update_themes() ) : ?>
1546 <a href="javascript:void(0)" class="ui mini green basic <?php echo $is_demo ? 'disabled' : ''; ?> button" onClick="return manage_themes_upgrade_theme( '<?php echo esc_js( rawurlencode( $theme_slug ) ); ?>', <?php echo esc_attr( $site_id ); ?> )"><?php esc_html_e( 'Update Now', 'mainwp' ); ?></a>
1547 <?php endif; ?>
1548 </div>
1549 <div class="two wide center aligned middle aligned column column-actions">
1550 <?php if ( $actived ) : ?>
1551 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_deactivate_themes' ) ) { ?>
1552 <a href="javascript:void(0)" disabled class="ui mini fluid <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Active theme cannot be deactivated. If you need to activate another theme, go to the list of inactive themes and activate the wanted theme.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Deactivate', 'mainwp' ); ?></a>
1553 <?php } ?>
1554 <?php else : ?>
1555 <div class="ui mini fluid buttons">
1556 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_deactivate_themes' ) ) { ?>
1557 <a href="javascript:void(0)" class="mainwp-manages-theme-activate ui green <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Activate the ', 'mainwp' ) . esc_html( wp_strip_all_tags( $theme_title ) ) . esc_attr_e( ' theme on the child site.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Activate', 'mainwp' ); ?></a>
1558 <?php } ?>
1559 <?php if ( mainwp_current_user_have_right( 'dashboard', 'delete_themes' ) && ! $not_delete ) { ?>
1560 <a href="javascript:void(0)" class="mainwp-manages-theme-delete ui <?php echo $is_demo ? 'disabled' : ''; ?> button" data-position="top right" data-tooltip="<?php esc_attr_e( 'Delete the', 'mainwp' ) . ' ' . esc_html( wp_strip_all_tags( $theme_title ) ) . ' ' . esc_attr_e( 'theme from the child site.', 'mainwp' ); ?>" data-inverted=""><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1561 <?php } ?>
1562 </div>
1563 <?php endif; ?>
1564 </div>
1565 </div>
1566 <?php
1567 }
1568 endforeach;
1569 ?>
1570 <span style="display:none" class="lastest-version-hidden" lastest-version="<?php echo esc_html( $lastest_version ); ?>"></span>
1571 <?php
1572 endforeach;
1573 ?>
1574 </div>
1575 </div>
1576 <?php endforeach; ?>
1577 </div>
1578
1579
1580 <script type="text/javascript">
1581 jQuery( '.mainwp-manage-theme-accordion' ).accordion( {
1582 "selector": {
1583 "trigger" : '.dropdown-trigger',
1584 }
1585 } );
1586
1587 jQuery( '.trigger-all-accordion' ).on( 'click', function() { // not use document here.
1588 if ( jQuery( this ).hasClass( 'active' ) ) {
1589 jQuery( this ).removeClass( 'active' );
1590 jQuery( '.mainwp-manage-themes-wrapper .ui.accordion div.title' ).each( function( i ) {
1591 if ( jQuery( this ).hasClass( 'active' ) ) {
1592 jQuery( this ).find('.dropdown-trigger').trigger( 'click' );
1593 }
1594 } );
1595 } else {
1596 jQuery( this ).addClass( 'active' );
1597 jQuery( '.mainwp-manage-themes-wrapper .ui.accordion div.title' ).each( function( i ) {
1598 if ( !jQuery( this ).hasClass( 'active' ) ) {
1599 jQuery( this ).find('.dropdown-trigger').trigger( 'click' );
1600 }
1601 } );
1602 }
1603 return false;
1604 } );
1605
1606 jQuery(document).ready(function ($) {
1607 $('.lastest-version-hidden').each(function(){
1608 $(this).closest('.mainwp-manage-theme-item').find('.lastest-version-info').html($(this).attr('lastest-version'));
1609 });
1610 mainwp_master_checkbox_init($);
1611 mainwp_get_icon_start();
1612 mainwp_show_hide_install_to_selected_sites( 'theme' );
1613 });
1614
1615 </script>
1616
1617 <?php
1618 /**
1619 * Action: mainwp_after_themes_table
1620 *
1621 * Fires after the Themes table.
1622 *
1623 * @since 4.1
1624 */
1625 do_action( 'mainwp_after_themes_table' );
1626 }
1627
1628 /**
1629 * Render the bulk actions UI.
1630 *
1631 * @param mixed $status Theme status.
1632 *
1633 * @return mixed $bulkActions
1634 */
1635 public static function render_bulk_actions( $status ) {
1636 ob_start();
1637 ?>
1638 <select class="ui dropdown" id="mainwp-bulk-actions">
1639 <option value="none"><?php esc_html_e( 'Bulk Actions', 'mainwp' ); ?></option>
1640 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
1641 <option data-value="ignore_updates" value="ignore_updates"><?php esc_html_e( 'Ignore updates', 'mainwp' ); ?></option>
1642 <?php endif; ?>
1643 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_themes' ) ) : ?>
1644 <?php if ( 'inactive' === $status ) : ?>
1645 <option data-value="activate" value="activate"><?php esc_html_e( 'Activate', 'mainwp' ); ?></option>
1646 <?php else : ?>
1647 <option data-value="activate" disabled value="activate"><?php esc_html_e( 'Activate', 'mainwp' ); ?></option>
1648 <?php endif; ?>
1649 <?php endif; ?>
1650 <?php if ( 'inactive' === $status ) : ?>
1651 <?php if ( mainwp_current_user_have_right( 'dashboard', 'delete_themes' ) ) : ?>
1652 <option data-value="delete" value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></option>
1653 <?php endif; ?>
1654 <?php else : ?>
1655 <?php if ( mainwp_current_user_have_right( 'dashboard', 'delete_themes' ) ) : ?>
1656 <option data-value="delete" disabled value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></option>
1657 <?php endif; ?>
1658 <?php endif; ?>
1659 <?php if ( 'all' === $status ) : ?>
1660 <?php if ( mainwp_current_user_have_right( 'dashboard', 'activate_themes' ) ) : ?>
1661 <option data-value="activate" disabled value="activate"><?php esc_html_e( 'Activate', 'mainwp' ); ?></option>
1662 <?php endif; ?>
1663 <?php if ( mainwp_current_user_have_right( 'dashboard', 'delete_themes' ) ) : ?>
1664 <option data-value="delete" disabled value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></option>
1665 <?php endif; ?>
1666 <?php endif; ?>
1667
1668 <?php
1669 /**
1670 * Action: mainwp_themes_bulk_action
1671 *
1672 * Adds a new action to the Manage Themes bulk actions menu.
1673 *
1674 * @param string $status Status search parameter.
1675 *
1676 * @since 4.1
1677 */
1678 do_action( 'mainwp_themes_bulk_action' );
1679 ?>
1680 </select>
1681 <button class="ui mini basic button" href="javascript:void(0)" id="mainwp-do-themes-bulk-actions"><?php esc_html_e( 'Apply', 'mainwp' ); ?></button>
1682 <span id="mainwp_bulk_action_loading"><i class="ui active inline loader tiny"></i></span>
1683 <?php
1684 $bulkActions = ob_get_clean();
1685 return $bulkActions;
1686 }
1687
1688
1689 /** Render the Install Themes Tab. */
1690 public static function render_install() {
1691 wp_enqueue_script( 'mainwp-theme', MAINWP_PLUGIN_URL . 'assets/js/mainwp-theme.js', array( 'wp-backbone', 'wp-a11y' ), MAINWP_VERSION, true );
1692 wp_localize_script(
1693 'mainwp-theme',
1694 '_mainwpThemeSettings',
1695 array(
1696 'themes' => false,
1697 'settings' => array(
1698 'isInstall' => true,
1699 'canInstall' => false,
1700 'installURI' => null,
1701 'adminUrl' => wp_parse_url( self_admin_url(), PHP_URL_PATH ),
1702 ),
1703 'l10n' => array(
1704 'addNew' => esc_html__( 'Add new theme' ),
1705 'search' => esc_html__( 'Search themes' ),
1706 'searchPlaceholder' => esc_html__( 'Search themes...' ),
1707 'upload' => esc_html__( 'Upload theme' ),
1708 'back' => esc_html__( 'Back' ),
1709 'error' => esc_html__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ),
1710 'themesFound' => esc_html__( 'Number of themes found: %d' ),
1711 'noThemesFound' => esc_html__( 'No themes found. Try a different search.' ),
1712 'collapseSidebar' => esc_html__( 'Collapse sidebar' ),
1713 'expandSidebar' => esc_html__( 'Expand sidebar' ),
1714 ),
1715 'installedThemes' => array(),
1716 )
1717 );
1718 self::render_header( 'Install' );
1719 self::render_themes_table();
1720 self::render_footer( 'Install' );
1721 }
1722
1723 /**
1724 * Render the Themes table for the Install Themes Tab.
1725 *
1726 * @uses \MainWP\Dashboard\MainWP_UI::render_modal_install_plugin_theme()
1727 *
1728 * @uses \MainWP\Dashboard\MainWP_Install_Bulk::render_upload()
1729 */
1730 public static function render_themes_table() {
1731 if ( ! mainwp_current_user_have_right( 'dashboard', 'install_themes' ) ) {
1732 mainwp_do_not_have_permissions( esc_html__( 'install themes', 'mainwp' ) );
1733 return;
1734 }
1735 $favorites_enabled = is_plugin_active( 'mainwp-favorites-extension/mainwp-favorites-extension.php' );
1736 ?>
1737 <div class="ui alt segment" id="mainwp-install-themes">
1738 <div class="mainwp-main-content">
1739 <div class="mainwp-actions-bar">
1740 <div class="ui stackable grid">
1741 <div class="ui two column row">
1742 <div class="column">
1743 <div class="ui fluid search focus">
1744 <div class="ui icon fluid input hide-if-upload" id="mainwp-search-themes-input-container" skeyword="<?php echo isset( $_GET['s'] ) ? esc_html( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>"></div>
1745 <div class="results"></div>
1746 </div>
1747 <?php
1748 /**
1749 * Install Themes actions bar (left)
1750 *
1751 * Fires at the left side of the actions bar on the Install Themes screen, after the search form.
1752 *
1753 * @since 4.0
1754 */
1755 do_action( 'mainwp_install_themes_actions_bar_left' );
1756 ?>
1757 </div>
1758 <div class="right aligned column">
1759 <div class="ui buttons">
1760 <a href="#" class="ui button browse-themes" ><?php esc_html_e( 'Install from WordPress.org', 'mainwp' ); ?></a>
1761 <div class="or"></div>
1762 <a href="#" class="ui button upload" ><?php esc_html_e( 'Upload .zip file', 'mainwp' ); ?></a>
1763 </div>
1764 <?php
1765 /**
1766 * Install Themes actions bar (right)
1767 *
1768 * Fires at the right side of the actions bar on the Install Themes screen.
1769 *
1770 * @since 4.0
1771 */
1772 do_action( 'mainwp_install_themes_actions_bar_right' );
1773 ?>
1774 </div>
1775 </div>
1776 </div>
1777 </div>
1778 <div class="ui segment">
1779 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-install-themes-info-message' ) ) : ?>
1780 <div class="ui info message">
1781 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-install-themes-info-message"></i>
1782 <?php printf( esc_html__( 'Install themes on your child sites. You can install themes from the WordPress.org repository or by uploading a ZIP file. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/install-themes/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?>
1783 </div>
1784 <?php endif; ?>
1785 <div id="mainwp-message-zone" class="ui message" style="display:none;"></div>
1786 <div class="mainwp-upload-theme">
1787 <?php MainWP_Install_Bulk::render_upload( 'theme' ); ?>
1788 </div>
1789 <div id="themes-loading" class="ui large text loader"><?php esc_html_e( 'Loading Themes...', 'mainwp' ); ?></div>
1790 <form id="theme-filter" method="post">
1791 <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
1792 <div class="mainwp-browse-themes content-filterable hide-if-upload"></div>
1793 <div class="theme-install-overlay wp-full-overlay expanded"></div>
1794 </form>
1795
1796 <?php MainWP_UI::render_modal_install_plugin_theme( 'theme' ); ?>
1797 </div>
1798 </div>
1799 <div class="mainwp-side-content mainwp-no-padding">
1800 <?php do_action( 'mainwp_manage_themes_sidebar_top' ); ?>
1801 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
1802 <?php do_action( 'mainwp_manage_themes_before_select_sites' ); ?>
1803 <div class="active title"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
1804 <div class="content active">
1805 <?php
1806 $selected_sites = array();
1807
1808 if ( isset( $_GET['selected_sites'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1809 $selected_sites = explode( '-', sanitize_text_field( wp_unslash( $_GET['selected_sites'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitize ok.
1810 $selected_sites = array_map( 'intval', $selected_sites );
1811 $selected_sites = array_filter( $selected_sites );
1812 }
1813 ?>
1814 <?php
1815 $sel_params = array(
1816 'class' => 'mainwp_select_sites_box_left',
1817 'selected_sites' => $selected_sites,
1818 'show_client' => true,
1819 );
1820 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
1821 ?>
1822 </div>
1823 <?php do_action( 'mainwp_manage_themes_after_select_sites' ); ?>
1824 </div>
1825 <div class="ui fitted divider"></div>
1826 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
1827 <?php do_action( 'mainwp_manage_themes_before_search_options' ); ?>
1828 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Installation Options', 'mainwp' ); ?></div>
1829 <div class="content active">
1830 <div class="ui form">
1831 <div class="field">
1832 <div class="ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled and the theme already installed on the sites, the already installed version will be overwritten.', 'mainwp' ); ?>" data-position="left center" data-inverted="">
1833 <input type="checkbox" value="2" checked="checked" id="chk_overwrite" />
1834 <label for="chk_overwrite"><?php esc_html_e( 'Overwrite existing version', 'mainwp' ); ?></label>
1835 </div>
1836 </div>
1837 </div>
1838 </div>
1839 <?php do_action( 'mainwp_manage_themes_after_search_options' ); ?>
1840 </div>
1841 <div class="ui fitted divider"></div>
1842 <div class="mainwp-search-submit">
1843 <?php do_action( 'mainwp_manage_themes_before_submit_button' ); ?>
1844 <?php
1845 /**
1846 * Disables themes installation
1847 *
1848 * Filters whether file modifications are allowed on the Dashboard site. If not, installation process will be disabled too.
1849 *
1850 * @since 4.1
1851 */
1852 $allow_install = apply_filters( 'file_mod_allowed', true, 'mainwp_install_theme' );
1853 if ( $allow_install ) {
1854 $is_demo = MainWP_Demo_Handle::is_demo_mode();
1855 if ( $is_demo ) {
1856 MainWP_Demo_Handle::get_instance()->render_demo_disable_button( '<input type="button" disabled="disabled" class="ui green big fluid button disabled" value="' . esc_attr__( 'Complete Installation', 'mainwp' ) . '" />' );
1857 } else {
1858 ?>
1859 <input type="button" value="<?php esc_attr_e( 'Complete Installation', 'mainwp' ); ?>" class="ui green big fluid button" bulk-action="install" id="mainwp_theme_bulk_install_btn" name="bulk-install">
1860 <?php
1861 }
1862 }
1863 ?>
1864 <?php do_action( 'mainwp_manage_themes_after_submit_button' ); ?>
1865 </div>
1866 <?php do_action( 'mainwp_manage_themes_sidebar_bottom', 'install' ); ?>
1867 </div>
1868 <div class="ui clearing hidden divider"></div>
1869 </div>
1870 <?php
1871 $favorites = '';
1872 $favorites_themes = apply_filters( 'mainwp_favorites_themes', array() );
1873 if ( is_array( $favorites_themes ) && ! empty( $favorites_themes ) ) {
1874 $favorites = wp_json_encode( $favorites_themes );
1875 }
1876 ?>
1877 <div id="mainwp-favorites-themes" favorites-themes="<?php echo esc_attr( $favorites ); ?>"></div>
1878 <script id="tmpl-theme" type="text/template">
1879 <# if ( data.screenshot_url ) { #>
1880 <div class="image">
1881 <img src="{{ data.screenshot_url }}" />
1882 </div>
1883 <# } #>
1884 <div class="content">
1885 <div class="header">{{ data.name }}</div>
1886 <div class="meta">
1887 <a><?php printf( esc_html__( 'By %s', 'mainwp' ), '{{ data.author }}' ); ?></a>
1888 </div>
1889 </div>
1890 <div class="extra content">
1891 <span class="right floated"><?php printf( esc_html__( 'Version: %s', 'mainwp' ), '{{ data.version }}' ); ?></span>
1892 <# if ( data.rating ) { #>
1893 <div class="star-rating rating-{{ Math.round( data.rating / 10 ) * 10 }}">
1894 <span class="one"></span><span class="two"></span><span class="three"></span><span class="four"></span><span class="five"></span>
1895 <small class="ratings">{{ data.num_ratings }}</small>
1896 </div>
1897 <# } else { #>
1898 <div class="star-rating">
1899 <small class="ratings"><?php esc_html_e( 'This theme has not been rated yet.', 'mainwp' ); ?></small>
1900 </div>
1901 <# } #>
1902 </div>
1903 <div class="extra content mainwp-theme-lnks">
1904 <a href="#" id="mainwp-{{data.slug}}-preview" class="ui mini button mainwp-theme-preview"><?php esc_html_e( 'Preview', 'mainwp' ); ?></a>
1905 <div class="ui radio checkbox right floated">
1906 <input name="install-theme" type="radio" id="install-theme-{{data.slug}}" title="Install {{data.name}}" theme-name="{{data.name}}" theme-version="{{data.version}}">
1907 <label for="install-theme-{{data.slug}}"><?php esc_html_e( 'Install Theme', 'mainwp' ); ?></label>
1908 </div>
1909 </div>
1910 <?php if ( $favorites_enabled ) { ?>
1911 <div class="extra content">
1912 <span><?php esc_html_e( 'Add to Favorites', 'mainwp-favorites-extension' ); ?></span>
1913 <a class="ui huge star rating right floated <# if ( data.added_fav ) { #> favorite <# } #>" data-max-rating="1" id="add-favorite-theme-{{data.slug}}"></a>
1914 </div>
1915 <?php } ?>
1916 <?php do_action( 'mainwp_install_theme_card_template_bottom' ); ?>
1917 </script>
1918
1919 <script id="tmpl-theme-preview" type="text/template">
1920 <div class="wp-full-overlay-sidebar">
1921 <div class="wp-full-overlay-header">
1922 <a href="#" class="close-full-overlay"><span class="screen-reader-text"><?php esc_html_e( 'Close', 'mainwp' ); ?></span></a>
1923 <a href="#" class="previous-theme"><span class="screen-reader-text"><?php esc_html_e( 'Previous', 'mainwp' ); ?></span></a>
1924 <a href="#" class="next-theme"><span class="screen-reader-text"><?php esc_html_e( 'Next', 'mainwp' ); ?></span></a>
1925 </div>
1926 <div class="wp-full-overlay-sidebar-content">
1927 <div class="install-theme-info">
1928 <h3 class="theme-name">{{ data.name }}</h3>
1929 <span class="theme-by"><?php printf( esc_html__( 'By %s', 'mainwp' ), '{{ data.author }}' ); ?></span>
1930 <img class="theme-screenshot" src="{{ data.screenshot_url }}" alt="" />
1931 <div class="theme-details">
1932 <# if ( data.rating ) { #>
1933 <div class="star-rating rating-{{ Math.round( data.rating / 10 ) * 10 }}">
1934 <span class="one"></span><span class="two"></span><span class="three"></span><span class="four"></span><span class="five"></span>
1935 <small class="ratings">{{ data.num_ratings }}</small>
1936 </div>
1937 <# } else { #>
1938 <div class="star-rating">
1939 <small class="ratings"><?php esc_html_e( 'This theme has not been rated yet.', 'mainwp' ); ?></small>
1940 </div>
1941 <# } #>
1942 <div class="theme-version"><?php printf( esc_html__( 'Version: %s', 'mainwp' ), '{{ data.version }}' ); ?></div>
1943 <div class="theme-description">{{{ data.description }}}</div>
1944 </div>
1945 </div>
1946 </div>
1947 <div class="wp-full-overlay-footer">
1948 <button type="button" class="collapse-sidebar button-secondary" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar', 'mainwp' ); ?>">
1949 <span class="collapse-sidebar-arrow"></span>
1950 <span class="collapse-sidebar-label"><?php esc_html_e( 'Collapse', 'mainwp' ); ?></span>
1951 </button>
1952 </div>
1953 </div>
1954 <div class="wp-full-overlay-main">
1955 <iframe src="{{ data.preview_url }}" title="<?php esc_attr_e( 'Preview', 'mainwp' ); ?>" />
1956 </div>
1957 </script>
1958 <script type="text/javascript">
1959 jQuery( document ).ready( function() {
1960 setTimeout( function () {
1961 jQuery('#wp-filter-search-input').val( jQuery('#mainwp-search-themes-input-container').attr('skeyword') );
1962 }, 1000 );
1963 });
1964 </script>
1965 <?php
1966 }
1967
1968 /**
1969 * Render the Themes Auto Update Tab.
1970 *
1971 * @uses \MainWP\Dashboard\MainWP_UI::render_modal_edit_notes()
1972 */
1973 public static function render_auto_update() { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
1974
1975 $cachedThemesSearch = null;
1976 if ( isset( $_SESSION['SNThemesAllStatus'] ) ) {
1977 $cachedThemesSearch = $_SESSION['SNThemesAllStatus']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1978 }
1979
1980 self::render_header( 'AutoUpdate' );
1981
1982 if ( ! mainwp_current_user_have_right( 'dashboard', 'trust_untrust_updates' ) ) {
1983 mainwp_do_not_have_permissions( esc_html__( 'trust/untrust updates', 'mainwp' ) );
1984 return;
1985 } else {
1986 $snThemeAutomaticDailyUpdate = get_option( 'mainwp_themeAutomaticDailyUpdate' );
1987
1988 if ( false === $snThemeAutomaticDailyUpdate ) {
1989 $snThemeAutomaticDailyUpdate = get_option( 'mainwp_automaticDailyUpdate' );
1990 update_option( 'mainwp_themeAutomaticDailyUpdate', $snThemeAutomaticDailyUpdate );
1991 }
1992
1993 ?>
1994 <div class="ui alt segment" id="mainwp-theme-auto-updates">
1995 <div class="mainwp-main-content">
1996 <div class="mainwp-actions-bar">
1997 <div class="ui mini form stackable grid">
1998 <div class="ui two column row">
1999 <div class="left aligned column">
2000 <select id="mainwp-bulk-actions" name="bulk_action" class="ui mini selection dropdown">
2001 <option class="item" value=""><?php esc_html_e( 'Bulk Actions', 'mainwp' ); ?></option>
2002 <option class="item" value="trust"><?php esc_html_e( 'Trust', 'mainwp' ); ?></option>
2003 <option class="item" value="untrust"><?php esc_html_e( 'Untrust', 'mainwp' ); ?></option>
2004 <?php
2005 /**
2006 * Action: mainwp_themes_auto_updates_bulk_action
2007 *
2008 * Adds new action to the bulk actions menu on Themes Auto Updates.
2009 *
2010 * @since 4.1
2011 */
2012 do_action( 'mainwp_themes_auto_updates_bulk_action' );
2013 ?>
2014 </select>
2015 <input type="button" name="" id="mainwp-bulk-trust-themes-action-apply" class="ui mini basic button" value="<?php esc_attr_e( 'Apply', 'mainwp' ); ?>"/>
2016 </div>
2017 <div class="right aligned column"></div>
2018 </div>
2019 </div>
2020 </div>
2021 <?php if ( isset( $_GET['message'] ) && 'saved' === $_GET['message'] ) : // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>
2022 <div class="ui message green"><?php esc_html_e( 'Settings have been saved.', 'mainwp' ); ?></div>
2023 <?php endif; ?>
2024 <div id="mainwp-message-zone" class="ui message" style="display:none"></div>
2025 <div id="mainwp-auto-updates-themes-content" class="ui segment">
2026 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-disable-auto-updates-info-message' ) ) : ?>
2027 <div class="ui info message">
2028 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-disable-auto-updates-info-message"></i>
2029 <div><?php printf( esc_html__( 'Check out %1$show to disable the WordPress built in auto-updates feature%2$s.', 'mainwp' ), '<a href="https://mainwp.com/how-to-disable-automatic-plugin-and-theme-updates-on-your-child-sites/" target="_blank">', '</a>' ); ?></div>
2030 </div>
2031 <?php endif; ?>
2032 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-themes-auto-updates-info-message' ) ) : ?>
2033 <div class="ui info message">
2034 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-themes-auto-updates-info-message"></i>
2035 <div><?php esc_html_e( 'The MainWP Advanced Auto Updates feature is a tool for your Dashboard to automatically update themes that you trust to be updated without breaking your Child sites.', 'mainwp' ); ?></div>
2036 <div><?php esc_html_e( 'Only mark themes as trusted if you are absolutely sure they can be automatically updated by your MainWP Dashboard without causing issues on the Child sites! ', 'mainwp' ); ?></div>
2037 <div><strong><?php esc_html_e( 'Advanced Auto Updates a delayed approximately 24 hours from the update release. Ignored themes can not be automatically updated.', 'mainwp' ); ?></strong></div>
2038 </div>
2039 <?php endif; ?>
2040 <div class="ui inverted dimmer">
2041 <div class="ui text loader"><?php esc_html_e( 'Loading themes', 'mainwp' ); ?></div>
2042 </div>
2043 <div id="mainwp-auto-updates-themes-table-wrapper">
2044 <?php
2045 if ( isset( $_SESSION['SNThemesAll'] ) ) {
2046 self::render_all_themes_table( $_SESSION['SNThemesAll'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2047 }
2048 ?>
2049 </div>
2050 </div>
2051 </div>
2052 <div class="mainwp-side-content mainwp-no-padding">
2053 <?php do_action( 'mainwp_manage_themes_sidebar_top' ); ?>
2054 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
2055 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Theme Status to Search', 'mainwp' ); ?></div>
2056 <div class="content active">
2057 <div class="ui mini form">
2058 <div class="field">
2059 <select class="ui fluid dropdown" id="mainwp_au_theme_status">
2060 <option value="all" <?php echo ( null !== $cachedThemesSearch && 'all' === $cachedThemesSearch['theme_status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Active and Inactive', 'mainwp' ); ?></option>
2061 <option value="active" <?php echo ( null !== $cachedThemesSearch && 'active' === $cachedThemesSearch['theme_status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Active', 'mainwp' ); ?></option>
2062 <option value="inactive" <?php echo ( null !== $cachedThemesSearch && 'inactive' === $cachedThemesSearch['theme_status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Inactive', 'mainwp' ); ?></option>
2063 </select>
2064 </div>
2065 </div>
2066 </div>
2067 </div>
2068 <div class="ui fitted divider"></div>
2069 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
2070 <?php do_action( 'mainwp_manage_themes_before_search_options' ); ?>
2071 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Search Options', 'mainwp' ); ?></div>
2072 <div class="content active">
2073 <div class="ui mini form">
2074 <div class="field">
2075 <select class="ui fluid dropdown" id="mainwp_au_theme_trust_status">
2076 <option value="all" <?php echo ( null !== $cachedThemesSearch && 'all' === $cachedThemesSearch['status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Trusted, Not trusted and Ignored', 'mainwp' ); ?></option>
2077 <option value="trust" <?php echo ( null !== $cachedThemesSearch && 'trust' === $cachedThemesSearch['status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Trusted', 'mainwp' ); ?></option>
2078 <option value="untrust" <?php echo ( null !== $cachedThemesSearch && 'untrust' === $cachedThemesSearch['status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Not trusted', 'mainwp' ); ?></option>
2079 <option value="ignored" <?php echo ( null !== $cachedThemesSearch && 'ignored' === $cachedThemesSearch['status'] ) ? 'selected' : ''; ?>><?php esc_html_e( 'Ignored', 'mainwp' ); ?></option>
2080 </select>
2081 </div>
2082 <div class="field">
2083 <div class="ui input fluid">
2084 <input type="text" placeholder="<?php esc_attr_e( 'Theme name', 'mainwp' ); ?>" id="mainwp_au_theme_keyword" class="text" value="<?php echo ( null !== $cachedThemesSearch ) ? esc_attr( $cachedThemesSearch['keyword'] ) : ''; ?>">
2085 </div>
2086 </div>
2087 </div>
2088 </div>
2089 <?php do_action( 'mainwp_manage_themes_after_search_options' ); ?>
2090 </div>
2091 <div class="ui fitted divider"></div>
2092 <div class="mainwp-search-submit">
2093 <?php do_action( 'mainwp_manage_themes_before_submit_button' ); ?>
2094 <a href="#" class="ui green big fluid button" id="mainwp_show_all_active_themes"><?php esc_html_e( 'Show Themes', 'mainwp' ); ?></a>
2095 <?php do_action( 'mainwp_manage_themes_after_submit_button' ); ?>
2096 </div>
2097 <?php do_action( 'mainwp_manage_themes_sidebar_bottom' ); ?>
2098 </div>
2099 </div>
2100 <?php
2101 }
2102 MainWP_UI::render_modal_edit_notes( 'theme' );
2103 self::render_footer( 'AutoUpdate' );
2104 }
2105
2106 /**
2107 * Method render_all_themes_table()
2108 *
2109 * Render the All Themes Table.
2110 *
2111 * @param null $output Function output.
2112 *
2113 * @return void
2114 *
2115 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
2116 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
2117 * @uses \MainWP\Dashboard\MainWP_DB::query()
2118 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
2119 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2120 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
2121 * @uses \MainWP\Dashboard\MainWP_Themes_Handler::get_class_name()
2122 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
2123 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
2124 */
2125 public static function render_all_themes_table( $output = null ) { // phpcs:ignore -- not quite complex function.
2126 $keyword = null;
2127 $search_status = 'all';
2128
2129 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
2130
2131 if ( null === $output ) {
2132 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2133 $keyword = isset( $_POST['keyword'] ) && ! empty( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : null;
2134 $search_status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : 'all';
2135 $search_theme_status = isset( $_POST['theme_status'] ) ? sanitize_text_field( wp_unslash( $_POST['theme_status'] ) ) : 'all';
2136 // phpcs:enable
2137
2138 $output = new \stdClass();
2139 $output->errors = array();
2140 $output->themes = array();
2141 $output->themes_installed = array();
2142 $output->status = $search_theme_status;
2143
2144 if ( 1 === (int) get_option( 'mainwp_optimize', 1 ) || MainWP_Demo_Handle::is_demo_mode() ) {
2145 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user() );
2146 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2147 $allThemes = json_decode( $website->themes, true );
2148 $_count = count( $allThemes );
2149 for ( $i = 0; $i < $_count; $i++ ) {
2150 $theme = $allThemes[ $i ];
2151 if ( 'all' !== $search_theme_status ) {
2152 if ( 1 === (int) $theme['active'] && 'active' !== $search_theme_status ) {
2153 continue;
2154 } elseif ( 1 !== $theme['active'] && 'inactive' !== $search_theme_status ) {
2155 continue;
2156 }
2157 }
2158 if ( ! empty( $keyword ) ) {
2159 $keyword = trim( $keyword );
2160 $multi_kws = explode( ',', $keyword );
2161 $multi_kws = array_filter( array_map( 'trim', $multi_kws ) );
2162 if ( ! MainWP_Utility::multi_find_keywords( $theme['name'], $multi_kws ) ) {
2163 continue;
2164 }
2165 }
2166 $theme['websiteid'] = $website->id;
2167 $theme['websiteurl'] = $website->url;
2168 $output->themes[] = $theme;
2169 }
2170 }
2171 MainWP_DB::free_result( $websites );
2172 } else {
2173 $dbwebsites = array();
2174 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user() );
2175 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2176 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
2177 continue;
2178 }
2179 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2180 $website,
2181 $data_fields
2182 );
2183 }
2184 MainWP_DB::free_result( $websites );
2185
2186 $post_data = array( 'keyword' => $keyword );
2187
2188 if ( 'active' === $search_theme_status || 'inactive' === $search_theme_status ) {
2189 $post_data['status'] = $search_theme_status;
2190 $post_data['filter'] = true;
2191 } else {
2192 $post_data['status'] = '';
2193 $post_data['filter'] = false;
2194 }
2195
2196 MainWP_Connect::fetch_urls_authed( $dbwebsites, 'get_all_themes', $post_data, array( MainWP_Themes_Handler::get_class_name(), 'themes_search_handler' ), $output );
2197
2198 if ( 0 < count( $output->errors ) ) {
2199 foreach ( $output->errors as $siteid => $error ) {
2200 echo MainWP_Utility::get_nice_url( $dbwebsites[ $siteid ]->url ) . ' - ' . $error . ' <br/>'; // phpcs:ignore WordPress.Security.EscapeOutput
2201 }
2202 echo '<div class="ui hidden divider"></div>';
2203 }
2204
2205 if ( count( $output->errors ) === count( $dbwebsites ) ) {
2206 $_SESSION['SNThemesAll'] = $output;
2207 return;
2208 }
2209 }
2210
2211 $_SESSION['SNThemesAll'] = $output;
2212 $_SESSION['SNThemesAllStatus'] = array(
2213 'keyword' => $keyword,
2214 'status' => $search_status,
2215 'theme_status' => $search_theme_status,
2216 );
2217 } elseif ( isset( $_SESSION['SNThemesAllStatus'] ) ) {
2218 //phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2219 $keyword = isset( $_SESSION['SNThemesAllStatus']['keyword'] ) ? $_SESSION['SNThemesAllStatus']['keyword'] : '';
2220 $search_status = isset( $_SESSION['SNThemesAllStatus']['status'] ) ? $_SESSION['SNThemesAllStatus']['status'] : '';
2221 $search_theme_status = isset( $_SESSION['SNThemesAllStatus']['theme_status'] ) ? $_SESSION['SNThemesAllStatus']['theme_status'] : '';
2222 //phpcs:enable
2223 }
2224
2225 if ( 0 === count( $output->themes ) ) {
2226 ?>
2227 <div class="ui message yellow"><?php esc_html_e( 'No themes found.', 'mainwp' ); ?></div>
2228 <?php
2229 return;
2230 }
2231
2232 $themes = array();
2233 foreach ( $output->themes as $theme ) {
2234 $themes[ $theme['slug'] ] = $theme;
2235 }
2236 asort( $themes );
2237
2238 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
2239 $decodedIgnoredThemes = json_decode( $userExtension->ignored_themes, true );
2240 $trustedThemes = json_decode( $userExtension->trusted_themes, true );
2241 if ( ! is_array( $trustedThemes ) ) {
2242 $trustedThemes = array();
2243 }
2244 $trustedThemesNotes = json_decode( $userExtension->trusted_themes_notes, true );
2245 if ( ! is_array( $trustedThemesNotes ) ) {
2246 $trustedThemesNotes = array();
2247 }
2248 self::render_all_themes_html( $themes, $search_status, $trustedThemes, $trustedThemesNotes, $decodedIgnoredThemes );
2249 }
2250
2251 /**
2252 * Render all themes html.
2253 *
2254 * @param mixed $themes Themes list.
2255 * @param mixed $search_status Search status.
2256 * @param mixed $trustedThemes Trusted themes.
2257 * @param mixed $trustedThemesNotes Trusted themes notes.
2258 * @param mixed $decodedIgnoredThemes Decoded ignored themes.
2259 *
2260 * @uses \MainWP\Dashboard\MainWP_Utility::esc_content()
2261 */
2262 public static function render_all_themes_html( $themes, $search_status, $trustedThemes, $trustedThemesNotes, $decodedIgnoredThemes ) {
2263
2264 /**
2265 * Action: mainwp_themes_before_auto_updates_table
2266 *
2267 * Fires before the Auto Update Themes table.
2268 *
2269 * @since 4.1
2270 */
2271 do_action( 'mainwp_themes_before_auto_updates_table' );
2272 ?>
2273 <table class="ui unstackable table" id="mainwp-all-active-themes-table">
2274 <thead>
2275 <tr>
2276 <th class="no-sort collapsing check-column"><span class="ui checkbox"><input id="cb-select-all-top" type="checkbox" /></span></th>
2277 <th data-priority="1"><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2278 <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
2279 <th data-priority="2" class="collapsing"><?php esc_html_e( 'Trust Status', 'mainwp' ); ?></th>
2280 <th><?php esc_html_e( 'Ignored Status', 'mainwp' ); ?></th>
2281 <th class="collapsing"></th>
2282 <th class="collapsing"><?php esc_html_e( 'Notes', 'mainwp' ); ?></th>
2283 </tr>
2284 </thead>
2285
2286 <tbody>
2287 <?php foreach ( $themes as $slug => $theme ) : ?>
2288 <?php
2289 $name = esc_html( $theme['name'] );
2290 if ( ! empty( $search_status ) && 'all' !== $search_status ) {
2291 if ( 'trust' === $search_status && ! in_array( $slug, $trustedThemes ) ) {
2292 continue;
2293 } elseif ( 'untrust' === $search_status && in_array( $slug, $trustedThemes ) ) {
2294 continue;
2295 } elseif ( 'ignored' === $search_status && ! isset( $decodedIgnoredThemes[ $slug ] ) ) {
2296 continue;
2297 }
2298 }
2299
2300 $esc_note = '';
2301 $strip_note = '';
2302 if ( isset( $trustedThemesNotes[ $slug ] ) ) {
2303 $esc_note = MainWP_Utility::esc_content( $trustedThemesNotes[ $slug ] );
2304 $strip_note = wp_strip_all_tags( $esc_note );
2305 }
2306
2307 ?>
2308 <tr theme-slug="<?php echo esc_attr( rawurlencode( $slug ) ); ?>" theme-name="<?php echo esc_attr( $name ); ?>">
2309 <td class="check-column"><span class="ui checkbox"><input type="checkbox" name="theme[]" value="<?php echo esc_attr( rawurlencode( $slug ) ); ?>"></span></td>
2310 <td><?php echo MainWP_System_Utility::get_theme_icon( $slug ) . '&nbsp;&nbsp;&nbsp;&nbsp;' . esc_html( $name ); //phpcs:ignore -- escaped. ?></td>
2311 <td><?php echo ( 1 === (int) $theme['active'] ) ? esc_html__( 'Active', 'mainwp' ) : esc_html__( 'Inactive', 'mainwp' ); //phpcs:ignore -- escaped. ?></td>
2312 <td><?php echo ( in_array( $slug, $trustedThemes ) ) ? '<span class="ui mini green fluid center aligned label">' . esc_html__( 'Trusted', 'mainwp' ) . '</span>' : '<span class="ui mini red fluid center aligned label">' . esc_html__( 'Not Trusted', 'mainwp' ) . '</span>'; ?></td>
2313 <td><?php echo ( isset( $decodedIgnoredThemes[ $slug ] ) ) ? '<span class="ui mini label">' . esc_html__( 'Ignored', 'mainwp' ) . '</span>' : ''; ?></td>
2314 <td><?php echo ( isset( $decodedIgnoredThemes[ $slug ] ) ) ? '<span data-tooltip="Ignored themes will not be automatically updated." data-inverted=""><i class="info red circle icon"></i></span>' : ''; ?></td>
2315 <td class="collapsing center aligned">
2316 <?php if ( '' === $esc_note ) : ?>
2317 <a href="javascript:void(0)" class="mainwp-edit-theme-note"><i class="sticky note outline icon"></i></a>
2318 <?php else : ?>
2319 <a href="javascript:void(0)" class="mainwp-edit-theme-note" data-tooltip="<?php echo substr( $strip_note, 0, 100 ); //phpcs:ignore -- escaped. ?>" data-position="left center" data-inverted=""><i class="sticky green note icon"></i></a>
2320 <?php endif; ?>
2321 <span style="display: none" class="esc-content-note"><?php echo $esc_note; //phpcs:ignore -- escaped. ?></span>
2322 </td>
2323 </tr>
2324 <?php endforeach; ?>
2325 </tbody>
2326
2327 <tfoot>
2328 <tr>
2329 <th class="no-sort check-column"><span class="ui checkbox"><input id="cb-select-all-bottom" type="checkbox" /></span></th>
2330 <th><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2331 <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
2332 <th><?php esc_html_e( 'Trust Status', 'mainwp' ); ?></th>
2333 <th><?php esc_html_e( 'Ignored Status', 'mainwp' ); ?></th>
2334 <th class="collapsing"></th>
2335 <th><?php esc_html_e( 'Notes', 'mainwp' ); ?></th>
2336 </tr>
2337 </tfoot>
2338 </table>
2339 <?php
2340 /**
2341 * Action: mainwp_themes_after_auto_updates_table
2342 *
2343 * Fires before the Auto Update Themes table.
2344 *
2345 * @since 4.1
2346 */
2347 do_action( 'mainwp_themes_after_auto_updates_table' );
2348
2349 $table_features = array(
2350 'searching' => 'true',
2351 'stateSave' => 'true',
2352 'colReorder' => 'true',
2353 'info' => 'true',
2354 'paging' => 'false',
2355 'ordering' => 'true',
2356 'order' => '[ [ 2, "asc" ] ]',
2357 'responsive' => 'true',
2358 );
2359
2360 /**
2361 * Filter: mainwp_theme_auto_updates_table_fatures
2362 *
2363 * Filters the Theme Auto Updates table features.
2364 *
2365 * @since 4.1
2366 */
2367 $table_features = apply_filters( 'mainwp_theme_auto_updates_table_fatures', $table_features );
2368 ?>
2369 <script type="text/javascript">
2370 var responsive = <?php echo esc_html( $table_features['responsive'] ); ?>;
2371 if( jQuery( window ).width() > 1140 ) {
2372 responsive = false;
2373 }
2374 jQuery( document ).ready( function() {
2375 jQuery( '.mainwp-ui-page .ui.checkbox' ).checkbox();
2376
2377 jQuery( '#mainwp-all-active-themes-table' ).DataTable( {
2378 "searching" : <?php echo esc_html( $table_features['searching'] ); ?>,
2379 "stateSave" : <?php echo esc_html( $table_features['stateSave'] ); ?>,
2380 "colReorder" : <?php echo esc_html( $table_features['colReorder'] ); ?>,
2381 "info" : <?php echo esc_html( $table_features['info'] ); ?>,
2382 "paging" : <?php echo esc_html( $table_features['paging'] ); ?>,
2383 "ordering" : <?php echo esc_html( $table_features['ordering'] ); ?>,
2384 "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
2385 "columnDefs": [ { "orderable": false, "targets": [ 0, 1, 6 ] } ],
2386 "responsive": responsive,
2387 } );
2388 } );
2389 </script>
2390 <?php
2391 }
2392
2393 /**
2394 * Render the Themes Ignored Updates Tab.
2395 *
2396 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
2397 * @uses \MainWP\Dashboard\MainWP_DB::query()
2398 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
2399 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2400 */
2401 public static function render_ignore() {
2402 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user() );
2403 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
2404 $decodedIgnoredThemes = json_decode( $userExtension->ignored_themes, true );
2405 $ignoredThemes = ( is_array( $decodedIgnoredThemes ) && ( 0 < count( $decodedIgnoredThemes ) ) );
2406
2407 $cnt = 0;
2408
2409 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2410 if ( $website->is_ignoreThemeUpdates ) {
2411 continue;
2412 }
2413
2414 $tmpDecodedIgnoredThemes = json_decode( $website->ignored_themes, true );
2415
2416 if ( ! is_array( $tmpDecodedIgnoredThemes ) || 0 === count( $tmpDecodedIgnoredThemes ) ) {
2417 continue;
2418 }
2419
2420 ++$cnt;
2421 }
2422
2423 self::render_header( 'Ignore' );
2424 ?>
2425 <div id="mainwp-ignored-plugins" class="ui segment">
2426 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-ignored-themes-info-message' ) ) : ?>
2427 <div class="ui info message">
2428 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-ignored-themes-info-message"></i>
2429 <?php printf( esc_html__( 'Manage themes you have told your MainWP Dashboard to ignore updates on global or per site level. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/ignore-themes-updates/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?>
2430 </div>
2431 <?php endif; ?>
2432 <?php
2433 /**
2434 * Action: mainwp_themes_before_ignored_updates
2435 *
2436 * Fires on the top of the Ignored Themes Updates page.
2437 *
2438 * @since 4.1
2439 */
2440 do_action( 'mainwp_themes_before_ignored_updates', $ignoredThemes, $websites );
2441 ?>
2442 <h3 class="ui header">
2443 <?php esc_html_e( 'Globally Ignored Themes', 'mainwp' ); ?>
2444 <div class="sub header"><?php esc_html_e( 'These are themes you have told your MainWP Dashboard to ignore updates on global level and not notify you about pending updates.', 'mainwp' ); ?></div>
2445 </h3>
2446 <?php self::render_global_ignored( $ignoredThemes, $decodedIgnoredThemes ); ?>
2447 <div class="ui hidden divider"></div>
2448 <h3 class="ui header">
2449 <?php esc_html_e( 'Per Site Ignored Themes', 'mainwp' ); ?>
2450 <div class="sub header"><?php esc_html_e( 'These are themes you have told your MainWP Dashboard to ignore updates per site level and not notify you about pending updates.', 'mainwp' ); ?></div>
2451 </h3>
2452 <?php self::render_sites_ignored( $cnt, $websites ); ?>
2453 <?php
2454 /**
2455 * Action: mainwp_themes_after_ignored_updates
2456 *
2457 * Fires on the bottom of the Ignored Themes Updates page.
2458 *
2459 * @since 4.1
2460 */
2461 do_action( 'mainwp_themes_after_ignored_updates', $ignoredThemes, $websites );
2462 ?>
2463 </div>
2464 <?php
2465 MainWP_Updates::render_plugin_details_modal();
2466 self::render_footer( 'Ignore' );
2467 }
2468
2469 /**
2470 * Render globally Ignored themes.
2471 *
2472 * @param mixed $ignoredThemes Encoded ignored themes.
2473 * @param mixed $decodedIgnoredThemes Decoded ignored themes.
2474 */
2475 public static function render_global_ignored( $ignoredThemes, $decodedIgnoredThemes ) {
2476 ?>
2477 <table id="mainwp-globally-ignored-themes" class="ui compact selectable table unstackable">
2478 <thead>
2479 <tr>
2480 <th><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2481 <th><?php esc_html_e( 'Theme slug', 'mainwp' ); ?></th>
2482 <th></th>
2483 </tr>
2484 </thead>
2485 <tbody id="globally-ignored-themes-list">
2486 <?php if ( $ignoredThemes ) : ?>
2487 <?php foreach ( $decodedIgnoredThemes as $ignoredTheme => $ignoredThemeName ) : ?>
2488 <tr theme-slug="<?php echo esc_attr( rawurlencode( $ignoredTheme ) ); ?>">
2489 <td><?php echo MainWP_System_Utility::get_theme_icon( $ignoredTheme ) . '&nbsp;&nbsp;&nbsp;&nbsp;' . esc_html( $ignoredThemeName ); //phpcs:ignore -- escaped. ?></td>
2490 <td><?php echo esc_html( $ignoredTheme ); ?></td>
2491 <td class="right aligned">
2492 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2493 <a href="#" class="ui mini button" onClick="return updatesoverview_themes_unignore_globally( '<?php echo esc_js( rawurlencode( $ignoredTheme ) ); ?>' )"><?php esc_html_e( 'Unignore', 'mainwp' ); ?></a>
2494 <?php endif; ?>
2495 </td>
2496 </tr>
2497 <?php endforeach; ?>
2498 <?php endif; ?>
2499 </tbody>
2500 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2501 <?php if ( $ignoredThemes ) : ?>
2502 <tfoot class="full-width">
2503 <tr>
2504 <th colspan="3">
2505 <a class="ui right floated small green labeled icon button" onClick="return updatesoverview_themes_unignore_globally_all();" id="mainwp-unignore-globally-all">
2506 <i class="check icon"></i> <?php esc_html_e( 'Unignore All', 'mainwp' ); ?>
2507 </a>
2508 </th>
2509 </tr>
2510 </tfoot>
2511 <?php endif; ?>
2512 <?php endif; ?>
2513 </table>
2514 <script type="text/javascript">
2515 jQuery( document ).ready( function() {
2516 jQuery( '#mainwp-globally-ignored-themes' ).DataTable( {
2517 searching: false,
2518 paging: false,
2519 info: false,
2520 responsive: true,
2521 "language": {
2522 "emptyTable": "<?php esc_html_e( 'No ignored themes.', 'mainwp' ); ?>"
2523 },
2524 } );
2525 } );
2526 </script>
2527 <?php
2528 }
2529
2530 /**
2531 * Method render_sites_ignored()
2532 *
2533 * Render ignored sites.
2534 *
2535 * @param int $cnt Count of items.
2536 * @param object $websites The websits object.
2537 *
2538 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
2539 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2540 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
2541 */
2542 public static function render_sites_ignored( $cnt, $websites ) {
2543 ?>
2544 <table id="mainwp-per-site-ignored-themes" class="ui compact selectable table unstackable">
2545 <thead>
2546 <tr>
2547 <th><?php esc_html_e( 'Site', 'mainwp' ); ?></th>
2548 <th><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2549 <th><?php esc_html_e( 'Theme slug', 'mainwp' ); ?></th>
2550 <th></th>
2551 </tr>
2552 </thead>
2553 <tbody id="ignored-themes-list">
2554 <?php if ( 0 < $cnt ) : ?>
2555 <?php
2556 MainWP_DB::data_seek( $websites, 0 );
2557
2558 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2559 if ( $website->is_ignoreThemeUpdates ) {
2560 continue;
2561 }
2562 $decodedIgnoredThemes = json_decode( $website->ignored_themes, true );
2563 if ( ! is_array( $decodedIgnoredThemes ) || 0 === count( $decodedIgnoredThemes ) ) {
2564 continue;
2565 }
2566 $first = true;
2567
2568 foreach ( $decodedIgnoredThemes as $ignoredTheme => $ignoredThemeName ) {
2569 ?>
2570 <tr site-id="<?php echo esc_attr( $website->id ); ?>" theme-slug="<?php echo esc_attr( rawurlencode( $ignoredTheme ) ); ?>">
2571 <?php if ( $first ) : ?>
2572 <td><div><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a></div></td>
2573 <?php $first = false; ?>
2574 <?php else : ?>
2575 <td><div style="display:none;"><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a></div></td>
2576 <?php endif; ?>
2577 <td><?php echo MainWP_System_Utility::get_theme_icon( $ignoredTheme ) . '&nbsp;&nbsp;&nbsp;&nbsp;' . esc_html( $ignoredThemeName ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
2578 <td><?php echo esc_html( $ignoredTheme ); ?></td>
2579 <td class="right aligned">
2580 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2581 <a href="#" class="ui mini button" onClick="return updatesoverview_themes_unignore_detail( '<?php echo esc_js( rawurlencode( $ignoredTheme ) ); ?>', <?php echo intval( $website->id ); ?> )"><?php esc_html_e( 'Unignore', 'mainwp' ); ?></a>
2582 <?php endif; ?>
2583 </td>
2584 </tr>
2585 <?php
2586 }
2587 }
2588 MainWP_DB::free_result( $websites );
2589 ?>
2590 <?php endif; ?>
2591 </tbody>
2592 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2593 <?php if ( 0 < $cnt ) : ?>
2594 <tfoot class="full-width">
2595 <tr>
2596 <th colspan="4">
2597 <a class="ui right floated small green labeled icon button" onClick="return updatesoverview_themes_unignore_detail_all();" id="mainwp-unignore-detail-all">
2598 <i class="check icon"></i> <?php esc_html_e( 'Unignore All', 'mainwp' ); ?>
2599 </a>
2600 </th>
2601 </tr>
2602 </tfoot>
2603 <?php endif; ?>
2604 <?php endif; ?>
2605 </table>
2606 <script type="text/javascript">
2607 jQuery( document ).ready( function() {
2608 jQuery( '#mainwp-per-site-ignored-themes' ).DataTable( {
2609 searching: false,
2610 paging: false,
2611 info: false,
2612 responsive: true,
2613 "language": {
2614 "emptyTable": "<?php esc_html_e( 'No ignored themes', 'mainwp' ); ?>"
2615 },
2616 } );
2617 } );
2618 </script>
2619 <?php
2620 }
2621
2622 /**
2623 * Render the Themes Ignored/Abandoned Tab.
2624 *
2625 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
2626 * @uses \MainWP\Dashboard\MainWP_DB::query()
2627 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
2628 * @uses \MainWP\Dashboard\MainWP_DB::get_website_option()
2629 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2630 */
2631 public static function render_ignored_abandoned() {
2632 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user() );
2633 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
2634 $decodedIgnoredThemes = json_decode( $userExtension->dismissed_themes, true );
2635 $ignoredThemes = ( is_array( $decodedIgnoredThemes ) && ( 0 < count( $decodedIgnoredThemes ) ) );
2636 $cnt = 0;
2637 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2638 $tmpDecodedIgnoredThemes = MainWP_DB::instance()->get_website_option( $website, 'themes_outdate_dismissed' );
2639 $tmpDecodedIgnoredThemes = ! empty( $tmpDecodedIgnoredThemes ) ? json_decode( $tmpDecodedIgnoredThemes, true ) : array();
2640
2641 if ( ! is_array( $tmpDecodedIgnoredThemes ) || 0 === count( $tmpDecodedIgnoredThemes ) ) {
2642 continue;
2643 }
2644 ++$cnt;
2645 }
2646
2647 self::render_header( 'IgnoreAbandoned' );
2648 ?>
2649 <div id="mainwp-ignored-abandoned-themes" class="ui segment">
2650 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-ignored-abandoned-themes-info-message' ) ) : ?>
2651 <div class="ui info message">
2652 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-ignored-abandoned-themes-info-message"></i>
2653 <?php printf( esc_html__( 'Manage abandoned themes you have told your MainWP Dashboard to ignore on global or per site level. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/abandoned-themes/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?>
2654 </div>
2655 <?php endif; ?>
2656 <?php
2657 /**
2658 * Action: mainwp_themes_before_ignored_abandoned
2659 *
2660 * Fires on the top of the Ignored Themes Abandoned page.
2661 *
2662 * @since 4.1
2663 */
2664 do_action( 'mainwp_themes_before_ignored_abandoned', $ignoredThemes, $websites );
2665 ?>
2666 <h3 class="ui header">
2667 <?php esc_html_e( 'Globally Ignored Abandoned Themes', 'mainwp' ); ?>
2668 <div class="sub header"><?php esc_html_e( 'These are themes you have told your MainWP Dashboard to ignore on global level even though they have passed your Abandoned Themes Tolerance date', 'mainwp' ); ?></div>
2669 </h3>
2670 <?php self::render_global_ignored_abandoned( $ignoredThemes, $decodedIgnoredThemes ); ?>
2671 <div class="ui hidden divider"></div>
2672 <h3 class="ui header">
2673 <?php esc_html_e( 'Per Site Ignored Abandoned Themes', 'mainwp' ); ?>
2674 <div class="sub header"><?php esc_html_e( 'These are themes you have told your MainWP Dashboard to ignore per site level even though they have passed your Abandoned Theme Tolerance date', 'mainwp' ); ?></div>
2675 </h3>
2676 <?php self::render_sites_ignored_abandoned( $cnt, $websites ); ?>
2677 <?php
2678 /**
2679 * Action: mainwp_themes_after_ignored_abandoned
2680 *
2681 * Fires on the bottom of the Ignored Themes Abandoned page.
2682 *
2683 * @since 4.1
2684 */
2685 do_action( 'mainwp_themes_after_ignored_abandoned', $ignoredThemes, $websites );
2686 ?>
2687 </div>
2688 <?php
2689 self::render_footer( 'IgnoreAbandoned' );
2690 }
2691
2692 /**
2693 * Render the global ignored themes list.
2694 *
2695 * @param mixed $ignoredThemes Encoded ignored themes list.
2696 * @param mixed $decodedIgnoredThemes Decoded ignored themes list.
2697 */
2698 public static function render_global_ignored_abandoned( $ignoredThemes, $decodedIgnoredThemes ) {
2699 ?>
2700 <table id="mainwp-globally-ignored-abandoned-themes" class="ui compact selectable table unstackable">
2701 <thead>
2702 <tr>
2703 <th><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2704 <th><?php esc_html_e( 'Theme slug', 'mainwp' ); ?></th>
2705 <th></th>
2706 </tr>
2707 </thead>
2708 <tbody id="globally-ignored-themes-list">
2709 <?php if ( $ignoredThemes ) : ?>
2710 <?php foreach ( $decodedIgnoredThemes as $ignoredTheme => $ignoredThemeName ) : ?>
2711 <tr theme-slug="<?php echo esc_attr( rawurlencode( $ignoredTheme ) ); ?>">
2712 <td><?php echo esc_html( $ignoredThemeName ); ?></td>
2713 <td><?php echo esc_html( $ignoredTheme ); ?></td>
2714 <td class="right aligned">
2715 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2716 <a href="#" class="ui mini button" onClick="return updatesoverview_themes_abandoned_unignore_globally( '<?php echo esc_js( rawurlencode( $ignoredTheme ) ); ?>' )"><?php esc_html_e( 'Unignore', 'mainwp' ); ?></a>
2717 <?php endif; ?>
2718 </td>
2719 </tr>
2720 <?php endforeach; ?>
2721 <?php endif; ?>
2722 </tbody>
2723 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2724 <?php if ( $ignoredThemes ) : ?>
2725 <tfoot class="full-width">
2726 <tr>
2727 <th colspan="3">
2728 <a class="ui right floated small green labeled icon button" onClick="return updatesoverview_themes_abandoned_unignore_globally_all();" id="mainwp-unignore-globally-all">
2729 <i class="check icon"></i> <?php esc_html_e( 'Unignore All', 'mainwp' ); ?>
2730 </a>
2731 </th>
2732 </tr>
2733 </tfoot>
2734 <?php endif; ?>
2735 <?php endif; ?>
2736 </table>
2737 <script type="text/javascript">
2738 jQuery( document ).ready( function() {
2739 jQuery( '#mainwp-globally-ignored-abandoned-themes' ).DataTable( {
2740 "responsive": true,
2741 "searching": false,
2742 "paging": false,
2743 "info": false,
2744 "language": {
2745 "emptyTable": "<?php esc_html_e( 'No ignored abandoned themes.', 'mainwp' ); ?>"
2746 },
2747 } );
2748 } );
2749 </script>
2750 <?php
2751 }
2752
2753 /**
2754 * Method render_sites_ignored_abandoned()
2755 *
2756 * Render ignored items per site list.
2757 *
2758 * @param int $cnt Count of items.
2759 * @param object $websites The websits object.
2760 *
2761 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
2762 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
2763 * @uses \MainWP\Dashboard\MainWP_DB::get_website_option()
2764 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2765 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
2766 */
2767 public static function render_sites_ignored_abandoned( $cnt, $websites ) {
2768 ?>
2769 <table id="mainwp-per-site-ignored-abandoned-themes" class="ui compact selectable table unstackable">
2770 <thead>
2771 <tr>
2772 <th><?php esc_html_e( 'Site', 'mainwp' ); ?></th>
2773 <th><?php esc_html_e( 'Theme', 'mainwp' ); ?></th>
2774 <th><?php esc_html_e( 'Theme slug', 'mainwp' ); ?></th>
2775 <th></th>
2776 </tr>
2777 </thead>
2778 <tbody id="ignored-abandoned-themes-list">
2779 <?php if ( 0 < $cnt ) : ?>
2780 <?php
2781 MainWP_DB::data_seek( $websites, 0 );
2782 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2783 $decodedIgnoredThemes = MainWP_DB::instance()->get_website_option( $website, 'themes_outdate_dismissed' );
2784 $decodedIgnoredThemes = ! empty( $decodedIgnoredThemes ) ? json_decode( $decodedIgnoredThemes, true ) : array();
2785
2786 if ( ! is_array( $decodedIgnoredThemes ) || 0 === count( $decodedIgnoredThemes ) ) {
2787 continue;
2788 }
2789
2790 $first = true;
2791 foreach ( $decodedIgnoredThemes as $ignoredTheme => $ignoredThemeName ) {
2792 ?>
2793 <tr site-id="<?php echo esc_attr( $website->id ); ?>" theme-slug="<?php echo esc_attr( rawurlencode( $ignoredTheme ) ); ?>">
2794 <?php if ( $first ) : ?>
2795 <td><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a></td>
2796 <?php $first = false; ?>
2797 <?php else : ?>
2798 <td><div style="display:none;"><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a></div></td>
2799 <?php endif; ?>
2800 <td><?php echo esc_html( $ignoredThemeName ); ?></td>
2801 <td><?php echo esc_html( $ignoredTheme ); ?></td>
2802 <td class="right aligned">
2803 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2804 <a href="#" class="ui mini button" onClick="return updatesoverview_themes_unignore_abandoned_detail( '<?php echo esc_js( rawurlencode( $ignoredTheme ) ); ?>', <?php echo intval( $website->id ); ?> )"><?php esc_html_e( 'Unignore', 'mainwp' ); ?></a>
2805 <?php endif; ?>
2806 </td>
2807 </tr>
2808 <?php
2809 }
2810 }
2811 MainWP_DB::free_result( $websites );
2812 ?>
2813 <?php endif; ?>
2814 </tbody>
2815 <?php if ( mainwp_current_user_have_right( 'dashboard', 'ignore_unignore_updates' ) ) : ?>
2816 <?php if ( 0 < $cnt ) : ?>
2817 <tfoot class="full-width">
2818 <tr>
2819 <th colspan="4">
2820 <a class="ui right floated small green labeled icon button" onClick="return updatesoverview_themes_unignore_abandoned_detail_all();" id="mainwp-unignore-detail-all">
2821 <i class="check icon"></i> <?php esc_html_e( 'Unignore All', 'mainwp' ); ?>
2822 </a>
2823 </th>
2824 </tr>
2825 </tfoot>
2826 <?php endif; ?>
2827 <?php endif; ?>
2828 </table>
2829 <script type="text/javascript">
2830 jQuery( document ).ready( function() {
2831 jQuery( '#mainwp-per-site-ignored-abandoned-themes' ).DataTable( {
2832 "responsive": true,
2833 "searching": false,
2834 "paging": false,
2835 "info": false,
2836 "language": {
2837 "emptyTable": "<?php esc_html_e( 'No ignored abandoned themes.', 'mainwp' ); ?>"
2838 },
2839 } );
2840 } );
2841 </script>
2842 <?php
2843 }
2844
2845
2846 /**
2847 * Hooks the section help content to the Help Sidebar element.
2848 */
2849 public static function mainwp_help_content() {
2850 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2851 if ( isset( $_GET['page'] ) && ( 'ThemesManage' === $_GET['page'] || 'ThemesInstall' === $_GET['page'] || 'ThemesAutoUpdate' === $_GET['page'] || 'ThemesIgnore' === $_GET['page'] || 'ThemesIgnoredAbandoned' === $_GET['page'] ) ) {
2852 ?>
2853 <p><?php esc_html_e( 'If you need help with managing themes, please review following help documents', 'mainwp' ); ?></p>
2854 <div class="ui relaxed bulleted list">
2855 <div class="item"><a href="https://kb.mainwp.com/docs/managing-themes-with-mainwp/" target="_blank">Managing Themes with MainWP</a> <i class="external alternate icon"></i></div>
2856 <div class="item"><a href="https://kb.mainwp.com/docs/install-themes/" target="_blank">Install Themes</a> <i class="external alternate icon"></i></div>
2857 <div class="item"><a href="https://kb.mainwp.com/docs/activate-themes/" target="_blank">Activate Themes</a> <i class="external alternate icon"></i></div>
2858 <div class="item"><a href="https://kb.mainwp.com/docs/delete-themes/" target="_blank">Delete Themes</a> <i class="external alternate icon"></i></div>
2859 <div class="item"><a href="https://kb.mainwp.com/docs/abandoned-themes/" target="_blank">Abandoned Themes</a> <i class="external alternate icon"></i></div>
2860 <div class="item"><a href="https://kb.mainwp.com/docs/update-themes/" target="_blank">Update Themes</a> <i class="external alternate icon"></i></div>
2861 <div class="item"><a href="https://kb.mainwp.com/docs/themes-auto-updates/" target="_blank">Themes Auto Updates</a> <i class="external alternate icon"></i></div>
2862 <div class="item"><a href="https://kb.mainwp.com/docs/ignore-theme-updates/" target="_blank">Ignore Theme Updates</a> <i class="external alternate icon"></i></div>
2863 <?php
2864 /**
2865 * Action: mainwp_themes_help_item
2866 *
2867 * Fires at the bottom of the help articles list in the Help sidebar on the Themes page.
2868 *
2869 * Suggested HTML markup:
2870 *
2871 * <div class="item"><a href="Your custom URL">Your custom text</a></div>
2872 *
2873 * @since 4.1
2874 */
2875 do_action( 'mainwp_themes_help_item' );
2876 ?>
2877 </div>
2878 <?php
2879 }
2880 // phpcs:enable
2881 }
2882 }
2883