Plugin Directory

source: contact-form-7/tags/5.9.6/includes/config-validator/validator.php

Last change on this file was 3103414, checked in by takayukister, 3 weeks ago

Merge changes on GitHub https://github.com/rocklobster-in/contact-form-7/

File size: 8.1 KB
Line 
1<?php
2
3require_once path_join( __DIR__, 'form.php' );
4require_once path_join( __DIR__, 'mail.php' );
5require_once path_join( __DIR__, 'messages.php' );
6require_once path_join( __DIR__, 'additional-settings.php' );
7require_once path_join( __DIR__, 'actions.php' );
8
9
10/**
11 * Configuration validator.
12 *
13 * @link https://contactform7.com/configuration-errors/
14 */
15class WPCF7_ConfigValidator {
16
17        /**
18         * The plugin version in which important updates happened last time.
19         */
20        const last_important_update = '5.8.1';
21
22        const error_codes = array(
23                'maybe_empty',
24                'invalid_mailbox_syntax',
25                'email_not_in_site_domain',
26                'html_in_message',
27                'multiple_controls_in_label',
28                'file_not_found',
29                'unavailable_names',
30                'invalid_mail_header',
31                'deprecated_settings',
32                'file_not_in_content_dir',
33                'unavailable_html_elements',
34                'attachments_overweight',
35                'dots_in_names',
36                'colons_in_names',
37                'upload_filesize_overlimit',
38                'unsafe_email_without_protection',
39        );
40
41        use WPCF7_ConfigValidator_Form;
42        use WPCF7_ConfigValidator_Mail;
43        use WPCF7_ConfigValidator_Messages;
44        use WPCF7_ConfigValidator_AdditionalSettings;
45
46        private $contact_form;
47        private $errors = array();
48        private $include;
49        private $exclude;
50
51
52        /**
53         * Returns a URL linking to the documentation page for the error type.
54         */
55        public static function get_doc_link( $child_page = '' ) {
56                $url = __( 'https://contactform7.com/configuration-errors/',
57                        'contact-form-7'
58                );
59
60                if ( '' !== $child_page ) {
61                        $child_page = strtr( $child_page, '_', '-' );
62
63                        $url = sprintf( '%s/%s', untrailingslashit( $url ), $child_page );
64                }
65
66                return esc_url( $url );
67        }
68
69
70        /**
71         * Constructor.
72         */
73        public function __construct( WPCF7_ContactForm $contact_form, $options = '' ) {
74                $options = wp_parse_args( $options, array(
75                        'include' => null,
76                        'exclude' => null,
77                ) );
78
79                $this->contact_form = $contact_form;
80
81                if ( isset( $options['include'] ) ) {
82                        $this->include = (array) $options['include'];
83                }
84
85                if ( isset( $options['exclude'] ) ) {
86                        $this->exclude = (array) $options['exclude'];
87                }
88        }
89
90
91        /**
92         * Returns the contact form object that is tied to this validator.
93         */
94        public function contact_form() {
95                return $this->contact_form;
96        }
97
98
99        /**
100         * Returns true if no error has been detected.
101         */
102        public function is_valid() {
103                return ! $this->count_errors();
104        }
105
106
107        /**
108         * Returns true if the given error code is supported by this instance.
109         */
110        public function supports( $error_code ) {
111                if ( isset( $this->include ) ) {
112                        $supported_codes = array_intersect( self::error_codes, $this->include );
113                } else {
114                        $supported_codes = self::error_codes;
115                }
116
117                if ( isset( $this->exclude ) ) {
118                        $supported_codes = array_diff( $supported_codes, $this->exclude );
119                }
120
121                return in_array( $error_code, $supported_codes, true );
122        }
123
124
125        /**
126         * Counts detected errors.
127         */
128        public function count_errors( $options = '' ) {
129                $options = wp_parse_args( $options, array(
130                        'section' => '',
131                        'code' => '',
132                ) );
133
134                $count = 0;
135
136                foreach ( $this->errors as $key => $errors ) {
137                        if ( preg_match( '/^mail_[0-9]+\.(.*)$/', $key, $matches ) ) {
138                                $key = sprintf( 'mail.%s', $matches[1] );
139                        }
140
141                        if ( $options['section']
142                        and $key !== $options['section']
143                        and preg_replace( '/\..*$/', '', $key, 1 ) !== $options['section'] ) {
144                                continue;
145                        }
146
147                        foreach ( $errors as $error ) {
148                                if ( empty( $error ) ) {
149                                        continue;
150                                }
151
152                                if ( $options['code'] and $error['code'] !== $options['code'] ) {
153                                        continue;
154                                }
155
156                                $count += 1;
157                        }
158                }
159
160                return $count;
161        }
162
163
164        /**
165         * Collects messages for detected errors.
166         */
167        public function collect_error_messages() {
168                $error_messages = array();
169
170                foreach ( $this->errors as $section => $errors ) {
171                        $error_messages[$section] = array();
172
173                        foreach ( $errors as $error ) {
174                                if ( empty( $error['args']['message'] ) ) {
175                                        $message = $this->get_default_message( $error['code'] );
176                                } elseif ( empty( $error['args']['params'] ) ) {
177                                        $message = $error['args']['message'];
178                                } else {
179                                        $message = $this->build_message(
180                                                $error['args']['message'],
181                                                $error['args']['params']
182                                        );
183                                }
184
185                                $link = '';
186
187                                if ( ! empty( $error['args']['link'] ) ) {
188                                        $link = $error['args']['link'];
189                                }
190
191                                $error_messages[$section][] = array(
192                                        'message' => $message,
193                                        'link' => esc_url( $link ),
194                                );
195                        }
196                }
197
198                return $error_messages;
199        }
200
201
202        /**
203         * Builds an error message by replacing placeholders.
204         */
205        public function build_message( $message, $params = '' ) {
206                $params = wp_parse_args( $params, array() );
207
208                foreach ( $params as $key => $val ) {
209                        if ( ! preg_match( '/^[0-9A-Za-z_]+$/', $key ) ) { // invalid key
210                                continue;
211                        }
212
213                        $placeholder = '%' . $key . '%';
214
215                        if ( false !== stripos( $message, $placeholder ) ) {
216                                $message = str_ireplace( $placeholder, $val, $message );
217                        }
218                }
219
220                return $message;
221        }
222
223
224        /**
225         * Returns a default message that is used when the message for the error
226         * is not specified.
227         */
228        public function get_default_message( $code = '' ) {
229                return __( "Configuration error is detected.", 'contact-form-7' );
230        }
231
232
233        /**
234         * Returns true if the specified section has the specified error.
235         *
236         * @param string $section The section where the error detected.
237         * @param string $code The unique code of the error.
238         */
239        public function has_error( $section, $code ) {
240                if ( empty( $this->errors[$section] ) ) {
241                        return false;
242                }
243
244                foreach ( (array) $this->errors[$section] as $error ) {
245                        if ( isset( $error['code'] ) and $error['code'] === $code ) {
246                                return true;
247                        }
248                }
249
250                return false;
251        }
252
253
254        /**
255         * Adds a validation error.
256         *
257         * @param string $section The section where the error detected.
258         * @param string $code The unique code of the error.
259         * @param string|array $args Optional options for the error.
260         */
261        public function add_error( $section, $code, $args = '' ) {
262                $args = wp_parse_args( $args, array(
263                        'message' => '',
264                        'params' => array(),
265                ) );
266
267                $available_error_codes = (array) apply_filters(
268                        'wpcf7_config_validator_available_error_codes',
269                        self::error_codes,
270                        $this->contact_form
271                );
272
273                if ( ! in_array( $code, $available_error_codes, true ) ) {
274                        return false;
275                }
276
277                if ( ! isset( $args['link'] ) ) {
278                        $args['link'] = self::get_doc_link( $code );
279                }
280
281                if ( ! isset( $this->errors[$section] ) ) {
282                        $this->errors[$section] = array();
283                }
284
285                $this->errors[$section][] = array(
286                        'code' => $code,
287                        'args' => $args,
288                );
289
290                return true;
291        }
292
293
294        /**
295         * Removes an error.
296         *
297         * @param string $section The section where the error detected.
298         * @param string $code The unique code of the error.
299         */
300        public function remove_error( $section, $code ) {
301                if ( empty( $this->errors[$section] ) ) {
302                        return;
303                }
304
305                foreach ( (array) $this->errors[$section] as $key => $error ) {
306                        if ( isset( $error['code'] ) and $error['code'] === $code ) {
307                                unset( $this->errors[$section][$key] );
308                        }
309                }
310
311                if ( empty( $this->errors[$section] ) ) {
312                        unset( $this->errors[$section] );
313                }
314        }
315
316
317        /**
318         * The main validation runner.
319         *
320         * @return bool True if there is no error detected.
321         */
322        public function validate() {
323                $this->validate_form();
324                $this->validate_mail( 'mail' );
325                $this->validate_mail( 'mail_2' );
326                $this->validate_messages();
327                $this->validate_additional_settings();
328
329                do_action( 'wpcf7_config_validator_validate', $this );
330
331                return $this->is_valid();
332        }
333
334
335        /**
336         * Saves detected errors as a post meta data.
337         */
338        public function save() {
339                if ( $this->contact_form->initial() ) {
340                        return;
341                }
342
343                delete_post_meta( $this->contact_form->id(), '_config_validation' );
344
345                if ( $this->errors ) {
346                        update_post_meta(
347                                $this->contact_form->id(), '_config_validation', $this->errors
348                        );
349                }
350        }
351
352
353        /**
354         * Restore errors from the database.
355         */
356        public function restore() {
357                $config_errors = get_post_meta(
358                        $this->contact_form->id(), '_config_validation', true
359                );
360
361                foreach ( (array) $config_errors as $section => $errors ) {
362                        if ( empty( $errors ) ) {
363                                continue;
364                        }
365
366                        foreach ( (array) $errors as $error ) {
367                                if ( ! empty( $error['code'] ) ) {
368                                        $code = $error['code'];
369                                        $args = isset( $error['args'] ) ? $error['args'] : '';
370                                        $this->add_error( $section, $code, $args );
371                                }
372                        }
373                }
374        }
375
376}
Note: See TracBrowser for help on using the repository browser.