add_filter( 'map_meta_cap', 'wpcf7_map_meta_cap', 10, 4 ); function wpcf7_map_meta_cap( $caps, $cap, $user_id, $args ) { $meta_caps = array( 'wpcf7_edit_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY, 'wpcf7_edit_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY, 'wpcf7_read_contact_form' => WPCF7_ADMIN_READ_CAPABILITY, 'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY, 'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY, 'wpcf7_delete_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY, 'wpcf7_manage_integration' => 'manage_options', 'wpcf7_submit' => 'read', ); $meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps ); $caps = array_diff( $caps, array_keys( $meta_caps ) ); if ( isset( $meta_caps[$cap] ) ) { $caps[] = $meta_caps[$cap]; } return $caps; } /** * Returns path to a plugin file. * * @param string $path File path relative to the plugin root directory. * @return string Absolute file path. */ function wpcf7_plugin_path( $path = '' ) { return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) ); } /** * Returns the URL to a plugin file. * * @param string $path File path relative to the plugin root directory. * @return string URL. */ function wpcf7_plugin_url( $path = '' ) { $url = plugins_url( $path, WPCF7_PLUGIN ); if ( is_ssl() and 'http:' == substr( $url, 0, 5 ) ) { $url = 'https:' . substr( $url, 5 ); } return $url; } /** * Include a file under WPCF7_PLUGIN_MODULES_DIR. * * @param string $path File path relative to the module dir. * @return bool True on success, false on failure. */ function wpcf7_include_module_file( $path ) { $dir = WPCF7_PLUGIN_MODULES_DIR; if ( empty( $dir ) or ! is_dir( $dir ) ) { return false; } $path = path_join( $dir, ltrim( $path, '/' ) ); if ( file_exists( $path ) ) { include_once $path; return true; } return false; } /** * Retrieves uploads directory information. * * @param string|bool $type Optional. Type of output. Default false. * @return array|string Information about the upload directory. */ function wpcf7_upload_dir( $type = false ) { $uploads = wp_get_upload_dir(); $uploads = apply_filters( 'wpcf7_upload_dir', array( 'dir' => $uploads['basedir'], 'url' => $uploads['baseurl'], ) ); if ( 'dir' == $type ) { return $uploads['dir']; } if ( 'url' == $type ) { return $uploads['url']; } return $uploads; } /** * Verifies that a correct security nonce was used with time limit. * * @param string $nonce Nonce value that was used for verification. * @param string $action Optional. Context to what is taking place. * Default 'wp_rest'. * @return int|bool 1 if the nonce is generated between 0-12 hours ago, * 2 if the nonce is generated between 12-24 hours ago. * False if the nonce is invalid. */ function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) { return wp_verify_nonce( $nonce, $action ); } /** * Creates a cryptographic token tied to a specific action, user, user session, * and window of time. * * @param string $action Optional. Context to what is taking place. * Default 'wp_rest'. * @return string The token. */ function wpcf7_create_nonce( $action = 'wp_rest' ) { return wp_create_nonce( $action ); } /** * Converts multi-dimensional array to a flat array. * * @param mixed $input Array or item of array. * @return array Flatten array. */ function wpcf7_array_flatten( $input ) { if ( ! is_array( $input ) ) { return array( $input ); } $output = array(); foreach ( $input as $value ) { $output = array_merge( $output, wpcf7_array_flatten( $value ) ); } return $output; } /** * Excludes unset or blank text values from the given array. * * @param array $input The array. * @return array Array without blank text values. */ function wpcf7_exclude_blank( $input ) { $output = array_filter( $input, static function ( $i ) { return isset( $i ) && '' !== $i; } ); return array_values( $output ); } /** * Creates a comma-separated list from a multi-dimensional array. * * @param mixed $input Array or item of array. * @param string|array $args Optional. Output options. * @return string Comma-separated list. */ function wpcf7_flat_join( $input, $args = '' ) { $args = wp_parse_args( $args, array( 'separator' => ', ', ) ); $input = wpcf7_array_flatten( $input ); $output = array(); foreach ( (array) $input as $value ) { if ( is_scalar( $value ) ) { $output[] = trim( (string) $value ); } } return implode( $args['separator'], $output ); } /** * Returns true if HTML5 is supported. */ function wpcf7_support_html5() { return (bool) wpcf7_apply_filters_deprecated( 'wpcf7_support_html5', array( true ), '5.6', '' ); } /** * Returns true if HTML5 fallback is active. */ function wpcf7_support_html5_fallback() { return (bool) apply_filters( 'wpcf7_support_html5_fallback', false ); } /** * Returns true if the Really Simple CAPTCHA plugin is used for contact forms. */ function wpcf7_use_really_simple_captcha() { return apply_filters( 'wpcf7_use_really_simple_captcha', WPCF7_USE_REALLY_SIMPLE_CAPTCHA ); } /** * Returns true if config validation is active. */ function wpcf7_validate_configuration() { return apply_filters( 'wpcf7_validate_configuration', WPCF7_VALIDATE_CONFIGURATION ); } /** * Returns true if wpcf7_autop() is applied. */ function wpcf7_autop_or_not( $options = '' ) { $options = wp_parse_args( $options, array( 'for' => 'form', ) ); return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP, $options ); } /** * Returns true if JavaScript for this plugin is loaded. */ function wpcf7_load_js() { return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS ); } /** * Returns true if CSS for this plugin is loaded. */ function wpcf7_load_css() { return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS ); } /** * Builds an HTML anchor element. * * @param string $url Link URL. * @param string $anchor_text Anchor label text. * @param string|array $args Optional. Link options. * @return string Formatted anchor element. */ function wpcf7_link( $url, $anchor_text, $args = '' ) { $args = wp_parse_args( $args, array( 'id' => null, 'class' => null, ) ); $atts = array_merge( $args, array( 'href' => esc_url( $url ), ) ); return sprintf( '%2$s', wpcf7_format_atts( $atts ), esc_html( $anchor_text ) ); } /** * Returns the current request URL. */ function wpcf7_get_request_uri() { static $request_uri = ''; if ( empty( $request_uri ) ) { $request_uri = add_query_arg( array() ); } return sanitize_url( $request_uri ); } /** * Registers post types used for this plugin. */ function wpcf7_register_post_types() { if ( class_exists( 'WPCF7_ContactForm' ) ) { WPCF7_ContactForm::register_post_type(); return true; } else { return false; } } /** * Returns the version string of this plugin. * * @param string|array $args Optional. Output options. * @return string Version string. */ function wpcf7_version( $args = '' ) { $defaults = array( 'limit' => -1, 'only_major' => false, ); $args = wp_parse_args( $args, $defaults ); if ( $args['only_major'] ) { $args['limit'] = 2; } $args['limit'] = (int) $args['limit']; $ver = WPCF7_VERSION; $ver = strtr( $ver, '_-+', '...' ); $ver = preg_replace( '/[^0-9.]+/', ".$0.", $ver ); $ver = preg_replace( '/[.]+/', ".", $ver ); $ver = trim( $ver, '.' ); $ver = explode( '.', $ver ); if ( -1 < $args['limit'] ) { $ver = array_slice( $ver, 0, $args['limit'] ); } $ver = implode( '.', $ver ); return $ver; } /** * Returns array entries that match the given version. * * @param string $version The version to search for. * @param array $input Search target array. * @return array|bool Array of matched entries. False on failure. */ function wpcf7_version_grep( $version, array $input ) { $pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/'; return preg_grep( $pattern, $input ); } /** * Returns an enctype attribute value. * * @param string $enctype Enctype value. * @return string Enctype value. Empty if not a valid enctype. */ function wpcf7_enctype_value( $enctype ) { $enctype = trim( $enctype ); if ( empty( $enctype ) ) { return ''; } $valid_enctypes = array( 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain', ); if ( in_array( $enctype, $valid_enctypes ) ) { return $enctype; } $pattern = '%^enctype="(' . implode( '|', $valid_enctypes ) . ')"$%'; if ( preg_match( $pattern, $enctype, $matches ) ) { return $matches[1]; // for back-compat } return ''; } /** * Removes directory recursively. * * @param string $dir Directory path. * @return bool True on success, false on failure. */ function wpcf7_rmdir_p( $dir ) { if ( is_file( $dir ) ) { $file = $dir; if ( @unlink( $file ) ) { return true; } $stat = stat( $file ); if ( @chmod( $file, $stat['mode'] | 0200 ) ) { // add write for owner if ( @unlink( $file ) ) { return true; } @chmod( $file, $stat['mode'] ); } return false; } if ( ! is_dir( $dir ) ) { return false; } if ( $handle = opendir( $dir ) ) { while ( false !== ( $file = readdir( $handle ) ) ) { if ( $file == "." or $file == ".." ) { continue; } wpcf7_rmdir_p( path_join( $dir, $file ) ); } closedir( $handle ); } if ( false !== ( $files = scandir( $dir ) ) and ! array_diff( $files, array( '.', '..' ) ) ) { return rmdir( $dir ); } return false; } /** * Builds a URL-encoded query string. * * @link https://developer.wordpress.org/reference/functions/_http_build_query/ * * @param array $args URL query parameters. * @param string $key Optional. If specified, used to prefix key name. * @return string Query string. */ function wpcf7_build_query( $args, $key = '' ) { $sep = '&'; $ret = array(); foreach ( (array) $args as $k => $v ) { $k = urlencode( $k ); if ( ! empty( $key ) ) { $k = $key . '%5B' . $k . '%5D'; } if ( null === $v ) { continue; } elseif ( false === $v ) { $v = '0'; } if ( is_array( $v ) or is_object( $v ) ) { array_push( $ret, wpcf7_build_query( $v, $k ) ); } else { array_push( $ret, $k . '=' . urlencode( $v ) ); } } return implode( $sep, $ret ); } /** * Returns the number of code units in a string. * * @link http://www.w3.org/TR/html5/infrastructure.html#code-unit-length * * @param string $text Input string. * @return int|bool The number of code units, or false if * mb_convert_encoding is not available. */ function wpcf7_count_code_units( $text ) { static $use_mb = null; if ( is_null( $use_mb ) ) { $use_mb = function_exists( 'mb_convert_encoding' ); } if ( ! $use_mb ) { return false; } $text = (string) $text; $text = str_replace( "\r\n", "\n", $text ); $encoding = mb_detect_encoding( $text, mb_detect_order(), true ); if ( $encoding ) { $text = mb_convert_encoding( $text, 'UTF-16', $encoding ); } else { $text = mb_convert_encoding( $text, 'UTF-16', 'UTF-8' ); } $byte_count = mb_strlen( $text, '8bit' ); return floor( $byte_count / 2 ); } /** * Returns true if WordPress is running on the localhost. */ function wpcf7_is_localhost() { $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST ); return in_array( strtolower( $sitename ), array( 'localhost', '127.0.0.1' ) ); } /** * Marks a function as deprecated and informs when it has been used. * * @param string $function_name The function that was called. * @param string $version The version of Contact Form 7 that deprecated * the function. * @param string $replacement The function that should have been called. */ function wpcf7_deprecated_function( $function_name, $version, $replacement ) { if ( WP_DEBUG ) { if ( function_exists( '__' ) ) { trigger_error( sprintf( /* translators: 1: PHP function name, 2: version number, 3: alternative function name */ __( 'Function %1$s is deprecated since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ), $function_name, $version, $replacement ), E_USER_DEPRECATED ); } else { trigger_error( sprintf( 'Function %1$s is deprecated since Contact Form 7 version %2$s! Use %3$s instead.', $function_name, $version, $replacement ), E_USER_DEPRECATED ); } } } /** * Fires functions attached to a deprecated filter hook. * * @param string $hook_name The name of the filter hook. * @param array $args Array of additional function arguments to be * passed to apply_filters(). * @param string $version The version of Contact Form 7 that deprecated * the hook. * @param string $replacement The hook that should have been used. */ function wpcf7_apply_filters_deprecated( $hook_name, $args, $version, $replacement = '' ) { if ( ! has_filter( $hook_name ) ) { return $args[0]; } if ( WP_DEBUG and apply_filters( 'deprecated_hook_trigger_error', true ) ) { if ( $replacement ) { trigger_error( sprintf( /* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */ __( 'Hook %1$s is deprecated since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ), $hook_name, $version, $replacement ), E_USER_DEPRECATED ); } else { trigger_error( sprintf( /* translators: 1: WordPress hook name, 2: version number */ __( 'Hook %1$s is deprecated since Contact Form 7 version %2$s with no alternative available.', 'contact-form-7' ), $hook_name, $version ), E_USER_DEPRECATED ); } } return apply_filters_ref_array( $hook_name, $args ); } /** * Marks something as being incorrectly called. * * @param string $function_name The function that was called. * @param string $message A message explaining what has been done incorrectly. * @param string $version The version of Contact Form 7 where the message * was added. */ function wpcf7_doing_it_wrong( $function_name, $message, $version ) { if ( WP_DEBUG ) { if ( function_exists( '__' ) ) { if ( $version ) { $version = sprintf( /* translators: %s: Contact Form 7 version number. */ __( '(This message was added in Contact Form 7 version %s.)', 'contact-form-7' ), $version ); } trigger_error( sprintf( /* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Contact Form 7 version number. */ __( 'Function %1$s was called incorrectly. %2$s %3$s', 'contact-form-7' ), $function_name, $message, $version ), E_USER_NOTICE ); } else { if ( $version ) { $version = sprintf( '(This message was added in Contact Form 7 version %s.)', $version ); } trigger_error( sprintf( 'Function %1$s was called incorrectly. %2$s %3$s', $function_name, $message, $version ), E_USER_NOTICE ); } } } /** * Triggers an error about a remote HTTP request and response. * * @param string $url The resource URL. * @param array $request Request arguments. * @param array|WP_Error $response The response or WP_Error on failure. */ function wpcf7_log_remote_request( $url, $request, $response ) { $log = sprintf( /* translators: 1: response code, 2: message, 3: body, 4: URL */ __( 'HTTP Response: %1$s %2$s %3$s from %4$s', 'contact-form-7' ), (int) wp_remote_retrieve_response_code( $response ), wp_remote_retrieve_response_message( $response ), wp_remote_retrieve_body( $response ), $url ); $log = apply_filters( 'wpcf7_log_remote_request', $log, $url, $request, $response ); if ( $log ) { trigger_error( $log ); } } /** * Anonymizes an IP address by masking local part. * * @param string $ip_addr The original IP address. * @return string|bool Anonymized IP address, or false on failure. */ function wpcf7_anonymize_ip_addr( $ip_addr ) { if ( ! function_exists( 'inet_ntop' ) or ! function_exists( 'inet_pton' ) ) { return $ip_addr; } $packed = inet_pton( $ip_addr ); if ( false === $packed ) { return $ip_addr; } if ( 4 == strlen( $packed ) ) { // IPv4 $mask = '255.255.255.0'; } elseif ( 16 == strlen( $packed ) ) { // IPv6 $mask = 'ffff:ffff:ffff:0000:0000:0000:0000:0000'; } else { return $ip_addr; } return inet_ntop( $packed & inet_pton( $mask ) ); } /** * Pipe-related classes. * * @link https://contactform7.com/selectable-recipient-with-pipes/ */ /** * Class representing a pair of pipe. */ class WPCF7_Pipe { public $before = ''; public $after = ''; public function __construct( $text ) { $text = (string) $text; $pipe_pos = strpos( $text, '|' ); if ( false === $pipe_pos ) { $this->before = $this->after = trim( $text ); } else { $this->before = trim( substr( $text, 0, $pipe_pos ) ); $this->after = trim( substr( $text, $pipe_pos + 1 ) ); } } } /** * Class representing a list of pipes. */ class WPCF7_Pipes { private $pipes = array(); public function __construct( array $texts ) { foreach ( $texts as $text ) { $this->add_pipe( $text ); } } private function add_pipe( $text ) { $pipe = new WPCF7_Pipe( $text ); $this->pipes[] = $pipe; } public function do_pipe( $input ) { $input_canonical = wpcf7_canonicalize( $input, array( 'strto' => 'as-is', ) ); foreach ( $this->pipes as $pipe ) { $before_canonical = wpcf7_canonicalize( $pipe->before, array( 'strto' => 'as-is', ) ); if ( $input_canonical === $before_canonical ) { return $pipe->after; } } return $input; } public function collect_befores() { $befores = array(); foreach ( $this->pipes as $pipe ) { $befores[] = $pipe->before; } return $befores; } public function collect_afters() { $afters = array(); foreach ( $this->pipes as $pipe ) { $afters[] = $pipe->after; } return $afters; } public function zero() { return empty( $this->pipes ); } public function random_pipe() { if ( $this->zero() ) { return null; } return $this->pipes[array_rand( $this->pipes )]; } public function to_array() { return array_map( static function ( WPCF7_Pipe $pipe ) { return array( $pipe->before, $pipe->after, ); }, $this->pipes ); } } /** * Handy trait provides methods to handle dynamic properties. */ trait WPCF7_PocketHolder { protected $pocket = array(); public function pull( $key ) { if ( isset( $this->pocket[$key] ) ) { return $this->pocket[$key]; } } public function push( $key, $value ) { $this->pocket[$key] = $value; } } add_action( 'wp_enqueue_scripts', static function () { $assets = array(); $asset_file = wpcf7_plugin_path( 'includes/swv/js/index.asset.php' ); if ( file_exists( $asset_file ) ) { $assets = include( $asset_file ); } $assets = wp_parse_args( $assets, array( 'dependencies' => array(), 'version' => WPCF7_VERSION, ) ); wp_register_script( 'swv', wpcf7_plugin_url( 'includes/swv/js/index.js' ), $assets['dependencies'], $assets['version'], true ); }, 10, 0 ); /** * Contact form helper functions */ /** * Wrapper function of WPCF7_ContactForm::get_instance(). * * @param WPCF7_ContactForm|WP_Post|int $post Object or post ID. * @return WPCF7_ContactForm|null Contact form object. Null if unset. */ function wpcf7_contact_form( $post ) { return WPCF7_ContactForm::get_instance( $post ); } /** * Searches for a contact form by an old unit ID. * * @param int $old_id Old unit ID. * @return WPCF7_ContactForm Contact form object. */ function wpcf7_get_contact_form_by_old_id( $old_id ) { global $wpdb; $q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_old_cf7_unit_id'" . $wpdb->prepare( " AND meta_value = %d", $old_id ); if ( $new_id = $wpdb->get_var( $q ) ) { return wpcf7_contact_form( $new_id ); } } /** * Searches for a contact form by a hash string. * * @param string $hash Part of a hash string. * @return WPCF7_ContactForm Contact form object. */ function wpcf7_get_contact_form_by_hash( $hash ) { global $wpdb; $hash = trim( $hash ); if ( strlen( $hash ) < 7 ) { return null; } $like = $wpdb->esc_like( $hash ) . '%'; $q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_hash'" . $wpdb->prepare( " AND meta_value LIKE %s", $like ); if ( $post_id = $wpdb->get_var( $q ) ) { return wpcf7_contact_form( $post_id ); } } /** * Searches for a contact form by title. * * @param string $title Title of contact form. * @return WPCF7_ContactForm|null Contact form object if found, null otherwise. */ function wpcf7_get_contact_form_by_title( $title ) { if ( ! is_string( $title ) or '' === $title ) { return null; } $contact_forms = WPCF7_ContactForm::find( array( 'title' => $title, 'posts_per_page' => 1, ) ); if ( $contact_forms ) { return wpcf7_contact_form( reset( $contact_forms ) ); } } /** * Wrapper function of WPCF7_ContactForm::get_current(). * * @return WPCF7_ContactForm Contact form object. */ function wpcf7_get_current_contact_form() { if ( $current = WPCF7_ContactForm::get_current() ) { return $current; } } /** * Returns true if it is in the state that a non-Ajax submission is accepted. */ function wpcf7_is_posted() { if ( ! $contact_form = wpcf7_get_current_contact_form() ) { return false; } return $contact_form->is_posted(); } /** * Retrieves the user input value through a non-Ajax submission. * * @param string $name Name of form control. * @param string $default_value Optional default value. * @return string The user input value through the form-control. */ function wpcf7_get_hangover( $name, $default_value = null ) { if ( ! wpcf7_is_posted() ) { return $default_value; } $submission = WPCF7_Submission::get_instance(); if ( ! $submission or $submission->is( 'mail_sent' ) ) { return $default_value; } return isset( $_POST[$name] ) ? wp_unslash( $_POST[$name] ) : $default_value; } /** * Retrieves an HTML snippet of validation error on the given form control. * * @param string $name Name of form control. * @return string Validation error message in a form of HTML snippet. */ function wpcf7_get_validation_error( $name ) { if ( ! $contact_form = wpcf7_get_current_contact_form() ) { return ''; } return $contact_form->validation_error( $name ); } /** * Returns a reference key to a validation error message. * * @param string $name Name of form control. * @param string $unit_tag Optional. Unit tag of the contact form. * @return string Reference key code. */ function wpcf7_get_validation_error_reference( $name, $unit_tag = '' ) { if ( '' === $unit_tag ) { $contact_form = wpcf7_get_current_contact_form(); if ( $contact_form and $contact_form->validation_error( $name ) ) { $unit_tag = $contact_form->unit_tag(); } else { return null; } } return preg_replace( '/[^0-9a-z_-]+/i', '', sprintf( '%1$s-ve-%2$s', $unit_tag, $name ) ); } /** * Retrieves a message for the given status. */ function wpcf7_get_message( $status ) { if ( ! $contact_form = wpcf7_get_current_contact_form() ) { return ''; } return $contact_form->message( $status ); } /** * Returns a class names list for a form-tag of the specified type. * * @param string $type Form-tag type. * @param string $default_classes Optional default classes. * @return string Whitespace-separated list of class names. */ function wpcf7_form_controls_class( $type, $default_classes = '' ) { $type = trim( $type ); if ( is_string( $default_classes ) ) { $default_classes = explode( ' ', $default_classes ); } $classes = array( 'wpcf7-form-control', sprintf( 'wpcf7-%s', rtrim( $type, '*' ) ), ); if ( str_ends_with( $type, '*' ) ) { $classes[] = 'wpcf7-validates-as-required'; } $classes = array_merge( $classes, $default_classes ); $classes = array_filter( array_unique( $classes ) ); return implode( ' ', $classes ); } /** * Callback function for the contact-form-7 shortcode. */ function wpcf7_contact_form_tag_func( $atts, $content = null, $code = '' ) { if ( is_feed() ) { return '[contact-form-7]'; } if ( 'contact-form-7' === $code ) { $atts = shortcode_atts( array( 'id' => '', 'title' => '', 'html_id' => '', 'html_name' => '', 'html_title' => '', 'html_class' => '', 'output' => 'form', ), $atts, 'wpcf7' ); $id = trim( $atts['id'] ); $title = trim( $atts['title'] ); $contact_form = wpcf7_get_contact_form_by_hash( $id ); if ( ! $contact_form ) { $contact_form = wpcf7_contact_form( $id ); } if ( ! $contact_form ) { $contact_form = wpcf7_get_contact_form_by_title( $title ); } } else { if ( is_string( $atts ) ) { $atts = explode( ' ', $atts, 2 ); } $id = (int) array_shift( $atts ); $contact_form = wpcf7_get_contact_form_by_old_id( $id ); } if ( ! $contact_form ) { return sprintf( '
%1$s %2$s
', esc_html( __( 'Error:', 'contact-form-7' ) ), esc_html( __( "Contact form not found.", 'contact-form-7' ) ) ); } $callback = static function ( $contact_form, $atts ) { return $contact_form->form_html( $atts ); }; $output = wpcf7_switch_locale( $contact_form->locale(), $callback, $contact_form, $atts ); do_action( 'wpcf7_shortcode_callback', $contact_form, $atts ); return $output; } /** * Saves the contact form data. */ function wpcf7_save_contact_form( $args = '', $context = 'save' ) { $args = wp_parse_args( $args, array( 'id' => -1, 'title' => null, 'locale' => null, 'form' => null, 'mail' => null, 'mail_2' => null, 'messages' => null, 'additional_settings' => null, ) ); $args = wp_unslash( $args ); $args['id'] = (int) $args['id']; if ( -1 == $args['id'] ) { $contact_form = WPCF7_ContactForm::get_template(); } else { $contact_form = wpcf7_contact_form( $args['id'] ); } if ( empty( $contact_form ) ) { return false; } if ( null !== $args['title'] ) { $contact_form->set_title( $args['title'] ); } if ( null !== $args['locale'] ) { $contact_form->set_locale( $args['locale'] ); } $properties = array(); if ( null !== $args['form'] ) { $properties['form'] = wpcf7_sanitize_form( $args['form'] ); } if ( null !== $args['mail'] ) { $properties['mail'] = wpcf7_sanitize_mail( $args['mail'] ); $properties['mail']['active'] = true; } if ( null !== $args['mail_2'] ) { $properties['mail_2'] = wpcf7_sanitize_mail( $args['mail_2'] ); } if ( null !== $args['messages'] ) { $properties['messages'] = wpcf7_sanitize_messages( $args['messages'] ); } if ( null !== $args['additional_settings'] ) { $properties['additional_settings'] = wpcf7_sanitize_additional_settings( $args['additional_settings'] ); } $contact_form->set_properties( $properties ); do_action( 'wpcf7_save_contact_form', $contact_form, $args, $context ); if ( 'save' == $context ) { $contact_form->save(); } return $contact_form; } /** * Sanitizes the form property data. */ function wpcf7_sanitize_form( $input, $default_template = '' ) { if ( null === $input ) { return $default_template; } $output = trim( $input ); if ( ! current_user_can( 'unfiltered_html' ) ) { $output = wpcf7_kses( $output, 'form' ); } return $output; } /** * Sanitizes the mail property data. */ function wpcf7_sanitize_mail( $input, $defaults = array() ) { $input = wp_parse_args( $input, array( 'active' => false, 'subject' => '', 'sender' => '', 'recipient' => '', 'body' => '', 'additional_headers' => '', 'attachments' => '', 'use_html' => false, 'exclude_blank' => false, ) ); $input = wp_parse_args( $input, $defaults ); $output = array(); $output['active'] = (bool) $input['active']; $output['subject'] = trim( $input['subject'] ); $output['sender'] = trim( $input['sender'] ); $output['recipient'] = trim( $input['recipient'] ); $output['body'] = trim( $input['body'] ); if ( ! current_user_can( 'unfiltered_html' ) ) { $output['body'] = wpcf7_kses( $output['body'], 'mail' ); } $output['additional_headers'] = ''; $headers = str_replace( "\r\n", "\n", $input['additional_headers'] ); $headers = explode( "\n", $headers ); foreach ( $headers as $header ) { $header = trim( $header ); if ( '' !== $header ) { $output['additional_headers'] .= $header . "\n"; } } $output['additional_headers'] = trim( $output['additional_headers'] ); $output['attachments'] = trim( $input['attachments'] ); $output['use_html'] = (bool) $input['use_html']; $output['exclude_blank'] = (bool) $input['exclude_blank']; return $output; } /** * Sanitizes the messages property data. */ function wpcf7_sanitize_messages( $input, $defaults = array() ) { $output = array(); foreach ( wpcf7_messages() as $key => $val ) { if ( isset( $input[$key] ) ) { $output[$key] = trim( $input[$key] ); } elseif ( isset( $defaults[$key] ) ) { $output[$key] = $defaults[$key]; } } return $output; } /** * Sanitizes the additional settings property data. */ function wpcf7_sanitize_additional_settings( $input, $default_template = '' ) { if ( null === $input ) { return $default_template; } $output = trim( $input ); return $output; } /** * Generates a random hash string for a contact form. * * @param int $post_id Post ID. * @return string SHA-1 hash. */ function wpcf7_generate_contact_form_hash( $post_id ) { return sha1( implode( '|', array( get_current_user_id(), $post_id, time(), home_url(), ) ) ); } class WPCF7_ContactForm { use WPCF7_SWV_SchemaHolder; const post_type = 'wpcf7_contact_form'; private static $found_items = 0; private static $current = null; private $id; private $name; private $title; private $locale; private $properties = array(); private $unit_tag; private $responses_count = 0; private $scanned_form_tags; private $shortcode_atts = array(); private $hash = ''; /** * Returns count of contact forms found by the previous retrieval. * * @return int Count of contact forms. */ public static function count() { return self::$found_items; } /** * Returns the contact form that is currently processed. * * @return WPCF7_ContactForm|null Current contact form object. Null if unset. */ public static function get_current() { return self::$current; } /** * Registers the post type for contact forms. */ public static function register_post_type() { register_post_type( self::post_type, array( 'labels' => array( 'name' => __( 'Contact Forms', 'contact-form-7' ), 'singular_name' => __( 'Contact Form', 'contact-form-7' ), ), 'rewrite' => false, 'query_var' => false, 'public' => false, 'capability_type' => 'page', 'capabilities' => array( 'edit_post' => 'wpcf7_edit_contact_form', 'read_post' => 'wpcf7_read_contact_form', 'delete_post' => 'wpcf7_delete_contact_form', 'edit_posts' => 'wpcf7_edit_contact_forms', 'edit_others_posts' => 'wpcf7_edit_contact_forms', 'publish_posts' => 'wpcf7_edit_contact_forms', 'read_private_posts' => 'wpcf7_edit_contact_forms', ), ) ); } /** * Retrieves contact form data that match given conditions. * * @param string|array $args Optional. Arguments to be passed to WP_Query. * @return array Array of WPCF7_ContactForm objects. */ public static function find( $args = '' ) { $defaults = array( 'post_status' => 'any', 'posts_per_page' => -1, 'offset' => 0, 'orderby' => 'ID', 'order' => 'ASC', ); $args = wp_parse_args( $args, $defaults ); $args['post_type'] = self::post_type; $q = new WP_Query(); $posts = $q->query( $args ); self::$found_items = $q->found_posts; $objs = array(); foreach ( (array) $posts as $post ) { $objs[] = new self( $post ); } return $objs; } /** * Returns a contact form data filled by default template contents. * * @param string|array $args Optional. Contact form options. * @return WPCF7_ContactForm A new contact form object. */ public static function get_template( $args = '' ) { $args = wp_parse_args( $args, array( 'locale' => null, 'title' => __( 'Untitled', 'contact-form-7' ), ) ); if ( ! isset( $args['locale'] ) ) { $args['locale'] = determine_locale(); } $callback = static function ( $args ) { $contact_form = new self; $contact_form->title = $args['title']; $contact_form->locale = $args['locale']; $properties = $contact_form->get_properties(); foreach ( $properties as $key => $value ) { $default_template = WPCF7_ContactFormTemplate::get_default( $key ); if ( isset( $default_template ) ) { $properties[$key] = $default_template; } } $contact_form->properties = $properties; return $contact_form; }; $contact_form = wpcf7_switch_locale( $args['locale'], $callback, $args ); self::$current = apply_filters( 'wpcf7_contact_form_default_pack', $contact_form, $args ); return self::$current; } /** * Creates a WPCF7_ContactForm object and sets it as the current instance. * * @param WPCF7_ContactForm|WP_Post|int $post Object or post ID. * @return WPCF7_ContactForm|null Contact form object. Null if unset. */ public static function get_instance( $post ) { $contact_form = null; if ( $post instanceof self ) { $contact_form = $post; } elseif ( ! empty( $post ) ) { $post = get_post( $post ); if ( isset( $post ) and self::post_type === get_post_type( $post ) ) { $contact_form = new self( $post ); } } return self::$current = $contact_form; } /** * Generates a "unit-tag" for the given contact form ID. * * @return string Unit-tag. */ private static function generate_unit_tag( $id = 0 ) { static $global_count = 0; $global_count += 1; if ( in_the_loop() ) { $unit_tag = sprintf( 'wpcf7-f%1$d-p%2$d-o%3$d', absint( $id ), get_the_ID(), $global_count ); } else { $unit_tag = sprintf( 'wpcf7-f%1$d-o%2$d', absint( $id ), $global_count ); } return $unit_tag; } /** * Constructor. */ private function __construct( $post = null ) { $post = get_post( $post ); if ( $post and self::post_type === get_post_type( $post ) ) { $this->id = $post->ID; $this->name = $post->post_name; $this->title = $post->post_title; $this->locale = get_post_meta( $post->ID, '_locale', true ); $this->hash = get_post_meta( $post->ID, '_hash', true ); $this->construct_properties( $post ); $this->upgrade(); } else { $this->construct_properties(); } do_action( 'wpcf7_contact_form', $this ); } /** * Magic method for property overloading. */ public function __get( $name ) { $message = __( '%1$s property of a WPCF7_ContactForm object is no longer accessible. Use %2$s method instead.', 'contact-form-7' );
if ( 'id' == $name ) {
if ( WP_DEBUG ) {
trigger_error(
sprintf( $message, 'id', 'id()' ),
E_USER_DEPRECATED
);
}
return $this->id;
} elseif ( 'title' == $name ) {
if ( WP_DEBUG ) {
trigger_error(
sprintf( $message, 'title', 'title()' ),
E_USER_DEPRECATED
);
}
return $this->title;
} elseif ( $prop = $this->prop( $name ) ) {
if ( WP_DEBUG ) {
trigger_error(
sprintf( $message, $name, 'prop(\'' . $name . '\')' ),
E_USER_DEPRECATED
);
}
return $prop;
}
}
/**
* Returns true if this contact form is not yet saved to the database.
*/
public function initial() {
return empty( $this->id );
}
/**
* Constructs contact form properties. This is called only once
* from the constructor.
*/
private function construct_properties( $post = null ) {
$builtin_properties = array(
'form' => '',
'mail' => array(),
'mail_2' => array(),
'messages' => array(),
'additional_settings' => '',
);
$properties = apply_filters(
'wpcf7_pre_construct_contact_form_properties',
$builtin_properties, $this
);
// Filtering out properties with invalid name
$properties = array_filter(
$properties,
static function ( $key ) {
$sanitized_key = sanitize_key( $key );
return $key === $sanitized_key;
},
ARRAY_FILTER_USE_KEY
);
foreach ( $properties as $name => $val ) {
$prop = $this->retrieve_property( $name );
if ( isset( $prop ) ) {
$properties[$name] = $prop;
}
}
$this->properties = $properties;
foreach ( $properties as $name => $val ) {
$properties[$name] = apply_filters(
"wpcf7_contact_form_property_{$name}",
$val, $this
);
}
$this->properties = $properties;
$properties = (array) apply_filters(
'wpcf7_contact_form_properties',
$properties, $this
);
$this->properties = $properties;
}
/**
* Retrieves contact form property of the specified name from the database.
*
* @param string $name Property name.
* @return array|string|null Property value. Null if property does not exist.
*/
private function retrieve_property( $name ) {
$property = null;
if ( ! $this->initial() ) {
$post_id = $this->id;
if ( metadata_exists( 'post', $post_id, '_' . $name ) ) {
$property = get_post_meta( $post_id, '_' . $name, true );
} elseif ( metadata_exists( 'post', $post_id, $name ) ) {
$property = get_post_meta( $post_id, $name, true );
}
}
return $property;
}
/**
* Returns the value for the given property name.
*
* @param string $name Property name.
* @return array|string|null Property value. Null if property does not exist.
*/
public function prop( $name ) {
$props = $this->get_properties();
return isset( $props[$name] ) ? $props[$name] : null;
}
/**
* Returns all the properties.
*
* @return array This contact form's properties.
*/
public function get_properties() {
return (array) $this->properties;
}
/**
* Updates properties.
*
* @param array $properties New properties.
*/
public function set_properties( $properties ) {
$defaults = $this->get_properties();
$properties = wp_parse_args( $properties, $defaults );
$properties = array_intersect_key( $properties, $defaults );
$this->properties = $properties;
}
/**
* Returns ID of this contact form.
*
* @return int The ID.
*/
public function id() {
return $this->id;
}
/**
* Returns unit-tag for this contact form.
*
* @return string Unit-tag.
*/
public function unit_tag() {
return $this->unit_tag;
}
/**
* Returns name (slug) of this contact form.
*
* @return string Name.
*/
public function name() {
return $this->name;
}
/**
* Returns title of this contact form.
*
* @return string Title.
*/
public function title() {
return $this->title;
}
/**
* Set a title for this contact form.
*
* @param string $title Title.
*/
public function set_title( $title ) {
$title = strip_tags( $title );
$title = trim( $title );
if ( '' === $title ) {
$title = __( 'Untitled', 'contact-form-7' );
}
$this->title = $title;
}
/**
* Returns the locale code of this contact form.
*
* @return string Locale code. Empty string if no valid locale is set.
*/
public function locale() {
if ( wpcf7_is_valid_locale( $this->locale ) ) {
return $this->locale;
} else {
return '';
}
}
/**
* Sets a locale for this contact form.
*
* @param string $locale Locale code.
*/
public function set_locale( $locale ) {
$locale = trim( $locale );
if ( wpcf7_is_valid_locale( $locale ) ) {
$this->locale = $locale;
} else {
$this->locale = 'en_US';
}
}
/**
* Retrieves the random hash string tied to this contact form.
*
* @param int $length Length of hash string.
* @return string Hash string unique to this contact form.
*/
public function hash( $length = 7 ) {
return substr( $this->hash, 0, absint( $length ) );
}
/**
* Returns the specified shortcode attribute value.
*
* @param string $name Shortcode attribute name.
* @return string|null Attribute value. Null if the attribute does not exist.
*/
public function shortcode_attr( $name ) {
if ( isset( $this->shortcode_atts[$name] ) ) {
return (string) $this->shortcode_atts[$name];
}
}
/**
* Returns true if this contact form is identical to the submitted one.
*/
public function is_posted() {
if ( ! WPCF7_Submission::get_instance() ) {
return false;
}
if ( empty( $_POST['_wpcf7_unit_tag'] ) ) {
return false;
}
return $this->unit_tag() === $_POST['_wpcf7_unit_tag'];
}
/**
* Generates HTML that represents a form.
*
* @param string|array $args Optional. Form options.
* @return string HTML output.
*/
public function form_html( $args = '' ) {
$args = wp_parse_args( $args, array(
'html_id' => '',
'html_name' => '',
'html_title' => '',
'html_class' => '',
'output' => 'form',
) );
$this->shortcode_atts = $args;
if ( 'raw_form' == $args['output'] ) {
return sprintf(
'%s',
esc_html( $this->prop( 'form' ) )
);
}
if ( $this->is_true( 'subscribers_only' )
and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
$notice = __(
"This contact form is available only for logged in users.",
'contact-form-7'
);
$notice = sprintf(
'%s
', esc_html( $notice ) ); return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this ); } $this->unit_tag = self::generate_unit_tag( $this->id ); $lang_tag = str_replace( '_', '-', $this->locale ); if ( preg_match( '/^([a-z]+-[a-z]+)-/i', $lang_tag, $matches ) ) { $lang_tag = $matches[1]; } $html = "\n" . sprintf( '%s
', esc_html( $primary_response ) ); $validation_errors = sprintf( '