Plugins
@@ -1 +0,0 @@
|
||||
env.php
|
||||
@@ -1,8 +0,0 @@
|
||||
Cleanup with pbcbf
|
||||
Change style to PSR2
|
||||
Automatically log users in if they have an Okta session already
|
||||
Use promises for sign-out
|
||||
Remove templating from sign-in page
|
||||
Log users out of Okta when they log out of Wordpress
|
||||
Remove all hardcoded values
|
||||
Validate OIDC tokens via /token endpoint
|
||||
@@ -1,41 +0,0 @@
|
||||
# WordPress Okta Sign-In Widget
|
||||
|
||||
This plugin replaces the WordPress login screen with the Okta sign-in widget.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
This plugin was created to demonstrate the capability of replacing the WordPress login screen with the Okta sign-in widget for [this 2018 blog post](https://developer.okta.com/blog/2018/10/30/wordpress-authentication-with-okta).
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
This plugin is not supported by Okta, and not updated regularly.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
If you would like to use an officially supported Okta WordPress integration, please see [this guide](https://plugins.miniorange.com/okta-single-sign-on-wordpress-sso-oauth-openid-connect) to configuring the [miniOrange WordPress SSO Plugin](https://www.okta.com/integrations/wordpress-oauth-single-sign-on-sso-by-miniorange/) with Okta.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
After dropping this folder into the WordPress plugins folder and activating the plugin, you should see a new Settings menu where you can configure your Okta settings to enable the plugin.
|
||||
|
||||
Make sure your admin user in WordPress has an email address that matches an Okta user, or enable native WordPress logins, otherwise you'll be locked out of your WordPress after configuring the plugin.
|
||||
|
||||
TODO:
|
||||
|
||||
* Clean up the UX around installing the plugin, like making sure the admin user can still log in after the plugin is activated
|
||||
* Handle errors better (or at all really)
|
||||
|
||||
## Development Environment
|
||||
|
||||
### Manual
|
||||
|
||||
Install WordPress and move plugin to `wp-content/plugins` directory
|
||||
|
||||
### Docker
|
||||
|
||||
Install Docker and docker-compose and run `docker-compose up`
|
||||
|
||||
Navigate to http://localhost:8080
|
||||
@@ -1,18 +0,0 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
wordpress:
|
||||
image: wordpress
|
||||
depends_on:
|
||||
- mysql
|
||||
ports:
|
||||
- 8080:80
|
||||
environment:
|
||||
WORDPRESS_DB_PASSWORD: password
|
||||
volumes:
|
||||
- .:/var/www/html/wp-content/plugins/okta-wordpress-sign-in-widget
|
||||
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password
|
||||
@@ -1,9 +0,0 @@
|
||||
var oktaSignIn = new OktaSignIn({
|
||||
baseUrl: '<?php echo parse_url($issuer = get_option('okta-issuer-url'), PHP_URL_SCHEME).'://'.parse_url($issuer, PHP_URL_HOST) ?>',
|
||||
redirectUri: '<?php echo wp_login_url() ?>',
|
||||
clientId: '<?php echo get_option('okta-widget-client-id') ?>',
|
||||
scopes: '<?php echo apply_filters( 'okta_widget_token_scope', 'openid email') ?>'.split(' '),
|
||||
authParams: {
|
||||
issuer: '<?php echo get_option('okta-issuer-url') ?>'
|
||||
}
|
||||
});
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
namespace Okta;
|
||||
|
||||
class OktaAdmin{
|
||||
|
||||
public function __construct(){
|
||||
// https://codex.wordpress.org/Creating_Options_Pages
|
||||
add_action('admin_init', array($this, 'registerSettingsAction'));
|
||||
|
||||
// https://codex.wordpress.org/Adding_Administration_Menus
|
||||
add_action('admin_menu', array($this, 'optionsMenuAction'));
|
||||
}
|
||||
|
||||
public function registerSettingsAction() {
|
||||
add_settings_section(
|
||||
'okta-sign-in-widget-options-section',
|
||||
'',
|
||||
null,
|
||||
'okta-sign-in-widget'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-issuer-url', array(
|
||||
'type' => 'string',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-issuer-url',
|
||||
'Okta Issuer URI',
|
||||
function() { $this->optionsPageTextInputAction('okta-issuer-url', 'text', 'e.g. https://youroktadomain.okta.com/oauth2/default', 'Find your Issuer URI in the Admin console under <b>Security -> API</b>, or in the Developer console under <b>API -> Authorization Servers</b>'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-widget-client-id', array(
|
||||
'type' => 'string',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-widget-client-id',
|
||||
'Sign-In Widget Client ID',
|
||||
function() { $this->optionsPageTextInputAction('okta-widget-client-id', 'text', null, 'Register a "SPA" app in Okta and provide its Client ID here. Set the Login redirect URI in Okta to <code>'.wp_login_url().'</code>, and set the Logout redirect URI to <code>'.home_url().'</code>'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-allow-wordpress-login', array(
|
||||
'type' => 'boolean',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-allow-wordpress-login',
|
||||
'Allow Native WordPress Login',
|
||||
function() { $this->optionsPageCheckboxInputAction('okta-allow-wordpress-login', 'checkbox', 'Check this to allow local WordPress users to log in with a password. When unchecked, Okta will be the only way users can log in. Make sure you have a WordPress admin user with an email address matching an Okta user already.'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
}
|
||||
|
||||
public function optionsMenuAction() {
|
||||
add_options_page(
|
||||
'Okta Sign-In Widget Options',
|
||||
'Okta Sign-In Widget',
|
||||
'manage_options',
|
||||
'okta-sign-in-widget',
|
||||
array($this, 'optionsPageAction')
|
||||
);
|
||||
}
|
||||
|
||||
public function optionsPageAction() {
|
||||
if (current_user_can('manage_options')) {
|
||||
include(plugin_dir_path(__FILE__)."../templates/options-form.php");
|
||||
} else {
|
||||
wp_die( 'You do not have sufficient permissions to access this page.' );
|
||||
}
|
||||
}
|
||||
|
||||
public function optionsPageTextInputAction($option_name, $type, $placeholder=false, $description=false) {
|
||||
$option_value = get_option($option_name, '');
|
||||
printf(
|
||||
'<input type="%s" id="%s" name="%s" value="%s" style="width: 100%%" autocomplete="off" placeholder="%s" />',
|
||||
esc_attr($type),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_value),
|
||||
esc_attr($placeholder)
|
||||
);
|
||||
if($description)
|
||||
echo '<p class="description">'.$description.'</p>';
|
||||
}
|
||||
|
||||
public function optionsPageCheckboxInputAction($option_name, $type, $description=false) {
|
||||
$option_value = get_option($option_name, false);
|
||||
printf(
|
||||
'<input type="%s" id="%s" name="%s" value="1" %s>',
|
||||
esc_attr($type),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_name),
|
||||
$option_value ? 'checked="checked"' : ''
|
||||
);
|
||||
if($description)
|
||||
echo '<p class="description">'.$description.'</p>';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
<script src="https://global.oktacdn.com/okta-signin-widget/5.12.0/js/okta-sign-in.min.js" type="text/javascript"></script>
|
||||
<link href="https://global.oktacdn.com/okta-signin-widget/5.12.0/css/okta-sign-in.min.css" type="text/css" rel="stylesheet"/>
|
||||
@@ -1,226 +0,0 @@
|
||||
<?php
|
||||
namespace Okta;
|
||||
|
||||
/**
|
||||
* Plugin Name: Okta Sign-In Widget
|
||||
* Plugin URI: https://github.com/oktadeveloper/okta-wordpress-sign-in-widget
|
||||
* Description: Log in to your site using the Okta Sign-In Widget
|
||||
* Version: 0.3.0
|
||||
* Author: Aaron Parecki, Tom Smith, Nico Triballier, Joël Franusic
|
||||
* Author URI: https://developer.okta.com/
|
||||
* License: MIT
|
||||
* License URI: http://opensource.org/licenses/MIT
|
||||
* Text Domain: okta
|
||||
* Domain Path: /languages
|
||||
* Update URI: false
|
||||
*/
|
||||
|
||||
include plugin_dir_path(__FILE__).'/includes/okta-admin.php';
|
||||
|
||||
class OktaSignIn
|
||||
{
|
||||
private $OktaAdmin;
|
||||
private $base_url = false;
|
||||
private $introspection_endpoint = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->OktaAdmin = new OktaAdmin;
|
||||
|
||||
$this->setBaseUrl();
|
||||
|
||||
// https://developer.wordpress.org/reference/hooks/login_init/
|
||||
add_action('login_init', array($this, 'loginAction'));
|
||||
|
||||
// This runs on every pageload to insert content into the HTML <head> section
|
||||
// https://codex.wordpress.org/Plugin_API/Action_Reference/wp_head
|
||||
add_action('wp_head', array($this, 'addLogInExistingSessionAction'));
|
||||
|
||||
add_action('init', array($this, 'startSessionAction'));
|
||||
}
|
||||
|
||||
private function setBaseUrl()
|
||||
{
|
||||
if($issuer = get_option('okta-issuer-url')) {
|
||||
$this->base_url = parse_url($issuer, PHP_URL_SCHEME).'://'.parse_url($issuer, PHP_URL_HOST);
|
||||
}
|
||||
}
|
||||
|
||||
private function getIntrospectionEndpoint() {
|
||||
if($this->introspection_endpoint)
|
||||
return $this->introspection_endpoint;
|
||||
|
||||
if(!$this->base_url)
|
||||
return false;
|
||||
|
||||
$response = wp_remote_get(get_option('okta-issuer-url').'/.well-known/openid-configuration');
|
||||
if(!$response)
|
||||
return false;
|
||||
|
||||
$metadata = json_decode($response['body'], true);
|
||||
if(!$metadata)
|
||||
return false;
|
||||
|
||||
if(!isset($metadata['introspection_endpoint']))
|
||||
return false;
|
||||
|
||||
return $this->introspection_endpoint = $metadata['introspection_endpoint'];
|
||||
}
|
||||
|
||||
public function startSessionAction()
|
||||
{
|
||||
if (session_status() != PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
public function addLogInExistingSessionAction()
|
||||
{
|
||||
if (!is_user_logged_in()) {
|
||||
$this->startSessionAction();
|
||||
$_SESSION['redirect_to'] = $_SERVER['REQUEST_URI'];
|
||||
include("templates/log-in-existing-session.php");
|
||||
}
|
||||
}
|
||||
|
||||
private function httpPost($url, $body)
|
||||
{
|
||||
$args = array(
|
||||
'headers' => array(
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
),
|
||||
'body' => $body,
|
||||
);
|
||||
return wp_remote_post($url, $args);
|
||||
}
|
||||
|
||||
public function loginAction()
|
||||
{
|
||||
// Support redirecting back to the page the user was on before they clicked log in
|
||||
$redirect_to = false;
|
||||
if (isset($_GET['redirect_to'])) {
|
||||
$redirect_to = $_GET['redirect_to'];
|
||||
$_SESSION['redirect_to'] = $_GET['redirect_to'];
|
||||
}
|
||||
|
||||
// When signing out of WordPress, tell the Okta JS library to log out of Okta as well
|
||||
if (isset($_GET["action"]) && $_GET["action"] === "logout") {
|
||||
$this->logUserOutOfOkta();
|
||||
}
|
||||
|
||||
if (isset($_GET['log_in_from_id_token'])) {
|
||||
$this->logUserIntoWordPressWithIDToken($_GET['log_in_from_id_token'], $redirect_to);
|
||||
exit;
|
||||
}
|
||||
|
||||
if($this->useWordpressLogin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no code in the query string, show the Okta sign-in widget
|
||||
$template = plugin_dir_path(__FILE__) . 'templates/sign-in-form.php';
|
||||
load_template($template);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function useWordpressLogin()
|
||||
{
|
||||
// Always skip showing the Okta widget on POST requests
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST')
|
||||
return true;
|
||||
|
||||
// If the plugin isn't configured yet, don't show the Okta widget
|
||||
if(!$this->base_url)
|
||||
return true;
|
||||
|
||||
// null when plugin is not configured, "1"/"0" after
|
||||
if(get_option('okta-allow-wordpress-login') === null || get_option('okta-allow-wordpress-login') === "1")
|
||||
{
|
||||
if(isset($_GET['wordpress_login']) && $_GET['wordpress_login'] == 'true')
|
||||
return true;
|
||||
|
||||
if(isset($_GET['action']) && $_GET['action'] == 'lostpassword')
|
||||
return true;
|
||||
|
||||
if(isset($_GET['checkemail']))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function logUserOutOfOkta() {
|
||||
$user = wp_get_current_user();
|
||||
|
||||
wp_clear_auth_cookie();
|
||||
|
||||
$template = plugin_dir_path(__FILE__) . 'templates/sign-out.php';
|
||||
load_template($template);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function logUserIntoWordPressWithIDToken($id_token, $redirect_to)
|
||||
{
|
||||
$introspection_endpoint = $this->getIntrospectionEndpoint();
|
||||
|
||||
if(!$this->introspection_endpoint)
|
||||
die("The plugin is not configured properly. Please double check the Issuer URI in the configuration.");
|
||||
|
||||
/********************************************/
|
||||
// [jpf] TODO: Implement client-side id_token validation to speed up the verification process
|
||||
// (~300ms for /introspect endpoint v. ~5ms for client-side validation)
|
||||
$payload = array(
|
||||
'client_id' => get_option('okta-widget-client-id'),
|
||||
'token' => $id_token,
|
||||
'token_type_hint' => 'id_token'
|
||||
);
|
||||
$response = $this->httpPost($this->introspection_endpoint, $payload);
|
||||
if ($response === false) {
|
||||
die("Invalid id_token received from Okta");
|
||||
}
|
||||
$claims = json_decode($response['body'], true);
|
||||
if (!$claims['active']) {
|
||||
die("Okta reports that id_token is not active or client authentication failed:" . $claims['error_description']);
|
||||
}
|
||||
/********************************************/
|
||||
|
||||
$this->logUserIntoWordPressFromEmail($claims, $redirect_to);
|
||||
}
|
||||
|
||||
private function logUserIntoWordPressFromEmail($claims, $redirect_to)
|
||||
{
|
||||
$email = $claims['email'];
|
||||
|
||||
// Find or create the WordPress user for this email address
|
||||
$user = get_user_by('email', $email);
|
||||
if (!$user) {
|
||||
$random_password = wp_generate_password($length = 64, $include_standard_special_chars = false);
|
||||
$user_id = wp_create_user($email, $random_password, $email);
|
||||
$user = get_user_by('id', $user_id);
|
||||
} else {
|
||||
$user_id = $user->ID;
|
||||
}
|
||||
|
||||
do_action('okta_widget_before_login', $claims, $user);
|
||||
|
||||
// Actually log the user in now
|
||||
wp_set_current_user($user_id);
|
||||
wp_set_auth_cookie($user_id);
|
||||
error_log("Logging in WordPress user with ID of: " . $user_id);
|
||||
|
||||
// See also: https://developer.wordpress.org/reference/functions/do_action/
|
||||
// Run the wp_login actions now that the user is logged in
|
||||
do_action('wp_login', $user->user_login, $user);
|
||||
|
||||
if (isset($_SESSION['redirect_to'])) {
|
||||
$redirect_uri = $_SESSION['redirect_to'];
|
||||
unset($_SESSION['redirect_to']);
|
||||
} else {
|
||||
$redirect_uri = home_url();
|
||||
}
|
||||
wp_redirect($redirect_uri);
|
||||
}
|
||||
}
|
||||
|
||||
$okta = new OktaSignIn();
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.session.exists()
|
||||
.then(function(exists) {
|
||||
if(exists) {
|
||||
oktaSignIn.authClient.token.getWithoutPrompt({
|
||||
responseType: ['id_token'],
|
||||
})
|
||||
.then(function(tokens){
|
||||
window.location.href = '<?php echo wp_login_url() ?>' + '?log_in_from_id_token=' + tokens.tokens.idToken.value;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,9 +0,0 @@
|
||||
<div class="wrap">
|
||||
<h1>Okta Sign-In Widget</h1>
|
||||
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields( 'okta-sign-in-widget' ); ?>
|
||||
<?php do_settings_sections( 'okta-sign-in-widget' ); ?>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
</div>
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: montserrat,Arial,Helvetica,sans-serif;
|
||||
}
|
||||
|
||||
#wordpress-login{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wordpress-login a{
|
||||
font-size:10px;
|
||||
color: #999;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
#error {
|
||||
max-width: 500px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px #d93934 solid;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#error h2 {
|
||||
color: #d93934;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php if(isset($_GET['error'])): ?>
|
||||
<div id="error">
|
||||
<h2>Error: <?php echo htmlspecialchars($_GET['error']) ?></h2>
|
||||
<p><?php echo htmlspecialchars($_GET['error_description']) ?></p>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div id="primary" class="content-area">
|
||||
<div id="okta-login-container"></div>
|
||||
<?php if(get_option('okta-allow-wordpress-login')): ?>
|
||||
<div id="wordpress-login"><a href="<?php echo wp_login_url(); ?>?wordpress_login=true">Login via Wordpress</a></div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.token.getUserInfo().then(function(user) {
|
||||
console.log("Already logged in");
|
||||
oktaSignIn.authClient.tokenManager.get('idToken').then(function(idToken){
|
||||
window.location = '<?php echo wp_login_url() ?>?log_in_from_id_token='+idToken.value;
|
||||
});
|
||||
}, function(error) {
|
||||
oktaSignIn.showSignInToGetTokens({
|
||||
el: '#okta-login-container'
|
||||
}).then(function(tokens) {
|
||||
oktaSignIn.authClient.tokenManager.setTokens(tokens);
|
||||
|
||||
oktaSignIn.remove(); // Remove the widget from the DOM
|
||||
|
||||
const idToken = tokens.idToken;
|
||||
window.location = '<?php echo wp_login_url() ?>?log_in_from_id_token='+idToken.value;
|
||||
|
||||
}).catch(function(err) {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.tokenManager.get('idToken').then(function(idToken){
|
||||
if(idToken) {
|
||||
oktaSignIn.authClient.signOut({
|
||||
idToken: idToken,
|
||||
postLogoutRedirectUri: '<?php echo home_url() ?>'
|
||||
});
|
||||
} else {
|
||||
window.location = '<?php echo home_url() ?>';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: MU Okta Sign In
|
||||
Version: 0.1
|
||||
*/
|
||||
|
||||
require_once( 'okta-wordpress-sign-in-widget-main/okta-widget.php' );
|
||||
@@ -1,400 +0,0 @@
|
||||
### WordPress - Web publishing software
|
||||
|
||||
Copyright 2011-2019 by the contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
This program incorporates work covered by the following copyright and
|
||||
permission notices:
|
||||
|
||||
b2 is (c) 2001, 2002 Michel Valdrighi - m@tidakada.com -
|
||||
http://tidakada.com
|
||||
|
||||
Wherever third party code has been used, credit has been given in the code's
|
||||
comments.
|
||||
|
||||
b2 is released under the GPL
|
||||
|
||||
and
|
||||
|
||||
WordPress - Web publishing software
|
||||
|
||||
Copyright 2003-2010 by the contributors
|
||||
|
||||
WordPress is released under the GPL
|
||||
|
||||
---
|
||||
|
||||
### GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
### Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom
|
||||
to share and change it. By contrast, the GNU General Public License is
|
||||
intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on,
|
||||
we want its recipients to know that what they have is not the
|
||||
original, so that any problems introduced by others will not reflect
|
||||
on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at
|
||||
all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
**0.** This License applies to any program or other work which
|
||||
contains a notice placed by the copyright holder saying it may be
|
||||
distributed under the terms of this General Public License. The
|
||||
"Program", below, refers to any such program or work, and a "work
|
||||
based on the Program" means either the Program or any derivative work
|
||||
under copyright law: that is to say, a work containing the Program or
|
||||
a portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".) Each licensee
|
||||
is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the Program
|
||||
(independent of having been made by running the Program). Whether that
|
||||
is true depends on what the Program does.
|
||||
|
||||
**1.** You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
**2.** You may modify your copy or copies of the Program or any
|
||||
portion of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
|
||||
**a)** You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
|
||||
**b)** You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any part
|
||||
thereof, to be licensed as a whole at no charge to all third parties
|
||||
under the terms of this License.
|
||||
|
||||
|
||||
**c)** If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such interactive
|
||||
use in the most ordinary way, to print or display an announcement
|
||||
including an appropriate copyright notice and a notice that there is
|
||||
no warranty (or else, saying that you provide a warranty) and that
|
||||
users may redistribute the program under these conditions, and telling
|
||||
the user how to view a copy of this License. (Exception: if the
|
||||
Program itself is interactive but does not normally print such an
|
||||
announcement, your work based on the Program is not required to print
|
||||
an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
**3.** You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
|
||||
**a)** Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
|
||||
**b)** Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your cost of
|
||||
physically performing source distribution, a complete machine-readable
|
||||
copy of the corresponding source code, to be distributed under the
|
||||
terms of Sections 1 and 2 above on a medium customarily used for
|
||||
software interchange; or,
|
||||
|
||||
|
||||
**c)** Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is allowed
|
||||
only for noncommercial distribution and only if you received the
|
||||
program in object code or executable form with such an offer, in
|
||||
accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
**4.** You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt otherwise
|
||||
to copy, modify, sublicense or distribute the Program is void, and
|
||||
will automatically terminate your rights under this License. However,
|
||||
parties who have received copies, or rights, from you under this
|
||||
License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
**5.** You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
**6.** Each time you redistribute the Program (or any work based on
|
||||
the Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
**7.** If, as a consequence of a court judgment or allegation of
|
||||
patent infringement or for any other reason (not limited to patent
|
||||
issues), conditions are imposed on you (whether by court order,
|
||||
agreement or otherwise) that contradict the conditions of this
|
||||
License, they do not excuse you from the conditions of this License.
|
||||
If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations,
|
||||
then as a consequence you may not distribute the Program at all. For
|
||||
example, if a patent license would not permit royalty-free
|
||||
redistribution of the Program by all those who receive copies directly
|
||||
or indirectly through you, then the only way you could satisfy both it
|
||||
and this License would be to refrain entirely from distribution of the
|
||||
Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
**8.** If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
**9.** The Free Software Foundation may publish revised and/or new
|
||||
versions of the General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Program does not specify a
|
||||
version number of this License, you may choose any version ever
|
||||
published by the Free Software Foundation.
|
||||
|
||||
**10.** If you wish to incorporate parts of the Program into other
|
||||
free programs whose distribution conditions are different, write to
|
||||
the author to ask for permission. For software which is copyrighted by
|
||||
the Free Software Foundation, write to the Free Software Foundation;
|
||||
we sometimes make exceptions for this. Our decision will be guided by
|
||||
the two goals of preserving the free status of all derivatives of our
|
||||
free software and of promoting the sharing and reuse of software
|
||||
generally.
|
||||
|
||||
**NO WARRANTY**
|
||||
|
||||
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
### END OF TERMS AND CONDITIONS
|
||||
|
||||
### How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the program's name and an idea of what it does.
|
||||
Copyright (C) yyyy name of author
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper
|
||||
mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
|
||||
type `show w'. This is free software, and you are welcome
|
||||
to redistribute it under certain conditions; type `show c'
|
||||
for details.
|
||||
|
||||
The hypothetical commands \`show w' and \`show c' should show the
|
||||
appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than \`show w' and
|
||||
\`show c'; they could even be mouse-clicks or menu items--whatever
|
||||
suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
your school, if any, to sign a "copyright disclaimer" for the program,
|
||||
if necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright
|
||||
interest in the program `Gnomovision'
|
||||
(which makes passes at compilers) written
|
||||
by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library,
|
||||
you may consider it more useful to permit linking proprietary
|
||||
applications with the library. If this is what you want to do, use the
|
||||
[GNU Lesser General Public
|
||||
License](http://www.gnu.org/licenses/lgpl.html) instead of this
|
||||
License.
|
||||
@@ -1,977 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Classic Editor
|
||||
*
|
||||
* Plugin Name: Classic Editor
|
||||
* Plugin URI: https://wordpress.org/plugins/classic-editor/
|
||||
* Description: Enables the WordPress classic editor and the old-style Edit Post screen with TinyMCE, Meta Boxes, etc. Supports the older plugins that extend this screen.
|
||||
* Version: 1.6.3
|
||||
* Author: WordPress Contributors
|
||||
* Author URI: https://github.com/WordPress/classic-editor/
|
||||
* License: GPLv2 or later
|
||||
* License URI: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* Text Domain: classic-editor
|
||||
* Domain Path: /languages
|
||||
* Requires at least: 4.9
|
||||
* Requires PHP: 5.2.4
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 2, as published by the Free Software Foundation. You may NOT assume
|
||||
* that you can use any other version of the GPL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Invalid request.' );
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Classic_Editor' ) ) :
|
||||
class Classic_Editor {
|
||||
private static $settings;
|
||||
private static $supported_post_types = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function init_actions() {
|
||||
$block_editor = has_action( 'enqueue_block_assets' );
|
||||
$gutenberg = function_exists( 'gutenberg_register_scripts_and_styles' );
|
||||
|
||||
register_activation_hook( __FILE__, array( __CLASS__, 'activate' ) );
|
||||
|
||||
$settings = self::get_settings();
|
||||
|
||||
if ( is_multisite() ) {
|
||||
add_action( 'wpmu_options', array( __CLASS__, 'network_settings' ) );
|
||||
add_action( 'update_wpmu_options', array( __CLASS__, 'save_network_settings' ) );
|
||||
}
|
||||
|
||||
if ( ! $settings['hide-settings-ui'] ) {
|
||||
// Add a link to the plugin's settings and/or network admin settings in the plugins list table.
|
||||
add_filter( 'plugin_action_links', array( __CLASS__, 'add_settings_link' ), 10, 2 );
|
||||
add_filter( 'network_admin_plugin_action_links', array( __CLASS__, 'add_settings_link' ), 10, 2 );
|
||||
|
||||
add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
|
||||
|
||||
if ( $settings['allow-users'] ) {
|
||||
// User settings.
|
||||
add_action( 'personal_options_update', array( __CLASS__, 'save_user_settings' ) );
|
||||
add_action( 'profile_personal_options', array( __CLASS__, 'user_settings' ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Always remove the "Try Gutenberg" dashboard widget. See https://core.trac.wordpress.org/ticket/44635.
|
||||
remove_action( 'try_gutenberg_panel', 'wp_try_gutenberg_panel' );
|
||||
|
||||
if ( ! $block_editor && ! $gutenberg ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $settings['allow-users'] ) {
|
||||
// Also used in Gutenberg.
|
||||
add_filter( 'use_block_editor_for_post', array( __CLASS__, 'choose_editor' ), 100, 2 );
|
||||
|
||||
if ( $gutenberg ) {
|
||||
// Support older Gutenberg versions.
|
||||
add_filter( 'gutenberg_can_edit_post', array( __CLASS__, 'choose_editor' ), 100, 2 );
|
||||
|
||||
if ( $settings['editor'] === 'classic' ) {
|
||||
self::remove_gutenberg_hooks( 'some' );
|
||||
}
|
||||
}
|
||||
|
||||
add_filter( 'get_edit_post_link', array( __CLASS__, 'get_edit_post_link' ) );
|
||||
add_filter( 'redirect_post_location', array( __CLASS__, 'redirect_location' ) );
|
||||
add_action( 'edit_form_top', array( __CLASS__, 'add_redirect_helper' ) );
|
||||
add_action( 'admin_head-edit.php', array( __CLASS__, 'add_edit_php_inline_style' ) );
|
||||
|
||||
add_action( 'edit_form_top', array( __CLASS__, 'remember_classic_editor' ) );
|
||||
|
||||
if ( version_compare( $GLOBALS['wp_version'], '5.8', '>=' ) ) {
|
||||
add_filter( 'block_editor_settings_all', array( __CLASS__, 'remember_block_editor' ), 10, 2 );
|
||||
} else {
|
||||
add_filter( 'block_editor_settings', array( __CLASS__, 'remember_block_editor' ), 10, 2 );
|
||||
}
|
||||
|
||||
// Post state (edit.php)
|
||||
add_filter( 'display_post_states', array( __CLASS__, 'add_post_state' ), 10, 2 );
|
||||
// Row actions (edit.php)
|
||||
add_filter( 'page_row_actions', array( __CLASS__, 'add_edit_links' ), 15, 2 );
|
||||
add_filter( 'post_row_actions', array( __CLASS__, 'add_edit_links' ), 15, 2 );
|
||||
|
||||
// Switch editors while editing a post
|
||||
add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ), 10, 2 );
|
||||
add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'enqueue_block_editor_scripts' ) );
|
||||
} else {
|
||||
if ( $settings['editor'] === 'classic' ) {
|
||||
// Also used in Gutenberg.
|
||||
// Consider disabling other Block Editor functionality.
|
||||
add_filter( 'use_block_editor_for_post_type', '__return_false', 100 );
|
||||
|
||||
if ( $gutenberg ) {
|
||||
// Support older Gutenberg versions.
|
||||
add_filter( 'gutenberg_can_edit_post_type', '__return_false', 100 );
|
||||
self::remove_gutenberg_hooks();
|
||||
}
|
||||
} else {
|
||||
// $settings['editor'] === 'block', nothing to do :)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $block_editor ) {
|
||||
// Move the Privacy Page notice back under the title.
|
||||
add_action( 'admin_init', array( __CLASS__, 'on_admin_init' ) );
|
||||
}
|
||||
if ( $gutenberg ) {
|
||||
// These are handled by this plugin. All are older, not used in 5.3+.
|
||||
remove_action( 'admin_init', 'gutenberg_add_edit_link_filters' );
|
||||
remove_action( 'admin_print_scripts-edit.php', 'gutenberg_replace_default_add_new_button' );
|
||||
remove_filter( 'redirect_post_location', 'gutenberg_redirect_to_classic_editor_when_saving_posts' );
|
||||
remove_filter( 'display_post_states', 'gutenberg_add_gutenberg_post_state' );
|
||||
remove_action( 'edit_form_top', 'gutenberg_remember_classic_editor_when_saving_posts' );
|
||||
}
|
||||
}
|
||||
|
||||
public static function remove_gutenberg_hooks( $remove = 'all' ) {
|
||||
remove_action( 'admin_menu', 'gutenberg_menu' );
|
||||
remove_action( 'admin_init', 'gutenberg_redirect_demo' );
|
||||
|
||||
if ( $remove !== 'all' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gutenberg 5.3+
|
||||
remove_action( 'wp_enqueue_scripts', 'gutenberg_register_scripts_and_styles' );
|
||||
remove_action( 'admin_enqueue_scripts', 'gutenberg_register_scripts_and_styles' );
|
||||
remove_action( 'admin_notices', 'gutenberg_wordpress_version_notice' );
|
||||
remove_action( 'rest_api_init', 'gutenberg_register_rest_widget_updater_routes' );
|
||||
remove_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' );
|
||||
remove_action( 'admin_print_scripts', 'gutenberg_block_editor_admin_print_scripts' );
|
||||
remove_action( 'admin_print_footer_scripts', 'gutenberg_block_editor_admin_print_footer_scripts' );
|
||||
remove_action( 'admin_footer', 'gutenberg_block_editor_admin_footer' );
|
||||
remove_action( 'admin_enqueue_scripts', 'gutenberg_widgets_init' );
|
||||
remove_action( 'admin_notices', 'gutenberg_build_files_notice' );
|
||||
|
||||
remove_filter( 'load_script_translation_file', 'gutenberg_override_translation_file' );
|
||||
remove_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_styles' );
|
||||
remove_filter( 'default_content', 'gutenberg_default_demo_content' );
|
||||
remove_filter( 'default_title', 'gutenberg_default_demo_title' );
|
||||
remove_filter( 'block_editor_settings', 'gutenberg_legacy_widget_settings' );
|
||||
remove_filter( 'rest_request_after_callbacks', 'gutenberg_filter_oembed_result' );
|
||||
|
||||
// Previously used, compat for older Gutenberg versions.
|
||||
remove_filter( 'wp_refresh_nonces', 'gutenberg_add_rest_nonce_to_heartbeat_response_headers' );
|
||||
remove_filter( 'get_edit_post_link', 'gutenberg_revisions_link_to_editor' );
|
||||
remove_filter( 'wp_prepare_revision_for_js', 'gutenberg_revisions_restore' );
|
||||
|
||||
remove_action( 'rest_api_init', 'gutenberg_register_rest_routes' );
|
||||
remove_action( 'rest_api_init', 'gutenberg_add_taxonomy_visibility_field' );
|
||||
remove_filter( 'registered_post_type', 'gutenberg_register_post_prepare_functions' );
|
||||
|
||||
remove_action( 'do_meta_boxes', 'gutenberg_meta_box_save' );
|
||||
remove_action( 'submitpost_box', 'gutenberg_intercept_meta_box_render' );
|
||||
remove_action( 'submitpage_box', 'gutenberg_intercept_meta_box_render' );
|
||||
remove_action( 'edit_page_form', 'gutenberg_intercept_meta_box_render' );
|
||||
remove_action( 'edit_form_advanced', 'gutenberg_intercept_meta_box_render' );
|
||||
remove_filter( 'redirect_post_location', 'gutenberg_meta_box_save_redirect' );
|
||||
remove_filter( 'filter_gutenberg_meta_boxes', 'gutenberg_filter_meta_boxes' );
|
||||
|
||||
remove_filter( 'body_class', 'gutenberg_add_responsive_body_class' );
|
||||
remove_filter( 'admin_url', 'gutenberg_modify_add_new_button_url' ); // old
|
||||
remove_action( 'admin_enqueue_scripts', 'gutenberg_check_if_classic_needs_warning_about_blocks' );
|
||||
remove_filter( 'register_post_type_args', 'gutenberg_filter_post_type_labels' );
|
||||
|
||||
// phpcs:disable Squiz.PHP.CommentedOutCode.Found
|
||||
// Keep
|
||||
// remove_filter( 'wp_kses_allowed_html', 'gutenberg_kses_allowedtags', 10, 2 ); // not needed in 5.0
|
||||
// remove_filter( 'bulk_actions-edit-wp_block', 'gutenberg_block_bulk_actions' );
|
||||
// remove_filter( 'wp_insert_post_data', 'gutenberg_remove_wpcom_markdown_support' );
|
||||
// remove_filter( 'the_content', 'do_blocks', 9 );
|
||||
// remove_action( 'init', 'gutenberg_register_post_types' );
|
||||
|
||||
// Continue to manage wpautop for posts that were edited in Gutenberg.
|
||||
// remove_filter( 'wp_editor_settings', 'gutenberg_disable_editor_settings_wpautop' );
|
||||
// remove_filter( 'the_content', 'gutenberg_wpautop', 8 );
|
||||
// phpcs:enable Squiz.PHP.CommentedOutCode.Found
|
||||
|
||||
}
|
||||
|
||||
private static function get_settings( $refresh = 'no' ) {
|
||||
/**
|
||||
* Can be used to override the plugin's settings. Always hides the settings UI when used (as users cannot change the settings).
|
||||
*
|
||||
* Has to return an associative array with two keys.
|
||||
* The defaults are:
|
||||
* 'editor' => 'classic', // Accepted values: 'classic', 'block'.
|
||||
* 'allow-users' => false,
|
||||
*
|
||||
* @param boolean To override the settings return an array with the above keys.
|
||||
*/
|
||||
$settings = apply_filters( 'classic_editor_plugin_settings', false );
|
||||
|
||||
if ( is_array( $settings ) ) {
|
||||
return array(
|
||||
'editor' => ( isset( $settings['editor'] ) && $settings['editor'] === 'block' ) ? 'block' : 'classic',
|
||||
'allow-users' => ! empty( $settings['allow-users'] ),
|
||||
'hide-settings-ui' => true,
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( self::$settings ) && $refresh === 'no' ) {
|
||||
return self::$settings;
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$defaults = array(
|
||||
'editor' => get_network_option( null, 'classic-editor-replace' ) === 'block' ? 'block' : 'classic',
|
||||
'allow-users' => false,
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the default network options.
|
||||
*
|
||||
* @param array $defaults The default options array. See `classic_editor_plugin_settings` for supported keys and values.
|
||||
*/
|
||||
$defaults = apply_filters( 'classic_editor_network_default_settings', $defaults );
|
||||
|
||||
if ( get_network_option( null, 'classic-editor-allow-sites' ) !== 'allow' ) {
|
||||
// Per-site settings are disabled. Return default network options nad hide the settings UI.
|
||||
$defaults['hide-settings-ui'] = true;
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
// Override with the site options.
|
||||
$editor_option = get_option( 'classic-editor-replace' );
|
||||
$allow_users_option = get_option( 'classic-editor-allow-users' );
|
||||
|
||||
if ( $editor_option ) {
|
||||
$defaults['editor'] = $editor_option;
|
||||
}
|
||||
if ( $allow_users_option ) {
|
||||
$defaults['allow-users'] = ( $allow_users_option === 'allow' );
|
||||
}
|
||||
|
||||
$editor = ( isset( $defaults['editor'] ) && $defaults['editor'] === 'block' ) ? 'block' : 'classic';
|
||||
$allow_users = ! empty( $defaults['allow-users'] );
|
||||
} else {
|
||||
$allow_users = ( get_option( 'classic-editor-allow-users' ) === 'allow' );
|
||||
$option = get_option( 'classic-editor-replace' );
|
||||
|
||||
// Normalize old options.
|
||||
if ( $option === 'block' || $option === 'no-replace' ) {
|
||||
$editor = 'block';
|
||||
} else {
|
||||
// empty( $option ) || $option === 'classic' || $option === 'replace'
|
||||
$editor = 'classic';
|
||||
}
|
||||
}
|
||||
|
||||
// Override the defaults with the user options.
|
||||
if ( ( ! isset( $GLOBALS['pagenow'] ) || $GLOBALS['pagenow'] !== 'options-writing.php' ) && $allow_users ) {
|
||||
$user_options = get_user_option( 'classic-editor-settings' );
|
||||
|
||||
if ( $user_options === 'block' || $user_options === 'classic' ) {
|
||||
$editor = $user_options;
|
||||
}
|
||||
}
|
||||
|
||||
self::$settings = array(
|
||||
'editor' => $editor,
|
||||
'hide-settings-ui' => false,
|
||||
'allow-users' => $allow_users,
|
||||
);
|
||||
|
||||
return self::$settings;
|
||||
}
|
||||
|
||||
private static function is_classic( $post_id = 0 ) {
|
||||
if ( ! $post_id ) {
|
||||
$post_id = self::get_edited_post_id();
|
||||
}
|
||||
|
||||
if ( $post_id ) {
|
||||
$settings = self::get_settings();
|
||||
|
||||
if ( $settings['allow-users'] && ! isset( $_GET['classic-editor__forget'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
$which = get_post_meta( $post_id, 'classic-editor-remember', true );
|
||||
|
||||
if ( $which ) {
|
||||
// The editor choice will be "remembered" when the post is opened in either the classic or the block editor.
|
||||
if ( 'classic-editor' === $which ) {
|
||||
return true;
|
||||
} elseif ( 'block-editor' === $which ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return ( ! self::has_blocks( $post_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_GET['classic-editor'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the edited post ID (early) when loading the Edit Post screen.
|
||||
*/
|
||||
private static function get_edited_post_id() {
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
if (
|
||||
! empty( $_GET['post'] ) &&
|
||||
! empty( $_GET['action'] ) &&
|
||||
$_GET['action'] === 'edit' &&
|
||||
! empty( $GLOBALS['pagenow'] ) &&
|
||||
$GLOBALS['pagenow'] === 'post.php'
|
||||
) {
|
||||
return (int) $_GET['post']; // post_ID
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function register_settings() {
|
||||
// Add an option to Settings -> Writing
|
||||
register_setting( 'writing', 'classic-editor-replace', array(
|
||||
'sanitize_callback' => array( __CLASS__, 'validate_option_editor' ),
|
||||
) );
|
||||
|
||||
register_setting( 'writing', 'classic-editor-allow-users', array(
|
||||
'sanitize_callback' => array( __CLASS__, 'validate_option_allow_users' ),
|
||||
) );
|
||||
|
||||
$allowed_options = array(
|
||||
'writing' => array(
|
||||
'classic-editor-replace',
|
||||
'classic-editor-allow-users'
|
||||
),
|
||||
);
|
||||
|
||||
if ( function_exists( 'add_allowed_options' ) ) {
|
||||
add_allowed_options( $allowed_options );
|
||||
} else {
|
||||
add_option_whitelist( $allowed_options );
|
||||
}
|
||||
|
||||
$heading_1 = __( 'Default editor for all users', 'classic-editor' );
|
||||
$heading_2 = __( 'Allow users to switch editors', 'classic-editor' );
|
||||
|
||||
add_settings_field( 'classic-editor-1', $heading_1, array( __CLASS__, 'settings_1' ), 'writing' );
|
||||
add_settings_field( 'classic-editor-2', $heading_2, array( __CLASS__, 'settings_2' ), 'writing' );
|
||||
}
|
||||
|
||||
public static function save_user_settings( $user_id ) {
|
||||
if (
|
||||
isset( $_POST['classic-editor-user-settings'] ) &&
|
||||
isset( $_POST['classic-editor-replace'] ) &&
|
||||
wp_verify_nonce( $_POST['classic-editor-user-settings'], 'allow-user-settings' ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
) {
|
||||
$user_id = (int) $user_id;
|
||||
|
||||
if ( $user_id !== get_current_user_id() && ! current_user_can( 'edit_user', $user_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$editor = self::validate_option_editor( $_POST['classic-editor-replace'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
update_user_option( $user_id, 'classic-editor-settings', $editor );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate
|
||||
*/
|
||||
public static function validate_option_editor( $value ) {
|
||||
if ( $value === 'block' ) {
|
||||
return 'block';
|
||||
}
|
||||
|
||||
return 'classic';
|
||||
}
|
||||
|
||||
public static function validate_option_allow_users( $value ) {
|
||||
if ( $value === 'allow' ) {
|
||||
return 'allow';
|
||||
}
|
||||
|
||||
return 'disallow';
|
||||
}
|
||||
|
||||
public static function settings_1() {
|
||||
$settings = self::get_settings( 'refresh' );
|
||||
|
||||
?>
|
||||
<div class="classic-editor-options">
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-replace" id="classic-editor-classic" value="classic"<?php if ( $settings['editor'] === 'classic' ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-classic"><?php _ex( 'Classic editor', 'Editor Name', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-replace" id="classic-editor-block" value="block"<?php if ( $settings['editor'] !== 'classic' ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-block"><?php _ex( 'Block editor', 'Editor Name', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
jQuery( 'document' ).ready( function( $ ) {
|
||||
if ( window.location.hash === '#classic-editor-options' ) {
|
||||
$( '.classic-editor-options' ).closest( 'td' ).addClass( 'highlight' );
|
||||
}
|
||||
} );
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function settings_2() {
|
||||
$settings = self::get_settings( 'refresh' );
|
||||
|
||||
?>
|
||||
<div class="classic-editor-options">
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-allow-users" id="classic-editor-allow" value="allow"<?php if ( $settings['allow-users'] ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-allow"><?php _e( 'Yes', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-allow-users" id="classic-editor-disallow" value="disallow"<?php if ( ! $settings['allow-users'] ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-disallow"><?php _e( 'No', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Shown on the Profile page when allowed by admin.
|
||||
*/
|
||||
public static function user_settings() {
|
||||
global $user_can_edit;
|
||||
$settings = self::get_settings( 'update' );
|
||||
|
||||
if (
|
||||
! defined( 'IS_PROFILE_PAGE' ) ||
|
||||
! IS_PROFILE_PAGE ||
|
||||
! $user_can_edit ||
|
||||
! $settings['allow-users']
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<table class="form-table">
|
||||
<tr class="classic-editor-user-options">
|
||||
<th scope="row"><?php _e( 'Default Editor', 'classic-editor' ); ?></th>
|
||||
<td>
|
||||
<?php wp_nonce_field( 'allow-user-settings', 'classic-editor-user-settings' ); ?>
|
||||
<?php self::settings_1(); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>jQuery( 'tr.user-rich-editing-wrap' ).before( jQuery( 'tr.classic-editor-user-options' ) );</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function network_settings() {
|
||||
$editor = get_network_option( null, 'classic-editor-replace' );
|
||||
$is_checked = ( get_network_option( null, 'classic-editor-allow-sites' ) === 'allow' );
|
||||
|
||||
?>
|
||||
<h2 id="classic-editor-options"><?php _e( 'Editor Settings', 'classic-editor' ); ?></h2>
|
||||
<table class="form-table">
|
||||
<?php wp_nonce_field( 'allow-site-admin-settings', 'classic-editor-network-settings' ); ?>
|
||||
<tr>
|
||||
<th scope="row"><?php _e( 'Default editor for all sites', 'classic-editor' ); ?></th>
|
||||
<td>
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-replace" id="classic-editor-classic" value="classic"<?php if ( $editor !== 'block' ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-classic"><?php _ex( 'Classic Editor', 'Editor Name', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="classic-editor-replace" id="classic-editor-block" value="block"<?php if ( $editor === 'block' ) echo ' checked'; ?> />
|
||||
<label for="classic-editor-block"><?php _ex( 'Block editor', 'Editor Name', 'classic-editor' ); ?></label>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php _e( 'Change settings', 'classic-editor' ); ?></th>
|
||||
<td>
|
||||
<input type="checkbox" name="classic-editor-allow-sites" id="classic-editor-allow-sites" value="allow"<?php if ( $is_checked ) echo ' checked'; ?>>
|
||||
<label for="classic-editor-allow-sites"><?php _e( 'Allow site admins to change settings', 'classic-editor' ); ?></label>
|
||||
<p class="description"><?php _e( 'By default the block editor is replaced with the classic editor and users cannot switch editors.', 'classic-editor' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function save_network_settings() {
|
||||
if (
|
||||
isset( $_POST['classic-editor-network-settings'] ) &&
|
||||
current_user_can( 'manage_network_options' ) &&
|
||||
wp_verify_nonce( $_POST['classic-editor-network-settings'], 'allow-site-admin-settings' ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
) {
|
||||
if ( isset( $_POST['classic-editor-replace'] ) && $_POST['classic-editor-replace'] === 'block' ) {
|
||||
update_network_option( null, 'classic-editor-replace', 'block' );
|
||||
} else {
|
||||
update_network_option( null, 'classic-editor-replace', 'classic' );
|
||||
}
|
||||
if ( isset( $_POST['classic-editor-allow-sites'] ) && $_POST['classic-editor-allow-sites'] === 'allow' ) {
|
||||
update_network_option( null, 'classic-editor-allow-sites', 'allow' );
|
||||
} else {
|
||||
update_network_option( null, 'classic-editor-allow-sites', 'disallow' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hidden field in edit-form-advanced.php
|
||||
* to help redirect back to the classic editor on saving.
|
||||
*/
|
||||
public static function add_redirect_helper() {
|
||||
?>
|
||||
<input type="hidden" name="classic-editor" value="" />
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember when the classic editor was used to edit a post.
|
||||
*/
|
||||
public static function remember_classic_editor( $post ) {
|
||||
$post_type = get_post_type( $post );
|
||||
|
||||
if ( $post_type && post_type_supports( $post_type, 'editor' ) ) {
|
||||
self::remember( $post->ID, 'classic-editor' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember when the block editor was used to edit a post.
|
||||
*/
|
||||
public static function remember_block_editor( $editor_settings, $context ) {
|
||||
if ( is_a( $context, 'WP_Post' ) ) {
|
||||
$post = $context;
|
||||
} elseif ( ! empty( $context->post ) ) {
|
||||
$post = $context->post;
|
||||
} else {
|
||||
return $editor_settings;
|
||||
}
|
||||
|
||||
$post_type = get_post_type( $post );
|
||||
|
||||
if ( $post_type && self::can_edit_post_type( $post_type ) ) {
|
||||
self::remember( $post->ID, 'block-editor' );
|
||||
}
|
||||
|
||||
return $editor_settings;
|
||||
}
|
||||
|
||||
private static function remember( $post_id, $editor ) {
|
||||
if ( get_post_meta( $post_id, 'classic-editor-remember', true ) !== $editor ) {
|
||||
update_post_meta( $post_id, 'classic-editor-remember', $editor );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose which editor to use for a post.
|
||||
*
|
||||
* Passes through `$which_editor` for block editor (it's sets to `true` but may be changed by another plugin).
|
||||
*
|
||||
* @uses `use_block_editor_for_post` filter.
|
||||
*
|
||||
* @param boolean $use_block_editor True for block editor, false for classic editor.
|
||||
* @param WP_Post $post The post being edited.
|
||||
* @return boolean True for block editor, false for classic editor.
|
||||
*/
|
||||
public static function choose_editor( $use_block_editor, $post ) {
|
||||
$settings = self::get_settings();
|
||||
$editors = self::get_enabled_editors_for_post( $post );
|
||||
|
||||
// If no editor is supported, pass through `$use_block_editor`.
|
||||
if ( ! $editors['block_editor'] && ! $editors['classic_editor'] ) {
|
||||
return $use_block_editor;
|
||||
}
|
||||
|
||||
// Open the default editor when no $post and for "Add New" links,
|
||||
// or the alternate editor when the user is switching editors.
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
if ( empty( $post->ID ) || $post->post_status === 'auto-draft' ) {
|
||||
if (
|
||||
( $settings['editor'] === 'classic' && ! isset( $_GET['classic-editor__forget'] ) ) || // Add New
|
||||
( isset( $_GET['classic-editor'] ) && isset( $_GET['classic-editor__forget'] ) ) // Switch to classic editor when no draft post.
|
||||
) {
|
||||
$use_block_editor = false;
|
||||
}
|
||||
} elseif ( self::is_classic( $post->ID ) ) {
|
||||
$use_block_editor = false;
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
// Enforce the editor if set by plugins.
|
||||
if ( $use_block_editor && ! $editors['block_editor'] ) {
|
||||
$use_block_editor = false;
|
||||
} elseif ( ! $use_block_editor && ! $editors['classic_editor'] && $editors['block_editor'] ) {
|
||||
$use_block_editor = true;
|
||||
}
|
||||
|
||||
return $use_block_editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the `classic-editor` query arg through redirects when saving posts.
|
||||
*/
|
||||
public static function redirect_location( $location ) {
|
||||
if (
|
||||
isset( $_REQUEST['classic-editor'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
( isset( $_POST['_wp_http_referer'] ) && strpos( $_POST['_wp_http_referer'], '&classic-editor' ) !== false ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
|
||||
) {
|
||||
$location = add_query_arg( 'classic-editor', '', $location );
|
||||
}
|
||||
|
||||
return $location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the `classic-editor` query arg when looking at revisions.
|
||||
*/
|
||||
public static function get_edit_post_link( $url ) {
|
||||
$settings = self::get_settings();
|
||||
|
||||
if ( isset( $_REQUEST['classic-editor'] ) || $settings['editor'] === 'classic' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
$url = add_query_arg( 'classic-editor', '', $url );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function add_meta_box( $post_type, $post ) {
|
||||
$editors = self::get_enabled_editors_for_post( $post );
|
||||
|
||||
if ( ! $editors['block_editor'] || ! $editors['classic_editor'] ) {
|
||||
// Editors cannot be switched.
|
||||
return;
|
||||
}
|
||||
|
||||
$id = 'classic-editor-switch-editor';
|
||||
$title = __( 'Editor', 'classic-editor' );
|
||||
$callback = array( __CLASS__, 'do_meta_box' );
|
||||
$args = array(
|
||||
'__back_compat_meta_box' => true,
|
||||
);
|
||||
|
||||
add_meta_box( $id, $title, $callback, null, 'side', 'default', $args );
|
||||
}
|
||||
|
||||
public static function do_meta_box( $post ) {
|
||||
$edit_url = get_edit_post_link( $post->ID, 'raw' );
|
||||
|
||||
// Switching to block editor.
|
||||
$edit_url = remove_query_arg( 'classic-editor', $edit_url );
|
||||
// Forget the previous value when going to a specific editor.
|
||||
$edit_url = add_query_arg( 'classic-editor__forget', '', $edit_url );
|
||||
|
||||
?>
|
||||
<p style="margin: 1em 0;">
|
||||
<a href="<?php echo esc_url( $edit_url ); ?>"><?php _e( 'Switch to block editor', 'classic-editor' ); ?></a>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function enqueue_block_editor_scripts() {
|
||||
// get_enabled_editors_for_post() needs a WP_Post or post_ID.
|
||||
if ( empty( $GLOBALS['post'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$editors = self::get_enabled_editors_for_post( $GLOBALS['post'] );
|
||||
|
||||
if ( ! $editors['classic_editor'] ) {
|
||||
// Editor cannot be switched.
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'classic-editor-plugin',
|
||||
plugins_url( 'js/block-editor-plugin.js', __FILE__ ),
|
||||
array( 'wp-element', 'wp-components', 'lodash' ),
|
||||
'1.4',
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'classic-editor-plugin',
|
||||
'classicEditorPluginL10n',
|
||||
array( 'linkText' => __( 'Switch to classic editor', 'classic-editor' ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a link to the settings on the Plugins screen.
|
||||
*/
|
||||
public static function add_settings_link( $links, $file ) {
|
||||
$settings = self::get_settings();
|
||||
|
||||
if ( $file === 'classic-editor/classic-editor.php' && ! $settings['hide-settings-ui'] && current_user_can( 'manage_options' ) ) {
|
||||
if ( current_filter() === 'plugin_action_links' ) {
|
||||
$url = admin_url( 'options-writing.php#classic-editor-options' );
|
||||
} else {
|
||||
$url = admin_url( '/network/settings.php#classic-editor-options' );
|
||||
}
|
||||
|
||||
// Prevent warnings in PHP 7.0+ when a plugin uses this filter incorrectly.
|
||||
$links = (array) $links;
|
||||
$links[] = sprintf( '<a href="%s">%s</a>', $url, __( 'Settings', 'classic-editor' ) );
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
private static function can_edit_post_type( $post_type ) {
|
||||
$can_edit = false;
|
||||
|
||||
if ( function_exists( 'gutenberg_can_edit_post_type' ) ) {
|
||||
$can_edit = gutenberg_can_edit_post_type( $post_type );
|
||||
} elseif ( function_exists( 'use_block_editor_for_post_type' ) ) {
|
||||
$can_edit = use_block_editor_for_post_type( $post_type );
|
||||
}
|
||||
|
||||
return $can_edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which editors are enabled for the post type.
|
||||
*
|
||||
* @param string $post_type The post type.
|
||||
* @return array Associative array of the editors and whether they are enabled for the post type.
|
||||
*/
|
||||
private static function get_enabled_editors_for_post_type( $post_type ) {
|
||||
if ( isset( self::$supported_post_types[ $post_type ] ) ) {
|
||||
return self::$supported_post_types[ $post_type ];
|
||||
}
|
||||
|
||||
$classic_editor = post_type_supports( $post_type, 'editor' );
|
||||
$block_editor = self::can_edit_post_type( $post_type );
|
||||
|
||||
$editors = array(
|
||||
'classic_editor' => $classic_editor,
|
||||
'block_editor' => $block_editor,
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the editors that are enabled for the post type.
|
||||
*
|
||||
* @param array $editors Associative array of the editors and whether they are enabled for the post type.
|
||||
* @param string $post_type The post type.
|
||||
*/
|
||||
$editors = apply_filters( 'classic_editor_enabled_editors_for_post_type', $editors, $post_type );
|
||||
self::$supported_post_types[ $post_type ] = $editors;
|
||||
|
||||
return $editors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which editors are enabled for the post.
|
||||
*
|
||||
* @param WP_Post $post The post object.
|
||||
* @return array Associative array of the editors and whether they are enabled for the post.
|
||||
*/
|
||||
private static function get_enabled_editors_for_post( $post ) {
|
||||
$post_type = get_post_type( $post );
|
||||
|
||||
if ( ! $post_type ) {
|
||||
return array(
|
||||
'classic_editor' => false,
|
||||
'block_editor' => false,
|
||||
);
|
||||
}
|
||||
|
||||
$editors = self::get_enabled_editors_for_post_type( $post_type );
|
||||
|
||||
/**
|
||||
* Filters the editors that are enabled for the post.
|
||||
*
|
||||
* @param array $editors Associative array of the editors and whether they are enabled for the post.
|
||||
* @param WP_Post $post The post object.
|
||||
*/
|
||||
return apply_filters( 'classic_editor_enabled_editors_for_post', $editors, $post );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds links to the post/page screens to edit any post or page in
|
||||
* the classic editor or block editor.
|
||||
*
|
||||
* @param array $actions Post actions.
|
||||
* @param WP_Post $post Edited post.
|
||||
* @return array Updated post actions.
|
||||
*/
|
||||
public static function add_edit_links( $actions, $post ) {
|
||||
// This is in Gutenberg, don't duplicate it.
|
||||
if ( array_key_exists( 'classic', $actions ) ) {
|
||||
unset( $actions['classic'] );
|
||||
}
|
||||
|
||||
if ( ! array_key_exists( 'edit', $actions ) ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
$edit_url = get_edit_post_link( $post->ID, 'raw' );
|
||||
|
||||
if ( ! $edit_url ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
$editors = self::get_enabled_editors_for_post( $post );
|
||||
|
||||
// Do not show the links if only one editor is available.
|
||||
if ( ! $editors['classic_editor'] || ! $editors['block_editor'] ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
// Forget the previous value when going to a specific editor.
|
||||
$edit_url = add_query_arg( 'classic-editor__forget', '', $edit_url );
|
||||
|
||||
// Build the edit actions. See also: WP_Posts_List_Table::handle_row_actions().
|
||||
$title = _draft_or_post_title( $post->ID );
|
||||
|
||||
// Link to the block editor.
|
||||
$url = remove_query_arg( 'classic-editor', $edit_url );
|
||||
$text = _x( 'Edit (block editor)', 'Editor Name', 'classic-editor' );
|
||||
/* translators: %s: post title */
|
||||
$label = sprintf( __( 'Edit “%s” in the block editor', 'classic-editor' ), $title );
|
||||
$edit_block = sprintf( '<a href="%s" aria-label="%s">%s</a>', esc_url( $url ), esc_attr( $label ), $text );
|
||||
|
||||
// Link to the classic editor.
|
||||
$url = add_query_arg( 'classic-editor', '', $edit_url );
|
||||
$text = _x( 'Edit (classic editor)', 'Editor Name', 'classic-editor' );
|
||||
/* translators: %s: post title */
|
||||
$label = sprintf( __( 'Edit “%s” in the classic editor', 'classic-editor' ), $title );
|
||||
$edit_classic = sprintf( '<a href="%s" aria-label="%s">%s</a>', esc_url( $url ), esc_attr( $label ), $text );
|
||||
|
||||
$edit_actions = array(
|
||||
'classic-editor-block' => $edit_block,
|
||||
'classic-editor-classic' => $edit_classic,
|
||||
);
|
||||
|
||||
// Insert the new Edit actions instead of the Edit action.
|
||||
$edit_offset = array_search( 'edit', array_keys( $actions ), true );
|
||||
array_splice( $actions, $edit_offset, 1, $edit_actions );
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the editor that will be used in a "post state" in the Posts list table.
|
||||
*/
|
||||
public static function add_post_state( $post_states, $post ) {
|
||||
if ( get_post_status( $post ) === 'trash' ) {
|
||||
return $post_states;
|
||||
}
|
||||
|
||||
$editors = self::get_enabled_editors_for_post( $post );
|
||||
|
||||
if ( ! $editors['classic_editor'] && ! $editors['block_editor'] ) {
|
||||
return $post_states;
|
||||
} elseif ( $editors['classic_editor'] && ! $editors['block_editor'] ) {
|
||||
// Forced to classic editor.
|
||||
$state = '<span class="classic-editor-forced-state">' . _x( 'classic editor', 'Editor Name', 'classic-editor' ) . '</span>';
|
||||
} elseif ( ! $editors['classic_editor'] && $editors['block_editor'] ) {
|
||||
// Forced to block editor.
|
||||
$state = '<span class="classic-editor-forced-state">' . _x( 'block editor', 'Editor Name', 'classic-editor' ) . '</span>';
|
||||
} else {
|
||||
$last_editor = get_post_meta( $post->ID, 'classic-editor-remember', true );
|
||||
|
||||
if ( $last_editor ) {
|
||||
$is_classic = ( $last_editor === 'classic-editor' );
|
||||
} elseif ( ! empty( $post->post_content ) ) {
|
||||
$is_classic = ! self::has_blocks( $post->post_content );
|
||||
} else {
|
||||
$settings = self::get_settings();
|
||||
$is_classic = ( $settings['editor'] === 'classic' );
|
||||
}
|
||||
|
||||
$state = $is_classic ? _x( 'Classic editor', 'Editor Name', 'classic-editor' ) : _x( 'Block editor', 'Editor Name', 'classic-editor' );
|
||||
}
|
||||
|
||||
// Fix PHP 7+ warnings if another plugin returns unexpected type.
|
||||
$post_states = (array) $post_states;
|
||||
$post_states['classic-editor-plugin'] = $state;
|
||||
|
||||
return $post_states;
|
||||
}
|
||||
|
||||
public static function add_edit_php_inline_style() {
|
||||
?>
|
||||
<style>
|
||||
.classic-editor-forced-state {
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
color: #72777c;
|
||||
font-size: small;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function on_admin_init() {
|
||||
global $pagenow;
|
||||
|
||||
if ( $pagenow !== 'post.php' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = self::get_settings();
|
||||
$post_id = self::get_edited_post_id();
|
||||
|
||||
if ( $post_id && ( $settings['editor'] === 'classic' || self::is_classic( $post_id ) ) ) {
|
||||
// Move the Privacy Policy help notice back under the title field.
|
||||
remove_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'notice' ) );
|
||||
add_action( 'edit_form_after_title', array( 'WP_Privacy_Policy_Content', 'notice' ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Need to support WP < 5.0
|
||||
private static function has_blocks( $post = null ) {
|
||||
if ( ! is_string( $post ) ) {
|
||||
$wp_post = get_post( $post );
|
||||
|
||||
if ( $wp_post instanceof WP_Post ) {
|
||||
$post = $wp_post->post_content;
|
||||
}
|
||||
}
|
||||
|
||||
return false !== strpos( (string) $post, '<!-- wp:' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set defaults on activation.
|
||||
*/
|
||||
public static function activate() {
|
||||
register_uninstall_hook( __FILE__, array( __CLASS__, 'uninstall' ) );
|
||||
|
||||
if ( is_multisite() ) {
|
||||
add_network_option( null, 'classic-editor-replace', 'classic' );
|
||||
add_network_option( null, 'classic-editor-allow-sites', 'disallow' );
|
||||
}
|
||||
|
||||
add_option( 'classic-editor-replace', 'classic' );
|
||||
add_option( 'classic-editor-allow-users', 'disallow' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the options on uninstall.
|
||||
*/
|
||||
public static function uninstall() {
|
||||
if ( is_multisite() ) {
|
||||
delete_network_option( null, 'classic-editor-replace' );
|
||||
delete_network_option( null, 'classic-editor-allow-sites' );
|
||||
}
|
||||
|
||||
delete_option( 'classic-editor-replace' );
|
||||
delete_option( 'classic-editor-allow-users' );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'plugins_loaded', array( 'Classic_Editor', 'init_actions' ) );
|
||||
|
||||
endif;
|
||||
@@ -1,23 +0,0 @@
|
||||
( function( wp ) {
|
||||
if ( ! wp ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp.plugins.registerPlugin( 'classic-editor-plugin', {
|
||||
render: function() {
|
||||
var createElement = wp.element.createElement;
|
||||
var PluginMoreMenuItem = wp.editPost.PluginMoreMenuItem;
|
||||
var url = wp.url.addQueryArgs( document.location.href, { 'classic-editor': '', 'classic-editor__forget': '' } );
|
||||
var linkText = lodash.get( window, [ 'classicEditorPluginL10n', 'linkText' ] ) || 'Switch to classic editor';
|
||||
|
||||
return createElement(
|
||||
PluginMoreMenuItem,
|
||||
{
|
||||
icon: 'editor-kitchensink',
|
||||
href: url,
|
||||
},
|
||||
linkText
|
||||
);
|
||||
},
|
||||
} );
|
||||
} )( window.wp );
|
||||
@@ -1,138 +0,0 @@
|
||||
=== Classic Editor ===
|
||||
Contributors: wordpressdotorg, azaozz, melchoyce, chanthaboune, alexislloyd, pento, youknowriad, desrosj, luciano-croce
|
||||
Tags: gutenberg, disable, disable gutenberg, editor, classic editor, block editor
|
||||
Requires at least: 4.9
|
||||
Tested up to: 6.2
|
||||
Stable tag: 1.6.3
|
||||
Requires PHP: 5.2.4
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Enables the previous "classic" editor and the old-style Edit Post screen with TinyMCE, Meta Boxes, etc. Supports all plugins that extend this screen.
|
||||
|
||||
== Description ==
|
||||
|
||||
Classic Editor is an official plugin maintained by the WordPress team that restores the previous ("classic") WordPress editor and the "Edit Post" screen. It makes it possible to use plugins that extend that screen, add old-style meta boxes, or otherwise depend on the previous editor.
|
||||
|
||||
Classic Editor is an official WordPress plugin, and will be fully supported and maintained until 2024, or as long as is necessary.
|
||||
|
||||
At a glance, this plugin adds the following:
|
||||
|
||||
* Administrators can select the default editor for all users.
|
||||
* Administrators can allow users to change their default editor.
|
||||
* When allowed, the users can choose which editor to use for each post.
|
||||
* Each post opens in the last editor used regardless of who edited it last. This is important for maintaining a consistent experience when editing content.
|
||||
|
||||
In addition, the Classic Editor plugin includes several filters that let other plugins control the settings, and the editor choice per post and per post type.
|
||||
|
||||
By default, this plugin hides all functionality available in the new block editor ("Gutenberg").
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.6.3 =
|
||||
* Added some WPCS fixes, props NicktheGeek on GitHub.
|
||||
* Updated "Tested up to" in the readme and removed it from classic-editor.php. This should fix false positive errors in security plugins in the future.
|
||||
|
||||
= 1.6.2 =
|
||||
* Fixed bug that was preventing saving of the last used editor.
|
||||
|
||||
= 1.6.1 =
|
||||
* Fixed a warning on the block editor based widgets screen.
|
||||
* Fixed use of a deprecated filter.
|
||||
|
||||
= 1.6 =
|
||||
* Updated for WordPress 5.5.
|
||||
* Fixed minor issues with calling deprecated functions, needlessly registering uninstall hook, and capitalization of some strings.
|
||||
|
||||
= 1.5 =
|
||||
* Updated for WordPress 5.2 and Gutenberg 5.3.
|
||||
* Enhanced and fixed the "open posts in the last editor used to edit them" logic.
|
||||
* Fixed adding post state so it can easily be accessed from other plugins.
|
||||
|
||||
= 1.4 =
|
||||
* On network installations removed the restriction for only network activation.
|
||||
* Added support for network administrators to choose the default network-wide editor.
|
||||
* Fixed the settings link in the warning on network About screen.
|
||||
* Properly added the "Switch to classic editor" menu item to the block editor menu.
|
||||
|
||||
= 1.3 =
|
||||
* Fixed removal of the "Try Gutenberg" dashboard widget.
|
||||
* Fixed condition for displaying of the after upgrade notice on the "What's New" screen. Shown when the classic editor is selected and users cannot switch editors.
|
||||
|
||||
= 1.2 =
|
||||
* Fixed switching editors from the Add New (post) screen before a draft post is saved.
|
||||
* Fixed typo that was appending the edit URL to the `classic-editor` query var.
|
||||
* Changed detecting of WordPress 5.0 to not use version check. Fixes a bug when testing 5.1-alpha.
|
||||
* Changed the default value of the option to allow users to switch editors to false.
|
||||
* Added disabling of the Gutenberg plugin and lowered the required WordPress version to 4.9.
|
||||
* Added `classic_editor_network_default_settings` filter.
|
||||
|
||||
= 1.1 =
|
||||
Fixed a bug where it may attempt to load the block editor for post types that do not support editor when users are allowed to switch editors.
|
||||
|
||||
= 1.0 =
|
||||
* Updated for WordPress 5.0.
|
||||
* Changed all "Gutenberg" names/references to "block editor".
|
||||
* Refreshed the settings UI.
|
||||
* Removed disabling of the Gutenberg plugin. This was added for testing in WordPress 4.9. Users who want to continue following the development of Gutenberg in WordPress 5.0 and beyond will not need another plugin to disable it.
|
||||
* Added support for per-user settings of default editor.
|
||||
* Added support for admins to set the default editor for the site.
|
||||
* Added support for admins to allow users to change their default editor.
|
||||
* Added support for network admins to prevent site admins from changing the default settings.
|
||||
* Added support to store the last editor used for each post and open it next time. Enabled when users can choose default editor.
|
||||
* Added "post editor state" in the listing of posts on the Posts screen. Shows the editor that will be opened for the post. Enabled when users can choose default editor.
|
||||
* Added `classic_editor_enabled_editors_for_post` and `classic_editor_enabled_editors_for_post_type` filters. Can be used by other plugins to control or override the editor used for a particular post of post type.
|
||||
* Added `classic_editor_plugin_settings` filter. Can be used by other plugins to override the settings and disable the settings UI.
|
||||
|
||||
= 0.5 =
|
||||
* Updated for Gutenberg 4.1 and WordPress 5.0-beta1.
|
||||
* Removed some functionality that now exists in Gutenberg.
|
||||
* Fixed redirecting back to the classic editor after looking at post revisions.
|
||||
|
||||
= 0.4 =
|
||||
* Fixed removing of the "Try Gutenberg" call-out when the Gutenberg plugin is not activated.
|
||||
* Fixed to always show the settings and the settings link in the plugins list table.
|
||||
* Updated the readme text.
|
||||
|
||||
= 0.3 =
|
||||
* Updated the option from a checkbox to couple of radio buttons, seems clearer. Thanks to @designsimply for the label text suggestions.
|
||||
* Some general updates and cleanup.
|
||||
|
||||
= 0.2 =
|
||||
* Update for Gutenberg 1.9.
|
||||
* Remove warning and automatic deactivation when Gutenberg is not active.
|
||||
|
||||
= 0.1 =
|
||||
Initial release.
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= Default settings =
|
||||
|
||||
When activated and when using a classic (non-block) theme, this plugin will restore the previous ("classic") WordPress editor and hide the new block editor ("Gutenberg").
|
||||
These settings can be changed at the Settings => Writing screen.
|
||||
|
||||
= Default settings for network installation =
|
||||
|
||||
There are two options:
|
||||
|
||||
* When network-activated and when using a classic (non-block) theme, this plugin will set the classic editor as default and prevent site administrators and users from changing editors.
|
||||
The settings can be changed and default network-wide editor can be selected on the Network Settings screen.
|
||||
* When not network-activated each site administrator will be able to activate the plugin and choose options for their users.
|
||||
|
||||
= Cannot find the "Switch to classic editor" link =
|
||||
|
||||
It is in the main block editor menu, see this [screenshot](https://ps.w.org/classic-editor/assets/screenshot-7.png?rev=2023480).
|
||||
|
||||
= Does this work with full site editing and block themes? =
|
||||
|
||||
No, as block themes rely on blocks. [See Block themes article](https://wordpress.org/support/article/block-themes/) for more information.
|
||||
|
||||
== Screenshots ==
|
||||
1. Admin settings on the Settings -> Writing screen.
|
||||
2. User settings on the Profile screen. Visible when the users are allowed to switch editors.
|
||||
3. "Action links" to choose alternative editor. Visible when the users are allowed to switch editors.
|
||||
4. Link to switch to the block editor while editing a post in the classic editor. Visible when the users are allowed to switch editors.
|
||||
5. Link to switch to the classic editor while editing a post in the block editor. Visible when the users are allowed to switch editors.
|
||||
6. Network settings to select the default editor for the network and allow site admins to change it.
|
||||
7. The "Switch to classic editor" link.
|
||||
@@ -1,229 +0,0 @@
|
||||
window['$'] = window['$'] || jQuery.noConflict();
|
||||
var dtx = {
|
||||
queue: [],
|
||||
init: function() {
|
||||
var $inputs = $('input.dtx-pageload[data-dtx-value]');
|
||||
if ($inputs.length) {
|
||||
// If this is any of our built-in shortcodes, see if there's any that can be duplicated via client side
|
||||
$inputs.each(function(i, el) {
|
||||
var $input = $(el),
|
||||
raw_value = $input.attr('data-dtx-value'),
|
||||
v = decodeURIComponent(raw_value).split(' ');
|
||||
if (v.length) {
|
||||
var tag = v[0],
|
||||
atts = {};
|
||||
if (v.length > 1) {
|
||||
for (var x = 1; x < v.length; x++) {
|
||||
var att = v[x].split('=');
|
||||
if (att.length === 2) {
|
||||
var key = att[0];
|
||||
atts[key] = att[1].split("'").join('');
|
||||
}
|
||||
}
|
||||
}
|
||||
var value = '';
|
||||
switch (tag) {
|
||||
case 'CF7_GET':
|
||||
value = dtx.get(atts);
|
||||
break;
|
||||
case 'CF7_referrer':
|
||||
value = dtx.referrer(atts);
|
||||
break;
|
||||
case 'CF7_URL':
|
||||
value = dtx.current_url(atts);
|
||||
break;
|
||||
case 'CF7_get_cookie':
|
||||
value = dtx.get_cookie(atts);
|
||||
break;
|
||||
case 'CF7_guid':
|
||||
value = dtx.guid();
|
||||
break;
|
||||
case 'CF7_get_current_var':
|
||||
if (dtx.validKey(atts, 'key') && atts.key == 'url') {
|
||||
value = dtx.current_url(atts);
|
||||
} else {
|
||||
return; // Do nothing, current page variables are safe to cache, just use the value that was calculated by server
|
||||
}
|
||||
break;
|
||||
case 'CF7_get_post_var': // Current post variables are safe to cache
|
||||
case 'CF7_get_custom_field': // Meta data is safe to cache
|
||||
case 'CF7_get_taxonomy': // Terms are safe to cache
|
||||
case 'CF7_get_attachment': // Media attachment info is safe to cache
|
||||
case 'CF7_bloginfo': // Site info is safe to cache
|
||||
case 'CF7_get_theme_option': // Theme options are safe to cache
|
||||
return; // Do nothing, just use the value that was calculated by server
|
||||
default:
|
||||
if (tag) {
|
||||
// Queue the requests for an AJAX call at the end of init
|
||||
dtx.queue.push({ 'value': raw_value, 'multiline': $input.is('textarea') });
|
||||
}
|
||||
return; // Don't continue after queuing it for AJAX
|
||||
}
|
||||
dtx.set($input, value);
|
||||
}
|
||||
});
|
||||
if (dtx.queue.length) {
|
||||
setTimeout(function() { // Set timeout to force it async
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dtx_obj.ajax_url,
|
||||
dataType: 'json', // only accept strict JSON objects
|
||||
data: {
|
||||
'action': 'wpcf7dtx',
|
||||
'shortcodes': dtx.queue
|
||||
},
|
||||
cache: false,
|
||||
error: function(xhr, status, error) {
|
||||
console.error('[CF7 DTX AJAX ERROR]', error, status, xhr);
|
||||
},
|
||||
success: function(data, status, xhr) {
|
||||
if (typeof(data) == 'object' && data.length) {
|
||||
$.each(data, function(i, obj) {
|
||||
var $inputs = $('.wpcf7 form input.dtx-pageload[data-dtx-value="' + obj.raw_value + '"]');
|
||||
if ($inputs.length) {
|
||||
$inputs.addClass('dtx-ajax-loaded');
|
||||
dtx.set($inputs, obj.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Check if Key Exists in Object
|
||||
*/
|
||||
validKey: function(obj, key) {
|
||||
return obj.hasOwnProperty(key) && typeof(obj[key]) == 'string' && obj[key].trim();
|
||||
},
|
||||
/**
|
||||
* Maybe Obfuscate Value
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-attribute-obfuscate/
|
||||
*/
|
||||
obfuscate: function(value, atts) {
|
||||
value = value.trim();
|
||||
if (dtx.validKey(atts, 'obfuscate') && atts.obfuscate) {
|
||||
var o = '';
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
o += '&#' + value.codePointAt(i) + ';';
|
||||
}
|
||||
return o;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
/**
|
||||
* Set Value for Form Field
|
||||
*/
|
||||
set: function($input, value) {
|
||||
$input
|
||||
.attr('value', value)
|
||||
.addClass('dtx-loaded')
|
||||
.trigger('dtx_init');
|
||||
},
|
||||
/**
|
||||
* Get Value form URL Query by Key
|
||||
*
|
||||
* @see @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-php-get-variables/
|
||||
*/
|
||||
get: function(atts) {
|
||||
if (dtx.validKey(atts, 'key')) {
|
||||
var query = window.location.search;
|
||||
if (query) {
|
||||
query = new URLSearchParams(query);
|
||||
return dtx.obfuscate(query.get(atts.key).trim(), atts);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* Get Referrering URL
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-referrer-url/
|
||||
*/
|
||||
referrer: function(atts) {
|
||||
return dtx.obfuscate(document.referrer, atts);
|
||||
},
|
||||
/**
|
||||
* Get Current URL or Part
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-url/
|
||||
*/
|
||||
current_url: function(atts) {
|
||||
if (atts.hasOwnProperty('part')) {
|
||||
var parts = [
|
||||
'scheme', // e.g. `http`
|
||||
'host',
|
||||
'port',
|
||||
'path',
|
||||
'query', // after the question mark ?
|
||||
'fragment' // after the pound sign #
|
||||
];
|
||||
if (parts.includes(atts.part)) {
|
||||
// return part of the url
|
||||
switch (atts.part) {
|
||||
case 'scheme':
|
||||
return dtx.obfuscate(window.location.protocol.replace(':', ''), atts);
|
||||
case 'host':
|
||||
return dtx.obfuscate(window.location.host, atts);
|
||||
case 'port':
|
||||
return dtx.obfuscate(window.location.port, atts);
|
||||
case 'path':
|
||||
return dtx.obfuscate(window.location.pathname, atts);
|
||||
case 'query':
|
||||
return dtx.obfuscate(window.location.search.replace('?', ''), atts);
|
||||
case 'fragment':
|
||||
return dtx.obfuscate(window.location.hash.replace('#', ''), atts);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return dtx.obfuscate(window.location.href, atts); // Return the full url
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* Get Cookie Value
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-cookie/
|
||||
*/
|
||||
get_cookie: function(atts) {
|
||||
if (atts.hasOwnProperty('key') && typeof(atts.key) == 'string' && atts.key.trim() != '') {
|
||||
var keyValue = document.cookie.match('(^|;) ?' + atts.key.trim() + '=([^;]*)(;|$)');
|
||||
return keyValue ? dtx.obfuscate(keyValue[2], atts) : '';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* Generate a random GUID (globally unique identifier)
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-guid/
|
||||
*/
|
||||
guid: function() {
|
||||
if (typeof(window.crypto) != 'undefined' && typeof(window.crypto.getRandomValues) != 'undefined') {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||
).toUpperCase();
|
||||
}
|
||||
console.warn('[CF7 DTX] Cryptographically secure PRNG is not available for generating GUID value');
|
||||
var d = new Date().getTime(), //Timestamp
|
||||
d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0; //Time in microseconds since page-load or 0 if unsupported
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16; //random number between 0 and 16
|
||||
if (d > 0) { //Use timestamp until depleted
|
||||
r = (d + r) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
} else { //Use microseconds since page-load if supported
|
||||
r = (d2 + r) % 16 | 0;
|
||||
d2 = Math.floor(d2 / 16);
|
||||
}
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16).toUpperCase();
|
||||
}).toUpperCase();;
|
||||
}
|
||||
};
|
||||
$(document).ready(dtx.init);
|
||||
@@ -1,2 +0,0 @@
|
||||
/*! Do not edit, this file is generated automatically - 2024-04-15 15:04:12 EDT */
|
||||
window.$=window.$||jQuery.noConflict();var dtx={queue:[],init:function(){var e=$("input.dtx-pageload[data-dtx-value]");e.length&&(e.each(function(e,t){var r=$(t),a=r.attr("data-dtx-value"),o=decodeURIComponent(a).split(" ");if(o.length){var n=o[0],c={};if(1<o.length)for(var i=1;i<o.length;i++){var u=o[i].split("="),d;2===u.length&&(c[u[0]]=u[1].split("'").join(""))}var s="";switch(n){case"CF7_GET":s=dtx.get(c);break;case"CF7_referrer":s=dtx.referrer(c);break;case"CF7_URL":s=dtx.current_url(c);break;case"CF7_get_cookie":s=dtx.get_cookie(c);break;case"CF7_guid":s=dtx.guid();break;case"CF7_get_current_var":if(!dtx.validKey(c,"key")||"url"!=c.key)return;s=dtx.current_url(c);break;case"CF7_get_post_var":case"CF7_get_custom_field":case"CF7_get_taxonomy":case"CF7_get_attachment":case"CF7_bloginfo":case"CF7_get_theme_option":return;default:return void(n&&dtx.queue.push({value:a,multiline:r.is("textarea")}))}dtx.set(r,s)}}),dtx.queue.length)&&setTimeout(function(){$.ajax({type:"POST",url:dtx_obj.ajax_url,dataType:"json",data:{action:"wpcf7dtx",shortcodes:dtx.queue},cache:!1,error:function(e,t,r){},success:function(e,t,r){"object"==typeof e&&e.length&&$.each(e,function(e,t){var r=$('.wpcf7 form input.dtx-pageload[data-dtx-value="'+t.raw_value+'"]');r.length&&(r.addClass("dtx-ajax-loaded"),dtx.set(r,t.value))})}})},10)},validKey:function(e,t){return e.hasOwnProperty(t)&&"string"==typeof e[t]&&e[t].trim()},obfuscate:function(e,t){if(e=e.trim(),dtx.validKey(t,"obfuscate")&&t.obfuscate){for(var r="",a=0;a<e.length;a++)r+="&#"+e.codePointAt(a)+";";return r}return e},set:function(e,t){e.attr("value",t).addClass("dtx-loaded").trigger("dtx_init")},get:function(e){if(dtx.validKey(e,"key")){var t=window.location.search;if(t)return t=new URLSearchParams(t),dtx.obfuscate(t.get(e.key).trim(),e)}return""},referrer:function(e){return dtx.obfuscate(document.referrer,e)},current_url:function(e){if(!e.hasOwnProperty("part"))return dtx.obfuscate(window.location.href,e);var t;if(["scheme","host","port","path","query","fragment"].includes(e.part))switch(e.part){case"scheme":return dtx.obfuscate(window.location.protocol.replace(":",""),e);case"host":return dtx.obfuscate(window.location.host,e);case"port":return dtx.obfuscate(window.location.port,e);case"path":return dtx.obfuscate(window.location.pathname,e);case"query":return dtx.obfuscate(window.location.search.replace("?",""),e);case"fragment":return dtx.obfuscate(window.location.hash.replace("#",""),e)}return""},get_cookie:function(e){var t;return e.hasOwnProperty("key")&&"string"==typeof e.key&&""!=e.key.trim()&&(t=document.cookie.match("(^|;) ?"+e.key.trim()+"=([^;]*)(;|$)"))?dtx.obfuscate(t[2],e):""},guid:function(){var r,a;return(void 0!==window.crypto&&void 0!==window.crypto.getRandomValues?([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16)):(r=(new Date).getTime(),a="undefined"!=typeof performance&&performance.now&&1e3*performance.now()||0,"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random();return 0<r?(t=(r+t)%16|0,r=Math.floor(r/16)):(t=(a+t)%16|0,a=Math.floor(a/16)),("x"===e?t:3&t|8).toString(16).toUpperCase()}))).toUpperCase()}};$(document).ready(dtx.init);
|
||||
@@ -1,101 +0,0 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
if (typeof wpcf7 === 'undefined' || wpcf7 === null) {
|
||||
return;
|
||||
}
|
||||
window.wpcf7dtx = window.wpcf7dtx || {};
|
||||
wpcf7dtx.taggen = {};
|
||||
|
||||
$('input.dtx-insert-tag').click(function() {
|
||||
var $form = $(this).closest('form.tag-generator-panel');
|
||||
var tag = $form.find('.insert-box .tag').val();
|
||||
wpcf7.taggen.insert(tag);
|
||||
tb_remove(); // close thickbox
|
||||
return false;
|
||||
});
|
||||
|
||||
wpcf7dtx.taggen.escapeRegExp = function(str) {
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
||||
};
|
||||
|
||||
wpcf7dtx.taggen.replaceAll = function(input, f, r, no_escape) {
|
||||
if (input !== undefined && input !== null && typeof(input) == 'string' && input.trim() !== '' && input.indexOf(f) > -1) {
|
||||
var rexp = new RegExp(wpcf7dtx.taggen.escapeRegExp(f), 'g');
|
||||
if (no_escape) { rexp = new RegExp(f, 'g'); }
|
||||
return input.replace(rexp, r);
|
||||
}
|
||||
return input;
|
||||
};
|
||||
|
||||
// Overwrite update function to allow the textarea display for advanced tags
|
||||
wpcf7.taggen.update = function($form) {
|
||||
var id = $form.attr('data-id');
|
||||
var name = '';
|
||||
var name_fields = $form.find('input[name="name"]');
|
||||
|
||||
if (name_fields.length) {
|
||||
name = name_fields.val();
|
||||
if ('' === name) {
|
||||
name = id + '-' + Math.floor(Math.random() * 1000);
|
||||
name_fields.val(name);
|
||||
}
|
||||
}
|
||||
|
||||
if ($.isFunction(wpcf7.taggen.update[id])) {
|
||||
return wpcf7.taggen.update[id].call(this, $form);
|
||||
}
|
||||
|
||||
let $display = $form.find('.insert-box .tag');
|
||||
// if (!$display.length) {
|
||||
// $display = $form.find('textarea.tag');
|
||||
// }
|
||||
|
||||
$display.each(function() {
|
||||
var tag_type = $(this).attr('name');
|
||||
|
||||
if ($form.find(':input[name="tagtype"]').length) {
|
||||
tag_type = $form.find(':input[name="tagtype"]').val();
|
||||
}
|
||||
|
||||
if ($form.find(':input[name="required"]').is(':checked')) {
|
||||
tag_type += '*';
|
||||
}
|
||||
|
||||
var components = wpcf7.taggen.compose(tag_type, $form);
|
||||
$(this).val(components);
|
||||
});
|
||||
|
||||
$form.find('span.mail-tag').text('[' + name + ']');
|
||||
$form.find('input.mail-tag').each(function() {
|
||||
$(this).val('[' + name + ']');
|
||||
});
|
||||
};
|
||||
|
||||
wpcf7dtx.taggen.updateOption = function(e) {
|
||||
var $this = $(e.currentTarget),
|
||||
value = encodeURIComponent(wpcf7dtx.taggen.replaceAll($this.val(), "'", ''')),
|
||||
$option = $this.siblings('input[type="hidden"].option');
|
||||
$option.val(value);
|
||||
if (e.type != 'change') {
|
||||
// DTX only listens for "change" so force the tag to rebuild for our other listeners
|
||||
$option.trigger('change');
|
||||
}
|
||||
};
|
||||
|
||||
$(function() {
|
||||
$('form.tag-generator-panel .dtx-option').on('change keyup click', wpcf7dtx.taggen.updateOption);
|
||||
$('.contact-form-editor-panel #tag-generator-list a.thickbox.button[href*="inlineId=tag-generator-panel-dynamic_"]').each(function() {
|
||||
var $btn = $(this),
|
||||
name = $btn.text();
|
||||
$btn.addClass('dtx-form-tag');
|
||||
if (
|
||||
name.indexOf('dynamic ') === 0 && // Set size of tag generator to be larger for dynamic fields
|
||||
name.indexOf('hidden') < 0 && // Except for this one because it doesn't have a lot of options
|
||||
name.indexOf('label') < 0 && // Except for this one because it doesn't have a lot of options
|
||||
name.indexOf('submit') < 0 // Except for this one because it doesn't have a lot of options
|
||||
) {
|
||||
$btn.attr('href', $btn.attr('href').replace('height=500', 'height=785'));
|
||||
}
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -1,2 +0,0 @@
|
||||
/*! Do not edit, this file is generated automatically - 2024-04-15 15:04:12 EDT */
|
||||
!function(g){"use strict";"undefined"!=typeof wpcf7&&null!==wpcf7&&(window.wpcf7dtx=window.wpcf7dtx||{},wpcf7dtx.taggen={},g("input.dtx-insert-tag").click(function(){var t,e=g(this).closest("form.tag-generator-panel").find(".insert-box .tag").val();return wpcf7.taggen.insert(e),tb_remove(),!1}),wpcf7dtx.taggen.escapeRegExp=function(t){return t.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")},wpcf7dtx.taggen.replaceAll=function(t,e,n,a){var i;return null!=t&&"string"==typeof t&&""!==t.trim()&&-1<t.indexOf(e)?(i=new RegExp(wpcf7dtx.taggen.escapeRegExp(e),"g"),a&&(i=new RegExp(e,"g")),t.replace(i,n)):t},wpcf7.taggen.update=function(e){var t=e.attr("data-id"),n="",a=e.find('input[name="name"]'),i;if(a.length&&""===(n=a.val())&&(n=t+"-"+Math.floor(1e3*Math.random()),a.val(n)),g.isFunction(wpcf7.taggen.update[t]))return wpcf7.taggen.update[t].call(this,e);e.find(".insert-box .tag").each(function(){var t=g(this).attr("name"),t=(e.find(':input[name="tagtype"]').length&&(t=e.find(':input[name="tagtype"]').val()),e.find(':input[name="required"]').is(":checked")&&(t+="*"),wpcf7.taggen.compose(t,e));g(this).val(t)}),e.find("span.mail-tag").text("["+n+"]"),e.find("input.mail-tag").each(function(){g(this).val("["+n+"]")})},wpcf7dtx.taggen.updateOption=function(t){var e=g(t.currentTarget),n=encodeURIComponent(wpcf7dtx.taggen.replaceAll(e.val(),"'","'")),e=e.siblings('input[type="hidden"].option');e.val(n),"change"!=t.type&&e.trigger("change")},g(function(){g("form.tag-generator-panel .dtx-option").on("change keyup click",wpcf7dtx.taggen.updateOption),g('.contact-form-editor-panel #tag-generator-list a.thickbox.button[href*="inlineId=tag-generator-panel-dynamic_"]').each(function(){var t=g(this),e=t.text();t.addClass("dtx-form-tag"),0===e.indexOf("dynamic ")&&e.indexOf("hidden")<0&&e.indexOf("label")<0&&e.indexOf("submit")<0&&t.attr("href",t.attr("href").replace("height=500","height=785"))})}))}(jQuery);
|
||||
@@ -1,67 +0,0 @@
|
||||
.tag-generator-panel[data-id^="dynamic_"]:not([data-id*="hidden"]):not([data-id*="label"]):not([data-id*="submit"]) {
|
||||
/* Set size of tag generator to be larger for dynamic fields, except for these because they don't have a lot of options */
|
||||
height: 775px;
|
||||
}
|
||||
|
||||
#tag-generator-list a.button.dtx-form-tag {
|
||||
border-color: #765cb9;
|
||||
color: #765cb9;
|
||||
}
|
||||
|
||||
.tag-generator-panel table.form-table th {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.tag-generator-panel table.form-table td small {
|
||||
display: block;
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input.oneline,
|
||||
.tag-generator-panel .control-box input.multiline,
|
||||
.tag-generator-panel .control-box textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input[list],
|
||||
.tag-generator-panel .control-box input.multiline,
|
||||
.tag-generator-panel .control-box textarea {
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input.multiline {
|
||||
display: inline-block;
|
||||
/* -webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none; */
|
||||
resize: vertical;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box textarea {
|
||||
height: 3.5em;
|
||||
}
|
||||
|
||||
.tag-generator-panel table.form-table td .wpcf7dtx-mini-att,
|
||||
.tag-generator-panel table.form-table td .wpcf7dtx-mini-att label,
|
||||
.tag-generator-panel table.form-table td .wpcf7dtx-mini-att input[type="text"] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box textarea.tag {
|
||||
border-radius: 4px;
|
||||
border: 1px solid #8c8f94;
|
||||
color: #2c3338;
|
||||
/* padding: 0 8px; */
|
||||
/* line-height: 2; */
|
||||
min-height: 30px;
|
||||
width: 500px;
|
||||
float: left;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
.tag-generator-panel[data-id^=dynamic_]:not([data-id*=hidden]):not([data-id*=label]):not([data-id*=submit]){height:775px}#tag-generator-list a.button.dtx-form-tag{border-color:#765cb9;color:#765cb9}.tag-generator-panel table.form-table th{width:130px}.tag-generator-panel table.form-table td small{display:block;margin-top:.25em}.tag-generator-panel .control-box input.multiline,.tag-generator-panel .control-box input.oneline,.tag-generator-panel .control-box textarea{width:100%}.tag-generator-panel .control-box input.multiline,.tag-generator-panel .control-box input[list],.tag-generator-panel .control-box textarea{height:30px;min-height:30px}.tag-generator-panel .control-box input.multiline{display:inline-block;resize:vertical;overflow-x:hidden;overflow-y:scroll}.tag-generator-panel .control-box textarea{height:3.5em}.tag-generator-panel table.form-table td .wpcf7dtx-mini-att,.tag-generator-panel table.form-table td .wpcf7dtx-mini-att input[type=text],.tag-generator-panel table.form-table td .wpcf7dtx-mini-att label{vertical-align:middle}.tag-generator-panel .insert-box textarea.tag{border-radius:4px;border:1px solid #8c8f94;color:#2c3338;min-height:30px;width:500px;float:left;background-color:transparent;box-shadow:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}
|
||||
@@ -1,267 +0,0 @@
|
||||
== Changelog ==
|
||||
|
||||
= 4.4.2 =
|
||||
|
||||
* Fix: Addressed PHP warning for undefined variable $default_placeholder introduced in version 4.4.0, [see support thread](https://wordpress.org/support/topic/php-warning-undefined-variable-default_placeholder/)
|
||||
* Minor: Create preview link using WordPress Playground, [check it out](https://wordpress.org/plugins/contact-form-7-dynamic-text-extension/?preview=1)
|
||||
|
||||
= 4.4.1 =
|
||||
|
||||
* Fix: Addressed PHP warnings for undefined array keys introduced in version 4.4.0, [see support thread](https://wordpress.org/support/topic/tons-of-errors-in-error_log/)
|
||||
|
||||
= 4.4.0 =
|
||||
|
||||
* Update: Added *Contact Form 7* (CF7) as a requirement as introduced in WordPress version 6.5. This plugin cannot be activated until CF7 is installed and activated.
|
||||
* Feature: introduced `dynamic_label` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-label/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: updated the following attributes to be dynamic: `autocapitalize`, `autocomplete`, `autofocus`, `cols`, `disabled`, `list`, `max`, `maxlength`, `min`, `minlength`, `pattern`, `readonly`, `size`, and `step`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Update: Updated the form tag generator for checkboxes and radio buttons to include documentation for the `default` attribute.
|
||||
* Update: Updated the form tag generator with fields for `min`, `max`, `step`, `minlength`, `maxlength`, and `autocomplete` for appropriate form tags. The `autocomplete` and `autocapitalize` are text fields that uses a `datalist` because I always forget those things...
|
||||
* Update: Increased the tag generator size to accommodate the new attributes.
|
||||
* Update: Some form tag generators display the generated form tag in a `textarea` to accommodate lengthy generated form tags.
|
||||
|
||||
= 4.3.1 =
|
||||
|
||||
* Fix: Resolved the PHP warning regarding `Undefined array key "value" in /.../contact-form-7-dynamic-text-extension/contact-form-7-dynamic-text-extension.php on line 391`, [see support thread](https://wordpress.org/support/topic/undefined-array-key-value-2/).
|
||||
* Fix: Resolved a bug introduced in version 4.2.1 that prevented the mail template validator from recognizing DTX form tags, [see support thread](https://wordpress.org/support/topic/email-field-validation-4/).
|
||||
* Fix: The `default` attribute for `dynamic_checkbox` can now accept multiple values that are delimited by an underscore (_), making it consistent with [Contact Form 7](https://contactform7.com/checkboxes-radio-buttons-and-menus/#checkbox-radio), [see support thread](https://wordpress.org/support/topic/help-dynamic_checkbox-and-default-values/).
|
||||
|
||||
= 4.3.0 =
|
||||
|
||||
* Feature: Added the `wpcf7dtx_shortcode` filter to all built-in shortcodes as requested. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/filter-modify-built-in-shortcode-responses/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
* Fix: Resolved a bug that prevented using the number zero as the value for select fields, checkboxes, and radio buttons, [see support thread](https://wordpress.org/support/topic/error-with-option-value-0-for-a-dynamic-radio-button/).
|
||||
|
||||
= 4.2.3 =
|
||||
|
||||
* Fix: Resolved a bug where the `dynamic_select` displayed with a default size of 40 instead of 1.
|
||||
|
||||
= 4.2.2 =
|
||||
|
||||
* Feature: Cache compatibility JavaScript triggers the custom `dtx_init` event on enabled input fields, [see support thread](https://wordpress.org/support/topic/dynamic_text-cf7_url-dont-fire-onchange-event/).
|
||||
|
||||
= 4.2.1 =
|
||||
|
||||
* Feature: Allows text-based fields to use `autocapitalize` attribute
|
||||
* Feature: Allows text-based fields to use `autofocus` attribute
|
||||
* Feature: Allows text-based fields to use `list` attribute
|
||||
* Feature: Allows text-based fields to use `pattern` attribute
|
||||
* Feature: Allows textareas to use `wrap` attribute
|
||||
* Fix: Resolved the bug that prevented the `dynamic_date` shortcode from using `min`, `max`, and `step` attributes, [see support thread](https://wordpress.org/support/topic/dynamic_date-min-max-step-options-ignored/).
|
||||
* Fix: Added minimum version check for Contact Form 7, [see support thread](https://wordpress.org/support/topic/str_contains-is-php-8-0-only-broken-compatibility/).
|
||||
* Fix: Resolved an issue that used a function introduced in PHP 8 while plugin compatibility setting is currently still set to 7.4+, [see support thread](https://wordpress.org/support/topic/str_contains-is-php-8-0-only-broken-compatibility/).
|
||||
|
||||
= 4.2.0 =
|
||||
|
||||
* Security Update: ** Please be sure to review this doc, as you may need to adjust the settings: [Documentation by SevenSpark](https://sevenspark.com/docs/contact-form-7-dynamic-text-extension/allow-data-access), [Documentation by AuRise Creative](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/security/) **
|
||||
* Feature: Added Settings Screen with Allow Lists
|
||||
* Feature: Added Form Scanner
|
||||
* Feature: Added Allow List key validation in CF7 Form Validator
|
||||
|
||||
= 4.1.0 =
|
||||
|
||||
* Feature: Looks for a `dtx.php` file in the `wp_content` directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Feature: Looks for a `dtx.php` file in the current active theme's directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Feature: Looks for a `dtx.php` file in the current active theme's parent directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Fix: addressed user reported bug, [see support thread](https://wordpress.org/support/topic/fatal-error-v4-0-3/)
|
||||
|
||||
= 4.0.3 =
|
||||
|
||||
* Feature: Added `exclusive` option to checkbox tag generator
|
||||
* Fix: addressed bug that put all dynamic checkbox/radio options into one
|
||||
* Fix: addressed bug in frontend validator for multiple selected values
|
||||
|
||||
= 4.0.2 =
|
||||
|
||||
* Fix: addressed bug that put all dynamic select options into one, [see support thread](https://wordpress.org/support/topic/dynamic-select-get-option-values-from-shortcode/)
|
||||
* Update: sanitizing and escaping filters now accept `none` as value for `$type` to bypass. Use with caution.
|
||||
|
||||
= 4.0.1 =
|
||||
|
||||
* Fix: addressed bug that prevented translation for cache compatibility description
|
||||
|
||||
= 4.0.0 =
|
||||
|
||||
* Major: modified function names
|
||||
* Major: deprecated `dynamictext` and `dynamichidden` form tags in favor of `dynamic_text` and `dynamic_hidden`. For more information, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_email` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-email/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_url` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-url/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_tel` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-tel/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_number` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-number/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_range` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-range/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_textarea` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-textarea/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_select` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_radio` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-radio/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_date` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-date/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_submit` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-submit/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dtx_hide_blank` form tag attribute for `dynamic_select`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dtx_disable_blank` form tag attribute for `dynamic_select`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: added mail validation for `dynamic_email` and `dynamic_hidden` for backend configuration. For more information, see the [FAQ](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/frequently-asked-questions/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: added the Akismet feature to DTX text, email, and URL form tags.
|
||||
* Update: adjusted how queued values were sent for cache compatibility mode to allow for multiline values in textareas
|
||||
* Removed unused utility functions
|
||||
|
||||
= 3.5.4 =
|
||||
|
||||
* Fix: Updated JavaScript to prevent cacheable fields from making unnecessary AJAX requests
|
||||
|
||||
= 3.5.3 =
|
||||
|
||||
* Update: removed the use of sessions, [see support thread](https://wordpress.org/support/topic/add-option-to-disable-session-data/)
|
||||
|
||||
= 3.5.2 =
|
||||
|
||||
* Fix: Updated the `CF7_URL` shortcode to only use `network_home_url()` for multisite installs that do not use subdomains, and use `home_url()` for all others to [maybe address this support thread](https://wordpress.org/support/topic/cf7_url-return-only-domain-and-not-subdomain/)
|
||||
* Fix: Removed a lingering debug call
|
||||
|
||||
= 3.5.1 =
|
||||
|
||||
* Fix: fixed bug so tag generator for dynamic fields work on "Add New Contact Form" page of Contact Form 7
|
||||
* Updated: Updated text in tag generator for cache compatible checkbox and added link to documentation
|
||||
|
||||
= 3.5.0 =
|
||||
|
||||
* Feature: Added the `dtx_pageload` form tag attribute for cache compatibility. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tag-attribute-after-page-load/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Fix: Updated to be compatible with WordPress version 6.3
|
||||
* Fix: Addressed a bug where `scheme` in `CF7_URL part='scheme'` was incorrectly sanitizing as URL instead of text
|
||||
* Fix: Fixed `wp_kses()` in tag generator that stripped out link opening in new tab
|
||||
* Update: `CF7_get_current_var` utilizes PHP session variables where appropriate
|
||||
* Update: All JavaScript assets will load with the `defer` strategy in the footer in [WordPress 6.3](https://make.wordpress.org/core/2023/07/14/registering-scripts-with-async-and-defer-attributes-in-wordpress-6-3/)
|
||||
|
||||
= 3.4.0 =
|
||||
|
||||
* Feature: Feature: Added the `CF7_get_current_var` shortcode, [see support thread for user request](https://wordpress.org/support/topic/wrong-page-title-7/). For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-variables/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Fix: Updated the `CF7_URL` shortcode to no longer check for ports since that's handled in `network_home_url()` function, [see support thread](https://wordpress.org/support/topic/version-3-3-0-breaking/)
|
||||
|
||||
= 3.3.0 =
|
||||
|
||||
* Feature: Added the `CF7_get_cookie` shortcode. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-cookie/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: Added the `CF7_get_taxonomy` shortcode. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-taxonomy/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: Added the `CF7_get_theme_option` shortcode. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-theme-option/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: Added `wpcf7dtx_sanitize` filter that sanitizes attribute values in built-in shortcodes
|
||||
* Feature: Added `wpcf7dtx_escape` filter that escapes values in built-in shortcodes
|
||||
* Feature: Added `wpcf7dtx_allow_protocols` filter to customize allowed protocols in escaping URLs in built-in shortcodes
|
||||
* Fix: Updated how plugin gets dynamic value in form tags, now uses `wpcf7dtx_get_dynamic()` function
|
||||
* Fix: Added case-insensitive ID in `CF7_get_post_var`
|
||||
* Fix: Sanitizes post variable keys as keys in `wpcf7dtx_get_post_var()`
|
||||
* Fix: Updated `wpcf7dtx_get_post_id()` to pull from "the loop" if `$post` is unavailable and now used consistently across built-in shortcodes
|
||||
* Fix: Updated tag markup to be compatible with Contact Form 7 version 5.6 Beta for successful form validation, [see support thread](https://wordpress.org/support/topic/required-field-no-error-is-output-when-validating-when-field-is-empty/)
|
||||
* Fix: Updated the `CF7_URL` shortcode to use `network_home_url()`, [see support thread](https://wordpress.org/support/topic/current-url-not-working/)
|
||||
* Fix: Updated GUID function to return appropriately escaped values
|
||||
* Fix: Updated all existing built-in shortcodes to use the the sanitizing, escaping, and obfuscating shortcodes, [see support thread](https://wordpress.org/support/topic/cant-get-obfuscate-to-work/)
|
||||
* Fix: Marked compatible with WordPress core version 6.2.
|
||||
|
||||
= 3.2 =
|
||||
|
||||
* Feature: Add optional 'part' parameter to CF7_URL shortcode to retrieve Host, Query, or Path from current URL
|
||||
* Updated minimum PHP requirement to 7.4 moving forward
|
||||
* Update branding assets
|
||||
* Update Tested Up To to 6.1.1
|
||||
* Plugin will now be jointly maintained by [SevenSpark](https://sevenspark.com/) and [AuRise Creative](https://aurisecreative.com)
|
||||
|
||||
= 3.1.3 =
|
||||
|
||||
* Fix: Fixed the syntax error that reappeared in 3.1.2.
|
||||
|
||||
= 3.1.2 =
|
||||
|
||||
**Release Date: January 27, 2023**
|
||||
|
||||
* Fix: updated the text domain to match the plugin slug
|
||||
* Fix: updated all of the translated strings to match
|
||||
|
||||
= 3.1.1 =
|
||||
|
||||
**Release Date: January 26, 2023**
|
||||
|
||||
* Fix: Fixed the syntax error: Parse error: syntax error, unexpected `)` in /wp-content/plugins/contact-form-7-dynamic-text extension/includes/admin.php on line 212
|
||||
|
||||
= 3.1.0 =
|
||||
|
||||
**Release Date: January 25, 2023**
|
||||
|
||||
* Feature: Added the `CF7_get_attachment` shortcode. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-media-attachment/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: Added the `CF7_guid` shortcode. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-guid/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
* Feature: Added the dynamic placeholder option to the dynamic form tags that allows you to specify dynamic or static placeholder content while also setting dynamic values. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-attribute-placeholder/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: Added a "required" dynamic hidden tag (e.g., `[dynamichidden* ...]`). It is identical to the original dynamic hidden tag (as in the field is not actually validated as required because it is hidden); it just doesn't break your website if you use it. This feature was requested by a user.
|
||||
* Feature: Added the `obfuscate` attribute to all included shortcodes
|
||||
|
||||
= 3.0.0 =
|
||||
|
||||
**Release Date: January 17, 2023**
|
||||
|
||||
* Major: Plugin was adopted by AuRise Creative
|
||||
* Major: All functions use the `wpcf7dtx_` prefix
|
||||
* Feature: Added a `post_id` key for the `CF7_get_post_var` shortcode so you can specify a different post
|
||||
* Feature: Updated the `CF7_get_current_user` shortcode to be able to pull data from user metadata too
|
||||
* Feature: Added the "obfuscate" option to `CF7_get_custom_field` shortcode
|
||||
* Feature: Added the "placeholder" checkbox option to the `dynamictext` tag
|
||||
* Fix: Added additional validation for post ID input
|
||||
* Fix: Added additional validation for the `key` attribute in the `CF7_GET` and `CF7_POST` shortcodes
|
||||
* Fix: Shortcode keys are normalized into lowercase before processing
|
||||
* Security: Sanitizing URLs for the `CF7_URL` and `CF7_referrer` shortcode outputs
|
||||
* Feature/Security: Added a `allowed_protocols` attribute to the `CF7_URL` and `CF7_referrer` shortcodes that defaults to `http,https`
|
||||
|
||||
= 2.0.3 =
|
||||
|
||||
* Security: [Fix Reflected XSS](https://web.archive.org/web/20230121180428/https://sevenspark.com/docs/cf7-dtx-security-2019-07-24)
|
||||
|
||||
= 2.0.2.1 =
|
||||
|
||||
* Update changelog properly for 2.0.2 changes:
|
||||
|
||||
= 2.0.2 =
|
||||
|
||||
* Update deprecated `get_currentuserinfo()` function to `wp_get_current_user()`
|
||||
* Update deprecated functions from `WPCF7_add_shortcode` to `WPCF7_add_formtag` and class from `WPCF7_Shortcode` to `WPCF7_FormTag` to comply with CF7 4.6 changes
|
||||
|
||||
= 2.0.1 =
|
||||
|
||||
* Hook change to guarantee the plugin only runs when Contact Form 7 is present in the admin (avoids errors if Contact Form 7 is disabled, or if there is a plugin sequencing issue)
|
||||
|
||||
= 2.0 =
|
||||
|
||||
* Complete rewrite for Compatibility with Contact Form 7 v4
|
||||
|
||||
= 1.2 =
|
||||
|
||||
* Compatibility update for Contact Form 7 v3.9
|
||||
|
||||
= 1.1.0.2 =
|
||||
|
||||
* Updated to work with Contact Form 7 v3.7.x
|
||||
|
||||
= 1.1.0.1 =
|
||||
|
||||
* Removed undefined variable warning
|
||||
|
||||
= 1.1 =
|
||||
|
||||
* Updated for compatibility with Contact Form 7 v3.6
|
||||
* Added Referrer shortcode
|
||||
|
||||
= 1.0.4.2 =
|
||||
|
||||
* Fixed a bug that created repeating square brackets around dynamic text values in cases where the form doesn't validate and JavaScript is deactivated.
|
||||
|
||||
= 1.0.4.1 =
|
||||
|
||||
* Removed trailing whitespace to fix "Headers already sent" errors
|
||||
|
||||
= 1.0.4 =
|
||||
|
||||
* Added Current User Info shortcode
|
||||
* Added Post Custom Field shortcode (with obfuscation support)
|
||||
* Added Hidden Field capability
|
||||
|
||||
= 1.0.3 =
|
||||
|
||||
* Added $_POST shortcode
|
||||
* Added current post/page variable shortcode
|
||||
* Added current URL shortcode
|
||||
|
||||
= 1.0.2 =
|
||||
|
||||
* Fixed administrative control panel dependency issue
|
||||
|
||||
= 1.0.1 =
|
||||
|
||||
* Fixed dependency issue.
|
||||
@@ -1,716 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Name: Contact Form 7 - Dynamic Text Extension
|
||||
* Description: Extends Contact Form 7 by adding dynamic form fields that accepts shortcodes to prepopulate form fields with default values and dynamic placeholders.
|
||||
* Version: 4.4.2
|
||||
* Text Domain: contact-form-7-dynamic-text-extension
|
||||
* Author: AuRise Creative, SevenSpark
|
||||
* Author URI: https://aurisecreative.com
|
||||
* Plugin URI: https://aurisecreative.com/products/wordpress-plugin/contact-form-7-dynamic-text-extension/
|
||||
* License: GPL v3
|
||||
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* Requires at least: 5.5
|
||||
* Requires PHP: 7.4
|
||||
* Requires Plugins: contact-form-7
|
||||
*
|
||||
* @copyright Copyright (c) 2010-2024 Chris Mavricos, SevenSpark <https://sevenspark.com>
|
||||
* @copyright Copyright (c) 2022-2024 Tessa Watkins, AuRise Creative <https://aurisecreative.com>
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License, version 3 or higher
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
define('WPCF7DTX_VERSION', '4.4.2'); // Define current version of DTX
|
||||
define('WPCF7DTX_MINVERSION', '5.7'); // The minimum version of CF7 required to use mail validator
|
||||
defined('WPCF7DTX_DIR') || define('WPCF7DTX_DIR', __DIR__); // Define root directory
|
||||
defined('WPCF7DTX_FILE') || define('WPCF7DTX_FILE', __FILE__); // Define root file
|
||||
define('WPCF7DTX_DATA_ACCESS_KB_URL', 'https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/security/');
|
||||
|
||||
/**
|
||||
* Determine Dependencies are Met
|
||||
*
|
||||
* @since 4.2.1
|
||||
*
|
||||
* @return bool True if minimum version of Contact Form 7 is met. False otherwise.
|
||||
*/
|
||||
function wpcf7dtx_dependencies()
|
||||
{
|
||||
return defined('WPCF7_VERSION') && version_compare(constant('WPCF7_VERSION'), WPCF7DTX_MINVERSION, '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Plugin
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_init()
|
||||
{
|
||||
if (!wpcf7dtx_dependencies()) {
|
||||
add_action('admin_notices', function () {
|
||||
echo (wp_kses_post(sprintf(
|
||||
'<div class="notice notice-error is-dismissible"><p><strong>%s</strong> %s</p></div>',
|
||||
__('Form validation for dynamic fields created with <em>Contact Form 7 - Dynamic Text Extension</em> is not available!', 'contact-form-7-dynamic-text-extension'),
|
||||
sprintf(
|
||||
__('<em>Contact Form 7</em> version %s or higher is required.', 'contact-form-7-dynamic-text-extension'),
|
||||
esc_html(WPCF7DTX_MINVERSION)
|
||||
)
|
||||
)));
|
||||
});
|
||||
}
|
||||
add_action('wpcf7_init', 'wpcf7dtx_add_shortcodes'); // Add custom form tags to CF7
|
||||
}
|
||||
add_action('plugins_loaded', 'wpcf7dtx_init', 20);
|
||||
|
||||
/**
|
||||
* DTX Formg Tag Configuration
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function wpcf7dtx_config()
|
||||
{
|
||||
global $wpcf7_dynamic_fields_config;
|
||||
if (!isset($wpcf7_dynamic_fields_config)) {
|
||||
$wpcf7_dynamic_fields_config = array(
|
||||
'dynamic_text' => array(
|
||||
'title' => __('dynamic text', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly'),
|
||||
'description' => __('a single-line plain text', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_hidden' => array(
|
||||
'title' => __('dynamic hidden', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array(),
|
||||
'description' => __('a single-line plain text hidden input field', 'contact-form-7-dynamic-text-extension'),
|
||||
'features' => array(
|
||||
'display-hidden' => true // Generates an HTML element that is not visible
|
||||
)
|
||||
),
|
||||
'dynamic_email' => array(
|
||||
'title' => __('dynamic email', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly'),
|
||||
'description' => __('a single-line email address input field', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_url' => array(
|
||||
'title' => __('dynamic URL', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly'),
|
||||
'description' => __('a single-line URL input field', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_tel' => array(
|
||||
'title' => __('dynamic tel', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly', 'pattern'),
|
||||
'description' => __('a single-line telephone number input field', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_number' => array(
|
||||
'title' => __('dynamic number', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly', 'min', 'max', 'step', 'pattern'),
|
||||
'description' => __('a numeric input field displayed as a number spinbox', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_range' => array(
|
||||
'title' => __('dynamic range', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly', 'min', 'max', 'step', 'pattern'),
|
||||
'description' => __('a numeric input field displayed as a slider between a minimum and maximum range', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_textarea' => array(
|
||||
'title' => __('dynamic textarea', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly'),
|
||||
'description' => __('a multi-line plain text input field', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_select' => array(
|
||||
'title' => __('dynamic drop-down menu', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly', 'multiple', 'include_blank'),
|
||||
'description' => __('a drop-down menu (i.e select input field)', 'contact-form-7-dynamic-text-extension'),
|
||||
'features' => array(
|
||||
'selectable-values' => true // Generates an option (or group of options) from which you can select one or more options
|
||||
)
|
||||
),
|
||||
'dynamic_checkbox' => array(
|
||||
'title' => __('dynamic checkboxes', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('readonly', 'label_first', 'use_label_element', 'exclusive'),
|
||||
'description' => __('a group of checkboxes', 'contact-form-7-dynamic-text-extension'),
|
||||
'features' => array(
|
||||
'multiple-controls-container' => true, // Generates an HTML element that can contain multiple form controls
|
||||
'selectable-values' => true // Generates an option (or group of options) from which you can select one or more options
|
||||
)
|
||||
),
|
||||
'dynamic_radio' => array(
|
||||
'title' => __('dynamic radio buttons', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('readonly', 'label_first', 'use_label_element'),
|
||||
'description' => __('a group of radio buttons', 'contact-form-7-dynamic-text-extension'),
|
||||
'features' => array(
|
||||
'multiple-controls-container' => true, // Generates an HTML element that can contain multiple form controls
|
||||
'selectable-values' => true // Generates an option (or group of options) from which you can select one or more options
|
||||
)
|
||||
),
|
||||
'dynamic_date' => array(
|
||||
'title' => __('dynamic date', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array('placeholder', 'readonly', 'min', 'max', 'step'),
|
||||
'description' => __('a date input field', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_submit' => array(
|
||||
'title' => __('dynamic submit', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array(),
|
||||
'description' => __('a submit button', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dynamic_label' => array(
|
||||
'title' => __('dynamic label', 'contact-form-7-dynamic-text-extension'), //title
|
||||
'options' => array(),
|
||||
'description' => __('a label element', 'contact-form-7-dynamic-text-extension')
|
||||
)
|
||||
);
|
||||
}
|
||||
return $wpcf7_dynamic_fields_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Custom Shortcodes to Contact Form 7
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_add_shortcodes()
|
||||
{
|
||||
//Add the dynamic form fields
|
||||
foreach (wpcf7dtx_config() as $form_tag => $field) {
|
||||
$input_type = str_replace('dynamic_', '', $form_tag);
|
||||
$tag_types = array($form_tag, "$form_tag*");
|
||||
$callback = 'wpcf7dtx_shortcode_handler';
|
||||
$features = array_merge(array('name-attr' => true), wpcf7dtx_array_has_key('features', $field, array()));
|
||||
switch ($input_type) {
|
||||
case 'text':
|
||||
case 'hidden':
|
||||
// Add deprecated tags
|
||||
$dep_tag = str_replace('_', '', $form_tag);
|
||||
$tag_types[] = $dep_tag;
|
||||
$tag_types[] = "$dep_tag*";
|
||||
add_filter("wpcf7_validate_$dep_tag*", 'wpcf7dtx_validation_filter', 20, 2); // Validate required deprecated form tags
|
||||
break;
|
||||
case 'submit':
|
||||
case 'reset':
|
||||
$callback = 'wpcf7dtx_button_shortcode_handler';
|
||||
$features['name-attr'] = false;
|
||||
break;
|
||||
case 'label':
|
||||
$callback = 'wpcf7dtx_label_shortcode_handler';
|
||||
$features['name-attr'] = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
add_filter("wpcf7_validate_$form_tag*", 'wpcf7dtx_validation_filter', 20, 2); // Validate required custom form tags
|
||||
wpcf7_add_form_tag($tag_types, $callback, $features);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Frontend Script
|
||||
*
|
||||
* Register the frontend script to be optionally loaded later.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*
|
||||
* @param string $hook Hook suffix for the current page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_enqueue_frontend_assets($hook = '')
|
||||
{
|
||||
$debug = defined('WP_DEBUG') && constant('WP_DEBUG');
|
||||
$url = plugin_dir_url(WPCF7DTX_FILE);
|
||||
$path = plugin_dir_path(WPCF7DTX_FILE);
|
||||
wp_register_script(
|
||||
'wpcf7dtx', // Handle
|
||||
$url . 'assets/scripts/dtx' . ($debug ? '' : '.min') . '.js', // Source
|
||||
array('jquery-core'), // Dependencies
|
||||
$debug ? @filemtime($path . 'assets/scripts/dtx.js') : WPCF7DTX_VERSION, // Version
|
||||
array('in_footer' => true, 'strategy' => 'defer') // Defer loading in footer
|
||||
|
||||
);
|
||||
wp_localize_script(
|
||||
'wpcf7dtx', // Handle
|
||||
'dtx_obj', // Object
|
||||
array('ajax_url' => admin_url('admin-ajax.php')) // Data
|
||||
);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'wpcf7dtx_enqueue_frontend_assets');
|
||||
|
||||
/**
|
||||
* Include Utility Functions
|
||||
*/
|
||||
include_once(WPCF7DTX_DIR . '/includes/utilities.php');
|
||||
|
||||
/**
|
||||
* Include Validation Functions
|
||||
*/
|
||||
include_once(WPCF7DTX_DIR . '/includes/validation.php');
|
||||
|
||||
/**
|
||||
* Form Tag Handler
|
||||
*
|
||||
* @param WPCF7_FormTag $tag Current Contact Form 7 tag object
|
||||
*
|
||||
* @return string HTML output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_shortcode_handler($tag)
|
||||
{
|
||||
// Name attribute is required for these form tags
|
||||
if (empty($tag->name)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Validate
|
||||
$validation_error = wpcf7_get_validation_error($tag->name);
|
||||
|
||||
//Configure input attributes
|
||||
$atts = array();
|
||||
$atts['type'] = sanitize_key(str_replace(array('dynamic_', 'dynamic'), '', $tag->basetype));
|
||||
$atts['name'] = $tag->name;
|
||||
$atts['id'] = strval($tag->get_id_option());
|
||||
$atts['tabindex'] = $tag->get_option('tabindex', 'signed_int', true);
|
||||
$atts['class'] = explode(' ', wpcf7_form_controls_class($atts['type']));
|
||||
$atts['class'][] = 'wpcf7dtx';
|
||||
$atts['class'][] = sanitize_html_class('wpcf7dtx-' . $atts['type']);
|
||||
if ($validation_error) {
|
||||
$atts['class'][] = 'wpcf7-not-valid';
|
||||
$atts['aria-invalid'] = 'true';
|
||||
$atts['aria-describedby'] = wpcf7_get_validation_error_reference($tag->name);
|
||||
} else {
|
||||
$atts['aria-invalid'] = 'false';
|
||||
}
|
||||
|
||||
// Add required attribute to applicable input types
|
||||
if ($tag->is_required() && !in_array($atts['type'], array('hidden', 'quiz'))) {
|
||||
$atts['aria-required'] = 'true';
|
||||
$atts['required'] = 'required';
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes for all fields
|
||||
*
|
||||
* Any attributes that are not allowed on specific elements will be stripped during escaping.
|
||||
* See the `wpcf7dtx_get_allowed_field_properties()` for details.
|
||||
*/
|
||||
$dynamic_atts = array('autofocus', 'disabled', 'readonly');
|
||||
foreach ($dynamic_atts as $dynamic_att) {
|
||||
// Don't override existing attributes
|
||||
if (!array_key_exists($dynamic_att, $atts) && $tag->has_option($dynamic_att)) {
|
||||
switch ($dynamic_att) {
|
||||
default:
|
||||
$atts[$dynamic_att] = wpcf7dtx_get_dynamic(false, $tag, 'text', $dynamic_att); // Get dynamic attribute
|
||||
if ($atts[$dynamic_att] === '') {
|
||||
$atts[$dynamic_att] = $dynamic_att; // Empty values are valid since boolean values just need to exist
|
||||
}
|
||||
if ($atts[$dynamic_att] !== $dynamic_att) {
|
||||
unset($atts[$dynamic_att]); // Remove attribute if it doesn't equal it's own name
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the dynamic value
|
||||
$sanitize_type = $atts['type'] == 'textarea' ? $atts['type'] : 'auto';
|
||||
$value = wpcf7dtx_get_dynamic(false, $tag, $sanitize_type);
|
||||
|
||||
// Identify placeholder
|
||||
if ($tag->has_option('placeholder') || $tag->has_option('watermark')) {
|
||||
//Reverse engineer what JS did (converted quotes to HTML entities --> URL encode) then sanitize
|
||||
$placeholder = html_entity_decode(urldecode($tag->get_option('placeholder', '', true)), ENT_QUOTES);
|
||||
if ($placeholder) {
|
||||
// If a different placeholder text has been specified, set both attributes
|
||||
$placeholder = wpcf7dtx_get_dynamic($placeholder, false, $sanitize_type);
|
||||
$atts['placeholder'] = $placeholder;
|
||||
$atts['value'] = $value;
|
||||
} else {
|
||||
// Default behavior of using the value as the placeholder
|
||||
$atts['placeholder'] = $value;
|
||||
$atts['value'] = '';
|
||||
}
|
||||
} else {
|
||||
$atts['value'] = $value;
|
||||
}
|
||||
|
||||
// Page load attribute
|
||||
if ($tag->has_option('dtx_pageload') && is_array($tag->raw_values) && count($tag->raw_values)) {
|
||||
$atts['data-dtx-value'] = rawurlencode(sanitize_text_field($tag->raw_values[0]));
|
||||
$atts['class'][] = 'dtx-pageload';
|
||||
if (wp_style_is('wpcf7dtx', 'registered') && !wp_script_is('wpcf7dtx', 'queue')) {
|
||||
// If already registered, just enqueue it
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
} elseif (!wp_style_is('wpcf7dtx', 'registered')) {
|
||||
// If not registered, do that first, then enqueue it
|
||||
wpcf7dtx_enqueue_frontend_assets();
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
}
|
||||
}
|
||||
|
||||
// Additional configuration based on form field type
|
||||
if (in_array($atts['type'], array('select', 'checkbox', 'radio'))) {
|
||||
/**
|
||||
* Configuration for selection-based fields
|
||||
*/
|
||||
if ($tag->has_option('default')) {
|
||||
$atts['dtx-default'] = wpcf7dtx_get_dynamic(html_entity_decode(urldecode($tag->get_option('default', '', true)), ENT_QUOTES));
|
||||
}
|
||||
|
||||
// Get options for selection-based fields
|
||||
$options = array();
|
||||
$pipes = $tag->pipes->to_array();
|
||||
if (count($pipes)) {
|
||||
foreach ($pipes as $pipe) {
|
||||
$key = trim(strval($pipe[0]));
|
||||
$value = trim(strval($pipe[1]));
|
||||
$valid_key = is_numeric($key) || (is_string($key) && !empty($key)); // Allow falsey numbers but not booleans or strings
|
||||
$valid_value = is_numeric($value) || (is_string($value) && !empty($value)); // Allow falsey numbers but not booleans or strings
|
||||
if ($valid_key && $valid_value) {
|
||||
$options[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($atts['type'] == 'select' && $tag->has_option('include_blank')) {
|
||||
$atts['placeholder'] = wpcf7dtx_array_has_key('placeholder', $atts, __('—Please choose an option—', 'contact-form-7-dynamic-text-extension'));
|
||||
}
|
||||
if ($atts['type'] == 'select') {
|
||||
$atts['size'] = wpcf7dtx_get_dynamic(false, $tag, 'text', 'size'); // Get dynamic attribute
|
||||
if ($atts['size'] === '') {
|
||||
$atts['size'] = $tag->get_size_option('1'); // Set default value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Attributes for text-based fields
|
||||
*
|
||||
* Any attributes that are not allowed on specific elements will be stripped during escaping.
|
||||
* See the `wpcf7dtx_get_allowed_field_properties()` for details.
|
||||
*/
|
||||
$dynamic_atts = array('autocapitalize', 'autocomplete', 'cols', 'list', 'max', 'maxlength', 'min', 'minlength', 'pattern', 'rows', 'size', 'step');
|
||||
foreach ($dynamic_atts as $dynamic_att) {
|
||||
// Don't override existing attributes
|
||||
if (!array_key_exists($dynamic_att, $atts) && $tag->has_option($dynamic_att)) {
|
||||
$atts[$dynamic_att] = wpcf7dtx_get_dynamic(false, $tag, 'text', $dynamic_att); // Get dynamic attribute
|
||||
switch ($dynamic_att) {
|
||||
case 'autocapitalize':
|
||||
if (!in_array($atts[$dynamic_att], array('none', 'off', 'on', 'sentences', 'words', 'characters'))) {
|
||||
unset($atts[$dynamic_att]); // Remove if invalid
|
||||
}
|
||||
break;
|
||||
case 'autocomplete':
|
||||
// Autocomplete attribute
|
||||
if ($atts['type'] == 'hidden') {
|
||||
$atts['autocomplete'] = 'off'; // Always disable for hidden fields
|
||||
} else {
|
||||
// Disable autocomplete for this field if a value has been specified
|
||||
$atts['autocomplete'] = $atts['value'] ? 'off' : $atts['autocomplete']; // Get dynamic attribute // Get dynamic attribute
|
||||
}
|
||||
break;
|
||||
case 'maxlength':
|
||||
if ($atts[$dynamic_att] === '' || !is_numeric($atts[$dynamic_att])) {
|
||||
$atts[$dynamic_att] = $tag->get_maxlength_option(); // Set default if empty or invalid
|
||||
}
|
||||
break;
|
||||
case 'minlength':
|
||||
if ($atts[$dynamic_att] === '' || !is_numeric($atts[$dynamic_att])) {
|
||||
$atts[$dynamic_att] = $tag->get_minlength_option(); // Set default if empty or invalid
|
||||
}
|
||||
break;
|
||||
case 'cols':
|
||||
if ($atts[$dynamic_att] === '' || !is_numeric($atts[$dynamic_att])) {
|
||||
$atts[$dynamic_att] = $tag->get_cols_option('40'); // Set default if empty or invalid
|
||||
}
|
||||
break;
|
||||
case 'rows':
|
||||
if ($atts[$dynamic_att] === '' || !is_numeric($atts[$dynamic_att])) {
|
||||
$atts[$dynamic_att] = $tag->get_rows_option('10'); // Set default if empty or invalid
|
||||
}
|
||||
break;
|
||||
case 'size':
|
||||
if ($atts[$dynamic_att] === '' || !is_numeric($atts[$dynamic_att])) {
|
||||
$atts[$dynamic_att] = $tag->get_size_option('40'); // Set default if empty or invalid
|
||||
}
|
||||
break;
|
||||
case 'wrap':
|
||||
if (!in_array($atts[$dynamic_att], array('hard', 'soft'))) {
|
||||
unset($atts[$dynamic_att]); // Remove if invalid
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ($atts[$dynamic_att] === '') {
|
||||
unset($atts[$dynamic_att]); // Remove attribute if empty
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate Min and Max length attributes (should always be numeric)
|
||||
if (array_key_exists('maxlength', $atts) && $atts['maxlength'] && array_key_exists('minlength', $atts) && $atts['minlength'] && intval($atts['maxlength']) < intval($atts['minlength'])) {
|
||||
unset($atts['maxlength'], $atts['minlength']);
|
||||
} else {
|
||||
/**
|
||||
* The `maxlength` attribute must be an integer with a value of 0 or higher
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength
|
||||
*/
|
||||
if (array_key_exists('maxlength', $atts) && (!is_numeric($atts['maxlength']) || intval($atts['maxlength']) < 0)) {
|
||||
unset($atts['maxlength']);
|
||||
}
|
||||
/**
|
||||
* The `minlength` attribute must be an integer with a value of 0 or higher
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/minlength
|
||||
*/
|
||||
if (array_key_exists('minlength', $atts) && (!is_numeric($atts['minlength']) || intval($atts['minlength']) < 0)) {
|
||||
unset($atts['minlength']);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate Min and Max attributes if numeric
|
||||
if (array_key_exists('max', $atts) && array_key_exists('min', $atts) && is_numeric($atts['max']) && is_numeric($atts['min']) && floatval($atts['max']) < floatval($atts['min'])) {
|
||||
unset($atts['max'], $atts['min']);
|
||||
}
|
||||
|
||||
// Client-side validation by type
|
||||
switch ($atts['type']) {
|
||||
case 'range':
|
||||
$atts['class'][] = 'wpcf7-validates-as-number';
|
||||
break;
|
||||
case 'date':
|
||||
case 'number':
|
||||
case 'email':
|
||||
case 'url':
|
||||
case 'tel':
|
||||
$atts['class'][] = sanitize_html_class('wpcf7-validates-as-' . $atts['type']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap up class attribute
|
||||
$atts['class'] = $tag->get_class_option($atts['class']);
|
||||
|
||||
// Output the form field HTML
|
||||
$wrapper = '<span class="wpcf7-form-control-wrap %1$s" data-name="%1$s">%2$s%3$s</span>';
|
||||
$allowed_html = array('br' => array(), 'span' => array('id' => array(), 'class' => array(), 'data-name' => array(), 'aria-hidden' => array()));
|
||||
switch ($atts['type']) {
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
return wp_kses(sprintf(
|
||||
str_replace('<span class=', '<span%4$s class=', $wrapper), // Insert a 4th parameter for wrapper
|
||||
esc_attr($tag->name),
|
||||
wpcf7dtx_checkbox_group_html(
|
||||
$atts,
|
||||
$options,
|
||||
in_array('use_label_element', $tag->options),
|
||||
in_array('label_first', $tag->options),
|
||||
in_array('exclusive', $tag->options)
|
||||
),
|
||||
$validation_error,
|
||||
$atts['id'] ? sprintf(' id="%s"', esc_attr($atts['id'])) : ''
|
||||
), array_merge($allowed_html, array(
|
||||
'label' => array('for' => array()),
|
||||
'input' => wpcf7dtx_get_allowed_field_properties($atts['type'])
|
||||
)));
|
||||
case 'select':
|
||||
$allowed_html = array_merge($allowed_html, wpcf7dtx_get_allowed_field_properties('option'), array(
|
||||
'select' => wpcf7dtx_get_allowed_field_properties($atts['type'])
|
||||
));
|
||||
return wp_kses(sprintf(
|
||||
$wrapper,
|
||||
esc_attr($tag->name),
|
||||
wpcf7dtx_select_html(
|
||||
$atts,
|
||||
$options,
|
||||
$tag->has_option('dtx_hide_blank'),
|
||||
$tag->has_option('dtx_disable_blank')
|
||||
),
|
||||
$validation_error
|
||||
), array_merge($allowed_html, wpcf7dtx_get_allowed_field_properties('option'), array(
|
||||
'select' => wpcf7dtx_get_allowed_field_properties($atts['type']),
|
||||
)));
|
||||
case 'textarea':
|
||||
return wp_kses(sprintf(
|
||||
$wrapper,
|
||||
esc_attr($tag->name),
|
||||
wpcf7dtx_textarea_html($atts),
|
||||
$validation_error
|
||||
), array_merge($allowed_html, array(
|
||||
'textarea' => wpcf7dtx_get_allowed_field_properties($atts['type'])
|
||||
)));
|
||||
default:
|
||||
return wp_kses(sprintf(
|
||||
$wrapper,
|
||||
esc_attr($tag->name),
|
||||
wpcf7dtx_input_html($atts),
|
||||
$validation_error
|
||||
), array_merge($allowed_html, array(
|
||||
'input' => wpcf7dtx_get_allowed_field_properties($atts['type'])
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form Tag Handler for Dynamic Submit
|
||||
*
|
||||
* @param WPCF7_FormTag $tag Current Contact Form 7 tag object
|
||||
*
|
||||
* @return string HTML output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_button_shortcode_handler($tag)
|
||||
{
|
||||
//Configure input attributes
|
||||
$atts = array();
|
||||
$atts['type'] = sanitize_key(str_replace('dynamic_', '', $tag->basetype));
|
||||
$atts['id'] = strval($tag->get_id_option());
|
||||
$atts['tabindex'] = $tag->get_option('tabindex', 'signed_int', true);
|
||||
$atts['value'] = wpcf7dtx_get_dynamic(false, $tag); // Evaluate the dynamic value
|
||||
$atts['class'] = explode(' ', wpcf7_form_controls_class($atts['type']));
|
||||
$atts['class'][] = 'wpcf7dtx';
|
||||
$atts['class'][] = sanitize_html_class('wpcf7dtx-' . $atts['type']);
|
||||
if ($atts['type'] == 'submit') {
|
||||
$atts['class'][] = 'has-spinner';
|
||||
}
|
||||
|
||||
// Default value if empty
|
||||
if (empty($atts['value'])) {
|
||||
switch ($atts['type']) {
|
||||
case 'reset':
|
||||
$atts['value'] = __('Clear', 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
default:
|
||||
$atts['value'] = __('Send', 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Page load attribute
|
||||
if ($tag->has_option('dtx_pageload') && is_array($tag->raw_values) && count($tag->raw_values)) {
|
||||
$atts['data-dtx-value'] = rawurlencode(sanitize_text_field($tag->raw_values[0]));
|
||||
$atts['class'][] = 'dtx-pageload';
|
||||
if (wp_style_is('wpcf7dtx', 'registered') && !wp_script_is('wpcf7dtx', 'queue')) {
|
||||
// If already registered, just enqueue it
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
} elseif (!wp_style_is('wpcf7dtx', 'registered')) {
|
||||
// If not registered, do that first, then enqueue it
|
||||
wpcf7dtx_enqueue_frontend_assets();
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap up class attribute
|
||||
$atts['class'] = $tag->get_class_option($atts['class']);
|
||||
|
||||
// Output the form field HTML
|
||||
return wp_kses(
|
||||
wpcf7dtx_input_html($atts),
|
||||
array('input' => wpcf7dtx_get_allowed_field_properties($atts['type']))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form Tag Handler for Dynamic Label
|
||||
*
|
||||
* @param WPCF7_FormTag $tag Current Contact Form 7 tag object
|
||||
*
|
||||
* @return string HTML output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_label_shortcode_handler($tag)
|
||||
{
|
||||
$atts = array();
|
||||
$atts['id'] = strval($tag->get_id_option());
|
||||
$atts['class'] = wpcf7_form_controls_class('wpcf7dtx wpcf7dtx-label');
|
||||
$atts['for'] = wpcf7dtx_get_dynamic(html_entity_decode(urldecode($tag->get_option('for', '', true)), ENT_QUOTES)); // Get dynamic attribute
|
||||
|
||||
// Page load attribute
|
||||
if ($tag->has_option('dtx_pageload') && is_array($tag->raw_values) && count($tag->raw_values)) {
|
||||
$atts['data-dtx-value'] = rawurlencode(sanitize_text_field($tag->raw_values[0]));
|
||||
$atts['class'] .= ' dtx-pageload';
|
||||
if (wp_style_is('wpcf7dtx', 'registered') && !wp_script_is('wpcf7dtx', 'queue')) {
|
||||
// If already registered, just enqueue it
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
} elseif (!wp_style_is('wpcf7dtx', 'registered')) {
|
||||
// If not registered, do that first, then enqueue it
|
||||
wpcf7dtx_enqueue_frontend_assets();
|
||||
wp_enqueue_script('wpcf7dtx');
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap up class attribute
|
||||
$atts['class'] = $tag->get_class_option($atts['class']);
|
||||
|
||||
// Output the form field HTML
|
||||
return wp_kses(
|
||||
sprintf(
|
||||
'<label %s>%s</label>',
|
||||
wpcf7dtx_format_atts($atts),
|
||||
wpcf7dtx_get_dynamic(false, $tag) // Evaluate the dynamic label text
|
||||
),
|
||||
array_merge(
|
||||
wp_kses_allowed_html('data'), // Get allowed HTML for inline data
|
||||
array('label' => wpcf7dtx_get_allowed_field_properties('label')) // Include our label field
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Request Handler for After Page Loading
|
||||
*
|
||||
* @since 3.5.0
|
||||
*
|
||||
* @param array $_POST A sequential array of url encoded shortcode values to evaluate
|
||||
*
|
||||
* @return array A sequential array of objects with `raw_value` and `value` keys
|
||||
*/
|
||||
function wpcf7dtx_js_handler()
|
||||
{
|
||||
$return = array();
|
||||
$queue = wpcf7dtx_array_has_key('shortcodes', $_POST);
|
||||
if (is_array($queue) && count($queue)) {
|
||||
foreach ($queue as $field) {
|
||||
$multiline = wpcf7dtx_array_has_key('multiline', $field, false);
|
||||
$raw_value = sanitize_text_field(rawurldecode(wpcf7dtx_array_has_key('value', $field)));
|
||||
$return[] = array(
|
||||
'raw_value' => esc_attr($raw_value),
|
||||
'value' => esc_attr(wpcf7dtx_get_dynamic($raw_value, false, $multiline ? 'textarea' : 'auto'))
|
||||
);
|
||||
}
|
||||
}
|
||||
wp_die(json_encode($return));
|
||||
}
|
||||
add_action('wp_ajax_wpcf7dtx', 'wpcf7dtx_js_handler'); // Add AJAX call for logged in users
|
||||
add_action('wp_ajax_nopriv_wpcf7dtx', 'wpcf7dtx_js_handler'); // Add AJAX call for anonymous users
|
||||
|
||||
if (is_admin()) {
|
||||
/**
|
||||
* Include the Admin Stuff
|
||||
*/
|
||||
include_once(WPCF7DTX_DIR . '/includes/admin.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Built-in Shortcodes
|
||||
*/
|
||||
include_once(WPCF7DTX_DIR . '/includes/shortcodes.php');
|
||||
|
||||
/**
|
||||
* Website's custom shortcodes, if they exist
|
||||
*/
|
||||
$user_files = array(
|
||||
constant('WP_CONTENT_DIR') . '/dtx.php', // e.g. C:\path\to\website\wp-content\dtx.php
|
||||
get_template_directory() . '/dtx.php', // e.g. C:\path\to\website\wp-content/themes/parent-theme/dtx.php
|
||||
get_stylesheet_directory() . '/dtx.php' // e.g. C:\path\to\website\wp-content/themes/child-theme/dtx.php
|
||||
);
|
||||
foreach ($user_files as $user_file) {
|
||||
if (file_exists($user_file)) {
|
||||
include_once($user_file);
|
||||
}
|
||||
}
|
||||
@@ -1,755 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Include the Settings Page & Update Check
|
||||
include_once('admin/settings.php');
|
||||
include_once('admin/update-check.php');
|
||||
|
||||
/**
|
||||
* Admin Scripts and Styles
|
||||
*
|
||||
* Enqueue scripts and styles to be used on the admin pages
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $hook Hook suffix for the current admin page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_enqueue_admin_assets($hook)
|
||||
{
|
||||
// Only load on CF7 Form pages (both editing forms and creating new forms)
|
||||
if ($hook === 'toplevel_page_wpcf7' || $hook === 'contact_page_wpcf7-new') {
|
||||
$prefix = 'wpcf7dtx-';
|
||||
$debug = defined('WP_DEBUG_SCRIPTS') && constant('WP_DEBUG_SCRIPTS');
|
||||
$url = plugin_dir_url(WPCF7DTX_FILE);
|
||||
$path = plugin_dir_path(WPCF7DTX_FILE);
|
||||
|
||||
wp_enqueue_style(
|
||||
$prefix . 'admin', //Handle
|
||||
$url . 'assets/styles/tag-generator' . ($debug ? '' : '.min') . '.css', //Source
|
||||
array('contact-form-7-admin'), //Dependencies
|
||||
$debug ? @filemtime($path . 'assets/styles/tag-generator.css') : WPCF7DTX_VERSION //Version
|
||||
);
|
||||
|
||||
//Plugin Scripts
|
||||
wp_enqueue_script(
|
||||
$prefix . 'taggenerator', //Handle
|
||||
$url . 'assets/scripts/tag-generator' . ($debug ? '' : '.min') . '.js', //Source
|
||||
array('jquery', 'wpcf7-admin-taggenerator'), //Dependencies
|
||||
$debug ? @filemtime($path . 'assets/scripts/tag-generator.js') : WPCF7DTX_VERSION, //Version
|
||||
array('in_footer' => true, 'strategy' => 'defer') // Defer loading in footer
|
||||
);
|
||||
}
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'wpcf7dtx_enqueue_admin_assets'); //Enqueue styles/scripts for admin page
|
||||
|
||||
/**
|
||||
* Create Tag Generators
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_add_tag_generators()
|
||||
{
|
||||
if (!class_exists('WPCF7_TagGenerator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Custom dynamic fields to add
|
||||
global $wpcf7_dynamic_fields_config;
|
||||
|
||||
// Loop fields to add them
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
foreach ($wpcf7_dynamic_fields_config as $id => $field) {
|
||||
$tag_generator->add($id, $field['title'], 'wpcf7dtx_tag_generator', array_merge(array('name-attr', 'dtx_pageload'), $field['options']));
|
||||
}
|
||||
}
|
||||
add_action('wpcf7_admin_init', 'wpcf7dtx_add_tag_generators', 100);
|
||||
|
||||
/**
|
||||
* Echo HTML for Dynamic Tag Generator
|
||||
*
|
||||
* @param WPCF7_ContactForm $contact_form
|
||||
* @param array $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_tag_generator($contact_form, $options = '')
|
||||
{
|
||||
$options = wp_parse_args($options);
|
||||
global $wpcf7_dynamic_fields_config;
|
||||
$type = $options['id'];
|
||||
$input_type = str_replace('dynamic_', '', $type);
|
||||
$utm_source = urlencode(home_url());
|
||||
$description = sprintf(
|
||||
__('Generate a form-tag for %s with a dynamic default value. For more details, see %s fields in the %s.', 'contact-form-7-dynamic-text-extension'),
|
||||
esc_html($wpcf7_dynamic_fields_config[$type]['description']), // dynamic description
|
||||
// Link to specific form-tag documentation
|
||||
sprintf(
|
||||
'<a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/%s?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" title="%s" target="_blank" rel="noopener">%s</a>',
|
||||
esc_attr(str_replace('_', '-', $type)), // URL component
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_attr__('View this form-tag on the DTX Documentation website', 'contact-form-7-dynamic-text-extension'), // Link title
|
||||
esc_html(ucwords(str_replace('_', ' ', $type))) // Link label
|
||||
),
|
||||
// Link to general DTX documentation
|
||||
sprintf(
|
||||
'<a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" title="%s" target="_blank" rel="noopener">%s</a>',
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_attr__('Go to DTX Documentation website', 'contact-form-7-dynamic-text-extension'),
|
||||
esc_html__('DTX knowledge base', 'contact-form-7-dynamic-text-extension')
|
||||
)
|
||||
);
|
||||
|
||||
// Open Form-Tag Generator
|
||||
printf(
|
||||
'<div class="control-box dtx-taggen"><fieldset><legend>%s</legend><table class="form-table"><tbody>',
|
||||
wp_kses($description, array('a' => array('href' => array(), 'target' => array(), 'rel' => array(), 'title' => array()))) //Tag generator description
|
||||
);
|
||||
|
||||
// Input field - Required checkbox (not available for some fields)
|
||||
if (!in_array($input_type, array('hidden', 'quiz', 'submit', 'reset', 'label'))) {
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-required'), // field id
|
||||
esc_html__('Field type', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'required',
|
||||
'id' => $options['content'] . '-required'
|
||||
)),
|
||||
esc_html__('Required field', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
}
|
||||
|
||||
// Input field - Field Name (not available for some fields)
|
||||
if (!in_array($input_type, array('submit', 'reset', 'label'))) {
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s /></td></tr>',
|
||||
esc_attr($options['content'] . '-name'), // field id
|
||||
esc_html__('Name', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'name',
|
||||
'id' => $options['content'] . '-name',
|
||||
'class' => 'tg-name oneline',
|
||||
'autocomplete' => 'off'
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
// Input field - Dynamic value/options
|
||||
$value_name = __('Dynamic value', 'contact-form-7-dynamic-text-extension');
|
||||
$value_description = __('Can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
$value_placeholder = "CF7_GET key='foo'";
|
||||
$value_input_type = '<input %s />';
|
||||
switch ($input_type) {
|
||||
case 'textarea':
|
||||
$value_placeholder = "CF7_get_post_var key='post_excerpt'";
|
||||
$value_input_type = '<textarea %s></textarea>';
|
||||
break;
|
||||
case 'select':
|
||||
$value_name = __('Dynamic options', 'contact-form-7-dynamic-text-extension');
|
||||
$value_description .= ' ' . __('If static text, use one option per line. Can define static key/value pairs using pipes.', 'contact-form-7-dynamic-text-extension');
|
||||
$value_description .= ' ' . __('If shortcode, it must return only option or optgroup HTML and can override the first option and select default settings here.', 'contact-form-7-dynamic-text-extension');
|
||||
$value_placeholder = "hello-world | Hello World" . PHP_EOL . "Foo";
|
||||
$value_input_type = '<textarea %s></textarea>';
|
||||
break;
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
$value_name = __('Dynamic options', 'contact-form-7-dynamic-text-extension');
|
||||
$value_description .= ' ' . __('If static text, use one option per line. Can define static key/value pairs using pipes.', 'contact-form-7-dynamic-text-extension');
|
||||
$value_description .= ' ' . __('If shortcode, it must return only option or optgroup HTML.', 'contact-form-7-dynamic-text-extension');
|
||||
$value_placeholder = "hello-world | Hello World" . PHP_EOL . "Foo";
|
||||
$value_input_type = '<textarea %s></textarea>';
|
||||
break;
|
||||
default: // All other text fields
|
||||
break;
|
||||
}
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td>' . $value_input_type . '<br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-values'), // field id
|
||||
esc_html($value_name), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'name' => 'values',
|
||||
'id' => $options['content'] . '-values',
|
||||
'class' => 'multiline',
|
||||
'placeholder' => $value_placeholder,
|
||||
'list' => 'dtx-shortcodes'
|
||||
)),
|
||||
esc_html($value_description),
|
||||
esc_attr($utm_source), // UTM source
|
||||
esc_attr($type), // UTM content
|
||||
esc_html__('View DTX shortcode syntax documentation', 'contact-form-7-dynamic-text-extension') // Link label
|
||||
);
|
||||
|
||||
if ($input_type == 'label') {
|
||||
$placeholder_description = __('The id attribute of the element this label is for.', 'contact-form-7-dynamic-text-extension');
|
||||
$placeholder_description .= __('Can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s /><input %s /><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-for'), // field id
|
||||
esc_html__('For attribute'), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'for',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'name' => 'dtx-for',
|
||||
'id' => $options['content'] . '-for', // field id
|
||||
'class' => 'multiline dtx-option'
|
||||
)),
|
||||
esc_html($placeholder_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View documentation for Dynamic Attributes', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
} elseif ($input_type == 'select') {
|
||||
// Input field - Multiple selections checkbox
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-multiple'), // field id
|
||||
esc_html__('Multiple Options', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'multiple',
|
||||
'id' => $options['content'] . '-multiple',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Allow user to select multiple options', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
|
||||
// Input field - Include blank checkbox
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-include_blank'), // field id
|
||||
esc_html__('First Option', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'include_blank',
|
||||
'id' => $options['content'] . '-include_blank',
|
||||
'class' => 'include_blankvalue option'
|
||||
)),
|
||||
esc_html__('Insert a blank item as the first option', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
}
|
||||
|
||||
// Input field - Dynamic placeholder (not available for some fields)
|
||||
if (!in_array($input_type, array('hidden', 'radio', 'checkbox', 'range', 'quiz', 'submit', 'reset', 'label'))) {
|
||||
$placeholder_description = '';
|
||||
if (in_array($input_type, array('select', 'checkbox', 'radio'))) {
|
||||
$placeholder_label = __('First Option Label', 'contact-form-7-dynamic-text-extension');
|
||||
$placeholder_description .= __('Optionally define a label for the first option.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
} else {
|
||||
$placeholder_label = __('Dynamic placeholder', 'contact-form-7-dynamic-text-extension');
|
||||
}
|
||||
$placeholder_description .= __('Can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
$placeholder_input_type = $input_type == 'textarea' ? $value_input_type : '<input %s />';
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s />' . $placeholder_input_type . '<br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-attribute-placeholder/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-placeholder'), // field id
|
||||
esc_html($placeholder_label), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'placeholder',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'name' => 'dtx-placeholder',
|
||||
'id' => $options['content'] . '-placeholder', // field id
|
||||
'class' => 'multiline dtx-option',
|
||||
'placeholder' => "CF7_get_post_var key='post_title'",
|
||||
'list' => 'dtx-shortcodes'
|
||||
)),
|
||||
esc_html($placeholder_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View DTX placeholder documentation', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
// Additional fields for select regarding placeholder options
|
||||
if ($input_type == 'select') {
|
||||
|
||||
// Input field - Hide Blank Option
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-dtx_hide_blank'), // field id
|
||||
esc_html__('Hide First Option', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'dtx_hide_blank',
|
||||
'id' => $options['content'] . '-dtx_hide_blank',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Hide the first blank option from being visible in the drop-down', 'contact-form-7-dynamic-text-extension'), // checkbox label
|
||||
esc_html__('Optional. Only works if "First Option" is checked.', 'contact-form-7-dynamic-text-extension'), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View Dynamic Select documentation', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
|
||||
// Input field - Disable Blank Option
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-dtx_disable_blank'), // field id
|
||||
esc_html__('Disable First Option', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'dtx_disable_blank',
|
||||
'id' => $options['content'] . '-dtx_disable_blank',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Disable the first blank option from being selectable in the drop-down', 'contact-form-7-dynamic-text-extension'), // checkbox label
|
||||
esc_html__('Optional. Only works if "First Option" is checked.', 'contact-form-7-dynamic-text-extension'), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View Dynamic Select documentation', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
|
||||
);
|
||||
} elseif (in_array($input_type, array('checkbox', 'radio'))) {
|
||||
// Additional fields for checkboxes and radio buttons
|
||||
|
||||
// Input field - Checkbox Layout Reverse Option
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-label_first'), // field id
|
||||
esc_html__('Reverse', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'label_first',
|
||||
'id' => $options['content'] . '-label_first',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Put a label first, an input last', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
|
||||
// Input field - Label UI
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-use_label_element'), // field id
|
||||
esc_html__('Label', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'use_label_element',
|
||||
'id' => $options['content'] . '-use_label_element',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Wrap each item with label element', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
|
||||
// Input field - Exclusive Checkbox
|
||||
if ($input_type == 'checkbox') {
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-exclusive'), // field id
|
||||
esc_html__('Exclusive', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'exclusive',
|
||||
'id' => $options['content'] . '-exclusive',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Make checkboxes exclusive', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Input field - Dynamic default value (only available for selection-based fields)
|
||||
if (in_array($input_type, array('select', 'checkbox', 'radio'))) {
|
||||
$default_input_type = '<input %s />';
|
||||
$default_placeholder = '';
|
||||
if ($input_type == 'checkbox') {
|
||||
//$default_input_type = '<textarea %s></textarea>';
|
||||
$default_description = __('Optionally define which checkboxes are checked by default by defining the checked values using an underscore (_) delimited list.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
$default_placeholder = 'hello-world_Foo';
|
||||
} else {
|
||||
$default_description = __('Optionally define the option that is selected by default. This can be different than the first [blank] option. If options use key/value pairs, only define the key here.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
}
|
||||
$default_description .= __('Can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s />' . $default_input_type . '<br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-default'), // field id
|
||||
esc_html__('Selected Default'), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'default',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'name' => 'dtx-default',
|
||||
'id' => $options['content'] . '-default', // field id
|
||||
'class' => 'oneline dtx-option',
|
||||
'placeholder' => $default_placeholder,
|
||||
'list' => 'dtx-shortcodes'
|
||||
)),
|
||||
esc_html($default_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View Dynamic Select documentation', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
// Input field - Range attributes (only available for numeric and date fields)
|
||||
if (in_array($input_type, array('number', 'range', 'date'))) {
|
||||
$default_input_type = 'number';
|
||||
$default_placeholder = 'Foo';
|
||||
$step_option = '';
|
||||
if ($input_type == 'date') {
|
||||
$default_input_type = 'date';
|
||||
$default_description = __('Optionally define the minimum and/or maximum date values.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
$default_placeholder = 'hello-world_Foo';
|
||||
} else {
|
||||
$step_option = sprintf(
|
||||
' <span class="wpcf7dtx-mini-att"><label for="%s">%s</label> <input %s /><input %s /></span>',
|
||||
esc_attr($options['content'] . '-step'),
|
||||
esc_html__('Step', 'contact-form-7-dynamic-text-extension'),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'step',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-step',
|
||||
'id' => $options['content'] . '-step',
|
||||
'class' => 'dtx-option',
|
||||
'size' => 7
|
||||
))
|
||||
);
|
||||
$default_description = __('Optionally define the minimum, maximum, and/or step values.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
}
|
||||
$default_description .= __('Each can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
printf(
|
||||
'<tr><th scope="row"><label>%s</label></th><td><span class="wpcf7dtx-mini-att"><label for="%s">%s</label> <input %s /><input %s /></span> - <span class="wpcf7dtx-mini-att"><label for="%s">%s</label> <input %s /><input %s /></span>%s<br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_html__('Range', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
esc_attr($options['content'] . '-min'),
|
||||
esc_html__('Min', 'contact-form-7-dynamic-text-extension'),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'min',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-min',
|
||||
'id' => $options['content'] . '-min',
|
||||
'class' => 'dtx-option',
|
||||
'size' => 7
|
||||
)),
|
||||
esc_attr($options['content'] . '-max'),
|
||||
esc_html__('Max', 'contact-form-7-dynamic-text-extension'),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'max',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-max',
|
||||
'id' => $options['content'] . '-max',
|
||||
'class' => 'dtx-option',
|
||||
'size' => 7
|
||||
)),
|
||||
$step_option, // Optional "step" option for numbers and ranges
|
||||
esc_html($default_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View documentation for Dynamic Attributes', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
//Input field - ID attribute
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s /></td></tr>',
|
||||
esc_attr($options['content'] . '-id'), // field id
|
||||
esc_html__('Id attribute', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'id',
|
||||
'id' => $options['content'] . '-id', // field id
|
||||
'class' => 'idvalue oneline option'
|
||||
))
|
||||
);
|
||||
|
||||
//Input field - Class attribute
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><input %s /></td></tr>',
|
||||
esc_attr($options['content'] . '-class'), // field id
|
||||
esc_html__('Class attribute', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'class',
|
||||
'id' => $options['content'] . '-class', // field id
|
||||
'class' => 'classvalue oneline option'
|
||||
))
|
||||
);
|
||||
|
||||
// Input field - Maxlenth & Minlength attributes (only available for visible text fields)
|
||||
if (!in_array($input_type, array('hidden', 'quiz', 'submit', 'reset', 'label', 'number', 'range', 'date', 'select', 'checkbox', 'radio'))) {
|
||||
$default_description = __('Optionally define the minimum and/or maximum character string length. Must be a positive whole number or integer.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
$default_description .= __('Each can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
printf(
|
||||
'<tr><th scope="row"><label>%s</label></th><td><span class="wpcf7dtx-mini-att"><label for="%s">%s</label> <input %s /><input %s /></span> - <span class="wpcf7dtx-mini-att"><label for="%s">%s</label> <input %s /><input %s /></span><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
//esc_attr($options['content'] . '-default'), // field id
|
||||
esc_html__('Character Length', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
esc_attr($options['content'] . '-minlength'),
|
||||
esc_html__('Min', 'contact-form-7-dynamic-text-extension'),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'minlength',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-minlength',
|
||||
'id' => $options['content'] . '-minlength',
|
||||
'class' => 'dtx-option',
|
||||
'size' => 10
|
||||
)),
|
||||
esc_attr($options['content'] . '-maxlength'),
|
||||
esc_html__('Max', 'contact-form-7-dynamic-text-extension'),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'maxlength',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-maxlength',
|
||||
'id' => $options['content'] . '-maxlength',
|
||||
'class' => 'dtx-option',
|
||||
'size' => 10
|
||||
)),
|
||||
esc_html($default_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View documentation for Dynamic Attributes', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
// Input field - Maxlenth & Minlength attributes (only available for visible text fields)
|
||||
if (in_array($input_type, array('text', 'email', 'phone', 'url', 'password', 'textarea'))) {
|
||||
$default_description = __('Optionally define an autocomplete setting by the browser.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
$default_description .= __('Each can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
$datalist = array(
|
||||
'off' => __('Off', 'contact-form-7-dynamic-text-extension'),
|
||||
'on' => __('On', 'contact-form-7-dynamic-text-extension'),
|
||||
'name' => __('Full Name', 'contact-form-7-dynamic-text-extension'),
|
||||
'given-name' => __('First Name', 'contact-form-7-dynamic-text-extension'),
|
||||
'family-name' => __('Last Name', 'contact-form-7-dynamic-text-extension'),
|
||||
'honorific-prefix' => __('Honorific prefix or title', 'contact-form-7-dynamic-text-extension'),
|
||||
'honorific-suffix' => __('Honorific suffix or credentials', 'contact-form-7-dynamic-text-extension'),
|
||||
'nickname' => __('Nickname', 'contact-form-7-dynamic-text-extension'),
|
||||
'email' => __('Email Address', 'contact-form-7-dynamic-text-extension'),
|
||||
'new-password' => __('A new password', 'contact-form-7-dynamic-text-extension'),
|
||||
'current-password' => __('The current password', 'contact-form-7-dynamic-text-extension'),
|
||||
'organization-title' => __('Job Title', 'contact-form-7-dynamic-text-extension'),
|
||||
'organization' => __('Company/Organization Name', 'contact-form-7-dynamic-text-extension'),
|
||||
'street-address' => __('Full Street Address', 'contact-form-7-dynamic-text-extension'),
|
||||
'shipping' => __('Full Shipping Address', 'contact-form-7-dynamic-text-extension'),
|
||||
'billing' => __('Full Billing Address', 'contact-form-7-dynamic-text-extension'),
|
||||
'address-line1' => __('Address Line 1', 'contact-form-7-dynamic-text-extension'),
|
||||
'address-line2' => __('Address Line 2', 'contact-form-7-dynamic-text-extension'),
|
||||
'address-line3' => __('Address Line 3', 'contact-form-7-dynamic-text-extension'),
|
||||
'address-level1' => __('State', 'contact-form-7-dynamic-text-extension'),
|
||||
'address-level2' => __('City', 'contact-form-7-dynamic-text-extension'),
|
||||
'country' => __('Country', 'contact-form-7-dynamic-text-extension'),
|
||||
'postal-code' => __('Zip Code', 'contact-form-7-dynamic-text-extension'),
|
||||
'sex' => __('Gender Identity', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel' => __('Phone Number', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-country-code' => __('Country Code', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-national' => __('Full phone number without the country code', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-area-code' => __('Area code, with country code if applicable', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-local' => __('Phone number without the country code or area code', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-local-prefix' => __('First part of the local phone number', 'contact-form-7-dynamic-text-extension'),
|
||||
'tel-local-suffix' => __('Last part of the local phone number', 'contact-form-7-dynamic-text-extension'),
|
||||
'url' => __('Website URL', 'contact-form-7-dynamic-text-extension'),
|
||||
'webauthn' => __('Passkeys generated by the Web Authentication API', 'contact-form-7-dynamic-text-extension')
|
||||
);
|
||||
$datalist_html = wpcf7dtx_options_html($datalist);
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><datalist id="dtx-autocomplete-datalist">%s</datalist><input %s /><input %s /><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-autocomplete'), // field id
|
||||
esc_html__('Auto-complete', 'contact-form-7-dynamic-text-extension'), // field label
|
||||
wp_kses($datalist_html, array('datalist' => array('id' => array()), 'option' => array('value' => array()))),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'autocomplete',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-autocomplete',
|
||||
'id' => $options['content'] . '-autocomplete',
|
||||
'class' => 'oneline dtx-option',
|
||||
'list' => 'dtx-autocomplete-datalist'
|
||||
)),
|
||||
esc_html($default_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View documentation for Dynamic Attributes', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
//Input field - Autocapitalize attribute (only available for some fields)
|
||||
if (in_array($input_type, array('text', 'textarea'))) {
|
||||
$default_description = __('Optionally define an autocapitalize attribute for input when entered via non-typing mechanisms such as virtual keyboards on mobile devices or voice-to-text.', 'contact-form-7-dynamic-text-extension') . ' ';
|
||||
$default_description .= __('Each can be static text or a shortcode.', 'contact-form-7-dynamic-text-extension');
|
||||
$datalist = array(
|
||||
'none' => __('Do not automatically capitlize any text', 'contact-form-7-dynamic-text-extension'),
|
||||
'off' => __('Do not automatically capitlize any text', 'contact-form-7-dynamic-text-extension'),
|
||||
'on' => __('Automatically capitalize the first character of each sentence', 'contact-form-7-dynamic-text-extension'),
|
||||
'sentences' => __('Automatically capitalize the first character of each sentence', 'contact-form-7-dynamic-text-extension'),
|
||||
'words' => __('Automatically capitalize the first character of each word', 'contact-form-7-dynamic-text-extension'),
|
||||
'characters' => __('Automatically capitalize every character', 'contact-form-7-dynamic-text-extension'),
|
||||
);
|
||||
$datalist_html = wpcf7dtx_options_html($datalist);
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><datalist id="dtx-autocapitalize-datalist">%s</datalist><input %s /><input %s /><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-autocapitalize'), // field id
|
||||
esc_html__('Auto-capitalize'), // field label
|
||||
wp_kses($datalist_html, array('datalist' => array('id' => array()), 'option' => array('value' => array()))),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'autocapitalize',
|
||||
'class' => 'option'
|
||||
)),
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'text',
|
||||
'name' => 'dtx-autocapitalize',
|
||||
'id' => $options['content'] . '-autocapitalize', // field id
|
||||
'class' => 'oneline dtx-option',
|
||||
'list' => 'dtx-autocapitalize-datalist'
|
||||
)),
|
||||
esc_html($default_description), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View documentation for Dynamic Attributes', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
);
|
||||
}
|
||||
|
||||
//Input field - Readonly attribute (not available for hidden, submit, or quiz fields)
|
||||
if (!in_array($input_type, array('hidden', 'submit', 'label', 'quiz', 'select'))) {
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-readonly'), // field id
|
||||
esc_html__('Read only attribute', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'readonly',
|
||||
'id' => $options['content'] . '-readonly',
|
||||
'class' => 'readonlyvalue option'
|
||||
)),
|
||||
esc_html__('Do not let users edit this field', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
);
|
||||
}
|
||||
|
||||
//Input field - Disabled attribute (not available for hidden, submit, or quiz fields)
|
||||
// if (!in_array($input_type, array('hidden', 'submit', 'quiz'))) {
|
||||
// printf(
|
||||
// '<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
// esc_attr($options['content'] . '-disabled'), // field id
|
||||
// esc_html__('Disabled attribute', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
// wpcf7_format_atts(array(
|
||||
// 'type' => 'checkbox',
|
||||
// 'name' => 'disabled',
|
||||
// 'id' => $options['content'] . '-disabled',
|
||||
// 'class' => 'disabledvalue option'
|
||||
// )),
|
||||
// esc_html__('Prevent this data from sending on submit', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
// );
|
||||
// }
|
||||
|
||||
//Input field - Autofocus attribute (not available for hidden, submit, or quiz fields)
|
||||
// if (!in_array($input_type, array('hidden', 'submit', 'quiz'))) {
|
||||
// printf(
|
||||
// '<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
// esc_attr($options['content'] . '-autofocus'), // field id
|
||||
// esc_html__('Autofocus attribute', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
// wpcf7_format_atts(array(
|
||||
// 'type' => 'checkbox',
|
||||
// 'name' => 'autofocus',
|
||||
// 'id' => $options['content'] . '-autofocus',
|
||||
// 'class' => 'autofocusvalue option'
|
||||
// )),
|
||||
// wp_kses_post('Automatically focus on this field <small>Use careful consideration for accessibility.</small>', 'contact-form-7-dynamic-text-extension') // checkbox label
|
||||
// );
|
||||
// }
|
||||
|
||||
// Input field - Page load data attribute (triggers the loading of a frontend script)
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label><br /><small>%s <a href="https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tag-attribute-after-page-load/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=form-tag-generator-%s" target="_blank" rel="noopener">%s</a></small></td></tr>',
|
||||
esc_attr($options['content'] . '-dtx_pageload'), // field id
|
||||
esc_html__('Cache Compatible', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'dtx_pageload',
|
||||
'id' => $options['content'] . '-dtx_pageload',
|
||||
'class' => 'option'
|
||||
)),
|
||||
esc_html__('Get the dynamic value after the page has loaded', 'contact-form-7-dynamic-text-extension'), // checkbox label
|
||||
esc_html__('May impact page performance.', 'contact-form-7-dynamic-text-extension'), // Small note below input
|
||||
esc_attr($utm_source), //UTM source
|
||||
esc_attr($type), //UTM content
|
||||
esc_html__('View DTX page load documentation', 'contact-form-7-dynamic-text-extension') //Link label
|
||||
|
||||
);
|
||||
|
||||
// Input field - Akismet module (only available for text, email, and url fields)
|
||||
if (in_array($input_type, array('text', 'email', 'url'))) {
|
||||
switch ($input_type) {
|
||||
case 'email':
|
||||
$akismet_name = 'author_email';
|
||||
$akismet_desc = __("This field requires author's email address", 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
case 'url':
|
||||
$akismet_name = 'author_url';
|
||||
$akismet_desc = __("This field requires author's URL", 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
default:
|
||||
$akismet_name = 'author';
|
||||
$akismet_desc = __("This field requires author's name", 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
}
|
||||
printf(
|
||||
'<tr><th scope="row"><label for="%s">%s</label></th><td><label><input %s />%s</label></td></tr>',
|
||||
esc_attr($options['content'] . '-readonly'), // field id
|
||||
esc_html__('Akismet', 'contact-form-7-dynamic-text-extension'), // field Label
|
||||
wpcf7_format_atts(array(
|
||||
'type' => 'checkbox',
|
||||
'name' => 'akismet:' . $akismet_name,
|
||||
'id' => $options['content'] . '-akismet-' . $akismet_name,
|
||||
'class' => 'akismetvalue option'
|
||||
)),
|
||||
esc_html($akismet_desc) // checkbox label
|
||||
);
|
||||
}
|
||||
|
||||
//Close Form-Tag Generator
|
||||
if (in_array($input_type, array('hidden', 'submit', 'label', 'reset'))) {
|
||||
$demo_tag = '<input name="%s"class="tag code" readonly="readonly" onfocus="this.select()" type="text" />';
|
||||
} else {
|
||||
$demo_tag = '<textarea name="%s" class="tag code"readonly="readonly" onfocus="this.select()" rows="3" ></textarea>';
|
||||
}
|
||||
if (in_array($input_type, array('submit', 'reset', 'label'))) {
|
||||
$mail_description = esc_html('This value is not submitted in the contact form and should not be used in the mail template.', 'contact-form-7-dynamic-text-extension');
|
||||
} else {
|
||||
$mail_description = sprintf(
|
||||
'<label>%s<input type="text" class="mail-tag code hidden" readonly="readonly" /></label>',
|
||||
sprintf(
|
||||
esc_html__('To use the value input through this field in a mail field, you need to insert the corresponding mail-tag (%s) into the field on the Mail tab.', 'contact-form-7-dynamic-text-extension'),
|
||||
'<strong><span class="mail-tag"></span></strong>'
|
||||
)
|
||||
);
|
||||
}
|
||||
printf(
|
||||
'</tbody></table></fieldset></div><div class="insert-box">' . $demo_tag . '<div class="submitbox"><input type="button" class="button button-primary dtx-insert-tag" value="%s" /></div><br class="clear" />
|
||||
<p class="description mail-tag">%s</p></div>',
|
||||
esc_attr($type),
|
||||
esc_html__('Insert Tag', 'contact-form-7-dynamic-text-extension'),
|
||||
$mail_description
|
||||
);
|
||||
}
|
||||
@@ -1,763 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class CF7DTX_Plugin_Settings
|
||||
*
|
||||
* Configure the plugin settings page.
|
||||
*/
|
||||
class CF7DTX_Plugin_Settings
|
||||
{
|
||||
|
||||
/**
|
||||
* Capability required by the user to access the My Plugin menu entry.
|
||||
*
|
||||
* @var string $capability
|
||||
*/
|
||||
private $capability = 'manage_options';
|
||||
|
||||
private $sections;
|
||||
private $fields;
|
||||
|
||||
private $num_forms_to_scan = 20;
|
||||
|
||||
/**
|
||||
* The Plugin Settings constructor.
|
||||
*/
|
||||
function __construct($sections, $fields)
|
||||
{
|
||||
add_action('admin_init', [$this, 'settings_init']);
|
||||
add_action('admin_menu', [$this, 'options_page']);
|
||||
|
||||
$this->sections = $sections;
|
||||
$this->fields = $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the settings and all fields.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function settings_init(): void
|
||||
{
|
||||
|
||||
// Register a new setting this page.
|
||||
register_setting('cf7dtx_settings', 'cf7dtx_settings');
|
||||
|
||||
foreach ($this->sections as $section_id => $section) {
|
||||
// Register a new section.
|
||||
add_settings_section(
|
||||
$section_id,
|
||||
$section['title'],
|
||||
[$this, 'render_section'],
|
||||
'cf7dtx_settings',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Register All The Fields. */
|
||||
foreach ($this->fields as $field) {
|
||||
// Register a new field in the main section.
|
||||
add_settings_field(
|
||||
$field['id'], /* ID for the field. Only used internally. To set the HTML ID attribute, use $args['label_for']. */
|
||||
$field['label'], /* Label for the field. */
|
||||
[$this, 'render_field'], /* The name of the callback function. */
|
||||
'cf7dtx_settings', /* The menu page on which to display this field. */
|
||||
$field['section'], /* The section of the settings page in which to show the box. */
|
||||
[
|
||||
'label_for' => $field['id'], /* The ID of the field. */
|
||||
'class' => 'cf7dtx_row', /* The class of the field. */
|
||||
'field' => $field, /* Custom data for the field. */
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subpage to the WordPress Settings menu.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function options_page(): void
|
||||
{
|
||||
add_submenu_page(
|
||||
'wpcf7', /* Parent Menu Slug */
|
||||
'Contact Form 7 - Dynamic Text Extension', /* Page Title */
|
||||
'Dynamic Text Extension', /* Menu Title */
|
||||
$this->capability, /* Capability */
|
||||
'cf7dtx_settings', /* Menu Slug */
|
||||
[$this, 'render_options_page'], /* Callback */
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the settings page.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function render_options_page(): void
|
||||
{
|
||||
|
||||
// check user capabilities
|
||||
if (!current_user_can($this->capability)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_GET['dismiss-access-keys-notice'])) {
|
||||
wpcf7dtx_set_update_access_scan_check_status('notice_dismissed');
|
||||
?>
|
||||
<div class="notice notice-success dtx-notice">
|
||||
<p><?php _e('Notice Dismissed. You can run the scan any time from the CF7 DTX settings page', 'contact-form-7-dynamic-text-extension'); ?></p>
|
||||
<p><?php $this->render_back_to_settings_button(); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
if (isset($_GET['scan-meta-keys'])) {
|
||||
|
||||
|
||||
if (isset($_POST['save-allows'])) {
|
||||
$r = $this->handle_save_allows();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('DTX: Keys Added To Allow List', 'contact-form-7-dynamic-text-extension'); ?></h1>
|
||||
|
||||
<?php $this->render_allow_keys_submission($r); ?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
$offset = isset($_GET['offset']) ? $_GET['offset'] : 0;
|
||||
$results = wpcf7dtx_scan_forms_for_access_keys($this->num_forms_to_scan, $offset);
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('DTX: Form Shortcode Scan Results', 'contact-form-7-dynamic-text-extension'); ?></h1>
|
||||
|
||||
<?php $this->render_scan_results($results); ?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
|
||||
// add error/update messages
|
||||
|
||||
// check if the user have submitted the settings
|
||||
// WordPress will add the "settings-updated" $_GET parameter to the url
|
||||
if (isset($_GET['settings-updated'])) {
|
||||
// add settings saved message with the class of "updated"
|
||||
add_settings_error('cf7dtx_messages', 'cf7dtx_message', __('Settings Saved', 'contact-form-7-dynamic-text-extension'), 'updated');
|
||||
}
|
||||
|
||||
// show error/update messages
|
||||
settings_errors('cf7dtx_messages');
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
/* output security fields for the registered setting "cf7dtx" */
|
||||
settings_fields('cf7dtx_settings');
|
||||
/* output setting sections and their fields */
|
||||
/* (sections are registered for "cf7dtx", each field is registered to a specific section) */
|
||||
do_settings_sections('cf7dtx_settings');
|
||||
/* output save settings button */
|
||||
submit_button('Save Settings');
|
||||
?>
|
||||
</form>
|
||||
|
||||
<a href="<?php echo wpcf7dtx_get_admin_scan_screen_url(); ?>">Scan Forms for Post Meta and User Data Keys</a>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a settings field.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @param array $args Args to configure the field.
|
||||
*/
|
||||
function render_field(array $args): void
|
||||
{
|
||||
|
||||
$field = $args['field'];
|
||||
|
||||
// Get the value of the setting we've registered with register_setting()
|
||||
$options = get_option('cf7dtx_settings');
|
||||
|
||||
switch ($field['type']) {
|
||||
|
||||
case "text": {
|
||||
?>
|
||||
<input type="text" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "checkbox": {
|
||||
?>
|
||||
<input type="checkbox" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="1" <?php echo isset($options[$field['id']]) ? (checked($options[$field['id']], 1, false)) : (''); ?>>
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "textarea": {
|
||||
?>
|
||||
<textarea id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" style="width:400px; height:200px;"><?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?></textarea>
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "select": {
|
||||
?>
|
||||
<select id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]">
|
||||
<?php foreach ($field['options'] as $key => $option) { ?>
|
||||
<option value="<?php echo $key; ?>" <?php echo isset($options[$field['id']]) ? (selected($options[$field['id']], $key, false)) : (''); ?>>
|
||||
<?php echo $option; ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "password": {
|
||||
?>
|
||||
<input type="password" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "wysiwyg": {
|
||||
wp_editor(
|
||||
isset($options[$field['id']]) ? $options[$field['id']] : '',
|
||||
$field['id'],
|
||||
array(
|
||||
'textarea_name' => 'cf7dtx_settings[' . $field['id'] . ']',
|
||||
'textarea_rows' => 5,
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "email": {
|
||||
?>
|
||||
<input type="email" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "url": {
|
||||
?>
|
||||
<input type="url" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "color": {
|
||||
?>
|
||||
<input type="color" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
||||
case "date": {
|
||||
?>
|
||||
<input type="date" id="<?php echo esc_attr($field['id']); ?>" name="cf7dtx_settings[<?php echo esc_attr($field['id']); ?>]" value="<?php echo isset($options[$field['id']]) ? esc_attr($options[$field['id']]) : ''; ?>">
|
||||
<p class="description">
|
||||
<?php esc_html_e($field['description'], 'cf7dtx_settings'); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render a section on a page, with an ID and a text label.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $args {
|
||||
* An array of parameters for the section.
|
||||
*
|
||||
* @type string $id The ID of the section.
|
||||
* }
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function render_section(array $args): void
|
||||
{
|
||||
?>
|
||||
<p id="<?php echo esc_attr($args['id']); ?>"><?php echo $this->sections[$args['id']]['description']; ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Scan Results
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $results The results array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function render_scan_results($results)
|
||||
{
|
||||
// No forms are using the shortcodes in question
|
||||
if (!count($results['forms'])) {
|
||||
|
||||
wpcf7dtx_set_update_access_scan_check_status('intervention_not_required');
|
||||
|
||||
echo '<div class="notice notice-success dtx-notice"><p>' . __('Scan complete. No keys detected.', 'contact-form-7-dynamic-text-extension') . '</p></div>';
|
||||
$this->render_back_to_settings_button();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we need to scan another batch
|
||||
if ($results['forms_scanned'] === $this->num_forms_to_scan) {
|
||||
$offset = isset($_GET['offset']) ? $_GET['offset'] : 0;
|
||||
$next_offset = $offset + $this->num_forms_to_scan;
|
||||
echo '<div class="notice notice-warning dtx-notice"><p>';
|
||||
echo sprintf(
|
||||
__('%1$s forms scanned. There may be more forms to scan.', 'contact-form-7-dynamic-text-extension'),
|
||||
$results['forms_scanned'],
|
||||
);
|
||||
echo ' ';
|
||||
echo '<a href="' . wpcf7dtx_get_admin_scan_screen_url($next_offset) . '">' . sprintf(
|
||||
__('Scan %1$s more forms', 'contact-form-7-dynamic-text-extension'),
|
||||
$this->num_forms_to_scan
|
||||
) . '</a>';
|
||||
echo '</p></div>';
|
||||
}
|
||||
|
||||
$settings = wpcf7dtx_get_settings();
|
||||
$already_allowed_meta_keys = wpcf7dtx_parse_allowed_keys(wpcf7dtx_array_has_key('post_meta_allow_keys', $settings));
|
||||
$already_allowed_user_keys = wpcf7dtx_parse_allowed_keys(wpcf7dtx_array_has_key('user_data_allow_keys', $settings));
|
||||
|
||||
// Check the results ahead of time to see if all of the keys are already in the allow list - if so, nothing to do
|
||||
$forms = $results['forms'];
|
||||
$all_keys_allowed = true;
|
||||
foreach ($forms as $form_id => $r) {
|
||||
if (count($r['meta_keys'])) {
|
||||
foreach ($r['meta_keys'] as $key) {
|
||||
if (!in_array($key, $already_allowed_meta_keys)) {
|
||||
$all_keys_allowed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($all_keys_allowed === false) break;
|
||||
}
|
||||
if (count($r['user_keys'])) {
|
||||
foreach ($r['user_keys'] as $key) {
|
||||
if (!in_array($key, $already_allowed_user_keys)) {
|
||||
$all_keys_allowed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($all_keys_allowed === false) break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($all_keys_allowed) {
|
||||
wpcf7dtx_set_update_access_scan_check_status('intervention_completed');
|
||||
} ?>
|
||||
<style>
|
||||
.postbox,
|
||||
.dtx-notice {
|
||||
max-width: 600px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.postbox-header {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.postbox-header h2 {
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.key-disabled {
|
||||
opacity: .8;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
|
||||
<?php if ($all_keys_allowed) : ?>
|
||||
<div class="notice notice-success dtx-notice">
|
||||
<p><?php
|
||||
echo sprintf(
|
||||
__('Scan of %1$s forms complete. All keys detected are already on allow list. No action necessary for these forms.', 'contact-form-7-dynamic-text-extension'),
|
||||
$results['forms_scanned'],
|
||||
); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="notice notice-error dtx-notice" style="width:600px; box-sizing:border-box;">
|
||||
<p><strong><?php _e('Shortcodes accessing potentially sensitive Post Meta or User Data were detected in the forms listed below.', 'contact-form-7-dynamic-text-extension'); ?></strong></p>
|
||||
<p><?php _e('Only keys on the allow list will return their value when accessed. Attempting to access keys that are not on the allow list via DTX shortcodes will return an empty string and throw a warning message.', 'contact-form-7-dynamic-text-extension'); ?></p>
|
||||
<p><?php _e('Review the keys below and confirm that you want to allow access, then select meta and/or user keys to add them to the relevant allow list. Any keys for sensitive data should be removed by editing your contact form.', 'contact-form-7-dynamic-text-extension'); ?></p>
|
||||
<p><?php _e('Note that keys which are already in the allow list are displayed but marked as already selected.', 'contact-form-7-dynamic-text-extension'); ?></p>
|
||||
<p><a href="<?php echo WPCF7DTX_DATA_ACCESS_KB_URL; ?>" target="_blank"><?php _e('More Information', 'contact-form-7-dynamic-text-extension'); ?></a></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="admin.php?page=cf7dtx_settings&scan-meta-keys" method="post">
|
||||
|
||||
<?php
|
||||
|
||||
settings_fields('cf7dtx_settings');
|
||||
|
||||
foreach ($results['forms'] as $form_id => $r) {
|
||||
?>
|
||||
<div class="postbox">
|
||||
<div class="postbox-header">
|
||||
<h2><?php echo $r['title']; ?></h2>
|
||||
<a href="<?php echo $r['admin_url']; ?>" target="_blank">View form</a>
|
||||
</div>
|
||||
<div class="inside">
|
||||
<?php if (count($r['meta_keys'])) : ?>
|
||||
<h4>Meta Keys</h3>
|
||||
|
||||
<div>
|
||||
<?php foreach ($r['meta_keys'] as $key) {
|
||||
$already_allowed = in_array($key, $already_allowed_meta_keys);
|
||||
$name = "dtx_meta_key/$key";
|
||||
?>
|
||||
<div>
|
||||
<label <?php if ($already_allowed) echo 'class="key-disabled" title="Already in Allow List"'; ?>>
|
||||
<input name="<?php echo $name; ?>" id="<?php echo $name; ?>" type="checkbox" value="1" <?php if ($already_allowed) echo 'checked="checked" disabled'; ?> />
|
||||
<?php echo $key; ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (count($r['user_keys'])) : ?>
|
||||
<h4>User Data Keys</h3>
|
||||
<div>
|
||||
<?php foreach ($r['user_keys'] as $key) {
|
||||
$name = "dtx_user_key/$key";
|
||||
$already_allowed = in_array($key, $already_allowed_user_keys);
|
||||
?>
|
||||
<div>
|
||||
<label <?php if ($already_allowed) echo 'class="key-disabled" title="Already in Allow List"'; ?>>
|
||||
<input name="<?php echo $name; ?>" id="<?php echo $name; ?>" type="checkbox" value="1" <?php if ($already_allowed) echo 'checked="checked" disabled'; ?> />
|
||||
<?php echo $key; ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if (!$all_keys_allowed) submit_button(__('Add Selected Keys to Allow Lists', 'contact-form-7-dynamic-text-extension'), 'primary', 'save-allows'); ?>
|
||||
</form>
|
||||
<?php $this->render_back_to_settings_button(); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Save Allows
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return array Save results.
|
||||
*/
|
||||
function handle_save_allows()
|
||||
{
|
||||
$user_keys = [];
|
||||
$meta_keys = [];
|
||||
|
||||
// Find saved keys
|
||||
foreach ($_POST as $key => $val) {
|
||||
if (str_starts_with($key, 'dtx_meta_key')) {
|
||||
$parts = explode('/', $key);
|
||||
$meta_keys[] = $parts[1];
|
||||
} else if (str_starts_with($key, 'dtx_user_key')) {
|
||||
$parts = explode('/', $key);
|
||||
$user_keys[] = $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Add those keys in options
|
||||
$settings = wpcf7dtx_get_settings();
|
||||
|
||||
// Meta Data
|
||||
if (count($meta_keys)) {
|
||||
// Get already saved values
|
||||
$post_meta_allow_keys = isset($settings['post_meta_allow_keys']) ? wpcf7dtx_parse_allowed_keys($settings['post_meta_allow_keys']) : [];
|
||||
// Merge with new values
|
||||
$new = array_unique(array_merge($post_meta_allow_keys, $meta_keys));
|
||||
$settings['post_meta_allow_keys'] = implode(PHP_EOL, $new);
|
||||
}
|
||||
|
||||
|
||||
// User Data
|
||||
if (count($user_keys)) {
|
||||
// Get already saved values
|
||||
$user_data_allow_keys = isset($settings['user_data_allow_keys']) ? wpcf7dtx_parse_allowed_keys($settings['user_data_allow_keys']) : [];
|
||||
// Merge with new values
|
||||
$new = array_unique(array_merge($user_data_allow_keys, $user_keys));
|
||||
$settings['user_data_allow_keys'] = implode(PHP_EOL, $new);
|
||||
}
|
||||
|
||||
// Update with new settings
|
||||
wpcf7dtx_update_settings($settings);
|
||||
|
||||
// Mark as intervention complete
|
||||
wpcf7dtx_set_update_access_scan_check_status('intervention_completed');
|
||||
|
||||
return [
|
||||
'user' => $user_keys,
|
||||
'meta' => $meta_keys,
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Render Allow Keys Submission
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $results The results array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function render_allow_keys_submission($r)
|
||||
{
|
||||
|
||||
?>
|
||||
<?php if (count($r['meta'])) : ?>
|
||||
<p><?php _e('Meta Keys Added', 'contact-form-7-dynamic-text-extension'); ?>: <?php echo implode(', ', $r['meta']); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if (count($r['user'])) : ?>
|
||||
<p><?php _e('User Data Keys Added', 'contact-form-7-dynamic-text-extension'); ?>: <?php echo implode(', ', $r['user']); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!count($r['meta']) && !count($r['user'])) : ?>
|
||||
<p><?php _e('No Keys Selected', 'contact-form-7-dynamic-text-extension'); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$this->render_back_to_settings_button();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Back to Settings Button
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function render_back_to_settings_button()
|
||||
{
|
||||
?>
|
||||
<a href="<?php echo wpcf7dtx_get_admin_settings_screen_url(); ?>">« <?php _e('Back to Settings', 'contact-form-7-dynamic-text-extension'); ?></a>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$sections = [
|
||||
'post_meta_access' => [
|
||||
'title' => __('Post Meta Access', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('Control which post metadata the CF7 DTX shortcodes (CF7_get_custom_field) can access. By default, all metadata is protected, so you can open up access through these settings. Keep in mind that users with Contributor+ credentials can add shortcodes and therefore access this data, so make sure not to expose anything sensitive.') .
|
||||
' <a href="' . WPCF7DTX_DATA_ACCESS_KB_URL . '" target="_blank">' . __('More Information', 'contact-form-7-dynamic-text-extension') . '</a>',
|
||||
],
|
||||
'user_data_access' => [
|
||||
'title' => __('User Data Access', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('Control which user data the CF7 DTX shortcodes (CF7_get_current_user) can access. By default, all user data is protected, so you can open up access through these settings. Keep in mind that users with Contributor+ credentials can add shortcodes and therefore access this data, so make sure not to expose anything sensitive.') .
|
||||
' <a href="' . WPCF7DTX_DATA_ACCESS_KB_URL . '" target="_blank">' . __('More Information', 'contact-form-7-dynamic-text-extension') . '</a>',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Array of fields that should be displayed in the settings page.
|
||||
*
|
||||
* @var array $fields
|
||||
*/
|
||||
$fields = [
|
||||
[
|
||||
'id' => 'post_meta_allow_keys',
|
||||
'label' => __('Meta Key Allow List', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('Allow access to these specific post metadata keys. Enter one per line.', 'contact-form-7-dynamic-text-extension'),
|
||||
'type' => 'textarea',
|
||||
'section' => 'post_meta_access',
|
||||
],
|
||||
[
|
||||
'id' => 'post_meta_allow_all',
|
||||
'label' => __('Allow Access to All Post Metadata', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('**Use with caution.** Should only be enabled if all authorized users with editor privileges (Contributor+) are trusted and should have access to this data. All metadata from any post (including custom post types) will be accessible via the CF7_get_custom_field shortcode. If in doubt, use the Allow List to allow only specific keys.', 'contact-form-7-dynamic-text-extension'),
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'disabled' => __('Disabled - Only Allow Access to Meta Key Allow List', 'contact-form-7-dynamic-text-extension'),
|
||||
'enabled' => __('Enabled - Allow Access to All Post Metadata', 'contact-form-7-dynamic-text-extension'),
|
||||
],
|
||||
'section' => 'post_meta_access',
|
||||
],
|
||||
[
|
||||
'id' => 'user_data_allow_keys',
|
||||
'label' => __('User Data Key Allow List', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('Allow access to these specific user data keys. Enter one per line.', 'contact-form-7-dynamic-text-extension'),
|
||||
'type' => 'textarea',
|
||||
'section' => 'user_data_access',
|
||||
],
|
||||
[
|
||||
'id' => 'user_data_allow_all',
|
||||
'label' => __('Allow Access to All User Data', 'contact-form-7-dynamic-text-extension'),
|
||||
'description' => __('**Use with caution.** Should only be enabled if all authorized users with editor privileges (Contributor+) are trusted and should have access to this data. All of the current user\'s data fields will be accessible via the CF7_get_current_user shortcode. If in doubt, use the Allow List to allow only specific keys.', 'contact-form-7-dynamic-text-extension'),
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'disabled' => __('Disabled - Only Allow Access to User Data Key Allow List', 'contact-form-7-dynamic-text-extension'),
|
||||
'enabled' => __('Enabled - Allow Access to User Data', 'contact-form-7-dynamic-text-extension'),
|
||||
],
|
||||
'section' => 'user_data_access',
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
new CF7DTX_Plugin_Settings($sections, $fields);
|
||||
|
||||
|
||||
function wpcf7dtx_get_admin_scan_screen_url($offset = 0)
|
||||
{
|
||||
$path = 'admin.php?page=cf7dtx_settings&scan-meta-keys';
|
||||
if ($offset) {
|
||||
$path .= '&offset=' . $offset;
|
||||
}
|
||||
return admin_url($path);
|
||||
}
|
||||
function wpcf7dtx_get_admin_settings_screen_url()
|
||||
{
|
||||
return admin_url('admin.php?page=cf7dtx_settings');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search all CF7 forms for
|
||||
*/
|
||||
function wpcf7dtx_scan_forms_for_access_keys($num, $offset = 0)
|
||||
{
|
||||
|
||||
$found = [
|
||||
'forms' => [],
|
||||
];
|
||||
$forms = [];
|
||||
|
||||
if (function_exists('wpcf7_contact_form')) {
|
||||
|
||||
$cf7forms = get_posts([
|
||||
'post_type' => 'wpcf7_contact_form',
|
||||
// 'numberposts' => $numposts, // sanity check
|
||||
'posts_per_page' => $num,
|
||||
'offset' => $offset,
|
||||
]);
|
||||
|
||||
$found['forms_scanned'] = count($cf7forms);
|
||||
|
||||
// Loop through forms
|
||||
foreach ($cf7forms as $form) {
|
||||
|
||||
// Search for the custom fields shortcode
|
||||
if (
|
||||
strpos($form->post_content, 'CF7_get_custom_field') !== false ||
|
||||
strpos($form->post_content, 'CF7_get_current_user') !== false
|
||||
) {
|
||||
$cf7 = wpcf7_contact_form($form->ID);
|
||||
|
||||
$forms[$form->ID] = [
|
||||
'title' => $cf7->title(),
|
||||
'meta_keys' => [],
|
||||
'user_keys' => [],
|
||||
'admin_url' => admin_url("admin.php?page=wpcf7&post={$form->ID}&action=edit"),
|
||||
];
|
||||
|
||||
$tags = $cf7->scan_form_tags();
|
||||
|
||||
// Check each tag
|
||||
foreach ($tags as $tag) {
|
||||
// Find dynamic tags
|
||||
if (str_starts_with($tag->type, 'dynamic')) {
|
||||
// Check each value
|
||||
foreach ($tag->values as $val) {
|
||||
// Find CF7_get_custom_field
|
||||
if (str_starts_with($val, 'CF7_get_custom_field')) {
|
||||
// Parse out the shortcode atts
|
||||
$atts = shortcode_parse_atts($val);
|
||||
if ($atts) {
|
||||
// Grab the meta key
|
||||
$meta_key = $atts['key'];
|
||||
|
||||
// Add meta key to the list
|
||||
if ($meta_key) {
|
||||
$forms[$form->ID]['meta_keys'][] = $meta_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find CF7_get_current_user
|
||||
if (str_starts_with($val, 'CF7_get_current_user')) {
|
||||
// Parse out the shortcode atts
|
||||
$atts = shortcode_parse_atts($val);
|
||||
if ($atts) {
|
||||
// Grab user data key
|
||||
$key = $atts['key'];
|
||||
if ($key) {
|
||||
$forms[$form->ID]['user_keys'][] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$found['forms'] = $forms;
|
||||
return $found;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Check for Updates
|
||||
*
|
||||
* Hooked to `plugins_loaded` to compare source code version with database version.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_update_check()
|
||||
{
|
||||
if (WPCF7DTX_VERSION !== get_option('cf7dtx_version', '')) {
|
||||
|
||||
// Update the database version with the current plugin version
|
||||
update_option('cf7dtx_version', WPCF7DTX_VERSION);
|
||||
|
||||
// Run the update handler
|
||||
add_action('admin_init', 'wpcf7dtx_update');
|
||||
}
|
||||
}
|
||||
add_action('plugins_loaded', 'wpcf7dtx_update_check');
|
||||
|
||||
/**
|
||||
* Maybe Update DTX
|
||||
*
|
||||
* Optionally hooked to `admin_init` when source code version is newer than database version.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_update()
|
||||
{
|
||||
|
||||
// v4.2.0 will scan for meta and user keys that should be allow-listed and display an admin alert
|
||||
wpcf7dtx_v4_2_0_access_scan_check();
|
||||
|
||||
// Future update processes would go here
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* DTX Form Scan
|
||||
*
|
||||
* Scan for meta and user keys that should be allowlisted and display an admin alert.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_v4_2_0_access_scan_check()
|
||||
{
|
||||
|
||||
$op = 'cf7dtx_v4_2_0_access_scan_check_status';
|
||||
$status = get_option($op, '');
|
||||
|
||||
// Status values:
|
||||
// intervention_required - show a notice to the admin
|
||||
// intervention_not_required - we can ignore
|
||||
// intervention_completed - no need to show notice any longer
|
||||
// notice_dismissed - alert was dismissed by user
|
||||
|
||||
// If we've never checked before
|
||||
if ($status === '') {
|
||||
// Run a scan - 20 by default. If they have more than 20 forms, we'll alert regardless.
|
||||
// For less than 20 forms, we'll only alert if we detect an issue
|
||||
$num_to_scan = 20;
|
||||
$r = wpcf7dtx_scan_forms_for_access_keys($num_to_scan);
|
||||
$found = count($r['forms']);
|
||||
$scanned = $r['forms_scanned'];
|
||||
|
||||
// If keys were found, or if we scanned the max number (so there are likely more to be scanned)
|
||||
if ($found || $scanned === $num_to_scan) {
|
||||
// We'll show a notice to the user
|
||||
$status = 'intervention_required';
|
||||
} else {
|
||||
// No keys need to be allow-listed, no need to show the user a list
|
||||
$status = 'intervention_not_required';
|
||||
}
|
||||
wpcf7dtx_set_update_access_scan_check_status($status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DTX Admin Notice
|
||||
*
|
||||
* Display an admin notice if there are unresolved issues with accessing disallowed keys via DTX shortcodes
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_access_keys_notice()
|
||||
{
|
||||
|
||||
// Don't show this notice on the Scan Results screen to avoid confusion
|
||||
if (isset($_GET['page']) && $_GET['page'] === 'cf7dtx_settings' && (isset($_GET['scan-meta-keys']) || isset($_GET['dismiss-access-keys-notice']))) return;
|
||||
|
||||
// If this user is not an administrator, don't do anything. Only admins should see this.
|
||||
$user = wp_get_current_user();
|
||||
if (!in_array('administrator', (array) $user->roles)) return;
|
||||
|
||||
// If the status doesn't require intervention, don't do anything
|
||||
$status = get_option('cf7dtx_v4_2_0_access_scan_check_status', '');
|
||||
if ($status !== 'intervention_required') {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="notice notice-error">
|
||||
<p>
|
||||
<?php _e('CF7 DTX: Shortcode data access requires allow-listing.', 'contact-form-7-dynamic-text-extension'); ?>
|
||||
<a href="<?php echo wpcf7dtx_get_admin_settings_screen_url(); ?>"><?php _e('Edit Settings', 'contact-form-7-dynamic-text-extension'); ?></a>
|
||||
|
|
||||
<a href="<?php echo wpcf7dtx_get_admin_scan_screen_url(); ?>"><?php _e('Scan & Resolve', 'contact-form-7-dynamic-text-extension'); ?></a>
|
||||
|
|
||||
<a href="<?php echo WPCF7DTX_DATA_ACCESS_KB_URL; ?>" target="_blank"><?php _e('More Information', 'contact-form-7-dynamic-text-extension'); ?></a>
|
||||
<?php if (isset($_GET['page']) && $_GET['page'] === 'cf7dtx_settings') : ?>
|
||||
| <a href="<?php echo admin_url('admin.php?page=cf7dtx_settings&dismiss-access-keys-notice'); ?>"><?php _e('Dismiss', 'contact-form-7-dynamic-text-extension'); ?></a>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
add_action('admin_notices', 'wpcf7dtx_access_keys_notice');
|
||||
|
||||
/**
|
||||
* Set Scan Status
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $status
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_set_update_access_scan_check_status($status)
|
||||
{
|
||||
update_option('cf7dtx_v4_2_0_access_scan_check_status', $status);
|
||||
}
|
||||
@@ -1,658 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*****************************************************
|
||||
* Included Shortcodes
|
||||
*
|
||||
* See documentation for usage:
|
||||
* https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/
|
||||
*
|
||||
*****************************************************/
|
||||
|
||||
/**
|
||||
* Initialise DTX included shortcodes
|
||||
*
|
||||
* Hooked to `init`
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_init_shortcodes()
|
||||
{
|
||||
add_shortcode('CF7_GET', 'wpcf7dtx_get', 10, 1);
|
||||
add_shortcode('CF7_POST', 'wpcf7dtx_post', 10, 1);
|
||||
add_shortcode('CF7_URL', 'wpcf7dtx_url', 10, 1);
|
||||
add_shortcode('CF7_referrer', 'wpcf7dtx_referrer', 10, 1);
|
||||
add_shortcode('CF7_bloginfo', 'wpcf7dtx_bloginfo', 10, 1);
|
||||
add_shortcode('CF7_get_post_var', 'wpcf7dtx_get_post_var', 10, 1);
|
||||
add_shortcode('CF7_get_custom_field', 'wpcf7dtx_get_custom_field', 10, 1);
|
||||
add_shortcode('CF7_get_current_var', 'wpcf7dtx_get_current_var', 10, 1);
|
||||
add_shortcode('CF7_get_current_user', 'wpcf7dtx_get_current_user', 10, 1);
|
||||
add_shortcode('CF7_get_attachment', 'wpcf7dtx_get_attachment', 10, 1);
|
||||
add_shortcode('CF7_get_cookie', 'wpcf7dtx_get_cookie', 10, 1);
|
||||
add_shortcode('CF7_get_taxonomy', 'wpcf7dtx_get_taxonomy', 10, 1);
|
||||
add_shortcode('CF7_get_theme_option', 'wpcf7dtx_get_theme_option', 10, 1);
|
||||
add_shortcode('CF7_guid', 'wpcf7dtx_guid', 10, 0);
|
||||
}
|
||||
add_action('init', 'wpcf7dtx_init_shortcodes'); //Add init hook to add shortcodes
|
||||
|
||||
/**
|
||||
* Get Variable from $_GET Array
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-php-get-variables/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => 0,
|
||||
'default' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$raw = wpcf7dtx_array_has_key($atts['key'], $_GET, $atts['default']);
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters(
|
||||
'wpcf7dtx_escape',
|
||||
apply_filters('wpcf7dtx_sanitize', $raw),
|
||||
$atts['obfuscate']
|
||||
), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'GET', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Variable from $_POST Array
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-php-post-variables/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_post($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => '',
|
||||
'default' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$raw = wpcf7dtx_array_has_key($atts['key'], $_POST, $atts['default']);
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', apply_filters(
|
||||
'wpcf7dtx_sanitize',
|
||||
apply_filters('wpcf7dtx_sanitize', $raw)
|
||||
), $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'POST', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Current URL or Part
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-url/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_url($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'allowed_protocols' => '',
|
||||
'part' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$atts['allowed_protocols'] = explode(',', sanitize_text_field($atts['allowed_protocols']));
|
||||
extract($atts);
|
||||
|
||||
// Get the absolute URL
|
||||
if (is_multisite() && !is_subdomain_install()) {
|
||||
// Network installs not using subdomains
|
||||
$url = apply_filters('wpcf7dtx_sanitize', network_home_url($_SERVER['REQUEST_URI']), 'url', $allowed_protocols);
|
||||
} else {
|
||||
// Single installs and network installs using subdomains
|
||||
$url = apply_filters('wpcf7dtx_sanitize', home_url($_SERVER['REQUEST_URI']), 'url', $allowed_protocols);
|
||||
}
|
||||
if ($url && !empty($part = sanitize_key(strtolower($part)))) {
|
||||
// If an individual part is requested, get that specific value using parse_url()
|
||||
$part_constant_map = [
|
||||
'scheme' => PHP_URL_SCHEME, // e.g. `http`
|
||||
'host' => PHP_URL_HOST, // the domain (or subdomain) of the current website
|
||||
'path' => PHP_URL_PATH, // e.g. `/path/to/current/page/`
|
||||
'query' => PHP_URL_QUERY // after the question mark ?
|
||||
];
|
||||
$value = '';
|
||||
if (array_key_exists($part, $part_constant_map)) {
|
||||
$value = strval(wp_parse_url($url, $part_constant_map[$part]));
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters(
|
||||
'wpcf7dtx_escape',
|
||||
apply_filters('wpcf7dtx_sanitize', $value, 'text'),
|
||||
$obfuscate,
|
||||
'text'
|
||||
), // Sanitized & escaped value to output
|
||||
$value, // Raw value
|
||||
'URL', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
// No part requested, return the absolute URL
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $url, $obfuscate, 'url', $allowed_protocols), // Sanitized & escaped value to output
|
||||
$url, // Raw value
|
||||
'URL', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Referrering URL
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-referrer-url/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_referrer($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'allowed_protocols' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$url = wpcf7dtx_array_has_key('HTTP_REFERER', $_SERVER);
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', apply_filters(
|
||||
'wpcf7dtx_sanitize',
|
||||
$url,
|
||||
'url',
|
||||
$atts['allowed_protocols']
|
||||
), $atts['obfuscate'], 'url'), // Sanitized & escaped value to output
|
||||
$url, // Raw value
|
||||
'referrer', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Variable from Bloginfo
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-post-page-variables/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_bloginfo($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'show' => 'name', //Backwards compatibility
|
||||
'key' => 'name',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
extract($atts);
|
||||
$key = $show != $key && $show != 'name' ? $show : $key; // Use old value of "show" if not set to default value
|
||||
$raw = get_bloginfo($key);
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $obfuscate), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'bloginfo', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Variable from a Post Object
|
||||
*
|
||||
* @link https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-post-page-variables/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_post_var($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => 'post_title',
|
||||
'post_id' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$key = strtolower(apply_filters('wpcf7dtx_sanitize', $atts['key']));
|
||||
switch ($key) {
|
||||
case 'acf_id': // If requesting the handle for ACF, return the post ID
|
||||
case 'id':
|
||||
$key = 'ID';
|
||||
break;
|
||||
case 'slug': // Alias
|
||||
$key = 'post_name';
|
||||
break;
|
||||
case 'title': // Alias
|
||||
$key = 'post_title';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$atts['post_id'] = wpcf7dtx_get_post_id($atts['post_id']);
|
||||
$raw = $atts['post_id'] ? get_post_field($key, $atts['post_id']) : '';
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_post_var', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Value from Post Meta Field
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-post-meta-custom-fields/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_custom_field($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => '',
|
||||
'post_id' => '',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
|
||||
// If this key can't be accessed
|
||||
if (!wpcf7dtx_post_meta_key_access_is_allowed($atts['key'])) {
|
||||
// Trigger a warning if a denied key is in use
|
||||
wpcf7dtx_access_denied_alert($atts['key'], 'post_meta');
|
||||
return '';
|
||||
}
|
||||
|
||||
$key = apply_filters('wpcf7dtx_sanitize', $atts['key'], 'text');
|
||||
$atts['post_id'] = wpcf7dtx_get_post_id($atts['post_id']);
|
||||
$raw = $atts['post_id'] && $key ? get_post_meta($atts['post_id'], $key, true) : '';
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_custom_field', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Variable from the Current Object
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @link https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-variables/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_current_var($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => 'title',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
extract($atts);
|
||||
$key = apply_filters('wpcf7dtx_sanitize', $key);
|
||||
$temp_key = str_replace('-', '_', sanitize_key($key));
|
||||
$raw = '';
|
||||
$value = '';
|
||||
if ($temp_key === 'url') {
|
||||
return wpcf7dtx_url($atts); // Getting the current URL is the same for all WordPress pages
|
||||
} elseif (!empty($key)) {
|
||||
$type = '';
|
||||
$obj = null;
|
||||
if (!wp_doing_ajax()) {
|
||||
$obj = get_queried_object(); // Get the current WordPress queried object
|
||||
if (!is_null($obj)) {
|
||||
if ($obj instanceof WP_User) {
|
||||
$type = 'user';
|
||||
} elseif (property_exists($obj, 'ID')) {
|
||||
$type = 'post';
|
||||
} elseif (property_exists($obj, 'term_id')) {
|
||||
$type = 'term';
|
||||
}
|
||||
} elseif (is_archive()) {
|
||||
$type = 'archive';
|
||||
}
|
||||
}
|
||||
switch ($type) {
|
||||
case 'user': // This is an author page
|
||||
switch ($temp_key) {
|
||||
case 'acf_id': // Get handle for Advanced Custom Fields
|
||||
$raw = 'user_' . $obj->ID;
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
case 'image':
|
||||
case 'featured_image': // Get the profile picture of the user being displayed on the page
|
||||
$raw = get_avatar_url($obj->ID);
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate, 'url');
|
||||
break;
|
||||
case 'title': // Get author's display name
|
||||
$raw = $obj->display_name;
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
case 'slug': // Not all author pages use the `user_login` variable for security reasons, so get what is currently displayed as slug
|
||||
$raw = basename(wpcf7dtx_url(array('part' => 'path')));
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
default: // Get user value by key should it exist
|
||||
$raw = $obj->get($key);
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
}
|
||||
case 'post': // This is a post object
|
||||
switch ($temp_key) {
|
||||
case 'image':
|
||||
case 'featured_image': // Get the current post's featured image
|
||||
return wpcf7dtx_get_attachment(array_merge($atts, array('post_id' => $obj->ID)));
|
||||
case 'terms': // Get the current post's assigned terms
|
||||
return wpcf7dtx_get_taxonomy(array_merge($atts, array('post_id' => $obj->ID)));
|
||||
default:
|
||||
// Use the post object shortcode should it exist as a post variable
|
||||
$value = wpcf7dtx_get_post_var(array_merge($atts, array('post_id' => $obj->ID)));
|
||||
if (empty($value)) {
|
||||
// Try post meta if post object variable failed
|
||||
$value = wpcf7dtx_get_custom_field(array_merge($atts, array('post_id' => $obj->ID)));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
case 'term': // This is a taxonomy with a term ID
|
||||
switch ($key) {
|
||||
case 'id': // Get term ID
|
||||
$raw = $obj->term_id;
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
case 'acf_id': // Get handle for Advanced Custom Fields
|
||||
$raw = $obj->taxonomy . '_' . $obj->term_id;
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
case 'title': // Get term name
|
||||
$raw = $obj->name;
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
default:
|
||||
if (property_exists($obj, $key)) {
|
||||
// Get any property if it exists
|
||||
$raw = $obj->{$key};
|
||||
} else {
|
||||
// Otherwise, try meta data if the property doesn't exist
|
||||
$raw = get_metadata('term', $obj->ID, $key, true);
|
||||
}
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
}
|
||||
case 'archive': // Possibly a date or formats archive
|
||||
switch ($temp_key) {
|
||||
case 'title': // Get archive title
|
||||
$raw = get_the_archive_title();
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default: // Possibly a search or 404 page at this point
|
||||
if ($temp_key == 'slug') {
|
||||
// no idea what else to get except the slug maybe
|
||||
$raw = basename(wpcf7dtx_url(array('part' => 'path')));
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $obfuscate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
$value, // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_current_var', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Value from Current User
|
||||
*
|
||||
* Retreives data from the `users` and `usermeta` tables.
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-user-user-meta/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_current_user($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => 'user_login',
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$raw = '';
|
||||
if (is_user_logged_in()) {
|
||||
|
||||
// If this key can't be accessed
|
||||
if (!wpcf7dtx_user_data_access_is_allowed($atts['key'])) {
|
||||
// Trigger a warning if a denied key is in use
|
||||
wpcf7dtx_access_denied_alert($atts['key'], 'user_data');
|
||||
return '';
|
||||
}
|
||||
|
||||
$raw = wp_get_current_user()->get($atts['key']);
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_current_user', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Attachment
|
||||
*
|
||||
* Retreives an attachment ID or absolute URL depending on attributes
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-media-attachment/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_attachment($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'id' => '', // Get attachment by ID
|
||||
'size' => 'full', // Define attachment size
|
||||
'post_id' => '', // If attachment ID is empty but post ID is not, get the featured image
|
||||
'return' => 'url', // Options are `id` or `url`
|
||||
'obfuscate' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
|
||||
// No attachment ID was provided, check for post ID to get it's featured image
|
||||
if (empty($atts['id'])) {
|
||||
if ($atts['post_id'] = wpcf7dtx_get_post_id($atts['post_id'])) {
|
||||
//If a post ID was provided, get it's featured image
|
||||
$atts['id'] = get_post_thumbnail_id($atts['post_id']);
|
||||
}
|
||||
}
|
||||
|
||||
//Get the value
|
||||
$value = '';
|
||||
$raw = '';
|
||||
if ($atts['id']) {
|
||||
$atts['id'] = intval(sanitize_text_field(strval($atts['id'])));
|
||||
switch ($atts['return']) {
|
||||
case 'id': //Return the attachment ID
|
||||
$raw = $atts['id'];
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']);
|
||||
break;
|
||||
default: //Return attachment URL
|
||||
$raw = wp_get_attachment_image_url(intval($atts['id']), sanitize_text_field(strval($atts['size'])));
|
||||
$value = apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate'], 'url');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
$value, // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_attachment', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Cookie Value
|
||||
*
|
||||
* Retreives the value of a cookie
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-cookie/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_cookie($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => '',
|
||||
'default' => '',
|
||||
'obfuscate' => '' // Optionally obfuscate returned value
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$raw = wpcf7dtx_array_has_key(apply_filters('wpcf7dtx_sanitize', $atts['key']), $_COOKIE, $atts['default']);
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_cookie', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Taxonomy
|
||||
*
|
||||
* Retreives a list of taxonomy values
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-taxonomy/
|
||||
* @see https://developer.wordpress.org/reference/classes/wp_term_query/get_terms/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_taxonomy($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'post_id' => '',
|
||||
'taxonomy' => 'category', // Default taxonomy is `category`
|
||||
'fields' => 'names', // Return an array of term names
|
||||
'obfuscate' => '' // Optionally obfuscate returned value
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$atts['post_id'] = wpcf7dtx_get_post_id($atts['post_id']);
|
||||
$fields = apply_filters('wpcf7dtx_sanitize', $atts['fields'], 'key');
|
||||
$raw = '';
|
||||
$value = '';
|
||||
if ($atts['post_id'] && in_array($fields, array('names', 'slugs', 'ids'))) {
|
||||
$terms = wp_get_object_terms(
|
||||
$atts['post_id'], // Get only the ones assigned to this post
|
||||
apply_filters('wpcf7dtx_sanitize', $atts['taxonomy'], 'slug'),
|
||||
array('fields' => $fields)
|
||||
);
|
||||
if (is_array($terms) && count($raw = array_values($terms)) && (is_string($raw[0]) || is_numeric($raw[0]))) {
|
||||
//return apply_filters('wpcf7dtx_escape', implode(', ', $values), $obfuscate, 'text');
|
||||
$value = implode(', ', $raw);
|
||||
}
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $value, $atts['obfuscate'], 'text'), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_taxonomy', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Theme Customization Option
|
||||
*
|
||||
* Retreives theme modification value for the active theme
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-theme-option/
|
||||
* @see https://developer.wordpress.org/reference/functions/get_theme_mod/
|
||||
*
|
||||
* @param array $atts Optional. An associative array of shortcode attributes. Default is an empty array.
|
||||
*
|
||||
* @return string Output of the shortcode
|
||||
*/
|
||||
function wpcf7dtx_get_theme_option($atts = array())
|
||||
{
|
||||
$atts = shortcode_atts(array(
|
||||
'key' => '',
|
||||
'default' => '', // Optional default value
|
||||
'obfuscate' => '' // Optionally obfuscate returned value
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$default = apply_filters('wpcf7dtx_sanitize', $atts['default']);
|
||||
$raw = $default;
|
||||
if ($key = apply_filters('wpcf7dtx_sanitize', $atts['key'], 'text')) {
|
||||
$raw = get_theme_mod($key, $default);
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
apply_filters('wpcf7dtx_escape', $raw, $atts['obfuscate']), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'get_theme_option', // Shortcode tag
|
||||
$atts // Shortcode attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* GUID Field
|
||||
*
|
||||
* Generate a random GUID (globally unique identifier)
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-guid/
|
||||
*
|
||||
* @return string a randomly generated 128-bit text string.
|
||||
*/
|
||||
function wpcf7dtx_guid()
|
||||
{
|
||||
if (function_exists('com_create_guid')) {
|
||||
$raw = trim(com_create_guid(), '{}');
|
||||
} else {
|
||||
$raw = sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
|
||||
}
|
||||
return apply_filters(
|
||||
'wpcf7dtx_shortcode', // DTX built-in shortcode hook
|
||||
esc_attr($raw), // Sanitized & escaped value to output
|
||||
$raw, // Raw value
|
||||
'guid', // Shortcode tag
|
||||
array() // Shortcode attributes
|
||||
);
|
||||
}
|
||||
@@ -1,924 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Custom DTX Allowed Protocols Filter
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param array|string $protocols Optional. Specify protocols to allow either as an array of string values or a string value of comma separated protocols.
|
||||
* @param bool $replace Optional. If true, this function will only return the specified values. If false, will merge specified values with default values. Default is false.
|
||||
*
|
||||
* @return array An array of string values, default only includes `http` and `https` protocols.
|
||||
*/
|
||||
function wpcf7dtx_allow_protocols($protocols = false, $replace = false)
|
||||
{
|
||||
// Get user-inputted protocols
|
||||
$user_protocols = false;
|
||||
if (is_string($protocols) && !empty($protocols)) {
|
||||
$user_protocols = explode(',', sanitize_text_field($protocols));
|
||||
} elseif (is_array($protocols) && count($protocols)) {
|
||||
$user_protocols = array_filter(array_values($protocols));
|
||||
}
|
||||
$default = array('http', 'https');
|
||||
if (is_array($user_protocols) && count($user_protocols)) {
|
||||
// Sanitize each value before adding
|
||||
$allowed_protocols = array();
|
||||
foreach ($user_protocols as $protocol) {
|
||||
$allowed_protocols[] = sanitize_text_field($protocol);
|
||||
}
|
||||
if ($replace) {
|
||||
return array_unique($allowed_protocols);
|
||||
}
|
||||
return array_unique(array_merge(array('http', 'https'), $allowed_protocols)); // Return merged values
|
||||
} elseif ($replace) {
|
||||
return array(); // None allowed, apparently
|
||||
}
|
||||
return $default; // Return only default values
|
||||
}
|
||||
add_filter('wpcf7dtx_allow_protocols', 'wpcf7dtx_allow_protocols', 10, 2);
|
||||
|
||||
/**
|
||||
* Custom DTX Sanitize Filter
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string $value value to be sanitized
|
||||
* @param string $type Optional. The type of sanitation to return. Default is `auto` where automatic identification will be used to attempt to identify URLs and email addresses vs text.
|
||||
* @param array|string $protocols Optional. Specify protocols to allow either as an array of string values or a string value of comma separated protocols.
|
||||
*
|
||||
* @return string the sanitized value
|
||||
*/
|
||||
function wpcf7dtx_sanitize($value = '', $type = 'auto', $protocols = false)
|
||||
{
|
||||
if ($type == 'none') {
|
||||
return $value;
|
||||
}
|
||||
$value = is_string($value) ? $value : strval($value); // Force string value
|
||||
if (!empty($value)) {
|
||||
$type = $type == 'auto' ? wpcf7dtx_detect_value_type($value) : sanitize_text_field($type);
|
||||
switch ($type) {
|
||||
case 'email':
|
||||
return sanitize_email($value);
|
||||
case 'url':
|
||||
return sanitize_url($value, apply_filters('wpcf7dtx_allow_protocols', $protocols));
|
||||
case 'key':
|
||||
return sanitize_key($value);
|
||||
case 'slug':
|
||||
return sanitize_title($value);
|
||||
case 'textarea':
|
||||
return sanitize_textarea_field($value);
|
||||
}
|
||||
}
|
||||
return sanitize_text_field($value);
|
||||
}
|
||||
add_filter('wpcf7dtx_sanitize', 'wpcf7dtx_sanitize', 10, 3);
|
||||
|
||||
/**
|
||||
* Custom DTX Escape Filter
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string $value value to be escaped
|
||||
* @param bool $obfuscate Optional. If true, returned value will be obfuscated. Default is false.
|
||||
* @param string $type Optional. The type of escape to return. Default is `auto` where automatic identification will be used to attempt to identify the type of text.
|
||||
* @param array|string $protocols Optional. Specify protocols to allow either as an array of string values or a string value of comma separated protocols.
|
||||
*
|
||||
* @return string the escaped value
|
||||
*/
|
||||
function wpcf7dtx_escape($value = '', $obfuscate = false, $type = 'auto', $protocols = false)
|
||||
{
|
||||
if ($type == 'none') {
|
||||
return $value;
|
||||
}
|
||||
$value = apply_filters('wpcf7dtx_sanitize', $value, $type); // Sanitize value
|
||||
if (!empty($value)) {
|
||||
if ($obfuscate) {
|
||||
return apply_filters('wpcf7dtx_obfuscate', $value); // Return obfuscated value
|
||||
}
|
||||
$type = $type == 'auto' ? wpcf7dtx_detect_value_type($value) : sanitize_text_field($type);
|
||||
switch ($type) {
|
||||
case 'url':
|
||||
return esc_url($value, apply_filters('wpcf7dtx_allow_protocols', $protocols));
|
||||
case 'textarea':
|
||||
return esc_textarea($value);
|
||||
}
|
||||
}
|
||||
return esc_attr($value); // Return attribute value
|
||||
}
|
||||
add_filter('wpcf7dtx_escape', 'wpcf7dtx_escape', 10, 4);
|
||||
|
||||
/**
|
||||
* Detect Value Type
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param string $value the value to be identified
|
||||
*
|
||||
* @return string Potentially identifies string values as `url`, `email`, or `text`.
|
||||
*/
|
||||
function wpcf7dtx_detect_value_type($value)
|
||||
{
|
||||
// Try to detect the value type
|
||||
$value = trim($value);
|
||||
$is_https_url = stripos($value, 'https') === 0 && strlen($value) > 5;
|
||||
$is_http_url = stripos($value, 'http') === 0 && strlen($value) > 4 && sanitize_key($value) != 'https';
|
||||
if ($is_https_url || $is_http_url) {
|
||||
return 'url';
|
||||
} elseif (preg_match('/^[^\s@]+@[^\s@]+\.[^\s@]+$/', $value)) {
|
||||
return 'email';
|
||||
}
|
||||
return 'text';
|
||||
}
|
||||
|
||||
/**
|
||||
* Obfuscate a value
|
||||
*
|
||||
* @see https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-attribute-obfuscate/
|
||||
*
|
||||
* @param mixed $value the value to be obfuscated
|
||||
*
|
||||
* @return string obfuscated value
|
||||
*/
|
||||
function wpcf7dtx_obfuscate($value = '')
|
||||
{
|
||||
$o = '';
|
||||
if (!is_string($value)) {
|
||||
$value = sanitize_text_field(strval($value)); // Force value to be string and sanitize it
|
||||
}
|
||||
if (!empty($value)) {
|
||||
$value = htmlentities($value, ENT_QUOTES);
|
||||
foreach (str_split($value) as $letter) {
|
||||
$o .= '&#' . ord($letter) . ';';
|
||||
}
|
||||
return $o; // Return obfuscated value
|
||||
}
|
||||
return esc_attr($value); // Return default attribute escape
|
||||
}
|
||||
add_filter('wpcf7dtx_obfuscate', 'wpcf7dtx_obfuscate', 10, 1);
|
||||
|
||||
/**
|
||||
* Get Post ID
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param mixed $post_id
|
||||
*
|
||||
* @return int An integer value of the passed post ID or the post ID of the current `$post` global object. 0 on Failure.
|
||||
*/
|
||||
function wpcf7dtx_get_post_id($post_id, $context = 'dtx')
|
||||
{
|
||||
$post_id = $post_id ? intval(sanitize_text_field(strval($post_id))) : '';
|
||||
if (!$post_id || !is_numeric($post_id)) {
|
||||
if ($context == 'dtx') {
|
||||
if (wp_doing_ajax()) {
|
||||
// If we're doing an AJAX call, just fail quietly
|
||||
return 0;
|
||||
} else {
|
||||
global $post;
|
||||
if (isset($post)) {
|
||||
$post_id = $post->ID; // If the global $post object is set, get its ID
|
||||
} else {
|
||||
$post_id = get_the_ID(); // Otherwise get it from "the loop"
|
||||
}
|
||||
}
|
||||
} elseif ($context == 'acf') {
|
||||
// When a post ID is not specified for ACF keys, it accepts the boolean `false`
|
||||
$post_id = false;
|
||||
}
|
||||
}
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Dynamic Value
|
||||
*
|
||||
* @since 3.2.2
|
||||
*
|
||||
* @param string $value The form tag value.
|
||||
* @param WPCF7_FormTag|false $tag Optional. Use to look up default value.
|
||||
* @param string $sanitize Optional. Specify type of sanitization. Default is `auto`.
|
||||
* @param string $option_name Optional. Specify an option from the $tag to retrieve and decode. Default is `value`.
|
||||
* @param string $option_pattern Optional. A regular expression pattern or one of the keys of preset patterns. If specified, only options whose value part matches this pattern will be returned.
|
||||
*
|
||||
* @return string The dynamic output or the original value, not escaped or sanitized.
|
||||
*/
|
||||
function wpcf7dtx_get_dynamic($value, $tag = false, $sanitize = 'auto', $option_name = 'value', $option_pattern = '')
|
||||
{
|
||||
if (is_object($tag)) {
|
||||
if ($option_name != 'value') {
|
||||
$value = html_entity_decode(urldecode(strval($tag->get_option($option_name, $option_pattern, true))), ENT_QUOTES);
|
||||
} else {
|
||||
$default = $tag->get_option('defaultvalue', '', true);
|
||||
if (!$default) {
|
||||
$default = $tag->get_default_option(strval(reset($tag->values)));
|
||||
}
|
||||
$value = wpcf7_get_hangover($tag->name, $default);
|
||||
}
|
||||
}
|
||||
$value = apply_filters('wpcf7dtx_sanitize', $value, $sanitize);
|
||||
if (is_string($value) && !empty($value)) {
|
||||
// If a shortcode was passed as the value, attempt to evaluate itevaluate it and use the result
|
||||
$shortcode_tag = '[' . $value . ']';
|
||||
//var_dump('Shortcode tag?', $shortcode_tag);
|
||||
$shortcode_output = do_shortcode($shortcode_tag); //Shortcode value
|
||||
//var_dump('Shortcode value?', $shortcode_output);
|
||||
if ($shortcode_output != $shortcode_tag) {
|
||||
return apply_filters('wpcf7dtx_sanitize', $shortcode_output, $sanitize);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Allowed HTML for Form Field Properties
|
||||
*
|
||||
* @see https://www.w3schools.com/tags/tag_input.asp
|
||||
* @see https://www.w3schools.com/tags/tag_optgroup.asp
|
||||
* @see https://www.w3schools.com/tags/tag_option.asp
|
||||
* @see https://www.w3schools.com/tags/tag_select.asp
|
||||
* @see https://www.w3schools.com/tags/tag_textarea.asp
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param string $type Optional. The type of input for unique properties. Default is `text`.
|
||||
* @param array $extra Optional. A sequential array of properties to additionally include.
|
||||
*
|
||||
* @return array An associative array of allowed properties appropriate for use in `wp_kses()`
|
||||
*/
|
||||
function wpcf7dtx_get_allowed_field_properties($type = 'text', $extra = array())
|
||||
{
|
||||
if (in_array($type, array('option', 'optgroup'))) {
|
||||
return array(
|
||||
'optgroup' => array(
|
||||
'label' => array(),
|
||||
'disabled' => array(),
|
||||
'hidden' => array()
|
||||
),
|
||||
'option' => array(
|
||||
'value' => array(),
|
||||
'selected' => array(),
|
||||
'disabled' => array(),
|
||||
'hidden' => array()
|
||||
)
|
||||
);
|
||||
}
|
||||
$allowed_properties = array(
|
||||
// Global properties
|
||||
'type' => array(),
|
||||
'id' => array(),
|
||||
'name' => array(),
|
||||
'value' => array(),
|
||||
'class' => array(),
|
||||
'disabled' => array(),
|
||||
'tabindex' => array(),
|
||||
'title' => array(),
|
||||
// ARIA properties
|
||||
'aria-invalid' => array(),
|
||||
'aria-describedby' => array(),
|
||||
// DTX properties
|
||||
'data-dtx-value' => array(),
|
||||
);
|
||||
if ($type != 'hidden') {
|
||||
$allowed_properties['autofocus'] = array();
|
||||
$allowed_properties['readonly'] = array();
|
||||
$allowed_properties['required'] = array();
|
||||
}
|
||||
if (in_array($type, array('checkbox', 'radio', 'acceptance'))) {
|
||||
// Properties exclusive to checkboxes and radio buttons
|
||||
$allowed_properties['checked'] = array();
|
||||
$allowed_properties['dtx-default'] = array();
|
||||
} elseif ($type == 'select') {
|
||||
// Properties exclusive to select fields
|
||||
$allowed_properties['size'] = array();
|
||||
$allowed_properties['multiple'] = array();
|
||||
$allowed_properties['dtx-default'] = array();
|
||||
unset($allowed_properties['type'], $allowed_properties['value']); // Remove invalid select attributes
|
||||
} elseif ($type == 'label') {
|
||||
// Properties exclusive to label elements
|
||||
$allowed_properties['for'] = array();
|
||||
// Remove invalid label attributes
|
||||
unset(
|
||||
$allowed_properties['type'],
|
||||
$allowed_properties['name'],
|
||||
$allowed_properties['value'],
|
||||
$allowed_properties['disabled'],
|
||||
$allowed_properties['aria-invalid']
|
||||
);
|
||||
} else {
|
||||
// Properties exclusive to text-based inputs
|
||||
$allowed_properties['autocapitalize'] = array();
|
||||
$allowed_properties['autocomplete'] = array();
|
||||
$allowed_properties['list'] = array();
|
||||
|
||||
// Placeholder
|
||||
if (in_array($type, array('text', 'search', 'url', 'tel', 'email', 'password', 'number'))) {
|
||||
$allowed_properties['placeholder'] = array();
|
||||
}
|
||||
|
||||
// Textarea
|
||||
if ($type == 'textarea') {
|
||||
// Additional properties exclusive to textarea fields
|
||||
$allowed_properties['cols'] = array();
|
||||
$allowed_properties['rows'] = array();
|
||||
$allowed_properties['minlength'] = array();
|
||||
$allowed_properties['maxlength'] = array();
|
||||
$allowed_properties['wrap'] = array();
|
||||
unset($allowed_properties['type'], $allowed_properties['value']); // Remove invalid textarea attributes
|
||||
} elseif (in_array($type, array('text', 'search', 'url', 'tel', 'email', 'password'))) {
|
||||
// Additional properties exclusive to these text-based fields
|
||||
$allowed_properties['size'] = array();
|
||||
$allowed_properties['minlength'] = array();
|
||||
$allowed_properties['maxlength'] = array();
|
||||
$allowed_properties['pattern'] = array();
|
||||
} elseif (in_array($type, array('number', 'range', 'date', 'datetime-local', 'time'))) {
|
||||
// Number and date inputs
|
||||
$allowed_properties['min'] = array();
|
||||
$allowed_properties['max'] = array();
|
||||
$allowed_properties['step'] = array();
|
||||
}
|
||||
}
|
||||
if (is_array($extra) && count($extra)) {
|
||||
foreach ($extra as $property) {
|
||||
$allowed_properties[sanitize_title($property)] = array();
|
||||
}
|
||||
}
|
||||
return $allowed_properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted string of HTML attributes
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $atts Associative array of attribute name and value pairs
|
||||
*
|
||||
* @return string Formatted HTML attributes with keys and values both escaped
|
||||
*/
|
||||
function wpcf7dtx_format_atts($atts)
|
||||
{
|
||||
if (is_array($atts) && count($atts)) {
|
||||
$sanitized_atts = array();
|
||||
static $boolean_attributes = array(
|
||||
'checked', 'disabled', 'multiple', 'readonly', 'required', 'selected'
|
||||
);
|
||||
foreach ($atts as $key => $value) {
|
||||
$key = sanitize_key(strval($key));
|
||||
if ($key) {
|
||||
if (in_array($key, $boolean_attributes) || is_bool($value)) {
|
||||
if ($value) {
|
||||
$sanitized_atts[$key] = $key;
|
||||
}
|
||||
} elseif (is_numeric($value) || (is_string($value) || !empty($value))) {
|
||||
$sanitized_atts[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($sanitized_atts)) {
|
||||
$output = array();
|
||||
foreach ($sanitized_atts as $key => $value) {
|
||||
$output[] = sprintf('%s="%s"', esc_attr($key), esc_attr($value));
|
||||
}
|
||||
return implode(' ', $output);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Input Field HTML
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $atts An associative array of input attributes.
|
||||
*
|
||||
* @return string HTML output of input field
|
||||
*/
|
||||
function wpcf7dtx_input_html($atts)
|
||||
{
|
||||
return sprintf('<input %s />', wpcf7dtx_format_atts($atts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Checkbox Field HTML
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $atts An associative array of select input attributes.
|
||||
* @param string $label_text Optional. The text to display next to the checkbox or radio button.
|
||||
* @param bool $label_ui Optional. If true, will place input and label text inside a `<label>` element. Default is true.
|
||||
* @param bool $reverse Optional. If true, will reverse the order to display the text label first then the button. Has no effect if label text is empty. Default is false.
|
||||
*
|
||||
* @return string HTML output of the checkbox or radio button or empty string on failure.
|
||||
*/
|
||||
function wpcf7dtx_checkbox_html($atts, $label_text = '', $label_ui = true, $reverse = false)
|
||||
{
|
||||
// Default field attributes
|
||||
$atts = array_merge(array('value' => '', 'dtx-default' => ''), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
|
||||
// Checkboxes can have multiple values checked, check mine if it's listed as a default value
|
||||
if ($atts['type'] == 'checkbox' && is_string($atts['dtx-default']) && strpos($atts['dtx-default'], '_') !== false) {
|
||||
$default = array_unique(explode('_', $atts['dtx-default']));
|
||||
if (in_array($atts['value'], $default)) {
|
||||
$atts['checked'] = 'checked';
|
||||
}
|
||||
} elseif ((is_numeric($atts['dtx-default']) || $atts['dtx-default']) && $atts['value'] == $atts['dtx-default']) {
|
||||
$atts['checked'] = 'checked';
|
||||
}
|
||||
$input = wpcf7dtx_input_html($atts);
|
||||
if (!empty(trim($label_text))) {
|
||||
$label_el = $label_ui ? 'span' : 'label'; // If not wrapping with a label element, display it next to it
|
||||
$label_text = sprintf(
|
||||
'<%1$s%2$s class="wpcf7-list-item-label">%3$s</%1$s>',
|
||||
$label_el,
|
||||
// If not wrapping with a label element and the element has an ID attribute, add a `for` attribute
|
||||
$label_ui ? '' : (wpcf7dtx_array_has_key('id', $atts) ? ' for="' . esc_attr($atts['id']) . '"' : ''),
|
||||
esc_html($label_text)
|
||||
);
|
||||
if ($reverse) {
|
||||
$html = $label_text . $input;
|
||||
} else {
|
||||
$html = $input . $label_text;
|
||||
}
|
||||
} else {
|
||||
$html = $input;
|
||||
}
|
||||
if ($label_ui) {
|
||||
$html = '<label>' . $html . '</label>';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Checkbox Group HTML
|
||||
*
|
||||
* @since 4.0.3
|
||||
*
|
||||
* @param array $atts An associative array of select input attributes.
|
||||
* @param array|string $options Accepts an associative array of key/value pairs to use as the
|
||||
* select option's value/label pairs. It also accepts an associative array of associative
|
||||
* arrays with the keys being used as option group labels and the array values used as that
|
||||
* group's options. It also accepts a string value of HTML already formatted as options or
|
||||
* option groups. It also accepts a string value of a self-closing shortcode that is
|
||||
* evaluated and its output is either options or option groups.
|
||||
* @param bool $label_ui Optional. If true, will place input and label text inside a `<label>` element. Default is true.
|
||||
* @param bool $reverse Optional. If true, will reverse the order to display the text label first then the button. Has no effect if label text is empty. Default is false.
|
||||
*
|
||||
* @return string HTML output of the checkbox or radio button or empty string on failure.
|
||||
*/
|
||||
function wpcf7dtx_checkbox_group_html($atts, $options, $label_ui = false, $reverse = false, $exclusive = false)
|
||||
{
|
||||
$group_html = '';
|
||||
if ($count = count($options)) {
|
||||
// Attributes specific to HTML creation
|
||||
$atts = array_merge(array(
|
||||
'type' => 'checkbox',
|
||||
'id' => '',
|
||||
'name' => '',
|
||||
'value' => '',
|
||||
'dtx-default' => ''
|
||||
), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
|
||||
// Loop all the options
|
||||
$group_html = array();
|
||||
$id_prefix = ($atts['id'] ? $atts['id'] : uniqid($atts['name'] . '_')) . '_'; // Create prefix from passed ID or Name
|
||||
$i = 1;
|
||||
foreach ($options as $value => $label) {
|
||||
$my_atts = array_merge($atts, array(
|
||||
'id' => sanitize_html_class($id_prefix . $i) // Always have unique IDs for group items
|
||||
));
|
||||
$dynamic_value = '';
|
||||
$dynamic_label = $label;
|
||||
if (is_string($value) && !empty($value) && $value === $label) {
|
||||
// These are identical, just handle it as one, could also be a raw shortcode
|
||||
$dynamic_option = trim(wpcf7dtx_get_dynamic($value, false, 'none')); // Do not sanitize yet, it may have HTML
|
||||
if (is_string($dynamic_option) && !empty($dynamic_option) && strpos($dynamic_option, '{') === 0 && strpos($dynamic_option, '}') === strlen($dynamic_option) - 1) {
|
||||
// If it outputs JSON, try parsing it
|
||||
try {
|
||||
$dynamic_option = json_decode($dynamic_option, true);
|
||||
if (is_array($dynamic_option) && count($dynamic_option)) {
|
||||
$group_html[] = wpcf7dtx_checkbox_group_html(
|
||||
$my_atts,
|
||||
$dynamic_option,
|
||||
$label_ui,
|
||||
$reverse,
|
||||
$exclusive
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Fail quietly
|
||||
if (WP_DEBUG && WP_DEBUG_LOG) {
|
||||
error_log('[Contact Form 7 - Dynamic Text Extension] Error parsing JSON value');
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
continue; // Continue with next iteration
|
||||
} elseif (is_string($dynamic_option) && !empty($dynamic_option) && esc_html($dynamic_option) != $dynamic_option) {
|
||||
$group_html[] = force_balance_tags($dynamic_option); // If it outputs HTML, escape and use them as-is
|
||||
$i++;
|
||||
continue; // Continue with next iteration
|
||||
} else {
|
||||
$dynamic_value = $dynamic_option;
|
||||
$dynamic_label = $dynamic_option;
|
||||
}
|
||||
} else {
|
||||
// These are different, could be raw shortcodes
|
||||
$dynamic_value = wpcf7dtx_get_dynamic($value, false);
|
||||
$dynamic_label = wpcf7dtx_get_dynamic($label, false);
|
||||
}
|
||||
// This could be a single??
|
||||
$class = array('wpcf7-list-item');
|
||||
$class[] = sanitize_html_class('wpcf7-list-item-' . $i);
|
||||
if ($i === 1) {
|
||||
$class[] = 'first';
|
||||
}
|
||||
if ($i === $count) {
|
||||
$class[] = 'last';
|
||||
}
|
||||
if ($exclusive) {
|
||||
$class[] = 'wpcf7-exclusive-checkbox';
|
||||
}
|
||||
$valid_default = is_numeric($atts['dtx-default']) || (is_string($atts['dtx-default']) && !empty($atts['dtx-default']));
|
||||
if ($valid_default && $dynamic_value == $atts['dtx-default']) {
|
||||
$my_atts['checked'] = 'checked';
|
||||
}
|
||||
$group_html[] = sprintf(
|
||||
'<span class="%s">%s</span>',
|
||||
esc_attr(implode(' ', $class)),
|
||||
wpcf7dtx_checkbox_html(
|
||||
// Overwrite name attribute
|
||||
array_merge($my_atts, array(
|
||||
'name' => $atts['type'] == 'radio' || $exclusive || $count === 1 ? $atts['name'] : $atts['name'] . '[]', // if there are multiple checkboxes and they aren't exclusive, names are an array
|
||||
'value' => $dynamic_value
|
||||
)),
|
||||
$dynamic_label,
|
||||
$label_ui,
|
||||
$reverse
|
||||
)
|
||||
);
|
||||
$i++;
|
||||
}
|
||||
$group_html = implode('', $group_html);
|
||||
}
|
||||
return $group_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Textarea Field HTML
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $atts An associative array of textarea field attributes.
|
||||
*
|
||||
* @return string HTML output of textarea field
|
||||
*/
|
||||
function wpcf7dtx_textarea_html($atts)
|
||||
{
|
||||
// Attributes specific to HTML creation
|
||||
$atts = array_merge(array('value' => ''), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
return sprintf(
|
||||
'<textarea %s>%s</textarea>',
|
||||
wpcf7dtx_format_atts($atts),
|
||||
apply_filters('wpcf7dtx_escape', $atts['value'], false, 'textarea')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Options HTML
|
||||
*
|
||||
* @since 4.4.0
|
||||
*
|
||||
* @param array $options Accepts an associative array of key/value pairs to use as the
|
||||
* select option's value/label pairs.
|
||||
* @param bool $selected_value Optional. The value that should be selected by default.
|
||||
*
|
||||
* @return string HTML output of options
|
||||
*/
|
||||
function wpcf7dtx_options_html($options, $selected_value = '')
|
||||
{
|
||||
$html = '';
|
||||
foreach ($options as $value => $label) {
|
||||
$dynamic_value = wpcf7dtx_get_dynamic($value);
|
||||
$dynamic_label = wpcf7dtx_get_dynamic($label);
|
||||
$html .= sprintf(
|
||||
'<option value="%1$s"%3$s>%2$s</option>',
|
||||
esc_attr(apply_filters('wpcf7dtx_escape', $dynamic_value)),
|
||||
esc_html(apply_filters('wpcf7dtx_escape', $dynamic_label)),
|
||||
$selected_value == $dynamic_label ? ' selected' : ''
|
||||
);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Select Field HTML
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $atts An associative array of select input attributes.
|
||||
* @param array|string $options Accepts an associative array of key/value pairs to use as the
|
||||
* select option's value/label pairs. It also accepts an associative array of associative
|
||||
* arrays with the keys being used as option group labels and the array values used as that
|
||||
* group's options. It also accepts a string value of HTML already formatted as options or
|
||||
* option groups. It also accepts a string value of a self-closing shortcode that is
|
||||
* evaluated and its output is either options or option groups.
|
||||
* @param bool $hide_blank Optional. If true, the first blank placeholder option will have the
|
||||
* `hidden` attribute added to it. Default is false.
|
||||
* @param bool $disable_blank Optional. If true, the first blank placeholder option will have
|
||||
* the `disabled` attribute added to it. Default is false.
|
||||
*
|
||||
* @return string HTML output of select field
|
||||
*/
|
||||
function wpcf7dtx_select_html($atts, $options, $hide_blank = false, $disable_blank = false)
|
||||
{
|
||||
// Attributes specific to HTML creation
|
||||
$atts = array_merge(array('placeholder' => '', 'dtx-default' => ''), array_change_key_case((array)$atts, CASE_LOWER));
|
||||
$options_html = ''; // Open options HTML
|
||||
|
||||
// If using a placeholder, use it as the text of the first option
|
||||
if ($atts['placeholder']) {
|
||||
$options_html .= sprintf(
|
||||
'<option value=""%s%s%s>%s</option>',
|
||||
empty($atts['dtx-default']) ? ' selected' : '',
|
||||
$hide_blank ? ' hidden' : '',
|
||||
$disable_blank ? ' disabled' : '',
|
||||
apply_filters('wpcf7dtx_escape', $atts['placeholder'])
|
||||
);
|
||||
}
|
||||
if (is_array($options) && count($options)) {
|
||||
//Check if using option groups
|
||||
if (is_array(array_values($options)[0])) {
|
||||
foreach ($options as $group_name => $opt_group) {
|
||||
$options_html .= sprintf('<optgroup label="%s">', esc_attr(apply_filters('wpcf7dtx_escape', wpcf7dtx_get_dynamic($group_name)))); // Open option group
|
||||
foreach ($opt_group as $option_value => $option_label) {
|
||||
// Check if option values and groups are dynamic
|
||||
$dynamic_option_value = wpcf7dtx_get_dynamic($option_value);
|
||||
$options_html .= sprintf(
|
||||
'<option value="%1$s"%3$s>%2$s</option>',
|
||||
esc_attr(apply_filters('wpcf7dtx_escape', $dynamic_option_value)),
|
||||
esc_html(apply_filters('wpcf7dtx_escape', wpcf7dtx_get_dynamic($option_label))),
|
||||
$atts['dtx-default'] == $dynamic_option_value ? ' selected' : ''
|
||||
);
|
||||
}
|
||||
$options_html .= '</optgroup>'; // Close option group
|
||||
}
|
||||
} else {
|
||||
$allowed_html = wpcf7dtx_get_allowed_field_properties('option');
|
||||
foreach ($options as $option_value => $option_label) {
|
||||
if ($option_value === $option_label) {
|
||||
// These are identical, just handle it as one, could also be a raw shortcode
|
||||
$dynamic_option = trim(wpcf7dtx_get_dynamic($option_value, false, 'none')); // Do not sanitize yet, it may have HTML
|
||||
if (is_string($dynamic_option) && !empty($dynamic_option) && (strpos($dynamic_option, '<option') === 0 || stripos($dynamic_option, '<optgroup') === 0)) {
|
||||
$options_html .= wp_kses($dynamic_option, $allowed_html); // If it outputs HTML, escape and use them as-is
|
||||
} elseif ($dynamic_option) {
|
||||
// Just output the option
|
||||
$dynamic_option = apply_filters('wpcf7dtx_escape', $dynamic_option);
|
||||
$options_html .= sprintf(
|
||||
'<option value="%1$s"%3$s>%2$s</option>',
|
||||
esc_attr($dynamic_option),
|
||||
esc_html($dynamic_option),
|
||||
$atts['dtx-default'] == $dynamic_option ? ' selected' : ''
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$dynamic_option_value = wpcf7dtx_get_dynamic($option_value, false);
|
||||
$options_html .= sprintf(
|
||||
'<option value="%1$s"%3$s>%2$s</option>',
|
||||
esc_attr(apply_filters('wpcf7dtx_escape', $dynamic_option_value)),
|
||||
esc_html(apply_filters('wpcf7dtx_escape', wpcf7dtx_get_dynamic($option_label))),
|
||||
$atts['dtx-default'] == $dynamic_option_value ? ' selected' : ''
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (is_string($options) && !empty($options = trim($options))) {
|
||||
$allowed_html = wpcf7dtx_get_allowed_field_properties('option');
|
||||
// If options were passed as a string, go ahead and use them
|
||||
if (strpos($options, '<option') === 0 || stripos($options, '<optgroup') === 0) {
|
||||
$options_html .= wp_kses($options, $allowed_html);
|
||||
} else {
|
||||
// If a shortcode was passed as the options, evaluate it and use the result
|
||||
$shortcode_output = wpcf7dtx_get_dynamic($options);
|
||||
if (is_string($shortcode_output) && !empty($shortcode_output) && (strpos($shortcode_output, '<option') === 0) || strpos($shortcode_output, '<optgroup') === 0) {
|
||||
$options_html .= wp_kses($shortcode_output, $allowed_html);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sprintf('<select %s>%s</select>', wpcf7dtx_format_atts($atts), $options_html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Key Exists and Has Value
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string|int $key The key to search for in the array.
|
||||
* @param array $array The array to search.
|
||||
* @param mixed $default The default value to return if not found or is empty. Default is
|
||||
* an empty string.
|
||||
*
|
||||
* @return mixed The value of the key found in the array if it exists or the value of
|
||||
* `$default` if not found or is empty.
|
||||
*/
|
||||
function wpcf7dtx_array_has_key($key, $array = array(), $default = '')
|
||||
{
|
||||
//Check if this key exists in the array
|
||||
$valid_key = (is_string($key) && !empty($key)) || is_numeric($key);
|
||||
$valid_array = is_array($array) && count($array);
|
||||
if ($valid_key && $valid_array && array_key_exists($key, $array)) {
|
||||
//Always return if it's a boolean or number, otherwise only return it if it has any value
|
||||
if ($array[$key] || is_bool($array[$key]) || is_numeric($array[$key])) {
|
||||
return $array[$key];
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if admin has allowed access to a specific post meta key
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $meta_key The post meta key to test
|
||||
*
|
||||
* @return bool True if this key can be accessed, false otherwise
|
||||
*/
|
||||
function wpcf7dtx_post_meta_key_access_is_allowed($meta_key)
|
||||
{
|
||||
|
||||
// Get the DTX Settings
|
||||
$settings = wpcf7dtx_get_settings();
|
||||
|
||||
// Has access to all metadata been enabled?
|
||||
if (isset($settings['post_meta_allow_all']) && $settings['post_meta_allow_all'] === 'enabled') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If not, check the Allow List
|
||||
$allowed_keys = array();
|
||||
|
||||
// No key list from settings
|
||||
if (isset($settings['post_meta_allow_keys']) && is_string($settings['post_meta_allow_keys'])) {
|
||||
// Extract allowed keys from setting text area
|
||||
$allowed_keys = wpcf7dtx_parse_allowed_keys($settings['post_meta_allow_keys']);
|
||||
}
|
||||
|
||||
// Allow custom filters
|
||||
$allowed_keys = apply_filters('wpcf7dtx_post_meta_key_allow_list', $allowed_keys);
|
||||
|
||||
// Check if the key is in the allow list
|
||||
if (in_array($meta_key, $allowed_keys)) {
|
||||
return true; // The key is allowed
|
||||
}
|
||||
|
||||
// Everything is disallowed by default
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if admin has allowed access to a specific user data
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $key The user data key to test
|
||||
*
|
||||
* @return bool True if this key can be accessed, false otherwise
|
||||
*/
|
||||
function wpcf7dtx_user_data_access_is_allowed($key)
|
||||
{
|
||||
|
||||
// Get the DTX Settings
|
||||
$settings = wpcf7dtx_get_settings(); //get_option('cf7dtx_settings', []);
|
||||
|
||||
// Has access to all metadata been enabled?
|
||||
if (isset($settings['user_data_allow_all']) && $settings['user_data_allow_all'] === 'enabled') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If not, check the Allow List
|
||||
$allowed_keys = array();
|
||||
|
||||
// No key list from settings
|
||||
if (isset($settings['user_data_allow_keys']) && is_string($settings['user_data_allow_keys'])) {
|
||||
// Extract allowed keys from setting text area
|
||||
$allowed_keys = wpcf7dtx_parse_allowed_keys($settings['user_data_allow_keys']);
|
||||
}
|
||||
|
||||
// Allow custom filters
|
||||
$allowed_keys = apply_filters('wpcf7dtx_user_data_key_allow_list', $allowed_keys);
|
||||
|
||||
// Check if the key is in the allow list
|
||||
if (in_array($key, $allowed_keys)) {
|
||||
return true; // The key is allowed
|
||||
}
|
||||
|
||||
// Everything is disallowed by default
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the string saved in the options array from the allow list textarea and parse it into an array by newlines.
|
||||
* Also strip whitespace
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $allowlist The string of allowed keys stored in the DB
|
||||
*
|
||||
* @return array Array of allowed keys
|
||||
*/
|
||||
function wpcf7dtx_parse_allowed_keys($allowlist)
|
||||
{
|
||||
// Split by newlines
|
||||
$keys = wpcf7dtx_split_newlines($allowlist);
|
||||
// Trim whitespace
|
||||
$keys = array_map('trim', $keys);
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to parse strings stored in the database that are from text areas with one element per line into an array of strings
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $str The multi-line string to be parsed into an array
|
||||
*
|
||||
* @return array Array of parsed strings
|
||||
*/
|
||||
function wpcf7dtx_split_newlines($str)
|
||||
{
|
||||
return preg_split('/\r\n|\r|\n/', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CF7 DTX settings field from the WP options table. Returns an empty array if option has not previously been set
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return array The settings array
|
||||
*/
|
||||
function wpcf7dtx_get_settings()
|
||||
{
|
||||
return get_option('cf7dtx_settings', array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the CF7 DTX settings in the WP options table
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $settings The settings array
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
function wpcf7dtx_update_settings($settings)
|
||||
{
|
||||
update_option('cf7dtx_settings', $settings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs a useful PHP Warning message to users on how to allow-list denied meta and user keys
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $key The post meta or user key to which access is currently denied
|
||||
* @param string $type Either 'post_meta' or 'user_data', used to display an appropriate message to the user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_access_denied_alert($key, $type)
|
||||
{
|
||||
// Only check on the front end
|
||||
if (is_admin() || wp_doing_ajax() || wp_is_json_request()) return;
|
||||
|
||||
switch ($type) {
|
||||
case 'post_meta':
|
||||
$shortcode = 'CF7_get_custom_field';
|
||||
$list_name = __('Meta Key Allow List', 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
case 'user_data':
|
||||
$shortcode = 'CF7_get_current_user';
|
||||
$list_name = __('User Data Key Allow List', 'contact-form-7-dynamic-text-extension');
|
||||
break;
|
||||
default:
|
||||
$shortcode = '';
|
||||
$list_name = '';
|
||||
break;
|
||||
}
|
||||
|
||||
$settings_page_url = admin_url('admin.php?page=cf7dtx_settings');
|
||||
|
||||
$msg = sprintf(
|
||||
__('CF7 DTX: Access denied to key: "%1$s" in dynamic contact form shortcode: [%2$s]. Please add this key to the %3$s at %4$s', 'contact-form-7-dynamic-text-extension'),
|
||||
$key,
|
||||
$shortcode,
|
||||
$list_name,
|
||||
$settings_page_url
|
||||
);
|
||||
|
||||
trigger_error($msg, E_USER_WARNING);
|
||||
}
|
||||
@@ -1,381 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Add Frontend Validation Messages
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array An associative array of messages
|
||||
*
|
||||
* @return array A modified associative array of messages
|
||||
*/
|
||||
function wpcf7dtx_messages($messages)
|
||||
{
|
||||
return array_merge($messages, array(
|
||||
'dtx_invalid_email' => array(
|
||||
'description' => __('There is a field with an invalid email address', 'contact-form-7-dynamic-text-extension'),
|
||||
'default' => __('Please enter a valid email address.', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dtx_invalid_tel' => array(
|
||||
'description' => __('There is a field with an invalid phone number', 'contact-form-7-dynamic-text-extension'),
|
||||
'default' => __('Please enter a valid phone number.', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dtx_invalid_number' => array(
|
||||
'description' => __('There is a field with an invalid number', 'contact-form-7-dynamic-text-extension'),
|
||||
'default' => __('Please enter a valid number.', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
'dtx_invalid_date' => array(
|
||||
'description' => __('There is a field with an invalid date', 'contact-form-7-dynamic-text-extension'),
|
||||
'default' => __('Please enter a valid date.', 'contact-form-7-dynamic-text-extension')
|
||||
),
|
||||
));
|
||||
}
|
||||
add_filter('wpcf7_messages', 'wpcf7dtx_messages');
|
||||
|
||||
/**
|
||||
* Add DTX Error Code to Config Validator
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $error_codes A sequential array of available error codes in Contact Form 7.
|
||||
*
|
||||
* @return array A modified sequential array of available error codes in Contact Form 7.
|
||||
*/
|
||||
function wpcf7dtx_config_validator_available_error_codes($error_codes)
|
||||
{
|
||||
$dtx_errors = array('dtx_disallowed');
|
||||
return array_merge($error_codes, $dtx_errors);
|
||||
}
|
||||
add_filter('wpcf7_config_validator_available_error_codes', 'wpcf7dtx_config_validator_available_error_codes');
|
||||
|
||||
/**
|
||||
* Validate DTX Form Fields
|
||||
*
|
||||
* Frontend validation for DTX form tags
|
||||
*
|
||||
* @param WPCF7_Validation $result the current validation result object
|
||||
* @param WPCF7_FormTag $tag the current form tag being filtered for validation
|
||||
*
|
||||
* @return WPCF7_Validation a possibly modified validation result object
|
||||
*/
|
||||
function wpcf7dtx_validation_filter($result, $tag)
|
||||
{
|
||||
$type = str_replace(array('dynamic_', 'dynamic'), '', $tag->basetype);
|
||||
if (empty($tag->name) || in_array($type, array('hidden', 'submit', 'reset'))) {
|
||||
return $result; // Bail early for tags without names or if a specific type
|
||||
}
|
||||
|
||||
// Get the value
|
||||
$user_value = wpcf7dtx_array_has_key($tag->name, $_POST);
|
||||
if (is_array($user_value)) {
|
||||
$selection_count = count($user_value);
|
||||
if (!wpcf7_form_tag_supports($tag->type, 'selectable-values')) {
|
||||
// Field passed selectable values when it's doesn't support them
|
||||
$result->invalidate($tag, wpcf7_get_message('validation_error'));
|
||||
return $result;
|
||||
} elseif ($selection_count > 1) {
|
||||
if (!wpcf7_form_tag_supports($tag->type, 'multiple-controls-container')) {
|
||||
// Field passed multiple values when it's doesn't support them
|
||||
$result->invalidate($tag, wpcf7_get_message('validation_error'));
|
||||
return $result;
|
||||
}
|
||||
foreach ($user_value as $selection) {
|
||||
// Validate each selected choice
|
||||
$result = wpcf7dtx_validate_value($result, sanitize_textarea_field(strval($selection)), $tag, $type);
|
||||
if (!$result->is_valid($tag->name)) {
|
||||
return $result; // Return early if any are invalid
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
$user_value = sanitize_text_field(strval(implode(' ', $user_value)));
|
||||
} elseif ($type == 'textarea') {
|
||||
$user_value = sanitize_textarea_field(strval($user_value));
|
||||
} else {
|
||||
$user_value = sanitize_text_field(strval($user_value));
|
||||
}
|
||||
// Validate and return
|
||||
return wpcf7dtx_validate_value($result, $user_value, $tag, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Single Value
|
||||
*
|
||||
* @param WPCF7_Validation $result the current validation result object
|
||||
* @param string $value the current value being validated, sanitized
|
||||
* @param WPCF7_FormTag $tag the current form tag being filtered for validation
|
||||
* @param string $type Optional. The type of the current form tag. Default is blank for lookup.
|
||||
*
|
||||
* @return WPCF7_Validation a possibly modified validation result object
|
||||
*/
|
||||
function wpcf7dtx_validate_value($result, $value, $tag, $type = '')
|
||||
{
|
||||
$type = $type ? $type : str_replace(array('dynamic_', 'dynamic'), '', $tag->basetype);
|
||||
|
||||
// Validate required fields for value
|
||||
if ($tag->is_required() && empty($value)) {
|
||||
$result->invalidate($tag, wpcf7_get_message('invalid_required'));
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Validate value by type
|
||||
if (!empty($value)) {
|
||||
switch ($type) {
|
||||
case 'email':
|
||||
if (!wpcf7_is_email($value)) {
|
||||
$result->invalidate($tag, wpcf7_get_message('dtx_invalid_email'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'tel':
|
||||
if (!wpcf7_is_tel($value)) {
|
||||
$result->invalidate($tag, wpcf7_get_message('dtx_invalid_tel'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'number':
|
||||
case 'range':
|
||||
if (!wpcf7_is_number($value)) {
|
||||
$result->invalidate($tag, wpcf7_get_message('dtx_invalid_number'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
if (!wpcf7_is_date($value)) {
|
||||
$result->invalidate($tag, wpcf7_get_message('dtx_invalid_date'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Finish validating text-based inputs
|
||||
$maxlength = $tag->get_maxlength_option();
|
||||
$minlength = $tag->get_minlength_option();
|
||||
if ($maxlength && $minlength && $maxlength < $minlength) {
|
||||
$maxlength = $minlength = null;
|
||||
}
|
||||
$code_units = wpcf7_count_code_units($value);
|
||||
if (false !== $code_units) {
|
||||
if ($maxlength && $maxlength < $code_units) {
|
||||
$result->invalidate($tag, wpcf7_get_message('invalid_too_long'));
|
||||
return $result;
|
||||
} elseif ($minlength && $code_units < $minlength) {
|
||||
$result->invalidate($tag, wpcf7_get_message('invalid_too_short'));
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend Mail Configuration Validation
|
||||
*
|
||||
* Validate dynamic form tags used in mail configuration.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param WPCF7_ConfigValidator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_validate($validator)
|
||||
{
|
||||
// Check for sensitive form tags
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
$contact_form = $validator->contact_form();
|
||||
$form = $contact_form->prop('form');
|
||||
if (wpcf7_autop_or_not()) {
|
||||
$form = $manager->replace_with_placeholders($form);
|
||||
$form = wpcf7_autop($form);
|
||||
$form = $manager->restore_from_placeholders($form);
|
||||
}
|
||||
$form = $manager->replace_all($form);
|
||||
$tags = $manager->get_scanned_tags();
|
||||
foreach ($tags as $tag) {
|
||||
/** @var WPCF7_FormTag $tag */
|
||||
|
||||
// Only validate DTX formtags
|
||||
if (in_array($tag->basetype, array_merge(
|
||||
array('dynamictext', 'dynamichidden'), // Deprecated DTX form tags
|
||||
array_keys(wpcf7dtx_config()) // DTX form tags
|
||||
))) {
|
||||
// Check value for sensitive data
|
||||
$default = $tag->get_option('defaultvalue', '', true);
|
||||
if (!$default) {
|
||||
$default = $tag->get_default_option(strval(reset($tag->values)));
|
||||
}
|
||||
if (
|
||||
!empty($value = trim(wpcf7_get_hangover($tag->name, $default))) && // Has value
|
||||
($result = wpcf7dtx_validate_sensitive_value($value))['status'] // Has sensitive data
|
||||
) {
|
||||
$validator->add_error('form.body', 'dtx_disallowed', array(
|
||||
'message' => sprintf(
|
||||
__('[%1$s %2$s]: Access to key "%3$s" in shortcode "%4$s" is disallowed by default. To allow access, add "%3$s" to the %5$s Allow List.', 'contact-form-7-dynamic-text-extension'),
|
||||
esc_html($tag->basetype),
|
||||
esc_html($tag->name),
|
||||
esc_html($result['key']),
|
||||
esc_html($result['shortcode']),
|
||||
esc_html($result['shortcode'] == 'CF7_get_current_user' ? __('User Data Key', 'contact-form-7-dynamic-text-extension') : __('Meta Key', 'contact-form-7-dynamic-text-extension'))
|
||||
),
|
||||
'link' => wpcf7dtx_get_admin_settings_screen_url()
|
||||
));
|
||||
}
|
||||
|
||||
// Check placeholder for sensitive data
|
||||
if (
|
||||
($tag->has_option('placeholder') || $tag->has_option('watermark')) && // Using placeholder
|
||||
!empty($placeholder = trim(html_entity_decode(urldecode($tag->get_option('placeholder', '', true)), ENT_QUOTES))) && // Has value
|
||||
($result = wpcf7dtx_validate_sensitive_value($placeholder))['status'] // Has sensitive data
|
||||
) {
|
||||
$validator->add_error('form.body', 'dtx_disallowed', array(
|
||||
'message' => sprintf(
|
||||
__('[%1$s %2$s]: Access to key "%3$s" in shortcode "%4$s" is disallowed by default. To allow access, add "%3$s" to the %5$s Allow List.', 'contact-form-7-dynamic-text-extension'),
|
||||
esc_html($tag->basetype),
|
||||
esc_html($tag->name),
|
||||
esc_html($result['key']),
|
||||
esc_html($result['shortcode']),
|
||||
esc_html($result['shortcode'] == 'CF7_get_current_user' ? __('User Data Key', 'contact-form-7-dynamic-text-extension') : __('Meta Key', 'contact-form-7-dynamic-text-extension'))
|
||||
),
|
||||
'link' => wpcf7dtx_get_admin_settings_screen_url()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate email address
|
||||
if (!$validator->is_valid()) {
|
||||
$contact_form = null;
|
||||
$form_tags = null;
|
||||
foreach ($validator->collect_error_messages() as $component => $errors) {
|
||||
$components = explode('.', $component);
|
||||
if (count($components) === 2 && strpos($components[0], 'mail') === 0 && in_array($components[1], array('sender', 'recipient', 'additional_headers'))) {
|
||||
foreach ($errors as $error) {
|
||||
// Focus on email fields that flag the invalid mailbox syntax warning, have to test link because code isn't sent and message could be in any language
|
||||
if (strpos(wpcf7dtx_array_has_key('link', $error), 'invalid-mailbox-syntax') !== false) {
|
||||
if (is_null($contact_form)) {
|
||||
$contact_form = $validator->contact_form();
|
||||
}
|
||||
if (is_null($form_tags)) {
|
||||
$form_tags = wpcf7_scan_form_tags();
|
||||
}
|
||||
$raw_value = $contact_form->prop($components[0])[$components[1]];
|
||||
foreach ($form_tags as $tag) {
|
||||
if (!empty($tag->name)) {
|
||||
// Check if this form tag is in the raw value
|
||||
$form_tag = '[' . $tag->name . ']';
|
||||
if (strpos($raw_value, $form_tag) !== false && in_array($tag->basetype, array_keys(wpcf7dtx_config()))) {
|
||||
$validator->remove_error($component, 'invalid_mailbox_syntax'); // Remove error, this is ours to handle now
|
||||
$utm_source = urlencode(home_url());
|
||||
if (!in_array($tag->basetype, array('dynamic_hidden', 'dynamic_email'))) {
|
||||
$validator->add_error($component, 'invalid_mailbox_syntax', array(
|
||||
'message' => __('Only email, dynamic email, hidden, or dynamic hidden form tags can be used for email addresses.', 'contact-form-7-dynamic-text-extension'),
|
||||
'link' => esc_url(sprintf('https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/configuration-errors/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=config-error-invalid_mailbox_syntax#valid-form-tags', $utm_source))
|
||||
));
|
||||
} else {
|
||||
$dynamic_value = wpcf7dtx_get_dynamic(false, $tag); // Get the dynamic value of this tag
|
||||
if (empty($dynamic_value) && $tag->basetype == 'dynamic_hidden') {
|
||||
$validator->add_error($component, 'maybe_empty', array(
|
||||
'message' => __('The dynamic hidden form tag must have a default value.', 'contact-form-7-dynamic-text-extension'),
|
||||
'link' => esc_url(sprintf('https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/configuration-errors/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=config-error-maybe_empty#maybe-empty', $utm_source))
|
||||
));
|
||||
} elseif (empty($dynamic_value) && !$tag->is_required()) {
|
||||
$validator->add_error($component, 'maybe_empty', array(
|
||||
'message' => __('The dynamic form tag must be required or have a default value.', 'contact-form-7-dynamic-text-extension'),
|
||||
'link' => esc_url(sprintf('https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/configuration-errors/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=config-error-maybe_empty#maybe-empty', $utm_source))
|
||||
));
|
||||
} elseif (!empty($dynamic_value)) {
|
||||
if (!wpcf7_is_email($dynamic_value)) {
|
||||
$validator->add_error($component, 'invalid_mailbox_syntax', array(
|
||||
'message' => __('The default dynamic value does not result in a valid email address.', 'contact-form-7-dynamic-text-extension'),
|
||||
'link' => esc_url(sprintf('https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/configuration-errors/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=config-error-invalid_mailbox_syntax#invalid-email-address', $utm_source))
|
||||
));
|
||||
} elseif ($component[1] == 'sender' && !wpcf7_is_email_in_site_domain($dynamic_value)) {
|
||||
$validator->add_error($component, 'email_not_in_site_domain', array(
|
||||
'message' => __('The dynamic email address for the sender does not belong to the site domain.', 'contact-form-7-dynamic-text-extension'),
|
||||
'link' => esc_url(sprintf('https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/configuration-errors/?utm_source=%s&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=config-error-email_not_in_site_domain#invalid-site-domain', $utm_source))
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Custom Mail Template Validator
|
||||
*
|
||||
* Validator requires a minimum version of Contact Form 7.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpcf7dtx_init_validator()
|
||||
{
|
||||
if (wpcf7dtx_dependencies()) {
|
||||
add_action('wpcf7_config_validator_validate', 'wpcf7dtx_validate');
|
||||
}
|
||||
}
|
||||
add_action('plugins_loaded', 'wpcf7dtx_init_validator', 30);
|
||||
|
||||
|
||||
/**
|
||||
* Validate Field Value for Sensitive Data
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @see https://developer.wordpress.org/reference/functions/get_bloginfo/#description
|
||||
*
|
||||
* @param string $content The string to validate.
|
||||
*
|
||||
* @return array An associative array with keys `status` (bool), `shortcode` (string), and `key` (string).
|
||||
* The value of `status` is true if the content is a shortcode that is attempting to access sensitive data. False
|
||||
* otherwise. The value of `shortcode` is the the shortcode that is making the attempt if `status` is true. The
|
||||
* value of `key` is the shortcode's `key` attribute of the attempt being made if `status` is true.
|
||||
*/
|
||||
function wpcf7dtx_validate_sensitive_value($content)
|
||||
{
|
||||
$r = array(
|
||||
'status' => false,
|
||||
'shortcode' => '',
|
||||
'key' => ''
|
||||
);
|
||||
|
||||
// Parse the attributes. [0] is the shortcode name. ['key'] is the key attribute
|
||||
$atts = shortcode_parse_atts($content);
|
||||
|
||||
// If we can't extract the atts, or the shortcode or `key` is not an att, don't validate
|
||||
if (!is_array($atts) || !array_key_exists('key', $atts) || !array_key_exists('0', $atts)) return $r;
|
||||
|
||||
// Find the key and shortcode in question
|
||||
$key = sanitize_text_field($atts['key']);
|
||||
$shortcode = sanitize_text_field($atts['0']);
|
||||
|
||||
// If the shortcode or key value does not exist, don't validate
|
||||
if (empty($shortcode) || empty($key)) return $r;
|
||||
|
||||
$allowed = true;
|
||||
switch ($shortcode) {
|
||||
case 'CF7_get_custom_field':
|
||||
$allowed = wpcf7dtx_post_meta_key_access_is_allowed($key);
|
||||
break;
|
||||
case 'CF7_get_current_user':
|
||||
$allowed = wpcf7dtx_user_data_access_is_allowed($key);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (!$allowed) {
|
||||
$r['status'] = true;
|
||||
$r['shortcode'] = $shortcode;
|
||||
$r['key'] = $key;
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<?php // Silence is golden
|
||||
@@ -1,497 +0,0 @@
|
||||
=== Contact Form 7 - Dynamic Text Extension ===
|
||||
Contributors: sevenspark, tessawatkinsllc
|
||||
Donate link: https://just1voice.com/donate/
|
||||
Tags: Contact Form 7, autofill, prepopulate, dynamic form, form field
|
||||
Tested up to: 6.5
|
||||
Stable tag: 4.4.2
|
||||
|
||||
Extends Contact Form 7 by adding dynamic form fields that accepts shortcodes to prepopulate form fields with default values and dynamic placeholders.
|
||||
|
||||
== Description ==
|
||||
|
||||
Contact Form 7 is an excellent WordPress plugin and one of the top choices of free WordPress plugins for contact forms. Contact Form 7 - Dynamic Text Extension (DTX) makes it even more awesome by adding dynamic content capabilities. While default values in Contact Form 7 are static, DTX lets you create pre-populated fields pulled from other locations. Some examples might include:
|
||||
|
||||
* Auto-filling a URL or just getting the domain name or path
|
||||
* Auto-filling a post ID, title, or slug
|
||||
* Auto-filling a title, URL, or slug for the current page
|
||||
* Pre-populating a product number
|
||||
* Referencing other content on the site
|
||||
* Populating with post or page info
|
||||
* Populating with the current user's info
|
||||
* Populating with custom and meta fields
|
||||
* Generating unique identifiers for support tickets
|
||||
* Getting a list of post categories or other custom taxonomies
|
||||
* Getting a value from a cookie
|
||||
* Getting custom theme modifications
|
||||
* Any value using custom shortcodes
|
||||
|
||||
The possibilities are endless!
|
||||
|
||||
(View Demo)[https://wordpress.org/plugins/contact-form-7-dynamic-text-extension/?preview=1]
|
||||
|
||||
For over 10 years, DTX only handled `<input type="text" />` and `<input type="hidden" />` form fields, but version 4 finally introduces more:
|
||||
|
||||
* email
|
||||
* URL
|
||||
* tel (for phone numbers)
|
||||
* number
|
||||
* range (slider)
|
||||
* textarea (multiline text)
|
||||
* drop-down menu (select field)
|
||||
* checkboxes
|
||||
* radio buttons
|
||||
* date
|
||||
* submit (yes, a submit button where you can have dynamic text!)
|
||||
|
||||
## WHAT DOES IT DO? ##
|
||||
|
||||
DTX provides flexibility to WordPress users in creating dynamic forms in Contact Form 7. DTX comes with several built-in shortcodes that will allow the contact form to be populated from HTTPS GET variable or any info from the `get_bloginfo()` function, among others. See below for included shortcodes.
|
||||
|
||||
Don't see the shortcode you need on the list? You can write a [custom one](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/custom-shortcodes/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)! Any shortcode that returns a string or numeric value can be used here. The included shortcodes just cover the most common scenarios, but DTX provides the flexibility for you to grab any value you have access to programmatically.
|
||||
|
||||
= Dynamic Value =
|
||||
|
||||
The bread and butter of this plugin, set a dynamic value! This field can take any shortcode, with two important provisions:
|
||||
|
||||
1. The shortcode should NOT include the normal square brackets (`[` and `]`). So, instead of `[CF7_GET key='value']` you would use `CF7_GET key='value'`.
|
||||
1. Any parameters in the shortcode must use single quotes. That is: `CF7_GET key='value'` and not `CF7_GET key="value"`
|
||||
|
||||
= Dynamic Placeholder =
|
||||
|
||||
Set a dynamic placeholder with this attribute! This feature accepts static text or a shortcode. If using a shortcode, the same syntax applies from the dynamic value field. However, this field also has a few more needs:
|
||||
|
||||
1. The text/shortcode must first have apostrophes converted to it's HTML entity code, `'`
|
||||
1. After that, it must be URL encoded so that spaces become `%20` and other non-alphanumeric characters are converted.
|
||||
|
||||
If you're using Contact Form 7's tag generator to create the form tag, those extra needs are already taken care of. Dynamic placeholders are not available for dynamic hidden form tags.
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-attribute-placeholder/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Compatible with Caching Plugins =
|
||||
|
||||
DTX is cache friendly! You can set a field to be calculated after the page loads by setting the `dtx_pageload` attribute to any dynamic form tag.
|
||||
|
||||
Many websites use caching plugins to optimize for performance. If your website caches the HTML of the form, then any dynamic form fields you have get their first calculated value cached alongside it. This becomes an issue if you're using DTX to pull values from a cookie or the current URL's query string.
|
||||
|
||||
This is best for dynamic form fields that:
|
||||
|
||||
* gets the current URL
|
||||
* gets a value from the URL query
|
||||
* gets a value from a cookie
|
||||
* gets the current user's info
|
||||
* generates a unique identifier (GUID)
|
||||
|
||||
For dynamic fields that are page-specific, it's perfectly safe to cache those values. For example, dynamic form fields that:
|
||||
|
||||
* getting the page or post's ID, title, or slug
|
||||
* getting post meta for the current page
|
||||
* getting the post's assigned categories, tags, or other custom taxonomy
|
||||
* getting site info
|
||||
* getting theme modification values
|
||||
|
||||
*Note: Enabling a dynamic field to be calculated after the page loads will add frontend JavaScript. Depending on the shortcode used as the dynamic value, an AJAX call to the server may be sent to be processed. The script is minified and loaded in the footer and is deferred, minimizing impact on site performance and the AJAX calls are called asynchronously to avoid being a render-blocking resource and minimizing main-thread work. The script itself can be safely cached too.*
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tag-attribute-after-page-load/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Read Only Form Fields =
|
||||
|
||||
Check this box if you do not want to let users edit this field. It will add the `readonly` attribute to the input form field. This feature is not available for dynamic hidden form tags.
|
||||
|
||||
= Obfuscate Values for Enhanced Privacy =
|
||||
|
||||
If you're pre-filling a form field with an email address, bots can scrape that value from the page and use it for spam. You can add an additional layer of protecting by obfuscating the value, which turns each character into it's ASCII code. To the human eye, it looks like the character it's supposed to be because browsers will render the ASCII code, but for bots, it won't look like an email address!
|
||||
|
||||
## HOW TO USE IT ##
|
||||
|
||||
After installing and activating the plugin, you will have 2 new tag types to select from when creating or editing a Contact Form 7 form: the dynamic text field and dynamic hidden field. Most of the options in their tag generators will be familiar to Contact Form 7 users but there have been some upgrades.
|
||||
|
||||
= How to Obfuscate Values =
|
||||
|
||||
All of the shortcodes included with the DTX plugin allow the `obfuscate` attribute that you can set to any truthy value to provide an additional layer of security for sensitive data.
|
||||
|
||||
The Contact Form 7 tag with obfuscation turned on would look like this: `[dynamictext user_email "CF7_get_current_user key='user_email' obfuscate='on'"]`
|
||||
|
||||
= How to Enable Cache-Friendly Mode =
|
||||
|
||||
All of the dynamic form tags can be enabled for processing on the frontend of the website, or the client-side, by adding the `dtx_pageload` attribute to the Contact Form 7 form tag.
|
||||
|
||||
In the form editor of Contact Form 7, your form tag would look like: `[dynamictext current_url dtx_pageload "CF7_URL"]`
|
||||
|
||||
If using the tag generator, it's as simple as checking a box!
|
||||
|
||||
## INCLUDED SHORTCODES ##
|
||||
|
||||
The plugin includes several shortcodes for use with the Dynamic Text Extension right out of the box. You can write your own as well—any self-closing shortcode will work, even with attributes!
|
||||
|
||||
= Current URL or Part =
|
||||
|
||||
Retrieve the current URL: `CF7_URL`
|
||||
|
||||
In the form editor of Contact Form 7, your form tag would look like: `[dynamictext dynamicname "CF7_URL"]`
|
||||
|
||||
Optional parameter: `part`, which will return a parsed part of the URL. Valid values are `host`, `query`, and `path`
|
||||
|
||||
Host: Just the domain name and tld
|
||||
`[dynamictext host "CF7_URL part='host'"]`
|
||||
|
||||
Query: The query string after the ?, if one exists
|
||||
`[dynamictext query "CF7_URL part='query'"]`
|
||||
|
||||
Path: The URL path, for example, /contact, if one exists
|
||||
`[dynamictext path "CF7_URL part='path'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-url/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Referrer URL =
|
||||
|
||||
Get the referral URL, if it exists. Note that this is not necessarily reliable as not all browsers send this data.
|
||||
|
||||
CF7 Tag: `[dynamictext dynamicname "CF7_referrer"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-referrer-url/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Current Page Variables =
|
||||
|
||||
Retrieve information about the current page that the contact form is displayed on. Works great for use in templated areas like the site header, footer, widget, or sidebar! The shortcode works as follows:
|
||||
|
||||
Built-in shortcode: `CF7_get_current_var`
|
||||
|
||||
Required attribute: `key`
|
||||
|
||||
Possible values for `key` include:
|
||||
|
||||
* `id`
|
||||
* `title`
|
||||
* `url` (an alias for `CF7_URL`)
|
||||
* `slug`
|
||||
* `featured_image`
|
||||
* `terms` (an alias for `CF7_get_taxonomy`)
|
||||
|
||||
For pages that use a `WP_POST` object, this acts as an alias for `CF7_get_post_var` so those attributes work here as well.
|
||||
|
||||
For author pages, this acts as an alias for `CF7_get_current_user` so those attributes work here as well.
|
||||
|
||||
In the form editor of Contact Form 7, your form tag's value could look like: `CF7_get_current_var key='title'`
|
||||
|
||||
And then the full form tag would be: `[dynamictext dynamicname "CF7_get_current_var key='title'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-variables/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Post/Page Info =
|
||||
|
||||
Retrieve information about the current post or page (must be for a WP_POST object) that the contact form is displayed on. The shortcode works as follows:
|
||||
|
||||
`CF7_get_post_var key='title'` <-- retrieves the Post's Title
|
||||
`CF7_get_post_var key='slug'` <-- retrieves the Post's Slug
|
||||
|
||||
You can also retrieve any parameter from the global `$post` object. Just set that as the `key` value, for example `post_date`
|
||||
|
||||
The Contact Form 7 Tag would look like: `[dynamictext dynamicname "CF7_get_post_var key='title'"]`
|
||||
|
||||
Need to pull data from a _different_ post/page? Not a problem! Just specify it's post ID like this:
|
||||
|
||||
Dynamic value: `CF7_get_post_var key='title' post_id='245'`
|
||||
|
||||
Contact Form 7 Tag: `[dynamictext dynamicname "CF7_get_post_var key='title' post_id='245'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-post-page-variables//?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Post Meta & Custom Fields =
|
||||
|
||||
Retrieve custom fields from the current post/page. Just set the custom field as the key in the shortcode.
|
||||
|
||||
Note: You must add any meta keys that you want to allow access to to the allow list in your admin panel > Contact > Dynamic Text Extension > Meta Key Allow List. [More Information](https://sevenspark.com/docs/contact-form-7-dynamic-text-extension/allow-data-access)
|
||||
|
||||
The dynamic value input becomes: `CF7_get_custom_field key='my_custom_field'`
|
||||
|
||||
And the tag looks like this: `[dynamictext dynamicname "CF7_get_custom_field key='my_custom_field'"]`
|
||||
|
||||
For the purposes of including an email address, you can obfuscate the custom field value by setting obfuscate='on' in the shortcode like this:
|
||||
`[dynamictext dynamicname "CF7_get_custom_field key='my_custom_field' obfuscate='on'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-post-meta-custom-fields/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Featured Images & Media Attachments =
|
||||
|
||||
Retrieve the current post's featured image, the featured image of a different page, or any attachment from the Media Library with this shortcode!
|
||||
|
||||
The base shortcode is simply: `CF7_get_attachment` which returns the absolute URL of the current page's featured image.
|
||||
|
||||
By setting the `post_id` attribute to a post ID, you can get the featured image of another page.
|
||||
|
||||
By setting the `id` attribute to an attachment ID, you can get the absolute URL of any image uploaded to your WordPress website.
|
||||
|
||||
By setting the `size` attribute to any size registered on your website, you can get a specific image size.
|
||||
|
||||
Want to return the attachment ID instead of the URL? Also not a problem! Just set `return='id'` in the shortcode.
|
||||
|
||||
Most of the optional attributes can be used at the same time. For example, if I wanted to retrieve the attachment ID of a featured image for a different post, then the dynamic text form tag would look like this:
|
||||
`[dynamictext input_name "CF7_get_attachment post_id='123' return='id'"]`
|
||||
|
||||
If I wanted to get a specific image at a specific size, I can use this:
|
||||
`[dynamictext input_name "CF7_get_attachment id='123' size='thumbnail'"]`
|
||||
|
||||
The only two attributes that can’t play together is `id` and `post_id`. If both are specified, it will get the attachment specified by `id` and completely ignore the `post_id` attribute. If neither are specified, then it looks to the current featured image assigned to the global `$post` object.
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-media-attachment/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Current User Info & User Meta =
|
||||
|
||||
Get data about the current logged-in user.
|
||||
|
||||
Dynamic value: `CF7_get_current_user key='user_displayname'`
|
||||
CF7 Tag: `[dynamictext dynamicname "CF7_get_current_user"]`
|
||||
|
||||
Note: You must add any user keys that you want to allow access to to the allow list in your admin panel > Contact > Dynamic Text Extension > User Data Key Allow List. [More Information](https://sevenspark.com/docs/contact-form-7-dynamic-text-extension/allow-data-access)
|
||||
|
||||
Valid values for `key` include:
|
||||
|
||||
* `ID`
|
||||
* `user_login`
|
||||
* `display_name`
|
||||
* `user_email`
|
||||
* `user_firstname`
|
||||
* `user_lastname`
|
||||
* `user_description`
|
||||
|
||||
But also custom meta user keys!
|
||||
|
||||
For the purposes of including an email address, you can obfuscate the value by setting obfuscate='on' in the shortcode like this:
|
||||
`[dynamictext dynamicname "CF7_get_current_user key='user_email' obfuscate='on'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-current-user-user-meta/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Site/Blog Info =
|
||||
|
||||
Want to grab some information from your blog like the URL or the site name? Use the `CF7_bloginfo` shortcode. For example, to get the site's URL:
|
||||
|
||||
Enter the following into the "Dynamic Value" input: `CF7_bloginfo show='url'`
|
||||
|
||||
Your Content Form 7 Tag will look something like this: `[dynamictext dynamicname "CF7_bloginfo show='url'"]`
|
||||
|
||||
Your form's dynamicname text input will then be pre-populated with your site's URL
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-site-blog-information/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Theme Options =
|
||||
|
||||
Want to retrieve values from your active theme's Customizer? Now you can with the `CF7_get_theme_option` shortcode.
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-theme-option/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= HTTP GET Variables =
|
||||
|
||||
Want to use a variable from the PHP `$_GET` array? Just use the `CF7_GET` shortcode. For example, if you want to get the foo parameter from the url
|
||||
`http://mysite.com?foo=bar`
|
||||
|
||||
Enter the following into the "Dynamic Value" input: `CF7_GET key='foo'`
|
||||
|
||||
Your Content Form 7 Tag will look something like this: `[dynamictext dynamicname "CF7_GET key='foo'"]`
|
||||
|
||||
Your form's dynamicname text input will then be pre-populated with the value of `foo`, in this case, `bar`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-php-get-variables/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= HTTP POST Variables =
|
||||
|
||||
Grab variables from the PHP `$_POST` array. The shortcode is much like the GET shortcode:
|
||||
|
||||
Dynamic value: `CF7_POST key='foo'`
|
||||
|
||||
Your Content Form 7 Tag will look something like this: `[dynamictext dynamicname "CF7_POST key='foo'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-php-post-variables/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= Cookie Values =
|
||||
|
||||
If your WordPress website uses cookies, you might want to pull the value of a specific cookie into a form. You can do that with the `CF7_get_cookie` shortcode. It only needs a `key` attribute.
|
||||
|
||||
Dynamic value: `CF7_get_cookie key='foo'`
|
||||
|
||||
Your Content Form 7 Tag will look something like this: `[dynamictext dynamicname "CF7_get_cookie key='foo'"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-cookie/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
= GUID =
|
||||
|
||||
Generate a globally unique identifier (GUID) in a form field. This is a great utility shortcode for forms that need unique identifiers for support tickets, receipts, reference numbers, etc., without having to expose personally identifiable information (PII). This shortcode takes no parameters: `CF7_guid`
|
||||
|
||||
In the form editor of Contact Form 7, your form tag would look like: `[dynamictext dynamicname "CF7_guid"]`
|
||||
|
||||
Learn more and see examples from [the DTX Knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/shortcodes/dtx-shortcode-guid/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
== Installation ==
|
||||
|
||||
= Minimum Requirements =
|
||||
|
||||
To ensure your WordPress installation meets these requirements, you can login to your WordPress website and navigate to *Tools > Site Health* and click on the *Info* tab. Expand the *WordPress*, *Active Plugins*, and *Server* accordions and compare that information with the details below.
|
||||
|
||||
* WordPress version 5.5 or greater
|
||||
* PHP version 7.4 or greater
|
||||
* [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) version 5.7 or greater
|
||||
|
||||
There are three (3) ways to install my plugin: automatically, upload, or manually.
|
||||
|
||||
= Install Method 1: Automatic Installation =
|
||||
|
||||
Automatic installation is the easiest option as WordPress handles the file transfers itself and you don’t need to leave your web browser.
|
||||
|
||||
1. Log in to your WordPress dashboard.
|
||||
1. Navigate to **Plugins > Add New**.
|
||||
1. Where it says “Keyword” in a dropdown, change it to “Author”
|
||||
1. In the search form, type “TessaWatkinsLLC” (results may begin populating as you type but my plugins will only show when the full name is there)
|
||||
1. Once you’ve found my plugin in the search results that appear, click the **Install Now** button and wait for the installation process to complete.
|
||||
1. Once the installation process is completed, click the **Activate** button to activate my plugin.
|
||||
|
||||
= Install Method 2: Upload via WordPress Admin =
|
||||
|
||||
This method involves is a little more involved. You don’t need to leave your web browser, but you’ll need to download and then upload the files yourself.
|
||||
|
||||
1. [Download my plugin](https://wordpress.org/plugins/contact-form-7-dynamic-text-extension/) from WordPress.org; it will be in the form of a zip file.
|
||||
1. Log in to your WordPress dashboard.
|
||||
1. Navigate to **Plugins > Add New**.
|
||||
1. Click the **Upload Plugin** button at the top of the screen.
|
||||
1. Select the zip file from your local file system that was downloaded in step 1.
|
||||
1. Click the **Install Now** button and wait for the installation process to complete.
|
||||
1. Once the installation process is completed, click the **Activate** button to activate my plugin.
|
||||
|
||||
= Install Method 3: Manual Installation =
|
||||
|
||||
This method is the most involved as it requires you to be familiar with the process of transferring files using an SFTP client.
|
||||
|
||||
1. [Download my plugin](https://wordpress.org/plugins/contact-form-7-dynamic-text-extension/) from WordPress.org; it will be in the form of a zip file.
|
||||
1. Unzip the contents; you should have a single folder named `contact-form-7-dynamic-text-extension`.
|
||||
1. Connect to your WordPress server with your favorite SFTP client.
|
||||
1. Copy the folder from step 2 to the `/wp-content/plugins/` folder in your WordPress directory. Once the folder and all of its files are there, installation is complete.
|
||||
1. Now log in to your WordPress dashboard.
|
||||
1. Navigate to **Plugins > Installed Plugins**. You should now see my plugin in your list.
|
||||
1. Click the **Activate** button under my plugin to activate it.
|
||||
|
||||
== Screenshots ==
|
||||
|
||||
1. Screenshot of the form tag buttons in the form editor of Contact Form 7. The dynamic buttons appear in purple instead of blue to visually set them apart.
|
||||
2. The form tag generator screen for the dynamic text form tag
|
||||
3. The form tag generator screen for the dynamic hidden form tag
|
||||
4. The form tag generator screen for the dynamic email form tag
|
||||
5. The form tag generator screen for the dynamic URL form tag
|
||||
6. The form tag generator screen for the dynamic phone number (tel) form tag
|
||||
7. The form tag generator screen for the dynamic number spinbox form tag
|
||||
8. The form tag generator screen for the dynamic sliding range form tag
|
||||
9. The form tag generator screen for the dynamic textarea form tag
|
||||
10. The form tag generator screen for the dynamic drop-down menu (select) form tag
|
||||
11. The form tag generator screen for the dynamic checkboxes form tag
|
||||
12. The form tag generator screen for the dynamic radio buttons form tag
|
||||
13. The form tag generator screen for the dynamic date form tag
|
||||
14. The form tag generator screen for the dynamic submit form tag
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
Please check out the [FAQ on our website](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/frequently-asked-questions/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
|
||||
== Upgrade Notice ==
|
||||
|
||||
= 4.4.2 =
|
||||
Addressed another PHP warning introduced in version 4.4.0. See [the changelog](https://plugins.trac.wordpress.org/browser/contact-form-7-dynamic-text-extension/trunk/changelog.txt) for more details.
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 4.4.2 =
|
||||
|
||||
= 4.4.2 =
|
||||
|
||||
* Fix: Addressed PHP warning for undefined variable $default_placeholder introduced in version 4.4.0, [see support thread](https://wordpress.org/support/topic/php-warning-undefined-variable-default_placeholder/)
|
||||
* Minor: Create preview link using WordPress Playground, [check it out](https://wordpress.org/plugins/contact-form-7-dynamic-text-extension/?preview=1)
|
||||
|
||||
= 4.4.1 =
|
||||
|
||||
* Fix: Addressed PHP warnings for undefined array keys introduced in version 4.4.0, [see support thread](https://wordpress.org/support/topic/tons-of-errors-in-error_log/)
|
||||
|
||||
= 4.4.0 =
|
||||
|
||||
* Update: Added *Contact Form 7* (CF7) as a requirement as introduced in WordPress version 6.5. This plugin cannot be activated until CF7 is installed and activated.
|
||||
* Feature: introduced `dynamic_label` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-label/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: updated the following attributes to be dynamic: `autocapitalize`, `autocomplete`, `autofocus`, `cols`, `disabled`, `list`, `max`, `maxlength`, `min`, `minlength`, `pattern`, `readonly`, `size`, and `step`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/dynamic-attributes/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Update: Updated the form tag generator for checkboxes and radio buttons to include documentation for the `default` attribute.
|
||||
* Update: Updated the form tag generator with fields for `min`, `max`, `step`, `minlength`, `maxlength`, and `autocomplete` for appropriate form tags. The `autocomplete` and `autocapitalize` are text fields that uses a `datalist` because I always forget those things...
|
||||
* Update: Increased the tag generator size to accommodate the new attributes.
|
||||
* Update: Some form tag generators display the generated form tag in a `textarea` to accommodate lengthy generated form tags.
|
||||
|
||||
= 4.3.1 =
|
||||
|
||||
* Fix: Resolved the PHP warning regarding `Undefined array key "value" in /.../contact-form-7-dynamic-text-extension/contact-form-7-dynamic-text-extension.php on line 391`, [see support thread](https://wordpress.org/support/topic/undefined-array-key-value-2/).
|
||||
* Fix: Resolved a bug introduced in version 4.2.1 that prevented the mail template validator from recognizing DTX form tags, [see support thread](https://wordpress.org/support/topic/email-field-validation-4/).
|
||||
* Fix: The `default` attribute for `dynamic_checkbox` can now accept multiple values that are delimited by an underscore (_), making it consistent with [Contact Form 7](https://contactform7.com/checkboxes-radio-buttons-and-menus/#checkbox-radio), [see support thread](https://wordpress.org/support/topic/help-dynamic_checkbox-and-default-values/).
|
||||
|
||||
= 4.3.0 =
|
||||
|
||||
* Feature: Added the `wpcf7dtx_shortcode` filter to all built-in shortcodes as requested. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/filter-modify-built-in-shortcode-responses/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme).
|
||||
* Fix: Resolved a bug that prevented using the number zero as the value for select fields, checkboxes, and radio buttons, [see support thread](https://wordpress.org/support/topic/error-with-option-value-0-for-a-dynamic-radio-button/).
|
||||
|
||||
= 4.2.2 =
|
||||
|
||||
* Feature: Cache compatibility JavaScript triggers the custom `dtx_init` event on enabled input fields, [see support thread](https://wordpress.org/support/topic/dynamic_text-cf7_url-dont-fire-onchange-event/).
|
||||
|
||||
= 4.2.1 =
|
||||
|
||||
* Feature: Allows text-based fields to use `autocapitalize` attribute
|
||||
* Feature: Allows text-based fields to use `autofocus` attribute
|
||||
* Feature: Allows text-based fields to use `list` attribute
|
||||
* Feature: Allows text-based fields to use `pattern` attribute
|
||||
* Feature: Allows textareas to use `wrap` attribute
|
||||
* Fix: Resolved the bug that prevented the `dynamic_date` shortcode from using `min`, `max`, and `step` attributes, [see support thread](https://wordpress.org/support/topic/dynamic_date-min-max-step-options-ignored/).
|
||||
* Fix: Added minimum version check for Contact Form 7, [see support thread](https://wordpress.org/support/topic/str_contains-is-php-8-0-only-broken-compatibility/).
|
||||
* Fix: Resolved an issue that used a function introduced in PHP 8 while plugin compatibility setting is currently still set to 7.4+, [see support thread](https://wordpress.org/support/topic/str_contains-is-php-8-0-only-broken-compatibility/).
|
||||
|
||||
= 4.2.0 =
|
||||
|
||||
* Security Update: ** Please be sure to review this doc, as you may need to adjust the settings: [Documentation by SevenSpark](https://sevenspark.com/docs/contact-form-7-dynamic-text-extension/allow-data-access), [Documentation by AuRise Creative](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/security/) **
|
||||
* Feature: Added Settings Screen with Allow Lists
|
||||
* Feature: Added Form Scanner
|
||||
* Feature: Added Allow List key validation in CF7 Form Validator
|
||||
|
||||
= 4.1.0 =
|
||||
|
||||
* Feature: Looks for a `dtx.php` file in the `wp_content` directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Feature: Looks for a `dtx.php` file in the current active theme's directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Feature: Looks for a `dtx.php` file in the current active theme's parent directory to maybe load custom shortcodes, [see support thread](https://wordpress.org/support/topic/how-to-avoid-custom-shortcodes-being-overwritten-on-updates/)
|
||||
* Fix: addressed user reported bug, [see support thread](https://wordpress.org/support/topic/fatal-error-v4-0-3/)
|
||||
|
||||
= 4.0.3 =
|
||||
|
||||
* Feature: Added `exclusive` option to checkbox tag generator
|
||||
* Fix: addressed bug that put all dynamic checkbox/radio options into one
|
||||
* Fix: addressed bug in frontend validator for multiple selected values
|
||||
|
||||
= 4.0.2 =
|
||||
|
||||
* Fix: addressed bug that put all dynamic select options into one, [see support thread](https://wordpress.org/support/topic/dynamic-select-get-option-values-from-shortcode/)
|
||||
* Update: sanitizing and escaping filters now accept `none` as value for `$type` to bypass. Use with caution.
|
||||
|
||||
= 4.0.1 =
|
||||
|
||||
* Fix: addressed bug that prevented translation for cache compatibility description
|
||||
|
||||
= 4.0.0 =
|
||||
|
||||
* Major: modified function names
|
||||
* Major: deprecated `dynamictext` and `dynamichidden` form tags in favor of `dynamic_text` and `dynamic_hidden`. For more information, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_email` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-email/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_url` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-url/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_tel` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-tel/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_number` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-number/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_range` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-range/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_textarea` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-textarea/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_select` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_radio` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-radio/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_date` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-date/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dynamic_submit` form tag. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-submit/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dtx_hide_blank` form tag attribute for `dynamic_select`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: introduced `dtx_disable_blank` form tag attribute for `dynamic_select`. For usage details, see the [knowledge base](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/form-tags/dynamic-select/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: added mail validation for `dynamic_email` and `dynamic_hidden` for backend configuration. For more information, see the [FAQ](https://aurisecreative.com/docs/contact-form-7-dynamic-text-extension/frequently-asked-questions/?utm_source=wordpress.org&utm_medium=link&utm_campaign=contact-form-7-dynamic-text-extension&utm_content=readme)
|
||||
* Feature: added the Akismet feature to DTX text, email, and URL form tags.
|
||||
* Update: adjusted how queued values were sent for cache compatibility mode to allow for multiline values in textareas
|
||||
* Removed unused utility functions
|
||||
|
||||
= Older Releases =
|
||||
|
||||
Please see our [additional changelog.txt file](https://plugins.trac.wordpress.org/browser/contact-form-7-dynamic-text-extension/trunk/changelog.txt)
|
||||
@@ -1,699 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/admin-functions.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/help-tabs.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/tag-generator.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/welcome-panel.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/config-validator.php';
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_init',
|
||||
static function () {
|
||||
do_action( 'wpcf7_admin_init' );
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_menu',
|
||||
'wpcf7_admin_menu',
|
||||
9, 0
|
||||
);
|
||||
|
||||
function wpcf7_admin_menu() {
|
||||
do_action( 'wpcf7_admin_menu' );
|
||||
|
||||
add_menu_page(
|
||||
__( 'Contact Form 7', 'contact-form-7' ),
|
||||
__( 'Contact', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice(),
|
||||
'wpcf7_read_contact_forms',
|
||||
'wpcf7',
|
||||
'wpcf7_admin_management_page',
|
||||
'dashicons-email',
|
||||
30
|
||||
);
|
||||
|
||||
$edit = add_submenu_page( 'wpcf7',
|
||||
__( 'Edit Contact Form', 'contact-form-7' ),
|
||||
__( 'Contact Forms', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7' ),
|
||||
'wpcf7_read_contact_forms',
|
||||
'wpcf7',
|
||||
'wpcf7_admin_management_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $edit, 'wpcf7_load_contact_form_admin', 10, 0 );
|
||||
|
||||
$addnew = add_submenu_page( 'wpcf7',
|
||||
__( 'Add New Contact Form', 'contact-form-7' ),
|
||||
__( 'Add New', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7-new' ),
|
||||
'wpcf7_edit_contact_forms',
|
||||
'wpcf7-new',
|
||||
'wpcf7_admin_add_new_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $addnew, 'wpcf7_load_contact_form_admin', 10, 0 );
|
||||
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
if ( $integration->service_exists() ) {
|
||||
$integration = add_submenu_page( 'wpcf7',
|
||||
__( 'Integration with External API', 'contact-form-7' ),
|
||||
__( 'Integration', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7-integration' ),
|
||||
'wpcf7_manage_integration',
|
||||
'wpcf7-integration',
|
||||
'wpcf7_admin_integration_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $integration, 'wpcf7_load_integration_page', 10, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_menu_change_notice( $menu_slug = '' ) {
|
||||
$counts = apply_filters( 'wpcf7_admin_menu_change_notice',
|
||||
array(
|
||||
'wpcf7' => 0,
|
||||
'wpcf7-new' => 0,
|
||||
'wpcf7-integration' => 0,
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $menu_slug ) ) {
|
||||
$count = absint( array_sum( $counts ) );
|
||||
} elseif ( isset( $counts[$menu_slug] ) ) {
|
||||
$count = absint( $counts[$menu_slug] );
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
if ( $count ) {
|
||||
return sprintf(
|
||||
' <span class="update-plugins %1$d"><span class="plugin-count">%2$s</span></span>',
|
||||
$count,
|
||||
esc_html( number_format_i18n( $count ) )
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
'wpcf7_admin_enqueue_scripts',
|
||||
10, 1
|
||||
);
|
||||
|
||||
function wpcf7_admin_enqueue_scripts( $hook_suffix ) {
|
||||
if ( false === strpos( $hook_suffix, 'wpcf7' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style( 'contact-form-7-admin',
|
||||
wpcf7_plugin_url( 'admin/css/styles.css' ),
|
||||
array(), WPCF7_VERSION, 'all'
|
||||
);
|
||||
|
||||
if ( wpcf7_is_rtl() ) {
|
||||
wp_enqueue_style( 'contact-form-7-admin-rtl',
|
||||
wpcf7_plugin_url( 'admin/css/styles-rtl.css' ),
|
||||
array(), WPCF7_VERSION, 'all'
|
||||
);
|
||||
}
|
||||
|
||||
wp_enqueue_script( 'wpcf7-admin',
|
||||
wpcf7_plugin_url( 'admin/js/scripts.js' ),
|
||||
array( 'jquery', 'jquery-ui-tabs' ),
|
||||
WPCF7_VERSION,
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'apiSettings' => array(
|
||||
'root' => sanitize_url( rest_url( 'contact-form-7/v1' ) ),
|
||||
'namespace' => 'contact-form-7/v1',
|
||||
'nonce' => ( wp_installing() && ! is_multisite() )
|
||||
? '' : wp_create_nonce( 'wp_rest' ),
|
||||
),
|
||||
'pluginUrl' => wpcf7_plugin_url(),
|
||||
'saveAlert' => __(
|
||||
"The changes you made will be lost if you navigate away from this page.",
|
||||
'contact-form-7' ),
|
||||
'activeTab' => (int) ( $_GET['active-tab'] ?? 0 ),
|
||||
'configValidator' => array(
|
||||
'errors' => array(),
|
||||
'howToCorrect' => __( "How to resolve?", 'contact-form-7' ),
|
||||
'oneError' => __( '1 configuration error detected', 'contact-form-7' ),
|
||||
'manyErrors' => __( '%d configuration errors detected', 'contact-form-7' ),
|
||||
'oneErrorInTab' => __( '1 configuration error detected in this tab panel', 'contact-form-7' ),
|
||||
'manyErrorsInTab' => __( '%d configuration errors detected in this tab panel', 'contact-form-7' ),
|
||||
'docUrl' => WPCF7_ConfigValidator::get_doc_link(),
|
||||
/* translators: screen reader text */
|
||||
'iconAlt' => __( '(configuration error)', 'contact-form-7' ),
|
||||
),
|
||||
);
|
||||
|
||||
if ( $post = wpcf7_get_current_contact_form()
|
||||
and current_user_can( 'wpcf7_edit_contact_form', $post->id() )
|
||||
and wpcf7_validate_configuration() ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $post );
|
||||
$config_validator->restore();
|
||||
$args['configValidator']['errors'] =
|
||||
$config_validator->collect_error_messages();
|
||||
}
|
||||
|
||||
wp_localize_script( 'wpcf7-admin', 'wpcf7', $args );
|
||||
|
||||
add_thickbox();
|
||||
|
||||
wp_enqueue_script( 'wpcf7-admin-taggenerator',
|
||||
wpcf7_plugin_url( 'admin/js/tag-generator.js' ),
|
||||
array( 'jquery', 'thickbox', 'wpcf7-admin' ),
|
||||
WPCF7_VERSION,
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'set_screen_option_wpcf7_contact_forms_per_page',
|
||||
static function ( $result, $option, $value ) {
|
||||
$wpcf7_screens = array(
|
||||
'wpcf7_contact_forms_per_page',
|
||||
);
|
||||
|
||||
if ( in_array( $option, $wpcf7_screens ) ) {
|
||||
$result = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
},
|
||||
10, 3
|
||||
);
|
||||
|
||||
|
||||
function wpcf7_load_contact_form_admin() {
|
||||
global $plugin_page;
|
||||
|
||||
$action = wpcf7_current_action();
|
||||
|
||||
do_action( 'wpcf7_admin_load',
|
||||
trim( $_GET['page'] ?? '' ),
|
||||
$action
|
||||
);
|
||||
|
||||
if ( 'save' === $action ) {
|
||||
$id = $_POST['post_ID'] ?? '-1';
|
||||
|
||||
check_admin_referer( 'wpcf7-save-contact-form_' . $id );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
wp_die(
|
||||
__( "You are not allowed to edit this item.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
$contact_form = wpcf7_save_contact_form(
|
||||
array_merge(
|
||||
$_REQUEST,
|
||||
array(
|
||||
'id' => $id,
|
||||
'title' => $_POST['post_title'] ?? null,
|
||||
'locale' => $_POST['wpcf7-locale'] ?? null,
|
||||
'form' => $_POST['wpcf7-form'] ?? '',
|
||||
'mail' => $_POST['wpcf7-mail'] ?? array(),
|
||||
'mail_2' => $_POST['wpcf7-mail-2'] ?? array(),
|
||||
'messages' => $_POST['wpcf7-messages'] ?? array(),
|
||||
'additional_settings' => $_POST['wpcf7-additional-settings'] ?? '',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ( $contact_form and wpcf7_validate_configuration() ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form );
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
}
|
||||
|
||||
$query = array(
|
||||
'post' => $contact_form ? $contact_form->id() : 0,
|
||||
'active-tab' => (int) ( $_POST['active-tab'] ?? 0 ),
|
||||
);
|
||||
|
||||
if ( ! $contact_form ) {
|
||||
$query['message'] = 'failed';
|
||||
} elseif ( -1 == $id ) {
|
||||
$query['message'] = 'created';
|
||||
} else {
|
||||
$query['message'] = 'saved';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( 'copy' === $action ) {
|
||||
$id = absint( $_POST['post_ID'] ?? $_REQUEST['post'] ?? '' );
|
||||
|
||||
check_admin_referer( 'wpcf7-copy-contact-form_' . $id );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
wp_die(
|
||||
__( "You are not allowed to edit this item.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
$query = array();
|
||||
|
||||
if ( $contact_form = wpcf7_contact_form( $id ) ) {
|
||||
$new_contact_form = $contact_form->copy();
|
||||
$new_contact_form->save();
|
||||
|
||||
$query['post'] = $new_contact_form->id();
|
||||
$query['message'] = 'created';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( 'delete' === $action ) {
|
||||
if ( ! empty( $_POST['post_ID'] ) ) {
|
||||
check_admin_referer( 'wpcf7-delete-contact-form_' . $_POST['post_ID'] );
|
||||
} elseif ( ! is_array( $_REQUEST['post'] ) ) {
|
||||
check_admin_referer( 'wpcf7-delete-contact-form_' . $_REQUEST['post'] );
|
||||
} else {
|
||||
check_admin_referer( 'bulk-posts' );
|
||||
}
|
||||
|
||||
$posts = (array) ( $_POST['post_ID'] ?? $_REQUEST['post'] ?? array() );
|
||||
|
||||
$deleted = 0;
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
$post = WPCF7_ContactForm::get_instance( $post );
|
||||
|
||||
if ( empty( $post ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_delete_contact_form', $post->id() ) ) {
|
||||
wp_die(
|
||||
__( "You are not allowed to delete this item.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $post->delete() ) {
|
||||
wp_die( __( "Error in deleting.", 'contact-form-7' ) );
|
||||
}
|
||||
|
||||
$deleted += 1;
|
||||
}
|
||||
|
||||
$query = array();
|
||||
|
||||
if ( ! empty( $deleted ) ) {
|
||||
$query['message'] = 'deleted';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
$post = null;
|
||||
|
||||
if ( 'wpcf7-new' === $plugin_page ) {
|
||||
$post = WPCF7_ContactForm::get_template( array(
|
||||
'locale' => $_GET['locale'] ?? null,
|
||||
) );
|
||||
} elseif ( ! empty( $_GET['post'] ) ) {
|
||||
$post = WPCF7_ContactForm::get_instance( $_GET['post'] );
|
||||
}
|
||||
|
||||
$current_screen = get_current_screen();
|
||||
|
||||
$help_tabs = new WPCF7_Help_Tabs( $current_screen );
|
||||
|
||||
if ( $post
|
||||
and current_user_can( 'wpcf7_edit_contact_form', $post->id() ) ) {
|
||||
$help_tabs->set_help_tabs( 'edit' );
|
||||
} else {
|
||||
$help_tabs->set_help_tabs( 'list' );
|
||||
|
||||
if ( ! class_exists( 'WPCF7_Contact_Form_List_Table' ) ) {
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/class-contact-forms-list-table.php';
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'manage_' . $current_screen->id . '_columns',
|
||||
array( 'WPCF7_Contact_Form_List_Table', 'define_columns' ),
|
||||
10, 0
|
||||
);
|
||||
|
||||
add_screen_option( 'per_page', array(
|
||||
'default' => 20,
|
||||
'option' => 'wpcf7_contact_forms_per_page',
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_management_page() {
|
||||
if ( $post = wpcf7_get_current_contact_form() ) {
|
||||
$post_id = $post->initial() ? -1 : $post->id();
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'validate' == wpcf7_current_action()
|
||||
and wpcf7_validate_configuration()
|
||||
and current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
wpcf7_admin_bulk_validate_page();
|
||||
return;
|
||||
}
|
||||
|
||||
$list_table = new WPCF7_Contact_Form_List_Table();
|
||||
$list_table->prepare_items();
|
||||
|
||||
?>
|
||||
<div class="wrap" id="wpcf7-contact-form-list-table">
|
||||
|
||||
<h1 class="wp-heading-inline"><?php
|
||||
echo esc_html( __( 'Contact Forms', 'contact-form-7' ) );
|
||||
?></h1>
|
||||
|
||||
<?php
|
||||
if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
echo wpcf7_link(
|
||||
menu_page_url( 'wpcf7-new', false ),
|
||||
__( 'Add New', 'contact-form-7' ),
|
||||
array( 'class' => 'page-title-action' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $_REQUEST['s'] ) ) {
|
||||
echo sprintf(
|
||||
'<span class="subtitle">'
|
||||
/* translators: %s: search keywords */
|
||||
. __( 'Search results for “%s”', 'contact-form-7' )
|
||||
. '</span>',
|
||||
esc_html( $_REQUEST['s'] )
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<hr class="wp-header-end">
|
||||
|
||||
<?php
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7', wpcf7_current_action(), null
|
||||
);
|
||||
|
||||
wpcf7_welcome_panel();
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
'wpcf7', wpcf7_current_action(), null
|
||||
);
|
||||
?>
|
||||
|
||||
<form method="get" action="">
|
||||
<input type="hidden" name="page" value="<?php echo esc_attr( $_REQUEST['page'] ); ?>" />
|
||||
<?php $list_table->search_box( __( 'Search Contact Forms', 'contact-form-7' ), 'wpcf7-contact' ); ?>
|
||||
<?php $list_table->display(); ?>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_add_new_page() {
|
||||
$post = wpcf7_get_current_contact_form();
|
||||
|
||||
if ( ! $post ) {
|
||||
$post = WPCF7_ContactForm::get_template();
|
||||
}
|
||||
|
||||
$post_id = -1;
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_load_integration_page() {
|
||||
do_action( 'wpcf7_admin_load',
|
||||
trim( $_GET['page'] ?? '' ),
|
||||
wpcf7_current_action()
|
||||
);
|
||||
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
if ( isset( $_REQUEST['service'] )
|
||||
and $integration->service_exists( $_REQUEST['service'] ) ) {
|
||||
$service = $integration->get_service( $_REQUEST['service'] );
|
||||
$service->load( wpcf7_current_action() );
|
||||
}
|
||||
|
||||
$help_tabs = new WPCF7_Help_Tabs( get_current_screen() );
|
||||
$help_tabs->set_help_tabs( 'integration' );
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_integration_page() {
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
$service = isset( $_REQUEST['service'] )
|
||||
? $integration->get_service( $_REQUEST['service'] )
|
||||
: null;
|
||||
|
||||
?>
|
||||
<div class="wrap" id="wpcf7-integration">
|
||||
|
||||
<h1><?php echo esc_html( __( 'Integration with External API', 'contact-form-7' ) ); ?></h1>
|
||||
|
||||
<p><?php
|
||||
echo sprintf(
|
||||
/* translators: %s: link labeled 'Integration with external APIs' */
|
||||
esc_html( __( "You can expand the possibilities of your contact forms by integrating them with external services. For details, see %s.", 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/integration-with-external-apis/', 'contact-form-7' ),
|
||||
__( 'Integration with external APIs', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
?></p>
|
||||
|
||||
<?php
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7-integration', wpcf7_current_action(), $service
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
'wpcf7-integration', wpcf7_current_action(), $service
|
||||
);
|
||||
|
||||
if ( $service ) {
|
||||
$message = $_REQUEST['message'] ?? '';
|
||||
$service->admin_notice( $message );
|
||||
|
||||
$integration->list_services( array(
|
||||
'include' => $_REQUEST['service'],
|
||||
) );
|
||||
} else {
|
||||
$integration->list_services();
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_notices', 'wpcf7_admin_updated_message', 10, 3 );
|
||||
|
||||
function wpcf7_admin_updated_message( $page, $action, $object ) {
|
||||
if ( ! in_array( $page, array( 'wpcf7', 'wpcf7-new' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $_REQUEST['message'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'created' === $_REQUEST['message'] ) {
|
||||
$updated_message = __( "Contact form created.", 'contact-form-7' );
|
||||
} elseif ( 'saved' === $_REQUEST['message'] ) {
|
||||
$updated_message = __( "Contact form saved.", 'contact-form-7' );
|
||||
} elseif ( 'deleted' === $_REQUEST['message'] ) {
|
||||
$updated_message = __( "Contact form deleted.", 'contact-form-7' );
|
||||
}
|
||||
|
||||
if ( ! empty( $updated_message ) ) {
|
||||
echo sprintf(
|
||||
'<div id="message" class="notice notice-success"><p>%s</p></div>',
|
||||
esc_html( $updated_message )
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'failed' === $_REQUEST['message'] ) {
|
||||
$updated_message =
|
||||
__( "There was an error saving the contact form.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div id="message" class="notice notice-error"><p>%s</p></div>',
|
||||
esc_html( $updated_message )
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'validated' === $_REQUEST['message'] ) {
|
||||
$bulk_validate = WPCF7::get_option( 'bulk_validate', array() );
|
||||
$count_invalid = isset( $bulk_validate['count_invalid'] )
|
||||
? absint( $bulk_validate['count_invalid'] ) : 0;
|
||||
|
||||
if ( $count_invalid ) {
|
||||
$updated_message = sprintf(
|
||||
_n(
|
||||
/* translators: %s: number of contact forms */
|
||||
"Configuration validation completed. %s invalid contact form was found.",
|
||||
"Configuration validation completed. %s invalid contact forms were found.",
|
||||
$count_invalid, 'contact-form-7'
|
||||
),
|
||||
number_format_i18n( $count_invalid )
|
||||
);
|
||||
|
||||
echo sprintf(
|
||||
'<div id="message" class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( $updated_message )
|
||||
);
|
||||
} else {
|
||||
$updated_message = __( "Configuration validation completed. No invalid contact form was found.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div id="message" class="notice notice-success"><p>%s</p></div>',
|
||||
esc_html( $updated_message )
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_filter( 'plugin_action_links', 'wpcf7_plugin_action_links', 10, 2 );
|
||||
|
||||
function wpcf7_plugin_action_links( $links, $file ) {
|
||||
if ( $file != WPCF7_PLUGIN_BASENAME ) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_read_contact_forms' ) ) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
$settings_link = wpcf7_link(
|
||||
menu_page_url( 'wpcf7', false ),
|
||||
__( 'Settings', 'contact-form-7' )
|
||||
);
|
||||
|
||||
array_unshift( $links, $settings_link );
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_old_wp_version_error', 10, 3 );
|
||||
|
||||
function wpcf7_old_wp_version_error( $page, $action, $object ) {
|
||||
$wp_version = get_bloginfo( 'version' );
|
||||
|
||||
if ( ! version_compare( $wp_version, WPCF7_REQUIRED_WP_VERSION, '<' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="notice notice-warning">
|
||||
<p><?php
|
||||
echo sprintf(
|
||||
/* translators: 1: version of Contact Form 7, 2: version of WordPress, 3: URL */
|
||||
__( '<strong>Contact Form 7 %1$s requires WordPress %2$s or higher.</strong> Please <a href="%3$s">update WordPress</a> first.', 'contact-form-7' ),
|
||||
WPCF7_VERSION,
|
||||
WPCF7_REQUIRED_WP_VERSION,
|
||||
admin_url( 'update-core.php' )
|
||||
);
|
||||
?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_not_allowed_to_edit', 10, 3 );
|
||||
|
||||
function wpcf7_not_allowed_to_edit( $page, $action, $object ) {
|
||||
if ( $object instanceof WPCF7_ContactForm ) {
|
||||
$contact_form = $object;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $contact_form->id() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = __( "You are not allowed to edit this contact form.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( $message )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_outdated_php_warning', 10, 3 );
|
||||
|
||||
function wpcf7_outdated_php_warning( $page, $action, $object ) {
|
||||
if ( ! version_compare( PHP_VERSION, '7.4', '<' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = __( "The next major release of Contact Form 7 will discontinue support for outdated PHP versions. If you don't upgrade PHP, you will not be able to upgrade the plugin.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( $message )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_ctct_deprecated_warning', 10, 3 );
|
||||
|
||||
function wpcf7_ctct_deprecated_warning( $page, $action, $object ) {
|
||||
$service = WPCF7_ConstantContact::get_instance();
|
||||
|
||||
if ( ! $service->is_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = __( "The Constant Contact integration is deprecated. It is not recommended to continue using the feature.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( $message )
|
||||
);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Tabs
|
||||
*/
|
||||
#contact-form-editor-tabs {
|
||||
padding: 9px 10px 0 15px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Form Tab
|
||||
*/
|
||||
.tag-generator-panel {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box > fieldset > legend {
|
||||
border: 1px solid #dfdfdf;
|
||||
border-right: 4px solid #00a0d2;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box input.tag {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box .submitbox input[type="button"] {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mail Tab
|
||||
*/
|
||||
.contact-form-editor-box-mail span.mailtag {
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Welcome Panel
|
||||
*/
|
||||
.wpcf7-welcome-panel .welcome-panel-close {
|
||||
left: 10px;
|
||||
right: auto;
|
||||
padding: 10px 21px 10px 15px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close::before {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-content {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
float: right;
|
||||
padding: 0 0 0 2%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Integration
|
||||
*/
|
||||
.card {
|
||||
border-left: 1px solid #e5e5e5;
|
||||
border-right: 4px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.card img.icon {
|
||||
float: right;
|
||||
margin: 8px -8px 8px 8px;
|
||||
}
|
||||
|
||||
.card h2.title {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.card .infobox {
|
||||
float: left;
|
||||
}
|
||||
@@ -1,512 +0,0 @@
|
||||
#titlediv .inside p.description {
|
||||
margin: 8px 2px 0;
|
||||
}
|
||||
|
||||
#titlediv .inside p.description label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span.shortcode {
|
||||
display: block;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
span.shortcode.old {
|
||||
background: #777;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
span.shortcode input {
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-list-table span.shortcode input,
|
||||
#wpcf7-contact-form-editor span.shortcode input {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-list-table span.shortcode input {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-editor span.shortcode input {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#submitpost input.copy {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#submitpost input.delete {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: inherit;
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
#submitpost input.delete:hover {
|
||||
color: #dc3232; /* Red */
|
||||
}
|
||||
|
||||
#submitpost input.delete:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
.postbox-container .postbox h3 {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
.keyboard-interaction {
|
||||
visibility: hidden;
|
||||
color: #23282d; /* Dark Gray 800 */
|
||||
}
|
||||
|
||||
div.config-error, span.config-error, ul.config-error {
|
||||
color: #444;
|
||||
font-style: normal;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
ul.config-error {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
ul.config-error li {
|
||||
list-style: none;
|
||||
padding: 2px 2px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
[data-config-field][aria-invalid="true"] {
|
||||
border-color: #dc3232;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li a .icon-in-circle,
|
||||
#contact-form-editor .config-error .icon-in-circle,
|
||||
.wp-list-table .config-error .icon-in-circle,
|
||||
.icon-in-circle {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
margin: 1px 6px 0;
|
||||
padding: 0 5px;
|
||||
min-width: 7px;
|
||||
height: 17px;
|
||||
border-radius: 11px;
|
||||
background-color: #ca4a1f;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
z-index: 26;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs
|
||||
*/
|
||||
#contact-form-editor-tabs {
|
||||
border-bottom: 1px solid #aaa;
|
||||
padding: 9px 15px 0 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: 1px solid #aaa;
|
||||
padding: 0;
|
||||
margin: 0 4px -1px;
|
||||
background-color: #e4e4e4;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li.ui-tabs-active,
|
||||
#contact-form-editor-tabs li.ui-tabs-active:hover {
|
||||
border-top: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li a {
|
||||
padding: 6px 10px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 30px;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li.ui-tabs-active a {
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel > div.config-error {
|
||||
margin-bottom: 1.4em;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs li.ui-tabs-active a .icon-in-circle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
margin: 8px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #aaa;
|
||||
border-top: none;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#contact-form-editor .form-table th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel fieldset legend {
|
||||
line-height: 1.5;
|
||||
margin: .6em 0 .4em;
|
||||
}
|
||||
|
||||
/*
|
||||
* Form Tab
|
||||
*/
|
||||
#tag-generator-list a.button {
|
||||
font-size: 12px;
|
||||
height: 26px;
|
||||
line-height: 24px;
|
||||
margin: 2px;
|
||||
padding: 0 8px 1px;
|
||||
}
|
||||
|
||||
.tag-generator-panel {
|
||||
height: 495px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box > fieldset > legend {
|
||||
border: 1px solid #dfdfdf;
|
||||
border-left: 4px solid #00a0d2;
|
||||
background: #f7fcfe;
|
||||
padding: 4px 12px;
|
||||
margin: 4px 0;
|
||||
line-height: 1.4em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tag-generator-panel table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tag-generator-panel table.form-table th {
|
||||
width: 120px;
|
||||
padding: 4px 10px 4px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag-generator-panel table.form-table td {
|
||||
padding: 4px 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input.oneline {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input.large-text {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box textarea.values {
|
||||
width: 200px;
|
||||
height: 6em;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box input[type="number"],
|
||||
.tag-generator-panel .control-box input[type="date"] {
|
||||
width: 88px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box table caption {
|
||||
text-align: left;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
color: #777;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box table.form-table td label {
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
.tag-generator-panel .control-box table.form-table td label .description {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box {
|
||||
margin: 0 -15px -15px;
|
||||
padding: 8px 16px;
|
||||
background-color: #fcfcfc;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box input.tag {
|
||||
width: 510px;
|
||||
float: left;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box .submitbox {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box .submitbox input[type="button"] {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.tag-generator-panel .insert-box .description label {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mail Tab
|
||||
*/
|
||||
.contact-form-editor-box-mail span.mailtag {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 4px;
|
||||
padding: 1px 2px;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.contact-form-editor-box-mail span.mailtag.used {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.contact-form-editor-box-mail span.mailtag.unused {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
* Messages Tab
|
||||
*/
|
||||
#messages-panel p.description {
|
||||
margin: 5px 0 10px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs for integration modules
|
||||
*/
|
||||
#ctct-panel table tr.inactive ~ tr,
|
||||
#sendinblue-panel table tr.inactive ~ tr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ctct-panel .dashicons,
|
||||
#sendinblue-panel .dashicons {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#ctct-panel td p,
|
||||
#sendinblue-panel td p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
* List Table
|
||||
*/
|
||||
.fixed .column-title {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
.fixed .column-shortcode {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Welcome Panel
|
||||
*/
|
||||
.wpcf7-welcome-panel {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
margin: 16px 0;
|
||||
padding: 23px 10px 0;
|
||||
border: 1px solid #c3c4c7;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 2.1em;
|
||||
margin: 1em 0 1.2em;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel h3 .dashicons {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
color: #575757;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel p {
|
||||
color: #646970;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel p a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
padding: 10px 15px 10px 21px;
|
||||
font-size: 13px;
|
||||
line-height: 1.23076923; /* Chrome rounding, needs to be 16px equivalent */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close::before {
|
||||
background: 0 0;
|
||||
color: #787c82;
|
||||
content: "\f153";
|
||||
display: block;
|
||||
font: normal 16px/20px dashicons;
|
||||
speak: never;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 0;
|
||||
transition: all .1s ease-in-out;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-content {
|
||||
display: block;
|
||||
margin-left: 13px;
|
||||
max-width: 1500px;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column-container {
|
||||
clear: both;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
display: block;
|
||||
width: 48%;
|
||||
min-width: 200px;
|
||||
float: left;
|
||||
padding: 0 2% 0 0;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 870px) {
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column p {
|
||||
margin-top: 7px;
|
||||
color: #3c434a;
|
||||
}
|
||||
|
||||
/*
|
||||
* Integration
|
||||
*/
|
||||
.card {
|
||||
background: #fff none repeat scroll 0 0;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-left: 4px solid #e5e5e5;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||
margin-top: 20px;
|
||||
max-width: 520px;
|
||||
min-width: 255px;
|
||||
padding: 0.7em 2em 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card.active {
|
||||
border-color: #00a0d2;
|
||||
}
|
||||
|
||||
.card img.icon {
|
||||
float: left;
|
||||
margin: 8px 8px 8px -8px;
|
||||
}
|
||||
|
||||
.card h2.title {
|
||||
float: left;
|
||||
max-width: 240px;
|
||||
font-size: 1.3em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.card .infobox {
|
||||
float: right;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin: 1em;
|
||||
line-height: 1.5;
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
.card .inside .form-table th {
|
||||
padding: 15px 10px 15px 0;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.card .inside .form-table td {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
.card .checkboxes li {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,301 +0,0 @@
|
||||
<?php
|
||||
|
||||
// don't load directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( '-1' );
|
||||
}
|
||||
|
||||
function wpcf7_admin_save_button( $post_id ) {
|
||||
static $button = '';
|
||||
|
||||
if ( ! empty( $button ) ) {
|
||||
echo $button;
|
||||
return;
|
||||
}
|
||||
|
||||
$nonce = wp_create_nonce( 'wpcf7-save-contact-form_' . $post_id );
|
||||
|
||||
$onclick = sprintf(
|
||||
"this.form._wpnonce.value = '%s';"
|
||||
. " this.form.action.value = 'save';"
|
||||
. " return true;",
|
||||
$nonce );
|
||||
|
||||
$button = sprintf(
|
||||
'<input type="submit" class="button-primary" name="wpcf7-save" value="%1$s" onclick="%2$s" />',
|
||||
esc_attr( __( 'Save', 'contact-form-7' ) ),
|
||||
$onclick );
|
||||
|
||||
echo $button;
|
||||
}
|
||||
|
||||
?><div class="wrap" id="wpcf7-contact-form-editor">
|
||||
|
||||
<h1 class="wp-heading-inline"><?php
|
||||
if ( $post->initial() ) {
|
||||
echo esc_html( __( 'Add New Contact Form', 'contact-form-7' ) );
|
||||
} else {
|
||||
echo esc_html( __( 'Edit Contact Form', 'contact-form-7' ) );
|
||||
}
|
||||
?></h1>
|
||||
|
||||
<?php
|
||||
if ( ! $post->initial()
|
||||
and current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
echo wpcf7_link(
|
||||
menu_page_url( 'wpcf7-new', false ),
|
||||
__( 'Add New', 'contact-form-7' ),
|
||||
array( 'class' => 'page-title-action' )
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<hr class="wp-header-end">
|
||||
|
||||
<?php
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
$post->initial() ? 'wpcf7-new' : 'wpcf7',
|
||||
wpcf7_current_action(),
|
||||
$post
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
$post->initial() ? 'wpcf7-new' : 'wpcf7',
|
||||
wpcf7_current_action(),
|
||||
$post
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
if ( $post ) :
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$disabled = '';
|
||||
} else {
|
||||
$disabled = ' disabled="disabled"';
|
||||
}
|
||||
?>
|
||||
|
||||
<form method="post" action="<?php echo esc_url( add_query_arg( array( 'post' => $post_id ), menu_page_url( 'wpcf7', false ) ) ); ?>" id="wpcf7-admin-form-element"<?php do_action( 'wpcf7_post_edit_form_tag' ); ?>>
|
||||
<?php
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
wp_nonce_field( 'wpcf7-save-contact-form_' . $post_id );
|
||||
}
|
||||
?>
|
||||
<input type="hidden" id="post_ID" name="post_ID" value="<?php echo (int) $post_id; ?>" />
|
||||
<input type="hidden" id="wpcf7-locale" name="wpcf7-locale" value="<?php echo esc_attr( $post->locale() ); ?>" />
|
||||
<input type="hidden" id="hiddenaction" name="action" value="save" />
|
||||
<input type="hidden" id="active-tab" name="active-tab" value="<?php echo (int) ( $_GET['active-tab'] ?? '0' ); ?>" />
|
||||
|
||||
<div id="poststuff">
|
||||
<div id="post-body" class="metabox-holder columns-2">
|
||||
<div id="post-body-content">
|
||||
<div id="titlediv">
|
||||
<div id="titlewrap">
|
||||
<label class="screen-reader-text" id="title-prompt-text" for="title"><?php echo esc_html( __( 'Enter title here', 'contact-form-7' ) ); ?></label>
|
||||
<?php
|
||||
$posttitle_atts = array(
|
||||
'type' => 'text',
|
||||
'name' => 'post_title',
|
||||
'size' => 30,
|
||||
'value' => $post->initial() ? '' : $post->title(),
|
||||
'id' => 'title',
|
||||
'spellcheck' => 'true',
|
||||
'autocomplete' => 'off',
|
||||
'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
|
||||
);
|
||||
|
||||
echo sprintf( '<input %s />', wpcf7_format_atts( $posttitle_atts ) );
|
||||
?>
|
||||
</div><!-- #titlewrap -->
|
||||
|
||||
<div class="inside">
|
||||
<?php
|
||||
if ( ! $post->initial() ) :
|
||||
?>
|
||||
<p class="description">
|
||||
<label for="wpcf7-shortcode"><?php echo esc_html( __( "Copy this shortcode and paste it into your post, page, or text widget content:", 'contact-form-7' ) ); ?></label>
|
||||
<span class="shortcode wp-ui-highlight"><input type="text" id="wpcf7-shortcode" onfocus="this.select();" readonly="readonly" class="large-text code" value="<?php echo esc_attr( $post->shortcode() ); ?>" /></span>
|
||||
</p>
|
||||
<?php
|
||||
if ( $old_shortcode = $post->shortcode( array( 'use_old_format' => true ) ) ) :
|
||||
?>
|
||||
<p class="description">
|
||||
<label for="wpcf7-shortcode-old"><?php echo esc_html( __( "You can also use this old-style shortcode:", 'contact-form-7' ) ); ?></label>
|
||||
<span class="shortcode old"><input type="text" id="wpcf7-shortcode-old" onfocus="this.select();" readonly="readonly" class="large-text code" value="<?php echo esc_attr( $old_shortcode ); ?>" /></span>
|
||||
</p>
|
||||
<?php
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
</div><!-- #titlediv -->
|
||||
</div><!-- #post-body-content -->
|
||||
|
||||
<div id="postbox-container-1" class="postbox-container">
|
||||
<?php if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) : ?>
|
||||
<div id="submitdiv" class="postbox">
|
||||
<h3><?php echo esc_html( __( 'Status', 'contact-form-7' ) ); ?></h3>
|
||||
<div class="inside">
|
||||
<div class="submitbox" id="submitpost">
|
||||
|
||||
<div id="minor-publishing-actions">
|
||||
|
||||
<div class="hidden">
|
||||
<input type="submit" class="button-primary" name="wpcf7-save" value="<?php echo esc_attr( __( 'Save', 'contact-form-7' ) ); ?>" />
|
||||
</div>
|
||||
|
||||
<?php
|
||||
if ( ! $post->initial() ) :
|
||||
$copy_nonce = wp_create_nonce( 'wpcf7-copy-contact-form_' . $post_id );
|
||||
?>
|
||||
<input type="submit" name="wpcf7-copy" class="copy button" value="<?php echo esc_attr( __( 'Duplicate', 'contact-form-7' ) ); ?>" <?php echo "onclick=\"this.form._wpnonce.value = '$copy_nonce'; this.form.action.value = 'copy'; return true;\""; ?> />
|
||||
<?php endif; ?>
|
||||
</div><!-- #minor-publishing-actions -->
|
||||
|
||||
<div id="misc-publishing-actions">
|
||||
<?php do_action( 'wpcf7_admin_misc_pub_section', $post_id ); ?>
|
||||
</div><!-- #misc-publishing-actions -->
|
||||
|
||||
<div id="major-publishing-actions">
|
||||
|
||||
<?php
|
||||
if ( ! $post->initial() ) :
|
||||
$delete_nonce = wp_create_nonce( 'wpcf7-delete-contact-form_' . $post_id );
|
||||
?>
|
||||
<div id="delete-action">
|
||||
<input type="submit" name="wpcf7-delete" class="delete submitdelete" value="<?php echo esc_attr( __( 'Delete', 'contact-form-7' ) ); ?>" <?php echo "onclick=\"if (confirm('" . esc_js( __( "You are about to delete this contact form.\n 'Cancel' to stop, 'OK' to delete.", 'contact-form-7' ) ) . "')) {this.form._wpnonce.value = '$delete_nonce'; this.form.action.value = 'delete'; return true;} return false;\""; ?> />
|
||||
</div><!-- #delete-action -->
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="publishing-action">
|
||||
<span class="spinner"></span>
|
||||
<?php wpcf7_admin_save_button( $post_id ); ?>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div><!-- #major-publishing-actions -->
|
||||
</div><!-- #submitpost -->
|
||||
</div>
|
||||
</div><!-- #submitdiv -->
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="informationdiv" class="postbox">
|
||||
<h3><?php echo esc_html( __( "Do you need help?", 'contact-form-7' ) ); ?></h3>
|
||||
<div class="inside">
|
||||
<p><?php echo esc_html( __( "Here are some available options to help solve your problems.", 'contact-form-7' ) ); ?></p>
|
||||
<ol>
|
||||
<li><?php echo sprintf(
|
||||
/* translators: 1: FAQ, 2: Docs ("FAQ & Docs") */
|
||||
__( '%1$s and %2$s', 'contact-form-7' ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/faq/', 'contact-form-7' ),
|
||||
__( 'FAQ', 'contact-form-7' )
|
||||
),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/docs/', 'contact-form-7' ),
|
||||
__( 'docs', 'contact-form-7' )
|
||||
)
|
||||
); ?></li>
|
||||
<li><?php echo wpcf7_link(
|
||||
__( 'https://wordpress.org/support/plugin/contact-form-7/', 'contact-form-7' ),
|
||||
__( 'Support forums', 'contact-form-7' )
|
||||
); ?></li>
|
||||
<li><?php echo wpcf7_link(
|
||||
__( 'https://contactform7.com/custom-development/', 'contact-form-7' ),
|
||||
__( 'Professional services', 'contact-form-7' )
|
||||
); ?></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div><!-- #informationdiv -->
|
||||
|
||||
</div><!-- #postbox-container-1 -->
|
||||
|
||||
<div id="postbox-container-2" class="postbox-container">
|
||||
<div id="contact-form-editor">
|
||||
<div class="keyboard-interaction"><?php
|
||||
echo sprintf(
|
||||
/* translators: 1: ◀ ▶ dashicon, 2: screen reader text for the dashicon */
|
||||
esc_html( __( '%1$s %2$s keys switch panels', 'contact-form-7' ) ),
|
||||
'<span class="dashicons dashicons-leftright" aria-hidden="true"></span>',
|
||||
sprintf(
|
||||
'<span class="screen-reader-text">%s</span>',
|
||||
/* translators: screen reader text */
|
||||
esc_html( __( '(left and right arrow)', 'contact-form-7' ) )
|
||||
)
|
||||
);
|
||||
?></div>
|
||||
|
||||
<?php
|
||||
|
||||
$editor = new WPCF7_Editor( $post );
|
||||
$panels = array();
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$panels = array(
|
||||
'form-panel' => array(
|
||||
'title' => __( 'Form', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_form',
|
||||
),
|
||||
'mail-panel' => array(
|
||||
'title' => __( 'Mail', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_mail',
|
||||
),
|
||||
'messages-panel' => array(
|
||||
'title' => __( 'Messages', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_messages',
|
||||
),
|
||||
);
|
||||
|
||||
$additional_settings = $post->prop( 'additional_settings' );
|
||||
|
||||
if ( ! is_scalar( $additional_settings ) ) {
|
||||
$additional_settings = '';
|
||||
}
|
||||
|
||||
$additional_settings = trim( $additional_settings );
|
||||
$additional_settings = explode( "\n", $additional_settings );
|
||||
$additional_settings = array_filter( $additional_settings );
|
||||
$additional_settings = count( $additional_settings );
|
||||
|
||||
$panels['additional-settings-panel'] = array(
|
||||
'title' => $additional_settings
|
||||
? sprintf(
|
||||
/* translators: %d: number of additional settings */
|
||||
__( 'Additional Settings (%d)', 'contact-form-7' ),
|
||||
$additional_settings )
|
||||
: __( 'Additional Settings', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_additional_settings',
|
||||
);
|
||||
}
|
||||
|
||||
$panels = apply_filters( 'wpcf7_editor_panels', $panels );
|
||||
|
||||
foreach ( $panels as $id => $panel ) {
|
||||
$editor->add_panel( $id, $panel['title'], $panel['callback'] );
|
||||
}
|
||||
|
||||
$editor->display();
|
||||
?>
|
||||
</div><!-- #contact-form-editor -->
|
||||
|
||||
<?php if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) : ?>
|
||||
<p class="submit"><?php wpcf7_admin_save_button( $post_id ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
</div><!-- #postbox-container-2 -->
|
||||
|
||||
</div><!-- #post-body -->
|
||||
<br class="clear" />
|
||||
</div><!-- #poststuff -->
|
||||
</form>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</div><!-- .wrap -->
|
||||
|
||||
<?php
|
||||
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
$tag_generator->print_panels( $post );
|
||||
|
||||
do_action( 'wpcf7_admin_footer', $post );
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
function wpcf7_current_action() {
|
||||
if ( isset( $_REQUEST['action'] ) and -1 != $_REQUEST['action'] ) {
|
||||
return $_REQUEST['action'];
|
||||
}
|
||||
|
||||
if ( isset( $_REQUEST['action2'] ) and -1 != $_REQUEST['action2'] ) {
|
||||
return $_REQUEST['action2'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function wpcf7_admin_has_edit_cap() {
|
||||
return current_user_can( 'wpcf7_edit_contact_forms' );
|
||||
}
|
||||
|
||||
function wpcf7_add_tag_generator( $name, $title, $elm_id, $callback, $options = array() ) {
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
return $tag_generator->add( $name, $title, $callback, $options );
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
||||
}
|
||||
|
||||
class WPCF7_Contact_Form_List_Table extends WP_List_Table {
|
||||
|
||||
public static function define_columns() {
|
||||
$columns = array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'title' => __( 'Title', 'contact-form-7' ),
|
||||
'shortcode' => __( 'Shortcode', 'contact-form-7' ),
|
||||
'author' => __( 'Author', 'contact-form-7' ),
|
||||
'date' => __( 'Date', 'contact-form-7' ),
|
||||
);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( array(
|
||||
'singular' => 'post',
|
||||
'plural' => 'posts',
|
||||
'ajax' => false,
|
||||
) );
|
||||
}
|
||||
|
||||
public function prepare_items() {
|
||||
$current_screen = get_current_screen();
|
||||
$per_page = $this->get_items_per_page( 'wpcf7_contact_forms_per_page' );
|
||||
|
||||
$args = array(
|
||||
'posts_per_page' => $per_page,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
'offset' => ( $this->get_pagenum() - 1 ) * $per_page,
|
||||
);
|
||||
|
||||
if ( ! empty( $_REQUEST['s'] ) ) {
|
||||
$args['s'] = $_REQUEST['s'];
|
||||
}
|
||||
|
||||
if ( ! empty( $_REQUEST['orderby'] ) ) {
|
||||
if ( 'title' == $_REQUEST['orderby'] ) {
|
||||
$args['orderby'] = 'title';
|
||||
} elseif ( 'author' == $_REQUEST['orderby'] ) {
|
||||
$args['orderby'] = 'author';
|
||||
} elseif ( 'date' == $_REQUEST['orderby'] ) {
|
||||
$args['orderby'] = 'date';
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $_REQUEST['order'] ) ) {
|
||||
if ( 'asc' == strtolower( $_REQUEST['order'] ) ) {
|
||||
$args['order'] = 'ASC';
|
||||
} elseif ( 'desc' == strtolower( $_REQUEST['order'] ) ) {
|
||||
$args['order'] = 'DESC';
|
||||
}
|
||||
}
|
||||
|
||||
$this->items = WPCF7_ContactForm::find( $args );
|
||||
|
||||
$total_items = WPCF7_ContactForm::count();
|
||||
$total_pages = ceil( $total_items / $per_page );
|
||||
|
||||
$this->set_pagination_args( array(
|
||||
'total_items' => $total_items,
|
||||
'total_pages' => $total_pages,
|
||||
'per_page' => $per_page,
|
||||
) );
|
||||
}
|
||||
|
||||
public function get_columns() {
|
||||
return get_column_headers( get_current_screen() );
|
||||
}
|
||||
|
||||
protected function get_sortable_columns() {
|
||||
$columns = array(
|
||||
'title' => array( 'title', true ),
|
||||
'author' => array( 'author', false ),
|
||||
'date' => array( 'date', false ),
|
||||
);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_bulk_actions() {
|
||||
$actions = array(
|
||||
'delete' => __( 'Delete', 'contact-form-7' ),
|
||||
);
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
protected function column_default( $item, $column_name ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function column_cb( $item ) {
|
||||
return sprintf(
|
||||
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
||||
$this->_args['singular'],
|
||||
$item->id()
|
||||
);
|
||||
}
|
||||
|
||||
public function column_title( $item ) {
|
||||
$edit_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'edit',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$output = sprintf(
|
||||
'<a class="row-title" href="%1$s" aria-label="%2$s">%3$s</a>',
|
||||
esc_url( $edit_link ),
|
||||
esc_attr( sprintf(
|
||||
/* translators: %s: title of contact form */
|
||||
__( 'Edit “%s”', 'contact-form-7' ),
|
||||
$item->title()
|
||||
) ),
|
||||
esc_html( $item->title() )
|
||||
);
|
||||
|
||||
$output = sprintf( '<strong>%s</strong>', $output );
|
||||
|
||||
if ( wpcf7_validate_configuration()
|
||||
and current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $item );
|
||||
$config_validator->restore();
|
||||
|
||||
if ( $count_errors = $config_validator->count_errors() ) {
|
||||
$error_notice = sprintf(
|
||||
_n(
|
||||
/* translators: %s: number of errors detected */
|
||||
'%s configuration error detected',
|
||||
'%s configuration errors detected',
|
||||
$count_errors, 'contact-form-7' ),
|
||||
number_format_i18n( $count_errors )
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<div class="config-error"><span class="icon-in-circle" aria-hidden="true">!</span> %s</div>',
|
||||
$error_notice
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function handle_row_actions( $item, $column_name, $primary ) {
|
||||
if ( $column_name !== $primary ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$edit_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'edit',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$actions = array(
|
||||
'edit' => wpcf7_link( $edit_link, __( 'Edit', 'contact-form-7' ) ),
|
||||
);
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
|
||||
$copy_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'copy',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$copy_link = wp_nonce_url(
|
||||
$copy_link,
|
||||
'wpcf7-copy-contact-form_' . absint( $item->id() )
|
||||
);
|
||||
|
||||
$actions = array_merge( $actions, array(
|
||||
'copy' => wpcf7_link( $copy_link, __( 'Duplicate', 'contact-form-7' ) ),
|
||||
) );
|
||||
}
|
||||
|
||||
return $this->row_actions( $actions );
|
||||
}
|
||||
|
||||
public function column_author( $item ) {
|
||||
$post = get_post( $item->id() );
|
||||
|
||||
if ( ! $post ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$author = get_userdata( $post->post_author );
|
||||
|
||||
if ( false === $author ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return esc_html( $author->display_name );
|
||||
}
|
||||
|
||||
public function column_shortcode( $item ) {
|
||||
$shortcodes = array( $item->shortcode() );
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ( $shortcodes as $shortcode ) {
|
||||
$output .= "\n" . '<span class="shortcode"><input type="text"'
|
||||
. ' onfocus="this.select();" readonly="readonly"'
|
||||
. ' value="' . esc_attr( $shortcode ) . '"'
|
||||
. ' class="large-text code" /></span>';
|
||||
}
|
||||
|
||||
return trim( $output );
|
||||
}
|
||||
|
||||
public function column_date( $item ) {
|
||||
$datetime = get_post_datetime( $item->id() );
|
||||
|
||||
if ( false === $datetime ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$t_time = sprintf(
|
||||
/* translators: 1: date, 2: time */
|
||||
__( '%1$s at %2$s', 'contact-form-7' ),
|
||||
/* translators: date format, see https://www.php.net/date */
|
||||
$datetime->format( __( 'Y/m/d', 'contact-form-7' ) ),
|
||||
/* translators: time format, see https://www.php.net/date */
|
||||
$datetime->format( __( 'g:i a', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
return $t_time;
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
<?php
|
||||
|
||||
add_action( 'wpcf7_admin_menu', 'wpcf7_admin_init_bulk_cv', 10, 0 );
|
||||
|
||||
function wpcf7_admin_init_bulk_cv() {
|
||||
if ( ! wpcf7_validate_configuration()
|
||||
or ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = WPCF7::get_option( 'bulk_validate' );
|
||||
$last_important_update = WPCF7_ConfigValidator::last_important_update;
|
||||
|
||||
if ( ! empty( $result['version'] )
|
||||
and version_compare( $last_important_update, $result['version'], '<=' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'wpcf7_admin_menu_change_notice',
|
||||
'wpcf7_admin_menu_change_notice_bulk_cv',
|
||||
10, 1
|
||||
);
|
||||
|
||||
add_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7_admin_warnings_bulk_cv',
|
||||
5, 3
|
||||
);
|
||||
}
|
||||
|
||||
function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
|
||||
$counts['wpcf7'] += 1;
|
||||
return $counts;
|
||||
}
|
||||
|
||||
function wpcf7_admin_warnings_bulk_cv( $page, $action, $object ) {
|
||||
if ( 'wpcf7' === $page and 'validate' === $action ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$link = wpcf7_link(
|
||||
add_query_arg(
|
||||
array( 'action' => 'validate' ),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
),
|
||||
__( 'Validate Contact Form 7 Configuration', 'contact-form-7' )
|
||||
);
|
||||
|
||||
$message = __( "Misconfiguration leads to mail delivery failure or other troubles. Validate your contact forms now.", 'contact-form-7' );
|
||||
|
||||
echo sprintf(
|
||||
'<div class="notice notice-warning"><p>%1$s » %2$s</p></div>',
|
||||
esc_html( $message ),
|
||||
$link
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'wpcf7_admin_load', 'wpcf7_load_bulk_validate_page', 10, 2 );
|
||||
|
||||
function wpcf7_load_bulk_validate_page( $page, $action ) {
|
||||
if ( 'wpcf7' != $page
|
||||
or 'validate' != $action
|
||||
or ! wpcf7_validate_configuration()
|
||||
or 'POST' != $_SERVER['REQUEST_METHOD'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_admin_referer( 'wpcf7-bulk-validate' );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
wp_die( __( "You are not allowed to validate configuration.", 'contact-form-7' ) );
|
||||
}
|
||||
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
|
||||
$result = array(
|
||||
'timestamp' => time(),
|
||||
'version' => WPCF7_VERSION,
|
||||
'count_valid' => 0,
|
||||
'count_invalid' => 0,
|
||||
);
|
||||
|
||||
foreach ( $contact_forms as $contact_form ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form );
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
|
||||
if ( $config_validator->is_valid() ) {
|
||||
$result['count_valid'] += 1;
|
||||
} else {
|
||||
$result['count_invalid'] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
WPCF7::update_option( 'bulk_validate', $result );
|
||||
|
||||
$redirect_to = add_query_arg(
|
||||
array(
|
||||
'message' => 'validated',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
function wpcf7_admin_bulk_validate_page() {
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
$count = WPCF7_ContactForm::count();
|
||||
|
||||
$submit_text = sprintf(
|
||||
_n(
|
||||
/* translators: %s: number of contact forms */
|
||||
"Validate %s contact form now",
|
||||
"Validate %s contact forms now",
|
||||
$count, 'contact-form-7'
|
||||
),
|
||||
number_format_i18n( $count )
|
||||
);
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
|
||||
<h1><?php echo esc_html( __( 'Validate Configuration', 'contact-form-7' ) ); ?></h1>
|
||||
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="action" value="validate" />
|
||||
<?php wp_nonce_field( 'wpcf7-bulk-validate' ); ?>
|
||||
<p><input type="submit" class="button" value="<?php echo esc_attr( $submit_text ); ?>" /></p>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
echo wpcf7_link(
|
||||
__( 'https://contactform7.com/configuration-validator-faq/', 'contact-form-7' ),
|
||||
__( 'FAQ about Configuration Validator', 'contact-form-7' )
|
||||
);
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_Editor {
|
||||
|
||||
private $contact_form;
|
||||
private $panels = array();
|
||||
|
||||
public function __construct( WPCF7_ContactForm $contact_form ) {
|
||||
$this->contact_form = $contact_form;
|
||||
}
|
||||
|
||||
public function add_panel( $panel_id, $title, $callback ) {
|
||||
if ( wpcf7_is_name( $panel_id ) ) {
|
||||
$this->panels[$panel_id] = array(
|
||||
'title' => $title,
|
||||
'callback' => $callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function display() {
|
||||
if ( empty( $this->panels ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<ul id="contact-form-editor-tabs">';
|
||||
|
||||
foreach ( $this->panels as $panel_id => $panel ) {
|
||||
echo sprintf(
|
||||
'<li id="%1$s-tab"><a href="#%1$s">%2$s</a></li>',
|
||||
esc_attr( $panel_id ),
|
||||
esc_html( $panel['title'] )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
|
||||
foreach ( $this->panels as $panel_id => $panel ) {
|
||||
echo sprintf(
|
||||
'<div class="contact-form-editor-panel" id="%1$s">',
|
||||
esc_attr( $panel_id )
|
||||
);
|
||||
|
||||
if ( is_callable( $panel['callback'] ) ) {
|
||||
$this->notice( $panel_id, $panel );
|
||||
call_user_func( $panel['callback'], $this->contact_form );
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
public function notice( $panel_id, $panel ) {
|
||||
echo '<div class="config-error"></div>';
|
||||
}
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_form( $post ) {
|
||||
$desc_link = wpcf7_link(
|
||||
__( 'https://contactform7.com/editing-form-template/', 'contact-form-7' ),
|
||||
__( 'Editing form template', 'contact-form-7' ) );
|
||||
$description = __( "You can edit the form template here. For details, see %s.", 'contact-form-7' );
|
||||
$description = sprintf( esc_html( $description ), $desc_link );
|
||||
?>
|
||||
|
||||
<h2><?php echo esc_html( __( 'Form', 'contact-form-7' ) ); ?></h2>
|
||||
|
||||
<fieldset>
|
||||
<legend><?php echo $description; ?></legend>
|
||||
|
||||
<?php
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
$tag_generator->print_buttons();
|
||||
?>
|
||||
|
||||
<textarea id="wpcf7-form" name="wpcf7-form" cols="100" rows="24" class="large-text code" data-config-field="form.body"><?php echo esc_textarea( $post->prop( 'form' ) ); ?></textarea>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_mail( $post ) {
|
||||
wpcf7_editor_box_mail( $post );
|
||||
|
||||
echo '<br class="clear" />';
|
||||
|
||||
wpcf7_editor_box_mail( $post, array(
|
||||
'id' => 'wpcf7-mail-2',
|
||||
'name' => 'mail_2',
|
||||
'title' => __( 'Mail (2)', 'contact-form-7' ),
|
||||
'use' => __( 'Use Mail (2)', 'contact-form-7' ),
|
||||
) );
|
||||
}
|
||||
|
||||
function wpcf7_editor_box_mail( $post, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'id' => 'wpcf7-mail',
|
||||
'name' => 'mail',
|
||||
'title' => __( 'Mail', 'contact-form-7' ),
|
||||
'use' => null,
|
||||
) );
|
||||
|
||||
$id = esc_attr( $args['id'] );
|
||||
|
||||
$mail = wp_parse_args( $post->prop( $args['name'] ), array(
|
||||
'active' => false,
|
||||
'recipient' => '',
|
||||
'sender' => '',
|
||||
'subject' => '',
|
||||
'body' => '',
|
||||
'additional_headers' => '',
|
||||
'attachments' => '',
|
||||
'use_html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
?>
|
||||
<div class="contact-form-editor-box-mail" id="<?php echo $id; ?>">
|
||||
<h2><?php echo esc_html( $args['title'] ); ?></h2>
|
||||
|
||||
<?php
|
||||
if ( ! empty( $args['use'] ) ) :
|
||||
?>
|
||||
<label for="<?php echo $id; ?>-active"><input type="checkbox" id="<?php echo $id; ?>-active" name="<?php echo $id; ?>[active]" data-config-field="" class="toggle-form-table" value="1"<?php echo ( $mail['active'] ) ? ' checked="checked"' : ''; ?> /> <?php echo esc_html( $args['use'] ); ?></label>
|
||||
<p class="description"><?php echo esc_html( __( "Mail (2) is an additional mail template often used as an autoresponder.", 'contact-form-7' ) ); ?></p>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
<fieldset>
|
||||
<legend>
|
||||
<?php
|
||||
$desc_link = wpcf7_link(
|
||||
__( 'https://contactform7.com/setting-up-mail/', 'contact-form-7' ),
|
||||
__( 'Setting up mail', 'contact-form-7' ) );
|
||||
$description = __( "You can edit the mail template here. For details, see %s.", 'contact-form-7' );
|
||||
$description = sprintf( esc_html( $description ), $desc_link );
|
||||
echo $description;
|
||||
echo '<br />';
|
||||
|
||||
echo esc_html( __( "In the following fields, you can use these mail-tags:",
|
||||
'contact-form-7' ) );
|
||||
echo '<br />';
|
||||
$post->suggest_mail_tags( $args['name'] );
|
||||
?>
|
||||
</legend>
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-recipient"><?php echo esc_html( __( 'To', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" id="<?php echo $id; ?>-recipient" name="<?php echo $id; ?>[recipient]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['recipient'] ); ?>" data-config-field="<?php echo sprintf( '%s.recipient', esc_attr( $args['name'] ) ); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-sender"><?php echo esc_html( __( 'From', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" id="<?php echo $id; ?>-sender" name="<?php echo $id; ?>[sender]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['sender'] ); ?>" data-config-field="<?php echo sprintf( '%s.sender', esc_attr( $args['name'] ) ); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-subject"><?php echo esc_html( __( 'Subject', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" id="<?php echo $id; ?>-subject" name="<?php echo $id; ?>[subject]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['subject'] ); ?>" data-config-field="<?php echo sprintf( '%s.subject', esc_attr( $args['name'] ) ); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-additional-headers"><?php echo esc_html( __( 'Additional headers', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="<?php echo $id; ?>-additional-headers" name="<?php echo $id; ?>[additional_headers]" cols="100" rows="4" class="large-text code" data-config-field="<?php echo sprintf( '%s.additional_headers', esc_attr( $args['name'] ) ); ?>"><?php echo esc_textarea( $mail['additional_headers'] ); ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-body"><?php echo esc_html( __( 'Message body', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="<?php echo $id; ?>-body" name="<?php echo $id; ?>[body]" cols="100" rows="18" class="large-text code" data-config-field="<?php echo sprintf( '%s.body', esc_attr( $args['name'] ) ); ?>"><?php echo esc_textarea( $mail['body'] ); ?></textarea>
|
||||
|
||||
<p><label for="<?php echo $id; ?>-exclude-blank"><input type="checkbox" id="<?php echo $id; ?>-exclude-blank" name="<?php echo $id; ?>[exclude_blank]" value="1"<?php echo ( ! empty( $mail['exclude_blank'] ) ) ? ' checked="checked"' : ''; ?> /> <?php echo esc_html( __( 'Exclude lines with blank mail-tags from output', 'contact-form-7' ) ); ?></label></p>
|
||||
|
||||
<p><label for="<?php echo $id; ?>-use-html"><input type="checkbox" id="<?php echo $id; ?>-use-html" name="<?php echo $id; ?>[use_html]" value="1"<?php echo ( $mail['use_html'] ) ? ' checked="checked"' : ''; ?> /> <?php echo esc_html( __( 'Use HTML content type', 'contact-form-7' ) ); ?></label></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="<?php echo $id; ?>-attachments"><?php echo esc_html( __( 'File attachments', 'contact-form-7' ) ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="<?php echo $id; ?>-attachments" name="<?php echo $id; ?>[attachments]" cols="100" rows="4" class="large-text code" data-config-field="<?php echo sprintf( '%s.attachments', esc_attr( $args['name'] ) ); ?>"><?php echo esc_textarea( $mail['attachments'] ); ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_messages( $post ) {
|
||||
$desc_link = wpcf7_link(
|
||||
__( 'https://contactform7.com/editing-messages/', 'contact-form-7' ),
|
||||
__( 'Editing messages', 'contact-form-7' ) );
|
||||
$description = __( "You can edit messages used in various situations here. For details, see %s.", 'contact-form-7' );
|
||||
$description = sprintf( esc_html( $description ), $desc_link );
|
||||
|
||||
$messages = wpcf7_messages();
|
||||
|
||||
if ( isset( $messages['captcha_not_match'] )
|
||||
and ! wpcf7_use_really_simple_captcha() ) {
|
||||
unset( $messages['captcha_not_match'] );
|
||||
}
|
||||
|
||||
?>
|
||||
<h2><?php echo esc_html( __( 'Messages', 'contact-form-7' ) ); ?></h2>
|
||||
<fieldset>
|
||||
<legend><?php echo $description; ?></legend>
|
||||
<?php
|
||||
|
||||
foreach ( $messages as $key => $arr ) {
|
||||
$field_id = sprintf( 'wpcf7-message-%s', strtr( $key, '_', '-' ) );
|
||||
$field_name = sprintf( 'wpcf7-messages[%s]', $key );
|
||||
|
||||
?>
|
||||
<p class="description">
|
||||
<label for="<?php echo $field_id; ?>"><?php echo esc_html( $arr['description'] ); ?><br />
|
||||
<input type="text" id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" class="large-text" size="70" value="<?php echo esc_attr( $post->message( $key, false ) ); ?>" data-config-field="<?php echo sprintf( 'messages.%s', esc_attr( $key ) ); ?>" />
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_additional_settings( $post ) {
|
||||
$desc_link = wpcf7_link(
|
||||
__( 'https://contactform7.com/additional-settings/', 'contact-form-7' ),
|
||||
__( 'Additional settings', 'contact-form-7' ) );
|
||||
$description = __( "You can add customization code snippets here. For details, see %s.", 'contact-form-7' );
|
||||
$description = sprintf( esc_html( $description ), $desc_link );
|
||||
|
||||
?>
|
||||
<h2><?php echo esc_html( __( 'Additional Settings', 'contact-form-7' ) ); ?></h2>
|
||||
<fieldset>
|
||||
<legend><?php echo $description; ?></legend>
|
||||
<textarea id="wpcf7-additional-settings" name="wpcf7-additional-settings" cols="100" rows="8" class="large-text" data-config-field="additional_settings.body"><?php echo esc_textarea( $post->prop( 'additional_settings' ) ); ?></textarea>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_Help_Tabs {
|
||||
|
||||
private $screen;
|
||||
|
||||
public function __construct( WP_Screen $screen ) {
|
||||
$this->screen = $screen;
|
||||
}
|
||||
|
||||
public function set_help_tabs( $screen_type ) {
|
||||
switch ( $screen_type ) {
|
||||
case 'list':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'list_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'list_overview' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'list_available_actions',
|
||||
'title' => __( 'Available Actions', 'contact-form-7' ),
|
||||
'content' => $this->content( 'list_available_actions' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
case 'edit':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_overview' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_form_tags',
|
||||
'title' => __( 'Form-tags', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_form_tags' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_mail_tags',
|
||||
'title' => __( 'Mail-tags', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_mail_tags' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
case 'integration':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'integration_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'integration_overview' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function content( $name ) {
|
||||
$content = array();
|
||||
|
||||
$content['list_overview'] = '<p>' . __( "On this screen, you can manage contact forms provided by Contact Form 7. You can manage an unlimited number of contact forms. Each contact form has a unique ID and Contact Form 7 shortcode ([contact-form-7 ...]). To insert a contact form into a post or a text widget, insert the shortcode into the target.", 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['list_available_actions'] = '<p>' . __( "Hovering over a row in the contact forms list will display action links that allow you to manage your contact form. You can perform the following actions:", 'contact-form-7' ) . '</p>';
|
||||
$content['list_available_actions'] .= '<p>' . __( "<strong>Edit</strong> - Navigates to the editing screen for that contact form. You can also reach that screen by clicking on the contact form title.", 'contact-form-7' ) . '</p>';
|
||||
$content['list_available_actions'] .= '<p>' . __( "<strong>Duplicate</strong> - Clones that contact form. A cloned contact form inherits all content from the original, but has a different ID.", 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_overview'] = '<p>' . __( "On this screen, you can edit a contact form. A contact form is comprised of the following components:", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "<strong>Title</strong> is the title of a contact form. This title is only used for labeling a contact form, and can be edited.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "<strong>Form</strong> is a content of HTML form. You can use arbitrary HTML, which is allowed inside a form element. You can also use Contact Form 7’s form-tags here.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "<strong>Mail</strong> manages a mail template (headers and message body) that this contact form will send when users submit it. You can use Contact Form 7’s mail-tags here.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "<strong>Mail (2)</strong> is an additional mail template that works similar to Mail. Mail (2) is different in that it is sent only when Mail has been sent successfully.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "In <strong>Messages</strong>, you can edit various types of messages used for this contact form. These messages are relatively short messages, like a validation error message you see when you leave a required field blank.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( "<strong>Additional Settings</strong> provides a place where you can customize the behavior of this contact form by adding code snippets.", 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_form_tags'] = '<p>' . __( "A form-tag is a short code enclosed in square brackets used in a form content. A form-tag generally represents an input field, and its components can be separated into four parts: type, name, options, and values. Contact Form 7 supports several types of form-tags including text fields, number fields, date fields, checkboxes, radio buttons, menus, file-uploading fields, CAPTCHAs, and quiz fields.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_form_tags'] .= '<p>' . __( "While form-tags have a comparatively complex syntax, you do not need to know the syntax to add form-tags because you can use the straightforward tag generator (<strong>Generate Tag</strong> button on this screen).", 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_mail_tags'] = '<p>' . __( "A mail-tag is also a short code enclosed in square brackets that you can use in every Mail and Mail (2) field. A mail-tag represents a user input value through an input field of a corresponding form-tag.", 'contact-form-7' ) . '</p>';
|
||||
$content['edit_mail_tags'] .= '<p>' . __( "There are also special mail-tags that have specific names, but do not have corresponding form-tags. They are used to represent meta information of form submissions like the submitter’s IP address or the URL of the page.", 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['integration_overview'] = '<p>' . __( "On this screen, you can manage services that are available through Contact Form 7. Using API will allow you to collaborate with any services that are available.", 'contact-form-7' ) . '</p>';
|
||||
$content['integration_overview'] .= '<p>' . __( "You may need to first sign up for an account with the service that you plan to use. When you do so, you would need to authorize Contact Form 7 to access the service with your account.", 'contact-form-7' ) . '</p>';
|
||||
$content['integration_overview'] .= '<p>' . __( "Any information you provide will not be shared with service providers without your authorization.", 'contact-form-7' ) . '</p>';
|
||||
|
||||
if ( ! empty( $content[$name] ) ) {
|
||||
return $content[$name];
|
||||
}
|
||||
}
|
||||
|
||||
public function sidebar() {
|
||||
$content = '<p><strong>' . __( 'For more information:', 'contact-form-7' ) . '</strong></p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/docs/', 'contact-form-7' ), __( 'Docs', 'contact-form-7' ) ) . '</p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/faq/', 'contact-form-7' ), __( 'FAQ', 'contact-form-7' ) ) . '</p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/support/', 'contact-form-7' ), __( 'Support', 'contact-form-7' ) ) . '</p>';
|
||||
|
||||
$this->screen->set_help_sidebar( $content );
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_TagGenerator {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $panels = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function add( $id, $title, $callback, $options = array() ) {
|
||||
$id = trim( $id );
|
||||
|
||||
if ( '' === $id
|
||||
or ! wpcf7_is_name( $id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->panels[$id] = array(
|
||||
'title' => $title,
|
||||
'content' => 'tag-generator-panel-' . $id,
|
||||
'options' => $options,
|
||||
'callback' => $callback,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function print_buttons() {
|
||||
echo '<span id="tag-generator-list">';
|
||||
|
||||
foreach ( (array) $this->panels as $panel ) {
|
||||
echo sprintf(
|
||||
'<a href="#TB_inline?width=900&height=500&inlineId=%1$s" class="thickbox button" title="%2$s">%3$s</a>',
|
||||
esc_attr( $panel['content'] ),
|
||||
esc_attr( sprintf(
|
||||
/* translators: %s: title of form-tag like 'email' or 'checkboxes' */
|
||||
__( 'Form-tag Generator: %s', 'contact-form-7' ),
|
||||
$panel['title'] ) ),
|
||||
esc_html( $panel['title'] )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</span>';
|
||||
}
|
||||
|
||||
public function print_panels( WPCF7_ContactForm $contact_form ) {
|
||||
foreach ( (array) $this->panels as $id => $panel ) {
|
||||
$callback = $panel['callback'];
|
||||
|
||||
$options = wp_parse_args( $panel['options'], array() );
|
||||
$options = array_merge( $options, array(
|
||||
'id' => $id,
|
||||
'title' => $panel['title'],
|
||||
'content' => $panel['content'],
|
||||
) );
|
||||
|
||||
if ( is_callable( $callback ) ) {
|
||||
echo sprintf( '<div id="%s" class="hidden">',
|
||||
esc_attr( $options['content'] ) );
|
||||
echo sprintf(
|
||||
'<form action="" class="tag-generator-panel" data-id="%s">',
|
||||
$options['id'] );
|
||||
|
||||
call_user_func( $callback, $contact_form, $options );
|
||||
|
||||
echo '</form></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
<?php
|
||||
|
||||
abstract class WPCF7_WelcomePanelColumn {
|
||||
|
||||
abstract protected function icon();
|
||||
abstract protected function title();
|
||||
abstract protected function content();
|
||||
|
||||
public function print_content() {
|
||||
$icon = sprintf(
|
||||
'<span class="dashicons dashicons-%s" aria-hidden="true"></span>',
|
||||
esc_attr( $this->icon() )
|
||||
);
|
||||
|
||||
$title = sprintf(
|
||||
'<h3>%1$s %2$s</h3>',
|
||||
$icon,
|
||||
$this->title()
|
||||
);
|
||||
|
||||
$content = $this->content();
|
||||
|
||||
if ( is_array( $content ) ) {
|
||||
$content = implode( "\n\n", $content );
|
||||
}
|
||||
|
||||
$content = wp_kses_post( $content );
|
||||
$content = wptexturize( $content );
|
||||
$content = convert_chars( $content );
|
||||
$content = wpautop( $content );
|
||||
|
||||
echo "\n";
|
||||
echo '<div class="welcome-panel-column">';
|
||||
echo $title;
|
||||
echo $content;
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_AntiSpam extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'shield';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return esc_html(
|
||||
__( "Getting spammed? You have protection.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
esc_html( __( "Spammers target everything; your contact forms are not an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.", 'contact-form-7' ) ),
|
||||
sprintf(
|
||||
/* translators: links labeled 1: 'Akismet', 2: 'reCAPTCHA', 3: 'disallowed list' */
|
||||
esc_html( __( 'Contact Form 7 supports spam-filtering with %1$s. Intelligent %2$s blocks annoying spambots. Plus, using %3$s, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
|
||||
__( 'Akismet', 'contact-form-7' )
|
||||
),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
|
||||
__( 'reCAPTCHA', 'contact-form-7' )
|
||||
),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' ),
|
||||
__( 'disallowed list', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Donation extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'megaphone';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return esc_html(
|
||||
__( "Contact Form 7 needs your support.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
esc_html( __( "It is hard to continue development and support for this plugin without contributions from users like you.", 'contact-form-7' ) ),
|
||||
sprintf(
|
||||
/* translators: %s: link labeled 'making a donation' */
|
||||
esc_html( __( 'If you enjoy using Contact Form 7 and find it useful, please consider %s.', 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/donate/', 'contact-form-7' ),
|
||||
__( 'making a donation', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
esc_html( __( "Your donation will help encourage and support the plugin’s continued development and better user support.", 'contact-form-7' ) ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Flamingo extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'editor-help';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return esc_html(
|
||||
__( "Before you cry over spilt mail…", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
esc_html( __( "Contact Form 7 does not store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.", 'contact-form-7' ) ),
|
||||
sprintf(
|
||||
/* translators: %s: link labeled 'Flamingo' */
|
||||
esc_html( __( 'Install a message storage plugin before this happens to you. %s saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' ),
|
||||
__( 'Flamingo', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Integration extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'superhero-alt';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return esc_html(
|
||||
__( "You have strong allies to back you up.", 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
sprintf(
|
||||
/* translators: 1: link labeled 'Brevo' */
|
||||
esc_html( __( 'Your contact forms will become more powerful and versatile by integrating them with external APIs. With CRM and email marketing services, you can build your own contact lists (%1$s).', 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' ),
|
||||
__( 'Brevo', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
sprintf(
|
||||
/* translators: 1: link labeled 'reCAPTCHA', 2: link labeled 'Stripe' */
|
||||
esc_html( __( 'With help from cloud-based machine learning, anti-spam services will protect your forms (%1$s). Even payment services are natively supported (%2$s).', 'contact-form-7' ) ),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
|
||||
__( 'reCAPTCHA', 'contact-form-7' )
|
||||
),
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/stripe-integration/', 'contact-form-7' ),
|
||||
__( 'Stripe', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_welcome_panel() {
|
||||
$columns = array();
|
||||
|
||||
$flamingo_is_active = defined( 'FLAMINGO_VERSION' );
|
||||
|
||||
$sendinblue_is_active = false;
|
||||
|
||||
if ( class_exists( 'WPCF7_Sendinblue' )
|
||||
and $sendinblue = WPCF7_Sendinblue::get_instance() ) {
|
||||
$sendinblue_is_active = $sendinblue->is_active();
|
||||
}
|
||||
|
||||
if ( $flamingo_is_active and $sendinblue_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Donation();
|
||||
} elseif ( $flamingo_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Integration();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
} elseif ( $sendinblue_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
} else {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Integration();
|
||||
}
|
||||
|
||||
$classes = 'wpcf7-welcome-panel';
|
||||
|
||||
$vers = (array) get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
|
||||
$classes .= ' hidden';
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="wpcf7-welcome-panel" class="<?php echo esc_attr( $classes ); ?>">
|
||||
<?php wp_nonce_field( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce', false ); ?>
|
||||
<a class="welcome-panel-close" href="<?php echo esc_url( menu_page_url( 'wpcf7', false ) ); ?>"><?php echo esc_html( __( 'Dismiss', 'contact-form-7' ) ); ?></a>
|
||||
|
||||
<div class="welcome-panel-content">
|
||||
<div class="welcome-panel-column-container">
|
||||
<?php
|
||||
|
||||
foreach ( $columns as $column ) {
|
||||
$column->print_content();
|
||||
}
|
||||
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wp_ajax_wpcf7-update-welcome-panel',
|
||||
'wpcf7_admin_ajax_welcome_panel',
|
||||
10, 0
|
||||
);
|
||||
|
||||
function wpcf7_admin_ajax_welcome_panel() {
|
||||
check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );
|
||||
|
||||
$vers = get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
if ( empty( $vers ) or ! is_array( $vers ) ) {
|
||||
$vers = array();
|
||||
}
|
||||
|
||||
if ( empty( $_POST['visible'] ) ) {
|
||||
$vers[] = wpcf7_version( 'only_major=1' );
|
||||
} else {
|
||||
$vers = array_diff( $vers, array( wpcf7_version( 'only_major=1' ) ) );
|
||||
}
|
||||
|
||||
$vers = array_unique( $vers );
|
||||
|
||||
update_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', $vers
|
||||
);
|
||||
|
||||
wp_die( 1 );
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'screen_settings',
|
||||
'wpcf7_welcome_panel_screen_settings',
|
||||
10, 2
|
||||
);
|
||||
|
||||
function wpcf7_welcome_panel_screen_settings( $screen_settings, $screen ) {
|
||||
|
||||
if ( 'toplevel_page_wpcf7' !== $screen->id ) {
|
||||
return $screen_settings;
|
||||
}
|
||||
|
||||
$vers = (array) get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
$checkbox_id = 'wpcf7-welcome-panel-show';
|
||||
$checked = ! in_array( wpcf7_version( 'only_major=1' ), $vers );
|
||||
|
||||
$checkbox = sprintf(
|
||||
'<input %s />',
|
||||
wpcf7_format_atts( array(
|
||||
'id' => $checkbox_id,
|
||||
'type' => 'checkbox',
|
||||
'checked' => $checked,
|
||||
) )
|
||||
);
|
||||
|
||||
$screen_settings .= sprintf( '
|
||||
<fieldset class="wpcf7-welcome-panel-options">
|
||||
<legend>%1$s</legend>
|
||||
<label for="%2$s">%3$s %4$s</label>
|
||||
</fieldset>',
|
||||
esc_html( __( 'Welcome panel', 'contact-form-7' ) ),
|
||||
esc_attr( $checkbox_id ),
|
||||
$checkbox,
|
||||
esc_html( __( 'Show welcome panel', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
return $screen_settings;
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
( function( $ ) {
|
||||
|
||||
'use strict';
|
||||
|
||||
if ( typeof wpcf7 === 'undefined' || wpcf7 === null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$( function() {
|
||||
var welcomePanel = $( '#wpcf7-welcome-panel' );
|
||||
var updateWelcomePanel;
|
||||
|
||||
updateWelcomePanel = function( visible ) {
|
||||
$.post( ajaxurl, {
|
||||
action: 'wpcf7-update-welcome-panel',
|
||||
visible: visible,
|
||||
welcomepanelnonce: $( '#welcomepanelnonce' ).val()
|
||||
} );
|
||||
};
|
||||
|
||||
$( 'a.welcome-panel-close', welcomePanel ).click( function( event ) {
|
||||
event.preventDefault();
|
||||
welcomePanel.addClass( 'hidden' );
|
||||
updateWelcomePanel( 0 );
|
||||
$( '#wpcf7-welcome-panel-show' ).prop( 'checked', false );
|
||||
} );
|
||||
|
||||
$( '#wpcf7-welcome-panel-show' ).click( function( event ) {
|
||||
if ( this.checked ) {
|
||||
welcomePanel.removeClass( 'hidden' );
|
||||
updateWelcomePanel( 1 );
|
||||
} else {
|
||||
welcomePanel.addClass( 'hidden' );
|
||||
updateWelcomePanel( 0 );
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#contact-form-editor' ).tabs( {
|
||||
active: wpcf7.activeTab,
|
||||
activate: function( event, ui ) {
|
||||
$( '#active-tab' ).val( ui.newTab.index() );
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#contact-form-editor-tabs' ).focusin( function( event ) {
|
||||
$( '#contact-form-editor .keyboard-interaction' ).css(
|
||||
'visibility', 'visible' );
|
||||
} ).focusout( function( event ) {
|
||||
$( '#contact-form-editor .keyboard-interaction' ).css(
|
||||
'visibility', 'hidden' );
|
||||
} );
|
||||
|
||||
wpcf7.toggleMail2( 'input:checkbox.toggle-form-table' );
|
||||
|
||||
$( 'input:checkbox.toggle-form-table' ).click( function( event ) {
|
||||
wpcf7.toggleMail2( this );
|
||||
} );
|
||||
|
||||
if ( '' === $( '#title' ).val() ) {
|
||||
$( '#title' ).focus();
|
||||
}
|
||||
|
||||
wpcf7.titleHint();
|
||||
|
||||
$( '.contact-form-editor-box-mail span.mailtag' ).click( function( event ) {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents( this );
|
||||
window.getSelection().addRange( range );
|
||||
} );
|
||||
|
||||
wpcf7.updateConfigErrors();
|
||||
|
||||
$( '[data-config-field]' ).change( function() {
|
||||
var postId = $( '#post_ID' ).val();
|
||||
|
||||
if ( ! postId || -1 == postId ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = [];
|
||||
|
||||
$( this ).closest( 'form' ).find( '[data-config-field]' ).each( function() {
|
||||
var val = $( this ).val();
|
||||
|
||||
if ( $( this ).is( '[type=checkbox]' ) ) {
|
||||
val = $( this ).is( ':checked' ) ? 1 : 0;
|
||||
}
|
||||
|
||||
data.push( {
|
||||
'name': $( this ).attr( 'name' ).replace( /^wpcf7-/, '' ).replace( /-/g, '_' ),
|
||||
'value': val
|
||||
} );
|
||||
} );
|
||||
|
||||
data.push( { 'name': 'context', 'value': 'dry-run' } );
|
||||
|
||||
$.ajax( {
|
||||
method: 'POST',
|
||||
url: wpcf7.apiSettings.getRoute( '/contact-forms/' + postId ),
|
||||
beforeSend: function( xhr ) {
|
||||
xhr.setRequestHeader( 'X-WP-Nonce', wpcf7.apiSettings.nonce );
|
||||
},
|
||||
data: data
|
||||
} ).done( function( response ) {
|
||||
wpcf7.configValidator.errors = response.config_errors;
|
||||
wpcf7.updateConfigErrors();
|
||||
} );
|
||||
} );
|
||||
|
||||
$( window ).on( 'beforeunload', function( event ) {
|
||||
var changed = false;
|
||||
|
||||
$( '#wpcf7-admin-form-element :input[type!="hidden"]' ).each( function() {
|
||||
if ( $( this ).is( ':checkbox, :radio' ) ) {
|
||||
if ( this.defaultChecked != $( this ).is( ':checked' ) ) {
|
||||
changed = true;
|
||||
}
|
||||
} else if ( $( this ).is( 'select' ) ) {
|
||||
$( this ).find( 'option' ).each( function() {
|
||||
if ( this.defaultSelected != $( this ).is( ':selected' ) ) {
|
||||
changed = true;
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
if ( this.defaultValue != $( this ).val() ) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
if ( changed ) {
|
||||
event.returnValue = wpcf7.saveAlert;
|
||||
return wpcf7.saveAlert;
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#wpcf7-admin-form-element' ).submit( function() {
|
||||
if ( 'copy' != this.action.value ) {
|
||||
$( window ).off( 'beforeunload' );
|
||||
}
|
||||
|
||||
if ( 'save' == this.action.value ) {
|
||||
$( '#publishing-action .spinner' ).addClass( 'is-active' );
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#wpcf7-ctct-enable-contact-list, #wpcf7-sendinblue-enable-contact-list, #wpcf7-sendinblue-enable-transactional-email' ).on( 'change', function() {
|
||||
if ( $( this ).is( ':checked' ) ) {
|
||||
$( this ).closest( 'tr' ).removeClass( 'inactive' );
|
||||
} else {
|
||||
$( this ).closest( 'tr' ).addClass( 'inactive' );
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
wpcf7.toggleMail2 = function( checkbox ) {
|
||||
var $checkbox = $( checkbox );
|
||||
var $fieldset = $( 'fieldset',
|
||||
$checkbox.closest( '.contact-form-editor-box-mail' ) );
|
||||
|
||||
if ( $checkbox.is( ':checked' ) ) {
|
||||
$fieldset.removeClass( 'hidden' );
|
||||
} else {
|
||||
$fieldset.addClass( 'hidden' );
|
||||
}
|
||||
};
|
||||
|
||||
wpcf7.updateConfigErrors = function() {
|
||||
var errors = wpcf7.configValidator.errors;
|
||||
var errorCount = { total: 0 };
|
||||
|
||||
$( '[data-config-field]' ).each( function() {
|
||||
$( this ).removeAttr( 'aria-invalid' );
|
||||
$( this ).next( 'ul.config-error' ).remove();
|
||||
|
||||
var section = $( this ).attr( 'data-config-field' );
|
||||
|
||||
$( this ).attr( 'aria-describedby', 'wpcf7-config-error-for-' + section );
|
||||
|
||||
if ( errors[ section ] ) {
|
||||
var $list = $( '<ul></ul>' ).attr( {
|
||||
'id': 'wpcf7-config-error-for-' + section,
|
||||
'class': 'config-error'
|
||||
} );
|
||||
|
||||
$.each( errors[ section ], function( i, val ) {
|
||||
var $li = $( '<li></li>' ).append(
|
||||
wpcf7.iconInCircle( '!' )
|
||||
).append(
|
||||
$( '<span class="screen-reader-text"></span>' ).text( wpcf7.configValidator.iconAlt )
|
||||
).append( ' ' );
|
||||
|
||||
if ( val.link ) {
|
||||
$li.append(
|
||||
$( '<a></a>' ).attr( 'href', val.link ).text( val.message )
|
||||
);
|
||||
} else {
|
||||
$li.text( val.message );
|
||||
}
|
||||
|
||||
$li.appendTo( $list );
|
||||
|
||||
var tab = section
|
||||
.replace( /^mail_\d+\./, 'mail.' ).replace( /\..*$/, '' );
|
||||
|
||||
if ( ! errorCount[ tab ] ) {
|
||||
errorCount[ tab ] = 0;
|
||||
}
|
||||
|
||||
errorCount[ tab ] += 1;
|
||||
|
||||
errorCount.total += 1;
|
||||
} );
|
||||
|
||||
$( this ).after( $list ).attr( { 'aria-invalid': 'true' } );
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#contact-form-editor-tabs > li' ).each( function() {
|
||||
var $item = $( this );
|
||||
$item.find( '.icon-in-circle' ).remove();
|
||||
var tab = $item.attr( 'id' ).replace( /-panel-tab$/, '' );
|
||||
|
||||
$.each( errors, function( key, val ) {
|
||||
key = key.replace( /^mail_\d+\./, 'mail.' );
|
||||
|
||||
if ( key.replace( /\..*$/, '' ) == tab.replace( '-', '_' ) ) {
|
||||
var $mark = wpcf7.iconInCircle( '!' );
|
||||
$item.find( 'a.ui-tabs-anchor' ).first().append( $mark );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
var $tabPanelError = $( '#' + tab + '-panel > div.config-error:first' );
|
||||
$tabPanelError.empty();
|
||||
|
||||
if ( errorCount[ tab.replace( '-', '_' ) ] ) {
|
||||
$tabPanelError.append( wpcf7.iconInCircle( '!' ) );
|
||||
|
||||
if ( 1 < errorCount[ tab.replace( '-', '_' ) ] ) {
|
||||
var manyErrorsInTab = wpcf7.configValidator.manyErrorsInTab
|
||||
.replace( '%d', errorCount[ tab.replace( '-', '_' ) ] );
|
||||
$tabPanelError.append( manyErrorsInTab );
|
||||
} else {
|
||||
$tabPanelError.append( wpcf7.configValidator.oneErrorInTab );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
$( '#misc-publishing-actions .misc-pub-section.config-error' ).remove();
|
||||
|
||||
if ( errorCount.total ) {
|
||||
var $warning = $( '<div></div>' )
|
||||
.addClass( 'misc-pub-section config-error' )
|
||||
.append( wpcf7.iconInCircle( '!' ) );
|
||||
|
||||
if ( 1 < errorCount.total ) {
|
||||
$warning.append(
|
||||
wpcf7.configValidator.manyErrors.replace( '%d', errorCount.total )
|
||||
);
|
||||
} else {
|
||||
$warning.append( wpcf7.configValidator.oneError );
|
||||
}
|
||||
|
||||
$warning.append( '<br />' ).append(
|
||||
$( '<a></a>' )
|
||||
.attr( 'href', wpcf7.configValidator.docUrl )
|
||||
.text( wpcf7.configValidator.howToCorrect )
|
||||
);
|
||||
|
||||
$( '#misc-publishing-actions' ).append( $warning );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Copied from wptitlehint() in wp-admin/js/post.js
|
||||
*/
|
||||
wpcf7.titleHint = function() {
|
||||
var $title = $( '#title' );
|
||||
var $titleprompt = $( '#title-prompt-text' );
|
||||
|
||||
if ( '' === $title.val() ) {
|
||||
$titleprompt.removeClass( 'screen-reader-text' );
|
||||
}
|
||||
|
||||
$titleprompt.click( function() {
|
||||
$( this ).addClass( 'screen-reader-text' );
|
||||
$title.focus();
|
||||
} );
|
||||
|
||||
$title.blur( function() {
|
||||
if ( '' === $(this).val() ) {
|
||||
$titleprompt.removeClass( 'screen-reader-text' );
|
||||
}
|
||||
} ).focus( function() {
|
||||
$titleprompt.addClass( 'screen-reader-text' );
|
||||
} ).keydown( function( e ) {
|
||||
$titleprompt.addClass( 'screen-reader-text' );
|
||||
$( this ).unbind( e );
|
||||
} );
|
||||
};
|
||||
|
||||
wpcf7.iconInCircle = function( icon ) {
|
||||
var $span = $( '<span class="icon-in-circle" aria-hidden="true"></span>' );
|
||||
return $span.text( icon );
|
||||
};
|
||||
|
||||
wpcf7.apiSettings.getRoute = function( path ) {
|
||||
var url = wpcf7.apiSettings.root;
|
||||
|
||||
url = url.replace(
|
||||
wpcf7.apiSettings.namespace,
|
||||
wpcf7.apiSettings.namespace + path );
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
} )( jQuery );
|
||||
@@ -1,249 +0,0 @@
|
||||
( function( $ ) {
|
||||
|
||||
'use strict';
|
||||
|
||||
if ( typeof wpcf7 === 'undefined' || wpcf7 === null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wpcf7.taggen = {};
|
||||
|
||||
$( function() {
|
||||
$( 'form.tag-generator-panel' ).each( function() {
|
||||
wpcf7.taggen.update( $( this ) );
|
||||
} );
|
||||
} );
|
||||
|
||||
$( 'form.tag-generator-panel' ).submit( function() {
|
||||
return false;
|
||||
} );
|
||||
|
||||
$( 'form.tag-generator-panel .control-box :input' ).change( function() {
|
||||
var $form = $( this ).closest( 'form.tag-generator-panel' );
|
||||
wpcf7.taggen.normalize( $( this ) );
|
||||
wpcf7.taggen.update( $form );
|
||||
} );
|
||||
|
||||
$( 'input.insert-tag' ).click( function() {
|
||||
var $form = $( this ).closest( 'form.tag-generator-panel' );
|
||||
var tag = $form.find( 'input.tag' ).val();
|
||||
wpcf7.taggen.insert( tag );
|
||||
tb_remove(); // close thickbox
|
||||
return false;
|
||||
} );
|
||||
|
||||
wpcf7.taggen.update = function( $form ) {
|
||||
var id = $form.attr( 'data-id' );
|
||||
var name = '';
|
||||
var name_fields = $form.find( 'input[name="name"]' );
|
||||
|
||||
if ( name_fields.length ) {
|
||||
name = name_fields.val();
|
||||
|
||||
if ( '' === name ) {
|
||||
name = id + '-' + Math.floor( Math.random() * 1000 );
|
||||
name_fields.val( name );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $.isFunction( wpcf7.taggen.update[ id ] ) ) {
|
||||
return wpcf7.taggen.update[ id ].call( this, $form );
|
||||
}
|
||||
|
||||
$form.find( 'input.tag' ).each( function() {
|
||||
var tag_type = $( this ).attr( 'name' );
|
||||
|
||||
if ( $form.find( ':input[name="tagtype"]' ).length ) {
|
||||
tag_type = $form.find( ':input[name="tagtype"]' ).val();
|
||||
}
|
||||
|
||||
if ( $form.find( ':input[name="required"]' ).is( ':checked' ) ) {
|
||||
tag_type += '*';
|
||||
}
|
||||
|
||||
var components = wpcf7.taggen.compose( tag_type, $form );
|
||||
$( this ).val( components );
|
||||
} );
|
||||
|
||||
$form.find( 'span.mail-tag' ).text( '[' + name + ']' );
|
||||
|
||||
$form.find( 'input.mail-tag' ).each( function() {
|
||||
$( this ).val( '[' + name + ']' );
|
||||
} );
|
||||
};
|
||||
|
||||
wpcf7.taggen.update.captcha = function( $form ) {
|
||||
var captchac = wpcf7.taggen.compose( 'captchac', $form );
|
||||
var captchar = wpcf7.taggen.compose( 'captchar', $form );
|
||||
|
||||
$form.find( 'input.tag' ).val( captchac + ' ' + captchar );
|
||||
};
|
||||
|
||||
wpcf7.taggen.compose = function( tagType, $form ) {
|
||||
var name = $form.find( 'input[name="name"]' ).val();
|
||||
var scope = $form.find( '.scope.' + tagType );
|
||||
|
||||
if ( ! scope.length ) {
|
||||
scope = $form;
|
||||
}
|
||||
|
||||
var options = [];
|
||||
|
||||
scope.find( 'input.option' ).not( ':checkbox,:radio' ).each( function( i ) {
|
||||
var val = $( this ).val();
|
||||
|
||||
if ( ! val ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $( this ).hasClass( 'filetype' ) ) {
|
||||
val = val.split( /[,|\s]+/ ).join( '|' );
|
||||
}
|
||||
|
||||
if ( $( this ).hasClass( 'color' ) ) {
|
||||
val = '#' + val;
|
||||
}
|
||||
|
||||
if ( 'class' == $( this ).attr( 'name' ) ) {
|
||||
$.each( val.split( ' ' ), function( i, n ) {
|
||||
options.push( 'class:' + n );
|
||||
} );
|
||||
} else {
|
||||
options.push( $( this ).attr( 'name' ) + ':' + val );
|
||||
}
|
||||
} );
|
||||
|
||||
scope.find( 'input:checkbox.option' ).each( function( i ) {
|
||||
if ( $( this ).is( ':checked' ) ) {
|
||||
options.push( $( this ).attr( 'name' ) );
|
||||
}
|
||||
} );
|
||||
|
||||
scope.find( 'input:radio.option' ).each( function( i ) {
|
||||
if ( $( this ).is( ':checked' ) && ! $( this ).hasClass( 'default' ) ) {
|
||||
options.push( $( this ).attr( 'name' ) + ':' + $( this ).val() );
|
||||
}
|
||||
} );
|
||||
|
||||
if ( 'radio' == tagType ) {
|
||||
options.push( 'default:1' );
|
||||
}
|
||||
|
||||
options = ( options.length > 0 ) ? options.join( ' ' ) : '';
|
||||
|
||||
var value = '';
|
||||
|
||||
if ( scope.find( ':input[name="values"]' ).val() ) {
|
||||
$.each(
|
||||
scope.find( ':input[name="values"]' ).val().split( "\n" ),
|
||||
function( i, n ) {
|
||||
value += ' "' + n.replace( /["]/g, '"' ) + '"';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var components = [];
|
||||
|
||||
$.each( [ tagType, name, options, value ], function( i, v ) {
|
||||
v = $.trim( v );
|
||||
|
||||
if ( '' != v ) {
|
||||
components.push( v );
|
||||
}
|
||||
} );
|
||||
|
||||
components = $.trim( components.join( ' ' ) );
|
||||
components = '[' + components + ']';
|
||||
|
||||
var content = scope.find( ':input[name="content"]' ).val();
|
||||
content = $.trim( content );
|
||||
|
||||
if ( content ) {
|
||||
components += ' ' + content + ' [/' + tagType + ']';
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
|
||||
wpcf7.taggen.normalize = function( $input ) {
|
||||
var val = $input.val();
|
||||
|
||||
if ( $input.is( 'input[name="name"]' ) ) {
|
||||
val = val.replace( /[^0-9a-zA-Z:._-]/g, '' ).replace( /^[^a-zA-Z]+/, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.numeric' ) ) {
|
||||
val = val.replace( /[^0-9.-]/g, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.idvalue' ) ) {
|
||||
val = val.replace( /[^-0-9a-zA-Z_]/g, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.classvalue' ) ) {
|
||||
val = $.map( val.split( ' ' ), function( n ) {
|
||||
return n.replace( /[^-0-9a-zA-Z_]/g, '' );
|
||||
} ).join( ' ' );
|
||||
|
||||
val = $.trim( val.replace( /\s+/g, ' ' ) );
|
||||
}
|
||||
|
||||
if ( $input.is( '.color' ) ) {
|
||||
val = val.replace( /[^0-9a-fA-F]/g, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.filesize' ) ) {
|
||||
val = val.replace( /[^0-9kKmMbB]/g, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.filetype' ) ) {
|
||||
val = val.replace( /[^0-9a-zA-Z.,|\s]/g, '' );
|
||||
}
|
||||
|
||||
if ( $input.is( '.date' ) ) {
|
||||
// 'yyyy-mm-dd' ISO 8601 format
|
||||
if ( ! val.match( /^\d{4}-\d{2}-\d{2}$/ ) ) {
|
||||
val = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $input.is( ':input[name="values"]' ) ) {
|
||||
val = $.trim( val );
|
||||
}
|
||||
|
||||
$input.val( val );
|
||||
|
||||
if ( $input.is( ':checkbox.exclusive' ) ) {
|
||||
wpcf7.taggen.exclusiveCheckbox( $input );
|
||||
}
|
||||
};
|
||||
|
||||
wpcf7.taggen.exclusiveCheckbox = function( $cb ) {
|
||||
if ( $cb.is( ':checked' ) ) {
|
||||
$cb.siblings( ':checkbox.exclusive' ).prop( 'checked', false );
|
||||
}
|
||||
};
|
||||
|
||||
wpcf7.taggen.insert = function( content ) {
|
||||
$( 'textarea#wpcf7-form' ).each( function() {
|
||||
this.focus();
|
||||
|
||||
if ( document.selection ) { // IE
|
||||
var selection = document.selection.createRange();
|
||||
selection.text = content;
|
||||
} else if ( this.selectionEnd || 0 === this.selectionEnd ) {
|
||||
var val = $( this ).val();
|
||||
var end = this.selectionEnd;
|
||||
$( this ).val( val.substring( 0, end ) +
|
||||
content + val.substring( end, val.length ) );
|
||||
this.selectionStart = end + content.length;
|
||||
this.selectionEnd = end + content.length;
|
||||
} else {
|
||||
$( this ).val( $( this ).val() + content );
|
||||
}
|
||||
|
||||
this.focus();
|
||||
} );
|
||||
};
|
||||
|
||||
} )( jQuery );
|
||||
|
Before Width: | Height: | Size: 29 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 242.5 239.46"><defs><style>.cls-1,.cls-6{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#33c6f4;}.cls-4{fill:#1b447e;}.cls-5{fill:#fff;}.cls-6{stroke:#221e1f;stroke-miterlimit:10;stroke-width:7.16px;}</style><clipPath id="clip-path" transform="translate(1.72)"><circle class="cls-1" cx="119.73" cy="119.73" r="116.15"/></clipPath></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1" data-name="Layer 1"><g class="cls-2"><circle class="cls-3" cx="121.45" cy="119.73" r="116.15"/><path class="cls-4" d="M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z" transform="translate(1.72)"/><path class="cls-5" d="M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z" transform="translate(1.72)"/><path class="cls-6" d="M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11" transform="translate(1.72)"/></g><circle class="cls-6" cx="121.45" cy="119.73" r="116.15"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
'wpcf7_init_block_editor_assets',
|
||||
10, 0
|
||||
);
|
||||
|
||||
function wpcf7_init_block_editor_assets() {
|
||||
register_block_type(
|
||||
wpcf7_plugin_path( 'includes/block-editor' )
|
||||
);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "contact-form-7/contact-form-selector",
|
||||
"title": "Contact Form 7",
|
||||
"category": "widgets",
|
||||
"description": "Insert a contact form you have created with Contact Form 7.",
|
||||
"keywords": [ "form" ],
|
||||
"textdomain": "contact-form-7",
|
||||
"attributes": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlId": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlName": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlTitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlClass": {
|
||||
"type": "string"
|
||||
},
|
||||
"output": {
|
||||
"enum": [ "form", "raw_form" ],
|
||||
"default": "form"
|
||||
}
|
||||
},
|
||||
"editorScript": [ "file:./index.js", "contact-form-7-block-editor" ]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'react',
|
||||
'wp-api-fetch',
|
||||
'wp-block-editor',
|
||||
'wp-blocks',
|
||||
'wp-components',
|
||||
'wp-element',
|
||||
'wp-i18n',
|
||||
'wp-url',
|
||||
),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'wpcf7_update_option',
|
||||
'wpcf7_config_validator_update_option',
|
||||
10, 3
|
||||
);
|
||||
|
||||
/**
|
||||
* Runs bulk validation after the reCAPTCHA integration option is updated.
|
||||
*/
|
||||
function wpcf7_config_validator_update_option( $name, $value, $old_option ) {
|
||||
if ( 'recaptcha' === $name ) {
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
|
||||
$options = array(
|
||||
'include' => 'unsafe_email_without_protection',
|
||||
);
|
||||
|
||||
foreach ( $contact_forms as $contact_form ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form, $options );
|
||||
$config_validator->restore();
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_AdditionalSettings {
|
||||
|
||||
/**
|
||||
* Runs error detection for the additional settings section.
|
||||
*/
|
||||
public function validate_additional_settings() {
|
||||
$section = 'additional_settings.body';
|
||||
|
||||
if ( $this->supports( 'deprecated_settings' ) ) {
|
||||
$deprecated_settings_used =
|
||||
$this->contact_form->additional_setting( 'on_sent_ok' ) ||
|
||||
$this->contact_form->additional_setting( 'on_submit' );
|
||||
|
||||
if ( $deprecated_settings_used ) {
|
||||
$this->add_error( $section, 'deprecated_settings',
|
||||
array(
|
||||
'message' => __( "Deprecated settings are used.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'deprecated_settings' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Form {
|
||||
|
||||
/**
|
||||
* Runs error detection for the form section.
|
||||
*/
|
||||
public function validate_form() {
|
||||
$section = 'form.body';
|
||||
$form = $this->contact_form->prop( 'form' );
|
||||
|
||||
if ( $this->supports( 'multiple_controls_in_label' ) ) {
|
||||
if ( $this->detect_multiple_controls_in_label( $section, $form ) ) {
|
||||
$this->add_error( $section, 'multiple_controls_in_label',
|
||||
array(
|
||||
'message' => __( "Multiple form controls are in a single label element.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'multiple_controls_in_label' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unavailable_names' ) ) {
|
||||
$ng_names = $this->detect_unavailable_names( $section, $form );
|
||||
|
||||
if ( $ng_names ) {
|
||||
$this->add_error( $section, 'unavailable_names',
|
||||
array(
|
||||
'message' =>
|
||||
/* translators: %names%: a list of form control names */
|
||||
__( "Unavailable names (%names%) are used for form controls.", 'contact-form-7' ),
|
||||
'params' => array( 'names' => implode( ', ', $ng_names ) ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unavailable_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unavailable_html_elements' ) ) {
|
||||
if ( $this->detect_unavailable_html_elements( $section, $form ) ) {
|
||||
$this->add_error( $section, 'unavailable_html_elements',
|
||||
array(
|
||||
'message' => __( "Unavailable HTML elements are used in the form template.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unavailable_html_elements' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'dots_in_names' ) ) {
|
||||
if ( $this->detect_dots_in_names( $section, $form ) ) {
|
||||
$this->add_error( $section, 'dots_in_names',
|
||||
array(
|
||||
'message' => __( "Dots are used in form-tag names.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'dots_in_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'colons_in_names' ) ) {
|
||||
if ( $this->detect_colons_in_names( $section, $form ) ) {
|
||||
$this->add_error( $section, 'colons_in_names',
|
||||
array(
|
||||
'message' => __( "Colons are used in form-tag names.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'colons_in_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'upload_filesize_overlimit' ) ) {
|
||||
if ( $this->detect_upload_filesize_overlimit( $section, $form ) ) {
|
||||
$this->add_error( $section, 'upload_filesize_overlimit',
|
||||
array(
|
||||
'message' => __( "Uploadable file size exceeds PHP’s maximum acceptable size.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'upload_filesize_overlimit' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of multiple form controls in a single label.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/multiple-controls-in-label/
|
||||
*/
|
||||
public function detect_multiple_controls_in_label( $section, $content ) {
|
||||
$pattern = '%<label(?:[ \t\n]+.*?)?>(.+?)</label>%s';
|
||||
|
||||
if ( preg_match_all( $pattern, $content, $matches ) ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
foreach ( $matches[1] as $insidelabel ) {
|
||||
$tags = $form_tags_manager->scan( $insidelabel );
|
||||
$fields_count = 0;
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$is_multiple_controls_container = wpcf7_form_tag_supports(
|
||||
$tag->type, 'multiple-controls-container'
|
||||
);
|
||||
|
||||
$is_zero_controls_container = wpcf7_form_tag_supports(
|
||||
$tag->type, 'zero-controls-container'
|
||||
);
|
||||
|
||||
if ( $is_multiple_controls_container ) {
|
||||
$fields_count += count( $tag->values );
|
||||
|
||||
if ( $tag->has_option( 'free_text' ) ) {
|
||||
$fields_count += 1;
|
||||
}
|
||||
} elseif ( $is_zero_controls_container ) {
|
||||
$fields_count += 0;
|
||||
} elseif ( ! empty( $tag->name ) ) {
|
||||
$fields_count += 1;
|
||||
}
|
||||
|
||||
if ( 1 < $fields_count ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of unavailable form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unavailable-names/
|
||||
*/
|
||||
public function detect_unavailable_names( $section, $content ) {
|
||||
$public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat',
|
||||
'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence',
|
||||
'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order',
|
||||
'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second',
|
||||
'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
|
||||
'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
|
||||
'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
|
||||
'cpage', 'post_type', 'embed',
|
||||
);
|
||||
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$ng_named_tags = $form_tags_manager->filter( $content, array(
|
||||
'name' => $public_query_vars,
|
||||
) );
|
||||
|
||||
$ng_names = array();
|
||||
|
||||
foreach ( $ng_named_tags as $tag ) {
|
||||
$ng_names[] = sprintf( '"%s"', $tag->name );
|
||||
}
|
||||
|
||||
if ( $ng_names ) {
|
||||
return array_unique( $ng_names );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of unavailable HTML elements.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unavailable-html-elements/
|
||||
*/
|
||||
public function detect_unavailable_html_elements( $section, $content ) {
|
||||
$pattern = '%(?:<form[\s\t>]|</form>)%i';
|
||||
|
||||
if ( preg_match( $pattern, $content ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of dots in form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/dots-in-names/
|
||||
*/
|
||||
public function detect_dots_in_names( $section, $content ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'feature' => 'name-attr',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( str_contains( $tag->raw_name, '.' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of colons in form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/colons-in-names/
|
||||
*/
|
||||
public function detect_colons_in_names( $section, $content ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'feature' => 'name-attr',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( str_contains( $tag->raw_name, ':' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of uploadable file size overlimit.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/upload-filesize-overlimit
|
||||
*/
|
||||
public function detect_upload_filesize_overlimit( $section, $content ) {
|
||||
$upload_max_filesize = ini_get( 'upload_max_filesize' );
|
||||
|
||||
if ( ! $upload_max_filesize ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$upload_max_filesize = strtolower( $upload_max_filesize );
|
||||
$upload_max_filesize = trim( $upload_max_filesize );
|
||||
|
||||
if ( ! preg_match( '/^(\d+)([kmg]?)$/', $upload_max_filesize, $matches ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'k' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * KB_IN_BYTES;
|
||||
} elseif ( 'm' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * MB_IN_BYTES;
|
||||
} elseif ( 'g' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * GB_IN_BYTES;
|
||||
} else {
|
||||
$upload_max_filesize = (int) $matches[1];
|
||||
}
|
||||
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'basetype' => 'file',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( $upload_max_filesize < $tag->get_limit_option() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Mail {
|
||||
|
||||
/**
|
||||
* Replaces all mail-tags in the given content.
|
||||
*/
|
||||
public function replace_mail_tags( $content, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'html' => false,
|
||||
'callback' =>
|
||||
array( $this, 'replace_mail_tags_with_minimum_input_callback' ),
|
||||
) );
|
||||
|
||||
$content = new WPCF7_MailTaggedText( $content, $args );
|
||||
|
||||
return $content->replace_tags();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for WPCF7_MailTaggedText. Replaces mail-tags with
|
||||
* the most conservative inputs.
|
||||
*/
|
||||
public function replace_mail_tags_with_minimum_input_callback( $matches ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( $matches[1] === '[' and $matches[4] === ']' ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$example_email = 'example@example.com';
|
||||
$example_text = 'example';
|
||||
$example_blank = '';
|
||||
|
||||
// for back-compat
|
||||
$field_name = preg_replace( '/^wpcf7\./', '_', $field_name );
|
||||
|
||||
if ( '_site_admin_email' === $field_name ) {
|
||||
return get_bloginfo( 'admin_email', 'raw' );
|
||||
|
||||
} elseif ( '_user_agent' === $field_name ) {
|
||||
return $example_text;
|
||||
|
||||
} elseif ( '_user_email' === $field_name ) {
|
||||
return $this->contact_form->is_true( 'subscribers_only' )
|
||||
? $example_email
|
||||
: $example_blank;
|
||||
|
||||
} elseif ( str_starts_with( $field_name, '_user_' ) ) {
|
||||
return $this->contact_form->is_true( 'subscribers_only' )
|
||||
? $example_text
|
||||
: $example_blank;
|
||||
|
||||
} elseif ( str_starts_with( $field_name, '_' ) ) {
|
||||
return str_ends_with( $field_name, '_email' )
|
||||
? $example_email
|
||||
: $example_text;
|
||||
|
||||
}
|
||||
|
||||
static $opcalcset = array();
|
||||
|
||||
if ( ! isset( $opcalcset[$this->contact_form->id()] ) ) {
|
||||
$opcalcset[$this->contact_form->id()] =
|
||||
new WPCF7_MailTag_OutputCalculator( $this->contact_form );
|
||||
}
|
||||
|
||||
$opcalc = $opcalcset[$this->contact_form->id()];
|
||||
$op = $opcalc->calc_output( $mail_tag );
|
||||
|
||||
if ( WPCF7_MailTag_OutputCalculator::email === $op ) {
|
||||
return $example_email;
|
||||
} elseif ( ! ( WPCF7_MailTag_OutputCalculator::blank & $op ) ) {
|
||||
return $example_text;
|
||||
} else {
|
||||
return $example_blank;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail sections.
|
||||
*/
|
||||
public function validate_mail( $template = 'mail' ) {
|
||||
if (
|
||||
$this->contact_form->is_true( 'demo_mode' ) or
|
||||
$this->contact_form->is_true( 'skip_mail' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$components = (array) $this->contact_form->prop( $template );
|
||||
|
||||
if ( ! $components ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'mail' !== $template and empty( $components['active'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$components = wp_parse_args( $components, array(
|
||||
'subject' => '',
|
||||
'sender' => '',
|
||||
'recipient' => '',
|
||||
'additional_headers' => '',
|
||||
'body' => '',
|
||||
'attachments' => '',
|
||||
) );
|
||||
|
||||
$this->validate_mail_subject(
|
||||
$template,
|
||||
$components['subject']
|
||||
);
|
||||
|
||||
$this->validate_mail_sender(
|
||||
$template,
|
||||
$components['sender']
|
||||
);
|
||||
|
||||
$this->validate_mail_recipient(
|
||||
$template,
|
||||
$components['recipient']
|
||||
);
|
||||
|
||||
$this->validate_mail_additional_headers(
|
||||
$template,
|
||||
$components['additional_headers']
|
||||
);
|
||||
|
||||
$this->validate_mail_body(
|
||||
$template,
|
||||
$components['body']
|
||||
);
|
||||
|
||||
$this->validate_mail_attachments(
|
||||
$template,
|
||||
$components['attachments']
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail subject section.
|
||||
*/
|
||||
public function validate_mail_subject( $template, $content ) {
|
||||
$section = sprintf( '%s.subject', $template );
|
||||
|
||||
if ( $this->supports( 'maybe_empty' ) ) {
|
||||
if ( $this->detect_maybe_empty( $section, $content ) ) {
|
||||
$this->add_error( $section, 'maybe_empty',
|
||||
array(
|
||||
'message' => __( "There is a possible empty field.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'maybe_empty' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail sender section.
|
||||
*/
|
||||
public function validate_mail_sender( $template, $content ) {
|
||||
$section = sprintf( '%s.sender', $template );
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'email_not_in_site_domain' ) ) {
|
||||
$this->remove_error( $section, 'email_not_in_site_domain' );
|
||||
|
||||
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
|
||||
$sender = $this->replace_mail_tags( $content );
|
||||
$sender = wpcf7_strip_newline( $sender );
|
||||
|
||||
if ( ! wpcf7_is_email_in_site_domain( $sender ) ) {
|
||||
$this->add_error( $section, 'email_not_in_site_domain',
|
||||
array(
|
||||
'message' => __( "Sender email address does not belong to the site domain.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail recipient section.
|
||||
*/
|
||||
public function validate_mail_recipient( $template, $content ) {
|
||||
$section = sprintf( '%s.recipient', $template );
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
|
||||
$this->remove_error( $section, 'unsafe_email_without_protection' );
|
||||
|
||||
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
|
||||
if (
|
||||
$this->detect_unsafe_email_without_protection( $section, $content )
|
||||
) {
|
||||
$this->add_error( $section, 'unsafe_email_without_protection',
|
||||
array(
|
||||
'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail additional headers section.
|
||||
*/
|
||||
public function validate_mail_additional_headers( $template, $content ) {
|
||||
$section = sprintf( '%s.additional_headers', $template );
|
||||
|
||||
$invalid_mail_headers = array();
|
||||
$invalid_mailbox_fields = array();
|
||||
$unsafe_email_fields = array();
|
||||
|
||||
foreach ( explode( "\n", $content ) as $header ) {
|
||||
$header = trim( $header );
|
||||
|
||||
if ( '' === $header ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$is_valid_header = preg_match(
|
||||
'/^([0-9A-Za-z-]+):(.*)$/',
|
||||
$header,
|
||||
$matches
|
||||
);
|
||||
|
||||
if ( ! $is_valid_header ) {
|
||||
$invalid_mail_headers[] = $header;
|
||||
continue;
|
||||
}
|
||||
|
||||
$header_name = $matches[1];
|
||||
$header_value = trim( $matches[2] );
|
||||
|
||||
if (
|
||||
in_array(
|
||||
strtolower( $header_name ), array( 'reply-to', 'cc', 'bcc' )
|
||||
) and
|
||||
'' !== $header_value and
|
||||
$this->detect_invalid_mailbox_syntax( $section, $header_value )
|
||||
) {
|
||||
$invalid_mailbox_fields[] = $header_name;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
in_array( strtolower( $header_name ), array( 'cc', 'bcc' ) ) and
|
||||
$this->detect_unsafe_email_without_protection( $section, $header_value )
|
||||
) {
|
||||
$unsafe_email_fields[] = $header_name;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'invalid_mail_header' ) ) {
|
||||
if ( ! empty( $invalid_mail_headers ) ) {
|
||||
$this->add_error( $section, 'invalid_mail_header',
|
||||
array(
|
||||
'message' => __( "There are invalid mail header fields.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mail_header' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( ! empty( $invalid_mailbox_fields ) ) {
|
||||
foreach ( $invalid_mailbox_fields as $header_name ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( "Invalid mailbox syntax is used in the %name% field.", 'contact-form-7' ),
|
||||
'params' => array( 'name' => $header_name ),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
|
||||
if ( ! empty( $unsafe_email_fields ) ) {
|
||||
$this->add_error( $section, 'unsafe_email_without_protection',
|
||||
array(
|
||||
'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unsafe_email_without_protection' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail body section.
|
||||
*/
|
||||
public function validate_mail_body( $template, $content ) {
|
||||
$section = sprintf( '%s.body', $template );
|
||||
|
||||
if ( $this->supports( 'maybe_empty' ) ) {
|
||||
if ( $this->detect_maybe_empty( $section, $content ) ) {
|
||||
$this->add_error( $section, 'maybe_empty',
|
||||
array(
|
||||
'message' => __( "There is a possible empty field.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'maybe_empty' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail attachments section.
|
||||
*/
|
||||
public function validate_mail_attachments( $template, $content ) {
|
||||
$section = sprintf( '%s.attachments', $template );
|
||||
|
||||
$total_size = 0;
|
||||
$files_not_found = array();
|
||||
$files_out_of_content = array();
|
||||
|
||||
if ( '' !== $content ) {
|
||||
$attachables = array();
|
||||
|
||||
$tags = $this->contact_form->scan_form_tags(
|
||||
array( 'type' => array( 'file', 'file*' ) )
|
||||
);
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$name = $tag->name;
|
||||
|
||||
if ( ! str_contains( $content, "[{$name}]" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$limit = (int) $tag->get_limit_option();
|
||||
|
||||
if ( empty( $attachables[$name] ) or $attachables[$name] < $limit ) {
|
||||
$attachables[$name] = $limit;
|
||||
}
|
||||
}
|
||||
|
||||
$total_size = array_sum( $attachables );
|
||||
|
||||
foreach ( explode( "\n", $content ) as $line ) {
|
||||
$line = trim( $line );
|
||||
|
||||
if ( '' === $line or str_starts_with( $line, '[' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->detect_file_not_found( $section, $line ) ) {
|
||||
$files_not_found[] = $line;
|
||||
} elseif ( $this->detect_file_not_in_content_dir( $section, $line ) ) {
|
||||
$files_out_of_content[] = $line;
|
||||
} else {
|
||||
$total_size += (int) @filesize( $path );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'file_not_found' ) ) {
|
||||
if ( ! empty( $files_not_found ) ) {
|
||||
foreach ( $files_not_found as $line ) {
|
||||
$this->add_error( $section, 'file_not_found',
|
||||
array(
|
||||
'message' => __( "Attachment file does not exist at %path%.", 'contact-form-7' ),
|
||||
'params' => array( 'path' => $line ),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->remove_error( $section, 'file_not_found' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'file_not_in_content_dir' ) ) {
|
||||
if ( ! empty( $files_out_of_content ) ) {
|
||||
$this->add_error( $section, 'file_not_in_content_dir',
|
||||
array(
|
||||
'message' => __( "It is not allowed to use files outside the wp-content directory.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'file_not_in_content_dir' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'attachments_overweight' ) ) {
|
||||
$max = 25 * MB_IN_BYTES; // 25 MB
|
||||
|
||||
if ( $max < $total_size ) {
|
||||
$this->add_error( $section, 'attachments_overweight',
|
||||
array(
|
||||
'message' => __( "The total size of attachment files is too large.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'attachments_overweight' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of invalid mailbox syntax.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/invalid-mailbox-syntax/
|
||||
*/
|
||||
public function detect_invalid_mailbox_syntax( $section, $content ) {
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( ! wpcf7_is_mailbox_list( $content ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of empty message fields.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/maybe-empty/
|
||||
*/
|
||||
public function detect_maybe_empty( $section, $content ) {
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( '' === $content ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of nonexistent attachment files.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/file-not-found/
|
||||
*/
|
||||
public function detect_file_not_found( $section, $content ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $content );
|
||||
|
||||
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of attachment files out of the content directory.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/file-not-in-content-dir/
|
||||
*/
|
||||
public function detect_file_not_in_content_dir( $section, $content ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $content );
|
||||
|
||||
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of that unsafe email config is used without
|
||||
* sufficient protection.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unsafe-email-without-protection/
|
||||
*/
|
||||
public function detect_unsafe_email_without_protection( $section, $content ) {
|
||||
static $is_recaptcha_active = null;
|
||||
|
||||
if ( null === $is_recaptcha_active ) {
|
||||
$is_recaptcha_active = call_user_func( function () {
|
||||
$service = WPCF7_RECAPTCHA::get_instance();
|
||||
return $service->is_active();
|
||||
} );
|
||||
}
|
||||
|
||||
if ( $is_recaptcha_active ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$example_email = 'user-specified@example.com';
|
||||
|
||||
// Replace mail-tags connected to an email type form-tag first.
|
||||
$content = $this->replace_mail_tags( $content, array(
|
||||
'callback' => function ( $matches ) use ( $example_email ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( $matches[1] === '[' and $matches[4] === ']' ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$form_tags = $this->contact_form->scan_form_tags(
|
||||
array( 'name' => $field_name )
|
||||
);
|
||||
|
||||
if ( $form_tags ) {
|
||||
$form_tag = new WPCF7_FormTag( $form_tags[0] );
|
||||
|
||||
if ( 'email' === $form_tag->basetype ) {
|
||||
return $example_email;
|
||||
}
|
||||
}
|
||||
|
||||
return $tag;
|
||||
},
|
||||
) );
|
||||
|
||||
// Replace remaining mail-tags.
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( str_contains( $content, $example_email ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Messages {
|
||||
|
||||
/**
|
||||
* Runs error detection for the messages section.
|
||||
*/
|
||||
public function validate_messages() {
|
||||
$messages = (array) $this->contact_form->prop( 'messages' );
|
||||
|
||||
if ( ! $messages ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $messages['captcha_not_match'] ) and
|
||||
! wpcf7_use_really_simple_captcha()
|
||||
) {
|
||||
unset( $messages['captcha_not_match'] );
|
||||
}
|
||||
|
||||
foreach ( $messages as $key => $message ) {
|
||||
$section = sprintf( 'messages.%s', $key );
|
||||
|
||||
if ( $this->supports( 'html_in_message' ) ) {
|
||||
if ( $this->detect_html_in_message( $section, $message ) ) {
|
||||
$this->add_error( $section, 'html_in_message',
|
||||
array(
|
||||
'message' => __( "HTML tags are used in a message.", 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'html_in_message' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of HTML uses in a message.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/html-in-message/
|
||||
*/
|
||||
public function detect_html_in_message( $section, $content ) {
|
||||
$stripped = wp_strip_all_tags( $content );
|
||||
|
||||
if ( $stripped !== $content ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once path_join( __DIR__, 'form.php' );
|
||||
require_once path_join( __DIR__, 'mail.php' );
|
||||
require_once path_join( __DIR__, 'messages.php' );
|
||||
require_once path_join( __DIR__, 'additional-settings.php' );
|
||||
require_once path_join( __DIR__, 'actions.php' );
|
||||
|
||||
|
||||
/**
|
||||
* Configuration validator.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/
|
||||
*/
|
||||
class WPCF7_ConfigValidator {
|
||||
|
||||
/**
|
||||
* The plugin version in which important updates happened last time.
|
||||
*/
|
||||
const last_important_update = '5.8.1';
|
||||
|
||||
const error_codes = array(
|
||||
'maybe_empty',
|
||||
'invalid_mailbox_syntax',
|
||||
'email_not_in_site_domain',
|
||||
'html_in_message',
|
||||
'multiple_controls_in_label',
|
||||
'file_not_found',
|
||||
'unavailable_names',
|
||||
'invalid_mail_header',
|
||||
'deprecated_settings',
|
||||
'file_not_in_content_dir',
|
||||
'unavailable_html_elements',
|
||||
'attachments_overweight',
|
||||
'dots_in_names',
|
||||
'colons_in_names',
|
||||
'upload_filesize_overlimit',
|
||||
'unsafe_email_without_protection',
|
||||
);
|
||||
|
||||
use WPCF7_ConfigValidator_Form;
|
||||
use WPCF7_ConfigValidator_Mail;
|
||||
use WPCF7_ConfigValidator_Messages;
|
||||
use WPCF7_ConfigValidator_AdditionalSettings;
|
||||
|
||||
private $contact_form;
|
||||
private $errors = array();
|
||||
private $include;
|
||||
private $exclude;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a URL linking to the documentation page for the error type.
|
||||
*/
|
||||
public static function get_doc_link( $child_page = '' ) {
|
||||
$url = __( 'https://contactform7.com/configuration-errors/',
|
||||
'contact-form-7'
|
||||
);
|
||||
|
||||
if ( '' !== $child_page ) {
|
||||
$child_page = strtr( $child_page, '_', '-' );
|
||||
|
||||
$url = sprintf( '%s/%s', untrailingslashit( $url ), $child_page );
|
||||
}
|
||||
|
||||
return esc_url( $url );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'include' => null,
|
||||
'exclude' => null,
|
||||
) );
|
||||
|
||||
$this->contact_form = $contact_form;
|
||||
|
||||
if ( isset( $args['include'] ) ) {
|
||||
$this->include = (array) $args['include'];
|
||||
}
|
||||
|
||||
if ( isset( $args['exclude'] ) ) {
|
||||
$this->exclude = (array) $args['exclude'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the contact form object that is tied to this validator.
|
||||
*/
|
||||
public function contact_form() {
|
||||
return $this->contact_form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if no error has been detected.
|
||||
*/
|
||||
public function is_valid() {
|
||||
return ! $this->count_errors();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given error code is supported by this instance.
|
||||
*/
|
||||
public function supports( $error_code ) {
|
||||
if ( isset( $this->include ) ) {
|
||||
$supported_codes = array_intersect( self::error_codes, $this->include );
|
||||
} else {
|
||||
$supported_codes = self::error_codes;
|
||||
}
|
||||
|
||||
if ( isset( $this->exclude ) ) {
|
||||
$supported_codes = array_diff( $supported_codes, $this->exclude );
|
||||
}
|
||||
|
||||
return in_array( $error_code, $supported_codes, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Counts detected errors.
|
||||
*/
|
||||
public function count_errors( $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'section' => '',
|
||||
'code' => '',
|
||||
) );
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ( $this->errors as $key => $errors ) {
|
||||
if ( preg_match( '/^mail_[0-9]+\.(.*)$/', $key, $matches ) ) {
|
||||
$key = sprintf( 'mail.%s', $matches[1] );
|
||||
}
|
||||
|
||||
if ( $args['section']
|
||||
and $key !== $args['section']
|
||||
and preg_replace( '/\..*$/', '', $key, 1 ) !== $args['section'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( empty( $error ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $args['code'] and $error['code'] !== $args['code'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects messages for detected errors.
|
||||
*/
|
||||
public function collect_error_messages() {
|
||||
$error_messages = array();
|
||||
|
||||
foreach ( $this->errors as $section => $errors ) {
|
||||
$error_messages[$section] = array();
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( empty( $error['args']['message'] ) ) {
|
||||
$message = $this->get_default_message( $error['code'] );
|
||||
} elseif ( empty( $error['args']['params'] ) ) {
|
||||
$message = $error['args']['message'];
|
||||
} else {
|
||||
$message = $this->build_message(
|
||||
$error['args']['message'],
|
||||
$error['args']['params']
|
||||
);
|
||||
}
|
||||
|
||||
$link = '';
|
||||
|
||||
if ( ! empty( $error['args']['link'] ) ) {
|
||||
$link = $error['args']['link'];
|
||||
}
|
||||
|
||||
$error_messages[$section][] = array(
|
||||
'message' => $message,
|
||||
'link' => esc_url( $link ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $error_messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an error message by replacing placeholders.
|
||||
*/
|
||||
public function build_message( $message, $params = '' ) {
|
||||
$params = wp_parse_args( $params, array() );
|
||||
|
||||
foreach ( $params as $key => $val ) {
|
||||
if ( ! preg_match( '/^[0-9A-Za-z_]+$/', $key ) ) { // invalid key
|
||||
continue;
|
||||
}
|
||||
|
||||
$placeholder = '%' . $key . '%';
|
||||
|
||||
if ( false !== stripos( $message, $placeholder ) ) {
|
||||
$message = str_ireplace( $placeholder, $val, $message );
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a default message that is used when the message for the error
|
||||
* is not specified.
|
||||
*/
|
||||
public function get_default_message( $code = '' ) {
|
||||
return __( "Configuration error is detected.", 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified section has the specified error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
*/
|
||||
public function has_error( $section, $code ) {
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( (array) $this->errors[$section] as $error ) {
|
||||
if ( isset( $error['code'] ) and $error['code'] === $code ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a validation error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
* @param string|array $args Optional options for the error.
|
||||
*/
|
||||
public function add_error( $section, $code, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'message' => '',
|
||||
'params' => array(),
|
||||
) );
|
||||
|
||||
$available_error_codes = (array) apply_filters(
|
||||
'wpcf7_config_validator_available_error_codes',
|
||||
self::error_codes,
|
||||
$this->contact_form
|
||||
);
|
||||
|
||||
if ( ! in_array( $code, $available_error_codes, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $args['link'] ) ) {
|
||||
$args['link'] = self::get_doc_link( $code );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->errors[$section] ) ) {
|
||||
$this->errors[$section] = array();
|
||||
}
|
||||
|
||||
$this->errors[$section][] = array(
|
||||
'code' => $code,
|
||||
'args' => $args,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes an error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
*/
|
||||
public function remove_error( $section, $code ) {
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( (array) $this->errors[$section] as $key => $error ) {
|
||||
if ( isset( $error['code'] ) and $error['code'] === $code ) {
|
||||
unset( $this->errors[$section][$key] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
unset( $this->errors[$section] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main validation runner.
|
||||
*
|
||||
* @return bool True if there is no error detected.
|
||||
*/
|
||||
public function validate() {
|
||||
$this->validate_form();
|
||||
$this->validate_mail( 'mail' );
|
||||
$this->validate_mail( 'mail_2' );
|
||||
$this->validate_messages();
|
||||
$this->validate_additional_settings();
|
||||
|
||||
do_action( 'wpcf7_config_validator_validate', $this );
|
||||
|
||||
return $this->is_valid();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves detected errors as a post meta data.
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->contact_form->initial() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete_post_meta( $this->contact_form->id(), '_config_validation' );
|
||||
|
||||
if ( $this->errors ) {
|
||||
update_post_meta(
|
||||
$this->contact_form->id(), '_config_validation', $this->errors
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore errors from the database.
|
||||
*/
|
||||
public function restore() {
|
||||
$config_errors = get_post_meta(
|
||||
$this->contact_form->id(), '_config_validation', true
|
||||
);
|
||||
|
||||
foreach ( (array) $config_errors as $section => $errors ) {
|
||||
if ( empty( $errors ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( (array) $errors as $error ) {
|
||||
if ( ! empty( $error['code'] ) ) {
|
||||
$code = $error['code'];
|
||||
$args = isset( $error['args'] ) ? $error['args'] : '';
|
||||
$this->add_error( $section, $code, $args );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,471 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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(
|
||||
'<p class="wpcf7-contact-form-not-found"><strong>%1$s</strong> %2$s</p>',
|
||||
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(),
|
||||
) ) );
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_ContactFormTemplate {
|
||||
|
||||
public static function get_default( $prop = 'form' ) {
|
||||
if ( 'form' == $prop ) {
|
||||
$template = self::form();
|
||||
} elseif ( 'mail' == $prop ) {
|
||||
$template = self::mail();
|
||||
} elseif ( 'mail_2' == $prop ) {
|
||||
$template = self::mail_2();
|
||||
} elseif ( 'messages' == $prop ) {
|
||||
$template = self::messages();
|
||||
} else {
|
||||
$template = null;
|
||||
}
|
||||
|
||||
return apply_filters( 'wpcf7_default_template', $template, $prop );
|
||||
}
|
||||
|
||||
public static function form() {
|
||||
$template = sprintf(
|
||||
'
|
||||
<label> %2$s
|
||||
[text* your-name autocomplete:name] </label>
|
||||
|
||||
<label> %3$s
|
||||
[email* your-email autocomplete:email] </label>
|
||||
|
||||
<label> %4$s
|
||||
[text* your-subject] </label>
|
||||
|
||||
<label> %5$s %1$s
|
||||
[textarea your-message] </label>
|
||||
|
||||
[submit "%6$s"]',
|
||||
__( '(optional)', 'contact-form-7' ),
|
||||
__( 'Your name', 'contact-form-7' ),
|
||||
__( 'Your email', 'contact-form-7' ),
|
||||
__( 'Subject', 'contact-form-7' ),
|
||||
__( 'Your message', 'contact-form-7' ),
|
||||
__( 'Submit', 'contact-form-7' )
|
||||
);
|
||||
|
||||
return trim( $template );
|
||||
}
|
||||
|
||||
public static function mail() {
|
||||
$template = array(
|
||||
'subject' => sprintf(
|
||||
/* translators: 1: blog name, 2: [your-subject] */
|
||||
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[your-subject]'
|
||||
),
|
||||
'sender' => sprintf(
|
||||
'%s <%s>',
|
||||
'[_site_title]',
|
||||
self::from_email()
|
||||
),
|
||||
'body' =>
|
||||
sprintf(
|
||||
/* translators: %s: [your-name] [your-email] */
|
||||
__( 'From: %s', 'contact-form-7' ),
|
||||
'[your-name] [your-email]'
|
||||
) . "\n"
|
||||
. sprintf(
|
||||
/* translators: %s: [your-subject] */
|
||||
__( 'Subject: %s', 'contact-form-7' ),
|
||||
'[your-subject]'
|
||||
) . "\n\n"
|
||||
. __( 'Message Body:', 'contact-form-7' )
|
||||
. "\n" . '[your-message]' . "\n\n"
|
||||
. '-- ' . "\n"
|
||||
. sprintf(
|
||||
/* translators: 1: blog name, 2: blog URL */
|
||||
__( 'This is a notification that a contact form was submitted on your website (%1$s %2$s).', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[_site_url]'
|
||||
),
|
||||
'recipient' => '[_site_admin_email]',
|
||||
'additional_headers' => 'Reply-To: [your-email]',
|
||||
'attachments' => '',
|
||||
'use_html' => 0,
|
||||
'exclude_blank' => 0,
|
||||
);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public static function mail_2() {
|
||||
$template = array(
|
||||
'active' => false,
|
||||
'subject' => sprintf(
|
||||
/* translators: 1: blog name, 2: [your-subject] */
|
||||
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[your-subject]'
|
||||
),
|
||||
'sender' => sprintf(
|
||||
'%s <%s>',
|
||||
'[_site_title]',
|
||||
self::from_email()
|
||||
),
|
||||
'body' =>
|
||||
__( 'Message Body:', 'contact-form-7' )
|
||||
. "\n" . '[your-message]' . "\n\n"
|
||||
. '-- ' . "\n"
|
||||
. sprintf(
|
||||
/* translators: 1: blog name, 2: blog URL */
|
||||
__( 'This email is a receipt for your contact form submission on our website (%1$s %2$s) in which your email address was used. If that was not you, please ignore this message.', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[_site_url]'
|
||||
),
|
||||
'recipient' => '[your-email]',
|
||||
'additional_headers' => sprintf(
|
||||
'Reply-To: %s',
|
||||
'[_site_admin_email]'
|
||||
),
|
||||
'attachments' => '',
|
||||
'use_html' => 0,
|
||||
'exclude_blank' => 0,
|
||||
);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public static function from_email() {
|
||||
$admin_email = get_option( 'admin_email' );
|
||||
|
||||
if ( wpcf7_is_localhost() ) {
|
||||
return $admin_email;
|
||||
}
|
||||
|
||||
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
|
||||
$sitename = strtolower( $sitename );
|
||||
|
||||
if ( 'www.' === substr( $sitename, 0, 4 ) ) {
|
||||
$sitename = substr( $sitename, 4 );
|
||||
}
|
||||
|
||||
if ( strpbrk( $admin_email, '@' ) === '@' . $sitename ) {
|
||||
return $admin_email;
|
||||
}
|
||||
|
||||
return 'wordpress@' . $sitename;
|
||||
}
|
||||
|
||||
public static function messages() {
|
||||
$messages = array();
|
||||
|
||||
foreach ( wpcf7_messages() as $key => $arr ) {
|
||||
$messages[$key] = $arr['default'];
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
|
||||
function wpcf7_messages() {
|
||||
$messages = array(
|
||||
'mail_sent_ok' => array(
|
||||
'description'
|
||||
=> __( "Sender's message was sent successfully", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "Thank you for your message. It has been sent.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'mail_sent_ng' => array(
|
||||
'description'
|
||||
=> __( "Sender's message failed to send", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'validation_error' => array(
|
||||
'description'
|
||||
=> __( "Validation errors occurred", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "One or more fields have an error. Please check and try again.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'spam' => array(
|
||||
'description'
|
||||
=> __( "Submission was referred to as spam", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'accept_terms' => array(
|
||||
'description'
|
||||
=> __( "There are terms that the sender must accept", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "You must accept the terms and conditions before sending your message.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_required' => array(
|
||||
'description'
|
||||
=> __( "There is a field that the sender must fill in", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "Please fill out this field.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_too_long' => array(
|
||||
'description'
|
||||
=> __( "There is a field with input that is longer than the maximum allowed length", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "This field has a too long input.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_too_short' => array(
|
||||
'description'
|
||||
=> __( "There is a field with input that is shorter than the minimum allowed length", 'contact-form-7' ),
|
||||
'default'
|
||||
=> __( "This field has a too short input.", 'contact-form-7' ),
|
||||
),
|
||||
);
|
||||
|
||||
return apply_filters( 'wpcf7_messages', $messages );
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Controller for front-end requests, scripts, and styles
|
||||
*/
|
||||
|
||||
|
||||
add_action(
|
||||
'parse_request',
|
||||
'wpcf7_control_init',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Handles a submission in non-Ajax mode.
|
||||
*/
|
||||
function wpcf7_control_init() {
|
||||
if ( WPCF7_Submission::is_restful() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $_POST['_wpcf7'] ) ) {
|
||||
$contact_form = wpcf7_contact_form( (int) $_POST['_wpcf7'] );
|
||||
|
||||
if ( $contact_form ) {
|
||||
$contact_form->submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers main scripts and styles.
|
||||
*/
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () {
|
||||
$assets = array();
|
||||
$asset_file = wpcf7_plugin_path( 'includes/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(
|
||||
'contact-form-7',
|
||||
wpcf7_plugin_url( 'includes/js/index.js' ),
|
||||
array_merge(
|
||||
$assets['dependencies'],
|
||||
array( 'swv' )
|
||||
),
|
||||
$assets['version'],
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'contact-form-7-html5-fallback',
|
||||
wpcf7_plugin_url( 'includes/js/html5-fallback.js' ),
|
||||
array( 'jquery-ui-datepicker' ),
|
||||
WPCF7_VERSION,
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
if ( wpcf7_load_js() ) {
|
||||
wpcf7_enqueue_scripts();
|
||||
}
|
||||
|
||||
wp_register_style(
|
||||
'contact-form-7',
|
||||
wpcf7_plugin_url( 'includes/css/styles.css' ),
|
||||
array(),
|
||||
WPCF7_VERSION,
|
||||
'all'
|
||||
);
|
||||
|
||||
wp_register_style(
|
||||
'contact-form-7-rtl',
|
||||
wpcf7_plugin_url( 'includes/css/styles-rtl.css' ),
|
||||
array( 'contact-form-7' ),
|
||||
WPCF7_VERSION,
|
||||
'all'
|
||||
);
|
||||
|
||||
wp_register_style(
|
||||
'jquery-ui-smoothness',
|
||||
wpcf7_plugin_url(
|
||||
'includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css'
|
||||
),
|
||||
array(),
|
||||
'1.12.1',
|
||||
'screen'
|
||||
);
|
||||
|
||||
if ( wpcf7_load_css() ) {
|
||||
wpcf7_enqueue_styles();
|
||||
}
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Enqueues scripts.
|
||||
*/
|
||||
function wpcf7_enqueue_scripts() {
|
||||
wp_enqueue_script( 'contact-form-7' );
|
||||
|
||||
$wpcf7 = array(
|
||||
'api' => array(
|
||||
'root' => sanitize_url( get_rest_url() ),
|
||||
'namespace' => 'contact-form-7/v1',
|
||||
),
|
||||
);
|
||||
|
||||
if ( defined( 'WP_CACHE' ) and WP_CACHE ) {
|
||||
$wpcf7['cached'] = 1;
|
||||
}
|
||||
|
||||
wp_localize_script( 'contact-form-7', 'wpcf7', $wpcf7 );
|
||||
|
||||
do_action( 'wpcf7_enqueue_scripts' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the main script is enqueued.
|
||||
*/
|
||||
function wpcf7_script_is() {
|
||||
return wp_script_is( 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enqueues styles.
|
||||
*/
|
||||
function wpcf7_enqueue_styles() {
|
||||
wp_enqueue_style( 'contact-form-7' );
|
||||
|
||||
if ( wpcf7_is_rtl() ) {
|
||||
wp_enqueue_style( 'contact-form-7-rtl' );
|
||||
}
|
||||
|
||||
do_action( 'wpcf7_enqueue_styles' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the main stylesheet is enqueued.
|
||||
*/
|
||||
function wpcf7_style_is() {
|
||||
return wp_style_is( 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
'wpcf7_html5_fallback',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Enqueues scripts and styles for the HTML5 fallback.
|
||||
*/
|
||||
function wpcf7_html5_fallback() {
|
||||
if ( ! wpcf7_support_html5_fallback() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( wpcf7_script_is() ) {
|
||||
wp_enqueue_script( 'contact-form-7-html5-fallback' );
|
||||
}
|
||||
|
||||
if ( wpcf7_style_is() ) {
|
||||
wp_enqueue_style( 'jquery-ui-smoothness' );
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
.wpcf7-not-valid-tip {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.use-floating-validation-tip .wpcf7-not-valid-tip {
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item {
|
||||
margin: 0 1em 0 0;
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
.wpcf7 .screen-reader-response {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
.wpcf7 form .wpcf7-response-output {
|
||||
margin: 2em 0.5em 1em;
|
||||
padding: 0.2em 1em;
|
||||
border: 2px solid #00a0d2; /* Blue */
|
||||
}
|
||||
|
||||
.wpcf7 form.init .wpcf7-response-output,
|
||||
.wpcf7 form.resetting .wpcf7-response-output,
|
||||
.wpcf7 form.submitting .wpcf7-response-output {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wpcf7 form.sent .wpcf7-response-output {
|
||||
border-color: #46b450; /* Green */
|
||||
}
|
||||
|
||||
.wpcf7 form.failed .wpcf7-response-output,
|
||||
.wpcf7 form.aborted .wpcf7-response-output {
|
||||
border-color: #dc3232; /* Red */
|
||||
}
|
||||
|
||||
.wpcf7 form.spam .wpcf7-response-output {
|
||||
border-color: #f56e28; /* Orange */
|
||||
}
|
||||
|
||||
.wpcf7 form.invalid .wpcf7-response-output,
|
||||
.wpcf7 form.unaccepted .wpcf7-response-output,
|
||||
.wpcf7 form.payment-required .wpcf7-response-output {
|
||||
border-color: #ffb900; /* Yellow */
|
||||
}
|
||||
|
||||
.wpcf7-form-control-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wpcf7-not-valid-tip {
|
||||
color: #dc3232; /* Red */
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.use-floating-validation-tip .wpcf7-not-valid-tip {
|
||||
position: relative;
|
||||
top: -2ex;
|
||||
left: 1em;
|
||||
z-index: 100;
|
||||
border: 1px solid #dc3232;
|
||||
background: #fff;
|
||||
padding: .2em .8em;
|
||||
width: 24em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item-label::before,
|
||||
.wpcf7-list-item-label::after {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.wpcf7-spinner {
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
background-color: #23282d; /* Dark Gray 800 */
|
||||
opacity: 0.75;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
padding: 0;
|
||||
margin: 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
form.submitting .wpcf7-spinner {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.wpcf7-spinner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: #fbfbfc; /* Light Gray 100 */
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
transform-origin: 8px 8px;
|
||||
animation-name: spin;
|
||||
animation-duration: 1000ms;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.wpcf7-spinner::before {
|
||||
animation-name: blink;
|
||||
animation-duration: 2000ms;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wpcf7 [inert] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="file"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="file"]:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.wpcf7 .wpcf7-submit:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="url"],
|
||||
.wpcf7 input[type="email"],
|
||||
.wpcf7 input[type="tel"] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.wpcf7-reflection > output {
|
||||
display: list-item;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.wpcf7-reflection > output[hidden] {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates uploaded files and moves them to the temporary directory.
|
||||
*
|
||||
* @param array $file An item of `$_FILES`.
|
||||
* @param string|array $args Optional. Arguments to control behavior.
|
||||
* @return array|WP_Error Array of file paths, or WP_Error if validation fails.
|
||||
*/
|
||||
function wpcf7_unship_uploaded_file( $file, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'required' => false,
|
||||
'filetypes' => '',
|
||||
'limit' => MB_IN_BYTES,
|
||||
) );
|
||||
|
||||
foreach ( array( 'name', 'size', 'tmp_name', 'error' ) as $key ) {
|
||||
if ( ! isset( $file[$key] ) ) {
|
||||
$file[$key] = array();
|
||||
}
|
||||
}
|
||||
|
||||
$names = wpcf7_array_flatten( $file['name'] );
|
||||
$sizes = wpcf7_array_flatten( $file['size'] );
|
||||
$tmp_names = wpcf7_array_flatten( $file['tmp_name'] );
|
||||
$errors = wpcf7_array_flatten( $file['error'] );
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( ! empty( $error ) and UPLOAD_ERR_NO_FILE !== $error ) {
|
||||
return new WP_Error( 'wpcf7_upload_failed_php_error',
|
||||
wpcf7_get_message( 'upload_failed_php_error' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $args['schema'] ) and isset( $args['name'] ) ) {
|
||||
$context = array(
|
||||
'file' => true,
|
||||
'field' => $args['name'],
|
||||
);
|
||||
|
||||
foreach ( $args['schema']->validate( $context ) as $result ) {
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move uploaded file to tmp dir
|
||||
$uploads_dir = wpcf7_upload_tmp_dir();
|
||||
$uploads_dir = wpcf7_maybe_add_random_dir( $uploads_dir );
|
||||
|
||||
$uploaded_files = array();
|
||||
|
||||
foreach ( $names as $key => $name ) {
|
||||
$tmp_name = $tmp_names[$key];
|
||||
|
||||
if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $name;
|
||||
$filename = wpcf7_canonicalize( $filename, array( 'strto' => 'as-is' ) );
|
||||
$filename = wpcf7_antiscript_file_name( $filename );
|
||||
|
||||
$filename = apply_filters( 'wpcf7_upload_file_name',
|
||||
$filename, $name, $args
|
||||
);
|
||||
|
||||
$filename = wp_unique_filename( $uploads_dir, $filename );
|
||||
$new_file = path_join( $uploads_dir, $filename );
|
||||
|
||||
if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
|
||||
return new WP_Error( 'wpcf7_upload_failed',
|
||||
wpcf7_get_message( 'upload_failed' )
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure the uploaded file is only readable for the owner process
|
||||
chmod( $new_file, 0400 );
|
||||
|
||||
$uploaded_files[] = $new_file;
|
||||
}
|
||||
|
||||
return $uploaded_files;
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'wpcf7_messages',
|
||||
'wpcf7_file_messages',
|
||||
10, 1
|
||||
);
|
||||
|
||||
/**
|
||||
* A wpcf7_messages filter callback that adds messages for
|
||||
* file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_messages( $messages ) {
|
||||
return array_merge( $messages, array(
|
||||
'upload_failed' => array(
|
||||
'description' => __( "Uploading a file fails for any reason", 'contact-form-7' ),
|
||||
'default' => __( "There was an unknown error uploading the file.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_file_type_invalid' => array(
|
||||
'description' => __( "Uploaded file is not allowed for file type", 'contact-form-7' ),
|
||||
'default' => __( "You are not allowed to upload files of this type.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_file_too_large' => array(
|
||||
'description' => __( "Uploaded file is too large", 'contact-form-7' ),
|
||||
'default' => __( "The uploaded file is too large.", 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_failed_php_error' => array(
|
||||
'description' => __( "Uploading a file fails for PHP error", 'contact-form-7' ),
|
||||
'default' => __( "There was an error uploading the file.", 'contact-form-7' ),
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'wpcf7_form_enctype',
|
||||
'wpcf7_file_form_enctype_filter',
|
||||
10, 1
|
||||
);
|
||||
|
||||
/**
|
||||
* A wpcf7_form_enctype filter callback that sets the enctype attribute
|
||||
* to multipart/form-data if the form has file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_form_enctype_filter( $enctype ) {
|
||||
$multipart = (bool) wpcf7_scan_form_tags( array(
|
||||
'feature' => 'file-uploading',
|
||||
) );
|
||||
|
||||
if ( $multipart ) {
|
||||
$enctype = 'multipart/form-data';
|
||||
}
|
||||
|
||||
return $enctype;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a MIME type string to an array of corresponding file extensions.
|
||||
*
|
||||
* @param string $mime MIME type.
|
||||
* Wildcard (*) is available for the subtype part.
|
||||
* @return array Corresponding file extensions.
|
||||
*/
|
||||
function wpcf7_convert_mime_to_ext( $mime ) {
|
||||
static $mime_types = array();
|
||||
|
||||
$mime_types = wp_get_mime_types();
|
||||
|
||||
$results = array();
|
||||
|
||||
if ( preg_match( '%^([a-z]+)/([*]|[a-z0-9.+-]+)$%i', $mime, $matches ) ) {
|
||||
foreach ( $mime_types as $key => $val ) {
|
||||
if ( '*' === $matches[2] and str_starts_with( $val, $matches[1] . '/' )
|
||||
or $val === $matches[0] ) {
|
||||
$results = array_merge( $results, explode( '|', $key ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = array_unique( $results );
|
||||
$results = array_filter( $results );
|
||||
$results = array_values( $results );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted list of acceptable filetypes.
|
||||
*
|
||||
* @param string|array $types Optional. Array of filetypes.
|
||||
* @param string $format Optional. Pre-defined format designator.
|
||||
* @return string Formatted list of acceptable filetypes.
|
||||
*/
|
||||
function wpcf7_acceptable_filetypes( $types = 'default', $format = 'regex' ) {
|
||||
if ( 'default' === $types or empty( $types ) ) {
|
||||
$types = array(
|
||||
'audio/*',
|
||||
'video/*',
|
||||
'image/*',
|
||||
);
|
||||
} else {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( is_string( $type ) ) {
|
||||
return preg_split( '/[\s|,]+/', strtolower( $type ) );
|
||||
}
|
||||
},
|
||||
(array) $types
|
||||
);
|
||||
|
||||
$types = wpcf7_array_flatten( $types );
|
||||
$types = array_filter( array_unique( $types ) );
|
||||
}
|
||||
|
||||
if ( 'attr' === $format or 'attribute' === $format ) {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( false === strpos( $type, '/' ) ) {
|
||||
return sprintf( '.%s', trim( $type, '.' ) );
|
||||
} elseif ( preg_match( '%^([a-z]+)/[*]$%i', $type, $matches ) ) {
|
||||
if ( in_array( $matches[1], array( 'audio', 'video', 'image' ) ) ) {
|
||||
return $type;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} elseif ( wpcf7_convert_mime_to_ext( $type ) ) {
|
||||
return $type;
|
||||
}
|
||||
},
|
||||
$types
|
||||
);
|
||||
|
||||
$types = array_filter( $types );
|
||||
|
||||
return implode( ',', $types );
|
||||
|
||||
} elseif ( 'regex' === $format ) {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( false === strpos( $type, '/' ) ) {
|
||||
return preg_quote( trim( $type, '.' ) );
|
||||
} elseif ( $type = wpcf7_convert_mime_to_ext( $type ) ) {
|
||||
return $type;
|
||||
}
|
||||
},
|
||||
$types
|
||||
);
|
||||
|
||||
$types = wpcf7_array_flatten( $types );
|
||||
$types = array_filter( array_unique( $types ) );
|
||||
|
||||
return implode( '|', $types );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wpcf7_init',
|
||||
'wpcf7_init_uploads',
|
||||
10, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Initializes the temporary directory for uploaded files.
|
||||
*/
|
||||
function wpcf7_init_uploads() {
|
||||
$dir = wpcf7_upload_tmp_dir();
|
||||
|
||||
if ( is_dir( $dir ) and is_writable( $dir ) ) {
|
||||
$htaccess_file = path_join( $dir, '.htaccess' );
|
||||
|
||||
if ( file_exists( $htaccess_file ) ) {
|
||||
list( $first_line_comment ) = (array) file(
|
||||
$htaccess_file,
|
||||
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
|
||||
);
|
||||
|
||||
if ( '# Apache 2.4+' === $first_line_comment ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
|
||||
fwrite( $handle, "# Apache 2.4+\n" );
|
||||
fwrite( $handle, "<IfModule authz_core_module>\n" );
|
||||
fwrite( $handle, " Require all denied\n" );
|
||||
fwrite( $handle, "</IfModule>\n" );
|
||||
fwrite( $handle, "\n" );
|
||||
fwrite( $handle, "# Apache 2.2\n" );
|
||||
fwrite( $handle, "<IfModule !authz_core_module>\n" );
|
||||
fwrite( $handle, " Deny from all\n" );
|
||||
fwrite( $handle, "</IfModule>\n" );
|
||||
|
||||
fclose( $handle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a child directory with a randomly generated name.
|
||||
*
|
||||
* @param string $dir The parent directory path.
|
||||
* @return string The child directory path if created, otherwise the parent.
|
||||
*/
|
||||
function wpcf7_maybe_add_random_dir( $dir ) {
|
||||
do {
|
||||
$rand_max = mt_getrandmax();
|
||||
$rand = zeroise( mt_rand( 0, $rand_max ), strlen( $rand_max ) );
|
||||
$dir_new = path_join( $dir, $rand );
|
||||
} while ( file_exists( $dir_new ) );
|
||||
|
||||
if ( wp_mkdir_p( $dir_new ) ) {
|
||||
return $dir_new;
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the directory path for uploaded files.
|
||||
*
|
||||
* @return string Directory path.
|
||||
*/
|
||||
function wpcf7_upload_tmp_dir() {
|
||||
if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
|
||||
$dir = path_join( WP_CONTENT_DIR, WPCF7_UPLOADS_TMP_DIR );
|
||||
wp_mkdir_p( $dir );
|
||||
|
||||
if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
|
||||
$dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
|
||||
wp_mkdir_p( $dir );
|
||||
return $dir;
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'shutdown',
|
||||
'wpcf7_cleanup_upload_files',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Cleans up files in the temporary directory for uploaded files.
|
||||
*
|
||||
* @param int $seconds Files older than this are removed. Default 60.
|
||||
* @param int $max Maximum number of files to be removed in a function call.
|
||||
* Default 100.
|
||||
*/
|
||||
function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
|
||||
$dir = trailingslashit( wpcf7_upload_tmp_dir() );
|
||||
|
||||
if ( ! is_dir( $dir )
|
||||
or ! is_readable( $dir )
|
||||
or ! wp_is_writable( $dir ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$seconds = absint( $seconds );
|
||||
$max = absint( $max );
|
||||
$count = 0;
|
||||
|
||||
if ( $handle = opendir( $dir ) ) {
|
||||
while ( false !== ( $file = readdir( $handle ) ) ) {
|
||||
if ( '.' == $file
|
||||
or '..' == $file
|
||||
or '.htaccess' == $file ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mtime = @filemtime( path_join( $dir, $file ) );
|
||||
|
||||
if ( $mtime and time() < $mtime + $seconds ) { // less than $seconds old
|
||||
continue;
|
||||
}
|
||||
|
||||
wpcf7_rmdir_p( path_join( $dir, $file ) );
|
||||
$count += 1;
|
||||
|
||||
if ( $max <= $count ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir( $handle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wpcf7_admin_warnings',
|
||||
'wpcf7_file_display_warning_message',
|
||||
10, 3
|
||||
);
|
||||
|
||||
/**
|
||||
* Displays warning messages about file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_display_warning_message( $page, $action, $object ) {
|
||||
if ( $object instanceof WPCF7_ContactForm ) {
|
||||
$contact_form = $object;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$has_tags = (bool) $contact_form->scan_form_tags( array(
|
||||
'feature' => 'file-uploading',
|
||||
) );
|
||||
|
||||
if ( ! $has_tags ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uploads_dir = wpcf7_upload_tmp_dir();
|
||||
|
||||
if ( ! is_dir( $uploads_dir ) or ! wp_is_writable( $uploads_dir ) ) {
|
||||
$message = sprintf(
|
||||
/* translators: %s: the path of the temporary folder */
|
||||
__( 'This contact form has file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'contact-form-7' ),
|
||||
$uploads_dir
|
||||
);
|
||||
|
||||
echo sprintf(
|
||||
'<div class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( $message )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,580 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A form-tag.
|
||||
*
|
||||
* @link https://contactform7.com/tag-syntax/#form_tag
|
||||
*/
|
||||
class WPCF7_FormTag implements ArrayAccess {
|
||||
|
||||
public $type;
|
||||
public $basetype;
|
||||
public $raw_name = '';
|
||||
public $name = '';
|
||||
public $options = array();
|
||||
public $raw_values = array();
|
||||
public $values = array();
|
||||
public $pipes;
|
||||
public $labels = array();
|
||||
public $attr = '';
|
||||
public $content = '';
|
||||
|
||||
public function __construct( $tag = array() ) {
|
||||
if ( is_array( $tag )
|
||||
or $tag instanceof self ) {
|
||||
foreach ( $tag as $key => $value ) {
|
||||
if ( property_exists( __CLASS__, $key ) ) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the type has a trailing asterisk.
|
||||
*/
|
||||
public function is_required() {
|
||||
return str_ends_with( $this->type, '*' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the form-tag has a specified option.
|
||||
*/
|
||||
public function has_option( $option_name ) {
|
||||
$pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $option_name, '/' ) );
|
||||
return (bool) preg_grep( $pattern, $this->options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves option values with the specified option name.
|
||||
*
|
||||
* @param string $option_name Option name.
|
||||
* @param string $pattern Optional. A regular expression pattern or one of
|
||||
* the keys of preset patterns. If specified, only options
|
||||
* whose value part matches this pattern will be returned.
|
||||
* @param bool $single Optional. If true, only the first matching option
|
||||
* will be returned. Default false.
|
||||
* @return string|array|bool The option value or an array of option values.
|
||||
* False if there is no option matches the pattern.
|
||||
*/
|
||||
public function get_option( $option_name, $pattern = '', $single = false ) {
|
||||
$preset_patterns = array(
|
||||
'date' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
'int' => '[0-9]+',
|
||||
'signed_int' => '[-]?[0-9]+',
|
||||
'num' => '(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
|
||||
'signed_num' => '[-]?(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
|
||||
'class' => '[-0-9a-zA-Z_]+',
|
||||
'id' => '[-0-9a-zA-Z_]+',
|
||||
);
|
||||
|
||||
if ( isset( $preset_patterns[$pattern] ) ) {
|
||||
$pattern = $preset_patterns[$pattern];
|
||||
}
|
||||
|
||||
if ( '' == $pattern ) {
|
||||
$pattern = '.+';
|
||||
}
|
||||
|
||||
$pattern = sprintf(
|
||||
'/^%s:%s$/i',
|
||||
preg_quote( $option_name, '/' ),
|
||||
$pattern
|
||||
);
|
||||
|
||||
if ( $single ) {
|
||||
$matches = $this->get_first_match_option( $pattern );
|
||||
|
||||
if ( ! $matches ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return substr( $matches[0], strlen( $option_name ) + 1 );
|
||||
} else {
|
||||
$matches_a = $this->get_all_match_options( $pattern );
|
||||
|
||||
if ( ! $matches_a ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$results = array();
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
$results[] = substr( $matches[0], strlen( $option_name ) + 1 );
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the id option value from the form-tag.
|
||||
*/
|
||||
public function get_id_option() {
|
||||
static $used = array();
|
||||
|
||||
$option = $this->get_option( 'id', 'id', true );
|
||||
|
||||
if (
|
||||
! $option or
|
||||
str_starts_with( $option, 'wpcf7' ) or
|
||||
in_array( $option, $used, true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$used[] = $option;
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the class option value from the form-tag.
|
||||
*
|
||||
* @param string|array $default_classes Optional. Preset classes as an array
|
||||
* or a whitespace-separated list. Default empty string.
|
||||
* @return string|bool A whitespace-separated list of classes.
|
||||
* False if there is no class to return.
|
||||
*/
|
||||
public function get_class_option( $default_classes = '' ) {
|
||||
if ( is_string( $default_classes ) ) {
|
||||
$default_classes = explode( ' ', $default_classes );
|
||||
}
|
||||
|
||||
$options = array_merge(
|
||||
(array) $default_classes,
|
||||
(array) $this->get_option( 'class' )
|
||||
);
|
||||
|
||||
$options = array_map( 'sanitize_html_class', $options );
|
||||
$options = array_filter( array_unique( $options ) );
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return implode( ' ', $options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the size option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_size_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'size', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
|
||||
|
||||
foreach ( (array) $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the maxlength option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_maxlength_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'maxlength', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%'
|
||||
);
|
||||
|
||||
foreach ( (array) $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the minlength option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_minlength_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'minlength', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
} else {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the cols option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_cols_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'cols', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
|
||||
);
|
||||
|
||||
foreach ( (array) $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the rows option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_rows_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'rows', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
|
||||
);
|
||||
|
||||
foreach ( (array) $matches_a as $matches ) {
|
||||
if ( isset( $matches[2] ) and '' !== $matches[2] ) {
|
||||
return $matches[2];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a date-type option value from the form-tag.
|
||||
*
|
||||
* @param string $option_name A date-type option name, such as 'min' or 'max'.
|
||||
* @return string|bool The option value in YYYY-MM-DD format. False if the
|
||||
* option does not exist or the date value is invalid.
|
||||
*/
|
||||
public function get_date_option( $option_name ) {
|
||||
$option_value = $this->get_option( $option_name, '', true );
|
||||
|
||||
if ( empty( $option_value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$date = apply_filters( 'wpcf7_form_tag_date_option',
|
||||
null,
|
||||
array( $option_name => $option_value )
|
||||
);
|
||||
|
||||
if ( $date ) {
|
||||
$date_pattern = '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/';
|
||||
|
||||
if ( preg_match( $date_pattern, $date, $matches )
|
||||
and checkdate( $matches[2], $matches[3], $matches[1] ) ) {
|
||||
return $date;
|
||||
}
|
||||
} else {
|
||||
$datetime_obj = date_create_immutable(
|
||||
preg_replace( '/[_]+/', ' ', $option_value ),
|
||||
wp_timezone()
|
||||
);
|
||||
|
||||
if ( $datetime_obj ) {
|
||||
return $datetime_obj->format( 'Y-m-d' );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the default option value from the form-tag.
|
||||
*
|
||||
* @param string|array $default_value Optional default value.
|
||||
* @param string|array $args Optional options for the option value retrieval.
|
||||
* @return string|array The option value. If the multiple option is enabled,
|
||||
* an array of option values.
|
||||
*/
|
||||
public function get_default_option( $default_value = '', $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'multiple' => false,
|
||||
'shifted' => false,
|
||||
) );
|
||||
|
||||
$options = (array) $this->get_option( 'default' );
|
||||
$values = array();
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
return $args['multiple'] ? $values : $default_value;
|
||||
}
|
||||
|
||||
foreach ( $options as $opt ) {
|
||||
$opt = sanitize_key( $opt );
|
||||
|
||||
if ( 'user_' == substr( $opt, 0, 5 ) and is_user_logged_in() ) {
|
||||
$primary_props = array( 'user_login', 'user_email', 'user_url' );
|
||||
$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
|
||||
|
||||
$user = wp_get_current_user();
|
||||
$user_prop = $user->get( $opt );
|
||||
|
||||
if ( ! empty( $user_prop ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $user_prop;
|
||||
} else {
|
||||
return $user_prop;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'post_meta' === $opt and in_the_loop() ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values,
|
||||
get_post_meta( get_the_ID(), $this->name )
|
||||
);
|
||||
} else {
|
||||
$val = (string) get_post_meta( get_the_ID(), $this->name, true );
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'get' === $opt and isset( $_GET[$this->name] ) ) {
|
||||
$vals = (array) $_GET[$this->name];
|
||||
$vals = array_map( 'wpcf7_sanitize_query_var', $vals );
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values, $vals );
|
||||
} else {
|
||||
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'post' === $opt and isset( $_POST[$this->name] ) ) {
|
||||
$vals = (array) $_POST[$this->name];
|
||||
$vals = array_map( 'wpcf7_sanitize_query_var', $vals );
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values, $vals );
|
||||
} else {
|
||||
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'shortcode_attr' === $opt ) {
|
||||
if ( $contact_form = WPCF7_ContactForm::get_current() ) {
|
||||
$val = $contact_form->shortcode_attr( $this->name );
|
||||
|
||||
if ( isset( $val ) and strlen( $val ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $val;
|
||||
} else {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( preg_match( '/^[0-9_]+$/', $opt ) ) {
|
||||
$nums = explode( '_', $opt );
|
||||
|
||||
foreach ( $nums as $num ) {
|
||||
$num = absint( $num );
|
||||
$num = $args['shifted'] ? $num : $num - 1;
|
||||
|
||||
if ( isset( $this->values[$num] ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $this->values[$num];
|
||||
} else {
|
||||
return $this->values[$num];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_unique( $values );
|
||||
return $values;
|
||||
} else {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the data option value from the form-tag.
|
||||
*
|
||||
* @param string|array $args Optional options for the option value retrieval.
|
||||
* @return mixed The option value.
|
||||
*/
|
||||
public function get_data_option( $args = '' ) {
|
||||
$options = (array) $this->get_option( 'data' );
|
||||
|
||||
return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the limit option value from the form-tag.
|
||||
*
|
||||
* @param int $default_value Optional default value. Default 1048576.
|
||||
* @return int The option value.
|
||||
*/
|
||||
public function get_limit_option( $default_value = MB_IN_BYTES ) {
|
||||
$pattern = '/^limit:([1-9][0-9]*)([kKmM]?[bB])?$/';
|
||||
|
||||
$matches = $this->get_first_match_option( $pattern );
|
||||
|
||||
if ( $matches ) {
|
||||
$size = (int) $matches[1];
|
||||
|
||||
if ( ! empty( $matches[2] ) ) {
|
||||
$kbmb = strtolower( $matches[2] );
|
||||
|
||||
if ( 'kb' === $kbmb ) {
|
||||
$size *= KB_IN_BYTES;
|
||||
} elseif ( 'mb' === $kbmb ) {
|
||||
$size *= MB_IN_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
return (int) $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the value of the first option matches the given
|
||||
* regular expression pattern.
|
||||
*
|
||||
* @param string $pattern Regular expression pattern.
|
||||
* @return array|bool Option value as an array of matched strings.
|
||||
* False if there is no option matches the pattern.
|
||||
*/
|
||||
public function get_first_match_option( $pattern ) {
|
||||
foreach( (array) $this->options as $option ) {
|
||||
if ( preg_match( $pattern, $option, $matches ) ) {
|
||||
return $matches;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves values of options that match the given
|
||||
* regular expression pattern.
|
||||
*
|
||||
* @param string $pattern Regular expression pattern.
|
||||
* @return array Array of arrays of strings that match the pattern.
|
||||
*/
|
||||
public function get_all_match_options( $pattern ) {
|
||||
$result = array();
|
||||
|
||||
foreach( (array) $this->options as $option ) {
|
||||
if ( preg_match( $pattern, $option, $matches ) ) {
|
||||
$result[] = $matches;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assigns a value to the specified offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetset.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet( $offset, $value ) {
|
||||
if ( property_exists( __CLASS__, $offset ) ) {
|
||||
$this->{$offset} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value at specified offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetget.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet( $offset ) {
|
||||
if ( property_exists( __CLASS__, $offset ) ) {
|
||||
return $this->{$offset};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified offset exists.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists( $offset ) {
|
||||
return property_exists( __CLASS__, $offset );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsets an offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset( $offset ) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,590 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::add().
|
||||
*/
|
||||
function wpcf7_add_form_tag( $tag_types, $callback, $features = '' ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->add( $tag_types, $callback, $features );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::remove().
|
||||
*/
|
||||
function wpcf7_remove_form_tag( $tag_type ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->remove( $tag_type );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::replace_all().
|
||||
*/
|
||||
function wpcf7_replace_all_form_tags( $content ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->replace_all( $content );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_ContactForm::scan_form_tags().
|
||||
*/
|
||||
function wpcf7_scan_form_tags( $cond = null ) {
|
||||
$contact_form = WPCF7_ContactForm::get_current();
|
||||
|
||||
if ( $contact_form ) {
|
||||
return $contact_form->scan_form_tags( $cond );
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::tag_type_supports().
|
||||
*/
|
||||
function wpcf7_form_tag_supports( $tag_type, $feature ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->tag_type_supports( $tag_type, $feature );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The singleton instance of this class manages the collection of form-tags.
|
||||
*/
|
||||
class WPCF7_FormTagsManager {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $tag_types = array();
|
||||
private $scanned_tags = null; // Tags scanned at the last time of scan()
|
||||
private $placeholders = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance.
|
||||
*
|
||||
* @return WPCF7_FormTagsManager The singleton manager.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns scanned form-tags.
|
||||
*
|
||||
* @return array Array of WPCF7_FormTag objects.
|
||||
*/
|
||||
public function get_scanned_tags() {
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers form-tag types to the manager.
|
||||
*
|
||||
* @param string|array $tag_types The name of the form-tag type or
|
||||
* an array of the names.
|
||||
* @param callable $callback The callback to generates a form control HTML
|
||||
* for a form-tag in this type.
|
||||
* @param string|array $features Optional. Features a form-tag
|
||||
* in this type supports.
|
||||
*/
|
||||
public function add( $tag_types, $callback, $features = '' ) {
|
||||
if ( ! is_callable( $callback ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( true === $features ) { // for back-compat
|
||||
$features = array( 'name-attr' => true );
|
||||
}
|
||||
|
||||
$features = wp_parse_args( $features, array() );
|
||||
|
||||
$tag_types = array_filter( array_unique( (array) $tag_types ) );
|
||||
|
||||
foreach ( $tag_types as $tag_type ) {
|
||||
$tag_type = $this->sanitize_tag_type( $tag_type );
|
||||
|
||||
if ( ! $this->tag_type_exists( $tag_type ) ) {
|
||||
$this->tag_types[$tag_type] = array(
|
||||
'function' => $callback,
|
||||
'features' => $features,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given tag type exists.
|
||||
*/
|
||||
public function tag_type_exists( $tag_type ) {
|
||||
return isset( $this->tag_types[$tag_type] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the tag type supports the features.
|
||||
*
|
||||
* @param string $tag_type The name of the form-tag type.
|
||||
* @param array|string $features The feature to check or an array of features.
|
||||
* @return bool True if the form-tag type supports at least one of
|
||||
* the given features, false otherwise.
|
||||
*/
|
||||
public function tag_type_supports( $tag_type, $features ) {
|
||||
$features = array_filter( (array) $features );
|
||||
|
||||
if ( isset( $this->tag_types[$tag_type]['features'] ) ) {
|
||||
return (bool) array_intersect(
|
||||
array_keys( array_filter( $this->tag_types[$tag_type]['features'] ) ),
|
||||
$features
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns form-tag types that support the given features.
|
||||
*
|
||||
* @param array|string $features Optional. The feature to check or
|
||||
* an array of features. Default empty array.
|
||||
* @param bool $invert Optional. If this value is true, returns form-tag
|
||||
* types that do not support the given features. Default false.
|
||||
* @return array An array of form-tag types. If the $features param is empty,
|
||||
* returns all form-tag types that have been registered.
|
||||
*/
|
||||
public function collect_tag_types( $features = array(), $invert = false ) {
|
||||
$tag_types = array_keys( $this->tag_types );
|
||||
|
||||
if ( empty( $features ) ) {
|
||||
return $tag_types;
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ( $tag_types as $tag_type ) {
|
||||
if ( ! $invert && $this->tag_type_supports( $tag_type, $features )
|
||||
|| $invert && ! $this->tag_type_supports( $tag_type, $features ) ) {
|
||||
$output[] = $tag_type;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the form-tag type name.
|
||||
*/
|
||||
private function sanitize_tag_type( $tag_type ) {
|
||||
$tag_type = preg_replace( '/[^a-zA-Z0-9_*]+/', '_', $tag_type );
|
||||
$tag_type = rtrim( $tag_type, '_' );
|
||||
$tag_type = strtolower( $tag_type );
|
||||
return $tag_type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deregisters the form-tag type.
|
||||
*/
|
||||
public function remove( $tag_type ) {
|
||||
unset( $this->tag_types[$tag_type] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the text content that includes form-tags.
|
||||
*/
|
||||
public function normalize( $content ) {
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$content = preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/s',
|
||||
array( $this, 'normalize_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function used within normalize().
|
||||
*/
|
||||
private function normalize_callback( $matches ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( $matches[1] == '['
|
||||
and $matches[6] == ']' ) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$tag = $matches[2];
|
||||
|
||||
$attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $matches[3] ) );
|
||||
$attr = strtr( $attr, array( '<' => '<', '>' => '>' ) );
|
||||
|
||||
$content = trim( $matches[5] );
|
||||
$content = str_replace( "\n", '<WPPreserveNewline />', $content );
|
||||
|
||||
$result = $matches[1] . '[' . $tag
|
||||
. ( $attr ? ' ' . $attr : '' )
|
||||
. ( $matches[4] ? ' ' . $matches[4] : '' )
|
||||
. ']'
|
||||
. ( $content ? $content . '[/' . $tag . ']' : '' )
|
||||
. $matches[6];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace all form-tags in the given text with placeholders.
|
||||
*/
|
||||
public function replace_with_placeholders( $content ) {
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$this->placeholders = array();
|
||||
|
||||
$callback = function ( $matches ) {
|
||||
// Allow [[foo]] syntax for escaping a tag.
|
||||
if ( '[' === $matches[1] and ']' === $matches[6] ) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tag_type = $matches[2];
|
||||
|
||||
$block_or_hidden = $this->tag_type_supports(
|
||||
$tag_type,
|
||||
array( 'display-block', 'display-hidden' )
|
||||
);
|
||||
|
||||
if ( $block_or_hidden ) {
|
||||
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_block;
|
||||
} else {
|
||||
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_inline;
|
||||
}
|
||||
|
||||
$placeholder = sprintf(
|
||||
'<%1$s id="%2$s" />',
|
||||
$placeholder_tag_name,
|
||||
sha1( $tag )
|
||||
);
|
||||
|
||||
list( $placeholder ) =
|
||||
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
|
||||
|
||||
$this->placeholders[$placeholder] = $tag;
|
||||
|
||||
return $placeholder;
|
||||
};
|
||||
|
||||
return preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/s',
|
||||
$callback,
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace placeholders in the given text with original form-tags.
|
||||
*/
|
||||
public function restore_from_placeholders( $content ) {
|
||||
return str_replace(
|
||||
array_keys( $this->placeholders ),
|
||||
array_values( $this->placeholders ),
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces all form-tags in the text content.
|
||||
*
|
||||
* @param string $content The text content including form-tags.
|
||||
* @return string The result of replacements.
|
||||
*/
|
||||
public function replace_all( $content ) {
|
||||
return $this->scan( $content, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scans form-tags in the text content.
|
||||
*
|
||||
* @param string $content The text content including form-tags.
|
||||
* @param bool $replace Optional. Whether scanned form-tags will be
|
||||
* replaced. Default false.
|
||||
* @return array|string An array of scanned form-tags if $replace is false.
|
||||
* Otherwise text that scanned form-tags are replaced.
|
||||
*/
|
||||
public function scan( $content, $replace = false ) {
|
||||
$this->scanned_tags = array();
|
||||
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
if ( $replace ) {
|
||||
return $content;
|
||||
} else {
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $replace ) {
|
||||
$content = preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/s',
|
||||
array( $this, 'replace_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $content;
|
||||
} else {
|
||||
preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/s',
|
||||
array( $this, 'scan_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters form-tags based on a condition array argument.
|
||||
*
|
||||
* @param array|string $input The original form-tags collection.
|
||||
* If it is a string, scans form-tags from it.
|
||||
* @param array $cond The conditions that filtering will be based on.
|
||||
* @return array The filtered form-tags collection.
|
||||
*/
|
||||
public function filter( $input, $cond ) {
|
||||
if ( is_array( $input ) ) {
|
||||
$tags = $input;
|
||||
} elseif ( is_string( $input ) ) {
|
||||
$tags = $this->scan( $input );
|
||||
} else {
|
||||
$tags = $this->scanned_tags;
|
||||
}
|
||||
|
||||
$cond = wp_parse_args( $cond, array(
|
||||
'type' => array(),
|
||||
'basetype' => array(),
|
||||
'name' => array(),
|
||||
'feature' => array(),
|
||||
) );
|
||||
|
||||
$cond = array_map( static function ( $c ) {
|
||||
return array_filter( array_map( 'trim', (array) $c ) );
|
||||
}, $cond );
|
||||
|
||||
$tags = array_filter(
|
||||
(array) $tags,
|
||||
function ( $tag ) use ( $cond ) {
|
||||
$tag = new WPCF7_FormTag( $tag );
|
||||
|
||||
if ( $cond['type']
|
||||
and ! in_array( $tag->type, $cond['type'], true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $cond['basetype']
|
||||
and ! in_array( $tag->basetype, $cond['basetype'], true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $cond['name']
|
||||
and ! in_array( $tag->name, $cond['name'], true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $cond['feature'] as $feature ) {
|
||||
if ( '!' === substr( $feature, 0, 1 ) ) { // Negation
|
||||
$feature = trim( substr( $feature, 1 ) );
|
||||
|
||||
if ( $this->tag_type_supports( $tag->type, $feature ) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( ! $this->tag_type_supports( $tag->type, $feature ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
return array_values( $tags );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the regular expression for a form-tag.
|
||||
*/
|
||||
private function tag_regex() {
|
||||
$tagnames = array_keys( $this->tag_types );
|
||||
$tagregexp = implode( '|', array_map( 'preg_quote', $tagnames ) );
|
||||
|
||||
return '(\[?)'
|
||||
. '\[(' . $tagregexp . ')(?:[\r\n\t ](.*?))?(?:[\r\n\t ](\/))?\]'
|
||||
. '(?:([^[]*?)\[\/\2\])?'
|
||||
. '(\]?)';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function for the form-tag replacement.
|
||||
*/
|
||||
private function replace_callback( $matches ) {
|
||||
return $this->scan_callback( $matches, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function for the form-tag scanning.
|
||||
*/
|
||||
private function scan_callback( $matches, $replace = false ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( $matches[1] == '['
|
||||
and $matches[6] == ']' ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag_type = $matches[2];
|
||||
$tag_basetype = trim( $tag_type, '*' );
|
||||
$attr = $this->parse_atts( $matches[3] );
|
||||
|
||||
$scanned_tag = array(
|
||||
'type' => $tag_type,
|
||||
'basetype' => $tag_basetype,
|
||||
'raw_name' => '',
|
||||
'name' => '',
|
||||
'options' => array(),
|
||||
'raw_values' => array(),
|
||||
'values' => array(),
|
||||
'pipes' => null,
|
||||
'labels' => array(),
|
||||
'attr' => '',
|
||||
'content' => '',
|
||||
);
|
||||
|
||||
if ( $this->tag_type_supports( $tag_type, 'singular' ) ) {
|
||||
$tags_in_same_basetype = $this->filter(
|
||||
$this->scanned_tags,
|
||||
array( 'basetype' => $tag_basetype )
|
||||
);
|
||||
|
||||
if ( $tags_in_same_basetype ) {
|
||||
// Another tag in the same base type already exists. Ignore this one.
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->tag_type_supports( $tag_type, 'name-attr' ) ) {
|
||||
if ( ! is_array( $attr ) ) {
|
||||
return $matches[0]; // Invalid form-tag.
|
||||
}
|
||||
|
||||
$scanned_tag['raw_name'] = (string) array_shift( $attr['options'] );
|
||||
|
||||
if ( ! wpcf7_is_name( $scanned_tag['raw_name'] ) ) {
|
||||
return $matches[0]; // Invalid name is used. Ignore this tag.
|
||||
}
|
||||
|
||||
$scanned_tag['name'] = strtr( $scanned_tag['raw_name'], '.', '_' );
|
||||
}
|
||||
|
||||
if ( is_array( $attr ) ) {
|
||||
$scanned_tag['options'] = (array) $attr['options'];
|
||||
$scanned_tag['raw_values'] = (array) $attr['values'];
|
||||
|
||||
if ( WPCF7_USE_PIPE ) {
|
||||
$pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
|
||||
$scanned_tag['values'] = $pipes->collect_befores();
|
||||
$scanned_tag['pipes'] = $pipes;
|
||||
} else {
|
||||
$scanned_tag['values'] = $scanned_tag['raw_values'];
|
||||
}
|
||||
|
||||
$scanned_tag['labels'] = $scanned_tag['values'];
|
||||
|
||||
} else {
|
||||
$scanned_tag['attr'] = $attr;
|
||||
}
|
||||
|
||||
$scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
|
||||
$scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );
|
||||
|
||||
$content = trim( $matches[5] );
|
||||
$content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
|
||||
$scanned_tag['content'] = $content;
|
||||
|
||||
$scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $replace );
|
||||
|
||||
$scanned_tag = new WPCF7_FormTag( $scanned_tag );
|
||||
|
||||
$this->scanned_tags[] = $scanned_tag;
|
||||
|
||||
if ( $replace ) {
|
||||
$callback = $this->tag_types[$tag_type]['function'];
|
||||
return $matches[1] . call_user_func( $callback, $scanned_tag ) . $matches[6];
|
||||
} else {
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the attributes of a form-tag to extract the name,
|
||||
* options, and values.
|
||||
*
|
||||
* @param string $text Attributes of a form-tag.
|
||||
* @return array|string An associative array of the options and values
|
||||
* if the input is in the correct syntax,
|
||||
* otherwise the input text itself.
|
||||
*/
|
||||
private function parse_atts( $text ) {
|
||||
$atts = array( 'options' => array(), 'values' => array() );
|
||||
$text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
|
||||
$text = trim( $text );
|
||||
|
||||
$pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
|
||||
|
||||
if ( preg_match( $pattern, $text, $matches ) ) {
|
||||
if ( ! empty( $matches[1] ) ) {
|
||||
$atts['options'] = preg_split( '/[\r\n\t ]+/', trim( $matches[1] ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $matches[2] ) ) {
|
||||
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $matches[2], $matched_values );
|
||||
$atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
|
||||
}
|
||||
} else {
|
||||
$atts = $text;
|
||||
}
|
||||
|
||||
return $atts;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,569 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Replaces double line breaks with paragraph elements.
|
||||
*
|
||||
* @param string $input The text which has to be formatted.
|
||||
* @param bool $br Optional. If set, this will convert all remaining
|
||||
* line breaks after paragraphing. Default true.
|
||||
* @return string Text which has been converted into correct paragraph tags.
|
||||
*/
|
||||
function wpcf7_autop( $input, $br = true ) {
|
||||
$placeholders = array();
|
||||
|
||||
// Replace non-HTML embedded elements with placeholders.
|
||||
$input = preg_replace_callback(
|
||||
'/<(math|svg).*?<\/\1>/is',
|
||||
static function ( $matches ) use ( &$placeholders ) {
|
||||
$placeholder = sprintf(
|
||||
'<%1$s id="%2$s" />',
|
||||
WPCF7_HTMLFormatter::placeholder_inline,
|
||||
sha1( $matches[0] )
|
||||
);
|
||||
|
||||
list( $placeholder ) =
|
||||
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
|
||||
|
||||
$placeholders[$placeholder] = $matches[0];
|
||||
|
||||
return $placeholder;
|
||||
},
|
||||
$input
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'auto_br' => $br,
|
||||
) );
|
||||
|
||||
$chunks = $formatter->separate_into_chunks( $input );
|
||||
|
||||
$output = $formatter->format( $chunks );
|
||||
|
||||
// Restore from placeholders.
|
||||
$output = str_replace(
|
||||
array_keys( $placeholders ),
|
||||
array_values( $placeholders ),
|
||||
$output
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Newline preservation help function for wpcf7_autop().
|
||||
*
|
||||
* @deprecated 5.7 Unnecessary to use any more.
|
||||
*
|
||||
* @param array $matches preg_replace_callback() matches array.
|
||||
* @return string Text including newline placeholders.
|
||||
*/
|
||||
function wpcf7_autop_preserve_newline_callback( $matches ) {
|
||||
return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the query variables.
|
||||
*
|
||||
* @param string $text Query variable.
|
||||
* @return string Text sanitized.
|
||||
*/
|
||||
function wpcf7_sanitize_query_var( $text ) {
|
||||
$text = wp_unslash( $text );
|
||||
$text = wp_check_invalid_utf8( $text );
|
||||
|
||||
if ( false !== strpos( $text, '<' ) ) {
|
||||
$text = wp_pre_kses_less_than( $text );
|
||||
$text = wp_strip_all_tags( $text );
|
||||
}
|
||||
|
||||
$text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
|
||||
$text = preg_replace( '/ +/', ' ', $text );
|
||||
$text = trim( $text, ' ' );
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strips quote characters surrounding the input.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @return string Processed output.
|
||||
*/
|
||||
function wpcf7_strip_quote( $text ) {
|
||||
$text = trim( $text );
|
||||
|
||||
if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
|
||||
$text = $matches[1];
|
||||
} elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
|
||||
$text = $matches[1];
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigates through an array, object, or scalar, and
|
||||
* strips quote characters surrounding the each value.
|
||||
*
|
||||
* @param mixed $input The array or string to be processed.
|
||||
* @return mixed Processed value.
|
||||
*/
|
||||
function wpcf7_strip_quote_deep( $input ) {
|
||||
if ( is_string( $input ) ) {
|
||||
return wpcf7_strip_quote( $input );
|
||||
}
|
||||
|
||||
if ( is_array( $input ) ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( $input as $key => $text ) {
|
||||
$result[$key] = wpcf7_strip_quote_deep( $text );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes newline characters.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @param string $to Optional. The newline character that is used in the output.
|
||||
* @return string Normalized text.
|
||||
*/
|
||||
function wpcf7_normalize_newline( $text, $to = "\n" ) {
|
||||
if ( ! is_string( $text ) ) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$nls = array( "\r\n", "\r", "\n" );
|
||||
|
||||
if ( ! in_array( $to, $nls ) ) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return str_replace( $nls, $to, $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigates through an array, object, or scalar, and
|
||||
* normalizes newline characters in the each value.
|
||||
*
|
||||
* @param mixed $input The array or string to be processed.
|
||||
* @param string $to Optional. The newline character that is used in the output.
|
||||
* @return mixed Processed value.
|
||||
*/
|
||||
function wpcf7_normalize_newline_deep( $input, $to = "\n" ) {
|
||||
if ( is_array( $input ) ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( $input as $key => $text ) {
|
||||
$result[$key] = wpcf7_normalize_newline_deep( $text, $to );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return wpcf7_normalize_newline( $input, $to );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strips newline characters.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @return string Processed one-line text.
|
||||
*/
|
||||
function wpcf7_strip_newline( $text ) {
|
||||
$text = (string) $text;
|
||||
$text = str_replace( array( "\r", "\n" ), '', $text );
|
||||
return trim( $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Canonicalizes text.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @param string|array|object $args Options.
|
||||
* @return string Canonicalized text.
|
||||
*/
|
||||
function wpcf7_canonicalize( $text, $args = '' ) {
|
||||
// for back-compat
|
||||
if ( is_string( $args ) and '' !== $args
|
||||
and false === strpos( $args, '=' ) ) {
|
||||
$args = array(
|
||||
'strto' => $args,
|
||||
);
|
||||
}
|
||||
|
||||
$args = wp_parse_args( $args, array(
|
||||
'strto' => 'lower',
|
||||
'strip_separators' => false,
|
||||
) );
|
||||
|
||||
static $charset = null;
|
||||
|
||||
if ( ! isset( $charset ) ) {
|
||||
$charset = get_option( 'blog_charset' );
|
||||
|
||||
$is_utf8 = in_array(
|
||||
$charset,
|
||||
array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' )
|
||||
);
|
||||
|
||||
if ( $is_utf8 ) {
|
||||
$charset = 'UTF-8';
|
||||
}
|
||||
}
|
||||
|
||||
$text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );
|
||||
|
||||
if ( function_exists( 'mb_convert_kana' ) ) {
|
||||
$text = mb_convert_kana( $text, 'asKV', $charset );
|
||||
}
|
||||
|
||||
if ( $args['strip_separators'] ) {
|
||||
$text = preg_replace( '/[\r\n\t ]+/', '', $text );
|
||||
} else {
|
||||
$text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
|
||||
}
|
||||
|
||||
if ( 'lower' == $args['strto'] ) {
|
||||
if ( function_exists( 'mb_strtolower' ) ) {
|
||||
$text = mb_strtolower( $text, $charset );
|
||||
} else {
|
||||
$text = strtolower( $text );
|
||||
}
|
||||
} elseif ( 'upper' == $args['strto'] ) {
|
||||
if ( function_exists( 'mb_strtoupper' ) ) {
|
||||
$text = mb_strtoupper( $text, $charset );
|
||||
} else {
|
||||
$text = strtoupper( $text );
|
||||
}
|
||||
}
|
||||
|
||||
$text = trim( $text );
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes Contact Form 7's form unit-tag.
|
||||
*
|
||||
* @param string $tag Unit-tag.
|
||||
* @return string Sanitized unit-tag.
|
||||
*/
|
||||
function wpcf7_sanitize_unit_tag( $tag ) {
|
||||
$tag = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $tag );
|
||||
return $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a file name to one that is not executable as a script.
|
||||
*
|
||||
* @param string $filename File name.
|
||||
* @return string Converted file name.
|
||||
*/
|
||||
function wpcf7_antiscript_file_name( $filename ) {
|
||||
$filename = wp_basename( $filename );
|
||||
|
||||
// Apply part of protection logic from sanitize_file_name().
|
||||
$filename = str_replace(
|
||||
array(
|
||||
'?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
|
||||
'&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
|
||||
'%', '+', '’', '«', '»', '”', '“', chr( 0 )
|
||||
),
|
||||
'',
|
||||
$filename
|
||||
);
|
||||
|
||||
$filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
|
||||
$filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
|
||||
|
||||
$parts = explode( '.', $filename );
|
||||
|
||||
if ( count( $parts ) < 2 ) {
|
||||
return $filename;
|
||||
}
|
||||
|
||||
$script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';
|
||||
|
||||
$filename = array_shift( $parts );
|
||||
$extension = array_pop( $parts );
|
||||
|
||||
foreach ( (array) $parts as $part ) {
|
||||
if ( preg_match( $script_pattern, $part ) ) {
|
||||
$filename .= '.' . $part . '_';
|
||||
} else {
|
||||
$filename .= '.' . $part;
|
||||
}
|
||||
}
|
||||
|
||||
if ( preg_match( $script_pattern, $extension ) ) {
|
||||
$filename .= '.' . $extension . '_.txt';
|
||||
} else {
|
||||
$filename .= '.' . $extension;
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Masks a password with asterisks (*).
|
||||
*
|
||||
* @param int $right Length of right-hand unmasked text. Default 0.
|
||||
* @param int $left Length of left-hand unmasked text. Default 0.
|
||||
* @return string Text of masked password.
|
||||
*/
|
||||
function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
|
||||
$length = strlen( $text );
|
||||
|
||||
$right = absint( $right );
|
||||
$left = absint( $left );
|
||||
|
||||
if ( $length < $right + $left ) {
|
||||
$right = $left = 0;
|
||||
}
|
||||
|
||||
if ( $length <= 48 ) {
|
||||
$masked = str_repeat( '*', $length - ( $right + $left ) );
|
||||
} elseif ( $right + $left < 48 ) {
|
||||
$masked = str_repeat( '*', 48 - ( $right + $left ) );
|
||||
} else {
|
||||
$masked = '****';
|
||||
}
|
||||
|
||||
$left_unmasked = $left ? substr( $text, 0, $left ) : '';
|
||||
$right_unmasked = $right ? substr( $text, -1 * $right ) : '';
|
||||
|
||||
$text = $left_unmasked . $masked . $right_unmasked;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of allowed HTML tags and attributes for a given context.
|
||||
*
|
||||
* @param string $context Context used to decide allowed tags and attributes.
|
||||
* @return array Array of allowed HTML tags and their allowed attributes.
|
||||
*/
|
||||
function wpcf7_kses_allowed_html( $context = 'form' ) {
|
||||
static $allowed_tags = array();
|
||||
|
||||
if ( isset( $allowed_tags[$context] ) ) {
|
||||
return apply_filters(
|
||||
'wpcf7_kses_allowed_html',
|
||||
$allowed_tags[$context],
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
$allowed_tags[$context] = wp_kses_allowed_html( 'post' );
|
||||
|
||||
if ( 'form' === $context ) {
|
||||
$additional_tags_for_form = array(
|
||||
'button' => array(
|
||||
'disabled' => true,
|
||||
'name' => true,
|
||||
'type' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'datalist' => array(),
|
||||
'fieldset' => array(
|
||||
'disabled' => true,
|
||||
'name' => true,
|
||||
),
|
||||
'input' => array(
|
||||
'accept' => true,
|
||||
'alt' => true,
|
||||
'capture' => true,
|
||||
'checked' => true,
|
||||
'disabled' => true,
|
||||
'list' => true,
|
||||
'max' => true,
|
||||
'maxlength' => true,
|
||||
'min' => true,
|
||||
'minlength' => true,
|
||||
'multiple' => true,
|
||||
'name' => true,
|
||||
'placeholder' => true,
|
||||
'readonly' => true,
|
||||
'size' => true,
|
||||
'step' => true,
|
||||
'type' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'for' => true,
|
||||
),
|
||||
'legend' => array(),
|
||||
'meter' => array(
|
||||
'value' => true,
|
||||
'min' => true,
|
||||
'max' => true,
|
||||
'low' => true,
|
||||
'high' => true,
|
||||
'optimum' => true,
|
||||
),
|
||||
'optgroup' => array(
|
||||
'disabled' => true,
|
||||
'label' => true,
|
||||
),
|
||||
'option' => array(
|
||||
'disabled' => true,
|
||||
'label' => true,
|
||||
'selected' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'output' => array(
|
||||
'for' => true,
|
||||
'name' => true,
|
||||
),
|
||||
'progress' => array(
|
||||
'max' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'select' => array(
|
||||
'disabled' => true,
|
||||
'multiple' => true,
|
||||
'name' => true,
|
||||
'size' => true,
|
||||
),
|
||||
'textarea' => array(
|
||||
'cols' => true,
|
||||
'disabled' => true,
|
||||
'maxlength' => true,
|
||||
'minlength' => true,
|
||||
'name' => true,
|
||||
'placeholder' => true,
|
||||
'readonly' => true,
|
||||
'rows' => true,
|
||||
'spellcheck' => true,
|
||||
'wrap' => true,
|
||||
),
|
||||
);
|
||||
|
||||
$additional_tags_for_form = array_map(
|
||||
static function ( $elm ) {
|
||||
$global_attributes = array(
|
||||
'aria-atomic' => true,
|
||||
'aria-checked' => true,
|
||||
'aria-describedby' => true,
|
||||
'aria-details' => true,
|
||||
'aria-disabled' => true,
|
||||
'aria-hidden' => true,
|
||||
'aria-invalid' => true,
|
||||
'aria-label' => true,
|
||||
'aria-labelledby' => true,
|
||||
'aria-live' => true,
|
||||
'aria-relevant' => true,
|
||||
'aria-required' => true,
|
||||
'aria-selected' => true,
|
||||
'class' => true,
|
||||
'data-*' => true,
|
||||
'id' => true,
|
||||
'inputmode' => true,
|
||||
'role' => true,
|
||||
'style' => true,
|
||||
'tabindex' => true,
|
||||
'title' => true,
|
||||
);
|
||||
|
||||
return array_merge( $global_attributes, (array) $elm );
|
||||
},
|
||||
$additional_tags_for_form
|
||||
);
|
||||
|
||||
$allowed_tags[$context] = array_merge(
|
||||
$allowed_tags[$context],
|
||||
$additional_tags_for_form
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters(
|
||||
'wpcf7_kses_allowed_html',
|
||||
$allowed_tags[$context],
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes content for allowed HTML tags for the specified context.
|
||||
*
|
||||
* @param string $input Content to filter.
|
||||
* @param string $context Context used to decide allowed tags and attributes.
|
||||
* @return string Filtered text with allowed HTML tags and attributes intact.
|
||||
*/
|
||||
function wpcf7_kses( $input, $context = 'form' ) {
|
||||
$output = wp_kses(
|
||||
$input,
|
||||
wpcf7_kses_allowed_html( $context )
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string of HTML attributes.
|
||||
*
|
||||
* @param array $atts Associative array of attribute name and value pairs.
|
||||
* @return string Formatted HTML attributes.
|
||||
*/
|
||||
function wpcf7_format_atts( $atts ) {
|
||||
$atts_filtered = array();
|
||||
|
||||
foreach ( $atts as $name => $value ) {
|
||||
$name = strtolower( trim( $name ) );
|
||||
|
||||
if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
static $boolean_attributes = array(
|
||||
'checked',
|
||||
'disabled',
|
||||
'inert',
|
||||
'multiple',
|
||||
'readonly',
|
||||
'required',
|
||||
'selected',
|
||||
);
|
||||
|
||||
if ( in_array( $name, $boolean_attributes ) and '' === $value ) {
|
||||
$value = false;
|
||||
}
|
||||
|
||||
if ( is_numeric( $value ) ) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if ( null === $value or false === $value ) {
|
||||
unset( $atts_filtered[$name] );
|
||||
} elseif ( true === $value ) {
|
||||
$atts_filtered[$name] = $name; // boolean attribute
|
||||
} elseif ( is_string( $value ) ) {
|
||||
$atts_filtered[$name] = trim( $value );
|
||||
}
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ( $atts_filtered as $name => $value ) {
|
||||
$output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
|
||||
}
|
||||
|
||||
return trim( $output );
|
||||
}
|
||||
@@ -1,695 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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(
|
||||
'<a %1$s>%2$s</a>',
|
||||
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() );
|
||||
$request_uri = '/' . ltrim( $request_uri, '/' );
|
||||
}
|
||||
|
||||
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 <strong>deprecated</strong> 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 <strong>deprecated</strong> 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 <strong>deprecated</strong> 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 <strong>deprecated</strong> 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 ) );
|
||||
}
|
||||
@@ -1,678 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Contact Form 7's class used for formatting HTML fragments.
|
||||
*/
|
||||
class WPCF7_HTMLFormatter {
|
||||
|
||||
// HTML component types.
|
||||
const text = 0;
|
||||
const start_tag = 1;
|
||||
const end_tag = 2;
|
||||
const comment = 3;
|
||||
|
||||
/**
|
||||
* Tag name reserved for a custom HTML element used as a block placeholder.
|
||||
*/
|
||||
const placeholder_block = 'placeholder:block';
|
||||
|
||||
/**
|
||||
* Tag name reserved for a custom HTML element used as an inline placeholder.
|
||||
*/
|
||||
const placeholder_inline = 'placeholder:inline';
|
||||
|
||||
/**
|
||||
* The void elements in HTML.
|
||||
*
|
||||
* @link https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
||||
*/
|
||||
const void_elements = array(
|
||||
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
|
||||
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
|
||||
self::placeholder_block, self::placeholder_inline,
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can contain flow content.
|
||||
*/
|
||||
const p_parent_elements = array(
|
||||
'address', 'article', 'aside', 'blockquote', 'body', 'caption',
|
||||
'dd', 'details', 'dialog', 'div', 'dt', 'fieldset', 'figcaption',
|
||||
'figure', 'footer', 'form', 'header', 'li', 'main', 'nav',
|
||||
'section', 'td', 'th',
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can be neither the parent nor a child of
|
||||
* a paragraph element.
|
||||
*/
|
||||
const p_nonparent_elements = array(
|
||||
'colgroup', 'dl', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
|
||||
'hgroup', 'html', 'legend', 'menu', 'ol', 'pre', 'style', 'summary',
|
||||
'table', 'tbody', 'template', 'tfoot', 'thead', 'title', 'tr', 'ul',
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements in the phrasing content category, plus non-phrasing
|
||||
* content elements that can be grandchildren of a paragraph element.
|
||||
*/
|
||||
const p_child_elements = array(
|
||||
'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button',
|
||||
'canvas', 'cite', 'code', 'data', 'datalist', 'del', 'dfn',
|
||||
'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
|
||||
'keygen', 'label', 'link', 'map', 'mark', 'meta',
|
||||
'meter', 'noscript', 'object', 'output', 'picture', 'progress',
|
||||
'q', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small',
|
||||
'span', 'strong', 'sub', 'sup', 'textarea',
|
||||
'time', 'u', 'var', 'video', 'wbr',
|
||||
'optgroup', 'option', 'rp', 'rt', // non-phrasing grandchildren
|
||||
self::placeholder_inline,
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can contain phrasing content.
|
||||
*/
|
||||
const br_parent_elements = array(
|
||||
'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi',
|
||||
'bdo', 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code',
|
||||
'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
|
||||
'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
|
||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'i', 'ins', 'kbd',
|
||||
'label', 'legend', 'li', 'main', 'map', 'mark', 'meter', 'nav',
|
||||
'noscript', 'object', 'output', 'p', 'progress', 'q', 'rt',
|
||||
'ruby', 's', 'samp', 'section', 'slot', 'small', 'span', 'strong',
|
||||
'sub', 'summary', 'sup', 'td', 'th', 'time', 'u', 'var',
|
||||
'video',
|
||||
);
|
||||
|
||||
|
||||
// Properties.
|
||||
private $options = array();
|
||||
private $stacked_elements = array();
|
||||
private $output = '';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct( $args = '' ) {
|
||||
$this->options = wp_parse_args( $args, array(
|
||||
'auto_br' => true,
|
||||
'auto_indent' => true,
|
||||
) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separates the given text into chunks of HTML. Each chunk must be an
|
||||
* associative array that includes 'position', 'type', and 'content' keys.
|
||||
*
|
||||
* @param string $input Text to be separated into chunks.
|
||||
* @return iterable Iterable of chunks.
|
||||
*/
|
||||
public function separate_into_chunks( $input ) {
|
||||
$input_bytelength = strlen( $input );
|
||||
$position = 0;
|
||||
|
||||
while ( $position < $input_bytelength ) {
|
||||
$next_tag = preg_match(
|
||||
'/(?:<!--.*?-->|<(?:\/?)[a-z].*?>)/is',
|
||||
$input,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE,
|
||||
$position
|
||||
);
|
||||
|
||||
if ( ! $next_tag ) {
|
||||
yield array(
|
||||
'position' => $position,
|
||||
'type' => self::text,
|
||||
'content' => substr( $input, $position ),
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$next_tag = $matches[0][0];
|
||||
$next_tag_position = $matches[0][1];
|
||||
|
||||
if ( $position < $next_tag_position ) {
|
||||
yield array(
|
||||
'position' => $position,
|
||||
'type' => self::text,
|
||||
'content' => substr(
|
||||
$input,
|
||||
$position,
|
||||
$next_tag_position - $position
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ( '<!' === substr( $next_tag, 0, 2 ) ) {
|
||||
$next_tag_type = self::comment;
|
||||
} elseif ( '</' === substr( $next_tag, 0, 2 ) ) {
|
||||
$next_tag_type = self::end_tag;
|
||||
} else {
|
||||
$next_tag_type = self::start_tag;
|
||||
}
|
||||
|
||||
yield array(
|
||||
'position' => $next_tag_position,
|
||||
'type' => $next_tag_type,
|
||||
'content' => substr(
|
||||
$input,
|
||||
$next_tag_position,
|
||||
strlen( $next_tag )
|
||||
),
|
||||
);
|
||||
|
||||
$position = $next_tag_position + strlen( $next_tag );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes content in each chunk. This may change the type and position
|
||||
* of the chunk.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return iterable Normalized chunks.
|
||||
*/
|
||||
public function pre_format( $chunks ) {
|
||||
$position = 0;
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$chunk['position'] = $position;
|
||||
|
||||
// Standardize newline characters to "\n".
|
||||
$chunk['content'] = str_replace(
|
||||
array( "\r\n", "\r" ), "\n", $chunk['content']
|
||||
);
|
||||
|
||||
if ( $chunk['type'] === self::start_tag ) {
|
||||
list( $chunk['content'] ) =
|
||||
self::normalize_start_tag( $chunk['content'] );
|
||||
|
||||
// Replace <br /> by a line break.
|
||||
if (
|
||||
$this->options['auto_br'] and
|
||||
preg_match( '/^<br\s*\/?>$/i', $chunk['content'] )
|
||||
) {
|
||||
$chunk['type'] = self::text;
|
||||
$chunk['content'] = "\n";
|
||||
}
|
||||
}
|
||||
|
||||
yield $chunk;
|
||||
$position = self::calc_next_position( $chunk );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Concatenates neighboring text chunks to create a single chunk.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return iterable Processed chunks.
|
||||
*/
|
||||
public function concatenate_texts( $chunks ) {
|
||||
$position = 0;
|
||||
$text_left = null;
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$chunk['position'] = $position;
|
||||
|
||||
if ( $chunk['type'] === self::text ) {
|
||||
if ( isset( $text_left ) ) {
|
||||
$text_left['content'] .= $chunk['content'];
|
||||
} else {
|
||||
$text_left = $chunk;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $text_left ) ) {
|
||||
yield $text_left;
|
||||
$chunk['position'] = self::calc_next_position( $text_left );
|
||||
$text_left = null;
|
||||
}
|
||||
|
||||
yield $chunk;
|
||||
$position = self::calc_next_position( $chunk );
|
||||
}
|
||||
|
||||
if ( isset( $text_left ) ) {
|
||||
yield $text_left;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs formatted HTML based on the given chunks.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return string Formatted HTML.
|
||||
*/
|
||||
public function format( $chunks ) {
|
||||
$chunks = $this->pre_format( $chunks );
|
||||
$chunks = $this->concatenate_texts( $chunks );
|
||||
|
||||
$this->output = '';
|
||||
$this->stacked_elements = array();
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
|
||||
if ( $chunk['type'] === self::text ) {
|
||||
$this->append_text( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( $chunk['type'] === self::start_tag ) {
|
||||
$this->start_tag( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( $chunk['type'] === self::end_tag ) {
|
||||
$this->end_tag( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( $chunk['type'] === self::comment ) {
|
||||
$this->append_comment( $chunk['content'] );
|
||||
}
|
||||
}
|
||||
|
||||
// Close all remaining tags.
|
||||
$this->close_all_tags();
|
||||
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a text node content to the output property.
|
||||
*
|
||||
* @param string $content Text node content.
|
||||
*/
|
||||
public function append_text( $content ) {
|
||||
if ( $this->is_inside( array( 'pre', 'template' ) ) ) {
|
||||
$this->output .= $content;
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
empty( $this->stacked_elements ) or
|
||||
$this->has_parent( 'p' ) or
|
||||
$this->has_parent( self::p_parent_elements )
|
||||
) {
|
||||
// Close <p> if the content starts with multiple line breaks.
|
||||
if ( preg_match( '/^\s*\n\s*\n\s*/', $content ) ) {
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
// Split up the contents into paragraphs, separated by double line breaks.
|
||||
$paragraphs = preg_split( '/\s*\n\s*\n\s*/', $content );
|
||||
|
||||
$paragraphs = array_filter( $paragraphs, static function ( $paragraph ) {
|
||||
return '' !== trim( $paragraph );
|
||||
} );
|
||||
|
||||
$paragraphs = array_values( $paragraphs );
|
||||
|
||||
if ( $paragraphs ) {
|
||||
if ( $this->is_inside( 'p' ) ) {
|
||||
$paragraph = array_shift( $paragraphs );
|
||||
|
||||
$paragraph = self::normalize_paragraph(
|
||||
$paragraph,
|
||||
$this->options['auto_br']
|
||||
);
|
||||
|
||||
$this->output .= $paragraph;
|
||||
}
|
||||
|
||||
foreach ( $paragraphs as $paragraph ) {
|
||||
$this->start_tag( 'p' );
|
||||
|
||||
$paragraph = ltrim( $paragraph );
|
||||
|
||||
$paragraph = self::normalize_paragraph(
|
||||
$paragraph,
|
||||
$this->options['auto_br']
|
||||
);
|
||||
|
||||
$this->output .= $paragraph;
|
||||
}
|
||||
}
|
||||
|
||||
// Close <p> if the content ends with multiple line breaks.
|
||||
if ( preg_match( '/\s*\n\s*\n\s*$/', $content ) ) {
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
// Cases where the content is a single line break.
|
||||
if ( preg_match( '/^\s*\n\s*$/', $content ) ) {
|
||||
$auto_br = $this->options['auto_br'] && $this->is_inside( 'p' );
|
||||
|
||||
$content = self::normalize_paragraph( $content, $auto_br );
|
||||
|
||||
$this->output .= $content;
|
||||
}
|
||||
} else {
|
||||
$auto_br = $this->options['auto_br'] &&
|
||||
$this->has_parent( self::br_parent_elements );
|
||||
|
||||
$content = self::normalize_paragraph( $content, $auto_br );
|
||||
|
||||
$this->output .= $content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a start tag to the output property.
|
||||
*
|
||||
* @param string $tag A start tag.
|
||||
*/
|
||||
public function start_tag( $tag ) {
|
||||
list( $tag, $tag_name ) = self::normalize_start_tag( $tag );
|
||||
|
||||
if ( in_array( $tag_name, self::p_child_elements ) ) {
|
||||
if (
|
||||
! $this->is_inside( 'p' ) and
|
||||
! $this->is_inside( self::p_child_elements ) and
|
||||
! $this->has_parent( self::p_nonparent_elements )
|
||||
) {
|
||||
// Open <p> if it does not exist.
|
||||
$this->start_tag( 'p' );
|
||||
}
|
||||
} elseif (
|
||||
'p' === $tag_name or
|
||||
in_array( $tag_name, self::p_parent_elements ) or
|
||||
in_array( $tag_name, self::p_nonparent_elements )
|
||||
) {
|
||||
// Close <p> if it exists.
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
if ( 'dd' === $tag_name or 'dt' === $tag_name ) {
|
||||
// Close <dd> and <dt> if closing tag is omitted.
|
||||
$this->end_tag( 'dd' );
|
||||
$this->end_tag( 'dt' );
|
||||
}
|
||||
|
||||
if ( 'li' === $tag_name ) {
|
||||
// Close <li> if closing tag is omitted.
|
||||
$this->end_tag( 'li' );
|
||||
}
|
||||
|
||||
if ( 'optgroup' === $tag_name ) {
|
||||
// Close <option> and <optgroup> if closing tag is omitted.
|
||||
$this->end_tag( 'option' );
|
||||
$this->end_tag( 'optgroup' );
|
||||
}
|
||||
|
||||
if ( 'option' === $tag_name ) {
|
||||
// Close <option> if closing tag is omitted.
|
||||
$this->end_tag( 'option' );
|
||||
}
|
||||
|
||||
if ( 'rp' === $tag_name or 'rt' === $tag_name ) {
|
||||
// Close <rp> and <rt> if closing tag is omitted.
|
||||
$this->end_tag( 'rp' );
|
||||
$this->end_tag( 'rt' );
|
||||
}
|
||||
|
||||
if ( 'td' === $tag_name or 'th' === $tag_name ) {
|
||||
// Close <td> and <th> if closing tag is omitted.
|
||||
$this->end_tag( 'td' );
|
||||
$this->end_tag( 'th' );
|
||||
}
|
||||
|
||||
if ( 'tr' === $tag_name ) {
|
||||
// Close <tr> if closing tag is omitted.
|
||||
$this->end_tag( 'tr' );
|
||||
}
|
||||
|
||||
if ( 'tbody' === $tag_name or 'tfoot' === $tag_name ) {
|
||||
// Close <thead> if closing tag is omitted.
|
||||
$this->end_tag( 'thead' );
|
||||
}
|
||||
|
||||
if ( 'tfoot' === $tag_name ) {
|
||||
// Close <tbody> if closing tag is omitted.
|
||||
$this->end_tag( 'tbody' );
|
||||
}
|
||||
|
||||
if ( ! in_array( $tag_name, self::void_elements ) ) {
|
||||
array_unshift( $this->stacked_elements, $tag_name );
|
||||
}
|
||||
|
||||
if ( ! in_array( $tag_name, self::p_child_elements ) ) {
|
||||
if ( '' !== $this->output ) {
|
||||
$this->output = rtrim( $this->output ) . "\n";
|
||||
}
|
||||
|
||||
if ( $this->options['auto_indent'] ) {
|
||||
$this->output .= self::indent( count( $this->stacked_elements ) - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
$this->output .= $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes an element and its open descendants at a time.
|
||||
*
|
||||
* @param string $tag An end tag.
|
||||
*/
|
||||
public function end_tag( $tag ) {
|
||||
if ( preg_match( '/<\/(.+?)(?:\s|>)/', $tag, $matches ) ) {
|
||||
$tag_name = strtolower( $matches[1] );
|
||||
} else {
|
||||
$tag_name = strtolower( $tag );
|
||||
}
|
||||
|
||||
$stacked_elements = array_values( $this->stacked_elements );
|
||||
|
||||
$tag_position = array_search( $tag_name, $stacked_elements );
|
||||
|
||||
if ( false === $tag_position ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Element groups that make up an indirect nesting structure.
|
||||
// Descendant can contain ancestors.
|
||||
static $nesting_families = array(
|
||||
array(
|
||||
'ancestors' => array( 'dl', ),
|
||||
'descendants' => array( 'dd', 'dt', ),
|
||||
),
|
||||
array(
|
||||
'ancestors' => array( 'ol', 'ul', 'menu', ),
|
||||
'descendants' => array( 'li', ),
|
||||
),
|
||||
array(
|
||||
'ancestors' => array( 'table', ),
|
||||
'descendants' => array( 'td', 'th', 'tr', 'thead', 'tbody', 'tfoot', ),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ( $nesting_families as $family ) {
|
||||
$ancestors = (array) $family['ancestors'];
|
||||
$descendants = (array) $family['descendants'];
|
||||
|
||||
if ( in_array( $tag_name, $descendants ) ) {
|
||||
$intersect = array_intersect(
|
||||
$ancestors,
|
||||
array_slice( $stacked_elements, 0, $tag_position )
|
||||
);
|
||||
|
||||
if ( $intersect ) { // Ancestor appears after descendant.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ( $element = array_shift( $this->stacked_elements ) ) {
|
||||
$this->append_end_tag( $element );
|
||||
|
||||
if ( $element === $tag_name ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes all open tags.
|
||||
*/
|
||||
public function close_all_tags() {
|
||||
while ( $element = array_shift( $this->stacked_elements ) ) {
|
||||
$this->append_end_tag( $element );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends an end tag to the output property.
|
||||
*
|
||||
* @param string $tag_name Tag name.
|
||||
*/
|
||||
public function append_end_tag( $tag_name ) {
|
||||
if ( ! in_array( $tag_name, self::p_child_elements ) ) {
|
||||
// Remove unnecessary <br />.
|
||||
$this->output = preg_replace( '/\s*<br \/>\s*$/', '', $this->output );
|
||||
|
||||
$this->output = rtrim( $this->output ) . "\n";
|
||||
|
||||
if ( $this->options['auto_indent'] ) {
|
||||
$this->output .= self::indent( count( $this->stacked_elements ) );
|
||||
}
|
||||
}
|
||||
|
||||
$this->output .= sprintf( '</%s>', $tag_name );
|
||||
|
||||
// Remove trailing <p></p>.
|
||||
$this->output = preg_replace( '/<p>\s*<\/p>$/', '', $this->output );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends an HTML comment to the output property.
|
||||
*
|
||||
* @param string $tag An HTML comment.
|
||||
*/
|
||||
public function append_comment( $tag ) {
|
||||
$this->output .= $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if it is currently inside one of HTML elements specified
|
||||
* by tag names.
|
||||
*
|
||||
* @param string|array $tag_names A tag name or an array of tag names.
|
||||
*/
|
||||
public function is_inside( $tag_names ) {
|
||||
$tag_names = (array) $tag_names;
|
||||
|
||||
foreach ( $this->stacked_elements as $element ) {
|
||||
if ( in_array( $element, $tag_names ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the parent node is one of HTML elements specified
|
||||
* by tag names.
|
||||
*
|
||||
* @param string|array $tag_names A tag name or an array of tag names.
|
||||
*/
|
||||
public function has_parent( $tag_names ) {
|
||||
$tag_names = (array) $tag_names;
|
||||
|
||||
$parent = reset( $this->stacked_elements );
|
||||
|
||||
if ( false === $parent ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $parent, $tag_names );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the position of the next chunk based on the position and
|
||||
* length of the current chunk.
|
||||
*
|
||||
* @param array $chunk An associative array of the current chunk.
|
||||
* @return int The position of the next chunk.
|
||||
*/
|
||||
public static function calc_next_position( $chunk ) {
|
||||
return $chunk['position'] + strlen( $chunk['content'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs a set of tabs to indent.
|
||||
*
|
||||
* @param int $level Indentation level.
|
||||
* @return string A series of tabs.
|
||||
*/
|
||||
public static function indent( $level ) {
|
||||
$level = (int) $level;
|
||||
|
||||
if ( 0 < $level ) {
|
||||
return str_repeat( "\t", $level );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a start tag.
|
||||
*
|
||||
* @param string $tag A start tag or a tag name.
|
||||
* @return array An array includes the normalized start tag and tag name.
|
||||
*/
|
||||
public static function normalize_start_tag( $tag ) {
|
||||
if ( preg_match( '/<(.+?)[\s\/>]/', $tag, $matches ) ) {
|
||||
$tag_name = strtolower( $matches[1] );
|
||||
} else {
|
||||
$tag_name = strtolower( $tag );
|
||||
$tag = sprintf( '<%s>', $tag_name );
|
||||
}
|
||||
|
||||
if ( in_array( $tag_name, self::void_elements ) ) {
|
||||
// Normalize void element.
|
||||
$tag = preg_replace( '/\s*\/?>/', ' />', $tag );
|
||||
}
|
||||
|
||||
return array( $tag, $tag_name );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a paragraph of text.
|
||||
*
|
||||
* @param string $paragraph A paragraph of text.
|
||||
* @param bool $auto_br Optional. If true, line breaks will be replaced
|
||||
* by a br element.
|
||||
* @return string The normalized paragraph.
|
||||
*/
|
||||
public static function normalize_paragraph( $paragraph, $auto_br = false ) {
|
||||
if ( $auto_br ) {
|
||||
$paragraph = preg_replace( '/\s*\n\s*/', "<br />\n", $paragraph );
|
||||
}
|
||||
|
||||
$paragraph = preg_replace( '/[ ]+/', " ", $paragraph );
|
||||
|
||||
return $paragraph;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration API
|
||||
*
|
||||
* @link https://contactform7.com/integration-with-external-apis/
|
||||
*/
|
||||
|
||||
class WPCF7_Integration {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $services = array();
|
||||
private $categories = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns initially supported service categories.
|
||||
*
|
||||
* @return array Service categories.
|
||||
*/
|
||||
public static function get_builtin_categories() {
|
||||
return array(
|
||||
'spam_protection' => __( 'Spam protection', 'contact-form-7' ),
|
||||
'email_marketing' => __( 'Email marketing', 'contact-form-7' ),
|
||||
'payments' => __( 'Payments', 'contact-form-7' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*
|
||||
* @return WPCF7_Integration The instance.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self;
|
||||
self::$instance->categories = self::get_builtin_categories();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a service to the services list.
|
||||
*/
|
||||
public function add_service( $name, WPCF7_Service $service ) {
|
||||
$name = sanitize_key( $name );
|
||||
|
||||
if ( empty( $name )
|
||||
or isset( $this->services[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->services[$name] = $service;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a service category to the categories list.
|
||||
*/
|
||||
public function add_category( $name, $title ) {
|
||||
$name = sanitize_key( $name );
|
||||
|
||||
if ( empty( $name )
|
||||
or isset( $this->categories[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->categories[$name] = $title;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if a service with the name exists in the services list.
|
||||
*
|
||||
* @param string $name The name of service to search.
|
||||
*/
|
||||
public function service_exists( $name = '' ) {
|
||||
if ( '' == $name ) {
|
||||
return (bool) count( $this->services );
|
||||
} else {
|
||||
return isset( $this->services[$name] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a service object with the name.
|
||||
*
|
||||
* @param string $name The name of service.
|
||||
* @return WPCF7_Service|bool The service object if it exists,
|
||||
* false otherwise.
|
||||
*/
|
||||
public function get_service( $name ) {
|
||||
if ( $this->service_exists( $name ) ) {
|
||||
return $this->services[$name];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints services list.
|
||||
*/
|
||||
public function list_services( $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'include' => array(),
|
||||
) );
|
||||
|
||||
$singular = false;
|
||||
$services = (array) $this->services;
|
||||
|
||||
if ( ! empty( $args['include'] ) ) {
|
||||
$services = array_intersect_key( $services,
|
||||
array_flip( (array) $args['include'] )
|
||||
);
|
||||
|
||||
if ( 1 == count( $services ) ) {
|
||||
$singular = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $services ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = wpcf7_current_action();
|
||||
|
||||
foreach ( $services as $name => $service ) {
|
||||
$cats = array_intersect_key( $this->categories,
|
||||
array_flip( $service->get_categories() )
|
||||
);
|
||||
?>
|
||||
<div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr( $name ); ?>">
|
||||
<?php $service->icon(); ?>
|
||||
<h2 class="title"><?php echo esc_html( $service->get_title() ); ?></h2>
|
||||
<div class="infobox">
|
||||
<?php echo esc_html( implode( ', ', $cats ) ); ?>
|
||||
<br />
|
||||
<?php $service->link(); ?>
|
||||
</div>
|
||||
<br class="clear" />
|
||||
|
||||
<div class="inside">
|
||||
<?php
|
||||
if ( $singular ) {
|
||||
$service->display( $action );
|
||||
} else {
|
||||
$service->display();
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class for services.
|
||||
*
|
||||
* Only instances of this class's subclasses are allowed to be
|
||||
* listed on the Integration page.
|
||||
*/
|
||||
abstract class WPCF7_Service {
|
||||
|
||||
abstract public function get_title();
|
||||
abstract public function is_active();
|
||||
|
||||
|
||||
public function get_categories() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
public function icon() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function link() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function load( $action = '' ) {
|
||||
}
|
||||
|
||||
|
||||
public function display( $action = '' ) {
|
||||
}
|
||||
|
||||
|
||||
public function admin_notice( $message = '' ) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class for services that use OAuth.
|
||||
*
|
||||
* While this is not an abstract class, subclassing this class for
|
||||
* your aim is advised.
|
||||
*/
|
||||
class WPCF7_Service_OAuth2 extends WPCF7_Service {
|
||||
|
||||
protected $client_id = '';
|
||||
protected $client_secret = '';
|
||||
protected $access_token = '';
|
||||
protected $refresh_token = '';
|
||||
protected $authorization_endpoint = 'https://example.com/authorization';
|
||||
protected $token_endpoint = 'https://example.com/token';
|
||||
|
||||
|
||||
public function get_title() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function is_active() {
|
||||
return ! empty( $this->refresh_token );
|
||||
}
|
||||
|
||||
|
||||
protected function save_data() {
|
||||
}
|
||||
|
||||
|
||||
protected function reset_data() {
|
||||
}
|
||||
|
||||
|
||||
protected function get_redirect_uri() {
|
||||
return admin_url();
|
||||
}
|
||||
|
||||
|
||||
protected function menu_page_url( $args = '' ) {
|
||||
return menu_page_url( 'wpcf7-integration', false );
|
||||
}
|
||||
|
||||
|
||||
public function load( $action = '' ) {
|
||||
if ( 'auth_redirect' === $action ) {
|
||||
$code = $_GET['code'] ?? '';
|
||||
|
||||
if ( $code ) {
|
||||
$this->request_token( $code );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->access_token ) ) {
|
||||
$message = 'success';
|
||||
} else {
|
||||
$message = 'failed';
|
||||
}
|
||||
|
||||
wp_safe_redirect( $this->menu_page_url(
|
||||
array(
|
||||
'action' => 'setup',
|
||||
'message' => $message,
|
||||
)
|
||||
) );
|
||||
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function authorize( $scope = '' ) {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->client_id,
|
||||
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
|
||||
'scope' => $scope,
|
||||
),
|
||||
$this->authorization_endpoint
|
||||
);
|
||||
|
||||
if ( wp_redirect( sanitize_url( $endpoint ) ) ) {
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function get_http_authorization_header( $scheme = 'basic' ) {
|
||||
$scheme = strtolower( trim( $scheme ) );
|
||||
|
||||
switch ( $scheme ) {
|
||||
case 'bearer':
|
||||
return sprintf( 'Bearer %s', $this->access_token );
|
||||
case 'basic':
|
||||
default:
|
||||
return sprintf( 'Basic %s',
|
||||
base64_encode( $this->client_id . ':' . $this->client_secret )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function request_token( $authorization_code ) {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'code' => $authorization_code,
|
||||
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
|
||||
'grant_type' => 'authorization_code',
|
||||
),
|
||||
$this->token_endpoint
|
||||
);
|
||||
|
||||
$request = array(
|
||||
'headers' => array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'basic' ),
|
||||
),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
|
||||
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
$response_body = wp_remote_retrieve_body( $response );
|
||||
$response_body = json_decode( $response_body, true );
|
||||
|
||||
if ( WP_DEBUG and 400 <= $response_code ) {
|
||||
$this->log( $endpoint, $request, $response );
|
||||
}
|
||||
|
||||
if ( 401 == $response_code ) { // Unauthorized
|
||||
$this->access_token = null;
|
||||
$this->refresh_token = null;
|
||||
} else {
|
||||
if ( isset( $response_body['access_token'] ) ) {
|
||||
$this->access_token = $response_body['access_token'];
|
||||
} else {
|
||||
$this->access_token = null;
|
||||
}
|
||||
|
||||
if ( isset( $response_body['refresh_token'] ) ) {
|
||||
$this->refresh_token = $response_body['refresh_token'];
|
||||
} else {
|
||||
$this->refresh_token = null;
|
||||
}
|
||||
}
|
||||
|
||||
$this->save_data();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function refresh_token() {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'refresh_token' => $this->refresh_token,
|
||||
'grant_type' => 'refresh_token',
|
||||
),
|
||||
$this->token_endpoint
|
||||
);
|
||||
|
||||
$request = array(
|
||||
'headers' => array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'basic' ),
|
||||
),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
|
||||
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
$response_body = wp_remote_retrieve_body( $response );
|
||||
$response_body = json_decode( $response_body, true );
|
||||
|
||||
if ( WP_DEBUG and 400 <= $response_code ) {
|
||||
$this->log( $endpoint, $request, $response );
|
||||
}
|
||||
|
||||
if ( 401 == $response_code ) { // Unauthorized
|
||||
$this->access_token = null;
|
||||
$this->refresh_token = null;
|
||||
} else {
|
||||
if ( isset( $response_body['access_token'] ) ) {
|
||||
$this->access_token = $response_body['access_token'];
|
||||
} else {
|
||||
$this->access_token = null;
|
||||
}
|
||||
|
||||
if ( isset( $response_body['refresh_token'] ) ) {
|
||||
$this->refresh_token = $response_body['refresh_token'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->save_data();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function remote_request( $url, $request = array() ) {
|
||||
static $refreshed = false;
|
||||
|
||||
$request = wp_parse_args( $request, array() );
|
||||
|
||||
$request['headers'] = array_merge(
|
||||
$request['headers'],
|
||||
array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'bearer' ),
|
||||
)
|
||||
);
|
||||
|
||||
$response = wp_remote_request( sanitize_url( $url ), $request );
|
||||
|
||||
if ( 401 === wp_remote_retrieve_response_code( $response )
|
||||
and ! $refreshed ) {
|
||||
$this->refresh_token();
|
||||
$refreshed = true;
|
||||
|
||||
$response = $this->remote_request( $url, $request );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function log( $url, $request, $response ) {
|
||||
wpcf7_log_remote_request( $url, $request, $response );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
( function( $ ) {
|
||||
$( function() {
|
||||
var supportHtml5 = ( function() {
|
||||
var features = {};
|
||||
var input = document.createElement( 'input' );
|
||||
var inputTypes = [ 'date' ];
|
||||
|
||||
$.each( inputTypes, function( index, value ) {
|
||||
input.setAttribute( 'type', value );
|
||||
features[ value ] = input.type !== 'text';
|
||||
} );
|
||||
|
||||
return features;
|
||||
} )();
|
||||
|
||||
if ( ! supportHtml5.date ) {
|
||||
$( 'input.wpcf7-date[type="date"]' ).each( function() {
|
||||
$( this ).datepicker( {
|
||||
dateFormat: 'yy-mm-dd',
|
||||
minDate: new Date( $( this ).attr( 'min' ) ),
|
||||
maxDate: new Date( $( this ).attr( 'max' ) )
|
||||
} );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} )( jQuery );
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
|
Before Width: | Height: | Size: 393 B |
|
Before Width: | Height: | Size: 265 B |
|
Before Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 324 B |
|
Before Width: | Height: | Size: 390 B |
|
Before Width: | Height: | Size: 325 B |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,443 +0,0 @@
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.12.1
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://api.jqueryui.com/category/theming/
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
*/
|
||||
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget {
|
||||
font-family: Verdana,Arial,sans-serif;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.ui-widget .ui-widget {
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget input,
|
||||
.ui-widget select,
|
||||
.ui-widget textarea,
|
||||
.ui-widget button {
|
||||
font-family: Verdana,Arial,sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget.ui-widget-content {
|
||||
border: 1px solid #d3d3d3;
|
||||
}
|
||||
.ui-widget-content {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #ffffff;
|
||||
color: #222222;
|
||||
}
|
||||
.ui-widget-content a {
|
||||
color: #222222;
|
||||
}
|
||||
.ui-widget-header {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
|
||||
color: #222222;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-widget-header a {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default,
|
||||
.ui-button,
|
||||
|
||||
/* We use html here because we need a greater specificity to make sure disabled
|
||||
works properly when clicked or hovered */
|
||||
html .ui-button.ui-state-disabled:hover,
|
||||
html .ui-button.ui-state-disabled:active {
|
||||
border: 1px solid #d3d3d3;
|
||||
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #555555;
|
||||
}
|
||||
.ui-state-default a,
|
||||
.ui-state-default a:link,
|
||||
.ui-state-default a:visited,
|
||||
a.ui-button,
|
||||
a:link.ui-button,
|
||||
a:visited.ui-button,
|
||||
.ui-button {
|
||||
color: #555555;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ui-state-hover,
|
||||
.ui-widget-content .ui-state-hover,
|
||||
.ui-widget-header .ui-state-hover,
|
||||
.ui-state-focus,
|
||||
.ui-widget-content .ui-state-focus,
|
||||
.ui-widget-header .ui-state-focus,
|
||||
.ui-button:hover,
|
||||
.ui-button:focus {
|
||||
border: 1px solid #999999;
|
||||
background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #212121;
|
||||
}
|
||||
.ui-state-hover a,
|
||||
.ui-state-hover a:hover,
|
||||
.ui-state-hover a:link,
|
||||
.ui-state-hover a:visited,
|
||||
.ui-state-focus a,
|
||||
.ui-state-focus a:hover,
|
||||
.ui-state-focus a:link,
|
||||
.ui-state-focus a:visited,
|
||||
a.ui-button:hover,
|
||||
a.ui-button:focus {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ui-visual-focus {
|
||||
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
|
||||
}
|
||||
.ui-state-active,
|
||||
.ui-widget-content .ui-state-active,
|
||||
.ui-widget-header .ui-state-active,
|
||||
a.ui-button:active,
|
||||
.ui-button:active,
|
||||
.ui-button.ui-state-active:hover {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #212121;
|
||||
}
|
||||
.ui-icon-background,
|
||||
.ui-state-active .ui-icon-background {
|
||||
border: #aaaaaa;
|
||||
background-color: #212121;
|
||||
}
|
||||
.ui-state-active a,
|
||||
.ui-state-active a:link,
|
||||
.ui-state-active a:visited {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight,
|
||||
.ui-widget-content .ui-state-highlight,
|
||||
.ui-widget-header .ui-state-highlight {
|
||||
border: 1px solid #fcefa1;
|
||||
background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
|
||||
color: #363636;
|
||||
}
|
||||
.ui-state-checked {
|
||||
border: 1px solid #fcefa1;
|
||||
background: #fbf9ee;
|
||||
}
|
||||
.ui-state-highlight a,
|
||||
.ui-widget-content .ui-state-highlight a,
|
||||
.ui-widget-header .ui-state-highlight a {
|
||||
color: #363636;
|
||||
}
|
||||
.ui-state-error,
|
||||
.ui-widget-content .ui-state-error,
|
||||
.ui-widget-header .ui-state-error {
|
||||
border: 1px solid #cd0a0a;
|
||||
background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-state-error a,
|
||||
.ui-widget-content .ui-state-error a,
|
||||
.ui-widget-header .ui-state-error a {
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-state-error-text,
|
||||
.ui-widget-content .ui-state-error-text,
|
||||
.ui-widget-header .ui-state-error-text {
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-priority-primary,
|
||||
.ui-widget-content .ui-priority-primary,
|
||||
.ui-widget-header .ui-priority-primary {
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-priority-secondary,
|
||||
.ui-widget-content .ui-priority-secondary,
|
||||
.ui-widget-header .ui-priority-secondary {
|
||||
opacity: .7;
|
||||
filter:Alpha(Opacity=70); /* support: IE8 */
|
||||
font-weight: normal;
|
||||
}
|
||||
.ui-state-disabled,
|
||||
.ui-widget-content .ui-state-disabled,
|
||||
.ui-widget-header .ui-state-disabled {
|
||||
opacity: .35;
|
||||
filter:Alpha(Opacity=35); /* support: IE8 */
|
||||
background-image: none;
|
||||
}
|
||||
.ui-state-disabled .ui-icon {
|
||||
filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
|
||||
}
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.ui-icon,
|
||||
.ui-widget-content .ui-icon {
|
||||
background-image: url("images/ui-icons_222222_256x240.png");
|
||||
}
|
||||
.ui-widget-header .ui-icon {
|
||||
background-image: url("images/ui-icons_222222_256x240.png");
|
||||
}
|
||||
.ui-state-hover .ui-icon,
|
||||
.ui-state-focus .ui-icon,
|
||||
.ui-button:hover .ui-icon,
|
||||
.ui-button:focus .ui-icon {
|
||||
background-image: url("images/ui-icons_454545_256x240.png");
|
||||
}
|
||||
.ui-state-active .ui-icon,
|
||||
.ui-button:active .ui-icon {
|
||||
background-image: url("images/ui-icons_454545_256x240.png");
|
||||
}
|
||||
.ui-state-highlight .ui-icon,
|
||||
.ui-button .ui-state-highlight.ui-icon {
|
||||
background-image: url("images/ui-icons_2e83ff_256x240.png");
|
||||
}
|
||||
.ui-state-error .ui-icon,
|
||||
.ui-state-error-text .ui-icon {
|
||||
background-image: url("images/ui-icons_cd0a0a_256x240.png");
|
||||
}
|
||||
.ui-button .ui-icon {
|
||||
background-image: url("images/ui-icons_888888_256x240.png");
|
||||
}
|
||||
|
||||
/* positioning */
|
||||
.ui-icon-blank { background-position: 16px 16px; }
|
||||
.ui-icon-caret-1-n { background-position: 0 0; }
|
||||
.ui-icon-caret-1-ne { background-position: -16px 0; }
|
||||
.ui-icon-caret-1-e { background-position: -32px 0; }
|
||||
.ui-icon-caret-1-se { background-position: -48px 0; }
|
||||
.ui-icon-caret-1-s { background-position: -65px 0; }
|
||||
.ui-icon-caret-1-sw { background-position: -80px 0; }
|
||||
.ui-icon-caret-1-w { background-position: -96px 0; }
|
||||
.ui-icon-caret-1-nw { background-position: -112px 0; }
|
||||
.ui-icon-caret-2-n-s { background-position: -128px 0; }
|
||||
.ui-icon-caret-2-e-w { background-position: -144px 0; }
|
||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||
.ui-icon-triangle-1-s { background-position: -65px -16px; }
|
||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||
.ui-icon-arrow-1-s { background-position: -65px -32px; }
|
||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
|
||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||
.ui-icon-extlink { background-position: -32px -80px; }
|
||||
.ui-icon-newwin { background-position: -48px -80px; }
|
||||
.ui-icon-refresh { background-position: -64px -80px; }
|
||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||
.ui-icon-document { background-position: -32px -96px; }
|
||||
.ui-icon-document-b { background-position: -48px -96px; }
|
||||
.ui-icon-note { background-position: -64px -96px; }
|
||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||
.ui-icon-comment { background-position: -128px -96px; }
|
||||
.ui-icon-person { background-position: -144px -96px; }
|
||||
.ui-icon-print { background-position: -160px -96px; }
|
||||
.ui-icon-trash { background-position: -176px -96px; }
|
||||
.ui-icon-locked { background-position: -192px -96px; }
|
||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||
.ui-icon-tag { background-position: -240px -96px; }
|
||||
.ui-icon-home { background-position: 0 -112px; }
|
||||
.ui-icon-flag { background-position: -16px -112px; }
|
||||
.ui-icon-calendar { background-position: -32px -112px; }
|
||||
.ui-icon-cart { background-position: -48px -112px; }
|
||||
.ui-icon-pencil { background-position: -64px -112px; }
|
||||
.ui-icon-clock { background-position: -80px -112px; }
|
||||
.ui-icon-disk { background-position: -96px -112px; }
|
||||
.ui-icon-calculator { background-position: -112px -112px; }
|
||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||
.ui-icon-search { background-position: -160px -112px; }
|
||||
.ui-icon-wrench { background-position: -176px -112px; }
|
||||
.ui-icon-gear { background-position: -192px -112px; }
|
||||
.ui-icon-heart { background-position: -208px -112px; }
|
||||
.ui-icon-star { background-position: -224px -112px; }
|
||||
.ui-icon-link { background-position: -240px -112px; }
|
||||
.ui-icon-cancel { background-position: 0 -128px; }
|
||||
.ui-icon-plus { background-position: -16px -128px; }
|
||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||
.ui-icon-minus { background-position: -48px -128px; }
|
||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||
.ui-icon-close { background-position: -80px -128px; }
|
||||
.ui-icon-closethick { background-position: -96px -128px; }
|
||||
.ui-icon-key { background-position: -112px -128px; }
|
||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||
.ui-icon-scissors { background-position: -144px -128px; }
|
||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||
.ui-icon-copy { background-position: -176px -128px; }
|
||||
.ui-icon-contact { background-position: -192px -128px; }
|
||||
.ui-icon-image { background-position: -208px -128px; }
|
||||
.ui-icon-video { background-position: -224px -128px; }
|
||||
.ui-icon-script { background-position: -240px -128px; }
|
||||
.ui-icon-alert { background-position: 0 -144px; }
|
||||
.ui-icon-info { background-position: -16px -144px; }
|
||||
.ui-icon-notice { background-position: -32px -144px; }
|
||||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
.ui-icon-pause { background-position: -16px -160px; }
|
||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||
.ui-icon-stop { background-position: -96px -160px; }
|
||||
.ui-icon-eject { background-position: -112px -160px; }
|
||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||
.ui-icon-power { background-position: 0 -176px; }
|
||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||
.ui-icon-signal { background-position: -32px -176px; }
|
||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-left,
|
||||
.ui-corner-tl {
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-right,
|
||||
.ui-corner-tr {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-left,
|
||||
.ui-corner-bl {
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-right,
|
||||
.ui-corner-br {
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
background: #aaaaaa;
|
||||
opacity: .3;
|
||||
filter: Alpha(Opacity=30); /* support: IE8 */
|
||||
}
|
||||
.ui-widget-shadow {
|
||||
-webkit-box-shadow: -8px -8px 8px #aaaaaa;
|
||||
box-shadow: -8px -8px 8px #aaaaaa;
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Retrieves an associative array of languages to which
|
||||
* this plugin is translated.
|
||||
*
|
||||
* @return array Array of languages.
|
||||
*/
|
||||
function wpcf7_l10n() {
|
||||
static $l10n = array();
|
||||
|
||||
if ( ! empty( $l10n ) ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
if ( ! is_admin() ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
|
||||
|
||||
$api = translations_api( 'plugins', array(
|
||||
'slug' => 'contact-form-7',
|
||||
'version' => WPCF7_VERSION,
|
||||
) );
|
||||
|
||||
if ( is_wp_error( $api )
|
||||
or empty( $api['translations'] ) ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
foreach ( (array) $api['translations'] as $translation ) {
|
||||
if ( ! empty( $translation['language'] )
|
||||
and ! empty( $translation['english_name'] ) ) {
|
||||
$l10n[$translation['language']] = $translation['english_name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given locale code looks valid.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
*/
|
||||
function wpcf7_is_valid_locale( $locale ) {
|
||||
if ( ! is_string( $locale ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/^[a-z]{2,3}(?:_[a-zA-Z_]{2,})?$/';
|
||||
return (bool) preg_match( $pattern, $locale );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given locale is an RTL language.
|
||||
*/
|
||||
function wpcf7_is_rtl( $locale = '' ) {
|
||||
static $rtl_locales = array(
|
||||
'ar' => 'Arabic',
|
||||
'ary' => 'Moroccan Arabic',
|
||||
'azb' => 'South Azerbaijani',
|
||||
'fa_IR' => 'Persian',
|
||||
'haz' => 'Hazaragi',
|
||||
'he_IL' => 'Hebrew',
|
||||
'ps' => 'Pashto',
|
||||
'ug_CN' => 'Uighur',
|
||||
);
|
||||
|
||||
if ( empty( $locale )
|
||||
and function_exists( 'is_rtl' ) ) {
|
||||
return is_rtl();
|
||||
}
|
||||
|
||||
if ( empty( $locale ) ) {
|
||||
$locale = determine_locale();
|
||||
}
|
||||
|
||||
return isset( $rtl_locales[$locale] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads a translation file into the plugin's text domain.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_load_textdomain( $locale = '' ) {
|
||||
$mofile = path_join(
|
||||
WP_LANG_DIR . '/plugins/',
|
||||
sprintf( '%s-%s.mo', WPCF7_TEXT_DOMAIN, $locale )
|
||||
);
|
||||
|
||||
return load_textdomain( WPCF7_TEXT_DOMAIN, $mofile, $locale );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unloads translations for the plugin's text domain.
|
||||
*
|
||||
* @param bool $reloadable Whether the text domain can be loaded
|
||||
* just-in-time again.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_unload_textdomain( $reloadable = false ) {
|
||||
return unload_textdomain( WPCF7_TEXT_DOMAIN, $reloadable );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Switches translation locale, calls the callback, then switches back
|
||||
* to the original locale.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
* @param callable $callback The callable to be called.
|
||||
* @param mixed $args Parameters to be passed to the callback.
|
||||
* @return mixed The return value of the callback.
|
||||
*/
|
||||
function wpcf7_switch_locale( $locale, callable $callback, ...$args ) {
|
||||
static $available_locales = null;
|
||||
|
||||
if ( ! isset( $available_locales ) ) {
|
||||
$available_locales = array_merge(
|
||||
array( 'en_US' ),
|
||||
get_available_languages()
|
||||
);
|
||||
}
|
||||
|
||||
$previous_locale = determine_locale();
|
||||
|
||||
$do_switch_locale = (
|
||||
$locale !== $previous_locale &&
|
||||
in_array( $locale, $available_locales, true ) &&
|
||||
in_array( $previous_locale, $available_locales, true )
|
||||
);
|
||||
|
||||
if ( $do_switch_locale ) {
|
||||
wpcf7_unload_textdomain();
|
||||
switch_to_locale( $locale );
|
||||
wpcf7_load_textdomain( $locale );
|
||||
}
|
||||
|
||||
$result = call_user_func( $callback, ...$args );
|
||||
|
||||
if ( $do_switch_locale ) {
|
||||
wpcf7_unload_textdomain( true );
|
||||
restore_previous_locale();
|
||||
wpcf7_load_textdomain( $previous_locale );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class that represents a mail-tag.
|
||||
*/
|
||||
class WPCF7_MailTag {
|
||||
|
||||
private $tag;
|
||||
private $tagname = '';
|
||||
private $name = '';
|
||||
private $options = array();
|
||||
private $values = array();
|
||||
private $form_tag = null;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*/
|
||||
public function __construct( $tag, $tagname, $values ) {
|
||||
$this->tag = $tag;
|
||||
$this->name = $this->tagname = $tagname;
|
||||
|
||||
$this->options = array(
|
||||
'do_not_heat' => false,
|
||||
'format' => '',
|
||||
);
|
||||
|
||||
if ( ! empty( $values ) ) {
|
||||
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $values, $matches );
|
||||
$this->values = wpcf7_strip_quote_deep( $matches[0] );
|
||||
}
|
||||
|
||||
if ( preg_match( '/^_raw_(.+)$/', $tagname, $matches ) ) {
|
||||
$this->name = trim( $matches[1] );
|
||||
$this->options['do_not_heat'] = true;
|
||||
}
|
||||
|
||||
if ( preg_match( '/^_format_(.+)$/', $tagname, $matches ) ) {
|
||||
$this->name = trim( $matches[1] );
|
||||
$this->options['format'] = $this->values[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name part of this mail-tag.
|
||||
*/
|
||||
public function tag_name() {
|
||||
return $this->tagname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the form field name corresponding to this mail-tag.
|
||||
*/
|
||||
public function field_name() {
|
||||
return strtr( $this->name, '.', '_' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the specified option.
|
||||
*/
|
||||
public function get_option( $option ) {
|
||||
return $this->options[$option];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the values part of this mail-tag.
|
||||
*/
|
||||
public function values() {
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the WPCF7_FormTag object that corresponds to this mail-tag.
|
||||
*/
|
||||
public function corresponding_form_tag() {
|
||||
if ( $this->form_tag instanceof WPCF7_FormTag ) {
|
||||
return $this->form_tag;
|
||||
}
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$contact_form = $submission->get_contact_form();
|
||||
$tags = $contact_form->scan_form_tags( array(
|
||||
'name' => $this->field_name(),
|
||||
'feature' => '! zero-controls-container',
|
||||
) );
|
||||
|
||||
if ( $tags ) {
|
||||
$this->form_tag = $tags[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->form_tag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
use Contactable\SWV;
|
||||
|
||||
/**
|
||||
* Mail-tag output calculator.
|
||||
*/
|
||||
class WPCF7_MailTag_OutputCalculator {
|
||||
|
||||
const email = 0b100;
|
||||
const text = 0b010;
|
||||
const blank = 0b001;
|
||||
|
||||
private $contact_form;
|
||||
|
||||
public function __construct( WPCF7_ContactForm $contact_form ) {
|
||||
$this->contact_form = $contact_form;
|
||||
}
|
||||
|
||||
public function calc_output( WPCF7_MailTag $mail_tag ) {
|
||||
return $this->calc_swv_result(
|
||||
$mail_tag,
|
||||
$this->contact_form->get_schema()
|
||||
);
|
||||
}
|
||||
|
||||
private function calc_swv_result( WPCF7_MailTag $mail_tag, SWV\Rule $rule ) {
|
||||
|
||||
if ( $rule instanceof SWV\AnyRule ) {
|
||||
$result = 0b000;
|
||||
|
||||
foreach ( $rule->rules() as $child_rule ) {
|
||||
$result |= $this->calc_swv_result( $mail_tag, $child_rule );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\CompositeRule ) {
|
||||
$result = 0b111;
|
||||
|
||||
foreach ( $rule->rules() as $child_rule ) {
|
||||
$result &= $this->calc_swv_result( $mail_tag, $child_rule );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$field_prop = $rule->get_property( 'field' );
|
||||
|
||||
if ( empty( $field_prop ) or $field_prop !== $mail_tag->field_name() ) {
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\RequiredRule ) {
|
||||
return ~ self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\EmailRule ) {
|
||||
return self::email | self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\EnumRule ) {
|
||||
$acceptable_values = (array) $rule->get_property( 'accept' );
|
||||
$acceptable_values = array_map( 'strval', $acceptable_values );
|
||||
$acceptable_values = array_filter( $acceptable_values );
|
||||
$acceptable_values = array_unique( $acceptable_values );
|
||||
|
||||
if ( ! $mail_tag->get_option( 'do_not_heat' ) ) {
|
||||
$pipes = $this->contact_form->get_pipes(
|
||||
$mail_tag->field_name()
|
||||
);
|
||||
|
||||
$acceptable_values = array_map(
|
||||
static function ( $val ) use ( $pipes ) {
|
||||
return $pipes->do_pipe( $val );
|
||||
},
|
||||
$acceptable_values
|
||||
);
|
||||
}
|
||||
|
||||
$email_values = array_filter(
|
||||
$acceptable_values,
|
||||
'wpcf7_is_mailbox_list'
|
||||
);
|
||||
|
||||
if ( count( $email_values ) === count( $acceptable_values ) ) {
|
||||
return self::email | self::blank;
|
||||
} else {
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
}
|
||||
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,632 +0,0 @@
|
||||
<?php
|
||||
|
||||
add_filter( 'wpcf7_mail_html_body', 'wpcf7_mail_html_body_autop', 10, 1 );
|
||||
|
||||
/**
|
||||
* Filter callback that applies auto-p to HTML email message body.
|
||||
*/
|
||||
function wpcf7_mail_html_body_autop( $body ) {
|
||||
if ( wpcf7_autop_or_not( array( 'for' => 'mail' ) ) ) {
|
||||
$body = wpcf7_autop( $body );
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that represents an attempt to compose and send email.
|
||||
*/
|
||||
class WPCF7_Mail {
|
||||
|
||||
private static $current = null;
|
||||
|
||||
private $name = '';
|
||||
private $locale = '';
|
||||
private $template = array();
|
||||
private $component = '';
|
||||
private $use_html = false;
|
||||
private $exclude_blank = false;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*/
|
||||
public static function get_current() {
|
||||
return self::$current;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template currently processed.
|
||||
*
|
||||
* Expected output: 'mail' or 'mail_2'
|
||||
*/
|
||||
public static function get_current_template_name() {
|
||||
$current = self::get_current();
|
||||
|
||||
if ( $current instanceof self ) {
|
||||
return $current->get_template_name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template component currently processed.
|
||||
*
|
||||
* Expected output: 'recipient', 'sender', 'subject',
|
||||
* 'additional_headers', 'body', or 'attachments'
|
||||
*/
|
||||
public static function get_current_component_name() {
|
||||
$current = self::get_current();
|
||||
|
||||
if ( $current instanceof self ) {
|
||||
return $current->get_component_name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composes and sends email based on the specified template.
|
||||
*
|
||||
* @param array $template Array of email template.
|
||||
* @param string $name Optional name of the template, such as
|
||||
* 'mail' or 'mail_2'. Default empty string.
|
||||
* @return bool Whether the email was sent successfully.
|
||||
*/
|
||||
public static function send( $template, $name = '' ) {
|
||||
self::$current = new self( $name, $template );
|
||||
return self::$current->compose();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*
|
||||
* @param string $name The name of the email template.
|
||||
* Such as 'mail' or 'mail_2'.
|
||||
* @param array $template Array of email template.
|
||||
*/
|
||||
private function __construct( $name, $template ) {
|
||||
$this->name = trim( $name );
|
||||
$this->use_html = ! empty( $template['use_html'] );
|
||||
$this->exclude_blank = ! empty( $template['exclude_blank'] );
|
||||
|
||||
$this->template = wp_parse_args( $template, array(
|
||||
'subject' => '',
|
||||
'sender' => '',
|
||||
'body' => '',
|
||||
'recipient' => '',
|
||||
'additional_headers' => '',
|
||||
'attachments' => '',
|
||||
) );
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$contact_form = $submission->get_contact_form();
|
||||
$this->locale = $contact_form->locale();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template.
|
||||
*/
|
||||
public function name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template. A wrapper method of name().
|
||||
*/
|
||||
public function get_template_name() {
|
||||
return $this->name();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template component currently processed.
|
||||
*/
|
||||
public function get_component_name() {
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a component from the email template.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param bool $replace_tags Whether to replace mail-tags
|
||||
* within the component.
|
||||
* @return string The text representation of the email component.
|
||||
*/
|
||||
public function get( $component, $replace_tags = false ) {
|
||||
$this->component = $component;
|
||||
|
||||
$use_html = ( $this->use_html && 'body' === $component );
|
||||
$exclude_blank = ( $this->exclude_blank && 'body' === $component );
|
||||
|
||||
$template = $this->template;
|
||||
$component = isset( $template[$component] ) ? $template[$component] : '';
|
||||
|
||||
if ( $replace_tags ) {
|
||||
$component = $this->replace_tags( $component, array(
|
||||
'html' => $use_html,
|
||||
'exclude_blank' => $exclude_blank,
|
||||
) );
|
||||
|
||||
if ( $use_html ) {
|
||||
// Convert <example@example.com> to <example@example.com>.
|
||||
$component = preg_replace_callback(
|
||||
'/<(.*?)>/',
|
||||
static function ( $matches ) {
|
||||
if ( is_email( $matches[1] ) ) {
|
||||
return sprintf( '<%s>', $matches[1] );
|
||||
} else {
|
||||
return $matches[0];
|
||||
}
|
||||
},
|
||||
$component
|
||||
);
|
||||
|
||||
if ( ! preg_match( '%<html[>\s].*</html>%is', $component ) ) {
|
||||
$component = $this->htmlize( $component );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->component = '';
|
||||
|
||||
return $component;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates HTML message body by adding the header and footer.
|
||||
*
|
||||
* @param string $body The body part of HTML.
|
||||
* @return string Formatted HTML.
|
||||
*/
|
||||
private function htmlize( $body ) {
|
||||
if ( $this->locale ) {
|
||||
$lang_atts = sprintf( ' %s',
|
||||
wpcf7_format_atts( array(
|
||||
'dir' => wpcf7_is_rtl( $this->locale ) ? 'rtl' : 'ltr',
|
||||
'lang' => str_replace( '_', '-', $this->locale ),
|
||||
) )
|
||||
);
|
||||
} else {
|
||||
$lang_atts = '';
|
||||
}
|
||||
|
||||
$header = apply_filters( 'wpcf7_mail_html_header',
|
||||
'<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"' . $lang_atts . '>
|
||||
<head>
|
||||
<title>' . esc_html( $this->get( 'subject', true ) ) . '</title>
|
||||
</head>
|
||||
<body>
|
||||
',
|
||||
$this
|
||||
);
|
||||
|
||||
$body = apply_filters( 'wpcf7_mail_html_body', $body, $this );
|
||||
|
||||
$footer = apply_filters( 'wpcf7_mail_html_footer',
|
||||
'</body>
|
||||
</html>',
|
||||
$this
|
||||
);
|
||||
|
||||
return $header . $body . $footer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composes an email message and attempts to send it.
|
||||
*
|
||||
* @param bool $send Whether to attempt to send email. Default true.
|
||||
*/
|
||||
private function compose( $send = true ) {
|
||||
$components = array(
|
||||
'subject' => $this->get( 'subject', true ),
|
||||
'sender' => $this->get( 'sender', true ),
|
||||
'body' => $this->get( 'body', true ),
|
||||
'recipient' => $this->get( 'recipient', true ),
|
||||
'additional_headers' => $this->get( 'additional_headers', true ),
|
||||
'attachments' => $this->attachments(),
|
||||
);
|
||||
|
||||
$components = apply_filters( 'wpcf7_mail_components',
|
||||
$components, wpcf7_get_current_contact_form(), $this
|
||||
);
|
||||
|
||||
if ( ! $send ) {
|
||||
return $components;
|
||||
}
|
||||
|
||||
$subject = wpcf7_strip_newline( $components['subject'] );
|
||||
$sender = wpcf7_strip_newline( $components['sender'] );
|
||||
$recipient = wpcf7_strip_newline( $components['recipient'] );
|
||||
$body = $components['body'];
|
||||
$additional_headers = trim( $components['additional_headers'] );
|
||||
|
||||
$headers = "From: $sender\n";
|
||||
|
||||
if ( $this->use_html ) {
|
||||
$headers .= "Content-Type: text/html\n";
|
||||
$headers .= "X-WPCF7-Content-Type: text/html\n";
|
||||
} else {
|
||||
$headers .= "X-WPCF7-Content-Type: text/plain\n";
|
||||
}
|
||||
|
||||
if ( $additional_headers ) {
|
||||
$headers .= $additional_headers . "\n";
|
||||
}
|
||||
|
||||
$attachments = array_filter(
|
||||
(array) $components['attachments'],
|
||||
function ( $attachment ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $attachment );
|
||||
|
||||
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
|
||||
if ( WP_DEBUG ) {
|
||||
trigger_error(
|
||||
sprintf(
|
||||
/* translators: %s: Attachment file path. */
|
||||
__( 'Failed to attach a file. %s is not in the allowed directory.', 'contact-form-7' ),
|
||||
$path
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
|
||||
if ( WP_DEBUG ) {
|
||||
trigger_error(
|
||||
sprintf(
|
||||
/* translators: %s: Attachment file path. */
|
||||
__( 'Failed to attach a file. %s is not a readable file.', 'contact-form-7' ),
|
||||
$path
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static $total_size = array();
|
||||
|
||||
if ( ! isset( $total_size[$this->name] ) ) {
|
||||
$total_size[$this->name] = 0;
|
||||
}
|
||||
|
||||
$file_size = (int) @filesize( $path );
|
||||
|
||||
if ( 25 * MB_IN_BYTES < $total_size[$this->name] + $file_size ) {
|
||||
if ( WP_DEBUG ) {
|
||||
trigger_error(
|
||||
__( 'Failed to attach a file. The total file size exceeds the limit of 25 megabytes.', 'contact-form-7' ),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$total_size[$this->name] += $file_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
return wp_mail( $recipient, $subject, $body, $headers, $attachments );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces mail-tags within the given text.
|
||||
*/
|
||||
public function replace_tags( $content, $args = '' ) {
|
||||
if ( true === $args ) {
|
||||
$args = array( 'html' => true );
|
||||
}
|
||||
|
||||
$args = wp_parse_args( $args, array(
|
||||
'html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
return wpcf7_mail_replace_tags( $content, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an array of attachments based on uploaded files and local files.
|
||||
*/
|
||||
private function attachments( $template = null ) {
|
||||
if ( ! $template ) {
|
||||
$template = $this->get( 'attachments' );
|
||||
}
|
||||
|
||||
$attachments = array();
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$uploaded_files = $submission->uploaded_files();
|
||||
|
||||
foreach ( (array) $uploaded_files as $name => $paths ) {
|
||||
if ( false !== strpos( $template, "[{$name}]" ) ) {
|
||||
$attachments = array_merge( $attachments, (array) $paths );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( explode( "\n", $template ) as $line ) {
|
||||
$line = trim( $line );
|
||||
|
||||
if ( '' === $line or '[' == substr( $line, 0, 1 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attachments[] = path_join( WP_CONTENT_DIR, $line );
|
||||
}
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$attachments = array_merge(
|
||||
$attachments,
|
||||
(array) $submission->extra_attachments( $this->name )
|
||||
);
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces all mail-tags within the given text content.
|
||||
*
|
||||
* @param string $content Text including mail-tags.
|
||||
* @param string|array $args Optional. Output options.
|
||||
* @return string Result of replacement.
|
||||
*/
|
||||
function wpcf7_mail_replace_tags( $content, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
if ( is_array( $content ) ) {
|
||||
foreach ( $content as $key => $value ) {
|
||||
$content[$key] = wpcf7_mail_replace_tags( $value, $args );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
$content = explode( "\n", $content );
|
||||
|
||||
foreach ( $content as $num => $line ) {
|
||||
$line = new WPCF7_MailTaggedText( $line, $args );
|
||||
$replaced = $line->replace_tags();
|
||||
|
||||
if ( $args['exclude_blank'] ) {
|
||||
$replaced_tags = $line->get_replaced_tags();
|
||||
|
||||
if ( empty( $replaced_tags )
|
||||
or array_filter( $replaced_tags, 'strlen' ) ) {
|
||||
$content[$num] = $replaced;
|
||||
} else {
|
||||
unset( $content[$num] ); // Remove a line.
|
||||
}
|
||||
} else {
|
||||
$content[$num] = $replaced;
|
||||
}
|
||||
}
|
||||
|
||||
$content = implode( "\n", $content );
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
add_action( 'phpmailer_init', 'wpcf7_phpmailer_init', 10, 1 );
|
||||
|
||||
/**
|
||||
* Adds custom properties to the PHPMailer object.
|
||||
*/
|
||||
function wpcf7_phpmailer_init( $phpmailer ) {
|
||||
$custom_headers = $phpmailer->getCustomHeaders();
|
||||
$phpmailer->clearCustomHeaders();
|
||||
$wpcf7_content_type = false;
|
||||
|
||||
foreach ( (array) $custom_headers as $custom_header ) {
|
||||
$name = $custom_header[0];
|
||||
$value = $custom_header[1];
|
||||
|
||||
if ( 'X-WPCF7-Content-Type' === $name ) {
|
||||
$wpcf7_content_type = trim( $value );
|
||||
} else {
|
||||
$phpmailer->addCustomHeader( $name, $value );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'text/html' === $wpcf7_content_type ) {
|
||||
$phpmailer->msgHTML( $phpmailer->Body );
|
||||
} elseif ( 'text/plain' === $wpcf7_content_type ) {
|
||||
$phpmailer->AltBody = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that represents a single-line text including mail-tags.
|
||||
*/
|
||||
class WPCF7_MailTaggedText {
|
||||
|
||||
private $html = false;
|
||||
private $callback = null;
|
||||
private $content = '';
|
||||
private $replaced_tags = array();
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*/
|
||||
public function __construct( $content, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'html' => false,
|
||||
'callback' => null,
|
||||
) );
|
||||
|
||||
$this->html = (bool) $args['html'];
|
||||
|
||||
if ( null !== $args['callback']
|
||||
and is_callable( $args['callback'] ) ) {
|
||||
$this->callback = $args['callback'];
|
||||
} elseif ( $this->html ) {
|
||||
$this->callback = array( $this, 'replace_tags_callback_html' );
|
||||
} else {
|
||||
$this->callback = array( $this, 'replace_tags_callback' );
|
||||
}
|
||||
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves mail-tags that have been replaced by this instance.
|
||||
*
|
||||
* @return array List of mail-tags replaced.
|
||||
*/
|
||||
public function get_replaced_tags() {
|
||||
return $this->replaced_tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces mail-tags based on regexp.
|
||||
*/
|
||||
public function replace_tags() {
|
||||
$regex = '/(\[?)\[[\t ]*'
|
||||
. '([a-zA-Z_][0-9a-zA-Z:._-]*)' // [2] = name
|
||||
. '((?:[\t ]+"[^"]*"|[\t ]+\'[^\']*\')*)' // [3] = values
|
||||
. '[\t ]*\](\]?)/';
|
||||
|
||||
return preg_replace_callback( $regex, $this->callback, $this->content );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for replacement. For HTML message body.
|
||||
*/
|
||||
private function replace_tags_callback_html( $matches ) {
|
||||
return $this->replace_tags_callback( $matches, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for replacement.
|
||||
*/
|
||||
private function replace_tags_callback( $matches, $html = false ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( $matches[1] == '['
|
||||
and $matches[4] == ']' ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
$submitted = $submission
|
||||
? $submission->get_posted_data( $field_name )
|
||||
: null;
|
||||
|
||||
if ( $mail_tag->get_option( 'do_not_heat' ) ) {
|
||||
$submitted = wp_unslash( $_POST[$field_name] ?? '' );
|
||||
}
|
||||
|
||||
$replaced = $submitted;
|
||||
|
||||
if ( null !== $replaced ) {
|
||||
if ( $format = $mail_tag->get_option( 'format' ) ) {
|
||||
$replaced = $this->format( $replaced, $format );
|
||||
}
|
||||
|
||||
$separator = ( 'body' === WPCF7_Mail::get_current_component_name() )
|
||||
? wp_get_list_item_separator()
|
||||
: ', ';
|
||||
|
||||
$replaced = wpcf7_flat_join( $replaced, array(
|
||||
'separator' => $separator,
|
||||
) );
|
||||
|
||||
if ( $html ) {
|
||||
$replaced = esc_html( $replaced );
|
||||
$replaced = wptexturize( $replaced );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $form_tag = $mail_tag->corresponding_form_tag() ) {
|
||||
$type = $form_tag->type;
|
||||
|
||||
$replaced = apply_filters(
|
||||
"wpcf7_mail_tag_replaced_{$type}", $replaced,
|
||||
$submitted, $html, $mail_tag
|
||||
);
|
||||
}
|
||||
|
||||
$replaced = apply_filters(
|
||||
'wpcf7_mail_tag_replaced', $replaced,
|
||||
$submitted, $html, $mail_tag
|
||||
);
|
||||
|
||||
if ( null !== $replaced ) {
|
||||
$replaced = trim( $replaced );
|
||||
|
||||
$this->replaced_tags[$tag] = $replaced;
|
||||
return $replaced;
|
||||
}
|
||||
|
||||
$special = apply_filters( 'wpcf7_special_mail_tags', null,
|
||||
$mail_tag->tag_name(), $html, $mail_tag
|
||||
);
|
||||
|
||||
if ( null !== $special ) {
|
||||
$this->replaced_tags[$tag] = $special;
|
||||
return $special;
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats string based on the formatting option in the form-tag.
|
||||
*/
|
||||
public function format( $original, $format ) {
|
||||
$original = (array) $original;
|
||||
|
||||
foreach ( $original as $key => $value ) {
|
||||
if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value ) ) {
|
||||
$datetime = date_create( $value, wp_timezone() );
|
||||
|
||||
if ( false !== $datetime ) {
|
||||
$original[$key] = wp_date( $format, $datetime->getTimestamp() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $original;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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 = null ) {
|
||||
foreach ( (array) $texts as $text ) {
|
||||
$this->add_pipe( $text );
|
||||
}
|
||||
}
|
||||
|
||||
private function add_pipe( $text ) {
|
||||
$pipe = new WPCF7_Pipe( $text );
|
||||
$this->pipes[] = $pipe;
|
||||
}
|
||||
|
||||
public function merge( self $another ) {
|
||||
$this->pipes = array_merge( $this->pipes, $another->pipes );
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trait for classes that hold cross-tag WPCF7_Pipes object.
|
||||
*/
|
||||
trait WPCF7_PipesHolder {
|
||||
|
||||
protected $pipes;
|
||||
|
||||
public function get_pipes( $field_name ) {
|
||||
if ( isset( $this->pipes[$field_name] ) ) {
|
||||
return $this->pipes[$field_name];
|
||||
}
|
||||
|
||||
$result = new WPCF7_Pipes;
|
||||
|
||||
$tags = $this->scan_form_tags( array(
|
||||
'name' => $field_name,
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( $tag->pipes instanceof WPCF7_Pipes ) {
|
||||
$result->merge( $tag->pipes );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->pipes[$field_name] = $result;
|
||||
}
|
||||
|
||||
public function scan_form_tags() {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,520 +0,0 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'rest_api_init',
|
||||
static function () {
|
||||
$controller = new WPCF7_REST_Controller;
|
||||
$controller->register_routes();
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
|
||||
|
||||
class WPCF7_REST_Controller {
|
||||
|
||||
const route_namespace = 'contact-form-7/v1';
|
||||
|
||||
public function register_routes() {
|
||||
|
||||
register_rest_route( self::route_namespace,
|
||||
'/contact-forms',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_contact_forms' ),
|
||||
'permission_callback' => static function () {
|
||||
if ( current_user_can( 'wpcf7_read_contact_forms' ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return new WP_Error( 'wpcf7_forbidden',
|
||||
__( "You are not allowed to access contact forms.", 'contact-form-7' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_contact_form' ),
|
||||
'permission_callback' => static function () {
|
||||
if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return new WP_Error( 'wpcf7_forbidden',
|
||||
__( "You are not allowed to create a contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( self::route_namespace,
|
||||
'/contact-forms/(?P<id>\d+)',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_contact_form' ),
|
||||
'permission_callback' => static function ( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return new WP_Error( 'wpcf7_forbidden',
|
||||
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_contact_form' ),
|
||||
'permission_callback' => static function ( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return new WP_Error( 'wpcf7_forbidden',
|
||||
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'callback' => array( $this, 'delete_contact_form' ),
|
||||
'permission_callback' => static function ( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
|
||||
if ( current_user_can( 'wpcf7_delete_contact_form', $id ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return new WP_Error( 'wpcf7_forbidden',
|
||||
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( self::route_namespace,
|
||||
'/contact-forms/(?P<id>\d+)/feedback',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_feedback' ),
|
||||
'permission_callback' => '__return_true',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( self::route_namespace,
|
||||
'/contact-forms/(?P<id>\d+)/feedback/schema',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_schema' ),
|
||||
'permission_callback' => '__return_true',
|
||||
),
|
||||
'schema' => 'wpcf7_swv_get_meta_schema',
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( self::route_namespace,
|
||||
'/contact-forms/(?P<id>\d+)/refill',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_refill' ),
|
||||
'permission_callback' => '__return_true',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function get_contact_forms( WP_REST_Request $request ) {
|
||||
$args = array();
|
||||
|
||||
$per_page = $request->get_param( 'per_page' );
|
||||
|
||||
if ( null !== $per_page ) {
|
||||
$args['posts_per_page'] = (int) $per_page;
|
||||
}
|
||||
|
||||
$offset = $request->get_param( 'offset' );
|
||||
|
||||
if ( null !== $offset ) {
|
||||
$args['offset'] = (int) $offset;
|
||||
}
|
||||
|
||||
$order = $request->get_param( 'order' );
|
||||
|
||||
if ( null !== $order ) {
|
||||
$args['order'] = (string) $order;
|
||||
}
|
||||
|
||||
$orderby = $request->get_param( 'orderby' );
|
||||
|
||||
if ( null !== $orderby ) {
|
||||
$args['orderby'] = (string) $orderby;
|
||||
}
|
||||
|
||||
$search = $request->get_param( 'search' );
|
||||
|
||||
if ( null !== $search ) {
|
||||
$args['s'] = (string) $search;
|
||||
}
|
||||
|
||||
$items = WPCF7_ContactForm::find( $args );
|
||||
|
||||
$response = array();
|
||||
|
||||
foreach ( $items as $item ) {
|
||||
$response[] = array(
|
||||
'id' => $item->id(),
|
||||
'hash' => $item->hash(),
|
||||
'slug' => $item->name(),
|
||||
'title' => $item->title(),
|
||||
'locale' => $item->locale(),
|
||||
);
|
||||
}
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
public function create_contact_form( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
|
||||
if ( $id ) {
|
||||
return new WP_Error( 'wpcf7_post_exists',
|
||||
__( "Cannot create existing contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 400 )
|
||||
);
|
||||
}
|
||||
|
||||
$args = $request->get_params();
|
||||
$args['id'] = -1; // Create
|
||||
$context = $request->get_param( 'context' );
|
||||
$item = wpcf7_save_contact_form( $args, $context );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_cannot_save',
|
||||
__( "There was an error saving the contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'id' => $item->id(),
|
||||
'slug' => $item->name(),
|
||||
'title' => $item->title(),
|
||||
'locale' => $item->locale(),
|
||||
'properties' => $this->get_properties( $item ),
|
||||
'config_errors' => array(),
|
||||
);
|
||||
|
||||
if ( wpcf7_validate_configuration() ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $item );
|
||||
$config_validator->validate();
|
||||
|
||||
$response['config_errors'] = $config_validator->collect_error_messages();
|
||||
|
||||
if ( 'save' == $context ) {
|
||||
$config_validator->save();
|
||||
}
|
||||
}
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
public function get_contact_form( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
$item = wpcf7_contact_form( $id );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'id' => $item->id(),
|
||||
'slug' => $item->name(),
|
||||
'title' => $item->title(),
|
||||
'locale' => $item->locale(),
|
||||
'properties' => $this->get_properties( $item ),
|
||||
);
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
public function update_contact_form( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
$item = wpcf7_contact_form( $id );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$args = $request->get_params();
|
||||
$context = $request->get_param( 'context' );
|
||||
$item = wpcf7_save_contact_form( $args, $context );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_cannot_save',
|
||||
__( "There was an error saving the contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'id' => $item->id(),
|
||||
'slug' => $item->name(),
|
||||
'title' => $item->title(),
|
||||
'locale' => $item->locale(),
|
||||
'properties' => $this->get_properties( $item ),
|
||||
'config_errors' => array(),
|
||||
);
|
||||
|
||||
if ( wpcf7_validate_configuration() ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $item );
|
||||
$config_validator->validate();
|
||||
|
||||
$response['config_errors'] = $config_validator->collect_error_messages();
|
||||
|
||||
if ( 'save' == $context ) {
|
||||
$config_validator->save();
|
||||
}
|
||||
}
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
public function delete_contact_form( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
$item = wpcf7_contact_form( $id );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$result = $item->delete();
|
||||
|
||||
if ( ! $result ) {
|
||||
return new WP_Error( 'wpcf7_cannot_delete',
|
||||
__( "There was an error deleting the contact form.", 'contact-form-7' ),
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
$response = array( 'deleted' => true );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
public function create_feedback( WP_REST_Request $request ) {
|
||||
$content_type = $request->get_header( 'Content-Type' );
|
||||
|
||||
if ( ! str_starts_with( $content_type, 'multipart/form-data' ) ) {
|
||||
return new WP_Error( 'wpcf7_unsupported_media_type',
|
||||
__( "The request payload format is not supported.", 'contact-form-7' ),
|
||||
array( 'status' => 415 )
|
||||
);
|
||||
}
|
||||
|
||||
$url_params = $request->get_url_params();
|
||||
|
||||
$item = null;
|
||||
|
||||
if ( ! empty( $url_params['id'] ) ) {
|
||||
$item = wpcf7_contact_form( $url_params['id'] );
|
||||
}
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$unit_tag = wpcf7_sanitize_unit_tag(
|
||||
$request->get_param( '_wpcf7_unit_tag' )
|
||||
);
|
||||
|
||||
if ( empty( $unit_tag ) ) {
|
||||
return new WP_Error( 'wpcf7_unit_tag_not_found',
|
||||
__( "There is no valid unit tag.", 'contact-form-7' ),
|
||||
array( 'status' => 400 )
|
||||
);
|
||||
}
|
||||
|
||||
$result = $item->submit();
|
||||
|
||||
$response = array_merge( $result, array(
|
||||
'into' => sprintf( '#%s', $unit_tag ),
|
||||
'invalid_fields' => array(),
|
||||
) );
|
||||
|
||||
if ( ! empty( $result['invalid_fields'] ) ) {
|
||||
$invalid_fields = array();
|
||||
|
||||
foreach ( (array) $result['invalid_fields'] as $name => $field ) {
|
||||
if ( ! wpcf7_is_name( $name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = strtr( $name, '.', '_' );
|
||||
|
||||
$invalid_fields[] = array(
|
||||
'field' => $name,
|
||||
'message' => $field['reason'],
|
||||
'idref' => $field['idref'],
|
||||
'error_id' => sprintf(
|
||||
'%1$s-ve-%2$s',
|
||||
$unit_tag,
|
||||
$name
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$response['invalid_fields'] = $invalid_fields;
|
||||
}
|
||||
|
||||
$response = wpcf7_apply_filters_deprecated(
|
||||
'wpcf7_ajax_json_echo',
|
||||
array( $response, $result ),
|
||||
'5.2',
|
||||
'wpcf7_feedback_response'
|
||||
);
|
||||
|
||||
$response = apply_filters( 'wpcf7_feedback_response', $response, $result );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
|
||||
public function get_schema( WP_REST_Request $request ) {
|
||||
$url_params = $request->get_url_params();
|
||||
|
||||
$item = null;
|
||||
|
||||
if ( ! empty( $url_params['id'] ) ) {
|
||||
$item = wpcf7_contact_form( $url_params['id'] );
|
||||
}
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$schema = $item->get_schema();
|
||||
|
||||
$response = isset( $schema ) ? $schema->to_array() : array();
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
|
||||
public function get_refill( WP_REST_Request $request ) {
|
||||
$id = (int) $request->get_param( 'id' );
|
||||
$item = wpcf7_contact_form( $id );
|
||||
|
||||
if ( ! $item ) {
|
||||
return new WP_Error( 'wpcf7_not_found',
|
||||
__( "The requested contact form was not found.", 'contact-form-7' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$response = wpcf7_apply_filters_deprecated(
|
||||
'wpcf7_ajax_onload',
|
||||
array( array() ),
|
||||
'5.2',
|
||||
'wpcf7_refill_response'
|
||||
);
|
||||
|
||||
$response = apply_filters( 'wpcf7_refill_response', array() );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
private function get_properties( WPCF7_ContactForm $contact_form ) {
|
||||
$properties = $contact_form->get_properties();
|
||||
|
||||
$properties['form'] = array(
|
||||
'content' => (string) $properties['form'],
|
||||
'fields' => array_map(
|
||||
static function ( WPCF7_FormTag $form_tag ) {
|
||||
return array(
|
||||
'type' => $form_tag->type,
|
||||
'basetype' => $form_tag->basetype,
|
||||
'name' => $form_tag->name,
|
||||
'options' => $form_tag->options,
|
||||
'raw_values' => $form_tag->raw_values,
|
||||
'labels' => $form_tag->labels,
|
||||
'values' => $form_tag->values,
|
||||
'pipes' => $form_tag->pipes instanceof WPCF7_Pipes
|
||||
? $form_tag->pipes->to_array()
|
||||
: $form_tag->pipes,
|
||||
'content' => $form_tag->content,
|
||||
);
|
||||
},
|
||||
$contact_form->scan_form_tags()
|
||||
),
|
||||
);
|
||||
|
||||
$properties['additional_settings'] = array(
|
||||
'content' => (string) $properties['additional_settings'],
|
||||
'settings' => array_filter( array_map(
|
||||
static function ( $setting ) {
|
||||
$pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';
|
||||
|
||||
if ( preg_match( $pattern, $setting, $matches ) ) {
|
||||
$name = trim( $matches[1] );
|
||||
$value = trim( $matches[2] );
|
||||
|
||||
if ( in_array( $value, array( 'on', 'true' ), true ) ) {
|
||||
$value = true;
|
||||
} elseif ( in_array( $value, array( 'off', 'false' ), true ) ) {
|
||||
$value = false;
|
||||
}
|
||||
|
||||
return array( $name, $value );
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
explode( "\n", $properties['additional_settings'] )
|
||||
) ),
|
||||
);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function get_argument_schema() {
|
||||
return array(
|
||||
'id' => array(
|
||||
'description' => __( "Unique identifier for the contact form.", 'contact-form-7' ),
|
||||
'type' => 'integer',
|
||||
'required' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* All the functions and classes in this file are deprecated.
|
||||
* You should not use them. The functions and classes will be
|
||||
* removed in a later version.
|
||||
*/
|
||||
|
||||
function wpcf7_add_shortcode( $tag, $callback, $has_name = false ) {
|
||||
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_add_form_tag' );
|
||||
|
||||
return wpcf7_add_form_tag( $tag, $callback, $has_name );
|
||||
}
|
||||
|
||||
function wpcf7_remove_shortcode( $tag ) {
|
||||
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_remove_form_tag' );
|
||||
|
||||
return wpcf7_remove_form_tag( $tag );
|
||||
}
|
||||
|
||||
function wpcf7_do_shortcode( $content ) {
|
||||
wpcf7_deprecated_function( __FUNCTION__, '4.6',
|
||||
'wpcf7_replace_all_form_tags' );
|
||||
|
||||
return wpcf7_replace_all_form_tags( $content );
|
||||
}
|
||||
|
||||
function wpcf7_scan_shortcode( $cond = null ) {
|
||||
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_scan_form_tags' );
|
||||
|
||||
return wpcf7_scan_form_tags( $cond );
|
||||
}
|
||||
|
||||
class WPCF7_ShortcodeManager {
|
||||
|
||||
private static $form_tags_manager;
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function get_instance() {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::get_instance' );
|
||||
|
||||
self::$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
return new self;
|
||||
}
|
||||
|
||||
public function get_scanned_tags() {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::get_scanned_tags' );
|
||||
|
||||
return self::$form_tags_manager->get_scanned_tags();
|
||||
}
|
||||
|
||||
public function add_shortcode( $tag, $callback, $has_name = false ) {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::add' );
|
||||
|
||||
return self::$form_tags_manager->add( $tag, $callback, $has_name );
|
||||
}
|
||||
|
||||
public function remove_shortcode( $tag ) {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::remove' );
|
||||
|
||||
return self::$form_tags_manager->remove( $tag );
|
||||
}
|
||||
|
||||
public function normalize_shortcode( $content ) {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::normalize' );
|
||||
|
||||
return self::$form_tags_manager->normalize( $content );
|
||||
}
|
||||
|
||||
public function do_shortcode( $content, $exec = true ) {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::replace_all' );
|
||||
|
||||
if ( $exec ) {
|
||||
return self::$form_tags_manager->replace_all( $content );
|
||||
} else {
|
||||
return self::$form_tags_manager->scan( $content );
|
||||
}
|
||||
}
|
||||
|
||||
public function scan_shortcode( $content ) {
|
||||
wpcf7_deprecated_function( __METHOD__, '4.6',
|
||||
'WPCF7_FormTagsManager::scan' );
|
||||
|
||||
return self::$form_tags_manager->scan( $content );
|
||||
}
|
||||
}
|
||||
|
||||
class WPCF7_Shortcode extends WPCF7_FormTag {
|
||||
|
||||
public function __construct( $tag ) {
|
||||
wpcf7_deprecated_function( 'WPCF7_Shortcode', '4.6', 'WPCF7_FormTag' );
|
||||
|
||||
parent::__construct( $tag );
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
** Special Mail Tags
|
||||
** https://contactform7.com/special-mail-tags/
|
||||
**/
|
||||
|
||||
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_special_mail_tag', 10, 4 );
|
||||
|
||||
/**
|
||||
* Returns output string of a special mail-tag.
|
||||
*
|
||||
* @param string $output The string to be output.
|
||||
* @param string $name The tag name of the special mail-tag.
|
||||
* @param bool $html Whether the mail-tag is used in an HTML content.
|
||||
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
|
||||
* @return string Output of the given special mail-tag.
|
||||
*/
|
||||
function wpcf7_special_mail_tag( $output, $name, $html, $mail_tag = null ) {
|
||||
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
|
||||
wpcf7_doing_it_wrong(
|
||||
sprintf( '%s()', __FUNCTION__ ),
|
||||
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
|
||||
'5.2.2'
|
||||
);
|
||||
}
|
||||
|
||||
$name = preg_replace( '/^wpcf7\./', '_', $name ); // for back-compat
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
|
||||
if ( ! $submission ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
if ( '_remote_ip' === $name ) {
|
||||
if ( $remote_ip = $submission->get_meta( 'remote_ip' ) ) {
|
||||
return $remote_ip;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( '_user_agent' === $name ) {
|
||||
if ( $user_agent = $submission->get_meta( 'user_agent' ) ) {
|
||||
return $html ? esc_html( $user_agent ) : $user_agent;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( '_url' === $name ) {
|
||||
if ( $url = $submission->get_meta( 'url' ) ) {
|
||||
return $url;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( '_date' === $name or '_time' === $name ) {
|
||||
if ( $timestamp = $submission->get_meta( 'timestamp' ) ) {
|
||||
if ( '_date' === $name ) {
|
||||
return wp_date( get_option( 'date_format' ), $timestamp );
|
||||
}
|
||||
|
||||
if ( '_time' === $name ) {
|
||||
return wp_date( get_option( 'time_format' ), $timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( '_invalid_fields' === $name ) {
|
||||
return count( $submission->get_invalid_fields() );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_post_related_smt', 10, 4 );
|
||||
|
||||
/**
|
||||
* Returns output string of a special mail-tag.
|
||||
*
|
||||
* @param string $output The string to be output.
|
||||
* @param string $name The tag name of the special mail-tag.
|
||||
* @param bool $html Whether the mail-tag is used in an HTML content.
|
||||
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
|
||||
* @return string Output of the given special mail-tag.
|
||||
*/
|
||||
function wpcf7_post_related_smt( $output, $name, $html, $mail_tag = null ) {
|
||||
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
|
||||
wpcf7_doing_it_wrong(
|
||||
sprintf( '%s()', __FUNCTION__ ),
|
||||
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
|
||||
'5.2.2'
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! str_starts_with( $name, '_post_' ) ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
|
||||
if ( ! $submission ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$post_id = (int) $submission->get_meta( 'container_post_id' );
|
||||
|
||||
if ( ! $post_id or ! $post = get_post( $post_id ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( '_post_id' === $name ) {
|
||||
return (string) $post->ID;
|
||||
}
|
||||
|
||||
if ( '_post_name' === $name ) {
|
||||
return $post->post_name;
|
||||
}
|
||||
|
||||
if ( '_post_title' === $name ) {
|
||||
return $html ? esc_html( $post->post_title ) : $post->post_title;
|
||||
}
|
||||
|
||||
if ( '_post_url' === $name ) {
|
||||
return get_permalink( $post->ID );
|
||||
}
|
||||
|
||||
$user = new WP_User( $post->post_author );
|
||||
|
||||
if ( '_post_author' === $name ) {
|
||||
return $user->display_name;
|
||||
}
|
||||
|
||||
if ( '_post_author_email' === $name ) {
|
||||
return $user->user_email;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_site_related_smt', 10, 4 );
|
||||
|
||||
/**
|
||||
* Returns output string of a special mail-tag.
|
||||
*
|
||||
* @param string $output The string to be output.
|
||||
* @param string $name The tag name of the special mail-tag.
|
||||
* @param bool $html Whether the mail-tag is used in an HTML content.
|
||||
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
|
||||
* @return string Output of the given special mail-tag.
|
||||
*/
|
||||
function wpcf7_site_related_smt( $output, $name, $html, $mail_tag = null ) {
|
||||
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
|
||||
wpcf7_doing_it_wrong(
|
||||
sprintf( '%s()', __FUNCTION__ ),
|
||||
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
|
||||
'5.2.2'
|
||||
);
|
||||
}
|
||||
|
||||
$filter = $html ? 'display' : 'raw';
|
||||
|
||||
if ( '_site_title' === $name ) {
|
||||
$output = get_bloginfo( 'name', $filter );
|
||||
|
||||
if ( ! $html ) {
|
||||
$output = wp_specialchars_decode( $output, ENT_QUOTES );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
if ( '_site_description' === $name ) {
|
||||
$output = get_bloginfo( 'description', $filter );
|
||||
|
||||
if ( ! $html ) {
|
||||
$output = wp_specialchars_decode( $output, ENT_QUOTES );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
if ( '_site_url' === $name ) {
|
||||
return get_bloginfo( 'url', $filter );
|
||||
}
|
||||
|
||||
if ( '_site_admin_email' === $name ) {
|
||||
return get_bloginfo( 'admin_email', $filter );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_user_related_smt', 10, 4 );
|
||||
|
||||
/**
|
||||
* Returns output string of a special mail-tag.
|
||||
*
|
||||
* @param string $output The string to be output.
|
||||
* @param string $name The tag name of the special mail-tag.
|
||||
* @param bool $html Whether the mail-tag is used in an HTML content.
|
||||
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
|
||||
* @return string Output of the given special mail-tag.
|
||||
*/
|
||||
function wpcf7_user_related_smt( $output, $name, $html, $mail_tag = null ) {
|
||||
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
|
||||
wpcf7_doing_it_wrong(
|
||||
sprintf( '%s()', __FUNCTION__ ),
|
||||
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
|
||||
'5.2.2'
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! str_starts_with( $name, '_user_' ) or '_user_agent' === $name ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
|
||||
if ( ! $submission ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$user_id = (int) $submission->get_meta( 'current_user_id' );
|
||||
|
||||
if ( ! $user_id ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$primary_props = array( 'user_login', 'user_email', 'user_url' );
|
||||
$opt = ltrim( $name, '_' );
|
||||
$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
|
||||
|
||||
$user = new WP_User( $user_id );
|
||||
|
||||
if ( $user->has_prop( $opt ) ) {
|
||||
return $user->get( $opt );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
@@ -1,924 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class representing contact form submission.
|
||||
*/
|
||||
class WPCF7_Submission {
|
||||
|
||||
use WPCF7_PocketHolder;
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $contact_form;
|
||||
private $status = 'init';
|
||||
private $posted_data = array();
|
||||
private $posted_data_hash = null;
|
||||
private $skip_spam_check = false;
|
||||
private $uploaded_files = array();
|
||||
private $extra_attachments = array();
|
||||
private $skip_mail = false;
|
||||
private $response = '';
|
||||
private $invalid_fields = array();
|
||||
private $meta = array();
|
||||
private $consent = array();
|
||||
private $spam_log = array();
|
||||
private $result_props = array();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*/
|
||||
public static function get_instance( $contact_form = null, $args = '' ) {
|
||||
if ( $contact_form instanceof WPCF7_ContactForm ) {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self( $contact_form, $args );
|
||||
self::$instance->proceed();
|
||||
return self::$instance;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if ( empty( self::$instance ) ) {
|
||||
return null;
|
||||
} else {
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this submission is created via WP REST API.
|
||||
*/
|
||||
public static function is_restful() {
|
||||
return defined( 'REST_REQUEST' ) && REST_REQUEST;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'skip_mail' => false,
|
||||
) );
|
||||
|
||||
$this->contact_form = $contact_form;
|
||||
$this->skip_mail = (bool) $args['skip_mail'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public function __destruct() {
|
||||
$this->remove_uploaded_files();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main logic of submission.
|
||||
*/
|
||||
private function proceed() {
|
||||
|
||||
$callback = function () {
|
||||
$contact_form = $this->contact_form;
|
||||
|
||||
$this->setup_meta_data();
|
||||
$this->setup_posted_data();
|
||||
|
||||
if ( $this->is( 'init' ) and ! $this->validate() ) {
|
||||
$this->set_status( 'validation_failed' );
|
||||
$this->set_response( $contact_form->message( 'validation_error' ) );
|
||||
}
|
||||
|
||||
if ( $this->is( 'init' ) and ! $this->accepted() ) {
|
||||
$this->set_status( 'acceptance_missing' );
|
||||
$this->set_response( $contact_form->message( 'accept_terms' ) );
|
||||
}
|
||||
|
||||
if ( $this->is( 'init' ) and $this->spam() ) {
|
||||
$this->set_status( 'spam' );
|
||||
$this->set_response( $contact_form->message( 'spam' ) );
|
||||
}
|
||||
|
||||
if ( $this->is( 'init' ) and ! $this->unship_uploaded_files() ) {
|
||||
$this->set_status( 'validation_failed' );
|
||||
$this->set_response( $contact_form->message( 'validation_error' ) );
|
||||
}
|
||||
|
||||
if ( $this->is( 'init' ) ) {
|
||||
$abort = ! $this->before_send_mail();
|
||||
|
||||
if ( $abort ) {
|
||||
if ( $this->is( 'init' ) ) {
|
||||
$this->set_status( 'aborted' );
|
||||
}
|
||||
|
||||
if ( '' === $this->get_response() ) {
|
||||
$this->set_response( $contact_form->filter_message(
|
||||
__( "Sending mail has been aborted.", 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
} elseif ( $this->mail() ) {
|
||||
$this->set_status( 'mail_sent' );
|
||||
$this->set_response( $contact_form->message( 'mail_sent_ok' ) );
|
||||
|
||||
do_action( 'wpcf7_mail_sent', $contact_form );
|
||||
} else {
|
||||
$this->set_status( 'mail_failed' );
|
||||
$this->set_response( $contact_form->message( 'mail_sent_ng' ) );
|
||||
|
||||
do_action( 'wpcf7_mail_failed', $contact_form );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
wpcf7_switch_locale( $this->contact_form->locale(), $callback );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current status property.
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the status property.
|
||||
*
|
||||
* @param string $status The status.
|
||||
*/
|
||||
public function set_status( $status ) {
|
||||
if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
|
||||
$this->status = $status;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified status is identical to the current
|
||||
* status property.
|
||||
*
|
||||
* @param string $status The status to compare.
|
||||
*/
|
||||
public function is( $status ) {
|
||||
return $this->status === $status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an associative array of submission result properties.
|
||||
*
|
||||
* @return array Submission result properties.
|
||||
*/
|
||||
public function get_result() {
|
||||
$result = array_merge( $this->result_props, array(
|
||||
'status' => $this->get_status(),
|
||||
'message' => $this->get_response(),
|
||||
) );
|
||||
|
||||
if ( $this->is( 'validation_failed' ) ) {
|
||||
$result['invalid_fields'] = $this->get_invalid_fields();
|
||||
}
|
||||
|
||||
switch ( $this->get_status() ) {
|
||||
case 'init':
|
||||
case 'validation_failed':
|
||||
case 'acceptance_missing':
|
||||
case 'spam':
|
||||
$result['posted_data_hash'] = '';
|
||||
break;
|
||||
default:
|
||||
$result['posted_data_hash'] = $this->get_posted_data_hash();
|
||||
break;
|
||||
}
|
||||
|
||||
$result = apply_filters( 'wpcf7_submission_result', $result, $this );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds items to the array of submission result properties.
|
||||
*
|
||||
* @param string|array|object $args Value to add to result properties.
|
||||
* @return array Added result properties.
|
||||
*/
|
||||
public function add_result_props( $args = '' ) {
|
||||
$args = wp_parse_args( $args, array() );
|
||||
|
||||
$this->result_props = array_merge( $this->result_props, $args );
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the response property.
|
||||
*
|
||||
* @return string The current response property value.
|
||||
*/
|
||||
public function get_response() {
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the response property.
|
||||
*
|
||||
* @param string $response New response property value.
|
||||
*/
|
||||
public function set_response( $response ) {
|
||||
$this->response = $response;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the contact form property.
|
||||
*
|
||||
* @return WPCF7_ContactForm A contact form object.
|
||||
*/
|
||||
public function get_contact_form() {
|
||||
return $this->contact_form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search an invalid field by field name.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @return array|bool An associative array of validation error
|
||||
* or false when no invalid field.
|
||||
*/
|
||||
public function get_invalid_field( $name ) {
|
||||
return $this->invalid_fields[$name] ?? false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all invalid fields.
|
||||
*
|
||||
* @return array Invalid fields.
|
||||
*/
|
||||
public function get_invalid_fields() {
|
||||
return $this->invalid_fields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves meta information.
|
||||
*
|
||||
* @param string $name Name of the meta information.
|
||||
* @return string|null The meta information of the given name if it exists,
|
||||
* null otherwise.
|
||||
*/
|
||||
public function get_meta( $name ) {
|
||||
return $this->meta[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects meta information about this submission.
|
||||
*/
|
||||
private function setup_meta_data() {
|
||||
$this->meta = array(
|
||||
'timestamp' => time(),
|
||||
'remote_ip' => $this->get_remote_ip_addr(),
|
||||
'remote_port' => $_SERVER['REMOTE_PORT'] ?? '',
|
||||
'user_agent' => substr( $_SERVER['HTTP_USER_AGENT'] ?? '', 0, 254 ),
|
||||
'url' => $this->get_request_url(),
|
||||
'unit_tag' => wpcf7_sanitize_unit_tag( $_POST['_wpcf7_unit_tag'] ?? '' ),
|
||||
'container_post_id' => absint( $_POST['_wpcf7_container_post'] ?? 0 ),
|
||||
'current_user_id' => get_current_user_id(),
|
||||
'do_not_store' => $this->contact_form->is_true( 'do_not_store' ),
|
||||
);
|
||||
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves user input data through this submission.
|
||||
*
|
||||
* @param string $name Optional field name.
|
||||
* @return string|array|null The user input of the field, or array of all
|
||||
* fields values if no field name specified.
|
||||
*/
|
||||
public function get_posted_data( $name = '' ) {
|
||||
if ( ! empty( $name ) ) {
|
||||
return $this->posted_data[$name] ?? null;
|
||||
}
|
||||
|
||||
return $this->posted_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a user input string value through the specified field.
|
||||
*
|
||||
* @param string $name Field name.
|
||||
* @return string The user input. If the input is an array,
|
||||
* the first item in the array.
|
||||
*/
|
||||
public function get_posted_string( $name ) {
|
||||
$data = $this->get_posted_data( $name );
|
||||
$data = wpcf7_array_flatten( $data );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Returns the first array item.
|
||||
return trim( reset( $data ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs posted data property based on user input values.
|
||||
*/
|
||||
private function setup_posted_data() {
|
||||
$posted_data = array_filter(
|
||||
(array) $_POST,
|
||||
static function ( $key ) {
|
||||
return ! str_starts_with( $key, '_' );
|
||||
},
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
|
||||
$posted_data = wp_unslash( $posted_data );
|
||||
$posted_data = $this->sanitize_posted_data( $posted_data );
|
||||
|
||||
$tags = $this->contact_form->scan_form_tags( array(
|
||||
'feature' => array(
|
||||
'name-attr',
|
||||
'! not-for-mail',
|
||||
),
|
||||
) );
|
||||
|
||||
$tags = array_reduce( $tags, static function ( $carry, $tag ) {
|
||||
if ( $tag->name and ! isset( $carry[$tag->name] ) ) {
|
||||
$carry[$tag->name] = $tag;
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}, array() );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$value_orig = $value = $posted_data[$tag->name] ?? '';
|
||||
|
||||
if ( wpcf7_form_tag_supports( $tag->type, 'selectable-values' ) ) {
|
||||
$value = ( '' === $value ) ? array() : (array) $value;
|
||||
|
||||
if ( WPCF7_USE_PIPE ) {
|
||||
$pipes = $this->contact_form->get_pipes( $tag->name );
|
||||
|
||||
$value = array_map( static function ( $value ) use ( $pipes ) {
|
||||
return $pipes->do_pipe( $value );
|
||||
}, $value );
|
||||
}
|
||||
}
|
||||
|
||||
$value = apply_filters( "wpcf7_posted_data_{$tag->type}",
|
||||
$value,
|
||||
$value_orig,
|
||||
$tag
|
||||
);
|
||||
|
||||
$posted_data[$tag->name] = $value;
|
||||
|
||||
if ( $tag->has_option( 'consent_for:storage' ) and empty( $value ) ) {
|
||||
$this->meta['do_not_store'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
|
||||
|
||||
$this->posted_data_hash = $this->create_posted_data_hash();
|
||||
|
||||
return $this->posted_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes user input data.
|
||||
*/
|
||||
private function sanitize_posted_data( $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_map( array( $this, 'sanitize_posted_data' ), $value );
|
||||
} elseif ( is_string( $value ) ) {
|
||||
$value = wp_check_invalid_utf8( $value );
|
||||
$value = wp_kses_no_null( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the time-dependent variable for hash creation.
|
||||
*
|
||||
* @return float Float value rounded up to the next highest integer.
|
||||
*/
|
||||
private function posted_data_hash_tick() {
|
||||
return ceil( time() / ( HOUR_IN_SECONDS / 2 ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a hash string based on posted data, the remote IP address,
|
||||
* contact form location, and window of time.
|
||||
*
|
||||
* @param string $tick Optional. If not specified, result of
|
||||
* posted_data_hash_tick() will be used.
|
||||
* @return string The hash.
|
||||
*/
|
||||
private function create_posted_data_hash( $tick = '' ) {
|
||||
if ( '' === $tick ) {
|
||||
$tick = $this->posted_data_hash_tick();
|
||||
}
|
||||
|
||||
$hash = wp_hash(
|
||||
wpcf7_flat_join( array_merge(
|
||||
array(
|
||||
$tick,
|
||||
$this->get_meta( 'remote_ip' ),
|
||||
$this->get_meta( 'unit_tag' ),
|
||||
),
|
||||
$this->posted_data
|
||||
) ),
|
||||
'wpcf7_submission'
|
||||
);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hash string created for this submission.
|
||||
*
|
||||
* @return string The current hash for the submission.
|
||||
*/
|
||||
public function get_posted_data_hash() {
|
||||
return $this->posted_data_hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the given string is equivalent to the posted data hash.
|
||||
*
|
||||
* @param string $hash Optional. This value will be compared to the
|
||||
* current posted data hash for the submission. If not
|
||||
* specified, the value of $_POST['_wpcf7_posted_data_hash']
|
||||
* will be used.
|
||||
* @return int|bool 1 if $hash is created 0-30 minutes ago,
|
||||
* 2 if $hash is created 30-60 minutes ago,
|
||||
* false if $hash is invalid.
|
||||
*/
|
||||
public function verify_posted_data_hash( $hash = '' ) {
|
||||
if ( '' === $hash and ! empty( $_POST['_wpcf7_posted_data_hash'] ) ) {
|
||||
$hash = trim( $_POST['_wpcf7_posted_data_hash'] );
|
||||
}
|
||||
|
||||
if ( '' === $hash ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tick = $this->posted_data_hash_tick();
|
||||
|
||||
// Hash created 0-30 minutes ago.
|
||||
$expected_1 = $this->create_posted_data_hash( $tick );
|
||||
|
||||
if ( hash_equals( $expected_1, $hash ) ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Hash created 30-60 minutes ago.
|
||||
$expected_2 = $this->create_posted_data_hash( $tick - 1 );
|
||||
|
||||
if ( hash_equals( $expected_2, $hash ) ) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the remote IP address of this submission.
|
||||
*/
|
||||
private function get_remote_ip_addr() {
|
||||
$ip_addr = '';
|
||||
|
||||
if ( isset( $_SERVER['REMOTE_ADDR'] )
|
||||
and WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
|
||||
$ip_addr = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the request URL of this submission.
|
||||
*/
|
||||
private function get_request_url() {
|
||||
$home_url = untrailingslashit( home_url() );
|
||||
|
||||
if ( self::is_restful() ) {
|
||||
$referer = trim( $_SERVER['HTTP_REFERER'] ?? '' );
|
||||
|
||||
if ( $referer
|
||||
and 0 === strpos( $referer, $home_url ) ) {
|
||||
return sanitize_url( $referer );
|
||||
}
|
||||
}
|
||||
|
||||
$url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
|
||||
. wpcf7_get_request_uri();
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs user input validation.
|
||||
*
|
||||
* @return bool True if no invalid field is found.
|
||||
*/
|
||||
private function validate() {
|
||||
if ( $this->invalid_fields ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = new WPCF7_Validation();
|
||||
|
||||
$this->contact_form->validate_schema(
|
||||
array(
|
||||
'text' => true,
|
||||
'file' => false,
|
||||
'field' => array(),
|
||||
),
|
||||
$result
|
||||
);
|
||||
|
||||
$tags = $this->contact_form->scan_form_tags( array(
|
||||
'feature' => '! file-uploading',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$type = $tag->type;
|
||||
$result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
|
||||
}
|
||||
|
||||
$result = apply_filters( 'wpcf7_validate', $result, $tags );
|
||||
|
||||
$this->invalid_fields = $result->get_invalid_fields();
|
||||
|
||||
return $result->is_valid();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if user consent is obtained.
|
||||
*/
|
||||
private function accepted() {
|
||||
return apply_filters( 'wpcf7_acceptance', true, $this );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds user consent data to this submission.
|
||||
*
|
||||
* @param string $name Field name.
|
||||
* @param string $conditions Conditions of consent.
|
||||
*/
|
||||
public function add_consent( $name, $conditions ) {
|
||||
$this->consent[$name] = $conditions;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects user consent data.
|
||||
*
|
||||
* @return array User consent data.
|
||||
*/
|
||||
public function collect_consent() {
|
||||
return (array) $this->consent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes spam protections.
|
||||
*
|
||||
* @return bool True if spam captured.
|
||||
*/
|
||||
private function spam() {
|
||||
$spam = false;
|
||||
|
||||
$skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
|
||||
$this->skip_spam_check,
|
||||
$this
|
||||
);
|
||||
|
||||
if ( $skip_spam_check ) {
|
||||
return $spam;
|
||||
}
|
||||
|
||||
if ( $this->contact_form->is_true( 'subscribers_only' )
|
||||
and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
|
||||
return $spam;
|
||||
}
|
||||
|
||||
$user_agent = (string) $this->get_meta( 'user_agent' );
|
||||
|
||||
if ( strlen( $user_agent ) < 2 ) {
|
||||
$spam = true;
|
||||
|
||||
$this->add_spam_log( array(
|
||||
'agent' => 'wpcf7',
|
||||
'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
|
||||
) );
|
||||
}
|
||||
|
||||
if ( ! $this->verify_nonce() ) {
|
||||
$spam = true;
|
||||
|
||||
$this->add_spam_log( array(
|
||||
'agent' => 'wpcf7',
|
||||
'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
|
||||
) );
|
||||
}
|
||||
|
||||
return apply_filters( 'wpcf7_spam', $spam, $this );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a spam log.
|
||||
*
|
||||
* @link https://contactform7.com/2019/05/31/why-is-this-message-marked-spam/
|
||||
*/
|
||||
public function add_spam_log( $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'agent' => '',
|
||||
'reason' => '',
|
||||
) );
|
||||
|
||||
$this->spam_log[] = $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the spam logging data.
|
||||
*
|
||||
* @return array Spam logging data.
|
||||
*/
|
||||
public function get_spam_log() {
|
||||
return $this->spam_log;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that a correct security nonce was used.
|
||||
*/
|
||||
private function verify_nonce() {
|
||||
if ( ! $this->contact_form->nonce_is_active() or ! is_user_logged_in() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$nonce = $_POST['_wpnonce'] ?? '';
|
||||
|
||||
return wpcf7_verify_nonce( $nonce );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called just before sending email.
|
||||
*/
|
||||
private function before_send_mail() {
|
||||
$abort = false;
|
||||
|
||||
do_action_ref_array( 'wpcf7_before_send_mail', array(
|
||||
$this->contact_form,
|
||||
&$abort,
|
||||
$this,
|
||||
) );
|
||||
|
||||
return ! $abort;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends emails based on user input values and contact form email templates.
|
||||
*/
|
||||
private function mail() {
|
||||
$contact_form = $this->contact_form;
|
||||
|
||||
$skip_mail = apply_filters( 'wpcf7_skip_mail',
|
||||
$this->skip_mail, $contact_form
|
||||
);
|
||||
|
||||
if ( $skip_mail ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );
|
||||
|
||||
if ( $result ) {
|
||||
$additional_mail = array();
|
||||
|
||||
if ( $mail_2 = $contact_form->prop( 'mail_2' )
|
||||
and $mail_2['active'] ) {
|
||||
$additional_mail['mail_2'] = $mail_2;
|
||||
}
|
||||
|
||||
$additional_mail = apply_filters( 'wpcf7_additional_mail',
|
||||
$additional_mail, $contact_form
|
||||
);
|
||||
|
||||
foreach ( $additional_mail as $name => $template ) {
|
||||
WPCF7_Mail::send( $template, $name );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves files uploaded through this submission.
|
||||
*/
|
||||
public function uploaded_files() {
|
||||
return $this->uploaded_files;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a file to the uploaded files array.
|
||||
*
|
||||
* @param string $name Field name.
|
||||
* @param string|array $file_path File path or array of file paths.
|
||||
*/
|
||||
private function add_uploaded_file( $name, $file_path ) {
|
||||
if ( ! wpcf7_is_name( $name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$paths = (array) $file_path;
|
||||
$uploaded_files = array();
|
||||
$hash_strings = array();
|
||||
|
||||
foreach ( $paths as $path ) {
|
||||
if ( @is_file( $path ) and @is_readable( $path ) ) {
|
||||
$uploaded_files[] = $path;
|
||||
$hash_strings[] = md5_file( $path );
|
||||
}
|
||||
}
|
||||
|
||||
$this->uploaded_files[$name] = $uploaded_files;
|
||||
|
||||
if ( empty( $this->posted_data[$name] ) ) {
|
||||
$this->posted_data[$name] = implode( ' ', $hash_strings );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes uploaded files.
|
||||
*/
|
||||
private function remove_uploaded_files() {
|
||||
foreach ( (array) $this->uploaded_files as $file_path ) {
|
||||
$paths = (array) $file_path;
|
||||
|
||||
foreach ( $paths as $path ) {
|
||||
wpcf7_rmdir_p( $path );
|
||||
|
||||
if ( $dir = dirname( $path )
|
||||
and false !== ( $files = scandir( $dir ) )
|
||||
and ! array_diff( $files, array( '.', '..' ) ) ) {
|
||||
// remove parent dir if it's empty.
|
||||
rmdir( $dir );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves uploaded files to the tmp directory and validates them.
|
||||
*
|
||||
* @return bool True if no invalid file is found.
|
||||
*/
|
||||
private function unship_uploaded_files() {
|
||||
$result = new WPCF7_Validation();
|
||||
|
||||
$tags = $this->contact_form->scan_form_tags( array(
|
||||
'feature' => 'file-uploading',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( empty( $_FILES[$tag->name] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = $_FILES[$tag->name];
|
||||
|
||||
$args = array(
|
||||
'tag' => $tag,
|
||||
'name' => $tag->name,
|
||||
'required' => $tag->is_required(),
|
||||
'filetypes' => $tag->get_option( 'filetypes' ),
|
||||
'limit' => $tag->get_limit_option(),
|
||||
'schema' => $this->contact_form->get_schema(),
|
||||
);
|
||||
|
||||
$new_files = wpcf7_unship_uploaded_file( $file, $args );
|
||||
|
||||
if ( is_wp_error( $new_files ) ) {
|
||||
$result->invalidate( $tag, $new_files );
|
||||
} else {
|
||||
$this->add_uploaded_file( $tag->name, $new_files );
|
||||
}
|
||||
|
||||
$result = apply_filters(
|
||||
"wpcf7_validate_{$tag->type}",
|
||||
$result, $tag,
|
||||
array(
|
||||
'uploaded_files' => $new_files,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->invalid_fields = $result->get_invalid_fields();
|
||||
|
||||
return $result->is_valid();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds extra email attachment files that are independent from form fields.
|
||||
*
|
||||
* @param string|array $file_path A file path or an array of file paths.
|
||||
* @param string $template Optional. The name of the template to which
|
||||
* the files are attached.
|
||||
* @return bool True if it succeeds to attach a file at least,
|
||||
* or false otherwise.
|
||||
*/
|
||||
public function add_extra_attachments( $file_path, $template = 'mail' ) {
|
||||
if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$extra_attachments = array();
|
||||
|
||||
foreach ( (array) $file_path as $path ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $path );
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
$extra_attachments[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $extra_attachments ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $this->extra_attachments[$template] ) ) {
|
||||
$this->extra_attachments[$template] = array();
|
||||
}
|
||||
|
||||
$this->extra_attachments[$template] = array_merge(
|
||||
$this->extra_attachments[$template],
|
||||
$extra_attachments
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns extra email attachment files.
|
||||
*
|
||||
* @param string $template An email template name.
|
||||
* @return array Array of file paths.
|
||||
*/
|
||||
public function extra_attachments( $template ) {
|
||||
if ( isset( $this->extra_attachments[$template] ) ) {
|
||||
return (array) $this->extra_attachments[$template];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||