PluginProbe
Passster – Password Protect Pages and Content / 4.3.13
Passster – Password Protect Pages and Content v4.3.13
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 4.2.16 All 47 releases
content-protector / build / blocks / protected-content / render.php

render.php in Passster – Password Protect Pages and Content 4.3.13, at build/blocks/protected-content/render.php

264 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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
264