PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 4.0.0
WP 2FA – Two-factor authentication for WordPress v4.0.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / Settings / templates / partials / premium-locked-panel.php
wp-2fa / includes / classes / Admin / Settings / templates / partials Last commit date
index.php 5 days ago premium-locked-panel.php 5 days ago
premium-locked-panel.php
128 lines
1 <?php
2 /**
3 * Reusable Premium Locked Panel Component.
4 *
5 * Renders a premium upsell panel with a banner, and a collapsible list of
6 * locked items (roles, features, etc.) showing only the first 3 with a
7 * "+ N more" toggle link.
8 *
9 * Expected variables:
10 * $panel_banner_title (string) - Banner title text.
11 * $panel_banner_desc (string) - Banner description text.
12 * $panel_banner_cta (string) - CTA button label.
13 * $panel_banner_url (string) - CTA button URL.
14 * $panel_items (array) - Array of items to display. Each item:
15 * ['title' => string, 'context' => string (optional premium dialog context key)]
16 * $panel_visible_count (int) - Number of items to show before collapsing (default 3).
17 * $panel_id (string) - Unique panel ID for JS targeting (optional).
18 *
19 * @package wp-2fa
20 * @since 5.1.0
21 */
22
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit;
25 }
26
27 $panel_visible_count = isset( $panel_visible_count ) ? (int) $panel_visible_count : 3;
28 $panel_id = isset( $panel_id ) ? $panel_id : 'wp2fa-locked-panel-' . wp_unique_id();
29 $total_items = count( $panel_items );
30 $hidden_count = max( 0, $total_items - $panel_visible_count );
31
32 // Lock icon SVG (same as used in premium badge).
33 $lock_icon_svg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">'
34 . '<path d="M4.66699 6.41667V4.08333C4.66699 3.46449 4.91282 2.871 5.35041 2.43342C5.78799 1.99583 6.38149 1.75 7.00033 1.75C7.61916 1.75 8.21266 1.99583 8.65024 2.43342C9.08783 2.871 9.33366 3.46449 9.33366 4.08333V6.41667M2.91699 7.58333C2.91699 7.27391 3.03991 6.97717 3.2587 6.75838C3.47749 6.53958 3.77424 6.41667 4.08366 6.41667H9.91699C10.2264 6.41667 10.5232 6.53958 10.742 6.75838C10.9607 6.97717 11.0837 7.27391 11.0837 7.58333V11.0833C11.0837 11.3928 10.9607 11.6895 10.742 11.9083C10.5232 12.1271 10.2264 12.25 9.91699 12.25H4.08366C3.77424 12.25 3.47749 12.1271 3.2587 11.9083C3.03991 11.6895 2.91699 11.3928 2.91699 11.0833V7.58333ZM6.41699 9.33333C6.41699 9.48804 6.47845 9.63642 6.58785 9.74581C6.69724 9.85521 6.84562 9.91667 7.00033 9.91667C7.15504 9.91667 7.30341 9.85521 7.4128 9.74581C7.5222 9.63642 7.58366 9.48804 7.58366 9.33333C7.58366 9.17862 7.5222 9.03025 7.4128 8.92085C7.30341 8.81146 7.15504 8.75 7.00033 8.75C6.84562 8.75 6.69724 8.81146 6.58785 8.92085C6.47845 9.03025 6.41699 9.17862 6.41699 9.33333Z" stroke="#646970" stroke-width="1.3125" stroke-linecap="round" stroke-linejoin="round"/>'
35 . '</svg>';
36
37 ?>
38 <div class="wp2fa-premium-locked-panel" id="<?php echo esc_attr( $panel_id ); ?>">
39 <div class="wp2fa-premium-locked-panel__card">
40 <?php // --- Banner --- ?>
41 <div class="wp2fa-premium-locked-panel__banner" role="region" aria-label="<?php echo esc_attr( $panel_banner_title ); ?>">
42 <div class="wp2fa-premium-locked-panel__banner-content">
43 <span class="wp2fa-premium-locked-panel__banner-icon" aria-hidden="true">
44 <svg xmlns="http://www.w3.org/2000/svg" width="33" height="49" viewBox="0 0 33 49" fill="none">
45 <path d="M10.7607 16.2846L18.7944 8.17949L26.9017 0H13.414H0V8.17949V16.2846L2.65332 13.6077L5.38035 10.8564L8.03367 13.6077L10.7607 16.2846Z" fill="#99FFFF"/>
46 <path d="M32.2094 48.9278V37.997V27.1406L21.5224 37.997L10.7617 48.7791L21.5224 48.8534L32.2094 48.9278Z" fill="#3E6BFF"/>
47 <path d="M10.7607 27.1406L8.03367 24.3893L5.38035 21.7124L2.65332 18.9611L0 16.2841V27.1406V37.997L2.65332 35.2457L5.38035 32.5688L8.03367 35.2457L10.7607 37.997L18.7944 29.8175L26.9017 21.7124L29.555 24.3893L32.2084 27.1406V16.2841V5.42773L21.5214 16.2841L10.7607 27.1406Z" fill="#40D3F0"/>
48 </svg>
49 </span>
50 <div class="wp2fa-premium-locked-panel__banner-text">
51 <h3 class="wp2fa-premium-locked-panel__banner-title"><?php echo esc_html( $panel_banner_title ); ?></h3>
52 <?php if ( ! empty( $panel_banner_desc ) ) : ?>
53 <p class="wp2fa-premium-locked-panel__banner-desc"><?php echo esc_html( $panel_banner_desc ); ?></p>
54 <?php endif; ?>
55 </div>
56 <?php
57 $badge_context_attr = ! empty( $panel_banner_badge_context ) ? ' data-wp2fa-premium-context="' . esc_attr( $panel_banner_badge_context ) . '"' : '';
58 ?>
59 <span class="wp2fa-premium-locked-panel__banner-badge wp2fa-premium-badge" role="button" tabindex="0" data-wp2fa-premium-dialog-trigger="1"<?php echo $badge_context_attr; ?> aria-label="<?php echo esc_attr__( 'Learn more about Premium features', 'wp-2fa' ); ?>">
60 <?php echo $lock_icon_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
61 <?php echo esc_html__( 'PREMIUM', 'wp-2fa' ); ?>
62 </span>
63 </div>
64 </div>
65
66 <?php // --- Items list --- ?>
67 <ul class="wp2fa-premium-locked-panel__list">
68 <?php foreach ( $panel_items as $index => $item ) :
69 $is_hidden = $index >= $panel_visible_count;
70 $context_attr = ! empty( $item['context'] ) ? ' data-wp2fa-premium-context="' . esc_attr( $item['context'] ) . '"' : '';
71 $lock_is_clickable = empty( $panel_lock_icons_disabled );
72 ?>
73 <li class="wp2fa-premium-locked-panel__item<?php echo $is_hidden ? ' wp2fa-premium-locked-panel__item--hidden' : ''; ?>">
74 <?php if ( $lock_is_clickable ) : ?>
75 <span class="wp2fa-premium-locked-panel__item-lock wp2fa-premium-badge" role="button" tabindex="0" data-wp2fa-premium-dialog-trigger="1"<?php echo $context_attr; ?> aria-label="<?php echo esc_attr__( 'Learn more about Premium features', 'wp-2fa' ); ?>">
76 <?php echo $lock_icon_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
77 </span>
78 <?php else : ?>
79 <span class="wp2fa-premium-locked-panel__item-lock" aria-hidden="true">
80 <?php echo $lock_icon_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
81 </span>
82 <?php endif; ?>
83 <span class="wp2fa-premium-locked-panel__item-title"><?php echo esc_html( $item['title'] ); ?></span>
84 <span class="wp2fa-premium-locked-panel__item-chevron" aria-hidden="true"></span>
85 </li>
86 <?php endforeach; ?>
87 </ul>
88
89 <?php if ( $hidden_count > 0 ) : ?>
90 <button type="button" class="wp2fa-premium-locked-panel__toggle" aria-expanded="false" data-panel-id="<?php echo esc_attr( $panel_id ); ?>">
91 <?php
92 printf(
93 /* translators: %d: number of additional hidden roles/items */
94 esc_html__( '+ %d more', 'wp-2fa' ),
95 $hidden_count
96 );
97 ?>
98 </button>
99 <?php endif; ?>
100 </div>
101 </div>
102 <?php if ( $hidden_count > 0 ) : ?>
103 <script>
104 (function() {
105 'use strict';
106 var panelId = <?php echo wp_json_encode( $panel_id ); ?>;
107 var panel = document.getElementById(panelId);
108 if (!panel) return;
109 var toggle = panel.querySelector('.wp2fa-premium-locked-panel__toggle');
110 if (!toggle) return;
111
112 toggle.addEventListener('click', function() {
113 var expanded = toggle.getAttribute('aria-expanded') === 'true';
114 var hiddenItems = panel.querySelectorAll('.wp2fa-premium-locked-panel__item--hidden');
115 for (var i = 0; i < hiddenItems.length; i++) {
116 if (expanded) {
117 hiddenItems[i].classList.remove('wp2fa-premium-locked-panel__item--visible');
118 } else {
119 hiddenItems[i].classList.add('wp2fa-premium-locked-panel__item--visible');
120 }
121 }
122 toggle.setAttribute('aria-expanded', expanded ? 'false' : 'true');
123 toggle.style.display = expanded ? '' : 'none';
124 });
125 })();
126 </script>
127 <?php endif; ?>
128