PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.0.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.0.2
6.2.3 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 All 156 releases
mainwp / pages / page-mainwp-themes.php

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

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