PluginProbe
Quill Forms | Conversational Multi Step Forms, Surveys & quizzes / trunk
Quill Forms | Conversational Multi Step Forms, Surveys & quizzes vtrunk
5.7.3 5.7.2 5.7.1 1.8.1 1.8.10 1.8.11 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 2.0.0 2.1.0 2.10.0 2.11.0 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 All 146 releases
quillforms / includes / functions.php

functions.php in Quill Forms | Conversational Multi Step Forms, Surveys & quizzes trunk, at includes/functions.php

342 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Some helper functions.
4 *
5 * @since 1.0.0
6 * @package QuillForms
7 */
8
9 use QuillForms\Interfaces\Logger_Interface;
10 use QuillForms\Logger;
11 use QuillForms\Settings;
12
13 defined( 'ABSPATH' ) || exit;
14
15
16 /**
17 * Helper function to sanitize a string from user input or from the db
18 * Forked from WordPress core
19 *
20 * @see https://developer.wordpress.org/reference/functions/_sanitize_text_fields/
21 * It is marked as a private function in WordPress.
22 * so we copied its implementation here in case it has been removed in any future WordPress version
23 *
24 * @since 1.0.0
25 *
26 * @param string $str String to deeply sanitize.
27 * @param bool $keep_newlines Whether to keep newlines. Default: false.
28 *
29 * @return string Sanitized string, or empty string if not a string provided.
30 */
31 function quillforms_sanitize_text_fields( $str, $keep_newlines = false ) {
32 if ( is_object( $str ) || is_array( $str ) ) {
33 return '';
34 }
35
36 $str = (string) $str;
37
38 $filtered = wp_check_invalid_utf8( $str );
39
40 if ( strpos( $filtered, '<' ) !== false ) {
41 $filtered = wp_pre_kses_less_than( $filtered );
42 // This will strip extra whitespace for us.
43 $filtered = wp_strip_all_tags( $filtered, false );
44
45 // Use HTML entities in a special case to make sure no later
46 // newline stripping stage could lead to a functional tag.
47 $filtered = str_replace( "<\n", "&lt;\n", $filtered );
48 }
49
50 if ( ! $keep_newlines ) {
51 $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
52 }
53 $filtered = trim( $filtered );
54
55 $found = false;
56 while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
57 $filtered = str_replace( $match[0], '', $filtered );
58 $found = true;
59 }
60
61 if ( $found ) {
62 // Strip out the whitespace that may now exist after removing the octets.
63 $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
64 }
65
66 return $filtered;
67 }
68
69 /**
70 * Deeply sanitize the string, preserve newlines if needed.
71 * Prevent maliciously prepared strings from containing HTML tags.
72 * Heavily inspired by wpforms
73 *
74 * @since 1.0.0
75 *
76 * @param string $string String to deeply sanitize.
77 * @param bool $keep_newlines Whether to keep newlines. Default: false.
78 *
79 * @return string Sanitized string, or empty string if not a string provided.
80 */
81 function quillforms_sanitize_text_deeply( $string, $keep_newlines = false ) {
82
83 if ( is_object( $string ) || is_array( $string ) ) {
84 return '';
85 }
86
87 $string = (string) $string;
88 $keep_newlines = (bool) $keep_newlines;
89
90 $new_value = quillforms_sanitize_text_fields( $string, $keep_newlines );
91
92 if ( strlen( $new_value ) !== strlen( $string ) ) {
93 $new_value = quillforms_sanitize_text_deeply( $new_value, $keep_newlines );
94 }
95
96 return $new_value;
97 }
98
99 /**
100 * Implode array without including blank values.
101 *
102 * @since 1.0.0
103 *
104 * @param string $separator The separator.
105 * @param array $array The array to be imploded.
106 *
107 * @return string The imploded array
108 */
109 function quillforms_implode_non_blank( $separator, $array ) {
110
111 if ( ! is_array( $array ) ) {
112 return '';
113 }
114
115 $ary = array();
116 foreach ( $array as $item ) {
117 if ( ! empty( $item ) || '0' !== strval( $item ) ) {
118 $ary[] = $item;
119 }
120 }
121
122 return implode( $separator, $ary );
123 }
124
125 /**
126 * Decode special characters, both alpha- (<) and numeric-based (').
127 * Sanitize recursively, preserve new lines.
128 * Handle all the possible mixed variations of < and `&lt;` that can be processed into tags.
129 * Heavily inspired by wpforms
130 *
131 * @since 1.0.0
132 *
133 * @param string $string Raw string to decode.
134 *
135 * @return string
136 */
137 function quillforms_decode_string( $string ) {
138
139 if ( ! is_string( $string ) ) {
140 return $string;
141 }
142
143 /*
144 * Sanitization should be done first, so tags are stripped and < is converted to &lt; etc.
145 * This iteration may do nothing when the string already comes with &lt; and &gt; only.
146 */
147 $string = quillforms_sanitize_text_deeply( $string, true );
148
149 // Now we need to convert the string without tags: &lt; back to < (same for quotes).
150 $string = wp_kses_decode_entities( html_entity_decode( $string, ENT_QUOTES ) );
151
152 // And now we need to sanitize AGAIN, to avoid unwanted tags that appeared after decoding.
153 return quillforms_sanitize_text_deeply( $string, true );
154 }
155
156 /**
157 * Clean variables using sanitize_text_field. Arrays are cleaned recursively.
158 * Non-scalar values are ignored.
159 * This function is forked from Woocommerce.
160 *
161 * @since 1.0.0
162 *
163 * @param string|array $var Data to sanitize.
164 *
165 * @return string|array
166 */
167 function quillforms_clean( $var ) {
168 if ( is_array( $var ) ) {
169 return array_map( 'quillforms_clean', $var );
170 } else {
171 return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
172 }
173 }
174
175
176 /**
177 * Get a shared logger instance.
178 * This function is forked from Woocommerce
179 *
180 * Use the quillforms_logging_class filter to change the logging class. You may provide one of the following:
181 * - a class name which will be instantiated as `new $class` with no arguments
182 * - an instance which will be used directly as the logger
183 * In either case, the class or instance *must* implement Logger_Interface.
184 *
185 * @since 1.0.0
186 * @see Logger_Interface
187 *
188 * @return Logger
189 */
190 function quillforms_get_logger() {
191 static $logger = null;
192
193 $class = apply_filters( 'quillforms_logging_class', Logger::class );
194
195 if ( null !== $logger && is_string( $class ) && is_a( $logger, $class ) ) {
196 return $logger;
197 }
198
199 $implements = class_implements( $class );
200
201 if ( is_array( $implements ) && in_array( Logger_Interface::class, $implements, true ) ) {
202 $threshold = Settings::get( 'log_level', 'info' );
203 $logger = is_object( $class ) ? $class : new $class( null, $threshold );
204 } else {
205 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- _doing_it_wrong handles escaping internally.
206 _doing_it_wrong(
207 __FUNCTION__,
208 sprintf(
209 /* translators: 1: class name 2: quillforms_logging_class 3: Logger_Interface */
210 __( 'The class %1$s provided by %2$s filter must implement %3$s.', 'quillforms' ),
211 '<code>' . esc_html( is_object( $class ) ? get_class( $class ) : $class ) . '</code>',
212 '<code>quillforms_logging_class</code>',
213 '<code>Logger_Interface</code>'
214 ),
215 '1.0.0'
216 );
217
218 $logger = is_a( $logger, Logger::class ) ? $logger : new Logger();
219 }
220
221 return $logger;
222 }
223
224 /**
225 * Trigger logging cleanup using the logging class.
226 *
227 * @since 1.0.0
228 */
229 function quillforms_cleanup_logs() {
230 $logger = quillforms_get_logger();
231
232 if ( is_callable( array( $logger, 'clear_expired_logs' ) ) ) {
233 $logger->clear_expired_logs();
234 }
235 }
236 add_action( 'quillforms_cleanup_logs', 'quillforms_cleanup_logs' );
237
238 /**
239 * Get client ip address
240 * https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/includes/misc-functions.php
241 *
242 * @since 1.19.0
243 *
244 * @return string
245 */
246 function quillforms_get_client_ip() {
247 $ip = false;
248
249 if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
250 // Check ip from share internet.
251 $ip = filter_var( wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ), FILTER_VALIDATE_IP );
252 } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
253 // To check ip is pass from proxy.
254 // Can include more than 1 ip, first is the public one.
255 // WPCS: sanitization ok.
256 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
257 $ips = explode( ',', wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
258 if ( is_array( $ips ) ) {
259 $ip = filter_var( $ips[0], FILTER_VALIDATE_IP );
260 }
261 } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
262 $ip = filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP );
263 }
264
265 $ip = false !== $ip ? $ip : '127.0.0.1';
266
267 // Fix potential CSV returned from $_SERVER variables.
268 $ip_array = explode( ',', $ip );
269 $ip_array = array_map( 'trim', $ip_array );
270
271 return apply_filters( 'quillforms_entry_meta_ip', $ip_array[0] );
272 }
273
274 /**
275 * Get client ip address hash
276 *
277 * @since 1.19.0
278 *
279 * @return string
280 */
281 function quillforms_get_client_ip_hash() {
282 return sha1( 'quillforms-' . quillforms_get_client_ip() );
283 }
284
285 /**
286 * Find array in arrays has specific key and value
287 *
288 * @since 1.13.0
289 *
290 * @param array[] $arrays Array of arrays.
291 * @param string $key Key.
292 * @param mixed $value Value.
293 * @return array|null
294 */
295 function quillforms_arrays_find( $arrays, $key, $value ) {
296 foreach ( $arrays as $array ) {
297 if ( $array[ $key ] === $value ) {
298 return $array;
299 }
300 }
301 return null;
302 }
303
304 /**
305 * Find object in objects has specific key and value
306 *
307 * @since 1.21.0
308 *
309 * @param object[] $objects Array of objects.
310 * @param string $key Key.
311 * @param mixed $value Value.
312 * @return object|null
313 */
314 function quillforms_objects_find( $objects, $key, $value ) {
315 foreach ( $objects as $object ) {
316 if ( $object->{$key} === $value ) {
317 return $object;
318 }
319 }
320 return null;
321 }
322
323
324 /**
325 * Js every equivalent for php
326 *
327 * @since @next
328 *
329 * @param array $arr The array to be checked.
330 * @param callable $predicate The predicate to be checked.
331 *
332 * @return bool
333 */
334 function quillforms_array_every(array $arr, callable $predicate) {
335 foreach ($arr as $e) {
336 if (!call_user_func($predicate, $e)) {
337 return false;
338 }
339 }
340
341 return true;
342 }