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 +268 -105 4.1.44.3.16 View file →
@@ -1,44 +1,65 @@
1 1 <?php
2 2
3 3 namespace passster;
4 4
5 -use Exception ;
6 -class PS_Public
7 -{
5 +use Exception;
6 +class PS_Public {
8 7 /**
9 8 * Contains instance or null
10 9 *
11 10 * @var object|null
12 11 */
13 - private static $instance = null ;
12 + private static $instance = null;
13 +
14 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 + /**
15 23 * Constructor for PS_Public
16 24 */
17 - public function __construct()
18 - {
19 - add_shortcode( 'content_protector', array( $this, 'render_shortcode' ) );
20 - add_shortcode( 'passster', array( $this, 'render_shortcode' ) );
21 - add_filter( 'the_content', array( $this, 'filter_the_content' ) );
22 - add_filter( 'acf_the_content', array( $this, 'filter_the_content' ) );
23 - add_filter( 'get_the_excerpt', array( $this, 'filter_the_content' ) );
24 - add_action( 'template_redirect', array( $this, 'check_global_proctection' ) );
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 );
25 33 }
26 -
34 +
27 35 /**
28 36 * Returns instance of PS_Public.
29 37 *
30 38 * @return object
31 39 */
32 - public static function get_instance()
33 - {
40 + public static function get_instance() {
34 41 if ( null === self::$instance ) {
35 42 self::$instance = new self();
36 43 }
37 44 return self::$instance;
38 45 }
39 -
46 +
40 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 + /**
41 62 * Render the Passster shortcode.
42 63 *
43 64 * @param array $atts array of attributes.
44 65 * @param string|null $content the current content.
@@ -44,125 +65,153 @@
44 65 * @param string|null $content the current content.
45 66 *
46 67 * @return string
47 68 */
48 - public function render_shortcode( array $atts, string $content = null ) : string
49 - {
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 + }
50 94 // check if valid before restrict anything.
51 95 $valid = PS_Conditional::is_valid( $atts );
52 96 $options = get_option( 'passster' );
53 97 if ( $valid ) {
54 -
55 - if ( !empty($atts['area']) ) {
98 + if ( !empty( $atts['area'] ) ) {
56 99 $area_id = esc_html( $atts['area'] );
57 100 $area = get_post( $area_id );
58 - $content = $area->post_content;
59 - do_action( 'passster_content_unlocked' );
60 - return apply_filters( 'the_content', str_replace( '{post-id}', get_the_id(), $content ) );
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 + }
61 106 } else {
62 - $content = apply_filters( 'the_content', $content );
107 + $content = $this->render_unlocked_content( $content );
63 108 do_action( 'passster_content_unlocked' );
64 109 return apply_filters( 'passster_content', $content );
65 110 }
66 -
67 111 }
68 112 // do nothing if no atts.
69 - if ( empty($atts) ) {
113 + if ( empty( $atts ) ) {
70 114 return $content;
71 115 }
72 116 // Set default form.
73 117 $form = PS_Form::get_password_form();
74 118 // Password.
75 -
76 - if ( !empty($atts['password']) ) {
119 + if ( !empty( $atts['password'] ) ) {
77 120 $form = PS_Form::get_password_form();
78 121 $form = str_replace( '[PASSSTER_TYPE]', 'password', $form );
79 122 }
80 -
81 123 // Area.
82 -
83 - if ( !empty($atts['area']) ) {
84 - $area_id = esc_html( $atts['area'] );
124 + if ( !empty( $atts['area'] ) ) {
125 + $area_id = absint( $atts['area'] );
85 126 $form = str_replace( '[PASSSTER_AREA]', $area_id, $form );
86 127 }
87 -
88 128 // Page.
89 -
90 - if ( !empty($atts['protection']) ) {
129 + if ( !empty( $atts['protection'] ) ) {
91 130 $form = str_replace( '[PASSSTER_PROTECTION]', 'full', $form );
92 - } else {
93 - if ( !empty($atts['area']) ) {
94 - $form = str_replace( '[PASSSTER_PROTECTION]', 'area', $form );
95 - }
131 + } elseif ( !empty( $atts['area'] ) ) {
132 + $form = str_replace( '[PASSSTER_PROTECTION]', 'area', $form );
96 133 }
97 -
98 134 // Redirect.
99 -
100 - if ( !empty($atts['redirect']) ) {
101 - $form = str_replace( '[PASSSTER_REDIRECT]', $atts['redirect'], $form );
135 + if ( !empty( $atts['redirect'] ) ) {
136 + $form = str_replace( '[PASSSTER_REDIRECT]', esc_url( $atts['redirect'] ), $form );
102 137 } else {
103 138 $form = str_replace( '[PASSSTER_REDIRECT]', '', $form );
104 139 }
105 -
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 );
106 154 // headline.
107 -
108 - if ( !empty($atts['headline']) ) {
155 + if ( !empty( $options['hide_headline'] ) ) {
156 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', '', $form );
157 + } elseif ( !empty( $atts['headline'] ) ) {
109 158 $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $atts['headline'] ), $form );
110 159 } else {
111 - $form = str_replace( '[PASSSTER_FORM_HEADLINE]', $options['headline'], $form );
160 + $form = str_replace( '[PASSSTER_FORM_HEADLINE]', esc_html( $options['headline'] ), $form );
112 161 }
113 -
114 162 // instruction.
115 -
116 - if ( !empty($atts['instruction']) ) {
117 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', esc_html( $atts['instruction'] ), $form );
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 );
118 168 } else {
119 - $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', $options['instruction'], $form );
169 + $form = str_replace( '[PASSSTER_FORM_INSTRUCTIONS]', wp_kses_post( $options['instruction'] ), $form );
120 170 }
121 -
122 171 // placeholder.
123 -
124 - if ( !empty($atts['placeholder']) ) {
125 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_html( $atts['placeholder'] ), $form );
172 + if ( !empty( $atts['placeholder'] ) ) {
173 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $atts['placeholder'] ), $form );
126 174 } else {
127 - $form = str_replace( '[PASSSTER_PLACEHOLDER]', $options['placeholder'], $form );
175 + $form = str_replace( '[PASSSTER_PLACEHOLDER]', esc_attr( $options['placeholder'] ), $form );
128 176 }
129 -
177 + // label.
178 + $form = str_replace( '[PASSSTER_LABEL]', esc_html__( 'Enter your password', 'content-protector' ), $form );
130 179 // button.
131 -
132 - if ( !empty($atts['button']) ) {
180 + if ( !empty( $atts['button'] ) ) {
133 181 $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $atts['button'] ), $form );
134 182 } else {
135 - $form = str_replace( '[PASSSTER_BUTTON_LABEL]', $options['button_label'], $form );
183 + $form = str_replace( '[PASSSTER_BUTTON_LABEL]', esc_html( $options['button_label'] ), $form );
136 184 }
137 -
138 185 // modify id.
139 -
140 - if ( !empty($atts['id']) ) {
141 - $form = str_replace( '[PASSSTER_ID]', 'ps-' . esc_html( $atts['id'] ), $form );
186 + if ( !empty( $atts['id'] ) ) {
187 + $form = str_replace( '[PASSSTER_ID]', 'ps-' . esc_attr( $atts['id'] ), $form );
142 188 } else {
143 189 $form = str_replace( '[PASSSTER_ID]', 'ps-' . wp_rand( 10, 1000 ), $form );
144 190 }
145 -
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 );
146 199 // hide or not.
147 -
148 - if ( !empty($atts['hide']) ) {
200 + if ( !empty( $atts['hide'] ) ) {
149 201 $form = str_replace( '[PASSSTER_HIDE]', ' passster-hide', $form );
150 202 } else {
151 203 $form = str_replace( '[PASSSTER_HIDE]', '', $form );
152 204 }
153 -
154 205 // ACF field.
155 -
156 - if ( !empty($atts['acf']) ) {
157 - $form = str_replace( '[PASSSTER_ACF]', ' data-acf="' . esc_html( $atts['acf'] ) . '"', $form );
206 + if ( !empty( $atts['acf'] ) ) {
207 + $form = str_replace( '[PASSSTER_ACF]', ' data-acf="' . esc_url( $atts['acf'] ) . '"', $form );
158 208 } else {
159 209 $form = str_replace( '[PASSSTER_ACF]', '', $form );
160 210 }
161 -
162 211 return $form;
163 212 }
164 -
213 +
165 214 /**
166 215 * Filters the_content with Passster.
167 216 *
168 217 * @param string $content given content.
@@ -169,11 +218,28 @@
169 218 *
170 219 * @return string
171 220 * @throws Exception
172 221 */
173 - public function filter_the_content( string $content ) : string
174 - {
222 + public function filter_the_content( string $content ) : string {
175 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 + }
176 242 $activate_protection = get_post_meta( $post_id, 'passster_activate_protection', true );
177 243 // user restriction.
178 244 $user_restriction_type = get_post_meta( $post_id, 'passster_user_restriction_type', true );
179 245 $user_restriction = get_post_meta( $post_id, 'passster_user_restriction', true );
@@ -179,12 +245,13 @@
179 245 $user_restriction = get_post_meta( $post_id, 'passster_user_restriction', true );
180 246 // Redirection.
181 247 $redirection = get_post_meta( $post_id, 'passster_redirect_url', true );
182 248 // texts.
183 - $headline = get_post_meta( $post_id, 'passster_headline', true );
184 - $instruction = get_post_meta( $post_id, 'passster_instruction', true );
185 - $placeholder = get_post_meta( $post_id, 'passster_placeholder', true );
186 - $button = get_post_meta( $post_id, 'passster_button', true );
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 ) : '' );
187 254 $id = get_post_meta( $post_id, 'passster_id', true );
188 255 if ( !$activate_protection ) {
189 256 return $content;
190 257 }
@@ -193,24 +260,24 @@
193 260 $shortcode = '';
194 261 $password = get_post_meta( $post_id, 'passster_password', true );
195 262 $atts['password'] = $password;
196 263 $shortcode = '[passster password="' . $password . '" protection="full" ';
197 - if ( !empty($redirection) ) {
264 + if ( !empty( $redirection ) ) {
198 265 $shortcode .= 'redirect="' . $redirection . '" ';
199 266 }
200 - if ( !empty($headline) ) {
267 + if ( !empty( $headline ) ) {
201 268 $shortcode .= 'headline="' . $headline . '" ';
202 269 }
203 - if ( !empty($instruction) ) {
204 - $shortcode .= 'instruction="' . $instruction . '" ';
270 + if ( !empty( $instruction ) ) {
271 + $shortcode .= 'instruction="' . base64_encode( $instruction ) . '" ';
205 272 }
206 - if ( !empty($placeholder) ) {
273 + if ( !empty( $placeholder ) ) {
207 274 $shortcode .= 'placeholder="' . $placeholder . '" ';
208 275 }
209 - if ( !empty($button) ) {
276 + if ( !empty( $button ) ) {
210 277 $shortcode .= 'button="' . $button . '" ';
211 278 }
212 - if ( !empty($id) ) {
279 + if ( !empty( $id ) ) {
213 280 $shortcode .= 'id="' . $id . '" ';
214 281 }
215 282 $shortcode .= ']{content}[/passster]';
216 283 // check if valid before restrict anything.
@@ -219,11 +286,17 @@
219 286 return $content;
220 287 }
221 288 // replace placeholder with content.
222 289 $shortcode = str_replace( '{content}', $content, $shortcode );
223 - return do_shortcode( $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;
224 297 }
225 -
298 +
226 299 /**
227 300 * Redirect if global protection is activated and no password is set.
228 301 *
229 302 * @return void
@@ -228,18 +301,22 @@
228 301 *
229 302 * @return void
230 303 * @throws Exception
231 304 */
232 - public function check_global_proctection()
233 - {
305 + public function check_global_proctection() {
234 306 $options = get_option( 'passster' );
235 - // Allow Elementor editing the page.
236 - if ( isset( $_GET['elementor-preview'] ) ) {
307 + $post_id = get_queried_object_id();
308 + if ( !$post_id ) {
237 309 return;
238 310 }
311 + // Allow Elementor editing the page.
312 + $elementor_preview = filter_input( INPUT_GET, 'elementor-preview', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
239 313 // Allow Live Canvas Editor.
240 - if ( isset( $_GET['lc_action_launch_editing'] ) ) {
241 - return;
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 + }
242 319 }
243 320 if ( !isset( $options['global_protection_id'] ) ) {
244 321 return;
245 322 }
@@ -246,15 +323,14 @@
246 323 if ( !isset( $options['activate_global_protection'] ) ) {
247 324 return;
248 325 }
249 326 // Build $atts array based on protection settings.
250 - $post_id = $options['global_protection_id'];
251 - $is_active = $options['activate_global_protection'];
327 + $post_id = esc_html( $options['global_protection_id'] );
328 + $is_active = esc_html( $options['activate_global_protection'] );
252 329 $atts = array();
253 330 $password = get_post_meta( $post_id, 'passster_password', true );
254 - $atts['password'] = esc_html( $password );
255 - if ( !empty($post_id) ) {
256 -
331 + $atts['password'] = $password;
332 + if ( !empty( $post_id ) ) {
257 333 if ( $is_active ) {
258 334 if ( is_page( $post_id ) || is_single( $post_id ) ) {
259 335 return;
260 336 }
@@ -266,17 +342,104 @@
266 342 }
267 343 }
268 344 }
269 345 // Check if cookie is set.
270 -
271 - if ( empty($_COOKIE['passster']) || !PS_Conditional::is_valid( $atts ) ) {
346 + $cookie = esc_html( $_COOKIE['passster'] );
347 + if ( !PS_Conditional::is_valid( $atts ) ) {
272 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 + }
273 353 wp_redirect( esc_url_raw( $global_protection_url ) );
274 354 exit;
275 355 }
276 -
277 356 }
278 -
279 357 }
280 358 }
281 359
282 -}
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 +}