PluginProbe
Passster – Password Protect Pages and Content / 4.3.16
Passster – Password Protect Pages and Content v4.3.16
4.3.16 4.3.15 4.3.14 4.3.12 4.3.13 4.3.11 4.3.10 4.3.9 4.3.8 4.3.7 4.3.6 4.3.5 trunk 3.5.4 3.5.5.2 3.5.5.8 3.5.5.9 4.0 4.1.4 4.2.10 4.2.11 4.2.12 4.2.13 4.2.14 4.2.15 All 48 releases
← All changes | build/blocks/protected-content/render.php +263 -263 4.3.94.3.16 View file →
@@ -1,263 +1,263 @@
1 -<?php
2 -/**
3 - * Server-side rendering for the Protected Content block.
4 - *
5 - * @package Passster
6 - *
7 - * @var array $attributes Block attributes.
8 - * @var string $content Block content (inner blocks).
9 - * @var WP_Block $block Block instance.
10 - */
11 -
12 -defined( 'ABSPATH' ) || exit;
13 -
14 -// Early exit if classes not loaded yet (edge case).
15 -if ( ! class_exists( 'passster\PS_Conditional' ) || ! class_exists( 'passster\PS_Form' ) ) {
16 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
17 - return;
18 -}
19 -
20 -// Ensure we have a valid block ID.
21 -if ( empty( $attributes['blockId'] ) ) {
22 - $attributes['blockId'] = 'ps-' . wp_generate_password( 8, false );
23 -}
24 -
25 -// Find the synced Protected Area by block ID.
26 -$synced_area_id = 0;
27 -$synced_areas = get_posts( array(
28 - 'post_type' => 'protected_areas',
29 - 'posts_per_page' => 1,
30 - 'fields' => 'ids',
31 - 'meta_query' => array(
32 - array(
33 - 'key' => '_passster_block_id',
34 - 'value' => $attributes['blockId'],
35 - ),
36 - ),
37 -) );
38 -if ( ! empty( $synced_areas ) ) {
39 - $synced_area_id = $synced_areas[0];
40 -}
41 -
42 -use passster\PS_Conditional;
43 -use passster\PS_Form;
44 -
45 -// Get block attributes.
46 -$block_id = ! empty( $attributes['blockId'] ) ? sanitize_text_field( $attributes['blockId'] ) : '';
47 -$protection_type = ! empty( $attributes['protectionType'] ) ? sanitize_text_field( $attributes['protectionType'] ) : 'password';
48 -$password = ! empty( $attributes['password'] ) ? $attributes['password'] : '';
49 -$passwords = ! empty( $attributes['passwords'] ) ? $attributes['passwords'] : '';
50 -$password_list = ! empty( $attributes['passwordList'] ) ? absint( $attributes['passwordList'] ) : 0;
51 -
52 -// User Restriction attributes.
53 -$user_restriction = ! empty( $attributes['userRestriction'] );
54 -$user_restriction_type = ! empty( $attributes['userRestrictionType'] ) ? sanitize_text_field( $attributes['userRestrictionType'] ) : 'username';
55 -$user_restriction_value = ! empty( $attributes['userRestrictionValue'] ) ? sanitize_text_field( $attributes['userRestrictionValue'] ) : '';
56 -
57 -// Override Defaults attributes.
58 -$overwrite_defaults = ! empty( $attributes['overwriteDefaults'] );
59 -$headline = ! empty( $attributes['headline'] ) ? sanitize_text_field( $attributes['headline'] ) : '';
60 -$instruction = ! empty( $attributes['instruction'] ) ? wp_kses_post( $attributes['instruction'] ) : '';
61 -$placeholder = ! empty( $attributes['placeholder'] ) ? sanitize_text_field( $attributes['placeholder'] ) : '';
62 -$button_label = ! empty( $attributes['buttonLabel'] ) ? sanitize_text_field( $attributes['buttonLabel'] ) : '';
63 -$form_id = ! empty( $attributes['formId'] ) ? sanitize_text_field( $attributes['formId'] ) : '';
64 -
65 -// Advanced Options attributes.
66 -$advanced_options = ! empty( $attributes['advancedOptions'] );
67 -$redirect_url = ! empty( $attributes['redirectUrl'] ) ? esc_url( $attributes['redirectUrl'] ) : '';
68 -$hide_form = ! empty( $attributes['hideForm'] );
69 -
70 -// Schedule attributes (PRO only).
71 -$schedule_enabled = ! empty( $attributes['scheduleEnabled'] );
72 -$schedule_start = ! empty( $attributes['scheduleStart'] ) ? $attributes['scheduleStart'] : '';
73 -$schedule_end = ! empty( $attributes['scheduleEnd'] ) ? $attributes['scheduleEnd'] : '';
74 -
75 -// Check schedule - if outside the scheduled period, show content without protection.
76 -if ( $schedule_enabled && \passster_fs()->is_plan_or_trial__premium_only( 'pro' ) ) {
77 - $now = current_time( 'timestamp' );
78 - $is_within_schedule = true;
79 -
80 - if ( ! empty( $schedule_start ) ) {
81 - $start_time = strtotime( $schedule_start );
82 - if ( $now < $start_time ) {
83 - $is_within_schedule = false;
84 - }
85 - }
86 -
87 - if ( ! empty( $schedule_end ) ) {
88 - $end_time = strtotime( $schedule_end );
89 - if ( $now > $end_time ) {
90 - $is_within_schedule = false;
91 - }
92 - }
93 -
94 - // If outside schedule, show content without protection.
95 - if ( ! $is_within_schedule ) {
96 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
97 - return;
98 - }
99 -}
100 -
101 -// If no protection is set, just render the content.
102 -if ( 'password' === $protection_type && empty( $password ) ) {
103 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
104 - return;
105 -}
106 -
107 -if ( 'passwords' === $protection_type && empty( $passwords ) ) {
108 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
109 - return;
110 -}
111 -
112 -if ( 'password_list' === $protection_type && empty( $password_list ) ) {
113 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
114 - return;
115 -}
116 -
117 -// Build attributes array for validation.
118 -$atts = array();
119 -
120 -switch ( $protection_type ) {
121 - case 'password':
122 - $atts['password'] = $password;
123 - break;
124 - case 'passwords':
125 - $atts['passwords'] = $passwords;
126 - break;
127 - case 'password_list':
128 - $atts['password_list'] = $password_list;
129 - break;
130 -}
131 -
132 -// Add user restriction to validation attributes if enabled.
133 -if ( $user_restriction && ! empty( $user_restriction_value ) && 'no-role' !== $user_restriction_value ) {
134 - if ( 'user-role' === $user_restriction_type ) {
135 - $atts['role'] = $user_restriction_value;
136 - } else {
137 - $atts['user'] = $user_restriction_value;
138 - }
139 -}
140 -
141 -// Check if already unlocked.
142 -$is_unlocked = false;
143 -if ( class_exists( PS_Conditional::class ) ) {
144 - $is_unlocked = PS_Conditional::is_valid( $atts );
145 -}
146 -
147 -// If unlocked, show content.
148 -if ( $is_unlocked ) {
149 - echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
150 - return;
151 -}
152 -
153 -if ( $advanced_options && $hide_form ) {
154 - return;
155 -}
156 -
157 -// Get global options for form defaults.
158 -$options = get_option( 'passster', array() );
159 -
160 -// Build the protection form using global settings.
161 -$form = PS_Form::get_password_form();
162 -
163 -// Form ID - use custom ID if set, otherwise block ID.
164 -$final_form_id = ! empty( $form_id ) ? $form_id : 'ps-block-' . $block_id;
165 -$form = str_replace( '[PASSSTER_ID]', esc_attr( $final_form_id ), $form );
166 -
167 -// Hide form placeholder.
168 -$form = str_replace( '[PASSSTER_HIDE]', '', $form );
169 -
170 -// Redirect URL.
171 -if ( $advanced_options && ! empty( $redirect_url ) ) {
172 - $form = str_replace( '[PASSSTER_REDIRECT]', esc_url( $redirect_url ), $form );
173 -} else {
174 - $form = str_replace( '[PASSSTER_REDIRECT]', '', $form );
175 -}
176 -
177 -// Label.
178 -$form = str_replace( '[PASSSTER_LABEL]', esc_html__( 'Enter your password', 'content-protector' ), $form );
179 -
180 -// Headline tag.
181 -$allowed_headline_tags = array( 'span', 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );
182 -$headline_tag = isset( $options['headline_tag'] ) && in_array( $options['headline_tag'], $allowed_headline_tags, true ) ? $options['headline_tag'] : 'span';
183 -$form = str_replace( '[PASSSTER_HEADLINE_TAG]', $headline_tag, $form );
184 -
185 -// Headline - use override if enabled and set, otherwise global.
186 -if ( ! empty( $options['hide_headline'] ) ) {
187 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', '', $form );
188 -} elseif ( $overwrite_defaults && ! empty( $headline ) ) {
189 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $headline ), $form );
190 -} else {
191 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $options['headline'] ?? '' ), $form );
192 -}
193 -
194 -// Instruction - use override if enabled and set, otherwise global.
195 -if ( $overwrite_defaults && ! empty( $instruction ) ) {
196 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $instruction ), $form );
197 -} else {
198 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $options['instruction'] ?? '' ), $form );
199 -}
200 -
201 -// Placeholder - use override if enabled and set, otherwise global.
202 -if ( $overwrite_defaults && ! empty( $placeholder ) ) {
203 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $placeholder ), $form );
204 -} else {
205 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $options['placeholder'] ?? '' ), $form );
206 -}
207 -
208 -// Button label - use override if enabled and set, otherwise global.
209 -if ( $overwrite_defaults && ! empty( $button_label ) ) {
210 - $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $button_label ), $form );
211 -} else {
212 - $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $options['button_label'] ?? '' ), $form );
213 -}
214 -
215 -// Protection type placeholder.
216 -$form = str_replace( '[PASSSTER_TYPE]', esc_attr( $protection_type ), $form );
217 -
218 -// Protection mode - 'block' for Content Lock blocks (REST API validates from block attributes).
219 -$form = str_replace( '[PASSSTER_PROTECTION]', 'block', $form );
220 -
221 -// Password list placeholders.
222 -$form = str_replace( '[PASSSTER_LIST]', esc_attr( $password_list ), $form );
223 -$form = str_replace( '[PASSSTER_LISTS]', '', $form );
224 -
225 -// Area placeholder (set to 0 for blocks - we use block_id instead).
226 -$form = str_replace( '[PASSSTER_AREA]', '0', $form );
227 -
228 -// ACF placeholder (not used in blocks).
229 -$form = str_replace( '[PASSSTER_ACF]', '', $form );
230 -
231 -// Wrapper classes.
232 -$wrapper_classes = array( 'passster-protected-content', 'wp-block-passster-protected-content' );
233 -if ( ! empty( $attributes['align'] ) ) {
234 - $wrapper_classes[] = 'align' . $attributes['align'];
235 -}
236 -if ( ! empty( $attributes['className'] ) ) {
237 - $wrapper_classes[] = $attributes['className'];
238 -}
239 -
240 -// Data attributes for JS handling.
241 -$data_attrs = array(
242 - 'block-id' => $block_id,
243 - 'protection-type' => $protection_type,
244 - 'post-id' => get_the_ID(),
245 -);
246 -
247 -if ( $advanced_options && ! empty( $redirect_url ) ) {
248 - $data_attrs['redirect'] = $redirect_url;
249 -}
250 -
251 -// Output.
252 -?>
253 -<div
254 - class="<?php echo esc_attr( implode( ' ', $wrapper_classes ) ); ?>"
255 - <?php foreach ( $data_attrs as $key => $value ) : ?>
256 - data-<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $value ); ?>"
257 - <?php endforeach; ?>
258 ->
259 - <div class="passster-protected-content__form">
260 - <?php echo $form; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
261 - </div>
262 -</div>
263 -<?php
1 +<?php
2 +/**
3 + * Server-side rendering for the Protected Content block.
4 + *
5 + * @package Passster
6 + *
7 + * @var array $attributes Block attributes.
8 + * @var string $content Block content (inner blocks).
9 + * @var WP_Block $block Block instance.
10 + */
11 +
12 +defined( 'ABSPATH' ) || exit;
13 +
14 +// Early exit if classes not loaded yet (edge case).
15 +if ( ! class_exists( 'passster\PS_Conditional' ) || ! class_exists( 'passster\PS_Form' ) ) {
16 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
17 + return;
18 +}
19 +
20 +// Ensure we have a valid block ID.
21 +if ( empty( $attributes['blockId'] ) ) {
22 + $attributes['blockId'] = 'ps-' . wp_generate_password( 8, false );
23 +}
24 +
25 +// Find the synced Protected Area by block ID.
26 +$synced_area_id = 0;
27 +$synced_areas = get_posts( array(
28 + 'post_type' => 'protected_areas',
29 + 'posts_per_page' => 1,
30 + 'fields' => 'ids',
31 + 'meta_query' => array(
32 + array(
33 + 'key' => '_passster_block_id',
34 + 'value' => $attributes['blockId'],
35 + ),
36 + ),
37 +) );
38 +if ( ! empty( $synced_areas ) ) {
39 + $synced_area_id = $synced_areas[0];
40 +}
41 +
42 +use passster\PS_Conditional;
43 +use passster\PS_Form;
44 +
45 +// Get block attributes.
46 +$block_id = ! empty( $attributes['blockId'] ) ? sanitize_text_field( $attributes['blockId'] ) : '';
47 +$protection_type = ! empty( $attributes['protectionType'] ) ? sanitize_text_field( $attributes['protectionType'] ) : 'password';
48 +$password = ! empty( $attributes['password'] ) ? $attributes['password'] : '';
49 +$passwords = ! empty( $attributes['passwords'] ) ? $attributes['passwords'] : '';
50 +$password_list = ! empty( $attributes['passwordList'] ) ? absint( $attributes['passwordList'] ) : 0;
51 +
52 +// User Restriction attributes.
53 +$user_restriction = ! empty( $attributes['userRestriction'] );
54 +$user_restriction_type = ! empty( $attributes['userRestrictionType'] ) ? sanitize_text_field( $attributes['userRestrictionType'] ) : 'username';
55 +$user_restriction_value = ! empty( $attributes['userRestrictionValue'] ) ? sanitize_text_field( $attributes['userRestrictionValue'] ) : '';
56 +
57 +// Override Defaults attributes.
58 +$overwrite_defaults = ! empty( $attributes['overwriteDefaults'] );
59 +$headline = ! empty( $attributes['headline'] ) ? sanitize_text_field( $attributes['headline'] ) : '';
60 +$instruction = ! empty( $attributes['instruction'] ) ? wp_kses_post( $attributes['instruction'] ) : '';
61 +$placeholder = ! empty( $attributes['placeholder'] ) ? sanitize_text_field( $attributes['placeholder'] ) : '';
62 +$button_label = ! empty( $attributes['buttonLabel'] ) ? sanitize_text_field( $attributes['buttonLabel'] ) : '';
63 +$form_id = ! empty( $attributes['formId'] ) ? sanitize_text_field( $attributes['formId'] ) : '';
64 +
65 +// Advanced Options attributes.
66 +$advanced_options = ! empty( $attributes['advancedOptions'] );
67 +$redirect_url = ! empty( $attributes['redirectUrl'] ) ? esc_url( $attributes['redirectUrl'] ) : '';
68 +$hide_form = ! empty( $attributes['hideForm'] );
69 +
70 +// Schedule attributes (PRO only).
71 +$schedule_enabled = ! empty( $attributes['scheduleEnabled'] );
72 +$schedule_start = ! empty( $attributes['scheduleStart'] ) ? $attributes['scheduleStart'] : '';
73 +$schedule_end = ! empty( $attributes['scheduleEnd'] ) ? $attributes['scheduleEnd'] : '';
74 +
75 +// Check schedule - if outside the scheduled period, show content without protection.
76 +if ( $schedule_enabled && \passster_fs()->is_plan_or_trial__premium_only( 'pro' ) ) {
77 + $now = current_time( 'timestamp' );
78 + $is_within_schedule = true;
79 +
80 + if ( ! empty( $schedule_start ) ) {
81 + $start_time = strtotime( $schedule_start );
82 + if ( $now < $start_time ) {
83 + $is_within_schedule = false;
84 + }
85 + }
86 +
87 + if ( ! empty( $schedule_end ) ) {
88 + $end_time = strtotime( $schedule_end );
89 + if ( $now > $end_time ) {
90 + $is_within_schedule = false;
91 + }
92 + }
93 +
94 + // If outside schedule, show content without protection.
95 + if ( ! $is_within_schedule ) {
96 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
97 + return;
98 + }
99 +}
100 +
101 +// If no protection is set, just render the content.
102 +if ( 'password' === $protection_type && empty( $password ) ) {
103 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
104 + return;
105 +}
106 +
107 +if ( 'passwords' === $protection_type && empty( $passwords ) ) {
108 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
109 + return;
110 +}
111 +
112 +if ( 'password_list' === $protection_type && empty( $password_list ) ) {
113 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
114 + return;
115 +}
116 +
117 +// Build attributes array for validation.
118 +$atts = array();
119 +
120 +switch ( $protection_type ) {
121 + case 'password':
122 + $atts['password'] = $password;
123 + break;
124 + case 'passwords':
125 + $atts['passwords'] = $passwords;
126 + break;
127 + case 'password_list':
128 + $atts['password_list'] = $password_list;
129 + break;
130 +}
131 +
132 +// Add user restriction to validation attributes if enabled.
133 +if ( $user_restriction && ! empty( $user_restriction_value ) && 'no-role' !== $user_restriction_value ) {
134 + if ( 'user-role' === $user_restriction_type ) {
135 + $atts['role'] = $user_restriction_value;
136 + } else {
137 + $atts['user'] = $user_restriction_value;
138 + }
139 +}
140 +
141 +// Check if already unlocked.
142 +$is_unlocked = false;
143 +if ( class_exists( PS_Conditional::class ) ) {
144 + $is_unlocked = PS_Conditional::is_valid( $atts );
145 +}
146 +
147 +// If unlocked, show content.
148 +if ( $is_unlocked ) {
149 + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
150 + return;
151 +}
152 +
153 +if ( $advanced_options && $hide_form ) {
154 + return;
155 +}
156 +
157 +// Get global options for form defaults.
158 +$options = get_option( 'passster', array() );
159 +
160 +// Build the protection form using global settings.
161 +$form = PS_Form::get_password_form();
162 +
163 +// Form ID - use custom ID if set, otherwise block ID.
164 +$final_form_id = ! empty( $form_id ) ? $form_id : 'ps-block-' . $block_id;
165 +$form = str_replace( '[PASSSTER_ID]', esc_attr( $final_form_id ), $form );
166 +
167 +// Hide form placeholder.
168 +$form = str_replace( '[PASSSTER_HIDE]', '', $form );
169 +
170 +// Redirect URL.
171 +if ( $advanced_options && ! empty( $redirect_url ) ) {
172 + $form = str_replace( '[PASSSTER_REDIRECT]', esc_url( $redirect_url ), $form );
173 +} else {
174 + $form = str_replace( '[PASSSTER_REDIRECT]', '', $form );
175 +}
176 +
177 +// Label.
178 +$form = str_replace( '[PASSSTER_LABEL]', esc_html__( 'Enter your password', 'content-protector' ), $form );
179 +
180 +// Headline tag.
181 +$allowed_headline_tags = array( 'span', 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );
182 +$headline_tag = isset( $options['headline_tag'] ) && in_array( $options['headline_tag'], $allowed_headline_tags, true ) ? $options['headline_tag'] : 'span';
183 +$form = str_replace( '[PASSSTER_HEADLINE_TAG]', $headline_tag, $form );
184 +
185 +// Headline - use override if enabled and set, otherwise global.
186 +if ( ! empty( $options['hide_headline'] ) ) {
187 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', '', $form );
188 +} elseif ( $overwrite_defaults && ! empty( $headline ) ) {
189 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $headline ), $form );
190 +} else {
191 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $options['headline'] ?? '' ), $form );
192 +}
193 +
194 +// Instruction - use override if enabled and set, otherwise global.
195 +if ( $overwrite_defaults && ! empty( $instruction ) ) {
196 + $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $instruction ), $form );
197 +} else {
198 + $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $options['instruction'] ?? '' ), $form );
199 +}
200 +
201 +// Placeholder - use override if enabled and set, otherwise global.
202 +if ( $overwrite_defaults && ! empty( $placeholder ) ) {
203 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $placeholder ), $form );
204 +} else {
205 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $options['placeholder'] ?? '' ), $form );
206 +}
207 +
208 +// Button label - use override if enabled and set, otherwise global.
209 +if ( $overwrite_defaults && ! empty( $button_label ) ) {
210 + $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $button_label ), $form );
211 +} else {
212 + $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $options['button_label'] ?? '' ), $form );
213 +}
214 +
215 +// Protection type placeholder.
216 +$form = str_replace( '[PASSSTER_TYPE]', esc_attr( $protection_type ), $form );
217 +
218 +// Protection mode - 'block' for Content Lock blocks (REST API validates from block attributes).
219 +$form = str_replace( '[PASSSTER_PROTECTION]', 'block', $form );
220 +
221 +// Password list placeholders.
222 +$form = str_replace( '[PASSSTER_LIST]', esc_attr( $password_list ), $form );
223 +$form = str_replace( '[PASSSTER_LISTS]', '', $form );
224 +
225 +// Area placeholder (set to 0 for blocks - we use block_id instead).
226 +$form = str_replace( '[PASSSTER_AREA]', '0', $form );
227 +
228 +// ACF placeholder (not used in blocks).
229 +$form = str_replace( '[PASSSTER_ACF]', '', $form );
230 +
231 +// Wrapper classes.
232 +$wrapper_classes = array( 'passster-protected-content', 'wp-block-passster-protected-content' );
233 +if ( ! empty( $attributes['align'] ) ) {
234 + $wrapper_classes[] = 'align' . $attributes['align'];
235 +}
236 +if ( ! empty( $attributes['className'] ) ) {
237 + $wrapper_classes[] = $attributes['className'];
238 +}
239 +
240 +// Data attributes for JS handling.
241 +$data_attrs = array(
242 + 'block-id' => $block_id,
243 + 'protection-type' => $protection_type,
244 + 'post-id' => get_the_ID(),
245 +);
246 +
247 +if ( $advanced_options && ! empty( $redirect_url ) ) {
248 + $data_attrs['redirect'] = $redirect_url;
249 +}
250 +
251 +// Output.
252 +?>
253 +<div
254 + class="<?php echo esc_attr( implode( ' ', $wrapper_classes ) ); ?>"
255 + <?php foreach ( $data_attrs as $key => $value ) : ?>
256 + data-<?php echo esc_attr( $key ); ?>="<?php echo esc_attr( $value ); ?>"
257 + <?php endforeach; ?>
258 +>
259 + <div class="passster-protected-content__form">
260 + <?php echo $form; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
261 + </div>
262 +</div>
263 +<?php