PluginProbe ʕ •ᴥ•ʔ
SureForms – Drag & Drop Contact Form & Form Builder, Payment Form, Survey, Quiz & Calculator / 2.12.1
SureForms – Drag & Drop Contact Form & Form Builder, Payment Form, Survey, Quiz & Calculator v2.12.1
2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8 0.0.9 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.1.2 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.12.3 1.13.0 1.13.1 1.13.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.8.0 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.0 2.5.2 2.6.0
sureforms / inc / form-restriction.php
sureforms / inc Last commit date
abilities 2 weeks ago admin 1 month ago ai-form-builder 2 weeks ago blocks 1 month ago compatibility 3 weeks ago database 3 weeks ago email 3 months ago fields 3 weeks ago global-settings 2 weeks ago lib 2 weeks ago migrator 3 weeks ago page-builders 3 weeks ago payments 2 weeks ago single-form-settings 1 month ago traits 1 month ago activator.php 1 year ago admin-ajax.php 3 weeks ago background-process.php 8 months ago create-new-form.php 2 months ago duplicate-form.php 1 month ago entries.php 3 weeks ago events-scheduler.php 2 years ago export.php 1 month ago field-validation.php 2 weeks ago form-restriction.php 1 month ago form-styling.php 3 months ago form-submit.php 3 weeks ago forms-data.php 3 months ago frontend-assets.php 2 weeks ago generate-form-markup.php 3 weeks ago gutenberg-hooks.php 1 month ago helper.php 3 weeks ago learn.php 3 months ago onboarding.php 1 month ago post-types.php 1 month ago rest-api.php 2 weeks ago smart-tags.php 2 months ago submit-token.php 3 months ago translatable.php 2 weeks ago updater-callbacks.php 1 year ago updater.php 1 year ago
form-restriction.php
288 lines
1 <?php
2 /**
3 * Create new Form with Template and return the form ID.
4 *
5 * @package sureforms.
6 * @since 1.10.1
7 */
8
9 namespace SRFM\Inc;
10
11 use SRFM\Inc\Compatibility\Multilingual\String_Translator;
12 use SRFM\Inc\Database\Tables\Entries;
13 use SRFM\Inc\Traits\Get_Instance;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Create New Form.
21 *
22 * @since 1.10.1
23 */
24 class Form_Restriction {
25 use Get_Instance;
26
27 /**
28 * Get the restriction settings for a given form.
29 *
30 * @param int $form_id The ID of the form.
31 * @since 1.10.1
32 * @return array Associative array of restriction settings or empty array if invalid.
33 */
34 public static function get_form_restriction_setting( $form_id ) {
35 // Validate the form ID. Must be numeric and non-empty.
36 if ( empty( $form_id ) || ! is_int( $form_id ) ) {
37 return [];
38 }
39
40 // Get the raw restriction meta.
41 $form_restriction_meta = get_post_meta( $form_id, '_srfm_form_restriction', true );
42
43 if ( empty( $form_restriction_meta ) || ! is_string( $form_restriction_meta ) ) {
44 return [];
45 }
46
47 // Decode the meta to an array.
48 $form_restriction = json_decode( $form_restriction_meta, true );
49
50 // Ensure it's a valid array.
51 return is_array( $form_restriction ) ? $form_restriction : [];
52 }
53
54 /**
55 * Check if the form has reached the entry limit.
56 *
57 * @param int $form_id The ID of the form.
58 * @since 1.10.1
59 * @return bool True if form is restricted, false otherwise.
60 */
61 public static function is_form_restricted( $form_id ) {
62
63 if ( empty( $form_id ) || ! is_int( $form_id ) ) {
64 return false; // Invalid form ID.
65 }
66
67 // Check for instant fom preview mode.
68 $srfm_live_mode_data = Helper::get_instant_form_live_data();
69
70 // Skip check in live mode.
71 if (
72 ! empty( $srfm_live_mode_data ) &&
73 is_array( $srfm_live_mode_data ) &&
74 isset( $srfm_live_mode_data['live_mode'] )
75 ) {
76 return false; // Skip check in live mode.
77 }
78
79 // Get parsed restriction settings.
80 $form_restriction = self::get_form_restriction_setting( $form_id );
81
82 // If the form restriction is empty or not an array, or if the status is not set, return false.
83 if ( empty( $form_restriction ) || ! is_array( $form_restriction ) || empty( $form_restriction['status'] ) ) {
84 // Check for form scheduling even if entry restriction is not enabled.
85 $is_outside_schedule = self::is_form_outside_schedule( $form_restriction );
86 return apply_filters( 'srfm_is_form_restricted', $is_outside_schedule, $form_id, $form_restriction, false, false, $is_outside_schedule );
87 }
88
89 $has_entries_limit_reached = self::has_entries_limit_reached( $form_id, $form_restriction );
90 $scheduling_state = self::get_form_scheduling_state( $form_restriction );
91 $is_outside_schedule = 'not_started' === $scheduling_state || 'ended' === $scheduling_state;
92
93 $conversational_form = get_post_meta( $form_id, '_srfm_conversational_form', true );
94 $is_conversational_form_enabled = is_array( $conversational_form ) && isset( $conversational_form['is_cf_enabled'] ) ? $conversational_form['is_cf_enabled'] : false;
95 if ( ( $has_entries_limit_reached || $is_outside_schedule ) && $is_conversational_form_enabled ) {
96 add_filter( 'srfm_show_conversational_form_footer', '__return_false' );
97 }
98
99 /**
100 * If the form has reached the entries limit or is outside schedule, return true.
101 *
102 * @since 1.10.1
103 */
104 return apply_filters(
105 'srfm_is_form_restricted',
106 $has_entries_limit_reached || $is_outside_schedule,
107 $form_id,
108 $form_restriction,
109 $has_entries_limit_reached,
110 false, // Deprecated: $has_time_limit_reached - now handled by scheduling.
111 $is_outside_schedule
112 );
113 }
114
115 /**
116 * Check if the entries limit has been reached for a given form.
117 *
118 * @param int $form_id The ID of the form.
119 * @param array<string, mixed> $form_restriction The form restriction settings.
120 * @since 1.10.1
121 * @return bool True if the entries limit is reached, false otherwise.
122 */
123 public static function has_entries_limit_reached( $form_id, $form_restriction = [] ) {
124
125 if ( ! isset( $form_restriction['maxEntries'] ) || ! is_int( $form_restriction['maxEntries'] ) ) {
126 return false; // Invalid form ID or restriction settings.
127 }
128
129 $max_entries = $form_restriction['maxEntries'];
130 $entries_count = Entries::get_total_entries_by_status( 'all', $form_id );
131
132 if ( ! is_int( $entries_count ) ) {
133 $entries_count = 0; // Ensure entries count is a non-negative integer.
134 }
135
136 /**
137 * Filter the count of entries used to evaluate the Maximum Number of Entries
138 * cap. Allows extensions (e.g. SureForms Pro's Recurring Entry Limit) to
139 * substitute a window-scoped count — entries since the start of today /
140 * the current week / month / year — in place of the lifetime count.
141 *
142 * Returning a value greater than `$entries_count` will trip the cap sooner;
143 * returning a smaller value will defer it. Non-integer return values are
144 * coerced back to a non-negative integer.
145 *
146 * @param int $entries_count Lifetime entry count for the form.
147 * @param int $form_id The ID of the form.
148 * @param array<string, mixed> $form_restriction The form restriction settings.
149 * @since 2.8.2
150 */
151 $entries_count = apply_filters( 'srfm_form_restriction_entries_count', $entries_count, $form_id, $form_restriction );
152
153 // Always coerce to a non-negative integer — covers both non-int returns
154 // from a misbehaving extension AND negative-int returns that would
155 // otherwise silently disable the cap (e.g. -5 >= 100 is false).
156 $entries_count = max( 0, (int) $entries_count );
157
158 return $entries_count >= $max_entries;
159 }
160
161 /**
162 * Check if the form is outside its scheduled time period.
163 *
164 * @param array<string, mixed> $form_restriction The form restriction settings.
165 * @since 2.4.0
166 * @return bool True if form is outside schedule, false otherwise.
167 */
168 public static function is_form_outside_schedule( $form_restriction ) {
169 $scheduling_state = self::get_form_scheduling_state( $form_restriction );
170 return 'not_started' === $scheduling_state || 'ended' === $scheduling_state;
171 }
172
173 /**
174 * Get the appropriate restriction message based on scheduling state.
175 *
176 * @param string $scheduling_state The scheduling state ('not_started', 'ended', 'active', or 'disabled').
177 * @param array<string, mixed> $form_restriction The form restriction settings.
178 * @since 2.4.0
179 * @return string The appropriate restriction message.
180 */
181 public static function get_restriction_message_by_state( $scheduling_state, $form_restriction ) {
182 if ( 'not_started' === $scheduling_state ) {
183 $message = $form_restriction['schedulingNotStartedMessage'] ?? __( 'This form is not yet available. Check back after the scheduled start time.', 'sureforms' );
184 return is_string( $message ) ? $message : __( 'This form is not yet available. Check back after the scheduled start time.', 'sureforms' );
185 }
186
187 if ( 'ended' === $scheduling_state ) {
188 $message = $form_restriction['schedulingEndedMessage'] ?? __( 'This form is no longer accepting submissions. The submission period has ended.', 'sureforms' );
189 return is_string( $message ) ? $message : __( 'This form is no longer accepting submissions. The submission period has ended.', 'sureforms' );
190 }
191
192 // Default to entry limit message.
193 $message = $form_restriction['message'] ?? Translatable::get_default_form_restriction_message();
194 return is_string( $message ) ? $message : Translatable::get_default_form_restriction_message();
195 }
196
197 /**
198 * Get the scheduling state for a form.
199 *
200 * @param array<string, mixed> $form_restriction The form restriction settings.
201 * @since 2.4.0
202 * @return string 'not_started', 'ended', 'active', or 'disabled'.
203 */
204 public static function get_form_scheduling_state( $form_restriction ) {
205 $scheduling_status = $form_restriction['schedulingStatus'] ?? false;
206
207 // Start date/time.
208 $start_date = $form_restriction['startDate'] ?? '';
209 $start_hours = Helper::get_string_value( $form_restriction['startHours'] ?? '12' );
210 $start_minutes = Helper::get_string_value( $form_restriction['startMinutes'] ?? '00' );
211 $start_meridiem = Helper::get_string_value( $form_restriction['startMeridiem'] ?? 'AM' );
212
213 // End date/time.
214 $end_date = $form_restriction['date'] ?? '';
215 $end_hours = Helper::get_string_value( $form_restriction['hours'] ?? '12' );
216 $end_minutes = Helper::get_string_value( $form_restriction['minutes'] ?? '00' );
217 $end_meridiem = Helper::get_string_value( $form_restriction['meridiem'] ?? 'PM' );
218
219 $dt = new \DateTime( 'now', wp_timezone() );
220 $current_timestamp = $dt->getTimestamp();
221
222 // Check if before start time (only if scheduling is enabled).
223 if ( $scheduling_status && ! empty( $start_date ) && is_string( $start_date ) ) {
224 $start_timestamp = Helper::get_timestamp_from_string( $start_date, $start_hours, $start_minutes, $start_meridiem );
225
226 if ( false !== $start_timestamp && is_int( $start_timestamp ) && $current_timestamp < $start_timestamp ) {
227 return 'not_started';
228 }
229 }
230
231 // Check if after end time (works for both scheduling and simple time limit).
232 if ( $scheduling_status && ! empty( $end_date ) && is_string( $end_date ) ) {
233 $end_timestamp = Helper::get_timestamp_from_string( $end_date, $end_hours, $end_minutes, $end_meridiem );
234
235 if ( false !== $end_timestamp && is_int( $end_timestamp ) && $current_timestamp > $end_timestamp ) {
236 return 'ended';
237 }
238 }
239
240 // If scheduling is disabled but we haven't passed the end date, return 'disabled'.
241 // If scheduling is enabled and we're within the window, return 'active'.
242 return $scheduling_status ? 'active' : 'disabled';
243 }
244
245 /**
246 * Display the form restriction message.
247 *
248 * @param int $form_id The ID of the form.
249 * @since 1.10.1
250 * @return string|false The HTML markup for the restriction message or false if no restriction is set.
251 */
252 public static function display_form_restriction_message( $form_id ) {
253 // Get parsed restriction settings.
254 $form_restriction = self::get_form_restriction_setting( $form_id );
255
256 // Get the scheduling state and appropriate message.
257 $scheduling_state = self::get_form_scheduling_state( $form_restriction );
258 $form_restriction_message = self::get_restriction_message_by_state( $scheduling_state, $form_restriction );
259
260 // Translate the restriction message via the active multilingual provider
261 // (no-op when no WPML/Polylang is installed).
262 $form_restriction_message = String_Translator::get_instance()->translate_restriction_message( (int) $form_id, $form_restriction_message );
263
264 $form_restriction_message = apply_filters( 'srfm_form_restriction_message', $form_restriction_message, $form_id, $form_restriction );
265
266 ob_start();
267 ?>
268 <div class="srfm-form-container srfm-form-restriction-wrapper">
269 <div class="srfm-form-restriction-message" role="alert" aria-live="assertive">
270 <span class="srfm-form-restriction-icon" aria-hidden="true">
271 <?php
272 echo wp_kses(
273 Helper::fetch_svg( 'instant-form-warning', 'srfm-form-restriction-icon', 'aria-hidden="true"' ),
274 Helper::$allowed_tags_svg
275 );
276 ?>
277 </span>
278 <p class="srfm-form-restriction-text">
279 <?php echo esc_html( $form_restriction_message ); ?>
280 </p>
281 </div>
282 </div>
283 <?php
284 return ob_get_clean();
285 }
286
287 }
288