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 | inc/class-ps-public.php +445 -254 4.2.134.3.16 View file →
@@ -1,254 +1,445 @@
1 -<?php
2 -
3 -namespace passster;
4 -
5 -use Exception;
6 -class PS_Public {
7 - /**
8 - * Contains instance or null
9 - *
10 - * @var object|null
11 - */
12 - private static $instance = null;
13 -
14 - /**
15 - * Constructor for PS_Public
16 - */
17 - public function __construct() {
18 - add_shortcode( 'content_protector', array($this, 'render_shortcode') );
19 - add_shortcode( 'passster', array($this, 'render_shortcode') );
20 - add_filter( 'the_content', array($this, 'filter_the_content') );
21 - add_filter( 'acf_the_content', array($this, 'filter_the_content') );
22 - add_filter( 'get_the_excerpt', array($this, 'filter_the_content') );
23 - add_action( 'template_redirect', array($this, 'check_global_proctection') );
24 - }
25 -
26 - /**
27 - * Returns instance of PS_Public.
28 - *
29 - * @return object
30 - */
31 - public static function get_instance() {
32 - if ( null === self::$instance ) {
33 - self::$instance = new self();
34 - }
35 - return self::$instance;
36 - }
37 -
38 - /**
39 - * Render the Passster shortcode.
40 - *
41 - * @param array $atts array of attributes.
42 - * @param string|null $content the current content.
43 - *
44 - * @return string
45 - */
46 - public function render_shortcode( array $atts, string $content = null ) : string {
47 - // check if valid before restrict anything.
48 - $valid = PS_Conditional::is_valid( $atts );
49 - $options = get_option( 'passster' );
50 - if ( $valid ) {
51 - if ( !empty( $atts['area'] ) ) {
52 - $area_id = esc_html( $atts['area'] );
53 - $area = get_post( $area_id );
54 - $content = $area->post_content;
55 - do_action( 'passster_content_unlocked' );
56 - return apply_filters( 'the_content', str_replace( '{post-id}', get_the_id(), $content ) );
57 - } else {
58 - $content = apply_filters( 'the_content', $content );
59 - do_action( 'passster_content_unlocked' );
60 - return apply_filters( 'passster_content', $content );
61 - }
62 - }
63 - // do nothing if no atts.
64 - if ( empty( $atts ) ) {
65 - return $content;
66 - }
67 - // Set default form.
68 - $form = PS_Form::get_password_form();
69 - // Password.
70 - if ( !empty( $atts['password'] ) ) {
71 - $form = PS_Form::get_password_form();
72 - $form = str_replace( '[PASSSTER_TYPE]', 'password', $form );
73 - }
74 - // Area.
75 - if ( !empty( $atts['area'] ) ) {
76 - $area_id = esc_html( $atts['area'] );
77 - $form = str_replace( '[PASSSTER_AREA]', $area_id, $form );
78 - }
79 - // Page.
80 - if ( !empty( $atts['protection'] ) ) {
81 - $form = str_replace( '[PASSSTER_PROTECTION]', 'full', $form );
82 - } else {
83 - if ( !empty( $atts['area'] ) ) {
84 - $form = str_replace( '[PASSSTER_PROTECTION]', 'area', $form );
85 - }
86 - }
87 - // Redirect.
88 - if ( !empty( $atts['redirect'] ) ) {
89 - $form = str_replace( '[PASSSTER_REDIRECT]', esc_url( $atts['redirect'] ), $form );
90 - } else {
91 - $form = str_replace( '[PASSSTER_REDIRECT]', '', $form );
92 - }
93 - // headline.
94 - if ( !empty( $options['hide_headline'] ) ) {
95 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', '', $form );
96 - } elseif ( !empty( $atts['headline'] ) ) {
97 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $atts['headline'] ), $form );
98 - } else {
99 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', $options['headline'], $form );
100 - }
101 - // instruction.
102 - if ( !empty( $atts['instruction'] ) ) {
103 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', esc_html( $atts['instruction'] ), $form );
104 - } else {
105 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', $options['instruction'], $form );
106 - }
107 - // placeholder.
108 - if ( !empty( $atts['placeholder'] ) ) {
109 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_html( $atts['placeholder'] ), $form );
110 - } else {
111 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', $options['placeholder'], $form );
112 - }
113 - // button.
114 - if ( !empty( $atts['button'] ) ) {
115 - $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $atts['button'] ), $form );
116 - } else {
117 - $form = str_replace( '[PASSSTER_BUTTON_LABEL]', $options['button_label'], $form );
118 - }
119 - // modify id.
120 - if ( !empty( $atts['id'] ) ) {
121 - $form = str_replace( '[PASSSTER_ID]', 'ps-' . esc_html( $atts['id'] ), $form );
122 - } else {
123 - $form = str_replace( '[PASSSTER_ID]', 'ps-' . wp_rand( 10, 1000 ), $form );
124 - }
125 - // hide or not.
126 - if ( !empty( $atts['hide'] ) ) {
127 - $form = str_replace( '[PASSSTER_HIDE]', ' passster-hide', $form );
128 - } else {
129 - $form = str_replace( '[PASSSTER_HIDE]', '', $form );
130 - }
131 - // ACF field.
132 - if ( !empty( $atts['acf'] ) ) {
133 - $form = str_replace( '[PASSSTER_ACF]', ' data-acf="' . esc_html( $atts['acf'] ) . '"', $form );
134 - } else {
135 - $form = str_replace( '[PASSSTER_ACF]', '', $form );
136 - }
137 - return $form;
138 - }
139 -
140 - /**
141 - * Filters the_content with Passster.
142 - *
143 - * @param string $content given content.
144 - *
145 - * @return string
146 - * @throws Exception
147 - */
148 - public function filter_the_content( string $content ) : string {
149 - $post_id = get_the_id();
150 - $activate_protection = get_post_meta( $post_id, 'passster_activate_protection', true );
151 - // user restriction.
152 - $user_restriction_type = get_post_meta( $post_id, 'passster_user_restriction_type', true );
153 - $user_restriction = get_post_meta( $post_id, 'passster_user_restriction', true );
154 - // Redirection.
155 - $redirection = get_post_meta( $post_id, 'passster_redirect_url', true );
156 - // texts.
157 - $headline = get_post_meta( $post_id, 'passster_headline', true );
158 - $instruction = get_post_meta( $post_id, 'passster_instruction', true );
159 - $placeholder = get_post_meta( $post_id, 'passster_placeholder', true );
160 - $button = get_post_meta( $post_id, 'passster_button', true );
161 - $id = get_post_meta( $post_id, 'passster_id', true );
162 - if ( !$activate_protection ) {
163 - return $content;
164 - }
165 - // build atts array to validate.
166 - $atts = array();
167 - $shortcode = '';
168 - $password = get_post_meta( $post_id, 'passster_password', true );
169 - $atts['password'] = $password;
170 - $shortcode = '[passster password="' . $password . '" protection="full" ';
171 - if ( !empty( $redirection ) ) {
172 - $shortcode .= 'redirect="' . $redirection . '" ';
173 - }
174 - if ( !empty( $headline ) ) {
175 - $shortcode .= 'headline="' . $headline . '" ';
176 - }
177 - if ( !empty( $instruction ) ) {
178 - $shortcode .= 'instruction="' . $instruction . '" ';
179 - }
180 - if ( !empty( $placeholder ) ) {
181 - $shortcode .= 'placeholder="' . $placeholder . '" ';
182 - }
183 - if ( !empty( $button ) ) {
184 - $shortcode .= 'button="' . $button . '" ';
185 - }
186 - if ( !empty( $id ) ) {
187 - $shortcode .= 'id="' . $id . '" ';
188 - }
189 - $shortcode .= ']{content}[/passster]';
190 - // check if valid before restrict anything.
191 - $valid = PS_Conditional::is_valid( $atts );
192 - if ( $valid ) {
193 - return $content;
194 - }
195 - // replace placeholder with content.
196 - $shortcode = str_replace( '{content}', $content, $shortcode );
197 - return do_shortcode( $shortcode );
198 - }
199 -
200 - /**
201 - * Redirect if global protection is activated and no password is set.
202 - *
203 - * @return void
204 - * @throws Exception
205 - */
206 - public function check_global_proctection() {
207 - $options = get_option( 'passster' );
208 - // Allow Elementor editing the page.
209 - $elementor_preview = filter_input( INPUT_GET, 'elementor-preview', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
210 - if ( $elementor_preview ) {
211 - return;
212 - }
213 - // Allow Live Canvas Editor.
214 - $live_canvas_preview = filter_input( INPUT_GET, 'lc_action_launch_editing', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
215 - if ( $live_canvas_preview ) {
216 - return;
217 - }
218 - if ( !isset( $options['global_protection_id'] ) ) {
219 - return;
220 - }
221 - if ( !isset( $options['activate_global_protection'] ) ) {
222 - return;
223 - }
224 - // Build $atts array based on protection settings.
225 - $post_id = esc_html( $options['global_protection_id'] );
226 - $is_active = esc_html( $options['activate_global_protection'] );
227 - $atts = array();
228 - $password = get_post_meta( $post_id, 'passster_password', true );
229 - $atts['password'] = esc_html( $password );
230 - if ( !empty( $post_id ) ) {
231 - if ( $is_active ) {
232 - if ( is_page( $post_id ) || is_single( $post_id ) ) {
233 - return;
234 - }
235 - // Check excluded pages.
236 - if ( isset( $options['exclude_pages'] ) ) {
237 - foreach ( $options['exclude_pages'] as $excluded_page_id ) {
238 - if ( is_page( $excluded_page_id ) ) {
239 - return;
240 - }
241 - }
242 - }
243 - // Check if cookie is set.
244 - $cookie = esc_html( $_COOKIE['passster'] );
245 - if ( empty( $cookie ) || !PS_Conditional::is_valid( $atts ) ) {
246 - $global_protection_url = get_permalink( $post_id );
247 - wp_redirect( esc_url_raw( $global_protection_url ) );
248 - exit;
249 - }
250 - }
251 - }
252 - }
253 -
254 -}
1 +<?php
2 +
3 +namespace passster;
4 +
5 +use Exception;
6 +class PS_Public {
7 + /**
8 + * Contains instance or null
9 + *
10 + * @var object|null
11 + */
12 + private static $instance = null;
13 +
14 + /**
15 + * Track which posts have already had their protection form rendered
16 + * to prevent duplicate forms on page builders like Avada.
17 + *
18 + * @var array
19 + */
20 + private static $rendered_protection = array();
21 +
22 + /**
23 + * Constructor for PS_Public
24 + */
25 + public function __construct() {
26 + add_shortcode( 'content_protector', array($this, 'render_shortcode') );
27 + add_shortcode( 'passster', array($this, 'render_shortcode') );
28 + add_filter( 'the_content', array($this, 'filter_the_content') );
29 + add_filter( 'acf_the_content', array($this, 'filter_the_content') );
30 + add_filter( 'get_the_excerpt', array($this, 'filter_the_content') );
31 + add_action( 'template_redirect', array($this, 'check_global_proctection') );
32 + add_action( 'wp_enqueue_scripts', array($this, 'add_public_scripts'), 9999 );
33 + }
34 +
35 + /**
36 + * Returns instance of PS_Public.
37 + *
38 + * @return object
39 + */
40 + public static function get_instance() {
41 + if ( null === self::$instance ) {
42 + self::$instance = new self();
43 + }
44 + return self::$instance;
45 + }
46 +
47 + /**
48 + * Avoids re-entering the_content recursively.
49 + *
50 + * @param string $content the unlocked content.
51 + *
52 + * @return string
53 + */
54 + private function render_unlocked_content( string $content ) : string {
55 + if ( doing_filter( 'the_content' ) ) {
56 + return wpautop( do_shortcode( $content ) );
57 + }
58 + return apply_filters( 'the_content', $content );
59 + }
60 +
61 + /**
62 + * Render the Passster shortcode.
63 + *
64 + * @param array $atts array of attributes.
65 + * @param string|null $content the current content.
66 + *
67 + * @return string
68 + */
69 + public function render_shortcode( array $atts, string $content = null ) : string {
70 + // Schedule check for protected areas (PRO only).
71 + if ( !empty( $atts['area'] ) && \passster_fs()->is_plan_or_trial__premium_only( 'pro' ) ) {
72 + $area_id = absint( $atts['area'] );
73 + $schedule_enabled = get_post_meta( $area_id, 'passster_schedule_enabled', true );
74 + if ( $schedule_enabled ) {
75 + $schedule_start = get_post_meta( $area_id, 'passster_schedule_start', true );
76 + $schedule_end = get_post_meta( $area_id, 'passster_schedule_end', true );
77 + $now = current_time( 'timestamp' );
78 + $in_schedule = true;
79 + if ( !empty( $schedule_start ) && $now < strtotime( $schedule_start ) ) {
80 + $in_schedule = false;
81 + }
82 + if ( !empty( $schedule_end ) && $now > strtotime( $schedule_end ) ) {
83 + $in_schedule = false;
84 + }
85 + if ( !$in_schedule ) {
86 + $area = get_post( $area_id );
87 + if ( $area && ('publish' === $area->post_status || current_user_can( 'edit_post', $area_id )) ) {
88 + return $this->render_unlocked_content( str_replace( '{post-id}', get_the_id(), $area->post_content ) );
89 + }
90 + return $content ?? '';
91 + }
92 + }
93 + }
94 + // check if valid before restrict anything.
95 + $valid = PS_Conditional::is_valid( $atts );
96 + $options = get_option( 'passster' );
97 + if ( $valid ) {
98 + if ( !empty( $atts['area'] ) ) {
99 + $area_id = esc_html( $atts['area'] );
100 + $area = get_post( $area_id );
101 + if ( 'publish' === $area->post_status || current_user_can( 'edit_post', $area_id ) ) {
102 + $content = $area->post_content;
103 + do_action( 'passster_content_unlocked' );
104 + return $this->render_unlocked_content( str_replace( '{post-id}', get_the_id(), $content ) );
105 + }
106 + } else {
107 + $content = $this->render_unlocked_content( $content );
108 + do_action( 'passster_content_unlocked' );
109 + return apply_filters( 'passster_content', $content );
110 + }
111 + }
112 + // do nothing if no atts.
113 + if ( empty( $atts ) ) {
114 + return $content;
115 + }
116 + // Set default form.
117 + $form = PS_Form::get_password_form();
118 + // Password.
119 + if ( !empty( $atts['password'] ) ) {
120 + $form = PS_Form::get_password_form();
121 + $form = str_replace( '[PASSSTER_TYPE]', 'password', $form );
122 + }
123 + // Area.
124 + if ( !empty( $atts['area'] ) ) {
125 + $area_id = absint( $atts['area'] );
126 + $form = str_replace( '[PASSSTER_AREA]', $area_id, $form );
127 + }
128 + // Page.
129 + if ( !empty( $atts['protection'] ) ) {
130 + $form = str_replace( '[PASSSTER_PROTECTION]', 'full', $form );
131 + } elseif ( !empty( $atts['area'] ) ) {
132 + $form = str_replace( '[PASSSTER_PROTECTION]', 'area', $form );
133 + }
134 + // Redirect.
135 + if ( !empty( $atts['redirect'] ) ) {
136 + $form = str_replace( '[PASSSTER_REDIRECT]', esc_url( $atts['redirect'] ), $form );
137 + } else {
138 + $form = str_replace( '[PASSSTER_REDIRECT]', '', $form );
139 + }
140 + // headline tag.
141 + $allowed_headline_tags = array(
142 + 'span',
143 + 'p',
144 + 'div',
145 + 'h1',
146 + 'h2',
147 + 'h3',
148 + 'h4',
149 + 'h5',
150 + 'h6'
151 + );
152 + $headline_tag = ( isset( $options['headline_tag'] ) && in_array( $options['headline_tag'], $allowed_headline_tags, true ) ? $options['headline_tag'] : 'span' );
153 + $form = str_replace( '[PASSSTER_HEADLINE_TAG]', $headline_tag, $form );
154 + // headline.
155 + if ( !empty( $options['hide_headline'] ) ) {
156 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', '', $form );
157 + } elseif ( !empty( $atts['headline'] ) ) {
158 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $atts['headline'] ), $form );
159 + } else {
160 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $options['headline'] ), $form );
161 + }
162 + // instruction.
163 + if ( !empty( $atts['instruction'] ) ) {
164 + $decoded_instruction = base64_decode( $atts['instruction'] );
165 + $decoded_instruction = html_entity_decode( $decoded_instruction );
166 + $sanitized_instruction = wp_kses_post( $decoded_instruction );
167 + $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', $sanitized_instruction, $form );
168 + } else {
169 + $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $options['instruction'] ), $form );
170 + }
171 + // placeholder.
172 + if ( !empty( $atts['placeholder'] ) ) {
173 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $atts['placeholder'] ), $form );
174 + } else {
175 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $options['placeholder'] ), $form );
176 + }
177 + // label.
178 + $form = str_replace( '[PASSSTER_LABEL]', esc_html__( 'Enter your password', 'content-protector' ), $form );
179 + // button.
180 + if ( !empty( $atts['button'] ) ) {
181 + $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $atts['button'] ), $form );
182 + } else {
183 + $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $options['button_label'] ), $form );
184 + }
185 + // modify id.
186 + if ( !empty( $atts['id'] ) ) {
187 + $form = str_replace( '[PASSSTER_ID]', 'ps-' . esc_attr( $atts['id'] ), $form );
188 + } else {
189 + $form = str_replace( '[PASSSTER_ID]', 'ps-' . wp_rand( 10, 1000 ), $form );
190 + }
191 + // post id (per-form, for correct REST unlock on archive pages with multiple protected posts).
192 + $form = str_replace( '[PASSSTER_POST_ID]', absint( get_the_ID() ), $form );
193 + // term id (for category archive protection — passed to REST API so it can validate against term meta).
194 + $term_id_val = ( !empty( $atts['term_id'] ) ? absint( $atts['term_id'] ) : 0 );
195 + $form = str_replace( '[PASSSTER_TERM_ID]', $term_id_val, $form );
196 + // post type (for post type archive protection — passed to REST API so it can validate against post type config).
197 + $post_type_val = ( !empty( $atts['post_type'] ) ? sanitize_key( $atts['post_type'] ) : '' );
198 + $form = str_replace( '[PASSSTER_POST_TYPE]', esc_attr( $post_type_val ), $form );
199 + // hide or not.
200 + if ( !empty( $atts['hide'] ) ) {
201 + $form = str_replace( '[PASSSTER_HIDE]', ' passster-hide', $form );
202 + } else {
203 + $form = str_replace( '[PASSSTER_HIDE]', '', $form );
204 + }
205 + // ACF field.
206 + if ( !empty( $atts['acf'] ) ) {
207 + $form = str_replace( '[PASSSTER_ACF]', ' data-acf="' . esc_url( $atts['acf'] ) . '"', $form );
208 + } else {
209 + $form = str_replace( '[PASSSTER_ACF]', '', $form );
210 + }
211 + return $form;
212 + }
213 +
214 + /**
215 + * Filters the_content with Passster.
216 + *
217 + * @param string $content given content.
218 + *
219 + * @return string
220 + * @throws Exception
221 + */
222 + public function filter_the_content( string $content ) : string {
223 + $post_id = get_the_id();
224 + // Prevent duplicate form rendering (fixes issue with Avada and other page builders)
225 + if ( isset( self::$rendered_protection[$post_id] ) ) {
226 + // Already rendered the protection form for this post, return protected content placeholder
227 + // or the form that was already generated
228 + return self::$rendered_protection[$post_id]['form'] ?? $content;
229 + }
230 + $parent_id = wp_get_post_parent_id( $post_id );
231 + if ( $parent_id ) {
232 + $activate_protection = get_post_meta( $parent_id, 'passster_activate_protection', true );
233 + $children_protection = get_post_meta( $parent_id, 'passster_protect_child_pages', true );
234 + if ( $activate_protection && $children_protection ) {
235 + $post_id = $parent_id;
236 + // Check parent too
237 + if ( isset( self::$rendered_protection[$post_id] ) ) {
238 + return self::$rendered_protection[$post_id]['form'] ?? $content;
239 + }
240 + }
241 + }
242 + $activate_protection = get_post_meta( $post_id, 'passster_activate_protection', true );
243 + // user restriction.
244 + $user_restriction_type = get_post_meta( $post_id, 'passster_user_restriction_type', true );
245 + $user_restriction = get_post_meta( $post_id, 'passster_user_restriction', true );
246 + // Redirection.
247 + $redirection = get_post_meta( $post_id, 'passster_redirect_url', true );
248 + // texts.
249 + $overwrite_defaults = get_post_meta( $post_id, 'passster_activate_overwrite_defaults', true );
250 + $headline = ( $overwrite_defaults ? get_post_meta( $post_id, 'passster_headline', true ) : '' );
251 + $instruction = ( $overwrite_defaults ? get_post_meta( $post_id, 'passster_instruction', true ) : '' );
252 + $placeholder = ( $overwrite_defaults ? get_post_meta( $post_id, 'passster_placeholder', true ) : '' );
253 + $button = ( $overwrite_defaults ? get_post_meta( $post_id, 'passster_button', true ) : '' );
254 + $id = get_post_meta( $post_id, 'passster_id', true );
255 + if ( !$activate_protection ) {
256 + return $content;
257 + }
258 + // build atts array to validate.
259 + $atts = array();
260 + $shortcode = '';
261 + $password = get_post_meta( $post_id, 'passster_password', true );
262 + $atts['password'] = $password;
263 + $shortcode = '[passster password="' . $password . '" protection="full" ';
264 + if ( !empty( $redirection ) ) {
265 + $shortcode .= 'redirect="' . $redirection . '" ';
266 + }
267 + if ( !empty( $headline ) ) {
268 + $shortcode .= 'headline="' . $headline . '" ';
269 + }
270 + if ( !empty( $instruction ) ) {
271 + $shortcode .= 'instruction="' . base64_encode( $instruction ) . '" ';
272 + }
273 + if ( !empty( $placeholder ) ) {
274 + $shortcode .= 'placeholder="' . $placeholder . '" ';
275 + }
276 + if ( !empty( $button ) ) {
277 + $shortcode .= 'button="' . $button . '" ';
278 + }
279 + if ( !empty( $id ) ) {
280 + $shortcode .= 'id="' . $id . '" ';
281 + }
282 + $shortcode .= ']{content}[/passster]';
283 + // check if valid before restrict anything.
284 + $valid = PS_Conditional::is_valid( $atts );
285 + if ( $valid ) {
286 + return $content;
287 + }
288 + // replace placeholder with content.
289 + $shortcode = str_replace( '{content}', $content, $shortcode );
290 + // Generate the form
291 + $rendered_form = do_shortcode( $shortcode );
292 + // Store reference to prevent duplicate rendering (Avada, Elementor, etc.)
293 + self::$rendered_protection[$post_id] = array(
294 + 'form' => $rendered_form,
295 + );
296 + return $rendered_form;
297 + }
298 +
299 + /**
300 + * Redirect if global protection is activated and no password is set.
301 + *
302 + * @return void
303 + * @throws Exception
304 + */
305 + public function check_global_proctection() {
306 + $options = get_option( 'passster' );
307 + $post_id = get_queried_object_id();
308 + if ( !$post_id ) {
309 + return;
310 + }
311 + // Allow Elementor editing the page.
312 + $elementor_preview = filter_input( INPUT_GET, 'elementor-preview', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
313 + // Allow Live Canvas Editor.
314 + $live_canvas_preview = filter_input( INPUT_GET, 'lc_action_launch_editing', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
315 + if ( is_preview() || $elementor_preview || $live_canvas_preview ) {
316 + if ( is_user_logged_in() && current_user_can( 'edit_post', $post_id ) ) {
317 + return;
318 + }
319 + }
320 + if ( !isset( $options['global_protection_id'] ) ) {
321 + return;
322 + }
323 + if ( !isset( $options['activate_global_protection'] ) ) {
324 + return;
325 + }
326 + // Build $atts array based on protection settings.
327 + $post_id = esc_html( $options['global_protection_id'] );
328 + $is_active = esc_html( $options['activate_global_protection'] );
329 + $atts = array();
330 + $password = get_post_meta( $post_id, 'passster_password', true );
331 + $atts['password'] = $password;
332 + if ( !empty( $post_id ) ) {
333 + if ( $is_active ) {
334 + if ( is_page( $post_id ) || is_single( $post_id ) ) {
335 + return;
336 + }
337 + // Check excluded pages.
338 + if ( isset( $options['exclude_pages'] ) ) {
339 + foreach ( $options['exclude_pages'] as $excluded_page_id ) {
340 + if ( is_page( $excluded_page_id ) ) {
341 + return;
342 + }
343 + }
344 + }
345 + // Check if cookie is set.
346 + $cookie = esc_html( $_COOKIE['passster'] );
347 + if ( !PS_Conditional::is_valid( $atts ) ) {
348 + $global_protection_url = get_permalink( $post_id );
349 + $pass_param = filter_input( INPUT_GET, 'pass', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
350 + if ( !empty( $pass_param ) ) {
351 + $global_protection_url = add_query_arg( 'pass', $pass_param, $global_protection_url );
352 + }
353 + wp_redirect( esc_url_raw( $global_protection_url ) );
354 + exit;
355 + }
356 + }
357 + }
358 + }
359 +
360 + /**
361 + * Enqueue scripts for shortcode
362 + *
363 + * @return void
364 + */
365 + public function add_public_scripts() {
366 + $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min' );
367 + $options = get_option( 'passster' );
368 + // Only load CSS if not disabled (allows themes to style the form)
369 + if ( empty( $options['disable_css'] ) ) {
370 + wp_enqueue_style(
371 + 'passster-public',
372 + PASSSTER_URL . '/assets/public/passster-public' . $suffix . '.css',
373 + array(),
374 + PASSSTER_VERSION,
375 + 'all'
376 + );
377 + }
378 + wp_enqueue_script(
379 + 'passster-cookie',
380 + PASSSTER_URL . '/assets/public/cookie.js',
381 + array('jquery', 'wp-api-fetch'),
382 + PASSSTER_VERSION,
383 + false
384 + );
385 + wp_enqueue_script(
386 + 'passster-public',
387 + PASSSTER_URL . '/assets/public/passster-public' . $suffix . '.js',
388 + array('jquery', 'passster-cookie'),
389 + PASSSTER_VERSION,
390 + false
391 + );
392 + $shortcodes = array();
393 + if ( isset( $options['third_party_shortcodes'] ) && !empty( $options['third_party_shortcodes'] ) ) {
394 + $shortcodes_in_options = explode( ',', $options['third_party_shortcodes'] );
395 + if ( is_array( $shortcodes_in_options ) ) {
396 + foreach ( $shortcodes_in_options as $shortcode ) {
397 + $shortcodes[$shortcode] = do_shortcode( str_replace( '{post-id}', get_the_id(), $shortcode ) );
398 + }
399 + }
400 + }
401 + // Archive/taxonomy pages have no singular post, so get_permalink() can't be used
402 + // to build the "reload after unlock" URL for links generated by area/CPT-level protection.
403 + $current_post_id = get_the_id();
404 + $reload_url = ( $current_post_id ? get_permalink( $current_post_id ) : esc_url_raw( remove_query_arg( 'pass' ) ) );
405 + $args = array(
406 + 'ajax_url' => admin_url() . 'admin-ajax.php',
407 + 'rest_url' => get_rest_url(),
408 + 'nonce' => wp_create_nonce( 'ps-password-nonce' ),
409 + 'hash_nonce' => wp_create_nonce( 'ps-hash-nonce' ),
410 + 'logout_nonce' => wp_create_nonce( 'ps-logout-nonce' ),
411 + 'post_id' => $current_post_id,
412 + 'shortcodes' => $shortcodes,
413 + 'permalink' => $reload_url,
414 + );
415 + if ( isset( $options['cookie_duration_unit'] ) ) {
416 + $args['cookie_duration_unit'] = esc_html( $options['cookie_duration_unit'] );
417 + } else {
418 + $args['cookie_duration_unit'] = 'days';
419 + }
420 + if ( isset( $options['cookie_duration'] ) ) {
421 + $args['cookie_duration'] = esc_html( $options['cookie_duration'] );
422 + } else {
423 + $args['cookie_duration'] = 1;
424 + }
425 + if ( isset( $options['disable_cookie'] ) ) {
426 + $args['disable_cookie'] = esc_html( $options['disable_cookie'] );
427 + } else {
428 + $args['disable_cookie'] = false;
429 + }
430 + $args['unlock_mode'] = !empty( $options['unlock_mode'] );
431 + wp_localize_script( 'passster-public', 'ps_ajax', $args );
432 + // if password type hint used.
433 + $password_typing = $options['show_password'];
434 + if ( $password_typing ) {
435 + wp_enqueue_script(
436 + 'password-typing',
437 + PASSSTER_URL . '/assets/public/password-typing.js',
438 + array('jquery'),
439 + PASSSTER_VERSION,
440 + false
441 + );
442 + }
443 + }
444 +
445 +}